UNPKG

914 kBJavaScriptView Raw
1const now = (typeof process !== 'undefined' && process.hrtime)
2 ? () => {
3 const t = process.hrtime();
4 return t[0] * 1e3 + t[1] / 1e6;
5 }
6 : () => self.performance.now();
7function collapse_timings(timings) {
8 const result = {};
9 timings.forEach(timing => {
10 result[timing.label] = Object.assign({
11 total: timing.end - timing.start
12 }, timing.children && collapse_timings(timing.children));
13 });
14 return result;
15}
16class Stats {
17 constructor() {
18 this.start_time = now();
19 this.stack = [];
20 this.current_children = this.timings = [];
21 }
22 start(label) {
23 const timing = {
24 label,
25 start: now(),
26 end: null,
27 children: []
28 };
29 this.current_children.push(timing);
30 this.stack.push(timing);
31 this.current_timing = timing;
32 this.current_children = timing.children;
33 }
34 stop(label) {
35 if (label !== this.current_timing.label) {
36 throw new Error(`Mismatched timing labels (expected ${this.current_timing.label}, got ${label})`);
37 }
38 this.current_timing.end = now();
39 this.stack.pop();
40 this.current_timing = this.stack[this.stack.length - 1];
41 this.current_children = this.current_timing ? this.current_timing.children : this.timings;
42 }
43 render() {
44 const timings = Object.assign({
45 total: now() - this.start_time
46 }, collapse_timings(this.timings));
47 return {
48 timings
49 };
50 }
51}
52
53// Reserved word lists for various dialects of the language
54
55var reservedWords = {
56 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
57 5: "class enum extends super const export import",
58 6: "enum",
59 strict: "implements interface let package private protected public static yield",
60 strictBind: "eval arguments"
61};
62
63// And the keywords
64
65var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
66
67var keywords = {
68 5: ecma5AndLessKeywords,
69 "5module": ecma5AndLessKeywords + " export import",
70 6: ecma5AndLessKeywords + " const class extends export import super"
71};
72
73var keywordRelationalOperator = /^in(stanceof)?$/;
74
75// ## Character categories
76
77// Big ugly regular expressions that match characters in the
78// whitespace, identifier, and identifier-start categories. These
79// are only applied when a character is found to actually have a
80// code point above 128.
81// Generated by `bin/generate-identifier-regex.js`.
82var 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\u0560-\u0588\u05d0-\u05ea\u05ef-\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\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\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\u09fc\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\u0d04-\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\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\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-\u1878\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\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\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-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\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-\uab69\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";
83var 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\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\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\u09fe\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\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\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\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\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\u1abf\u1ac0\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\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\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\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\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";
84
85var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
86var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
87
88nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
89
90// These are a run-length and offset encoded representation of the
91// >0xffff code points that are a valid part of identifiers. The
92// offset starts at 0x10000, and each pair of numbers represents an
93// offset to the next range, and then a size of the range. They were
94// generated by bin/generate-identifier-regex.js
95
96// eslint-disable-next-line comma-spacing
97var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,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,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,349,41,7,1,79,28,11,0,9,21,107,20,28,22,13,52,76,44,33,24,27,35,30,0,3,0,9,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,21,2,31,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,7,3,0,3,7,2,1,2,23,16,0,2,0,95,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,190,0,80,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,1237,43,8,8952,286,50,2,18,3,9,395,2309,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,2357,44,11,6,17,0,370,43,1301,196,60,67,8,0,1205,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,42717,35,4148,12,221,3,5761,15,7472,3104,541,1507,4938];
98
99// eslint-disable-next-line comma-spacing
100var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,370,1,154,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,2,11,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,71,5,2,1,3,3,2,0,2,1,13,9,120,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1014,0,2,54,8,3,82,0,12,1,19628,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,262,6,10,9,419,13,1495,6,110,6,6,9,4759,9,787719,239];
101
102// This has a complexity linear to the value of the code. The
103// assumption is that looking up astral identifier characters is
104// rare.
105function isInAstralSet(code, set) {
106 var pos = 0x10000;
107 for (var i = 0; i < set.length; i += 2) {
108 pos += set[i];
109 if (pos > code) { return false }
110 pos += set[i + 1];
111 if (pos >= code) { return true }
112 }
113}
114
115// Test whether a given character code starts an identifier.
116
117function isIdentifierStart(code, astral) {
118 if (code < 65) { return code === 36 }
119 if (code < 91) { return true }
120 if (code < 97) { return code === 95 }
121 if (code < 123) { return true }
122 if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) }
123 if (astral === false) { return false }
124 return isInAstralSet(code, astralIdentifierStartCodes)
125}
126
127// Test whether a given character is part of an identifier.
128
129function isIdentifierChar(code, astral) {
130 if (code < 48) { return code === 36 }
131 if (code < 58) { return true }
132 if (code < 65) { return false }
133 if (code < 91) { return true }
134 if (code < 97) { return code === 95 }
135 if (code < 123) { return true }
136 if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) }
137 if (astral === false) { return false }
138 return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
139}
140
141// ## Token types
142
143// The assignment of fine-grained, information-carrying type objects
144// allows the tokenizer to store the information it has about a
145// token in a way that is very cheap for the parser to look up.
146
147// All token type variables start with an underscore, to make them
148// easy to recognize.
149
150// The `beforeExpr` property is used to disambiguate between regular
151// expressions and divisions. It is set on all token types that can
152// be followed by an expression (thus, a slash after them would be a
153// regular expression).
154//
155// The `startsExpr` property is used to check if the token ends a
156// `yield` expression. It is set on all token types that either can
157// directly start an expression (like a quotation mark) or can
158// continue an expression (like the body of a string).
159//
160// `isLoop` marks a keyword as starting a loop, which is important
161// to know when parsing a label, in order to allow or disallow
162// continue jumps to that label.
163
164var TokenType = function TokenType(label, conf) {
165 if ( conf === void 0 ) conf = {};
166
167 this.label = label;
168 this.keyword = conf.keyword;
169 this.beforeExpr = !!conf.beforeExpr;
170 this.startsExpr = !!conf.startsExpr;
171 this.isLoop = !!conf.isLoop;
172 this.isAssign = !!conf.isAssign;
173 this.prefix = !!conf.prefix;
174 this.postfix = !!conf.postfix;
175 this.binop = conf.binop || null;
176 this.updateContext = null;
177};
178
179function binop(name, prec) {
180 return new TokenType(name, {beforeExpr: true, binop: prec})
181}
182var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true};
183
184// Map keyword names to token types.
185
186var keywords$1 = {};
187
188// Succinct definitions of keyword token types
189function kw(name, options) {
190 if ( options === void 0 ) options = {};
191
192 options.keyword = name;
193 return keywords$1[name] = new TokenType(name, options)
194}
195
196var types = {
197 num: new TokenType("num", startsExpr),
198 regexp: new TokenType("regexp", startsExpr),
199 string: new TokenType("string", startsExpr),
200 name: new TokenType("name", startsExpr),
201 eof: new TokenType("eof"),
202
203 // Punctuation token types.
204 bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
205 bracketR: new TokenType("]"),
206 braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
207 braceR: new TokenType("}"),
208 parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
209 parenR: new TokenType(")"),
210 comma: new TokenType(",", beforeExpr),
211 semi: new TokenType(";", beforeExpr),
212 colon: new TokenType(":", beforeExpr),
213 dot: new TokenType("."),
214 question: new TokenType("?", beforeExpr),
215 questionDot: new TokenType("?."),
216 arrow: new TokenType("=>", beforeExpr),
217 template: new TokenType("template"),
218 invalidTemplate: new TokenType("invalidTemplate"),
219 ellipsis: new TokenType("...", beforeExpr),
220 backQuote: new TokenType("`", startsExpr),
221 dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
222
223 // Operators. These carry several kinds of properties to help the
224 // parser use them properly (the presence of these properties is
225 // what categorizes them as operators).
226 //
227 // `binop`, when present, specifies that this operator is a binary
228 // operator, and will refer to its precedence.
229 //
230 // `prefix` and `postfix` mark the operator as a prefix or postfix
231 // unary operator.
232 //
233 // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
234 // binary operators with a very low precedence, that should result
235 // in AssignmentExpression nodes.
236
237 eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
238 assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
239 incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
240 prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
241 logicalOR: binop("||", 1),
242 logicalAND: binop("&&", 2),
243 bitwiseOR: binop("|", 3),
244 bitwiseXOR: binop("^", 4),
245 bitwiseAND: binop("&", 5),
246 equality: binop("==/!=/===/!==", 6),
247 relational: binop("</>/<=/>=", 7),
248 bitShift: binop("<</>>/>>>", 8),
249 plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
250 modulo: binop("%", 10),
251 star: binop("*", 10),
252 slash: binop("/", 10),
253 starstar: new TokenType("**", {beforeExpr: true}),
254 coalesce: binop("??", 1),
255
256 // Keyword token types.
257 _break: kw("break"),
258 _case: kw("case", beforeExpr),
259 _catch: kw("catch"),
260 _continue: kw("continue"),
261 _debugger: kw("debugger"),
262 _default: kw("default", beforeExpr),
263 _do: kw("do", {isLoop: true, beforeExpr: true}),
264 _else: kw("else", beforeExpr),
265 _finally: kw("finally"),
266 _for: kw("for", {isLoop: true}),
267 _function: kw("function", startsExpr),
268 _if: kw("if"),
269 _return: kw("return", beforeExpr),
270 _switch: kw("switch"),
271 _throw: kw("throw", beforeExpr),
272 _try: kw("try"),
273 _var: kw("var"),
274 _const: kw("const"),
275 _while: kw("while", {isLoop: true}),
276 _with: kw("with"),
277 _new: kw("new", {beforeExpr: true, startsExpr: true}),
278 _this: kw("this", startsExpr),
279 _super: kw("super", startsExpr),
280 _class: kw("class", startsExpr),
281 _extends: kw("extends", beforeExpr),
282 _export: kw("export"),
283 _import: kw("import", startsExpr),
284 _null: kw("null", startsExpr),
285 _true: kw("true", startsExpr),
286 _false: kw("false", startsExpr),
287 _in: kw("in", {beforeExpr: true, binop: 7}),
288 _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
289 _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
290 _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
291 _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
292};
293
294// Matches a whole line break (where CRLF is considered a single
295// line break). Used to count lines.
296
297var lineBreak = /\r\n?|\n|\u2028|\u2029/;
298var lineBreakG = new RegExp(lineBreak.source, "g");
299
300function isNewLine(code, ecma2019String) {
301 return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029))
302}
303
304var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
305
306var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
307
308var ref = Object.prototype;
309var hasOwnProperty = ref.hasOwnProperty;
310var toString = ref.toString;
311
312// Checks if an object has a property.
313
314function has(obj, propName) {
315 return hasOwnProperty.call(obj, propName)
316}
317
318var isArray = Array.isArray || (function (obj) { return (
319 toString.call(obj) === "[object Array]"
320); });
321
322function wordsRegexp(words) {
323 return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
324}
325
326// These are used when `options.locations` is on, for the
327// `startLoc` and `endLoc` properties.
328
329var Position = function Position(line, col) {
330 this.line = line;
331 this.column = col;
332};
333
334Position.prototype.offset = function offset (n) {
335 return new Position(this.line, this.column + n)
336};
337
338var SourceLocation = function SourceLocation(p, start, end) {
339 this.start = start;
340 this.end = end;
341 if (p.sourceFile !== null) { this.source = p.sourceFile; }
342};
343
344// The `getLineInfo` function is mostly useful when the
345// `locations` option is off (for performance reasons) and you
346// want to find the line/column position for a given character
347// offset. `input` should be the code string that the offset refers
348// into.
349
350function getLineInfo(input, offset) {
351 for (var line = 1, cur = 0;;) {
352 lineBreakG.lastIndex = cur;
353 var match = lineBreakG.exec(input);
354 if (match && match.index < offset) {
355 ++line;
356 cur = match.index + match[0].length;
357 } else {
358 return new Position(line, offset - cur)
359 }
360 }
361}
362
363// A second optional argument can be given to further configure
364// the parser process. These options are recognized:
365
366var defaultOptions = {
367 // `ecmaVersion` indicates the ECMAScript version to parse. Must be
368 // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10
369 // (2019). This influences support for strict mode, the set of
370 // reserved words, and support for new syntax features. The default
371 // is 10.
372 ecmaVersion: 10,
373 // `sourceType` indicates the mode the code should be parsed in.
374 // Can be either `"script"` or `"module"`. This influences global
375 // strict mode and parsing of `import` and `export` declarations.
376 sourceType: "script",
377 // `onInsertedSemicolon` can be a callback that will be called
378 // when a semicolon is automatically inserted. It will be passed
379 // the position of the comma as an offset, and if `locations` is
380 // enabled, it is given the location as a `{line, column}` object
381 // as second argument.
382 onInsertedSemicolon: null,
383 // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
384 // trailing commas.
385 onTrailingComma: null,
386 // By default, reserved words are only enforced if ecmaVersion >= 5.
387 // Set `allowReserved` to a boolean value to explicitly turn this on
388 // an off. When this option has the value "never", reserved words
389 // and keywords can also not be used as property names.
390 allowReserved: null,
391 // When enabled, a return at the top level is not considered an
392 // error.
393 allowReturnOutsideFunction: false,
394 // When enabled, import/export statements are not constrained to
395 // appearing at the top of the program.
396 allowImportExportEverywhere: false,
397 // When enabled, await identifiers are allowed to appear at the top-level scope,
398 // but they are still not allowed in non-async functions.
399 allowAwaitOutsideFunction: false,
400 // When enabled, hashbang directive in the beginning of file
401 // is allowed and treated as a line comment.
402 allowHashBang: false,
403 // When `locations` is on, `loc` properties holding objects with
404 // `start` and `end` properties in `{line, column}` form (with
405 // line being 1-based and column 0-based) will be attached to the
406 // nodes.
407 locations: false,
408 // A function can be passed as `onToken` option, which will
409 // cause Acorn to call that function with object in the same
410 // format as tokens returned from `tokenizer().getToken()`. Note
411 // that you are not allowed to call the parser from the
412 // callback—that will corrupt its internal state.
413 onToken: null,
414 // A function can be passed as `onComment` option, which will
415 // cause Acorn to call that function with `(block, text, start,
416 // end)` parameters whenever a comment is skipped. `block` is a
417 // boolean indicating whether this is a block (`/* */`) comment,
418 // `text` is the content of the comment, and `start` and `end` are
419 // character offsets that denote the start and end of the comment.
420 // When the `locations` option is on, two more parameters are
421 // passed, the full `{line, column}` locations of the start and
422 // end of the comments. Note that you are not allowed to call the
423 // parser from the callback—that will corrupt its internal state.
424 onComment: null,
425 // Nodes have their start and end characters offsets recorded in
426 // `start` and `end` properties (directly on the node, rather than
427 // the `loc` object, which holds line/column data. To also add a
428 // [semi-standardized][range] `range` property holding a `[start,
429 // end]` array with the same numbers, set the `ranges` option to
430 // `true`.
431 //
432 // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
433 ranges: false,
434 // It is possible to parse multiple files into a single AST by
435 // passing the tree produced by parsing the first file as
436 // `program` option in subsequent parses. This will add the
437 // toplevel forms of the parsed file to the `Program` (top) node
438 // of an existing parse tree.
439 program: null,
440 // When `locations` is on, you can pass this to record the source
441 // file in every node's `loc` object.
442 sourceFile: null,
443 // This value, if given, is stored in every node, whether
444 // `locations` is on or off.
445 directSourceFile: null,
446 // When enabled, parenthesized expressions are represented by
447 // (non-standard) ParenthesizedExpression nodes
448 preserveParens: false
449};
450
451// Interpret and default an options object
452
453function getOptions(opts) {
454 var options = {};
455
456 for (var opt in defaultOptions)
457 { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; }
458
459 if (options.ecmaVersion >= 2015)
460 { options.ecmaVersion -= 2009; }
461
462 if (options.allowReserved == null)
463 { options.allowReserved = options.ecmaVersion < 5; }
464
465 if (isArray(options.onToken)) {
466 var tokens = options.onToken;
467 options.onToken = function (token) { return tokens.push(token); };
468 }
469 if (isArray(options.onComment))
470 { options.onComment = pushComment(options, options.onComment); }
471
472 return options
473}
474
475function pushComment(options, array) {
476 return function(block, text, start, end, startLoc, endLoc) {
477 var comment = {
478 type: block ? "Block" : "Line",
479 value: text,
480 start: start,
481 end: end
482 };
483 if (options.locations)
484 { comment.loc = new SourceLocation(this, startLoc, endLoc); }
485 if (options.ranges)
486 { comment.range = [start, end]; }
487 array.push(comment);
488 }
489}
490
491// Each scope gets a bitset that may contain these flags
492var
493 SCOPE_TOP = 1,
494 SCOPE_FUNCTION = 2,
495 SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION,
496 SCOPE_ASYNC = 4,
497 SCOPE_GENERATOR = 8,
498 SCOPE_ARROW = 16,
499 SCOPE_SIMPLE_CATCH = 32,
500 SCOPE_SUPER = 64,
501 SCOPE_DIRECT_SUPER = 128;
502
503function functionFlags(async, generator) {
504 return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0)
505}
506
507// Used in checkLVal and declareName to determine the type of a binding
508var
509 BIND_NONE = 0, // Not a binding
510 BIND_VAR = 1, // Var-style binding
511 BIND_LEXICAL = 2, // Let- or const-style binding
512 BIND_FUNCTION = 3, // Function declaration
513 BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding
514 BIND_OUTSIDE = 5; // Special case for function names as bound inside the function
515
516var Parser = function Parser(options, input, startPos) {
517 this.options = options = getOptions(options);
518 this.sourceFile = options.sourceFile;
519 this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]);
520 var reserved = "";
521 if (options.allowReserved !== true) {
522 for (var v = options.ecmaVersion;; v--)
523 { if (reserved = reservedWords[v]) { break } }
524 if (options.sourceType === "module") { reserved += " await"; }
525 }
526 this.reservedWords = wordsRegexp(reserved);
527 var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
528 this.reservedWordsStrict = wordsRegexp(reservedStrict);
529 this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind);
530 this.input = String(input);
531
532 // Used to signal to callers of `readWord1` whether the word
533 // contained any escape sequences. This is needed because words with
534 // escape sequences must not be interpreted as keywords.
535 this.containsEsc = false;
536
537 // Set up token state
538
539 // The current position of the tokenizer in the input.
540 if (startPos) {
541 this.pos = startPos;
542 this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
543 this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
544 } else {
545 this.pos = this.lineStart = 0;
546 this.curLine = 1;
547 }
548
549 // Properties of the current token:
550 // Its type
551 this.type = types.eof;
552 // For tokens that include more information than their type, the value
553 this.value = null;
554 // Its start and end offset
555 this.start = this.end = this.pos;
556 // And, if locations are used, the {line, column} object
557 // corresponding to those offsets
558 this.startLoc = this.endLoc = this.curPosition();
559
560 // Position information for the previous token
561 this.lastTokEndLoc = this.lastTokStartLoc = null;
562 this.lastTokStart = this.lastTokEnd = this.pos;
563
564 // The context stack is used to superficially track syntactic
565 // context to predict whether a regular expression is allowed in a
566 // given position.
567 this.context = this.initialContext();
568 this.exprAllowed = true;
569
570 // Figure out if it's a module code.
571 this.inModule = options.sourceType === "module";
572 this.strict = this.inModule || this.strictDirective(this.pos);
573
574 // Used to signify the start of a potential arrow function
575 this.potentialArrowAt = -1;
576
577 // Positions to delayed-check that yield/await does not exist in default parameters.
578 this.yieldPos = this.awaitPos = this.awaitIdentPos = 0;
579 // Labels in scope.
580 this.labels = [];
581 // Thus-far undefined exports.
582 this.undefinedExports = {};
583
584 // If enabled, skip leading hashbang line.
585 if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
586 { this.skipLineComment(2); }
587
588 // Scope tracking for duplicate variable names (see scope.js)
589 this.scopeStack = [];
590 this.enterScope(SCOPE_TOP);
591
592 // For RegExp validation
593 this.regexpState = null;
594};
595
596var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true } };
597
598Parser.prototype.parse = function parse () {
599 var node = this.options.program || this.startNode();
600 this.nextToken();
601 return this.parseTopLevel(node)
602};
603
604prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 };
605prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 };
606prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 };
607prototypeAccessors.allowSuper.get = function () { return (this.currentThisScope().flags & SCOPE_SUPER) > 0 };
608prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 };
609prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) };
610
611// Switch to a getter for 7.0.0.
612Parser.prototype.inNonArrowFunction = function inNonArrowFunction () { return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0 };
613
614Parser.extend = function extend () {
615 var plugins = [], len = arguments.length;
616 while ( len-- ) plugins[ len ] = arguments[ len ];
617
618 var cls = this;
619 for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
620 return cls
621};
622
623Parser.parse = function parse (input, options) {
624 return new this(options, input).parse()
625};
626
627Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) {
628 var parser = new this(options, input, pos);
629 parser.nextToken();
630 return parser.parseExpression()
631};
632
633Parser.tokenizer = function tokenizer (input, options) {
634 return new this(options, input)
635};
636
637Object.defineProperties( Parser.prototype, prototypeAccessors );
638
639var pp = Parser.prototype;
640
641// ## Parser utilities
642
643var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)")/;
644pp.strictDirective = function(start) {
645 for (;;) {
646 // Try to find string literal.
647 skipWhiteSpace.lastIndex = start;
648 start += skipWhiteSpace.exec(this.input)[0].length;
649 var match = literal.exec(this.input.slice(start));
650 if (!match) { return false }
651 if ((match[1] || match[2]) === "use strict") {
652 skipWhiteSpace.lastIndex = start + match[0].length;
653 var spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length;
654 var next = this.input.charAt(end);
655 return next === ";" || next === "}" ||
656 (lineBreak.test(spaceAfter[0]) &&
657 !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "="))
658 }
659 start += match[0].length;
660
661 // Skip semicolon, if any.
662 skipWhiteSpace.lastIndex = start;
663 start += skipWhiteSpace.exec(this.input)[0].length;
664 if (this.input[start] === ";")
665 { start++; }
666 }
667};
668
669// Predicate that tests whether the next token is of the given
670// type, and if yes, consumes it as a side effect.
671
672pp.eat = function(type) {
673 if (this.type === type) {
674 this.next();
675 return true
676 } else {
677 return false
678 }
679};
680
681// Tests whether parsed token is a contextual keyword.
682
683pp.isContextual = function(name) {
684 return this.type === types.name && this.value === name && !this.containsEsc
685};
686
687// Consumes contextual keyword if possible.
688
689pp.eatContextual = function(name) {
690 if (!this.isContextual(name)) { return false }
691 this.next();
692 return true
693};
694
695// Asserts that following token is given contextual keyword.
696
697pp.expectContextual = function(name) {
698 if (!this.eatContextual(name)) { this.unexpected(); }
699};
700
701// Test whether a semicolon can be inserted at the current position.
702
703pp.canInsertSemicolon = function() {
704 return this.type === types.eof ||
705 this.type === types.braceR ||
706 lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
707};
708
709pp.insertSemicolon = function() {
710 if (this.canInsertSemicolon()) {
711 if (this.options.onInsertedSemicolon)
712 { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
713 return true
714 }
715};
716
717// Consume a semicolon, or, failing that, see if we are allowed to
718// pretend that there is a semicolon at this position.
719
720pp.semicolon = function() {
721 if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); }
722};
723
724pp.afterTrailingComma = function(tokType, notNext) {
725 if (this.type === tokType) {
726 if (this.options.onTrailingComma)
727 { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
728 if (!notNext)
729 { this.next(); }
730 return true
731 }
732};
733
734// Expect a token of a given type. If found, consume it, otherwise,
735// raise an unexpected token error.
736
737pp.expect = function(type) {
738 this.eat(type) || this.unexpected();
739};
740
741// Raise an unexpected token error.
742
743pp.unexpected = function(pos) {
744 this.raise(pos != null ? pos : this.start, "Unexpected token");
745};
746
747function DestructuringErrors() {
748 this.shorthandAssign =
749 this.trailingComma =
750 this.parenthesizedAssign =
751 this.parenthesizedBind =
752 this.doubleProto =
753 -1;
754}
755
756pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {
757 if (!refDestructuringErrors) { return }
758 if (refDestructuringErrors.trailingComma > -1)
759 { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
760 var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
761 if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); }
762};
763
764pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
765 if (!refDestructuringErrors) { return false }
766 var shorthandAssign = refDestructuringErrors.shorthandAssign;
767 var doubleProto = refDestructuringErrors.doubleProto;
768 if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 }
769 if (shorthandAssign >= 0)
770 { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); }
771 if (doubleProto >= 0)
772 { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); }
773};
774
775pp.checkYieldAwaitInDefaultParams = function() {
776 if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
777 { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
778 if (this.awaitPos)
779 { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
780};
781
782pp.isSimpleAssignTarget = function(expr) {
783 if (expr.type === "ParenthesizedExpression")
784 { return this.isSimpleAssignTarget(expr.expression) }
785 return expr.type === "Identifier" || expr.type === "MemberExpression"
786};
787
788var pp$1 = Parser.prototype;
789
790// ### Statement parsing
791
792// Parse a program. Initializes the parser, reads any number of
793// statements, and wraps them in a Program node. Optionally takes a
794// `program` argument. If present, the statements will be appended
795// to its body instead of creating a new node.
796
797pp$1.parseTopLevel = function(node) {
798 var exports = {};
799 if (!node.body) { node.body = []; }
800 while (this.type !== types.eof) {
801 var stmt = this.parseStatement(null, true, exports);
802 node.body.push(stmt);
803 }
804 if (this.inModule)
805 { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1)
806 {
807 var name = list[i];
808
809 this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined"));
810 } }
811 this.adaptDirectivePrologue(node.body);
812 this.next();
813 node.sourceType = this.options.sourceType;
814 return this.finishNode(node, "Program")
815};
816
817var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};
818
819pp$1.isLet = function(context) {
820 if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false }
821 skipWhiteSpace.lastIndex = this.pos;
822 var skip = skipWhiteSpace.exec(this.input);
823 var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
824 // For ambiguous cases, determine if a LexicalDeclaration (or only a
825 // Statement) is allowed here. If context is not empty then only a Statement
826 // is allowed. However, `let [` is an explicit negative lookahead for
827 // ExpressionStatement, so special-case it first.
828 if (nextCh === 91) { return true } // '['
829 if (context) { return false }
830
831 if (nextCh === 123) { return true } // '{'
832 if (isIdentifierStart(nextCh, true)) {
833 var pos = next + 1;
834 while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; }
835 var ident = this.input.slice(next, pos);
836 if (!keywordRelationalOperator.test(ident)) { return true }
837 }
838 return false
839};
840
841// check 'async [no LineTerminator here] function'
842// - 'async /*foo*/ function' is OK.
843// - 'async /*\n*/ function' is invalid.
844pp$1.isAsyncFunction = function() {
845 if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
846 { return false }
847
848 skipWhiteSpace.lastIndex = this.pos;
849 var skip = skipWhiteSpace.exec(this.input);
850 var next = this.pos + skip[0].length;
851 return !lineBreak.test(this.input.slice(this.pos, next)) &&
852 this.input.slice(next, next + 8) === "function" &&
853 (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))
854};
855
856// Parse a single statement.
857//
858// If expecting a statement and finding a slash operator, parse a
859// regular expression literal. This is to handle cases like
860// `if (foo) /blah/.exec(foo)`, where looking at the previous token
861// does not help.
862
863pp$1.parseStatement = function(context, topLevel, exports) {
864 var starttype = this.type, node = this.startNode(), kind;
865
866 if (this.isLet(context)) {
867 starttype = types._var;
868 kind = "let";
869 }
870
871 // Most types of statements are recognized by the keyword they
872 // start with. Many are trivial to parse, some require a bit of
873 // complexity.
874
875 switch (starttype) {
876 case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
877 case types._debugger: return this.parseDebuggerStatement(node)
878 case types._do: return this.parseDoStatement(node)
879 case types._for: return this.parseForStatement(node)
880 case types._function:
881 // Function as sole body of either an if statement or a labeled statement
882 // works, but not when it is part of a labeled statement that is the sole
883 // body of an if statement.
884 if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); }
885 return this.parseFunctionStatement(node, false, !context)
886 case types._class:
887 if (context) { this.unexpected(); }
888 return this.parseClass(node, true)
889 case types._if: return this.parseIfStatement(node)
890 case types._return: return this.parseReturnStatement(node)
891 case types._switch: return this.parseSwitchStatement(node)
892 case types._throw: return this.parseThrowStatement(node)
893 case types._try: return this.parseTryStatement(node)
894 case types._const: case types._var:
895 kind = kind || this.value;
896 if (context && kind !== "var") { this.unexpected(); }
897 return this.parseVarStatement(node, kind)
898 case types._while: return this.parseWhileStatement(node)
899 case types._with: return this.parseWithStatement(node)
900 case types.braceL: return this.parseBlock(true, node)
901 case types.semi: return this.parseEmptyStatement(node)
902 case types._export:
903 case types._import:
904 if (this.options.ecmaVersion > 10 && starttype === types._import) {
905 skipWhiteSpace.lastIndex = this.pos;
906 var skip = skipWhiteSpace.exec(this.input);
907 var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
908 if (nextCh === 40 || nextCh === 46) // '(' or '.'
909 { return this.parseExpressionStatement(node, this.parseExpression()) }
910 }
911
912 if (!this.options.allowImportExportEverywhere) {
913 if (!topLevel)
914 { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
915 if (!this.inModule)
916 { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
917 }
918 return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports)
919
920 // If the statement does not start with a statement keyword or a
921 // brace, it's an ExpressionStatement or LabeledStatement. We
922 // simply start parsing an expression, and afterwards, if the
923 // next token is a colon and the expression was a simple
924 // Identifier node, we switch to interpreting it as a label.
925 default:
926 if (this.isAsyncFunction()) {
927 if (context) { this.unexpected(); }
928 this.next();
929 return this.parseFunctionStatement(node, true, !context)
930 }
931
932 var maybeName = this.value, expr = this.parseExpression();
933 if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon))
934 { return this.parseLabeledStatement(node, maybeName, expr, context) }
935 else { return this.parseExpressionStatement(node, expr) }
936 }
937};
938
939pp$1.parseBreakContinueStatement = function(node, keyword) {
940 var isBreak = keyword === "break";
941 this.next();
942 if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; }
943 else if (this.type !== types.name) { this.unexpected(); }
944 else {
945 node.label = this.parseIdent();
946 this.semicolon();
947 }
948
949 // Verify that there is an actual destination to break or
950 // continue to.
951 var i = 0;
952 for (; i < this.labels.length; ++i) {
953 var lab = this.labels[i];
954 if (node.label == null || lab.name === node.label.name) {
955 if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
956 if (node.label && isBreak) { break }
957 }
958 }
959 if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
960 return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
961};
962
963pp$1.parseDebuggerStatement = function(node) {
964 this.next();
965 this.semicolon();
966 return this.finishNode(node, "DebuggerStatement")
967};
968
969pp$1.parseDoStatement = function(node) {
970 this.next();
971 this.labels.push(loopLabel);
972 node.body = this.parseStatement("do");
973 this.labels.pop();
974 this.expect(types._while);
975 node.test = this.parseParenExpression();
976 if (this.options.ecmaVersion >= 6)
977 { this.eat(types.semi); }
978 else
979 { this.semicolon(); }
980 return this.finishNode(node, "DoWhileStatement")
981};
982
983// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
984// loop is non-trivial. Basically, we have to parse the init `var`
985// statement or expression, disallowing the `in` operator (see
986// the second parameter to `parseExpression`), and then check
987// whether the next token is `in` or `of`. When there is no init
988// part (semicolon immediately after the opening parenthesis), it
989// is a regular `for` loop.
990
991pp$1.parseForStatement = function(node) {
992 this.next();
993 var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1;
994 this.labels.push(loopLabel);
995 this.enterScope(0);
996 this.expect(types.parenL);
997 if (this.type === types.semi) {
998 if (awaitAt > -1) { this.unexpected(awaitAt); }
999 return this.parseFor(node, null)
1000 }
1001 var isLet = this.isLet();
1002 if (this.type === types._var || this.type === types._const || isLet) {
1003 var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
1004 this.next();
1005 this.parseVar(init$1, true, kind);
1006 this.finishNode(init$1, "VariableDeclaration");
1007 if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1) {
1008 if (this.options.ecmaVersion >= 9) {
1009 if (this.type === types._in) {
1010 if (awaitAt > -1) { this.unexpected(awaitAt); }
1011 } else { node.await = awaitAt > -1; }
1012 }
1013 return this.parseForIn(node, init$1)
1014 }
1015 if (awaitAt > -1) { this.unexpected(awaitAt); }
1016 return this.parseFor(node, init$1)
1017 }
1018 var refDestructuringErrors = new DestructuringErrors;
1019 var init = this.parseExpression(true, refDestructuringErrors);
1020 if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
1021 if (this.options.ecmaVersion >= 9) {
1022 if (this.type === types._in) {
1023 if (awaitAt > -1) { this.unexpected(awaitAt); }
1024 } else { node.await = awaitAt > -1; }
1025 }
1026 this.toAssignable(init, false, refDestructuringErrors);
1027 this.checkLVal(init);
1028 return this.parseForIn(node, init)
1029 } else {
1030 this.checkExpressionErrors(refDestructuringErrors, true);
1031 }
1032 if (awaitAt > -1) { this.unexpected(awaitAt); }
1033 return this.parseFor(node, init)
1034};
1035
1036pp$1.parseFunctionStatement = function(node, isAsync, declarationPosition) {
1037 this.next();
1038 return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync)
1039};
1040
1041pp$1.parseIfStatement = function(node) {
1042 this.next();
1043 node.test = this.parseParenExpression();
1044 // allow function declarations in branches, but only in non-strict mode
1045 node.consequent = this.parseStatement("if");
1046 node.alternate = this.eat(types._else) ? this.parseStatement("if") : null;
1047 return this.finishNode(node, "IfStatement")
1048};
1049
1050pp$1.parseReturnStatement = function(node) {
1051 if (!this.inFunction && !this.options.allowReturnOutsideFunction)
1052 { this.raise(this.start, "'return' outside of function"); }
1053 this.next();
1054
1055 // In `return` (and `break`/`continue`), the keywords with
1056 // optional arguments, we eagerly look for a semicolon or the
1057 // possibility to insert one.
1058
1059 if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; }
1060 else { node.argument = this.parseExpression(); this.semicolon(); }
1061 return this.finishNode(node, "ReturnStatement")
1062};
1063
1064pp$1.parseSwitchStatement = function(node) {
1065 this.next();
1066 node.discriminant = this.parseParenExpression();
1067 node.cases = [];
1068 this.expect(types.braceL);
1069 this.labels.push(switchLabel);
1070 this.enterScope(0);
1071
1072 // Statements under must be grouped (by label) in SwitchCase
1073 // nodes. `cur` is used to keep the node that we are currently
1074 // adding statements to.
1075
1076 var cur;
1077 for (var sawDefault = false; this.type !== types.braceR;) {
1078 if (this.type === types._case || this.type === types._default) {
1079 var isCase = this.type === types._case;
1080 if (cur) { this.finishNode(cur, "SwitchCase"); }
1081 node.cases.push(cur = this.startNode());
1082 cur.consequent = [];
1083 this.next();
1084 if (isCase) {
1085 cur.test = this.parseExpression();
1086 } else {
1087 if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); }
1088 sawDefault = true;
1089 cur.test = null;
1090 }
1091 this.expect(types.colon);
1092 } else {
1093 if (!cur) { this.unexpected(); }
1094 cur.consequent.push(this.parseStatement(null));
1095 }
1096 }
1097 this.exitScope();
1098 if (cur) { this.finishNode(cur, "SwitchCase"); }
1099 this.next(); // Closing brace
1100 this.labels.pop();
1101 return this.finishNode(node, "SwitchStatement")
1102};
1103
1104pp$1.parseThrowStatement = function(node) {
1105 this.next();
1106 if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
1107 { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
1108 node.argument = this.parseExpression();
1109 this.semicolon();
1110 return this.finishNode(node, "ThrowStatement")
1111};
1112
1113// Reused empty array added for node fields that are always empty.
1114
1115var empty = [];
1116
1117pp$1.parseTryStatement = function(node) {
1118 this.next();
1119 node.block = this.parseBlock();
1120 node.handler = null;
1121 if (this.type === types._catch) {
1122 var clause = this.startNode();
1123 this.next();
1124 if (this.eat(types.parenL)) {
1125 clause.param = this.parseBindingAtom();
1126 var simple = clause.param.type === "Identifier";
1127 this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0);
1128 this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL);
1129 this.expect(types.parenR);
1130 } else {
1131 if (this.options.ecmaVersion < 10) { this.unexpected(); }
1132 clause.param = null;
1133 this.enterScope(0);
1134 }
1135 clause.body = this.parseBlock(false);
1136 this.exitScope();
1137 node.handler = this.finishNode(clause, "CatchClause");
1138 }
1139 node.finalizer = this.eat(types._finally) ? this.parseBlock() : null;
1140 if (!node.handler && !node.finalizer)
1141 { this.raise(node.start, "Missing catch or finally clause"); }
1142 return this.finishNode(node, "TryStatement")
1143};
1144
1145pp$1.parseVarStatement = function(node, kind) {
1146 this.next();
1147 this.parseVar(node, false, kind);
1148 this.semicolon();
1149 return this.finishNode(node, "VariableDeclaration")
1150};
1151
1152pp$1.parseWhileStatement = function(node) {
1153 this.next();
1154 node.test = this.parseParenExpression();
1155 this.labels.push(loopLabel);
1156 node.body = this.parseStatement("while");
1157 this.labels.pop();
1158 return this.finishNode(node, "WhileStatement")
1159};
1160
1161pp$1.parseWithStatement = function(node) {
1162 if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
1163 this.next();
1164 node.object = this.parseParenExpression();
1165 node.body = this.parseStatement("with");
1166 return this.finishNode(node, "WithStatement")
1167};
1168
1169pp$1.parseEmptyStatement = function(node) {
1170 this.next();
1171 return this.finishNode(node, "EmptyStatement")
1172};
1173
1174pp$1.parseLabeledStatement = function(node, maybeName, expr, context) {
1175 for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1)
1176 {
1177 var label = list[i$1];
1178
1179 if (label.name === maybeName)
1180 { this.raise(expr.start, "Label '" + maybeName + "' is already declared");
1181 } }
1182 var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null;
1183 for (var i = this.labels.length - 1; i >= 0; i--) {
1184 var label$1 = this.labels[i];
1185 if (label$1.statementStart === node.start) {
1186 // Update information about previous labels on this node
1187 label$1.statementStart = this.start;
1188 label$1.kind = kind;
1189 } else { break }
1190 }
1191 this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
1192 node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label");
1193 this.labels.pop();
1194 node.label = expr;
1195 return this.finishNode(node, "LabeledStatement")
1196};
1197
1198pp$1.parseExpressionStatement = function(node, expr) {
1199 node.expression = expr;
1200 this.semicolon();
1201 return this.finishNode(node, "ExpressionStatement")
1202};
1203
1204// Parse a semicolon-enclosed block of statements, handling `"use
1205// strict"` declarations when `allowStrict` is true (used for
1206// function bodies).
1207
1208pp$1.parseBlock = function(createNewLexicalScope, node, exitStrict) {
1209 if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;
1210 if ( node === void 0 ) node = this.startNode();
1211
1212 node.body = [];
1213 this.expect(types.braceL);
1214 if (createNewLexicalScope) { this.enterScope(0); }
1215 while (this.type !== types.braceR) {
1216 var stmt = this.parseStatement(null);
1217 node.body.push(stmt);
1218 }
1219 if (exitStrict) { this.strict = false; }
1220 this.next();
1221 if (createNewLexicalScope) { this.exitScope(); }
1222 return this.finishNode(node, "BlockStatement")
1223};
1224
1225// Parse a regular `for` loop. The disambiguation code in
1226// `parseStatement` will already have parsed the init statement or
1227// expression.
1228
1229pp$1.parseFor = function(node, init) {
1230 node.init = init;
1231 this.expect(types.semi);
1232 node.test = this.type === types.semi ? null : this.parseExpression();
1233 this.expect(types.semi);
1234 node.update = this.type === types.parenR ? null : this.parseExpression();
1235 this.expect(types.parenR);
1236 node.body = this.parseStatement("for");
1237 this.exitScope();
1238 this.labels.pop();
1239 return this.finishNode(node, "ForStatement")
1240};
1241
1242// Parse a `for`/`in` and `for`/`of` loop, which are almost
1243// same from parser's perspective.
1244
1245pp$1.parseForIn = function(node, init) {
1246 var isForIn = this.type === types._in;
1247 this.next();
1248
1249 if (
1250 init.type === "VariableDeclaration" &&
1251 init.declarations[0].init != null &&
1252 (
1253 !isForIn ||
1254 this.options.ecmaVersion < 8 ||
1255 this.strict ||
1256 init.kind !== "var" ||
1257 init.declarations[0].id.type !== "Identifier"
1258 )
1259 ) {
1260 this.raise(
1261 init.start,
1262 ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer")
1263 );
1264 } else if (init.type === "AssignmentPattern") {
1265 this.raise(init.start, "Invalid left-hand side in for-loop");
1266 }
1267 node.left = init;
1268 node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign();
1269 this.expect(types.parenR);
1270 node.body = this.parseStatement("for");
1271 this.exitScope();
1272 this.labels.pop();
1273 return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement")
1274};
1275
1276// Parse a list of variable declarations.
1277
1278pp$1.parseVar = function(node, isFor, kind) {
1279 node.declarations = [];
1280 node.kind = kind;
1281 for (;;) {
1282 var decl = this.startNode();
1283 this.parseVarId(decl, kind);
1284 if (this.eat(types.eq)) {
1285 decl.init = this.parseMaybeAssign(isFor);
1286 } else if (kind === "const" && !(this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
1287 this.unexpected();
1288 } else if (decl.id.type !== "Identifier" && !(isFor && (this.type === types._in || this.isContextual("of")))) {
1289 this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value");
1290 } else {
1291 decl.init = null;
1292 }
1293 node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
1294 if (!this.eat(types.comma)) { break }
1295 }
1296 return node
1297};
1298
1299pp$1.parseVarId = function(decl, kind) {
1300 decl.id = this.parseBindingAtom();
1301 this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false);
1302};
1303
1304var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4;
1305
1306// Parse a function declaration or literal (depending on the
1307// `statement & FUNC_STATEMENT`).
1308
1309// Remove `allowExpressionBody` for 7.0.0, as it is only called with false
1310pp$1.parseFunction = function(node, statement, allowExpressionBody, isAsync) {
1311 this.initFunction(node);
1312 if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) {
1313 if (this.type === types.star && (statement & FUNC_HANGING_STATEMENT))
1314 { this.unexpected(); }
1315 node.generator = this.eat(types.star);
1316 }
1317 if (this.options.ecmaVersion >= 8)
1318 { node.async = !!isAsync; }
1319
1320 if (statement & FUNC_STATEMENT) {
1321 node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name ? null : this.parseIdent();
1322 if (node.id && !(statement & FUNC_HANGING_STATEMENT))
1323 // If it is a regular function declaration in sloppy mode, then it is
1324 // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
1325 // mode depends on properties of the current scope (see
1326 // treatFunctionsAsVar).
1327 { this.checkLVal(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); }
1328 }
1329
1330 var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
1331 this.yieldPos = 0;
1332 this.awaitPos = 0;
1333 this.awaitIdentPos = 0;
1334 this.enterScope(functionFlags(node.async, node.generator));
1335
1336 if (!(statement & FUNC_STATEMENT))
1337 { node.id = this.type === types.name ? this.parseIdent() : null; }
1338
1339 this.parseFunctionParams(node);
1340 this.parseFunctionBody(node, allowExpressionBody, false);
1341
1342 this.yieldPos = oldYieldPos;
1343 this.awaitPos = oldAwaitPos;
1344 this.awaitIdentPos = oldAwaitIdentPos;
1345 return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression")
1346};
1347
1348pp$1.parseFunctionParams = function(node) {
1349 this.expect(types.parenL);
1350 node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
1351 this.checkYieldAwaitInDefaultParams();
1352};
1353
1354// Parse a class declaration or literal (depending on the
1355// `isStatement` parameter).
1356
1357pp$1.parseClass = function(node, isStatement) {
1358 this.next();
1359
1360 // ecma-262 14.6 Class Definitions
1361 // A class definition is always strict mode code.
1362 var oldStrict = this.strict;
1363 this.strict = true;
1364
1365 this.parseClassId(node, isStatement);
1366 this.parseClassSuper(node);
1367 var classBody = this.startNode();
1368 var hadConstructor = false;
1369 classBody.body = [];
1370 this.expect(types.braceL);
1371 while (this.type !== types.braceR) {
1372 var element = this.parseClassElement(node.superClass !== null);
1373 if (element) {
1374 classBody.body.push(element);
1375 if (element.type === "MethodDefinition" && element.kind === "constructor") {
1376 if (hadConstructor) { this.raise(element.start, "Duplicate constructor in the same class"); }
1377 hadConstructor = true;
1378 }
1379 }
1380 }
1381 this.strict = oldStrict;
1382 this.next();
1383 node.body = this.finishNode(classBody, "ClassBody");
1384 return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
1385};
1386
1387pp$1.parseClassElement = function(constructorAllowsSuper) {
1388 var this$1 = this;
1389
1390 if (this.eat(types.semi)) { return null }
1391
1392 var method = this.startNode();
1393 var tryContextual = function (k, noLineBreak) {
1394 if ( noLineBreak === void 0 ) noLineBreak = false;
1395
1396 var start = this$1.start, startLoc = this$1.startLoc;
1397 if (!this$1.eatContextual(k)) { return false }
1398 if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true }
1399 if (method.key) { this$1.unexpected(); }
1400 method.computed = false;
1401 method.key = this$1.startNodeAt(start, startLoc);
1402 method.key.name = k;
1403 this$1.finishNode(method.key, "Identifier");
1404 return false
1405 };
1406
1407 method.kind = "method";
1408 method.static = tryContextual("static");
1409 var isGenerator = this.eat(types.star);
1410 var isAsync = false;
1411 if (!isGenerator) {
1412 if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) {
1413 isAsync = true;
1414 isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
1415 } else if (tryContextual("get")) {
1416 method.kind = "get";
1417 } else if (tryContextual("set")) {
1418 method.kind = "set";
1419 }
1420 }
1421 if (!method.key) { this.parsePropertyName(method); }
1422 var key = method.key;
1423 var allowsDirectSuper = false;
1424 if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" ||
1425 key.type === "Literal" && key.value === "constructor")) {
1426 if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); }
1427 if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); }
1428 if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); }
1429 method.kind = "constructor";
1430 allowsDirectSuper = constructorAllowsSuper;
1431 } else if (method.static && key.type === "Identifier" && key.name === "prototype") {
1432 this.raise(key.start, "Classes may not have a static property named prototype");
1433 }
1434 this.parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper);
1435 if (method.kind === "get" && method.value.params.length !== 0)
1436 { this.raiseRecoverable(method.value.start, "getter should have no params"); }
1437 if (method.kind === "set" && method.value.params.length !== 1)
1438 { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); }
1439 if (method.kind === "set" && method.value.params[0].type === "RestElement")
1440 { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); }
1441 return method
1442};
1443
1444pp$1.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) {
1445 method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper);
1446 return this.finishNode(method, "MethodDefinition")
1447};
1448
1449pp$1.parseClassId = function(node, isStatement) {
1450 if (this.type === types.name) {
1451 node.id = this.parseIdent();
1452 if (isStatement)
1453 { this.checkLVal(node.id, BIND_LEXICAL, false); }
1454 } else {
1455 if (isStatement === true)
1456 { this.unexpected(); }
1457 node.id = null;
1458 }
1459};
1460
1461pp$1.parseClassSuper = function(node) {
1462 node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null;
1463};
1464
1465// Parses module export declaration.
1466
1467pp$1.parseExport = function(node, exports) {
1468 this.next();
1469 // export * from '...'
1470 if (this.eat(types.star)) {
1471 if (this.options.ecmaVersion >= 11) {
1472 if (this.eatContextual("as")) {
1473 node.exported = this.parseIdent(true);
1474 this.checkExport(exports, node.exported.name, this.lastTokStart);
1475 } else {
1476 node.exported = null;
1477 }
1478 }
1479 this.expectContextual("from");
1480 if (this.type !== types.string) { this.unexpected(); }
1481 node.source = this.parseExprAtom();
1482 this.semicolon();
1483 return this.finishNode(node, "ExportAllDeclaration")
1484 }
1485 if (this.eat(types._default)) { // export default ...
1486 this.checkExport(exports, "default", this.lastTokStart);
1487 var isAsync;
1488 if (this.type === types._function || (isAsync = this.isAsyncFunction())) {
1489 var fNode = this.startNode();
1490 this.next();
1491 if (isAsync) { this.next(); }
1492 node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync);
1493 } else if (this.type === types._class) {
1494 var cNode = this.startNode();
1495 node.declaration = this.parseClass(cNode, "nullableID");
1496 } else {
1497 node.declaration = this.parseMaybeAssign();
1498 this.semicolon();
1499 }
1500 return this.finishNode(node, "ExportDefaultDeclaration")
1501 }
1502 // export var|const|let|function|class ...
1503 if (this.shouldParseExportStatement()) {
1504 node.declaration = this.parseStatement(null);
1505 if (node.declaration.type === "VariableDeclaration")
1506 { this.checkVariableExport(exports, node.declaration.declarations); }
1507 else
1508 { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); }
1509 node.specifiers = [];
1510 node.source = null;
1511 } else { // export { x, y as z } [from '...']
1512 node.declaration = null;
1513 node.specifiers = this.parseExportSpecifiers(exports);
1514 if (this.eatContextual("from")) {
1515 if (this.type !== types.string) { this.unexpected(); }
1516 node.source = this.parseExprAtom();
1517 } else {
1518 for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
1519 // check for keywords used as local names
1520 var spec = list[i];
1521
1522 this.checkUnreserved(spec.local);
1523 // check if export is defined
1524 this.checkLocalExport(spec.local);
1525 }
1526
1527 node.source = null;
1528 }
1529 this.semicolon();
1530 }
1531 return this.finishNode(node, "ExportNamedDeclaration")
1532};
1533
1534pp$1.checkExport = function(exports, name, pos) {
1535 if (!exports) { return }
1536 if (has(exports, name))
1537 { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
1538 exports[name] = true;
1539};
1540
1541pp$1.checkPatternExport = function(exports, pat) {
1542 var type = pat.type;
1543 if (type === "Identifier")
1544 { this.checkExport(exports, pat.name, pat.start); }
1545 else if (type === "ObjectPattern")
1546 { for (var i = 0, list = pat.properties; i < list.length; i += 1)
1547 {
1548 var prop = list[i];
1549
1550 this.checkPatternExport(exports, prop);
1551 } }
1552 else if (type === "ArrayPattern")
1553 { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
1554 var elt = list$1[i$1];
1555
1556 if (elt) { this.checkPatternExport(exports, elt); }
1557 } }
1558 else if (type === "Property")
1559 { this.checkPatternExport(exports, pat.value); }
1560 else if (type === "AssignmentPattern")
1561 { this.checkPatternExport(exports, pat.left); }
1562 else if (type === "RestElement")
1563 { this.checkPatternExport(exports, pat.argument); }
1564 else if (type === "ParenthesizedExpression")
1565 { this.checkPatternExport(exports, pat.expression); }
1566};
1567
1568pp$1.checkVariableExport = function(exports, decls) {
1569 if (!exports) { return }
1570 for (var i = 0, list = decls; i < list.length; i += 1)
1571 {
1572 var decl = list[i];
1573
1574 this.checkPatternExport(exports, decl.id);
1575 }
1576};
1577
1578pp$1.shouldParseExportStatement = function() {
1579 return this.type.keyword === "var" ||
1580 this.type.keyword === "const" ||
1581 this.type.keyword === "class" ||
1582 this.type.keyword === "function" ||
1583 this.isLet() ||
1584 this.isAsyncFunction()
1585};
1586
1587// Parses a comma-separated list of module exports.
1588
1589pp$1.parseExportSpecifiers = function(exports) {
1590 var nodes = [], first = true;
1591 // export { x, y as z } [from '...']
1592 this.expect(types.braceL);
1593 while (!this.eat(types.braceR)) {
1594 if (!first) {
1595 this.expect(types.comma);
1596 if (this.afterTrailingComma(types.braceR)) { break }
1597 } else { first = false; }
1598
1599 var node = this.startNode();
1600 node.local = this.parseIdent(true);
1601 node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local;
1602 this.checkExport(exports, node.exported.name, node.exported.start);
1603 nodes.push(this.finishNode(node, "ExportSpecifier"));
1604 }
1605 return nodes
1606};
1607
1608// Parses import declaration.
1609
1610pp$1.parseImport = function(node) {
1611 this.next();
1612 // import '...'
1613 if (this.type === types.string) {
1614 node.specifiers = empty;
1615 node.source = this.parseExprAtom();
1616 } else {
1617 node.specifiers = this.parseImportSpecifiers();
1618 this.expectContextual("from");
1619 node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
1620 }
1621 this.semicolon();
1622 return this.finishNode(node, "ImportDeclaration")
1623};
1624
1625// Parses a comma-separated list of module imports.
1626
1627pp$1.parseImportSpecifiers = function() {
1628 var nodes = [], first = true;
1629 if (this.type === types.name) {
1630 // import defaultObj, { x, y as z } from '...'
1631 var node = this.startNode();
1632 node.local = this.parseIdent();
1633 this.checkLVal(node.local, BIND_LEXICAL);
1634 nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
1635 if (!this.eat(types.comma)) { return nodes }
1636 }
1637 if (this.type === types.star) {
1638 var node$1 = this.startNode();
1639 this.next();
1640 this.expectContextual("as");
1641 node$1.local = this.parseIdent();
1642 this.checkLVal(node$1.local, BIND_LEXICAL);
1643 nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
1644 return nodes
1645 }
1646 this.expect(types.braceL);
1647 while (!this.eat(types.braceR)) {
1648 if (!first) {
1649 this.expect(types.comma);
1650 if (this.afterTrailingComma(types.braceR)) { break }
1651 } else { first = false; }
1652
1653 var node$2 = this.startNode();
1654 node$2.imported = this.parseIdent(true);
1655 if (this.eatContextual("as")) {
1656 node$2.local = this.parseIdent();
1657 } else {
1658 this.checkUnreserved(node$2.imported);
1659 node$2.local = node$2.imported;
1660 }
1661 this.checkLVal(node$2.local, BIND_LEXICAL);
1662 nodes.push(this.finishNode(node$2, "ImportSpecifier"));
1663 }
1664 return nodes
1665};
1666
1667// Set `ExpressionStatement#directive` property for directive prologues.
1668pp$1.adaptDirectivePrologue = function(statements) {
1669 for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
1670 statements[i].directive = statements[i].expression.raw.slice(1, -1);
1671 }
1672};
1673pp$1.isDirectiveCandidate = function(statement) {
1674 return (
1675 statement.type === "ExpressionStatement" &&
1676 statement.expression.type === "Literal" &&
1677 typeof statement.expression.value === "string" &&
1678 // Reject parenthesized strings.
1679 (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
1680 )
1681};
1682
1683var pp$2 = Parser.prototype;
1684
1685// Convert existing expression atom to assignable pattern
1686// if possible.
1687
1688pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) {
1689 if (this.options.ecmaVersion >= 6 && node) {
1690 switch (node.type) {
1691 case "Identifier":
1692 if (this.inAsync && node.name === "await")
1693 { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); }
1694 break
1695
1696 case "ObjectPattern":
1697 case "ArrayPattern":
1698 case "RestElement":
1699 break
1700
1701 case "ObjectExpression":
1702 node.type = "ObjectPattern";
1703 if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1704 for (var i = 0, list = node.properties; i < list.length; i += 1) {
1705 var prop = list[i];
1706
1707 this.toAssignable(prop, isBinding);
1708 // Early error:
1709 // AssignmentRestProperty[Yield, Await] :
1710 // `...` DestructuringAssignmentTarget[Yield, Await]
1711 //
1712 // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
1713 if (
1714 prop.type === "RestElement" &&
1715 (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")
1716 ) {
1717 this.raise(prop.argument.start, "Unexpected token");
1718 }
1719 }
1720 break
1721
1722 case "Property":
1723 // AssignmentProperty has type === "Property"
1724 if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); }
1725 this.toAssignable(node.value, isBinding);
1726 break
1727
1728 case "ArrayExpression":
1729 node.type = "ArrayPattern";
1730 if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1731 this.toAssignableList(node.elements, isBinding);
1732 break
1733
1734 case "SpreadElement":
1735 node.type = "RestElement";
1736 this.toAssignable(node.argument, isBinding);
1737 if (node.argument.type === "AssignmentPattern")
1738 { this.raise(node.argument.start, "Rest elements cannot have a default value"); }
1739 break
1740
1741 case "AssignmentExpression":
1742 if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); }
1743 node.type = "AssignmentPattern";
1744 delete node.operator;
1745 this.toAssignable(node.left, isBinding);
1746 // falls through to AssignmentPattern
1747
1748 case "AssignmentPattern":
1749 break
1750
1751 case "ParenthesizedExpression":
1752 this.toAssignable(node.expression, isBinding, refDestructuringErrors);
1753 break
1754
1755 case "ChainExpression":
1756 this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side");
1757 break
1758
1759 case "MemberExpression":
1760 if (!isBinding) { break }
1761
1762 default:
1763 this.raise(node.start, "Assigning to rvalue");
1764 }
1765 } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1766 return node
1767};
1768
1769// Convert list of expression atoms to binding list.
1770
1771pp$2.toAssignableList = function(exprList, isBinding) {
1772 var end = exprList.length;
1773 for (var i = 0; i < end; i++) {
1774 var elt = exprList[i];
1775 if (elt) { this.toAssignable(elt, isBinding); }
1776 }
1777 if (end) {
1778 var last = exprList[end - 1];
1779 if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
1780 { this.unexpected(last.argument.start); }
1781 }
1782 return exprList
1783};
1784
1785// Parses spread element.
1786
1787pp$2.parseSpread = function(refDestructuringErrors) {
1788 var node = this.startNode();
1789 this.next();
1790 node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
1791 return this.finishNode(node, "SpreadElement")
1792};
1793
1794pp$2.parseRestBinding = function() {
1795 var node = this.startNode();
1796 this.next();
1797
1798 // RestElement inside of a function parameter must be an identifier
1799 if (this.options.ecmaVersion === 6 && this.type !== types.name)
1800 { this.unexpected(); }
1801
1802 node.argument = this.parseBindingAtom();
1803
1804 return this.finishNode(node, "RestElement")
1805};
1806
1807// Parses lvalue (assignable) atom.
1808
1809pp$2.parseBindingAtom = function() {
1810 if (this.options.ecmaVersion >= 6) {
1811 switch (this.type) {
1812 case types.bracketL:
1813 var node = this.startNode();
1814 this.next();
1815 node.elements = this.parseBindingList(types.bracketR, true, true);
1816 return this.finishNode(node, "ArrayPattern")
1817
1818 case types.braceL:
1819 return this.parseObj(true)
1820 }
1821 }
1822 return this.parseIdent()
1823};
1824
1825pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
1826 var elts = [], first = true;
1827 while (!this.eat(close)) {
1828 if (first) { first = false; }
1829 else { this.expect(types.comma); }
1830 if (allowEmpty && this.type === types.comma) {
1831 elts.push(null);
1832 } else if (allowTrailingComma && this.afterTrailingComma(close)) {
1833 break
1834 } else if (this.type === types.ellipsis) {
1835 var rest = this.parseRestBinding();
1836 this.parseBindingListItem(rest);
1837 elts.push(rest);
1838 if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); }
1839 this.expect(close);
1840 break
1841 } else {
1842 var elem = this.parseMaybeDefault(this.start, this.startLoc);
1843 this.parseBindingListItem(elem);
1844 elts.push(elem);
1845 }
1846 }
1847 return elts
1848};
1849
1850pp$2.parseBindingListItem = function(param) {
1851 return param
1852};
1853
1854// Parses assignment pattern around given atom if possible.
1855
1856pp$2.parseMaybeDefault = function(startPos, startLoc, left) {
1857 left = left || this.parseBindingAtom();
1858 if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left }
1859 var node = this.startNodeAt(startPos, startLoc);
1860 node.left = left;
1861 node.right = this.parseMaybeAssign();
1862 return this.finishNode(node, "AssignmentPattern")
1863};
1864
1865// Verify that a node is an lval — something that can be assigned
1866// to.
1867// bindingType can be either:
1868// 'var' indicating that the lval creates a 'var' binding
1869// 'let' indicating that the lval creates a lexical ('let' or 'const') binding
1870// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references
1871
1872pp$2.checkLVal = function(expr, bindingType, checkClashes) {
1873 if ( bindingType === void 0 ) bindingType = BIND_NONE;
1874
1875 switch (expr.type) {
1876 case "Identifier":
1877 if (bindingType === BIND_LEXICAL && expr.name === "let")
1878 { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); }
1879 if (this.strict && this.reservedWordsStrictBind.test(expr.name))
1880 { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
1881 if (checkClashes) {
1882 if (has(checkClashes, expr.name))
1883 { this.raiseRecoverable(expr.start, "Argument name clash"); }
1884 checkClashes[expr.name] = true;
1885 }
1886 if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); }
1887 break
1888
1889 case "ChainExpression":
1890 this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side");
1891 break
1892
1893 case "MemberExpression":
1894 if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); }
1895 break
1896
1897 case "ObjectPattern":
1898 for (var i = 0, list = expr.properties; i < list.length; i += 1)
1899 {
1900 var prop = list[i];
1901
1902 this.checkLVal(prop, bindingType, checkClashes);
1903 }
1904 break
1905
1906 case "Property":
1907 // AssignmentProperty has type === "Property"
1908 this.checkLVal(expr.value, bindingType, checkClashes);
1909 break
1910
1911 case "ArrayPattern":
1912 for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
1913 var elem = list$1[i$1];
1914
1915 if (elem) { this.checkLVal(elem, bindingType, checkClashes); }
1916 }
1917 break
1918
1919 case "AssignmentPattern":
1920 this.checkLVal(expr.left, bindingType, checkClashes);
1921 break
1922
1923 case "RestElement":
1924 this.checkLVal(expr.argument, bindingType, checkClashes);
1925 break
1926
1927 case "ParenthesizedExpression":
1928 this.checkLVal(expr.expression, bindingType, checkClashes);
1929 break
1930
1931 default:
1932 this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue");
1933 }
1934};
1935
1936// A recursive descent parser operates by defining functions for all
1937
1938var pp$3 = Parser.prototype;
1939
1940// Check if property name clashes with already added.
1941// Object/class getters and setters are not allowed to clash —
1942// either with each other or with an init property — and in
1943// strict mode, init properties are also not allowed to be repeated.
1944
1945pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) {
1946 if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
1947 { return }
1948 if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
1949 { return }
1950 var key = prop.key;
1951 var name;
1952 switch (key.type) {
1953 case "Identifier": name = key.name; break
1954 case "Literal": name = String(key.value); break
1955 default: return
1956 }
1957 var kind = prop.kind;
1958 if (this.options.ecmaVersion >= 6) {
1959 if (name === "__proto__" && kind === "init") {
1960 if (propHash.proto) {
1961 if (refDestructuringErrors) {
1962 if (refDestructuringErrors.doubleProto < 0)
1963 { refDestructuringErrors.doubleProto = key.start; }
1964 // Backwards-compat kludge. Can be removed in version 6.0
1965 } else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); }
1966 }
1967 propHash.proto = true;
1968 }
1969 return
1970 }
1971 name = "$" + name;
1972 var other = propHash[name];
1973 if (other) {
1974 var redefinition;
1975 if (kind === "init") {
1976 redefinition = this.strict && other.init || other.get || other.set;
1977 } else {
1978 redefinition = other.init || other[kind];
1979 }
1980 if (redefinition)
1981 { this.raiseRecoverable(key.start, "Redefinition of property"); }
1982 } else {
1983 other = propHash[name] = {
1984 init: false,
1985 get: false,
1986 set: false
1987 };
1988 }
1989 other[kind] = true;
1990};
1991
1992// ### Expression parsing
1993
1994// These nest, from the most general expression type at the top to
1995// 'atomic', nondivisible expression types at the bottom. Most of
1996// the functions will simply let the function(s) below them parse,
1997// and, *if* the syntactic construct they handle is present, wrap
1998// the AST node that the inner parser gave them in another node.
1999
2000// Parse a full expression. The optional arguments are used to
2001// forbid the `in` operator (in for loops initalization expressions)
2002// and provide reference for storing '=' operator inside shorthand
2003// property assignment in contexts where both object expression
2004// and object pattern might appear (so it's possible to raise
2005// delayed syntax error at correct position).
2006
2007pp$3.parseExpression = function(noIn, refDestructuringErrors) {
2008 var startPos = this.start, startLoc = this.startLoc;
2009 var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
2010 if (this.type === types.comma) {
2011 var node = this.startNodeAt(startPos, startLoc);
2012 node.expressions = [expr];
2013 while (this.eat(types.comma)) { node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); }
2014 return this.finishNode(node, "SequenceExpression")
2015 }
2016 return expr
2017};
2018
2019// Parse an assignment expression. This includes applications of
2020// operators like `+=`.
2021
2022pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
2023 if (this.isContextual("yield")) {
2024 if (this.inGenerator) { return this.parseYield(noIn) }
2025 // The tokenizer will assume an expression is allowed after
2026 // `yield`, but this isn't that kind of yield
2027 else { this.exprAllowed = false; }
2028 }
2029
2030 var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1;
2031 if (refDestructuringErrors) {
2032 oldParenAssign = refDestructuringErrors.parenthesizedAssign;
2033 oldTrailingComma = refDestructuringErrors.trailingComma;
2034 refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
2035 } else {
2036 refDestructuringErrors = new DestructuringErrors;
2037 ownDestructuringErrors = true;
2038 }
2039
2040 var startPos = this.start, startLoc = this.startLoc;
2041 if (this.type === types.parenL || this.type === types.name)
2042 { this.potentialArrowAt = this.start; }
2043 var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
2044 if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
2045 if (this.type.isAssign) {
2046 var node = this.startNodeAt(startPos, startLoc);
2047 node.operator = this.value;
2048 node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left;
2049 if (!ownDestructuringErrors) {
2050 refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
2051 }
2052 if (refDestructuringErrors.shorthandAssign >= node.left.start)
2053 { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly
2054 this.checkLVal(left);
2055 this.next();
2056 node.right = this.parseMaybeAssign(noIn);
2057 return this.finishNode(node, "AssignmentExpression")
2058 } else {
2059 if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
2060 }
2061 if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
2062 if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
2063 return left
2064};
2065
2066// Parse a ternary conditional (`?:`) operator.
2067
2068pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) {
2069 var startPos = this.start, startLoc = this.startLoc;
2070 var expr = this.parseExprOps(noIn, refDestructuringErrors);
2071 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2072 if (this.eat(types.question)) {
2073 var node = this.startNodeAt(startPos, startLoc);
2074 node.test = expr;
2075 node.consequent = this.parseMaybeAssign();
2076 this.expect(types.colon);
2077 node.alternate = this.parseMaybeAssign(noIn);
2078 return this.finishNode(node, "ConditionalExpression")
2079 }
2080 return expr
2081};
2082
2083// Start the precedence parser.
2084
2085pp$3.parseExprOps = function(noIn, refDestructuringErrors) {
2086 var startPos = this.start, startLoc = this.startLoc;
2087 var expr = this.parseMaybeUnary(refDestructuringErrors, false);
2088 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2089 return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn)
2090};
2091
2092// Parse binary operators with the operator precedence parsing
2093// algorithm. `left` is the left-hand side of the operator.
2094// `minPrec` provides context that allows the function to stop and
2095// defer further parser to one of its callers when it encounters an
2096// operator that has a lower precedence than the set it is parsing.
2097
2098pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
2099 var prec = this.type.binop;
2100 if (prec != null && (!noIn || this.type !== types._in)) {
2101 if (prec > minPrec) {
2102 var logical = this.type === types.logicalOR || this.type === types.logicalAND;
2103 var coalesce = this.type === types.coalesce;
2104 if (coalesce) {
2105 // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions.
2106 // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error.
2107 prec = types.logicalAND.binop;
2108 }
2109 var op = this.value;
2110 this.next();
2111 var startPos = this.start, startLoc = this.startLoc;
2112 var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
2113 var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce);
2114 if ((logical && this.type === types.coalesce) || (coalesce && (this.type === types.logicalOR || this.type === types.logicalAND))) {
2115 this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses");
2116 }
2117 return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
2118 }
2119 }
2120 return left
2121};
2122
2123pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) {
2124 var node = this.startNodeAt(startPos, startLoc);
2125 node.left = left;
2126 node.operator = op;
2127 node.right = right;
2128 return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
2129};
2130
2131// Parse unary operators, both prefix and postfix.
2132
2133pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
2134 var startPos = this.start, startLoc = this.startLoc, expr;
2135 if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) {
2136 expr = this.parseAwait();
2137 sawUnary = true;
2138 } else if (this.type.prefix) {
2139 var node = this.startNode(), update = this.type === types.incDec;
2140 node.operator = this.value;
2141 node.prefix = true;
2142 this.next();
2143 node.argument = this.parseMaybeUnary(null, true);
2144 this.checkExpressionErrors(refDestructuringErrors, true);
2145 if (update) { this.checkLVal(node.argument); }
2146 else if (this.strict && node.operator === "delete" &&
2147 node.argument.type === "Identifier")
2148 { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
2149 else { sawUnary = true; }
2150 expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
2151 } else {
2152 expr = this.parseExprSubscripts(refDestructuringErrors);
2153 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2154 while (this.type.postfix && !this.canInsertSemicolon()) {
2155 var node$1 = this.startNodeAt(startPos, startLoc);
2156 node$1.operator = this.value;
2157 node$1.prefix = false;
2158 node$1.argument = expr;
2159 this.checkLVal(expr);
2160 this.next();
2161 expr = this.finishNode(node$1, "UpdateExpression");
2162 }
2163 }
2164
2165 if (!sawUnary && this.eat(types.starstar))
2166 { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) }
2167 else
2168 { return expr }
2169};
2170
2171// Parse call, dot, and `[]`-subscript expressions.
2172
2173pp$3.parseExprSubscripts = function(refDestructuringErrors) {
2174 var startPos = this.start, startLoc = this.startLoc;
2175 var expr = this.parseExprAtom(refDestructuringErrors);
2176 if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")")
2177 { return expr }
2178 var result = this.parseSubscripts(expr, startPos, startLoc);
2179 if (refDestructuringErrors && result.type === "MemberExpression") {
2180 if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
2181 if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
2182 }
2183 return result
2184};
2185
2186pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) {
2187 var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
2188 this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 &&
2189 this.potentialArrowAt === base.start;
2190 var optionalChained = false;
2191
2192 while (true) {
2193 var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained);
2194
2195 if (element.optional) { optionalChained = true; }
2196 if (element === base || element.type === "ArrowFunctionExpression") {
2197 if (optionalChained) {
2198 var chainNode = this.startNodeAt(startPos, startLoc);
2199 chainNode.expression = element;
2200 element = this.finishNode(chainNode, "ChainExpression");
2201 }
2202 return element
2203 }
2204
2205 base = element;
2206 }
2207};
2208
2209pp$3.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained) {
2210 var optionalSupported = this.options.ecmaVersion >= 11;
2211 var optional = optionalSupported && this.eat(types.questionDot);
2212 if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); }
2213
2214 var computed = this.eat(types.bracketL);
2215 if (computed || (optional && this.type !== types.parenL && this.type !== types.backQuote) || this.eat(types.dot)) {
2216 var node = this.startNodeAt(startPos, startLoc);
2217 node.object = base;
2218 node.property = computed ? this.parseExpression() : this.parseIdent(this.options.allowReserved !== "never");
2219 node.computed = !!computed;
2220 if (computed) { this.expect(types.bracketR); }
2221 if (optionalSupported) {
2222 node.optional = optional;
2223 }
2224 base = this.finishNode(node, "MemberExpression");
2225 } else if (!noCalls && this.eat(types.parenL)) {
2226 var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2227 this.yieldPos = 0;
2228 this.awaitPos = 0;
2229 this.awaitIdentPos = 0;
2230 var exprList = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors);
2231 if (maybeAsyncArrow && !optional && !this.canInsertSemicolon() && this.eat(types.arrow)) {
2232 this.checkPatternErrors(refDestructuringErrors, false);
2233 this.checkYieldAwaitInDefaultParams();
2234 if (this.awaitIdentPos > 0)
2235 { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); }
2236 this.yieldPos = oldYieldPos;
2237 this.awaitPos = oldAwaitPos;
2238 this.awaitIdentPos = oldAwaitIdentPos;
2239 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true)
2240 }
2241 this.checkExpressionErrors(refDestructuringErrors, true);
2242 this.yieldPos = oldYieldPos || this.yieldPos;
2243 this.awaitPos = oldAwaitPos || this.awaitPos;
2244 this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos;
2245 var node$1 = this.startNodeAt(startPos, startLoc);
2246 node$1.callee = base;
2247 node$1.arguments = exprList;
2248 if (optionalSupported) {
2249 node$1.optional = optional;
2250 }
2251 base = this.finishNode(node$1, "CallExpression");
2252 } else if (this.type === types.backQuote) {
2253 if (optional || optionalChained) {
2254 this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions");
2255 }
2256 var node$2 = this.startNodeAt(startPos, startLoc);
2257 node$2.tag = base;
2258 node$2.quasi = this.parseTemplate({isTagged: true});
2259 base = this.finishNode(node$2, "TaggedTemplateExpression");
2260 }
2261 return base
2262};
2263
2264// Parse an atomic expression — either a single token that is an
2265// expression, an expression started by a keyword like `function` or
2266// `new`, or an expression wrapped in punctuation like `()`, `[]`,
2267// or `{}`.
2268
2269pp$3.parseExprAtom = function(refDestructuringErrors) {
2270 // If a division operator appears in an expression position, the
2271 // tokenizer got confused, and we force it to read a regexp instead.
2272 if (this.type === types.slash) { this.readRegexp(); }
2273
2274 var node, canBeArrow = this.potentialArrowAt === this.start;
2275 switch (this.type) {
2276 case types._super:
2277 if (!this.allowSuper)
2278 { this.raise(this.start, "'super' keyword outside a method"); }
2279 node = this.startNode();
2280 this.next();
2281 if (this.type === types.parenL && !this.allowDirectSuper)
2282 { this.raise(node.start, "super() call outside constructor of a subclass"); }
2283 // The `super` keyword can appear at below:
2284 // SuperProperty:
2285 // super [ Expression ]
2286 // super . IdentifierName
2287 // SuperCall:
2288 // super ( Arguments )
2289 if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
2290 { this.unexpected(); }
2291 return this.finishNode(node, "Super")
2292
2293 case types._this:
2294 node = this.startNode();
2295 this.next();
2296 return this.finishNode(node, "ThisExpression")
2297
2298 case types.name:
2299 var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
2300 var id = this.parseIdent(false);
2301 if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function))
2302 { return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) }
2303 if (canBeArrow && !this.canInsertSemicolon()) {
2304 if (this.eat(types.arrow))
2305 { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) }
2306 if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) {
2307 id = this.parseIdent(false);
2308 if (this.canInsertSemicolon() || !this.eat(types.arrow))
2309 { this.unexpected(); }
2310 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
2311 }
2312 }
2313 return id
2314
2315 case types.regexp:
2316 var value = this.value;
2317 node = this.parseLiteral(value.value);
2318 node.regex = {pattern: value.pattern, flags: value.flags};
2319 return node
2320
2321 case types.num: case types.string:
2322 return this.parseLiteral(this.value)
2323
2324 case types._null: case types._true: case types._false:
2325 node = this.startNode();
2326 node.value = this.type === types._null ? null : this.type === types._true;
2327 node.raw = this.type.keyword;
2328 this.next();
2329 return this.finishNode(node, "Literal")
2330
2331 case types.parenL:
2332 var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow);
2333 if (refDestructuringErrors) {
2334 if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
2335 { refDestructuringErrors.parenthesizedAssign = start; }
2336 if (refDestructuringErrors.parenthesizedBind < 0)
2337 { refDestructuringErrors.parenthesizedBind = start; }
2338 }
2339 return expr
2340
2341 case types.bracketL:
2342 node = this.startNode();
2343 this.next();
2344 node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors);
2345 return this.finishNode(node, "ArrayExpression")
2346
2347 case types.braceL:
2348 return this.parseObj(false, refDestructuringErrors)
2349
2350 case types._function:
2351 node = this.startNode();
2352 this.next();
2353 return this.parseFunction(node, 0)
2354
2355 case types._class:
2356 return this.parseClass(this.startNode(), false)
2357
2358 case types._new:
2359 return this.parseNew()
2360
2361 case types.backQuote:
2362 return this.parseTemplate()
2363
2364 case types._import:
2365 if (this.options.ecmaVersion >= 11) {
2366 return this.parseExprImport()
2367 } else {
2368 return this.unexpected()
2369 }
2370
2371 default:
2372 this.unexpected();
2373 }
2374};
2375
2376pp$3.parseExprImport = function() {
2377 var node = this.startNode();
2378
2379 // Consume `import` as an identifier for `import.meta`.
2380 // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`.
2381 if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); }
2382 var meta = this.parseIdent(true);
2383
2384 switch (this.type) {
2385 case types.parenL:
2386 return this.parseDynamicImport(node)
2387 case types.dot:
2388 node.meta = meta;
2389 return this.parseImportMeta(node)
2390 default:
2391 this.unexpected();
2392 }
2393};
2394
2395pp$3.parseDynamicImport = function(node) {
2396 this.next(); // skip `(`
2397
2398 // Parse node.source.
2399 node.source = this.parseMaybeAssign();
2400
2401 // Verify ending.
2402 if (!this.eat(types.parenR)) {
2403 var errorPos = this.start;
2404 if (this.eat(types.comma) && this.eat(types.parenR)) {
2405 this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()");
2406 } else {
2407 this.unexpected(errorPos);
2408 }
2409 }
2410
2411 return this.finishNode(node, "ImportExpression")
2412};
2413
2414pp$3.parseImportMeta = function(node) {
2415 this.next(); // skip `.`
2416
2417 var containsEsc = this.containsEsc;
2418 node.property = this.parseIdent(true);
2419
2420 if (node.property.name !== "meta")
2421 { this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); }
2422 if (containsEsc)
2423 { this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); }
2424 if (this.options.sourceType !== "module")
2425 { this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); }
2426
2427 return this.finishNode(node, "MetaProperty")
2428};
2429
2430pp$3.parseLiteral = function(value) {
2431 var node = this.startNode();
2432 node.value = value;
2433 node.raw = this.input.slice(this.start, this.end);
2434 if (node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1).replace(/_/g, ""); }
2435 this.next();
2436 return this.finishNode(node, "Literal")
2437};
2438
2439pp$3.parseParenExpression = function() {
2440 this.expect(types.parenL);
2441 var val = this.parseExpression();
2442 this.expect(types.parenR);
2443 return val
2444};
2445
2446pp$3.parseParenAndDistinguishExpression = function(canBeArrow) {
2447 var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
2448 if (this.options.ecmaVersion >= 6) {
2449 this.next();
2450
2451 var innerStartPos = this.start, innerStartLoc = this.startLoc;
2452 var exprList = [], first = true, lastIsComma = false;
2453 var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
2454 this.yieldPos = 0;
2455 this.awaitPos = 0;
2456 // Do not save awaitIdentPos to allow checking awaits nested in parameters
2457 while (this.type !== types.parenR) {
2458 first ? first = false : this.expect(types.comma);
2459 if (allowTrailingComma && this.afterTrailingComma(types.parenR, true)) {
2460 lastIsComma = true;
2461 break
2462 } else if (this.type === types.ellipsis) {
2463 spreadStart = this.start;
2464 exprList.push(this.parseParenItem(this.parseRestBinding()));
2465 if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); }
2466 break
2467 } else {
2468 exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem));
2469 }
2470 }
2471 var innerEndPos = this.start, innerEndLoc = this.startLoc;
2472 this.expect(types.parenR);
2473
2474 if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
2475 this.checkPatternErrors(refDestructuringErrors, false);
2476 this.checkYieldAwaitInDefaultParams();
2477 this.yieldPos = oldYieldPos;
2478 this.awaitPos = oldAwaitPos;
2479 return this.parseParenArrowList(startPos, startLoc, exprList)
2480 }
2481
2482 if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
2483 if (spreadStart) { this.unexpected(spreadStart); }
2484 this.checkExpressionErrors(refDestructuringErrors, true);
2485 this.yieldPos = oldYieldPos || this.yieldPos;
2486 this.awaitPos = oldAwaitPos || this.awaitPos;
2487
2488 if (exprList.length > 1) {
2489 val = this.startNodeAt(innerStartPos, innerStartLoc);
2490 val.expressions = exprList;
2491 this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
2492 } else {
2493 val = exprList[0];
2494 }
2495 } else {
2496 val = this.parseParenExpression();
2497 }
2498
2499 if (this.options.preserveParens) {
2500 var par = this.startNodeAt(startPos, startLoc);
2501 par.expression = val;
2502 return this.finishNode(par, "ParenthesizedExpression")
2503 } else {
2504 return val
2505 }
2506};
2507
2508pp$3.parseParenItem = function(item) {
2509 return item
2510};
2511
2512pp$3.parseParenArrowList = function(startPos, startLoc, exprList) {
2513 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)
2514};
2515
2516// New's precedence is slightly tricky. It must allow its argument to
2517// be a `[]` or dot subscript expression, but not a call — at least,
2518// not without wrapping it in parentheses. Thus, it uses the noCalls
2519// argument to parseSubscripts to prevent it from consuming the
2520// argument list.
2521
2522var empty$1 = [];
2523
2524pp$3.parseNew = function() {
2525 if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); }
2526 var node = this.startNode();
2527 var meta = this.parseIdent(true);
2528 if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) {
2529 node.meta = meta;
2530 var containsEsc = this.containsEsc;
2531 node.property = this.parseIdent(true);
2532 if (node.property.name !== "target")
2533 { this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); }
2534 if (containsEsc)
2535 { this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); }
2536 if (!this.inNonArrowFunction())
2537 { this.raiseRecoverable(node.start, "'new.target' can only be used in functions"); }
2538 return this.finishNode(node, "MetaProperty")
2539 }
2540 var startPos = this.start, startLoc = this.startLoc, isImport = this.type === types._import;
2541 node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
2542 if (isImport && node.callee.type === "ImportExpression") {
2543 this.raise(startPos, "Cannot use new with import()");
2544 }
2545 if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); }
2546 else { node.arguments = empty$1; }
2547 return this.finishNode(node, "NewExpression")
2548};
2549
2550// Parse template expression.
2551
2552pp$3.parseTemplateElement = function(ref) {
2553 var isTagged = ref.isTagged;
2554
2555 var elem = this.startNode();
2556 if (this.type === types.invalidTemplate) {
2557 if (!isTagged) {
2558 this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
2559 }
2560 elem.value = {
2561 raw: this.value,
2562 cooked: null
2563 };
2564 } else {
2565 elem.value = {
2566 raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
2567 cooked: this.value
2568 };
2569 }
2570 this.next();
2571 elem.tail = this.type === types.backQuote;
2572 return this.finishNode(elem, "TemplateElement")
2573};
2574
2575pp$3.parseTemplate = function(ref) {
2576 if ( ref === void 0 ) ref = {};
2577 var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;
2578
2579 var node = this.startNode();
2580 this.next();
2581 node.expressions = [];
2582 var curElt = this.parseTemplateElement({isTagged: isTagged});
2583 node.quasis = [curElt];
2584 while (!curElt.tail) {
2585 if (this.type === types.eof) { this.raise(this.pos, "Unterminated template literal"); }
2586 this.expect(types.dollarBraceL);
2587 node.expressions.push(this.parseExpression());
2588 this.expect(types.braceR);
2589 node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged}));
2590 }
2591 this.next();
2592 return this.finishNode(node, "TemplateLiteral")
2593};
2594
2595pp$3.isAsyncProp = function(prop) {
2596 return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
2597 (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) &&
2598 !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
2599};
2600
2601// Parse an object literal or binding pattern.
2602
2603pp$3.parseObj = function(isPattern, refDestructuringErrors) {
2604 var node = this.startNode(), first = true, propHash = {};
2605 node.properties = [];
2606 this.next();
2607 while (!this.eat(types.braceR)) {
2608 if (!first) {
2609 this.expect(types.comma);
2610 if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types.braceR)) { break }
2611 } else { first = false; }
2612
2613 var prop = this.parseProperty(isPattern, refDestructuringErrors);
2614 if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); }
2615 node.properties.push(prop);
2616 }
2617 return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
2618};
2619
2620pp$3.parseProperty = function(isPattern, refDestructuringErrors) {
2621 var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
2622 if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) {
2623 if (isPattern) {
2624 prop.argument = this.parseIdent(false);
2625 if (this.type === types.comma) {
2626 this.raise(this.start, "Comma is not permitted after the rest element");
2627 }
2628 return this.finishNode(prop, "RestElement")
2629 }
2630 // To disallow parenthesized identifier via `this.toAssignable()`.
2631 if (this.type === types.parenL && refDestructuringErrors) {
2632 if (refDestructuringErrors.parenthesizedAssign < 0) {
2633 refDestructuringErrors.parenthesizedAssign = this.start;
2634 }
2635 if (refDestructuringErrors.parenthesizedBind < 0) {
2636 refDestructuringErrors.parenthesizedBind = this.start;
2637 }
2638 }
2639 // Parse argument.
2640 prop.argument = this.parseMaybeAssign(false, refDestructuringErrors);
2641 // To disallow trailing comma via `this.toAssignable()`.
2642 if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
2643 refDestructuringErrors.trailingComma = this.start;
2644 }
2645 // Finish
2646 return this.finishNode(prop, "SpreadElement")
2647 }
2648 if (this.options.ecmaVersion >= 6) {
2649 prop.method = false;
2650 prop.shorthand = false;
2651 if (isPattern || refDestructuringErrors) {
2652 startPos = this.start;
2653 startLoc = this.startLoc;
2654 }
2655 if (!isPattern)
2656 { isGenerator = this.eat(types.star); }
2657 }
2658 var containsEsc = this.containsEsc;
2659 this.parsePropertyName(prop);
2660 if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
2661 isAsync = true;
2662 isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
2663 this.parsePropertyName(prop, refDestructuringErrors);
2664 } else {
2665 isAsync = false;
2666 }
2667 this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
2668 return this.finishNode(prop, "Property")
2669};
2670
2671pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
2672 if ((isGenerator || isAsync) && this.type === types.colon)
2673 { this.unexpected(); }
2674
2675 if (this.eat(types.colon)) {
2676 prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
2677 prop.kind = "init";
2678 } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) {
2679 if (isPattern) { this.unexpected(); }
2680 prop.kind = "init";
2681 prop.method = true;
2682 prop.value = this.parseMethod(isGenerator, isAsync);
2683 } else if (!isPattern && !containsEsc &&
2684 this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
2685 (prop.key.name === "get" || prop.key.name === "set") &&
2686 (this.type !== types.comma && this.type !== types.braceR && this.type !== types.eq)) {
2687 if (isGenerator || isAsync) { this.unexpected(); }
2688 prop.kind = prop.key.name;
2689 this.parsePropertyName(prop);
2690 prop.value = this.parseMethod(false);
2691 var paramCount = prop.kind === "get" ? 0 : 1;
2692 if (prop.value.params.length !== paramCount) {
2693 var start = prop.value.start;
2694 if (prop.kind === "get")
2695 { this.raiseRecoverable(start, "getter should have no params"); }
2696 else
2697 { this.raiseRecoverable(start, "setter should have exactly one param"); }
2698 } else {
2699 if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
2700 { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
2701 }
2702 } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
2703 if (isGenerator || isAsync) { this.unexpected(); }
2704 this.checkUnreserved(prop.key);
2705 if (prop.key.name === "await" && !this.awaitIdentPos)
2706 { this.awaitIdentPos = startPos; }
2707 prop.kind = "init";
2708 if (isPattern) {
2709 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
2710 } else if (this.type === types.eq && refDestructuringErrors) {
2711 if (refDestructuringErrors.shorthandAssign < 0)
2712 { refDestructuringErrors.shorthandAssign = this.start; }
2713 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
2714 } else {
2715 prop.value = prop.key;
2716 }
2717 prop.shorthand = true;
2718 } else { this.unexpected(); }
2719};
2720
2721pp$3.parsePropertyName = function(prop) {
2722 if (this.options.ecmaVersion >= 6) {
2723 if (this.eat(types.bracketL)) {
2724 prop.computed = true;
2725 prop.key = this.parseMaybeAssign();
2726 this.expect(types.bracketR);
2727 return prop.key
2728 } else {
2729 prop.computed = false;
2730 }
2731 }
2732 return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never")
2733};
2734
2735// Initialize empty function node.
2736
2737pp$3.initFunction = function(node) {
2738 node.id = null;
2739 if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; }
2740 if (this.options.ecmaVersion >= 8) { node.async = false; }
2741};
2742
2743// Parse object or class method.
2744
2745pp$3.parseMethod = function(isGenerator, isAsync, allowDirectSuper) {
2746 var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2747
2748 this.initFunction(node);
2749 if (this.options.ecmaVersion >= 6)
2750 { node.generator = isGenerator; }
2751 if (this.options.ecmaVersion >= 8)
2752 { node.async = !!isAsync; }
2753
2754 this.yieldPos = 0;
2755 this.awaitPos = 0;
2756 this.awaitIdentPos = 0;
2757 this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0));
2758
2759 this.expect(types.parenL);
2760 node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
2761 this.checkYieldAwaitInDefaultParams();
2762 this.parseFunctionBody(node, false, true);
2763
2764 this.yieldPos = oldYieldPos;
2765 this.awaitPos = oldAwaitPos;
2766 this.awaitIdentPos = oldAwaitIdentPos;
2767 return this.finishNode(node, "FunctionExpression")
2768};
2769
2770// Parse arrow function expression with given parameters.
2771
2772pp$3.parseArrowExpression = function(node, params, isAsync) {
2773 var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2774
2775 this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW);
2776 this.initFunction(node);
2777 if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; }
2778
2779 this.yieldPos = 0;
2780 this.awaitPos = 0;
2781 this.awaitIdentPos = 0;
2782
2783 node.params = this.toAssignableList(params, true);
2784 this.parseFunctionBody(node, true, false);
2785
2786 this.yieldPos = oldYieldPos;
2787 this.awaitPos = oldAwaitPos;
2788 this.awaitIdentPos = oldAwaitIdentPos;
2789 return this.finishNode(node, "ArrowFunctionExpression")
2790};
2791
2792// Parse function body and check parameters.
2793
2794pp$3.parseFunctionBody = function(node, isArrowFunction, isMethod) {
2795 var isExpression = isArrowFunction && this.type !== types.braceL;
2796 var oldStrict = this.strict, useStrict = false;
2797
2798 if (isExpression) {
2799 node.body = this.parseMaybeAssign();
2800 node.expression = true;
2801 this.checkParams(node, false);
2802 } else {
2803 var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
2804 if (!oldStrict || nonSimple) {
2805 useStrict = this.strictDirective(this.end);
2806 // If this is a strict mode function, verify that argument names
2807 // are not repeated, and it does not try to bind the words `eval`
2808 // or `arguments`.
2809 if (useStrict && nonSimple)
2810 { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
2811 }
2812 // Start a new scope with regard to labels and the `inFunction`
2813 // flag (restore them to their old value afterwards).
2814 var oldLabels = this.labels;
2815 this.labels = [];
2816 if (useStrict) { this.strict = true; }
2817
2818 // Add the params to varDeclaredNames to ensure that an error is thrown
2819 // if a let/const declaration in the function clashes with one of the params.
2820 this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params));
2821 // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
2822 if (this.strict && node.id) { this.checkLVal(node.id, BIND_OUTSIDE); }
2823 node.body = this.parseBlock(false, undefined, useStrict && !oldStrict);
2824 node.expression = false;
2825 this.adaptDirectivePrologue(node.body.body);
2826 this.labels = oldLabels;
2827 }
2828 this.exitScope();
2829};
2830
2831pp$3.isSimpleParamList = function(params) {
2832 for (var i = 0, list = params; i < list.length; i += 1)
2833 {
2834 var param = list[i];
2835
2836 if (param.type !== "Identifier") { return false
2837 } }
2838 return true
2839};
2840
2841// Checks function params for various disallowed patterns such as using "eval"
2842// or "arguments" and duplicate parameters.
2843
2844pp$3.checkParams = function(node, allowDuplicates) {
2845 var nameHash = {};
2846 for (var i = 0, list = node.params; i < list.length; i += 1)
2847 {
2848 var param = list[i];
2849
2850 this.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash);
2851 }
2852};
2853
2854// Parses a comma-separated list of expressions, and returns them as
2855// an array. `close` is the token type that ends the list, and
2856// `allowEmpty` can be turned on to allow subsequent commas with
2857// nothing in between them to be parsed as `null` (which is needed
2858// for array literals).
2859
2860pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
2861 var elts = [], first = true;
2862 while (!this.eat(close)) {
2863 if (!first) {
2864 this.expect(types.comma);
2865 if (allowTrailingComma && this.afterTrailingComma(close)) { break }
2866 } else { first = false; }
2867
2868 var elt = (void 0);
2869 if (allowEmpty && this.type === types.comma)
2870 { elt = null; }
2871 else if (this.type === types.ellipsis) {
2872 elt = this.parseSpread(refDestructuringErrors);
2873 if (refDestructuringErrors && this.type === types.comma && refDestructuringErrors.trailingComma < 0)
2874 { refDestructuringErrors.trailingComma = this.start; }
2875 } else {
2876 elt = this.parseMaybeAssign(false, refDestructuringErrors);
2877 }
2878 elts.push(elt);
2879 }
2880 return elts
2881};
2882
2883pp$3.checkUnreserved = function(ref) {
2884 var start = ref.start;
2885 var end = ref.end;
2886 var name = ref.name;
2887
2888 if (this.inGenerator && name === "yield")
2889 { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); }
2890 if (this.inAsync && name === "await")
2891 { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); }
2892 if (this.keywords.test(name))
2893 { this.raise(start, ("Unexpected keyword '" + name + "'")); }
2894 if (this.options.ecmaVersion < 6 &&
2895 this.input.slice(start, end).indexOf("\\") !== -1) { return }
2896 var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
2897 if (re.test(name)) {
2898 if (!this.inAsync && name === "await")
2899 { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); }
2900 this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved"));
2901 }
2902};
2903
2904// Parse the next token as an identifier. If `liberal` is true (used
2905// when parsing properties), it will also convert keywords into
2906// identifiers.
2907
2908pp$3.parseIdent = function(liberal, isBinding) {
2909 var node = this.startNode();
2910 if (this.type === types.name) {
2911 node.name = this.value;
2912 } else if (this.type.keyword) {
2913 node.name = this.type.keyword;
2914
2915 // To fix https://github.com/acornjs/acorn/issues/575
2916 // `class` and `function` keywords push new context into this.context.
2917 // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
2918 // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
2919 if ((node.name === "class" || node.name === "function") &&
2920 (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
2921 this.context.pop();
2922 }
2923 } else {
2924 this.unexpected();
2925 }
2926 this.next(!!liberal);
2927 this.finishNode(node, "Identifier");
2928 if (!liberal) {
2929 this.checkUnreserved(node);
2930 if (node.name === "await" && !this.awaitIdentPos)
2931 { this.awaitIdentPos = node.start; }
2932 }
2933 return node
2934};
2935
2936// Parses yield expression inside generator.
2937
2938pp$3.parseYield = function(noIn) {
2939 if (!this.yieldPos) { this.yieldPos = this.start; }
2940
2941 var node = this.startNode();
2942 this.next();
2943 if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) {
2944 node.delegate = false;
2945 node.argument = null;
2946 } else {
2947 node.delegate = this.eat(types.star);
2948 node.argument = this.parseMaybeAssign(noIn);
2949 }
2950 return this.finishNode(node, "YieldExpression")
2951};
2952
2953pp$3.parseAwait = function() {
2954 if (!this.awaitPos) { this.awaitPos = this.start; }
2955
2956 var node = this.startNode();
2957 this.next();
2958 node.argument = this.parseMaybeUnary(null, false);
2959 return this.finishNode(node, "AwaitExpression")
2960};
2961
2962var pp$4 = Parser.prototype;
2963
2964// This function is used to raise exceptions on parse errors. It
2965// takes an offset integer (into the current `input`) to indicate
2966// the location of the error, attaches the position to the end
2967// of the error message, and then raises a `SyntaxError` with that
2968// message.
2969
2970pp$4.raise = function(pos, message) {
2971 var loc = getLineInfo(this.input, pos);
2972 message += " (" + loc.line + ":" + loc.column + ")";
2973 var err = new SyntaxError(message);
2974 err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
2975 throw err
2976};
2977
2978pp$4.raiseRecoverable = pp$4.raise;
2979
2980pp$4.curPosition = function() {
2981 if (this.options.locations) {
2982 return new Position(this.curLine, this.pos - this.lineStart)
2983 }
2984};
2985
2986var pp$5 = Parser.prototype;
2987
2988var Scope = function Scope(flags) {
2989 this.flags = flags;
2990 // A list of var-declared names in the current lexical scope
2991 this.var = [];
2992 // A list of lexically-declared names in the current lexical scope
2993 this.lexical = [];
2994 // A list of lexically-declared FunctionDeclaration names in the current lexical scope
2995 this.functions = [];
2996};
2997
2998// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.
2999
3000pp$5.enterScope = function(flags) {
3001 this.scopeStack.push(new Scope(flags));
3002};
3003
3004pp$5.exitScope = function() {
3005 this.scopeStack.pop();
3006};
3007
3008// The spec says:
3009// > At the top level of a function, or script, function declarations are
3010// > treated like var declarations rather than like lexical declarations.
3011pp$5.treatFunctionsAsVarInScope = function(scope) {
3012 return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP)
3013};
3014
3015pp$5.declareName = function(name, bindingType, pos) {
3016 var redeclared = false;
3017 if (bindingType === BIND_LEXICAL) {
3018 var scope = this.currentScope();
3019 redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
3020 scope.lexical.push(name);
3021 if (this.inModule && (scope.flags & SCOPE_TOP))
3022 { delete this.undefinedExports[name]; }
3023 } else if (bindingType === BIND_SIMPLE_CATCH) {
3024 var scope$1 = this.currentScope();
3025 scope$1.lexical.push(name);
3026 } else if (bindingType === BIND_FUNCTION) {
3027 var scope$2 = this.currentScope();
3028 if (this.treatFunctionsAsVar)
3029 { redeclared = scope$2.lexical.indexOf(name) > -1; }
3030 else
3031 { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; }
3032 scope$2.functions.push(name);
3033 } else {
3034 for (var i = this.scopeStack.length - 1; i >= 0; --i) {
3035 var scope$3 = this.scopeStack[i];
3036 if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) ||
3037 !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) {
3038 redeclared = true;
3039 break
3040 }
3041 scope$3.var.push(name);
3042 if (this.inModule && (scope$3.flags & SCOPE_TOP))
3043 { delete this.undefinedExports[name]; }
3044 if (scope$3.flags & SCOPE_VAR) { break }
3045 }
3046 }
3047 if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); }
3048};
3049
3050pp$5.checkLocalExport = function(id) {
3051 // scope.functions must be empty as Module code is always strict.
3052 if (this.scopeStack[0].lexical.indexOf(id.name) === -1 &&
3053 this.scopeStack[0].var.indexOf(id.name) === -1) {
3054 this.undefinedExports[id.name] = id;
3055 }
3056};
3057
3058pp$5.currentScope = function() {
3059 return this.scopeStack[this.scopeStack.length - 1]
3060};
3061
3062pp$5.currentVarScope = function() {
3063 for (var i = this.scopeStack.length - 1;; i--) {
3064 var scope = this.scopeStack[i];
3065 if (scope.flags & SCOPE_VAR) { return scope }
3066 }
3067};
3068
3069// Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
3070pp$5.currentThisScope = function() {
3071 for (var i = this.scopeStack.length - 1;; i--) {
3072 var scope = this.scopeStack[i];
3073 if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) { return scope }
3074 }
3075};
3076
3077var Node = function Node(parser, pos, loc) {
3078 this.type = "";
3079 this.start = pos;
3080 this.end = 0;
3081 if (parser.options.locations)
3082 { this.loc = new SourceLocation(parser, loc); }
3083 if (parser.options.directSourceFile)
3084 { this.sourceFile = parser.options.directSourceFile; }
3085 if (parser.options.ranges)
3086 { this.range = [pos, 0]; }
3087};
3088
3089// Start an AST node, attaching a start offset.
3090
3091var pp$6 = Parser.prototype;
3092
3093pp$6.startNode = function() {
3094 return new Node(this, this.start, this.startLoc)
3095};
3096
3097pp$6.startNodeAt = function(pos, loc) {
3098 return new Node(this, pos, loc)
3099};
3100
3101// Finish an AST node, adding `type` and `end` properties.
3102
3103function finishNodeAt(node, type, pos, loc) {
3104 node.type = type;
3105 node.end = pos;
3106 if (this.options.locations)
3107 { node.loc.end = loc; }
3108 if (this.options.ranges)
3109 { node.range[1] = pos; }
3110 return node
3111}
3112
3113pp$6.finishNode = function(node, type) {
3114 return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
3115};
3116
3117// Finish node at given position
3118
3119pp$6.finishNodeAt = function(node, type, pos, loc) {
3120 return finishNodeAt.call(this, node, type, pos, loc)
3121};
3122
3123// The algorithm used to determine whether a regexp can appear at a
3124
3125var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
3126 this.token = token;
3127 this.isExpr = !!isExpr;
3128 this.preserveSpace = !!preserveSpace;
3129 this.override = override;
3130 this.generator = !!generator;
3131};
3132
3133var types$1 = {
3134 b_stat: new TokContext("{", false),
3135 b_expr: new TokContext("{", true),
3136 b_tmpl: new TokContext("${", false),
3137 p_stat: new TokContext("(", false),
3138 p_expr: new TokContext("(", true),
3139 q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
3140 f_stat: new TokContext("function", false),
3141 f_expr: new TokContext("function", true),
3142 f_expr_gen: new TokContext("function", true, false, null, true),
3143 f_gen: new TokContext("function", false, false, null, true)
3144};
3145
3146var pp$7 = Parser.prototype;
3147
3148pp$7.initialContext = function() {
3149 return [types$1.b_stat]
3150};
3151
3152pp$7.braceIsBlock = function(prevType) {
3153 var parent = this.curContext();
3154 if (parent === types$1.f_expr || parent === types$1.f_stat)
3155 { return true }
3156 if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr))
3157 { return !parent.isExpr }
3158
3159 // The check for `tt.name && exprAllowed` detects whether we are
3160 // after a `yield` or `of` construct. See the `updateContext` for
3161 // `tt.name`.
3162 if (prevType === types._return || prevType === types.name && this.exprAllowed)
3163 { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
3164 if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow)
3165 { return true }
3166 if (prevType === types.braceL)
3167 { return parent === types$1.b_stat }
3168 if (prevType === types._var || prevType === types._const || prevType === types.name)
3169 { return false }
3170 return !this.exprAllowed
3171};
3172
3173pp$7.inGeneratorContext = function() {
3174 for (var i = this.context.length - 1; i >= 1; i--) {
3175 var context = this.context[i];
3176 if (context.token === "function")
3177 { return context.generator }
3178 }
3179 return false
3180};
3181
3182pp$7.updateContext = function(prevType) {
3183 var update, type = this.type;
3184 if (type.keyword && prevType === types.dot)
3185 { this.exprAllowed = false; }
3186 else if (update = type.updateContext)
3187 { update.call(this, prevType); }
3188 else
3189 { this.exprAllowed = type.beforeExpr; }
3190};
3191
3192// Token-specific context update code
3193
3194types.parenR.updateContext = types.braceR.updateContext = function() {
3195 if (this.context.length === 1) {
3196 this.exprAllowed = true;
3197 return
3198 }
3199 var out = this.context.pop();
3200 if (out === types$1.b_stat && this.curContext().token === "function") {
3201 out = this.context.pop();
3202 }
3203 this.exprAllowed = !out.isExpr;
3204};
3205
3206types.braceL.updateContext = function(prevType) {
3207 this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr);
3208 this.exprAllowed = true;
3209};
3210
3211types.dollarBraceL.updateContext = function() {
3212 this.context.push(types$1.b_tmpl);
3213 this.exprAllowed = true;
3214};
3215
3216types.parenL.updateContext = function(prevType) {
3217 var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while;
3218 this.context.push(statementParens ? types$1.p_stat : types$1.p_expr);
3219 this.exprAllowed = true;
3220};
3221
3222types.incDec.updateContext = function() {
3223 // tokExprAllowed stays unchanged
3224};
3225
3226types._function.updateContext = types._class.updateContext = function(prevType) {
3227 if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else &&
3228 !(prevType === types._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) &&
3229 !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat))
3230 { this.context.push(types$1.f_expr); }
3231 else
3232 { this.context.push(types$1.f_stat); }
3233 this.exprAllowed = false;
3234};
3235
3236types.backQuote.updateContext = function() {
3237 if (this.curContext() === types$1.q_tmpl)
3238 { this.context.pop(); }
3239 else
3240 { this.context.push(types$1.q_tmpl); }
3241 this.exprAllowed = false;
3242};
3243
3244types.star.updateContext = function(prevType) {
3245 if (prevType === types._function) {
3246 var index = this.context.length - 1;
3247 if (this.context[index] === types$1.f_expr)
3248 { this.context[index] = types$1.f_expr_gen; }
3249 else
3250 { this.context[index] = types$1.f_gen; }
3251 }
3252 this.exprAllowed = true;
3253};
3254
3255types.name.updateContext = function(prevType) {
3256 var allowed = false;
3257 if (this.options.ecmaVersion >= 6 && prevType !== types.dot) {
3258 if (this.value === "of" && !this.exprAllowed ||
3259 this.value === "yield" && this.inGeneratorContext())
3260 { allowed = true; }
3261 }
3262 this.exprAllowed = allowed;
3263};
3264
3265// This file contains Unicode properties extracted from the ECMAScript
3266// specification. The lists are extracted like so:
3267// $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText)
3268
3269// #table-binary-unicode-properties
3270var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS";
3271var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic";
3272var ecma11BinaryProperties = ecma10BinaryProperties;
3273var unicodeBinaryProperties = {
3274 9: ecma9BinaryProperties,
3275 10: ecma10BinaryProperties,
3276 11: ecma11BinaryProperties
3277};
3278
3279// #table-unicode-general-category-values
3280var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu";
3281
3282// #table-unicode-script-values
3283var ecma9ScriptValues = "Adlam Adlm Ahom Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb";
3284var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd";
3285var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho";
3286var unicodeScriptValues = {
3287 9: ecma9ScriptValues,
3288 10: ecma10ScriptValues,
3289 11: ecma11ScriptValues
3290};
3291
3292var data = {};
3293function buildUnicodeData(ecmaVersion) {
3294 var d = data[ecmaVersion] = {
3295 binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues),
3296 nonBinary: {
3297 General_Category: wordsRegexp(unicodeGeneralCategoryValues),
3298 Script: wordsRegexp(unicodeScriptValues[ecmaVersion])
3299 }
3300 };
3301 d.nonBinary.Script_Extensions = d.nonBinary.Script;
3302
3303 d.nonBinary.gc = d.nonBinary.General_Category;
3304 d.nonBinary.sc = d.nonBinary.Script;
3305 d.nonBinary.scx = d.nonBinary.Script_Extensions;
3306}
3307buildUnicodeData(9);
3308buildUnicodeData(10);
3309buildUnicodeData(11);
3310
3311var pp$8 = Parser.prototype;
3312
3313var RegExpValidationState = function RegExpValidationState(parser) {
3314 this.parser = parser;
3315 this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "");
3316 this.unicodeProperties = data[parser.options.ecmaVersion >= 11 ? 11 : parser.options.ecmaVersion];
3317 this.source = "";
3318 this.flags = "";
3319 this.start = 0;
3320 this.switchU = false;
3321 this.switchN = false;
3322 this.pos = 0;
3323 this.lastIntValue = 0;
3324 this.lastStringValue = "";
3325 this.lastAssertionIsQuantifiable = false;
3326 this.numCapturingParens = 0;
3327 this.maxBackReference = 0;
3328 this.groupNames = [];
3329 this.backReferenceNames = [];
3330};
3331
3332RegExpValidationState.prototype.reset = function reset (start, pattern, flags) {
3333 var unicode = flags.indexOf("u") !== -1;
3334 this.start = start | 0;
3335 this.source = pattern + "";
3336 this.flags = flags;
3337 this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
3338 this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
3339};
3340
3341RegExpValidationState.prototype.raise = function raise (message) {
3342 this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message));
3343};
3344
3345// If u flag is given, this returns the code point at the index (it combines a surrogate pair).
3346// Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
3347RegExpValidationState.prototype.at = function at (i, forceU) {
3348 if ( forceU === void 0 ) forceU = false;
3349
3350 var s = this.source;
3351 var l = s.length;
3352 if (i >= l) {
3353 return -1
3354 }
3355 var c = s.charCodeAt(i);
3356 if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
3357 return c
3358 }
3359 var next = s.charCodeAt(i + 1);
3360 return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c
3361};
3362
3363RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) {
3364 if ( forceU === void 0 ) forceU = false;
3365
3366 var s = this.source;
3367 var l = s.length;
3368 if (i >= l) {
3369 return l
3370 }
3371 var c = s.charCodeAt(i), next;
3372 if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l ||
3373 (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) {
3374 return i + 1
3375 }
3376 return i + 2
3377};
3378
3379RegExpValidationState.prototype.current = function current (forceU) {
3380 if ( forceU === void 0 ) forceU = false;
3381
3382 return this.at(this.pos, forceU)
3383};
3384
3385RegExpValidationState.prototype.lookahead = function lookahead (forceU) {
3386 if ( forceU === void 0 ) forceU = false;
3387
3388 return this.at(this.nextIndex(this.pos, forceU), forceU)
3389};
3390
3391RegExpValidationState.prototype.advance = function advance (forceU) {
3392 if ( forceU === void 0 ) forceU = false;
3393
3394 this.pos = this.nextIndex(this.pos, forceU);
3395};
3396
3397RegExpValidationState.prototype.eat = function eat (ch, forceU) {
3398 if ( forceU === void 0 ) forceU = false;
3399
3400 if (this.current(forceU) === ch) {
3401 this.advance(forceU);
3402 return true
3403 }
3404 return false
3405};
3406
3407function codePointToString(ch) {
3408 if (ch <= 0xFFFF) { return String.fromCharCode(ch) }
3409 ch -= 0x10000;
3410 return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00)
3411}
3412
3413/**
3414 * Validate the flags part of a given RegExpLiteral.
3415 *
3416 * @param {RegExpValidationState} state The state to validate RegExp.
3417 * @returns {void}
3418 */
3419pp$8.validateRegExpFlags = function(state) {
3420 var validFlags = state.validFlags;
3421 var flags = state.flags;
3422
3423 for (var i = 0; i < flags.length; i++) {
3424 var flag = flags.charAt(i);
3425 if (validFlags.indexOf(flag) === -1) {
3426 this.raise(state.start, "Invalid regular expression flag");
3427 }
3428 if (flags.indexOf(flag, i + 1) > -1) {
3429 this.raise(state.start, "Duplicate regular expression flag");
3430 }
3431 }
3432};
3433
3434/**
3435 * Validate the pattern part of a given RegExpLiteral.
3436 *
3437 * @param {RegExpValidationState} state The state to validate RegExp.
3438 * @returns {void}
3439 */
3440pp$8.validateRegExpPattern = function(state) {
3441 this.regexp_pattern(state);
3442
3443 // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
3444 // parsing contains a |GroupName|, reparse with the goal symbol
3445 // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
3446 // exception if _P_ did not conform to the grammar, if any elements of _P_
3447 // were not matched by the parse, or if any Early Error conditions exist.
3448 if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) {
3449 state.switchN = true;
3450 this.regexp_pattern(state);
3451 }
3452};
3453
3454// https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
3455pp$8.regexp_pattern = function(state) {
3456 state.pos = 0;
3457 state.lastIntValue = 0;
3458 state.lastStringValue = "";
3459 state.lastAssertionIsQuantifiable = false;
3460 state.numCapturingParens = 0;
3461 state.maxBackReference = 0;
3462 state.groupNames.length = 0;
3463 state.backReferenceNames.length = 0;
3464
3465 this.regexp_disjunction(state);
3466
3467 if (state.pos !== state.source.length) {
3468 // Make the same messages as V8.
3469 if (state.eat(0x29 /* ) */)) {
3470 state.raise("Unmatched ')'");
3471 }
3472 if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) {
3473 state.raise("Lone quantifier brackets");
3474 }
3475 }
3476 if (state.maxBackReference > state.numCapturingParens) {
3477 state.raise("Invalid escape");
3478 }
3479 for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) {
3480 var name = list[i];
3481
3482 if (state.groupNames.indexOf(name) === -1) {
3483 state.raise("Invalid named capture referenced");
3484 }
3485 }
3486};
3487
3488// https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
3489pp$8.regexp_disjunction = function(state) {
3490 this.regexp_alternative(state);
3491 while (state.eat(0x7C /* | */)) {
3492 this.regexp_alternative(state);
3493 }
3494
3495 // Make the same message as V8.
3496 if (this.regexp_eatQuantifier(state, true)) {
3497 state.raise("Nothing to repeat");
3498 }
3499 if (state.eat(0x7B /* { */)) {
3500 state.raise("Lone quantifier brackets");
3501 }
3502};
3503
3504// https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
3505pp$8.regexp_alternative = function(state) {
3506 while (state.pos < state.source.length && this.regexp_eatTerm(state))
3507 { }
3508};
3509
3510// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
3511pp$8.regexp_eatTerm = function(state) {
3512 if (this.regexp_eatAssertion(state)) {
3513 // Handle `QuantifiableAssertion Quantifier` alternative.
3514 // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
3515 // is a QuantifiableAssertion.
3516 if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
3517 // Make the same message as V8.
3518 if (state.switchU) {
3519 state.raise("Invalid quantifier");
3520 }
3521 }
3522 return true
3523 }
3524
3525 if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
3526 this.regexp_eatQuantifier(state);
3527 return true
3528 }
3529
3530 return false
3531};
3532
3533// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
3534pp$8.regexp_eatAssertion = function(state) {
3535 var start = state.pos;
3536 state.lastAssertionIsQuantifiable = false;
3537
3538 // ^, $
3539 if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) {
3540 return true
3541 }
3542
3543 // \b \B
3544 if (state.eat(0x5C /* \ */)) {
3545 if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) {
3546 return true
3547 }
3548 state.pos = start;
3549 }
3550
3551 // Lookahead / Lookbehind
3552 if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) {
3553 var lookbehind = false;
3554 if (this.options.ecmaVersion >= 9) {
3555 lookbehind = state.eat(0x3C /* < */);
3556 }
3557 if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) {
3558 this.regexp_disjunction(state);
3559 if (!state.eat(0x29 /* ) */)) {
3560 state.raise("Unterminated group");
3561 }
3562 state.lastAssertionIsQuantifiable = !lookbehind;
3563 return true
3564 }
3565 }
3566
3567 state.pos = start;
3568 return false
3569};
3570
3571// https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
3572pp$8.regexp_eatQuantifier = function(state, noError) {
3573 if ( noError === void 0 ) noError = false;
3574
3575 if (this.regexp_eatQuantifierPrefix(state, noError)) {
3576 state.eat(0x3F /* ? */);
3577 return true
3578 }
3579 return false
3580};
3581
3582// https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
3583pp$8.regexp_eatQuantifierPrefix = function(state, noError) {
3584 return (
3585 state.eat(0x2A /* * */) ||
3586 state.eat(0x2B /* + */) ||
3587 state.eat(0x3F /* ? */) ||
3588 this.regexp_eatBracedQuantifier(state, noError)
3589 )
3590};
3591pp$8.regexp_eatBracedQuantifier = function(state, noError) {
3592 var start = state.pos;
3593 if (state.eat(0x7B /* { */)) {
3594 var min = 0, max = -1;
3595 if (this.regexp_eatDecimalDigits(state)) {
3596 min = state.lastIntValue;
3597 if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) {
3598 max = state.lastIntValue;
3599 }
3600 if (state.eat(0x7D /* } */)) {
3601 // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
3602 if (max !== -1 && max < min && !noError) {
3603 state.raise("numbers out of order in {} quantifier");
3604 }
3605 return true
3606 }
3607 }
3608 if (state.switchU && !noError) {
3609 state.raise("Incomplete quantifier");
3610 }
3611 state.pos = start;
3612 }
3613 return false
3614};
3615
3616// https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
3617pp$8.regexp_eatAtom = function(state) {
3618 return (
3619 this.regexp_eatPatternCharacters(state) ||
3620 state.eat(0x2E /* . */) ||
3621 this.regexp_eatReverseSolidusAtomEscape(state) ||
3622 this.regexp_eatCharacterClass(state) ||
3623 this.regexp_eatUncapturingGroup(state) ||
3624 this.regexp_eatCapturingGroup(state)
3625 )
3626};
3627pp$8.regexp_eatReverseSolidusAtomEscape = function(state) {
3628 var start = state.pos;
3629 if (state.eat(0x5C /* \ */)) {
3630 if (this.regexp_eatAtomEscape(state)) {
3631 return true
3632 }
3633 state.pos = start;
3634 }
3635 return false
3636};
3637pp$8.regexp_eatUncapturingGroup = function(state) {
3638 var start = state.pos;
3639 if (state.eat(0x28 /* ( */)) {
3640 if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) {
3641 this.regexp_disjunction(state);
3642 if (state.eat(0x29 /* ) */)) {
3643 return true
3644 }
3645 state.raise("Unterminated group");
3646 }
3647 state.pos = start;
3648 }
3649 return false
3650};
3651pp$8.regexp_eatCapturingGroup = function(state) {
3652 if (state.eat(0x28 /* ( */)) {
3653 if (this.options.ecmaVersion >= 9) {
3654 this.regexp_groupSpecifier(state);
3655 } else if (state.current() === 0x3F /* ? */) {
3656 state.raise("Invalid group");
3657 }
3658 this.regexp_disjunction(state);
3659 if (state.eat(0x29 /* ) */)) {
3660 state.numCapturingParens += 1;
3661 return true
3662 }
3663 state.raise("Unterminated group");
3664 }
3665 return false
3666};
3667
3668// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
3669pp$8.regexp_eatExtendedAtom = function(state) {
3670 return (
3671 state.eat(0x2E /* . */) ||
3672 this.regexp_eatReverseSolidusAtomEscape(state) ||
3673 this.regexp_eatCharacterClass(state) ||
3674 this.regexp_eatUncapturingGroup(state) ||
3675 this.regexp_eatCapturingGroup(state) ||
3676 this.regexp_eatInvalidBracedQuantifier(state) ||
3677 this.regexp_eatExtendedPatternCharacter(state)
3678 )
3679};
3680
3681// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
3682pp$8.regexp_eatInvalidBracedQuantifier = function(state) {
3683 if (this.regexp_eatBracedQuantifier(state, true)) {
3684 state.raise("Nothing to repeat");
3685 }
3686 return false
3687};
3688
3689// https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
3690pp$8.regexp_eatSyntaxCharacter = function(state) {
3691 var ch = state.current();
3692 if (isSyntaxCharacter(ch)) {
3693 state.lastIntValue = ch;
3694 state.advance();
3695 return true
3696 }
3697 return false
3698};
3699function isSyntaxCharacter(ch) {
3700 return (
3701 ch === 0x24 /* $ */ ||
3702 ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ ||
3703 ch === 0x2E /* . */ ||
3704 ch === 0x3F /* ? */ ||
3705 ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ ||
3706 ch >= 0x7B /* { */ && ch <= 0x7D /* } */
3707 )
3708}
3709
3710// https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
3711// But eat eager.
3712pp$8.regexp_eatPatternCharacters = function(state) {
3713 var start = state.pos;
3714 var ch = 0;
3715 while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
3716 state.advance();
3717 }
3718 return state.pos !== start
3719};
3720
3721// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
3722pp$8.regexp_eatExtendedPatternCharacter = function(state) {
3723 var ch = state.current();
3724 if (
3725 ch !== -1 &&
3726 ch !== 0x24 /* $ */ &&
3727 !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) &&
3728 ch !== 0x2E /* . */ &&
3729 ch !== 0x3F /* ? */ &&
3730 ch !== 0x5B /* [ */ &&
3731 ch !== 0x5E /* ^ */ &&
3732 ch !== 0x7C /* | */
3733 ) {
3734 state.advance();
3735 return true
3736 }
3737 return false
3738};
3739
3740// GroupSpecifier ::
3741// [empty]
3742// `?` GroupName
3743pp$8.regexp_groupSpecifier = function(state) {
3744 if (state.eat(0x3F /* ? */)) {
3745 if (this.regexp_eatGroupName(state)) {
3746 if (state.groupNames.indexOf(state.lastStringValue) !== -1) {
3747 state.raise("Duplicate capture group name");
3748 }
3749 state.groupNames.push(state.lastStringValue);
3750 return
3751 }
3752 state.raise("Invalid group");
3753 }
3754};
3755
3756// GroupName ::
3757// `<` RegExpIdentifierName `>`
3758// Note: this updates `state.lastStringValue` property with the eaten name.
3759pp$8.regexp_eatGroupName = function(state) {
3760 state.lastStringValue = "";
3761 if (state.eat(0x3C /* < */)) {
3762 if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) {
3763 return true
3764 }
3765 state.raise("Invalid capture group name");
3766 }
3767 return false
3768};
3769
3770// RegExpIdentifierName ::
3771// RegExpIdentifierStart
3772// RegExpIdentifierName RegExpIdentifierPart
3773// Note: this updates `state.lastStringValue` property with the eaten name.
3774pp$8.regexp_eatRegExpIdentifierName = function(state) {
3775 state.lastStringValue = "";
3776 if (this.regexp_eatRegExpIdentifierStart(state)) {
3777 state.lastStringValue += codePointToString(state.lastIntValue);
3778 while (this.regexp_eatRegExpIdentifierPart(state)) {
3779 state.lastStringValue += codePointToString(state.lastIntValue);
3780 }
3781 return true
3782 }
3783 return false
3784};
3785
3786// RegExpIdentifierStart ::
3787// UnicodeIDStart
3788// `$`
3789// `_`
3790// `\` RegExpUnicodeEscapeSequence[+U]
3791pp$8.regexp_eatRegExpIdentifierStart = function(state) {
3792 var start = state.pos;
3793 var forceU = this.options.ecmaVersion >= 11;
3794 var ch = state.current(forceU);
3795 state.advance(forceU);
3796
3797 if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
3798 ch = state.lastIntValue;
3799 }
3800 if (isRegExpIdentifierStart(ch)) {
3801 state.lastIntValue = ch;
3802 return true
3803 }
3804
3805 state.pos = start;
3806 return false
3807};
3808function isRegExpIdentifierStart(ch) {
3809 return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */
3810}
3811
3812// RegExpIdentifierPart ::
3813// UnicodeIDContinue
3814// `$`
3815// `_`
3816// `\` RegExpUnicodeEscapeSequence[+U]
3817// <ZWNJ>
3818// <ZWJ>
3819pp$8.regexp_eatRegExpIdentifierPart = function(state) {
3820 var start = state.pos;
3821 var forceU = this.options.ecmaVersion >= 11;
3822 var ch = state.current(forceU);
3823 state.advance(forceU);
3824
3825 if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
3826 ch = state.lastIntValue;
3827 }
3828 if (isRegExpIdentifierPart(ch)) {
3829 state.lastIntValue = ch;
3830 return true
3831 }
3832
3833 state.pos = start;
3834 return false
3835};
3836function isRegExpIdentifierPart(ch) {
3837 return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */
3838}
3839
3840// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
3841pp$8.regexp_eatAtomEscape = function(state) {
3842 if (
3843 this.regexp_eatBackReference(state) ||
3844 this.regexp_eatCharacterClassEscape(state) ||
3845 this.regexp_eatCharacterEscape(state) ||
3846 (state.switchN && this.regexp_eatKGroupName(state))
3847 ) {
3848 return true
3849 }
3850 if (state.switchU) {
3851 // Make the same message as V8.
3852 if (state.current() === 0x63 /* c */) {
3853 state.raise("Invalid unicode escape");
3854 }
3855 state.raise("Invalid escape");
3856 }
3857 return false
3858};
3859pp$8.regexp_eatBackReference = function(state) {
3860 var start = state.pos;
3861 if (this.regexp_eatDecimalEscape(state)) {
3862 var n = state.lastIntValue;
3863 if (state.switchU) {
3864 // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
3865 if (n > state.maxBackReference) {
3866 state.maxBackReference = n;
3867 }
3868 return true
3869 }
3870 if (n <= state.numCapturingParens) {
3871 return true
3872 }
3873 state.pos = start;
3874 }
3875 return false
3876};
3877pp$8.regexp_eatKGroupName = function(state) {
3878 if (state.eat(0x6B /* k */)) {
3879 if (this.regexp_eatGroupName(state)) {
3880 state.backReferenceNames.push(state.lastStringValue);
3881 return true
3882 }
3883 state.raise("Invalid named reference");
3884 }
3885 return false
3886};
3887
3888// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
3889pp$8.regexp_eatCharacterEscape = function(state) {
3890 return (
3891 this.regexp_eatControlEscape(state) ||
3892 this.regexp_eatCControlLetter(state) ||
3893 this.regexp_eatZero(state) ||
3894 this.regexp_eatHexEscapeSequence(state) ||
3895 this.regexp_eatRegExpUnicodeEscapeSequence(state, false) ||
3896 (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) ||
3897 this.regexp_eatIdentityEscape(state)
3898 )
3899};
3900pp$8.regexp_eatCControlLetter = function(state) {
3901 var start = state.pos;
3902 if (state.eat(0x63 /* c */)) {
3903 if (this.regexp_eatControlLetter(state)) {
3904 return true
3905 }
3906 state.pos = start;
3907 }
3908 return false
3909};
3910pp$8.regexp_eatZero = function(state) {
3911 if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) {
3912 state.lastIntValue = 0;
3913 state.advance();
3914 return true
3915 }
3916 return false
3917};
3918
3919// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
3920pp$8.regexp_eatControlEscape = function(state) {
3921 var ch = state.current();
3922 if (ch === 0x74 /* t */) {
3923 state.lastIntValue = 0x09; /* \t */
3924 state.advance();
3925 return true
3926 }
3927 if (ch === 0x6E /* n */) {
3928 state.lastIntValue = 0x0A; /* \n */
3929 state.advance();
3930 return true
3931 }
3932 if (ch === 0x76 /* v */) {
3933 state.lastIntValue = 0x0B; /* \v */
3934 state.advance();
3935 return true
3936 }
3937 if (ch === 0x66 /* f */) {
3938 state.lastIntValue = 0x0C; /* \f */
3939 state.advance();
3940 return true
3941 }
3942 if (ch === 0x72 /* r */) {
3943 state.lastIntValue = 0x0D; /* \r */
3944 state.advance();
3945 return true
3946 }
3947 return false
3948};
3949
3950// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
3951pp$8.regexp_eatControlLetter = function(state) {
3952 var ch = state.current();
3953 if (isControlLetter(ch)) {
3954 state.lastIntValue = ch % 0x20;
3955 state.advance();
3956 return true
3957 }
3958 return false
3959};
3960function isControlLetter(ch) {
3961 return (
3962 (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) ||
3963 (ch >= 0x61 /* a */ && ch <= 0x7A /* z */)
3964 )
3965}
3966
3967// https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
3968pp$8.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) {
3969 if ( forceU === void 0 ) forceU = false;
3970
3971 var start = state.pos;
3972 var switchU = forceU || state.switchU;
3973
3974 if (state.eat(0x75 /* u */)) {
3975 if (this.regexp_eatFixedHexDigits(state, 4)) {
3976 var lead = state.lastIntValue;
3977 if (switchU && lead >= 0xD800 && lead <= 0xDBFF) {
3978 var leadSurrogateEnd = state.pos;
3979 if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) {
3980 var trail = state.lastIntValue;
3981 if (trail >= 0xDC00 && trail <= 0xDFFF) {
3982 state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
3983 return true
3984 }
3985 }
3986 state.pos = leadSurrogateEnd;
3987 state.lastIntValue = lead;
3988 }
3989 return true
3990 }
3991 if (
3992 switchU &&
3993 state.eat(0x7B /* { */) &&
3994 this.regexp_eatHexDigits(state) &&
3995 state.eat(0x7D /* } */) &&
3996 isValidUnicode(state.lastIntValue)
3997 ) {
3998 return true
3999 }
4000 if (switchU) {
4001 state.raise("Invalid unicode escape");
4002 }
4003 state.pos = start;
4004 }
4005
4006 return false
4007};
4008function isValidUnicode(ch) {
4009 return ch >= 0 && ch <= 0x10FFFF
4010}
4011
4012// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
4013pp$8.regexp_eatIdentityEscape = function(state) {
4014 if (state.switchU) {
4015 if (this.regexp_eatSyntaxCharacter(state)) {
4016 return true
4017 }
4018 if (state.eat(0x2F /* / */)) {
4019 state.lastIntValue = 0x2F; /* / */
4020 return true
4021 }
4022 return false
4023 }
4024
4025 var ch = state.current();
4026 if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) {
4027 state.lastIntValue = ch;
4028 state.advance();
4029 return true
4030 }
4031
4032 return false
4033};
4034
4035// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
4036pp$8.regexp_eatDecimalEscape = function(state) {
4037 state.lastIntValue = 0;
4038 var ch = state.current();
4039 if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) {
4040 do {
4041 state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
4042 state.advance();
4043 } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */)
4044 return true
4045 }
4046 return false
4047};
4048
4049// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
4050pp$8.regexp_eatCharacterClassEscape = function(state) {
4051 var ch = state.current();
4052
4053 if (isCharacterClassEscape(ch)) {
4054 state.lastIntValue = -1;
4055 state.advance();
4056 return true
4057 }
4058
4059 if (
4060 state.switchU &&
4061 this.options.ecmaVersion >= 9 &&
4062 (ch === 0x50 /* P */ || ch === 0x70 /* p */)
4063 ) {
4064 state.lastIntValue = -1;
4065 state.advance();
4066 if (
4067 state.eat(0x7B /* { */) &&
4068 this.regexp_eatUnicodePropertyValueExpression(state) &&
4069 state.eat(0x7D /* } */)
4070 ) {
4071 return true
4072 }
4073 state.raise("Invalid property name");
4074 }
4075
4076 return false
4077};
4078function isCharacterClassEscape(ch) {
4079 return (
4080 ch === 0x64 /* d */ ||
4081 ch === 0x44 /* D */ ||
4082 ch === 0x73 /* s */ ||
4083 ch === 0x53 /* S */ ||
4084 ch === 0x77 /* w */ ||
4085 ch === 0x57 /* W */
4086 )
4087}
4088
4089// UnicodePropertyValueExpression ::
4090// UnicodePropertyName `=` UnicodePropertyValue
4091// LoneUnicodePropertyNameOrValue
4092pp$8.regexp_eatUnicodePropertyValueExpression = function(state) {
4093 var start = state.pos;
4094
4095 // UnicodePropertyName `=` UnicodePropertyValue
4096 if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) {
4097 var name = state.lastStringValue;
4098 if (this.regexp_eatUnicodePropertyValue(state)) {
4099 var value = state.lastStringValue;
4100 this.regexp_validateUnicodePropertyNameAndValue(state, name, value);
4101 return true
4102 }
4103 }
4104 state.pos = start;
4105
4106 // LoneUnicodePropertyNameOrValue
4107 if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
4108 var nameOrValue = state.lastStringValue;
4109 this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue);
4110 return true
4111 }
4112 return false
4113};
4114pp$8.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
4115 if (!has(state.unicodeProperties.nonBinary, name))
4116 { state.raise("Invalid property name"); }
4117 if (!state.unicodeProperties.nonBinary[name].test(value))
4118 { state.raise("Invalid property value"); }
4119};
4120pp$8.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
4121 if (!state.unicodeProperties.binary.test(nameOrValue))
4122 { state.raise("Invalid property name"); }
4123};
4124
4125// UnicodePropertyName ::
4126// UnicodePropertyNameCharacters
4127pp$8.regexp_eatUnicodePropertyName = function(state) {
4128 var ch = 0;
4129 state.lastStringValue = "";
4130 while (isUnicodePropertyNameCharacter(ch = state.current())) {
4131 state.lastStringValue += codePointToString(ch);
4132 state.advance();
4133 }
4134 return state.lastStringValue !== ""
4135};
4136function isUnicodePropertyNameCharacter(ch) {
4137 return isControlLetter(ch) || ch === 0x5F /* _ */
4138}
4139
4140// UnicodePropertyValue ::
4141// UnicodePropertyValueCharacters
4142pp$8.regexp_eatUnicodePropertyValue = function(state) {
4143 var ch = 0;
4144 state.lastStringValue = "";
4145 while (isUnicodePropertyValueCharacter(ch = state.current())) {
4146 state.lastStringValue += codePointToString(ch);
4147 state.advance();
4148 }
4149 return state.lastStringValue !== ""
4150};
4151function isUnicodePropertyValueCharacter(ch) {
4152 return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch)
4153}
4154
4155// LoneUnicodePropertyNameOrValue ::
4156// UnicodePropertyValueCharacters
4157pp$8.regexp_eatLoneUnicodePropertyNameOrValue = function(state) {
4158 return this.regexp_eatUnicodePropertyValue(state)
4159};
4160
4161// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
4162pp$8.regexp_eatCharacterClass = function(state) {
4163 if (state.eat(0x5B /* [ */)) {
4164 state.eat(0x5E /* ^ */);
4165 this.regexp_classRanges(state);
4166 if (state.eat(0x5D /* ] */)) {
4167 return true
4168 }
4169 // Unreachable since it threw "unterminated regular expression" error before.
4170 state.raise("Unterminated character class");
4171 }
4172 return false
4173};
4174
4175// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
4176// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
4177// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
4178pp$8.regexp_classRanges = function(state) {
4179 while (this.regexp_eatClassAtom(state)) {
4180 var left = state.lastIntValue;
4181 if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) {
4182 var right = state.lastIntValue;
4183 if (state.switchU && (left === -1 || right === -1)) {
4184 state.raise("Invalid character class");
4185 }
4186 if (left !== -1 && right !== -1 && left > right) {
4187 state.raise("Range out of order in character class");
4188 }
4189 }
4190 }
4191};
4192
4193// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
4194// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
4195pp$8.regexp_eatClassAtom = function(state) {
4196 var start = state.pos;
4197
4198 if (state.eat(0x5C /* \ */)) {
4199 if (this.regexp_eatClassEscape(state)) {
4200 return true
4201 }
4202 if (state.switchU) {
4203 // Make the same message as V8.
4204 var ch$1 = state.current();
4205 if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
4206 state.raise("Invalid class escape");
4207 }
4208 state.raise("Invalid escape");
4209 }
4210 state.pos = start;
4211 }
4212
4213 var ch = state.current();
4214 if (ch !== 0x5D /* ] */) {
4215 state.lastIntValue = ch;
4216 state.advance();
4217 return true
4218 }
4219
4220 return false
4221};
4222
4223// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
4224pp$8.regexp_eatClassEscape = function(state) {
4225 var start = state.pos;
4226
4227 if (state.eat(0x62 /* b */)) {
4228 state.lastIntValue = 0x08; /* <BS> */
4229 return true
4230 }
4231
4232 if (state.switchU && state.eat(0x2D /* - */)) {
4233 state.lastIntValue = 0x2D; /* - */
4234 return true
4235 }
4236
4237 if (!state.switchU && state.eat(0x63 /* c */)) {
4238 if (this.regexp_eatClassControlLetter(state)) {
4239 return true
4240 }
4241 state.pos = start;
4242 }
4243
4244 return (
4245 this.regexp_eatCharacterClassEscape(state) ||
4246 this.regexp_eatCharacterEscape(state)
4247 )
4248};
4249
4250// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
4251pp$8.regexp_eatClassControlLetter = function(state) {
4252 var ch = state.current();
4253 if (isDecimalDigit(ch) || ch === 0x5F /* _ */) {
4254 state.lastIntValue = ch % 0x20;
4255 state.advance();
4256 return true
4257 }
4258 return false
4259};
4260
4261// https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
4262pp$8.regexp_eatHexEscapeSequence = function(state) {
4263 var start = state.pos;
4264 if (state.eat(0x78 /* x */)) {
4265 if (this.regexp_eatFixedHexDigits(state, 2)) {
4266 return true
4267 }
4268 if (state.switchU) {
4269 state.raise("Invalid escape");
4270 }
4271 state.pos = start;
4272 }
4273 return false
4274};
4275
4276// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
4277pp$8.regexp_eatDecimalDigits = function(state) {
4278 var start = state.pos;
4279 var ch = 0;
4280 state.lastIntValue = 0;
4281 while (isDecimalDigit(ch = state.current())) {
4282 state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
4283 state.advance();
4284 }
4285 return state.pos !== start
4286};
4287function isDecimalDigit(ch) {
4288 return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */
4289}
4290
4291// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
4292pp$8.regexp_eatHexDigits = function(state) {
4293 var start = state.pos;
4294 var ch = 0;
4295 state.lastIntValue = 0;
4296 while (isHexDigit(ch = state.current())) {
4297 state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
4298 state.advance();
4299 }
4300 return state.pos !== start
4301};
4302function isHexDigit(ch) {
4303 return (
4304 (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) ||
4305 (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) ||
4306 (ch >= 0x61 /* a */ && ch <= 0x66 /* f */)
4307 )
4308}
4309function hexToInt(ch) {
4310 if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) {
4311 return 10 + (ch - 0x41 /* A */)
4312 }
4313 if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) {
4314 return 10 + (ch - 0x61 /* a */)
4315 }
4316 return ch - 0x30 /* 0 */
4317}
4318
4319// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
4320// Allows only 0-377(octal) i.e. 0-255(decimal).
4321pp$8.regexp_eatLegacyOctalEscapeSequence = function(state) {
4322 if (this.regexp_eatOctalDigit(state)) {
4323 var n1 = state.lastIntValue;
4324 if (this.regexp_eatOctalDigit(state)) {
4325 var n2 = state.lastIntValue;
4326 if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
4327 state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
4328 } else {
4329 state.lastIntValue = n1 * 8 + n2;
4330 }
4331 } else {
4332 state.lastIntValue = n1;
4333 }
4334 return true
4335 }
4336 return false
4337};
4338
4339// https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
4340pp$8.regexp_eatOctalDigit = function(state) {
4341 var ch = state.current();
4342 if (isOctalDigit(ch)) {
4343 state.lastIntValue = ch - 0x30; /* 0 */
4344 state.advance();
4345 return true
4346 }
4347 state.lastIntValue = 0;
4348 return false
4349};
4350function isOctalDigit(ch) {
4351 return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */
4352}
4353
4354// https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
4355// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
4356// And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
4357pp$8.regexp_eatFixedHexDigits = function(state, length) {
4358 var start = state.pos;
4359 state.lastIntValue = 0;
4360 for (var i = 0; i < length; ++i) {
4361 var ch = state.current();
4362 if (!isHexDigit(ch)) {
4363 state.pos = start;
4364 return false
4365 }
4366 state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
4367 state.advance();
4368 }
4369 return true
4370};
4371
4372// Object type used to represent tokens. Note that normally, tokens
4373// simply exist as properties on the parser object. This is only
4374// used for the onToken callback and the external tokenizer.
4375
4376var Token = function Token(p) {
4377 this.type = p.type;
4378 this.value = p.value;
4379 this.start = p.start;
4380 this.end = p.end;
4381 if (p.options.locations)
4382 { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
4383 if (p.options.ranges)
4384 { this.range = [p.start, p.end]; }
4385};
4386
4387// ## Tokenizer
4388
4389var pp$9 = Parser.prototype;
4390
4391// Move to the next token
4392
4393pp$9.next = function(ignoreEscapeSequenceInKeyword) {
4394 if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc)
4395 { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); }
4396 if (this.options.onToken)
4397 { this.options.onToken(new Token(this)); }
4398
4399 this.lastTokEnd = this.end;
4400 this.lastTokStart = this.start;
4401 this.lastTokEndLoc = this.endLoc;
4402 this.lastTokStartLoc = this.startLoc;
4403 this.nextToken();
4404};
4405
4406pp$9.getToken = function() {
4407 this.next();
4408 return new Token(this)
4409};
4410
4411// If we're in an ES6 environment, make parsers iterable
4412if (typeof Symbol !== "undefined")
4413 { pp$9[Symbol.iterator] = function() {
4414 var this$1 = this;
4415
4416 return {
4417 next: function () {
4418 var token = this$1.getToken();
4419 return {
4420 done: token.type === types.eof,
4421 value: token
4422 }
4423 }
4424 }
4425 }; }
4426
4427// Toggle strict mode. Re-reads the next number or string to please
4428// pedantic tests (`"use strict"; 010;` should fail).
4429
4430pp$9.curContext = function() {
4431 return this.context[this.context.length - 1]
4432};
4433
4434// Read a single token, updating the parser object's token-related
4435// properties.
4436
4437pp$9.nextToken = function() {
4438 var curContext = this.curContext();
4439 if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }
4440
4441 this.start = this.pos;
4442 if (this.options.locations) { this.startLoc = this.curPosition(); }
4443 if (this.pos >= this.input.length) { return this.finishToken(types.eof) }
4444
4445 if (curContext.override) { return curContext.override(this) }
4446 else { this.readToken(this.fullCharCodeAtPos()); }
4447};
4448
4449pp$9.readToken = function(code) {
4450 // Identifier or keyword. '\uXXXX' sequences are allowed in
4451 // identifiers, so '\' also dispatches to that.
4452 if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
4453 { return this.readWord() }
4454
4455 return this.getTokenFromCode(code)
4456};
4457
4458pp$9.fullCharCodeAtPos = function() {
4459 var code = this.input.charCodeAt(this.pos);
4460 if (code <= 0xd7ff || code >= 0xe000) { return code }
4461 var next = this.input.charCodeAt(this.pos + 1);
4462 return (code << 10) + next - 0x35fdc00
4463};
4464
4465pp$9.skipBlockComment = function() {
4466 var startLoc = this.options.onComment && this.curPosition();
4467 var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
4468 if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
4469 this.pos = end + 2;
4470 if (this.options.locations) {
4471 lineBreakG.lastIndex = start;
4472 var match;
4473 while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
4474 ++this.curLine;
4475 this.lineStart = match.index + match[0].length;
4476 }
4477 }
4478 if (this.options.onComment)
4479 { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
4480 startLoc, this.curPosition()); }
4481};
4482
4483pp$9.skipLineComment = function(startSkip) {
4484 var start = this.pos;
4485 var startLoc = this.options.onComment && this.curPosition();
4486 var ch = this.input.charCodeAt(this.pos += startSkip);
4487 while (this.pos < this.input.length && !isNewLine(ch)) {
4488 ch = this.input.charCodeAt(++this.pos);
4489 }
4490 if (this.options.onComment)
4491 { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
4492 startLoc, this.curPosition()); }
4493};
4494
4495// Called at the start of the parse and after every token. Skips
4496// whitespace and comments, and.
4497
4498pp$9.skipSpace = function() {
4499 loop: while (this.pos < this.input.length) {
4500 var ch = this.input.charCodeAt(this.pos);
4501 switch (ch) {
4502 case 32: case 160: // ' '
4503 ++this.pos;
4504 break
4505 case 13:
4506 if (this.input.charCodeAt(this.pos + 1) === 10) {
4507 ++this.pos;
4508 }
4509 case 10: case 8232: case 8233:
4510 ++this.pos;
4511 if (this.options.locations) {
4512 ++this.curLine;
4513 this.lineStart = this.pos;
4514 }
4515 break
4516 case 47: // '/'
4517 switch (this.input.charCodeAt(this.pos + 1)) {
4518 case 42: // '*'
4519 this.skipBlockComment();
4520 break
4521 case 47:
4522 this.skipLineComment(2);
4523 break
4524 default:
4525 break loop
4526 }
4527 break
4528 default:
4529 if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
4530 ++this.pos;
4531 } else {
4532 break loop
4533 }
4534 }
4535 }
4536};
4537
4538// Called at the end of every token. Sets `end`, `val`, and
4539// maintains `context` and `exprAllowed`, and skips the space after
4540// the token, so that the next one's `start` will point at the
4541// right position.
4542
4543pp$9.finishToken = function(type, val) {
4544 this.end = this.pos;
4545 if (this.options.locations) { this.endLoc = this.curPosition(); }
4546 var prevType = this.type;
4547 this.type = type;
4548 this.value = val;
4549
4550 this.updateContext(prevType);
4551};
4552
4553// ### Token reading
4554
4555// This is the function that is called to fetch the next token. It
4556// is somewhat obscure, because it works in character codes rather
4557// than characters, and because operator parsing has been inlined
4558// into it.
4559//
4560// All in the name of speed.
4561//
4562pp$9.readToken_dot = function() {
4563 var next = this.input.charCodeAt(this.pos + 1);
4564 if (next >= 48 && next <= 57) { return this.readNumber(true) }
4565 var next2 = this.input.charCodeAt(this.pos + 2);
4566 if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
4567 this.pos += 3;
4568 return this.finishToken(types.ellipsis)
4569 } else {
4570 ++this.pos;
4571 return this.finishToken(types.dot)
4572 }
4573};
4574
4575pp$9.readToken_slash = function() { // '/'
4576 var next = this.input.charCodeAt(this.pos + 1);
4577 if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
4578 if (next === 61) { return this.finishOp(types.assign, 2) }
4579 return this.finishOp(types.slash, 1)
4580};
4581
4582pp$9.readToken_mult_modulo_exp = function(code) { // '%*'
4583 var next = this.input.charCodeAt(this.pos + 1);
4584 var size = 1;
4585 var tokentype = code === 42 ? types.star : types.modulo;
4586
4587 // exponentiation operator ** and **=
4588 if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
4589 ++size;
4590 tokentype = types.starstar;
4591 next = this.input.charCodeAt(this.pos + 2);
4592 }
4593
4594 if (next === 61) { return this.finishOp(types.assign, size + 1) }
4595 return this.finishOp(tokentype, size)
4596};
4597
4598pp$9.readToken_pipe_amp = function(code) { // '|&'
4599 var next = this.input.charCodeAt(this.pos + 1);
4600 if (next === code) {
4601 if (this.options.ecmaVersion >= 12) {
4602 var next2 = this.input.charCodeAt(this.pos + 2);
4603 if (next2 === 61) { return this.finishOp(types.assign, 3) }
4604 }
4605 return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2)
4606 }
4607 if (next === 61) { return this.finishOp(types.assign, 2) }
4608 return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1)
4609};
4610
4611pp$9.readToken_caret = function() { // '^'
4612 var next = this.input.charCodeAt(this.pos + 1);
4613 if (next === 61) { return this.finishOp(types.assign, 2) }
4614 return this.finishOp(types.bitwiseXOR, 1)
4615};
4616
4617pp$9.readToken_plus_min = function(code) { // '+-'
4618 var next = this.input.charCodeAt(this.pos + 1);
4619 if (next === code) {
4620 if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 &&
4621 (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
4622 // A `-->` line comment
4623 this.skipLineComment(3);
4624 this.skipSpace();
4625 return this.nextToken()
4626 }
4627 return this.finishOp(types.incDec, 2)
4628 }
4629 if (next === 61) { return this.finishOp(types.assign, 2) }
4630 return this.finishOp(types.plusMin, 1)
4631};
4632
4633pp$9.readToken_lt_gt = function(code) { // '<>'
4634 var next = this.input.charCodeAt(this.pos + 1);
4635 var size = 1;
4636 if (next === code) {
4637 size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
4638 if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) }
4639 return this.finishOp(types.bitShift, size)
4640 }
4641 if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 &&
4642 this.input.charCodeAt(this.pos + 3) === 45) {
4643 // `<!--`, an XML-style comment that should be interpreted as a line comment
4644 this.skipLineComment(4);
4645 this.skipSpace();
4646 return this.nextToken()
4647 }
4648 if (next === 61) { size = 2; }
4649 return this.finishOp(types.relational, size)
4650};
4651
4652pp$9.readToken_eq_excl = function(code) { // '=!'
4653 var next = this.input.charCodeAt(this.pos + 1);
4654 if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
4655 if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
4656 this.pos += 2;
4657 return this.finishToken(types.arrow)
4658 }
4659 return this.finishOp(code === 61 ? types.eq : types.prefix, 1)
4660};
4661
4662pp$9.readToken_question = function() { // '?'
4663 var ecmaVersion = this.options.ecmaVersion;
4664 if (ecmaVersion >= 11) {
4665 var next = this.input.charCodeAt(this.pos + 1);
4666 if (next === 46) {
4667 var next2 = this.input.charCodeAt(this.pos + 2);
4668 if (next2 < 48 || next2 > 57) { return this.finishOp(types.questionDot, 2) }
4669 }
4670 if (next === 63) {
4671 if (ecmaVersion >= 12) {
4672 var next2$1 = this.input.charCodeAt(this.pos + 2);
4673 if (next2$1 === 61) { return this.finishOp(types.assign, 3) }
4674 }
4675 return this.finishOp(types.coalesce, 2)
4676 }
4677 }
4678 return this.finishOp(types.question, 1)
4679};
4680
4681pp$9.getTokenFromCode = function(code) {
4682 switch (code) {
4683 // The interpretation of a dot depends on whether it is followed
4684 // by a digit or another two dots.
4685 case 46: // '.'
4686 return this.readToken_dot()
4687
4688 // Punctuation tokens.
4689 case 40: ++this.pos; return this.finishToken(types.parenL)
4690 case 41: ++this.pos; return this.finishToken(types.parenR)
4691 case 59: ++this.pos; return this.finishToken(types.semi)
4692 case 44: ++this.pos; return this.finishToken(types.comma)
4693 case 91: ++this.pos; return this.finishToken(types.bracketL)
4694 case 93: ++this.pos; return this.finishToken(types.bracketR)
4695 case 123: ++this.pos; return this.finishToken(types.braceL)
4696 case 125: ++this.pos; return this.finishToken(types.braceR)
4697 case 58: ++this.pos; return this.finishToken(types.colon)
4698
4699 case 96: // '`'
4700 if (this.options.ecmaVersion < 6) { break }
4701 ++this.pos;
4702 return this.finishToken(types.backQuote)
4703
4704 case 48: // '0'
4705 var next = this.input.charCodeAt(this.pos + 1);
4706 if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number
4707 if (this.options.ecmaVersion >= 6) {
4708 if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number
4709 if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number
4710 }
4711
4712 // Anything else beginning with a digit is an integer, octal
4713 // number, or float.
4714 case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
4715 return this.readNumber(false)
4716
4717 // Quotes produce strings.
4718 case 34: case 39: // '"', "'"
4719 return this.readString(code)
4720
4721 // Operators are parsed inline in tiny state machines. '=' (61) is
4722 // often referred to. `finishOp` simply skips the amount of
4723 // characters it is given as second argument, and returns a token
4724 // of the type given by its first argument.
4725
4726 case 47: // '/'
4727 return this.readToken_slash()
4728
4729 case 37: case 42: // '%*'
4730 return this.readToken_mult_modulo_exp(code)
4731
4732 case 124: case 38: // '|&'
4733 return this.readToken_pipe_amp(code)
4734
4735 case 94: // '^'
4736 return this.readToken_caret()
4737
4738 case 43: case 45: // '+-'
4739 return this.readToken_plus_min(code)
4740
4741 case 60: case 62: // '<>'
4742 return this.readToken_lt_gt(code)
4743
4744 case 61: case 33: // '=!'
4745 return this.readToken_eq_excl(code)
4746
4747 case 63: // '?'
4748 return this.readToken_question()
4749
4750 case 126: // '~'
4751 return this.finishOp(types.prefix, 1)
4752 }
4753
4754 this.raise(this.pos, "Unexpected character '" + codePointToString$1(code) + "'");
4755};
4756
4757pp$9.finishOp = function(type, size) {
4758 var str = this.input.slice(this.pos, this.pos + size);
4759 this.pos += size;
4760 return this.finishToken(type, str)
4761};
4762
4763pp$9.readRegexp = function() {
4764 var escaped, inClass, start = this.pos;
4765 for (;;) {
4766 if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); }
4767 var ch = this.input.charAt(this.pos);
4768 if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); }
4769 if (!escaped) {
4770 if (ch === "[") { inClass = true; }
4771 else if (ch === "]" && inClass) { inClass = false; }
4772 else if (ch === "/" && !inClass) { break }
4773 escaped = ch === "\\";
4774 } else { escaped = false; }
4775 ++this.pos;
4776 }
4777 var pattern = this.input.slice(start, this.pos);
4778 ++this.pos;
4779 var flagsStart = this.pos;
4780 var flags = this.readWord1();
4781 if (this.containsEsc) { this.unexpected(flagsStart); }
4782
4783 // Validate pattern
4784 var state = this.regexpState || (this.regexpState = new RegExpValidationState(this));
4785 state.reset(start, pattern, flags);
4786 this.validateRegExpFlags(state);
4787 this.validateRegExpPattern(state);
4788
4789 // Create Literal#value property value.
4790 var value = null;
4791 try {
4792 value = new RegExp(pattern, flags);
4793 } catch (e) {
4794 // ESTree requires null if it failed to instantiate RegExp object.
4795 // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral
4796 }
4797
4798 return this.finishToken(types.regexp, {pattern: pattern, flags: flags, value: value})
4799};
4800
4801// Read an integer in the given radix. Return null if zero digits
4802// were read, the integer value otherwise. When `len` is given, this
4803// will return `null` unless the integer has exactly `len` digits.
4804
4805pp$9.readInt = function(radix, len, maybeLegacyOctalNumericLiteral) {
4806 // `len` is used for character escape sequences. In that case, disallow separators.
4807 var allowSeparators = this.options.ecmaVersion >= 12 && len === undefined;
4808
4809 // `maybeLegacyOctalNumericLiteral` is true if it doesn't have prefix (0x,0o,0b)
4810 // and isn't fraction part nor exponent part. In that case, if the first digit
4811 // is zero then disallow separators.
4812 var isLegacyOctalNumericLiteral = maybeLegacyOctalNumericLiteral && this.input.charCodeAt(this.pos) === 48;
4813
4814 var start = this.pos, total = 0, lastCode = 0;
4815 for (var i = 0, e = len == null ? Infinity : len; i < e; ++i, ++this.pos) {
4816 var code = this.input.charCodeAt(this.pos), val = (void 0);
4817
4818 if (allowSeparators && code === 95) {
4819 if (isLegacyOctalNumericLiteral) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed in legacy octal numeric literals"); }
4820 if (lastCode === 95) { this.raiseRecoverable(this.pos, "Numeric separator must be exactly one underscore"); }
4821 if (i === 0) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed at the first of digits"); }
4822 lastCode = code;
4823 continue
4824 }
4825
4826 if (code >= 97) { val = code - 97 + 10; } // a
4827 else if (code >= 65) { val = code - 65 + 10; } // A
4828 else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
4829 else { val = Infinity; }
4830 if (val >= radix) { break }
4831 lastCode = code;
4832 total = total * radix + val;
4833 }
4834
4835 if (allowSeparators && lastCode === 95) { this.raiseRecoverable(this.pos - 1, "Numeric separator is not allowed at the last of digits"); }
4836 if (this.pos === start || len != null && this.pos - start !== len) { return null }
4837
4838 return total
4839};
4840
4841function stringToNumber(str, isLegacyOctalNumericLiteral) {
4842 if (isLegacyOctalNumericLiteral) {
4843 return parseInt(str, 8)
4844 }
4845
4846 // `parseFloat(value)` stops parsing at the first numeric separator then returns a wrong value.
4847 return parseFloat(str.replace(/_/g, ""))
4848}
4849
4850function stringToBigInt(str) {
4851 if (typeof BigInt !== "function") {
4852 return null
4853 }
4854
4855 // `BigInt(value)` throws syntax error if the string contains numeric separators.
4856 return BigInt(str.replace(/_/g, ""))
4857}
4858
4859pp$9.readRadixNumber = function(radix) {
4860 var start = this.pos;
4861 this.pos += 2; // 0x
4862 var val = this.readInt(radix);
4863 if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
4864 if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
4865 val = stringToBigInt(this.input.slice(start, this.pos));
4866 ++this.pos;
4867 } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4868 return this.finishToken(types.num, val)
4869};
4870
4871// Read an integer, octal integer, or floating-point number.
4872
4873pp$9.readNumber = function(startsWithDot) {
4874 var start = this.pos;
4875 if (!startsWithDot && this.readInt(10, undefined, true) === null) { this.raise(start, "Invalid number"); }
4876 var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48;
4877 if (octal && this.strict) { this.raise(start, "Invalid number"); }
4878 var next = this.input.charCodeAt(this.pos);
4879 if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
4880 var val$1 = stringToBigInt(this.input.slice(start, this.pos));
4881 ++this.pos;
4882 if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4883 return this.finishToken(types.num, val$1)
4884 }
4885 if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; }
4886 if (next === 46 && !octal) { // '.'
4887 ++this.pos;
4888 this.readInt(10);
4889 next = this.input.charCodeAt(this.pos);
4890 }
4891 if ((next === 69 || next === 101) && !octal) { // 'eE'
4892 next = this.input.charCodeAt(++this.pos);
4893 if (next === 43 || next === 45) { ++this.pos; } // '+-'
4894 if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
4895 }
4896 if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4897
4898 var val = stringToNumber(this.input.slice(start, this.pos), octal);
4899 return this.finishToken(types.num, val)
4900};
4901
4902// Read a string value, interpreting backslash-escapes.
4903
4904pp$9.readCodePoint = function() {
4905 var ch = this.input.charCodeAt(this.pos), code;
4906
4907 if (ch === 123) { // '{'
4908 if (this.options.ecmaVersion < 6) { this.unexpected(); }
4909 var codePos = ++this.pos;
4910 code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
4911 ++this.pos;
4912 if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
4913 } else {
4914 code = this.readHexChar(4);
4915 }
4916 return code
4917};
4918
4919function codePointToString$1(code) {
4920 // UTF-16 Decoding
4921 if (code <= 0xFFFF) { return String.fromCharCode(code) }
4922 code -= 0x10000;
4923 return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
4924}
4925
4926pp$9.readString = function(quote) {
4927 var out = "", chunkStart = ++this.pos;
4928 for (;;) {
4929 if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); }
4930 var ch = this.input.charCodeAt(this.pos);
4931 if (ch === quote) { break }
4932 if (ch === 92) { // '\'
4933 out += this.input.slice(chunkStart, this.pos);
4934 out += this.readEscapedChar(false);
4935 chunkStart = this.pos;
4936 } else {
4937 if (isNewLine(ch, this.options.ecmaVersion >= 10)) { this.raise(this.start, "Unterminated string constant"); }
4938 ++this.pos;
4939 }
4940 }
4941 out += this.input.slice(chunkStart, this.pos++);
4942 return this.finishToken(types.string, out)
4943};
4944
4945// Reads template string tokens.
4946
4947var INVALID_TEMPLATE_ESCAPE_ERROR = {};
4948
4949pp$9.tryReadTemplateToken = function() {
4950 this.inTemplateElement = true;
4951 try {
4952 this.readTmplToken();
4953 } catch (err) {
4954 if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
4955 this.readInvalidTemplateToken();
4956 } else {
4957 throw err
4958 }
4959 }
4960
4961 this.inTemplateElement = false;
4962};
4963
4964pp$9.invalidStringToken = function(position, message) {
4965 if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
4966 throw INVALID_TEMPLATE_ESCAPE_ERROR
4967 } else {
4968 this.raise(position, message);
4969 }
4970};
4971
4972pp$9.readTmplToken = function() {
4973 var out = "", chunkStart = this.pos;
4974 for (;;) {
4975 if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); }
4976 var ch = this.input.charCodeAt(this.pos);
4977 if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${'
4978 if (this.pos === this.start && (this.type === types.template || this.type === types.invalidTemplate)) {
4979 if (ch === 36) {
4980 this.pos += 2;
4981 return this.finishToken(types.dollarBraceL)
4982 } else {
4983 ++this.pos;
4984 return this.finishToken(types.backQuote)
4985 }
4986 }
4987 out += this.input.slice(chunkStart, this.pos);
4988 return this.finishToken(types.template, out)
4989 }
4990 if (ch === 92) { // '\'
4991 out += this.input.slice(chunkStart, this.pos);
4992 out += this.readEscapedChar(true);
4993 chunkStart = this.pos;
4994 } else if (isNewLine(ch)) {
4995 out += this.input.slice(chunkStart, this.pos);
4996 ++this.pos;
4997 switch (ch) {
4998 case 13:
4999 if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; }
5000 case 10:
5001 out += "\n";
5002 break
5003 default:
5004 out += String.fromCharCode(ch);
5005 break
5006 }
5007 if (this.options.locations) {
5008 ++this.curLine;
5009 this.lineStart = this.pos;
5010 }
5011 chunkStart = this.pos;
5012 } else {
5013 ++this.pos;
5014 }
5015 }
5016};
5017
5018// Reads a template token to search for the end, without validating any escape sequences
5019pp$9.readInvalidTemplateToken = function() {
5020 for (; this.pos < this.input.length; this.pos++) {
5021 switch (this.input[this.pos]) {
5022 case "\\":
5023 ++this.pos;
5024 break
5025
5026 case "$":
5027 if (this.input[this.pos + 1] !== "{") {
5028 break
5029 }
5030 // falls through
5031
5032 case "`":
5033 return this.finishToken(types.invalidTemplate, this.input.slice(this.start, this.pos))
5034
5035 // no default
5036 }
5037 }
5038 this.raise(this.start, "Unterminated template");
5039};
5040
5041// Used to read escaped characters
5042
5043pp$9.readEscapedChar = function(inTemplate) {
5044 var ch = this.input.charCodeAt(++this.pos);
5045 ++this.pos;
5046 switch (ch) {
5047 case 110: return "\n" // 'n' -> '\n'
5048 case 114: return "\r" // 'r' -> '\r'
5049 case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
5050 case 117: return codePointToString$1(this.readCodePoint()) // 'u'
5051 case 116: return "\t" // 't' -> '\t'
5052 case 98: return "\b" // 'b' -> '\b'
5053 case 118: return "\u000b" // 'v' -> '\u000b'
5054 case 102: return "\f" // 'f' -> '\f'
5055 case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
5056 case 10: // ' \n'
5057 if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
5058 return ""
5059 case 56:
5060 case 57:
5061 if (inTemplate) {
5062 var codePos = this.pos - 1;
5063
5064 this.invalidStringToken(
5065 codePos,
5066 "Invalid escape sequence in template string"
5067 );
5068
5069 return null
5070 }
5071 default:
5072 if (ch >= 48 && ch <= 55) {
5073 var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
5074 var octal = parseInt(octalStr, 8);
5075 if (octal > 255) {
5076 octalStr = octalStr.slice(0, -1);
5077 octal = parseInt(octalStr, 8);
5078 }
5079 this.pos += octalStr.length - 1;
5080 ch = this.input.charCodeAt(this.pos);
5081 if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
5082 this.invalidStringToken(
5083 this.pos - 1 - octalStr.length,
5084 inTemplate
5085 ? "Octal literal in template string"
5086 : "Octal literal in strict mode"
5087 );
5088 }
5089 return String.fromCharCode(octal)
5090 }
5091 if (isNewLine(ch)) {
5092 // Unicode new line characters after \ get removed from output in both
5093 // template literals and strings
5094 return ""
5095 }
5096 return String.fromCharCode(ch)
5097 }
5098};
5099
5100// Used to read character escape sequences ('\x', '\u', '\U').
5101
5102pp$9.readHexChar = function(len) {
5103 var codePos = this.pos;
5104 var n = this.readInt(16, len);
5105 if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
5106 return n
5107};
5108
5109// Read an identifier, and return it as a string. Sets `this.containsEsc`
5110// to whether the word contained a '\u' escape.
5111//
5112// Incrementally adds only escaped chars, adding other chunks as-is
5113// as a micro-optimization.
5114
5115pp$9.readWord1 = function() {
5116 this.containsEsc = false;
5117 var word = "", first = true, chunkStart = this.pos;
5118 var astral = this.options.ecmaVersion >= 6;
5119 while (this.pos < this.input.length) {
5120 var ch = this.fullCharCodeAtPos();
5121 if (isIdentifierChar(ch, astral)) {
5122 this.pos += ch <= 0xffff ? 1 : 2;
5123 } else if (ch === 92) { // "\"
5124 this.containsEsc = true;
5125 word += this.input.slice(chunkStart, this.pos);
5126 var escStart = this.pos;
5127 if (this.input.charCodeAt(++this.pos) !== 117) // "u"
5128 { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); }
5129 ++this.pos;
5130 var esc = this.readCodePoint();
5131 if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
5132 { this.invalidStringToken(escStart, "Invalid Unicode escape"); }
5133 word += codePointToString$1(esc);
5134 chunkStart = this.pos;
5135 } else {
5136 break
5137 }
5138 first = false;
5139 }
5140 return word + this.input.slice(chunkStart, this.pos)
5141};
5142
5143// Read an identifier or keyword token. Will check for reserved
5144// words when necessary.
5145
5146pp$9.readWord = function() {
5147 var word = this.readWord1();
5148 var type = types.name;
5149 if (this.keywords.test(word)) {
5150 type = keywords$1[word];
5151 }
5152 return this.finishToken(type, word)
5153};
5154
5155// Acorn is a tiny, fast JavaScript parser written in JavaScript.
5156
5157var version = "7.4.0";
5158
5159Parser.acorn = {
5160 Parser: Parser,
5161 version: version,
5162 defaultOptions: defaultOptions,
5163 Position: Position,
5164 SourceLocation: SourceLocation,
5165 getLineInfo: getLineInfo,
5166 Node: Node,
5167 TokenType: TokenType,
5168 tokTypes: types,
5169 keywordTypes: keywords$1,
5170 TokContext: TokContext,
5171 tokContexts: types$1,
5172 isIdentifierChar: isIdentifierChar,
5173 isIdentifierStart: isIdentifierStart,
5174 Token: Token,
5175 isNewLine: isNewLine,
5176 lineBreak: lineBreak,
5177 lineBreakG: lineBreakG,
5178 nonASCIIwhitespace: nonASCIIwhitespace
5179};
5180
5181// The main exported interface (under `self.acorn` when in the
5182// browser) is a `parse` function that takes a code string and
5183// returns an abstract syntax tree as specified by [Mozilla parser
5184// API][api].
5185//
5186// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
5187
5188function parse(input, options) {
5189 return Parser.parse(input, options)
5190}
5191
5192// This function tries to parse a single expression at a given
5193// offset in a string. Useful for parsing mixed-language formats
5194// that embed JavaScript expressions.
5195
5196function parseExpressionAt(input, pos, options) {
5197 return Parser.parseExpressionAt(input, pos, options)
5198}
5199
5200function walk(ast, { enter, leave }) {
5201 return visit(ast, null, enter, leave);
5202}
5203
5204let should_skip = false;
5205let should_remove = false;
5206let replacement = null;
5207const context = {
5208 skip: () => should_skip = true,
5209 remove: () => should_remove = true,
5210 replace: (node) => replacement = node
5211};
5212
5213function replace(parent, prop, index, node) {
5214 if (parent) {
5215 if (index !== null) {
5216 parent[prop][index] = node;
5217 } else {
5218 parent[prop] = node;
5219 }
5220 }
5221}
5222
5223function remove(parent, prop, index) {
5224 if (parent) {
5225 if (index !== null) {
5226 parent[prop].splice(index, 1);
5227 } else {
5228 delete parent[prop];
5229 }
5230 }
5231}
5232
5233function visit(
5234 node,
5235 parent,
5236 enter,
5237 leave,
5238 prop,
5239 index
5240) {
5241 if (node) {
5242 if (enter) {
5243 const _should_skip = should_skip;
5244 const _should_remove = should_remove;
5245 const _replacement = replacement;
5246 should_skip = false;
5247 should_remove = false;
5248 replacement = null;
5249
5250 enter.call(context, node, parent, prop, index);
5251
5252 if (replacement) {
5253 node = replacement;
5254 replace(parent, prop, index, node);
5255 }
5256
5257 if (should_remove) {
5258 remove(parent, prop, index);
5259 }
5260
5261 const skipped = should_skip;
5262 const removed = should_remove;
5263
5264 should_skip = _should_skip;
5265 should_remove = _should_remove;
5266 replacement = _replacement;
5267
5268 if (skipped) return node;
5269 if (removed) return null;
5270 }
5271
5272 for (const key in node) {
5273 const value = (node )[key];
5274
5275 if (typeof value !== 'object') {
5276 continue;
5277 }
5278
5279 else if (Array.isArray(value)) {
5280 for (let j = 0, k = 0; j < value.length; j += 1, k += 1) {
5281 if (value[j] !== null && typeof value[j].type === 'string') {
5282 if (!visit(value[j], node, enter, leave, key, k)) {
5283 // removed
5284 j--;
5285 }
5286 }
5287 }
5288 }
5289
5290 else if (value !== null && typeof value.type === 'string') {
5291 visit(value, node, enter, leave, key, null);
5292 }
5293 }
5294
5295 if (leave) {
5296 const _replacement = replacement;
5297 const _should_remove = should_remove;
5298 replacement = null;
5299 should_remove = false;
5300
5301 leave.call(context, node, parent, prop, index);
5302
5303 if (replacement) {
5304 node = replacement;
5305 replace(parent, prop, index, node);
5306 }
5307
5308 if (should_remove) {
5309 remove(parent, prop, index);
5310 }
5311
5312 const removed = should_remove;
5313
5314 replacement = _replacement;
5315 should_remove = _should_remove;
5316
5317 if (removed) return null;
5318 }
5319 }
5320
5321 return node;
5322}
5323
5324function isReference(node, parent) {
5325 if (node.type === 'MemberExpression') {
5326 return !node.computed && isReference(node.object, node);
5327 }
5328 if (node.type === 'Identifier') {
5329 if (!parent)
5330 return true;
5331 switch (parent.type) {
5332 // disregard `bar` in `foo.bar`
5333 case 'MemberExpression': return parent.computed || node === parent.object;
5334 // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
5335 case 'MethodDefinition': return parent.computed;
5336 // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
5337 case 'FieldDefinition': return parent.computed || node === parent.value;
5338 // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
5339 case 'Property': return parent.computed || node === parent.value;
5340 // disregard the `bar` in `export { foo as bar }` or
5341 // the foo in `import { foo as bar }`
5342 case 'ExportSpecifier':
5343 case 'ImportSpecifier': return node === parent.local;
5344 // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
5345 case 'LabeledStatement':
5346 case 'BreakStatement':
5347 case 'ContinueStatement': return false;
5348 default: return true;
5349 }
5350 }
5351 return false;
5352}
5353
5354function analyze(expression) {
5355 const map = new WeakMap();
5356
5357 let scope = new Scope$1(null, false);
5358
5359 walk(expression, {
5360 enter(node, parent) {
5361 if (node.type === 'ImportDeclaration') {
5362 node.specifiers.forEach((specifier) => {
5363 scope.declarations.set(specifier.local.name, specifier);
5364 });
5365 } else if (/(Function(Declaration|Expression)|ArrowFunctionExpression)/.test(node.type)) {
5366 if (node.type === 'FunctionDeclaration') {
5367 scope.declarations.set(node.id.name, node);
5368 map.set(node, scope = new Scope$1(scope, false));
5369 } else {
5370 map.set(node, scope = new Scope$1(scope, false));
5371 if (node.type === 'FunctionExpression' && node.id) scope.declarations.set(node.id.name, node);
5372 }
5373
5374 node.params.forEach((param) => {
5375 extract_names(param).forEach(name => {
5376 scope.declarations.set(name, node);
5377 });
5378 });
5379 } else if (/For(?:In|Of)?Statement/.test(node.type)) {
5380 map.set(node, scope = new Scope$1(scope, true));
5381 } else if (node.type === 'BlockStatement') {
5382 map.set(node, scope = new Scope$1(scope, true));
5383 } else if (/(Class|Variable)Declaration/.test(node.type)) {
5384 scope.add_declaration(node);
5385 } else if (node.type === 'CatchClause') {
5386 map.set(node, scope = new Scope$1(scope, true));
5387
5388 if (node.param) {
5389 extract_names(node.param).forEach(name => {
5390 scope.declarations.set(name, node.param);
5391 });
5392 }
5393 }
5394 },
5395
5396 leave(node) {
5397 if (map.has(node)) {
5398 scope = scope.parent;
5399 }
5400 }
5401 });
5402
5403 const globals = new Map();
5404
5405 walk(expression, {
5406 enter(node, parent) {
5407 if (map.has(node)) scope = map.get(node);
5408
5409 if (node.type === 'Identifier' && isReference(node, parent)) {
5410 const owner = scope.find_owner(node.name);
5411 if (!owner) globals.set(node.name, node);
5412
5413 add_reference(scope, node.name);
5414 }
5415 },
5416 leave(node) {
5417 if (map.has(node)) {
5418 scope = scope.parent;
5419 }
5420 }
5421 });
5422
5423 return { map, scope, globals };
5424}
5425
5426function add_reference(scope, name) {
5427 scope.references.add(name);
5428 if (scope.parent) add_reference(scope.parent, name);
5429}
5430
5431class Scope$1 {
5432
5433
5434 __init() {this.declarations = new Map();}
5435 __init2() {this.initialised_declarations = new Set();}
5436 __init3() {this.references = new Set();}
5437
5438 constructor(parent, block) {Scope$1.prototype.__init.call(this);Scope$1.prototype.__init2.call(this);Scope$1.prototype.__init3.call(this);
5439 this.parent = parent;
5440 this.block = block;
5441 }
5442
5443
5444 add_declaration(node) {
5445 if (node.type === 'VariableDeclaration') {
5446 if (node.kind === 'var' && this.block && this.parent) {
5447 this.parent.add_declaration(node);
5448 } else if (node.type === 'VariableDeclaration') {
5449 node.declarations.forEach((declarator) => {
5450 extract_names(declarator.id).forEach(name => {
5451 this.declarations.set(name, node);
5452 if (declarator.init) this.initialised_declarations.add(name);
5453 });
5454 });
5455 }
5456 } else {
5457 this.declarations.set(node.id.name, node);
5458 }
5459 }
5460
5461 find_owner(name) {
5462 if (this.declarations.has(name)) return this;
5463 return this.parent && this.parent.find_owner(name);
5464 }
5465
5466 has(name) {
5467 return (
5468 this.declarations.has(name) || (this.parent && this.parent.has(name))
5469 );
5470 }
5471}
5472
5473function extract_names(param) {
5474 return extract_identifiers(param).map(node => node.name);
5475}
5476
5477function extract_identifiers(param) {
5478 const nodes = [];
5479 extractors[param.type] && extractors[param.type](nodes, param);
5480 return nodes;
5481}
5482
5483const extractors = {
5484 Identifier(nodes, param) {
5485 nodes.push(param);
5486 },
5487
5488 MemberExpression(nodes, param) {
5489 let object = param;
5490 while (object.type === 'MemberExpression') object = object.object;
5491 nodes.push(object);
5492 },
5493
5494 ObjectPattern(nodes, param) {
5495 param.properties.forEach((prop) => {
5496 if (prop.type === 'RestElement') {
5497 nodes.push(prop.argument);
5498 } else {
5499 extractors[prop.value.type](nodes, prop.value);
5500 }
5501 });
5502 },
5503
5504 ArrayPattern(nodes, param) {
5505 param.elements.forEach((element) => {
5506 if (element) extractors[element.type](nodes, element);
5507 });
5508 },
5509
5510 RestElement(nodes, param) {
5511 extractors[param.argument.type](nodes, param.argument);
5512 },
5513
5514 AssignmentPattern(nodes, param) {
5515 extractors[param.left.type](nodes, param.left);
5516 }
5517};
5518
5519var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
5520function encode(decoded) {
5521 var sourceFileIndex = 0; // second field
5522 var sourceCodeLine = 0; // third field
5523 var sourceCodeColumn = 0; // fourth field
5524 var nameIndex = 0; // fifth field
5525 var mappings = '';
5526 for (var i = 0; i < decoded.length; i++) {
5527 var line = decoded[i];
5528 if (i > 0)
5529 mappings += ';';
5530 if (line.length === 0)
5531 continue;
5532 var generatedCodeColumn = 0; // first field
5533 var lineMappings = [];
5534 for (var _i = 0, line_1 = line; _i < line_1.length; _i++) {
5535 var segment = line_1[_i];
5536 var segmentMappings = encodeInteger(segment[0] - generatedCodeColumn);
5537 generatedCodeColumn = segment[0];
5538 if (segment.length > 1) {
5539 segmentMappings +=
5540 encodeInteger(segment[1] - sourceFileIndex) +
5541 encodeInteger(segment[2] - sourceCodeLine) +
5542 encodeInteger(segment[3] - sourceCodeColumn);
5543 sourceFileIndex = segment[1];
5544 sourceCodeLine = segment[2];
5545 sourceCodeColumn = segment[3];
5546 }
5547 if (segment.length === 5) {
5548 segmentMappings += encodeInteger(segment[4] - nameIndex);
5549 nameIndex = segment[4];
5550 }
5551 lineMappings.push(segmentMappings);
5552 }
5553 mappings += lineMappings.join(',');
5554 }
5555 return mappings;
5556}
5557function encodeInteger(num) {
5558 var result = '';
5559 num = num < 0 ? (-num << 1) | 1 : num << 1;
5560 do {
5561 var clamped = num & 31;
5562 num >>>= 5;
5563 if (num > 0) {
5564 clamped |= 32;
5565 }
5566 result += chars[clamped];
5567 } while (num > 0);
5568 return result;
5569}
5570
5571// generate an ID that is, to all intents and purposes, unique
5572const id = (Math.round(Math.random() * 1e20)).toString(36);
5573const re = new RegExp(`_${id}_(?:(\\d+)|(AT)|(HASH))_(\\w+)?`, 'g');
5574
5575const get_comment_handlers = (comments, raw) => ({
5576
5577 // pass to acorn options
5578 onComment: (block, value, start, end) => {
5579 if (block && /\n/.test(value)) {
5580 let a = start;
5581 while (a > 0 && raw[a - 1] !== '\n') a -= 1;
5582
5583 let b = a;
5584 while (/[ \t]/.test(raw[b])) b += 1;
5585
5586 const indentation = raw.slice(a, b);
5587 value = value.replace(new RegExp(`^${indentation}`, 'gm'), '');
5588 }
5589
5590 comments.push({ type: block ? 'Block' : 'Line', value, start, end });
5591 },
5592
5593 // pass to estree-walker options
5594 enter(node) {
5595 let comment;
5596
5597 while (comments[0] && comments[0].start < (node ).start) {
5598 comment = comments.shift();
5599
5600 comment.value = comment.value.replace(re, (match, id, at, hash, value) => {
5601 if (hash) return `#${value}`;
5602 if (at) return `@${value}`;
5603
5604 return match;
5605 });
5606
5607 const next = comments[0] || node;
5608 (comment ).has_trailing_newline = (
5609 comment.type === 'Line' ||
5610 /\n/.test(raw.slice(comment.end, (next ).start))
5611 );
5612
5613 (node.leadingComments || (node.leadingComments = [])).push(comment);
5614 }
5615 },
5616 leave(node) {
5617 if (comments[0]) {
5618 const slice = raw.slice((node ).end, comments[0].start);
5619
5620 if (/^[,) \t]*$/.test(slice)) {
5621 node.trailingComments = [comments.shift()];
5622 }
5623 }
5624 }
5625
5626});
5627
5628function handle(node, state) {
5629 const handler = handlers[node.type];
5630
5631 if (!handler) {
5632 throw new Error(`Not implemented ${node.type}`);
5633 }
5634
5635 const result = handler(node, state);
5636
5637 if (node.leadingComments) {
5638 result.unshift(c(node.leadingComments.map(comment => comment.type === 'Block'
5639 ? `/*${comment.value}*/${(comment ).has_trailing_newline ? `\n${state.indent}` : ` `}`
5640 : `//${comment.value}${(comment ).has_trailing_newline ? `\n${state.indent}` : ` `}`).join(``)));
5641 }
5642
5643 if (node.trailingComments) {
5644 state.comments.push(node.trailingComments[0]); // there is only ever one
5645 }
5646
5647 return result;
5648}
5649
5650function c(content, node) {
5651 return {
5652 content,
5653 loc: node && node.loc,
5654 has_newline: /\n/.test(content)
5655 };
5656}
5657
5658const OPERATOR_PRECEDENCE = {
5659 '||': 2,
5660 '&&': 3,
5661 '??': 4,
5662 '|': 5,
5663 '^': 6,
5664 '&': 7,
5665 '==': 8,
5666 '!=': 8,
5667 '===': 8,
5668 '!==': 8,
5669 '<': 9,
5670 '>': 9,
5671 '<=': 9,
5672 '>=': 9,
5673 in: 9,
5674 instanceof: 9,
5675 '<<': 10,
5676 '>>': 10,
5677 '>>>': 10,
5678 '+': 11,
5679 '-': 11,
5680 '*': 12,
5681 '%': 12,
5682 '/': 12,
5683 '**': 13,
5684};
5685
5686const EXPRESSIONS_PRECEDENCE = {
5687 ArrayExpression: 20,
5688 TaggedTemplateExpression: 20,
5689 ThisExpression: 20,
5690 Identifier: 20,
5691 Literal: 18,
5692 TemplateLiteral: 20,
5693 Super: 20,
5694 SequenceExpression: 20,
5695 MemberExpression: 19,
5696 CallExpression: 19,
5697 NewExpression: 19,
5698 AwaitExpression: 17,
5699 ClassExpression: 17,
5700 FunctionExpression: 17,
5701 ObjectExpression: 17,
5702 UpdateExpression: 16,
5703 UnaryExpression: 15,
5704 BinaryExpression: 14,
5705 LogicalExpression: 13,
5706 ConditionalExpression: 4,
5707 ArrowFunctionExpression: 3,
5708 AssignmentExpression: 3,
5709 YieldExpression: 2,
5710 RestElement: 1
5711};
5712
5713function needs_parens(node, parent, is_right) {
5714 // special case where logical expressions and coalesce expressions cannot be mixed,
5715 // either of them need to be wrapped with parentheses
5716 if (
5717 node.type === 'LogicalExpression' &&
5718 parent.type === 'LogicalExpression' &&
5719 ((parent.operator === '??' && node.operator !== '??') ||
5720 (parent.operator !== '??' && node.operator === '??'))
5721 ) {
5722 return true;
5723 }
5724
5725 const precedence = EXPRESSIONS_PRECEDENCE[node.type];
5726 const parent_precedence = EXPRESSIONS_PRECEDENCE[parent.type];
5727
5728 if (precedence !== parent_precedence) {
5729 // Different node types
5730 return (
5731 (!is_right &&
5732 precedence === 15 &&
5733 parent_precedence === 14 &&
5734 parent.operator === '**') ||
5735 precedence < parent_precedence
5736 );
5737 }
5738
5739 if (precedence !== 13 && precedence !== 14) {
5740 // Not a `LogicalExpression` or `BinaryExpression`
5741 return false;
5742 }
5743
5744 if ((node ).operator === '**' && parent.operator === '**') {
5745 // Exponentiation operator has right-to-left associativity
5746 return !is_right;
5747 }
5748
5749 if (is_right) {
5750 // Parenthesis are used if both operators have the same precedence
5751 return (
5752 OPERATOR_PRECEDENCE[(node ).operator] <=
5753 OPERATOR_PRECEDENCE[parent.operator]
5754 );
5755 }
5756
5757 return (
5758 OPERATOR_PRECEDENCE[(node ).operator] <
5759 OPERATOR_PRECEDENCE[parent.operator]
5760 );
5761}
5762
5763function has_call_expression(node) {
5764 while (node) {
5765 if (node.type[0] === 'CallExpression') {
5766 return true;
5767 } else if (node.type === 'MemberExpression') {
5768 node = node.object;
5769 } else {
5770 return false;
5771 }
5772 }
5773}
5774
5775const has_newline = (chunks) => {
5776 for (let i = 0; i < chunks.length; i += 1) {
5777 if (chunks[i].has_newline) return true;
5778 }
5779 return false;
5780};
5781
5782const get_length = (chunks) => {
5783 let total = 0;
5784 for (let i = 0; i < chunks.length; i += 1) {
5785 total += chunks[i].content.length;
5786 }
5787 return total;
5788};
5789
5790const sum = (a, b) => a + b;
5791
5792const join = (nodes, separator) => {
5793 if (nodes.length === 0) return [];
5794 const joined = [...nodes[0]];
5795 for (let i = 1; i < nodes.length; i += 1) {
5796 joined.push(separator, ...nodes[i] );
5797 }
5798 return joined;
5799};
5800
5801const scoped = (fn) => {
5802 return (node, state) => {
5803 return fn(node, {
5804 ...state,
5805 scope: state.scope_map.get(node)
5806 });
5807 };
5808};
5809
5810const deconflict = (name, names) => {
5811 const original = name;
5812 let i = 1;
5813
5814 while (names.has(name)) {
5815 name = `${original}$${i++}`;
5816 }
5817
5818 return name;
5819};
5820
5821const handle_body = (nodes, state) => {
5822 const chunks = [];
5823
5824 const body = nodes.map(statement => {
5825 const chunks = handle(statement, {
5826 ...state,
5827 indent: state.indent
5828 });
5829
5830 let add_newline = false;
5831
5832 while (state.comments.length) {
5833 const comment = state.comments.shift();
5834 const prefix = add_newline ? `\n${state.indent}` : ` `;
5835
5836 chunks.push(c(comment.type === 'Block'
5837 ? `${prefix}/*${comment.value}*/`
5838 : `${prefix}//${comment.value}`));
5839
5840 add_newline = (comment.type === 'Line');
5841 }
5842
5843 return chunks;
5844 });
5845
5846 let needed_padding = false;
5847
5848 for (let i = 0; i < body.length; i += 1) {
5849 const needs_padding = has_newline(body[i]);
5850
5851 if (i > 0) {
5852 chunks.push(
5853 c(needs_padding || needed_padding ? `\n\n${state.indent}` : `\n${state.indent}`)
5854 );
5855 }
5856
5857 chunks.push(
5858 ...body[i]
5859 );
5860
5861 needed_padding = needs_padding;
5862 }
5863
5864 return chunks;
5865};
5866
5867const handle_var_declaration = (node, state) => {
5868 const chunks = [c(`${node.kind} `)];
5869
5870 const declarators = node.declarations.map(d => handle(d, {
5871 ...state,
5872 indent: state.indent + (node.declarations.length === 1 ? '' : '\t')
5873 }));
5874
5875 const multiple_lines = (
5876 declarators.some(has_newline) ||
5877 (declarators.map(get_length).reduce(sum, 0) + (state.indent.length + declarators.length - 1) * 2) > 80
5878 );
5879
5880 const separator = c(multiple_lines ? `,\n${state.indent}\t` : ', ');
5881
5882 if (multiple_lines) {
5883 chunks.push(...join(declarators, separator));
5884 } else {
5885 chunks.push(
5886 ...join(declarators, separator)
5887 );
5888 }
5889
5890 return chunks;
5891};
5892
5893const handlers = {
5894 Program(node, state) {
5895 return handle_body(node.body, state);
5896 },
5897
5898 BlockStatement: scoped((node, state) => {
5899 return [
5900 c(`{\n${state.indent}\t`),
5901 ...handle_body(node.body, { ...state, indent: state.indent + '\t' }),
5902 c(`\n${state.indent}}`)
5903 ];
5904 }),
5905
5906 EmptyStatement(node, state) {
5907 return [];
5908 },
5909
5910 ParenthesizedExpression(node, state) {
5911 return handle(node.expression, state);
5912 },
5913
5914 ExpressionStatement(node, state) {
5915 if (
5916 node.expression.type === 'AssignmentExpression' &&
5917 node.expression.left.type === 'ObjectPattern'
5918 ) {
5919 // is an AssignmentExpression to an ObjectPattern
5920 return [
5921 c('('),
5922 ...handle(node.expression, state),
5923 c(');')
5924 ];
5925 }
5926
5927 return [
5928 ...handle(node.expression, state),
5929 c(';')
5930 ];
5931 },
5932
5933 IfStatement(node, state) {
5934 const chunks = [
5935 c('if ('),
5936 ...handle(node.test, state),
5937 c(') '),
5938 ...handle(node.consequent, state)
5939 ];
5940
5941 if (node.alternate) {
5942 chunks.push(
5943 c(' else '),
5944 ...handle(node.alternate, state)
5945 );
5946 }
5947
5948 return chunks;
5949 },
5950
5951 LabeledStatement(node, state) {
5952 return [
5953 ...handle(node.label, state),
5954 c(': '),
5955 ...handle(node.body, state)
5956 ];
5957 },
5958
5959 BreakStatement(node, state) {
5960 return node.label
5961 ? [c('break '), ...handle(node.label, state), c(';')]
5962 : [c('break;')];
5963 },
5964
5965 ContinueStatement(node, state) {
5966 return node.label
5967 ? [c('continue '), ...handle(node.label, state), c(';')]
5968 : [c('continue;')];
5969 },
5970
5971 WithStatement(node, state) {
5972 return [
5973 c('with ('),
5974 ...handle(node.object, state),
5975 c(') '),
5976 ...handle(node.body, state)
5977 ];
5978 },
5979
5980 SwitchStatement(node, state) {
5981 const chunks = [
5982 c('switch ('),
5983 ...handle(node.discriminant, state),
5984 c(') {')
5985 ];
5986
5987 node.cases.forEach(block => {
5988 if (block.test) {
5989 chunks.push(
5990 c(`\n${state.indent}\tcase `),
5991 ...handle(block.test, { ...state, indent: `${state.indent}\t` }),
5992 c(':')
5993 );
5994 } else {
5995 chunks.push(c(`\n${state.indent}\tdefault:`));
5996 }
5997
5998 block.consequent.forEach(statement => {
5999 chunks.push(
6000 c(`\n${state.indent}\t\t`),
6001 ...handle(statement, { ...state, indent: `${state.indent}\t\t` })
6002 );
6003 });
6004 });
6005
6006 chunks.push(c(`\n${state.indent}}`));
6007
6008 return chunks;
6009 },
6010
6011 ReturnStatement(node, state) {
6012 if (node.argument) {
6013 return [
6014 c('return '),
6015 ...handle(node.argument, state),
6016 c(';')
6017 ];
6018 } else {
6019 return [c('return;')];
6020 }
6021 },
6022
6023 ThrowStatement(node, state) {
6024 return [
6025 c('throw '),
6026 ...handle(node.argument, state),
6027 c(';')
6028 ];
6029 },
6030
6031 TryStatement(node, state) {
6032 const chunks = [
6033 c('try '),
6034 ...handle(node.block, state)
6035 ];
6036
6037 if (node.handler) {
6038 if (node.handler.param) {
6039 chunks.push(
6040 c(' catch('),
6041 ...handle(node.handler.param, state),
6042 c(') ')
6043 );
6044 } else {
6045 chunks.push(c(' catch '));
6046 }
6047
6048 chunks.push(...handle(node.handler.body, state));
6049 }
6050
6051 if (node.finalizer) {
6052 chunks.push(c(' finally '), ...handle(node.finalizer, state));
6053 }
6054
6055 return chunks;
6056 },
6057
6058 WhileStatement(node, state) {
6059 return [
6060 c('while ('),
6061 ...handle(node.test, state),
6062 c(') '),
6063 ...handle(node.body, state)
6064 ];
6065 },
6066
6067 DoWhileStatement(node, state) {
6068 return [
6069 c('do '),
6070 ...handle(node.body, state),
6071 c(' while ('),
6072 ...handle(node.test, state),
6073 c(');')
6074 ];
6075 },
6076
6077 ForStatement: scoped((node, state) => {
6078 const chunks = [c('for (')];
6079
6080 if (node.init) {
6081 if ((node.init ).type === 'VariableDeclaration') {
6082 chunks.push(...handle_var_declaration(node.init , state));
6083 } else {
6084 chunks.push(...handle(node.init, state));
6085 }
6086 }
6087
6088 chunks.push(c('; '));
6089 if (node.test) chunks.push(...handle(node.test, state));
6090 chunks.push(c('; '));
6091 if (node.update) chunks.push(...handle(node.update, state));
6092
6093 chunks.push(
6094 c(') '),
6095 ...handle(node.body, state)
6096 );
6097
6098 return chunks;
6099 }),
6100
6101 ForInStatement: scoped((node, state) => {
6102 const chunks = [
6103 c(`for ${(node ).await ? 'await ' : ''}(`)
6104 ];
6105
6106 if ((node.left ).type === 'VariableDeclaration') {
6107 chunks.push(...handle_var_declaration(node.left , state));
6108 } else {
6109 chunks.push(...handle(node.left, state));
6110 }
6111
6112 chunks.push(
6113 c(node.type === 'ForInStatement' ? ` in ` : ` of `),
6114 ...handle(node.right, state),
6115 c(') '),
6116 ...handle(node.body, state)
6117 );
6118
6119 return chunks;
6120 }),
6121
6122 DebuggerStatement(node, state) {
6123 return [c('debugger', node), c(';')];
6124 },
6125
6126 FunctionDeclaration: scoped((node, state) => {
6127 const chunks = [];
6128
6129 if (node.async) chunks.push(c('async '));
6130 chunks.push(c(node.generator ? 'function* ' : 'function '));
6131 if (node.id) chunks.push(...handle(node.id, state));
6132 chunks.push(c('('));
6133
6134 const params = node.params.map(p => handle(p, {
6135 ...state,
6136 indent: state.indent + '\t'
6137 }));
6138
6139 const multiple_lines = (
6140 params.some(has_newline) ||
6141 (params.map(get_length).reduce(sum, 0) + (state.indent.length + params.length - 1) * 2) > 80
6142 );
6143
6144 const separator = c(multiple_lines ? `,\n${state.indent}` : ', ');
6145
6146 if (multiple_lines) {
6147 chunks.push(
6148 c(`\n${state.indent}\t`),
6149 ...join(params, separator),
6150 c(`\n${state.indent}`)
6151 );
6152 } else {
6153 chunks.push(
6154 ...join(params, separator)
6155 );
6156 }
6157
6158 chunks.push(
6159 c(') '),
6160 ...handle(node.body, state)
6161 );
6162
6163 return chunks;
6164 }),
6165
6166 VariableDeclaration(node, state) {
6167 return handle_var_declaration(node, state).concat(c(';'));
6168 },
6169
6170 VariableDeclarator(node, state) {
6171 if (node.init) {
6172 return [
6173 ...handle(node.id, state),
6174 c(' = '),
6175 ...handle(node.init, state)
6176 ];
6177 } else {
6178 return handle(node.id, state);
6179 }
6180 },
6181
6182 ClassDeclaration(node, state) {
6183 const chunks = [c('class ')];
6184
6185 if (node.id) chunks.push(...handle(node.id, state), c(' '));
6186
6187 if (node.superClass) {
6188 chunks.push(
6189 c('extends '),
6190 ...handle(node.superClass, state),
6191 c(' ')
6192 );
6193 }
6194
6195 chunks.push(...handle(node.body, state));
6196
6197 return chunks;
6198 },
6199
6200 ImportDeclaration(node, state) {
6201 const chunks = [c('import ')];
6202
6203 const { length } = node.specifiers;
6204 const source = handle(node.source, state);
6205
6206 if (length > 0) {
6207 let i = 0;
6208
6209 while (i < length) {
6210 if (i > 0) {
6211 chunks.push(c(', '));
6212 }
6213
6214 const specifier = node.specifiers[i];
6215
6216 if (specifier.type === 'ImportDefaultSpecifier') {
6217 chunks.push(c(specifier.local.name, specifier));
6218 i += 1;
6219 } else if (specifier.type === 'ImportNamespaceSpecifier') {
6220 chunks.push(c('* as ' + specifier.local.name, specifier));
6221 i += 1;
6222 } else {
6223 break;
6224 }
6225 }
6226
6227 if (i < length) {
6228 // we have named specifiers
6229 const specifiers = node.specifiers.slice(i).map((specifier) => {
6230 const name = handle(specifier.imported, state)[0];
6231 const as = handle(specifier.local, state)[0];
6232
6233 if (name.content === as.content) {
6234 return [as];
6235 }
6236
6237 return [name, c(' as '), as];
6238 });
6239
6240 const width = get_length(chunks) + specifiers.map(get_length).reduce(sum, 0) + (2 * specifiers.length) + 6 + get_length(source);
6241
6242 if (width > 80) {
6243 chunks.push(
6244 c(`{\n\t`),
6245 ...join(specifiers, c(',\n\t')),
6246 c('\n}')
6247 );
6248 } else {
6249 chunks.push(
6250 c(`{ `),
6251 ...join(specifiers, c(', ')),
6252 c(' }')
6253 );
6254 }
6255 }
6256
6257 chunks.push(c(' from '));
6258 }
6259
6260 chunks.push(
6261 ...source,
6262 c(';')
6263 );
6264
6265 return chunks;
6266 },
6267
6268 ImportExpression(node, state) {
6269 return [c('import('), ...handle(node.source, state), c(')')];
6270 },
6271
6272 ExportDefaultDeclaration(node, state) {
6273 const chunks = [
6274 c(`export default `),
6275 ...handle(node.declaration, state)
6276 ];
6277
6278 if (node.declaration.type !== 'FunctionDeclaration') {
6279 chunks.push(c(';'));
6280 }
6281
6282 return chunks;
6283 },
6284
6285 ExportNamedDeclaration(node, state) {
6286 const chunks = [c('export ')];
6287
6288 if (node.declaration) {
6289 chunks.push(...handle(node.declaration, state));
6290 } else {
6291 const specifiers = node.specifiers.map(specifier => {
6292 const name = handle(specifier.local, state)[0];
6293 const as = handle(specifier.exported, state)[0];
6294
6295 if (name.content === as.content) {
6296 return [name];
6297 }
6298
6299 return [name, c(' as '), as];
6300 });
6301
6302 const width = 7 + specifiers.map(get_length).reduce(sum, 0) + 2 * specifiers.length;
6303
6304 if (width > 80) {
6305 chunks.push(
6306 c('{\n\t'),
6307 ...join(specifiers, c(',\n\t')),
6308 c('\n}')
6309 );
6310 } else {
6311 chunks.push(
6312 c('{ '),
6313 ...join(specifiers, c(', ')),
6314 c(' }')
6315 );
6316 }
6317
6318 if (node.source) {
6319 chunks.push(
6320 c(' from '),
6321 ...handle(node.source, state)
6322 );
6323 }
6324 }
6325
6326 chunks.push(c(';'));
6327
6328 return chunks;
6329 },
6330
6331 ExportAllDeclaration(node, state) {
6332 return [
6333 c(`export * from `),
6334 ...handle(node.source, state),
6335 c(`;`)
6336 ];
6337 },
6338
6339 MethodDefinition(node, state) {
6340 const chunks = [];
6341
6342 if (node.static) {
6343 chunks.push(c('static '));
6344 }
6345
6346 if (node.kind === 'get' || node.kind === 'set') {
6347 // Getter or setter
6348 chunks.push(c(node.kind + ' '));
6349 }
6350
6351 if (node.value.async) {
6352 chunks.push(c('async '));
6353 }
6354
6355 if (node.value.generator) {
6356 chunks.push(c('*'));
6357 }
6358
6359 if (node.computed) {
6360 chunks.push(
6361 c('['),
6362 ...handle(node.key, state),
6363 c(']')
6364 );
6365 } else {
6366 chunks.push(...handle(node.key, state));
6367 }
6368
6369 chunks.push(c('('));
6370
6371 const { params } = node.value;
6372 for (let i = 0; i < params.length; i += 1) {
6373 chunks.push(...handle(params[i], state));
6374 if (i < params.length - 1) chunks.push(c(', '));
6375 }
6376
6377 chunks.push(
6378 c(') '),
6379 ...handle(node.value.body, state)
6380 );
6381
6382 return chunks;
6383 },
6384
6385 ArrowFunctionExpression: scoped((node, state) => {
6386 const chunks = [];
6387
6388 if (node.async) chunks.push(c('async '));
6389
6390 if (node.params.length === 1 && node.params[0].type === 'Identifier') {
6391 chunks.push(...handle(node.params[0], state));
6392 } else {
6393 const params = node.params.map(param => handle(param, {
6394 ...state,
6395 indent: state.indent + '\t'
6396 }));
6397
6398 chunks.push(
6399 c('('),
6400 ...join(params, c(', ')),
6401 c(')')
6402 );
6403 }
6404
6405 chunks.push(c(' => '));
6406
6407 if (node.body.type === 'ObjectExpression') {
6408 chunks.push(
6409 c('('),
6410 ...handle(node.body, state),
6411 c(')')
6412 );
6413 } else {
6414 chunks.push(...handle(node.body, state));
6415 }
6416
6417 return chunks;
6418 }),
6419
6420 ThisExpression(node, state) {
6421 return [c('this', node)];
6422 },
6423
6424 Super(node, state) {
6425 return [c('super', node)];
6426 },
6427
6428 RestElement(node, state) {
6429 return [c('...'), ...handle(node.argument, state)];
6430 },
6431
6432 YieldExpression(node, state) {
6433 if (node.argument) {
6434 return [c(node.delegate ? `yield* ` : `yield `), ...handle(node.argument, state)];
6435 }
6436
6437 return [c(node.delegate ? `yield*` : `yield`)];
6438 },
6439
6440 AwaitExpression(node, state) {
6441 if (node.argument) {
6442 const precedence = EXPRESSIONS_PRECEDENCE[node.argument.type];
6443
6444 if (precedence && (precedence < EXPRESSIONS_PRECEDENCE.AwaitExpression)) {
6445 return [c('await ('), ...handle(node.argument, state), c(')')];
6446 } else {
6447 return [c('await '), ...handle(node.argument, state)];
6448 }
6449 }
6450
6451 return [c('await')];
6452 },
6453
6454 TemplateLiteral(node, state) {
6455 const chunks = [c('`')];
6456
6457 const { quasis, expressions } = node;
6458
6459 for (let i = 0; i < expressions.length; i++) {
6460 chunks.push(
6461 c(quasis[i].value.raw),
6462 c('${'),
6463 ...handle(expressions[i], state),
6464 c('}')
6465 );
6466 }
6467
6468 chunks.push(
6469 c(quasis[quasis.length - 1].value.raw),
6470 c('`')
6471 );
6472
6473 return chunks;
6474 },
6475
6476 TaggedTemplateExpression(node, state) {
6477 return handle(node.tag, state).concat(handle(node.quasi, state));
6478 },
6479
6480 ArrayExpression(node, state) {
6481 const chunks = [c('[')];
6482
6483 const elements = [];
6484 let sparse_commas = [];
6485
6486 for (let i = 0; i < node.elements.length; i += 1) {
6487 // can't use map/forEach because of sparse arrays
6488 const element = node.elements[i];
6489 if (element) {
6490 elements.push([...sparse_commas, ...handle(element, {
6491 ...state,
6492 indent: state.indent + '\t'
6493 })]);
6494 sparse_commas = [];
6495 } else {
6496 sparse_commas.push(c(','));
6497 }
6498 }
6499
6500 const multiple_lines = (
6501 elements.some(has_newline) ||
6502 (elements.map(get_length).reduce(sum, 0) + (state.indent.length + elements.length - 1) * 2) > 80
6503 );
6504
6505 if (multiple_lines) {
6506 chunks.push(
6507 c(`\n${state.indent}\t`),
6508 ...join(elements, c(`,\n${state.indent}\t`)),
6509 c(`\n${state.indent}`),
6510 ...sparse_commas
6511 );
6512 } else {
6513 chunks.push(...join(elements, c(', ')), ...sparse_commas);
6514 }
6515
6516 chunks.push(c(']'));
6517
6518 return chunks;
6519 },
6520
6521 ObjectExpression(node, state) {
6522 if (node.properties.length === 0) {
6523 return [c('{}')];
6524 }
6525
6526 let has_inline_comment = false;
6527
6528 const chunks = [];
6529 const separator = c(', ');
6530
6531 node.properties.forEach((p, i) => {
6532 chunks.push(...handle(p, {
6533 ...state,
6534 indent: state.indent + '\t'
6535 }));
6536
6537 if (state.comments.length) {
6538 // TODO generalise this, so it works with ArrayExpressions and other things.
6539 // At present, stuff will just get appended to the closest statement/declaration
6540 chunks.push(c(', '));
6541
6542 while (state.comments.length) {
6543 const comment = state.comments.shift();
6544
6545 chunks.push(c(comment.type === 'Block'
6546 ? `/*${comment.value}*/\n${state.indent}\t`
6547 : `//${comment.value}\n${state.indent}\t`));
6548
6549 if (comment.type === 'Line') {
6550 has_inline_comment = true;
6551 }
6552 }
6553 } else {
6554 if (i < node.properties.length - 1) {
6555 chunks.push(separator);
6556 }
6557 }
6558 });
6559
6560 const multiple_lines = (
6561 has_inline_comment ||
6562 has_newline(chunks) ||
6563 get_length(chunks) > 40
6564 );
6565
6566 if (multiple_lines) {
6567 separator.content = `,\n${state.indent}\t`;
6568 }
6569
6570 return [
6571 c(multiple_lines ? `{\n${state.indent}\t` : `{ `),
6572 ...chunks,
6573 c(multiple_lines ? `\n${state.indent}}` : ` }`)
6574 ];
6575 },
6576
6577 Property(node, state) {
6578 const value = handle(node.value, state);
6579
6580 if (node.key === node.value) {
6581 return value;
6582 }
6583
6584 // special case
6585 if (
6586 !node.computed &&
6587 node.value.type === 'AssignmentPattern' &&
6588 node.value.left.type === 'Identifier' &&
6589 node.value.left.name === (node.key ).name
6590 ) {
6591 return value;
6592 }
6593
6594 if (node.value.type === 'Identifier' && (
6595 (node.key.type === 'Identifier' && node.key.name === value[0].content) ||
6596 (node.key.type === 'Literal' && node.key.value === value[0].content)
6597 )) {
6598 return value;
6599 }
6600
6601 const key = handle(node.key, state);
6602
6603 if (node.value.type === 'FunctionExpression' && !node.value.id) {
6604 state = {
6605 ...state,
6606 scope: state.scope_map.get(node.value)
6607 };
6608
6609 const chunks = node.kind !== 'init'
6610 ? [c(`${node.kind} `)]
6611 : [];
6612
6613 if (node.value.async) {
6614 chunks.push(c('async '));
6615 }
6616 if (node.value.generator) {
6617 chunks.push(c('*'));
6618 }
6619
6620 chunks.push(
6621 ...(node.computed ? [c('['), ...key, c(']')] : key),
6622 c('('),
6623 ...join((node.value ).params.map(param => handle(param, state)), c(', ')),
6624 c(') '),
6625 ...handle((node.value ).body, state)
6626 );
6627
6628 return chunks;
6629 }
6630
6631 if (node.computed) {
6632 return [
6633 c('['),
6634 ...key,
6635 c(']: '),
6636 ...value
6637 ];
6638 }
6639
6640 return [
6641 ...key,
6642 c(': '),
6643 ...value
6644 ];
6645 },
6646
6647 ObjectPattern(node, state) {
6648 const chunks = [c('{ ')];
6649
6650 for (let i = 0; i < node.properties.length; i += 1) {
6651 chunks.push(...handle(node.properties[i], state));
6652 if (i < node.properties.length - 1) chunks.push(c(', '));
6653 }
6654
6655 chunks.push(c(' }'));
6656
6657 return chunks;
6658 },
6659
6660 SequenceExpression(node, state) {
6661 const expressions = node.expressions.map(e => handle(e, state));
6662
6663 return [
6664 c('('),
6665 ...join(expressions, c(', ')),
6666 c(')')
6667 ];
6668 },
6669
6670 UnaryExpression(node, state) {
6671 const chunks = [c(node.operator)];
6672
6673 if (node.operator.length > 1) {
6674 chunks.push(c(' '));
6675 }
6676
6677 if (
6678 EXPRESSIONS_PRECEDENCE[node.argument.type] <
6679 EXPRESSIONS_PRECEDENCE.UnaryExpression
6680 ) {
6681 chunks.push(
6682 c('('),
6683 ...handle(node.argument, state),
6684 c(')')
6685 );
6686 } else {
6687 chunks.push(...handle(node.argument, state));
6688 }
6689
6690 return chunks;
6691 },
6692
6693 UpdateExpression(node, state) {
6694 return node.prefix
6695 ? [c(node.operator), ...handle(node.argument, state)]
6696 : [...handle(node.argument, state), c(node.operator)];
6697 },
6698
6699 AssignmentExpression(node, state) {
6700 return [
6701 ...handle(node.left, state),
6702 c(` ${node.operator || '='} `),
6703 ...handle(node.right, state)
6704 ];
6705 },
6706
6707 BinaryExpression(node, state) {
6708 const chunks = [];
6709
6710 // TODO
6711 // const is_in = node.operator === 'in';
6712 // if (is_in) {
6713 // // Avoids confusion in `for` loops initializers
6714 // chunks.push(c('('));
6715 // }
6716
6717 if (needs_parens(node.left, node, false)) {
6718 chunks.push(
6719 c('('),
6720 ...handle(node.left, state),
6721 c(')')
6722 );
6723 } else {
6724 chunks.push(...handle(node.left, state));
6725 }
6726
6727 chunks.push(c(` ${node.operator} `));
6728
6729 if (needs_parens(node.right, node, true)) {
6730 chunks.push(
6731 c('('),
6732 ...handle(node.right, state),
6733 c(')')
6734 );
6735 } else {
6736 chunks.push(...handle(node.right, state));
6737 }
6738
6739 return chunks;
6740 },
6741
6742 ConditionalExpression(node, state) {
6743 const chunks = [];
6744
6745 if (
6746 EXPRESSIONS_PRECEDENCE[node.test.type] >
6747 EXPRESSIONS_PRECEDENCE.ConditionalExpression
6748 ) {
6749 chunks.push(...handle(node.test, state));
6750 } else {
6751 chunks.push(
6752 c('('),
6753 ...handle(node.test, state),
6754 c(')')
6755 );
6756 }
6757
6758 const child_state = { ...state, indent: state.indent + '\t' };
6759
6760 const consequent = handle(node.consequent, child_state);
6761 const alternate = handle(node.alternate, child_state);
6762
6763 const multiple_lines = (
6764 has_newline(consequent) || has_newline(alternate) ||
6765 get_length(chunks) + get_length(consequent) + get_length(alternate) > 50
6766 );
6767
6768 if (multiple_lines) {
6769 chunks.push(
6770 c(`\n${state.indent}? `),
6771 ...consequent,
6772 c(`\n${state.indent}: `),
6773 ...alternate
6774 );
6775 } else {
6776 chunks.push(
6777 c(` ? `),
6778 ...consequent,
6779 c(` : `),
6780 ...alternate
6781 );
6782 }
6783
6784 return chunks;
6785 },
6786
6787 NewExpression(node, state) {
6788 const chunks = [c('new ')];
6789
6790 if (
6791 EXPRESSIONS_PRECEDENCE[node.callee.type] <
6792 EXPRESSIONS_PRECEDENCE.CallExpression || has_call_expression(node.callee)
6793 ) {
6794 chunks.push(
6795 c('('),
6796 ...handle(node.callee, state),
6797 c(')')
6798 );
6799 } else {
6800 chunks.push(...handle(node.callee, state));
6801 }
6802
6803 // TODO this is copied from CallExpression — DRY it out
6804 const args = node.arguments.map(arg => handle(arg, {
6805 ...state,
6806 indent: state.indent + '\t'
6807 }));
6808
6809 const separator = args.some(has_newline) // TODO or length exceeds 80
6810 ? c(',\n' + state.indent)
6811 : c(', ');
6812
6813 chunks.push(
6814 c('('),
6815 ...join(args, separator) ,
6816 c(')')
6817 );
6818
6819 return chunks;
6820 },
6821
6822 ChainExpression(node, state) {
6823 return handle(node.expression, state);
6824 },
6825
6826 CallExpression(node, state) {
6827 const chunks = [];
6828
6829 if (
6830 EXPRESSIONS_PRECEDENCE[node.callee.type] <
6831 EXPRESSIONS_PRECEDENCE.CallExpression
6832 ) {
6833 chunks.push(
6834 c('('),
6835 ...handle(node.callee, state),
6836 c(')')
6837 );
6838 } else {
6839 chunks.push(...handle(node.callee, state));
6840 }
6841
6842 if ((node ).optional) {
6843 chunks.push(c('?.'));
6844 }
6845
6846 const args = node.arguments.map(arg => handle(arg, state));
6847
6848 const multiple_lines = args.slice(0, -1).some(has_newline); // TODO or length exceeds 80
6849
6850 if (multiple_lines) {
6851 // need to handle args again. TODO find alternative approach?
6852 const args = node.arguments.map(arg => handle(arg, {
6853 ...state,
6854 indent: `${state.indent}\t`
6855 }));
6856
6857 chunks.push(
6858 c(`(\n${state.indent}\t`),
6859 ...join(args, c(`,\n${state.indent}\t`)),
6860 c(`\n${state.indent})`)
6861 );
6862 } else {
6863 chunks.push(
6864 c('('),
6865 ...join(args, c(', ')),
6866 c(')')
6867 );
6868 }
6869
6870 return chunks;
6871 },
6872
6873 MemberExpression(node, state) {
6874 const chunks = [];
6875
6876 if (EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression) {
6877 chunks.push(
6878 c('('),
6879 ...handle(node.object, state),
6880 c(')')
6881 );
6882 } else {
6883 chunks.push(...handle(node.object, state));
6884 }
6885
6886 if (node.computed) {
6887 if (node.optional) {
6888 chunks.push(c('?.'));
6889 }
6890 chunks.push(
6891 c('['),
6892 ...handle(node.property, state),
6893 c(']')
6894 );
6895 } else {
6896 chunks.push(
6897 c(node.optional ? '?.' : '.'),
6898 ...handle(node.property, state)
6899 );
6900 }
6901
6902 return chunks;
6903 },
6904
6905 MetaProperty(node, state) {
6906 return [...handle(node.meta, state), c('.'), ...handle(node.property, state)];
6907 },
6908
6909 Identifier(node, state) {
6910 let name = node.name;
6911
6912 if (name[0] === '@') {
6913 name = state.getName(name.slice(1));
6914 } else if (node.name[0] === '#') {
6915 const owner = state.scope.find_owner(node.name);
6916
6917 if (!owner) {
6918 throw new Error(`Could not find owner for node`);
6919 }
6920
6921 if (!state.deconflicted.has(owner)) {
6922 state.deconflicted.set(owner, new Map());
6923 }
6924
6925 const deconflict_map = state.deconflicted.get(owner);
6926
6927 if (!deconflict_map.has(node.name)) {
6928 deconflict_map.set(node.name, deconflict(node.name.slice(1), owner.references));
6929 }
6930
6931 name = deconflict_map.get(node.name);
6932 }
6933
6934 return [c(name, node)];
6935 },
6936
6937 Literal(node, state) {
6938 if (typeof node.value === 'string') {
6939 return [
6940 // TODO do we need to handle weird unicode characters somehow?
6941 // str.replace(/\\u(\d{4})/g, (m, n) => String.fromCharCode(+n))
6942 c(JSON.stringify(node.value).replace(re, (_m, _i, at, hash, name) => {
6943 if (at) return '@' + name;
6944 if (hash) return '#' + name;
6945 throw new Error(`this shouldn't happen`);
6946 }), node)
6947 ];
6948 }
6949
6950 const { regex } = node ; // TODO is this right?
6951 if (regex) {
6952 return [c(`/${regex.pattern}/${regex.flags}`, node)];
6953 }
6954
6955 return [c(String(node.value), node)];
6956 }
6957};
6958
6959handlers.ForOfStatement = handlers.ForInStatement;
6960handlers.FunctionExpression = handlers.FunctionDeclaration;
6961handlers.ClassExpression = handlers.ClassDeclaration;
6962handlers.ClassBody = handlers.BlockStatement;
6963handlers.SpreadElement = handlers.RestElement;
6964handlers.ArrayPattern = handlers.ArrayExpression;
6965handlers.LogicalExpression = handlers.BinaryExpression;
6966handlers.AssignmentPattern = handlers.AssignmentExpression;
6967
6968let btoa = () => {
6969 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
6970};
6971if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
6972 btoa = (str) => window.btoa(unescape(encodeURIComponent(str)));
6973} else if (typeof Buffer === 'function') {
6974 btoa = (str) => Buffer.from(str, 'utf-8').toString('base64');
6975}
6976
6977
6978
6979
6980
6981
6982
6983
6984function print(node, opts = {}) {
6985 if (Array.isArray(node)) {
6986 return print({
6987 type: 'Program',
6988 body: node
6989 } , opts);
6990 }
6991
6992 const {
6993 getName = (x) => {
6994 throw new Error(`Unhandled sigil @${x}`);
6995 }
6996 } = opts;
6997
6998 let { map: scope_map, scope } = analyze(node);
6999 const deconflicted = new WeakMap();
7000
7001 const chunks = handle(node, {
7002 indent: '',
7003 getName,
7004 scope,
7005 scope_map,
7006 deconflicted,
7007 comments: []
7008 });
7009
7010
7011
7012 let code = '';
7013 let mappings = [];
7014 let current_line = [];
7015 let current_column = 0;
7016
7017 for (let i = 0; i < chunks.length; i += 1) {
7018 const chunk = chunks[i];
7019
7020 code += chunk.content;
7021
7022 if (chunk.loc) {
7023 current_line.push([
7024 current_column,
7025 0, // source index is always zero
7026 chunk.loc.start.line - 1,
7027 chunk.loc.start.column,
7028 ]);
7029 }
7030
7031 for (let i = 0; i < chunk.content.length; i += 1) {
7032 if (chunk.content[i] === '\n') {
7033 mappings.push(current_line);
7034 current_line = [];
7035 current_column = 0;
7036 } else {
7037 current_column += 1;
7038 }
7039 }
7040
7041 if (chunk.loc) {
7042 current_line.push([
7043 current_column,
7044 0, // source index is always zero
7045 chunk.loc.end.line - 1,
7046 chunk.loc.end.column,
7047 ]);
7048 }
7049 }
7050
7051 mappings.push(current_line);
7052
7053 const map = {
7054 version: 3,
7055 names: [] ,
7056 sources: [opts.sourceMapSource || null],
7057 sourcesContent: [opts.sourceMapContent || null],
7058 mappings: encode(mappings)
7059 };
7060
7061 Object.defineProperties(map, {
7062 toString: {
7063 enumerable: false,
7064 value: function toString() {
7065 return JSON.stringify(this);
7066 }
7067 },
7068 toUrl: {
7069 enumerable: false,
7070 value: function toUrl() {
7071 return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString());
7072 }
7073 }
7074 });
7075
7076 return {
7077 code,
7078 map
7079 };
7080}
7081
7082const sigils = {
7083 '@': 'AT',
7084 '#': 'HASH'
7085};
7086
7087const join$1 = (strings) => {
7088 let str = strings[0];
7089 for (let i = 1; i < strings.length; i += 1) {
7090 str += `_${id}_${i - 1}_${strings[i]}`;
7091 }
7092 return str.replace(/([@#])(\w+)/g, (_m, sigil, name) => `_${id}_${sigils[sigil]}_${name}`);
7093};
7094
7095const flatten_body = (array, target) => {
7096 for (let i = 0; i < array.length; i += 1) {
7097 const statement = array[i];
7098 if (Array.isArray(statement)) {
7099 flatten_body(statement, target);
7100 continue;
7101 }
7102
7103 if (statement.type === 'ExpressionStatement') {
7104 if (statement.expression === EMPTY) continue;
7105
7106 if (Array.isArray(statement.expression)) {
7107 // TODO this is hacktacular
7108 let node = statement.expression[0];
7109 while (Array.isArray(node)) node = node[0];
7110 if (node) node.leadingComments = statement.leadingComments;
7111
7112 flatten_body(statement.expression, target);
7113 continue;
7114 }
7115
7116 if (/(Expression|Literal)$/.test(statement.expression.type)) {
7117 target.push(statement);
7118 continue;
7119 }
7120
7121 if (statement.leadingComments) statement.expression.leadingComments = statement.leadingComments;
7122 if (statement.trailingComments) statement.expression.trailingComments = statement.trailingComments;
7123
7124 target.push(statement.expression);
7125 continue;
7126 }
7127
7128 target.push(statement);
7129 }
7130
7131 return target;
7132};
7133
7134const flatten_properties = (array, target) => {
7135 for (let i = 0; i < array.length; i += 1) {
7136 const property = array[i];
7137
7138 if (property.value === EMPTY) continue;
7139
7140 if (property.key === property.value && Array.isArray(property.key)) {
7141 flatten_properties(property.key, target);
7142 continue;
7143 }
7144
7145 target.push(property);
7146 }
7147
7148 return target;
7149};
7150
7151const flatten = (nodes, target) => {
7152 for (let i = 0; i < nodes.length; i += 1) {
7153 const node = nodes[i];
7154
7155 if (node === EMPTY) continue;
7156
7157 if (Array.isArray(node)) {
7158 flatten(node, target);
7159 continue;
7160 }
7161
7162 target.push(node);
7163 }
7164
7165 return target;
7166};
7167
7168const EMPTY = { type: 'Empty' };
7169
7170const acorn_opts = (comments, raw) => {
7171 const { onComment } = get_comment_handlers(comments, raw);
7172 return {
7173 ecmaVersion: 2020,
7174 sourceType: 'module',
7175 allowAwaitOutsideFunction: true,
7176 allowImportExportEverywhere: true,
7177 allowReturnOutsideFunction: true,
7178 onComment
7179 } ;
7180};
7181
7182const inject = (raw, node, values, comments) => {
7183 comments.forEach(comment => {
7184 comment.value = comment.value.replace(re, (m, i) => +i in values ? values[+i] : m);
7185 });
7186
7187 const { enter, leave } = get_comment_handlers(comments, raw);
7188
7189 walk(node, {
7190 enter,
7191
7192 leave(node, parent, key, index) {
7193 if (node.type === 'Identifier') {
7194 re.lastIndex = 0;
7195 const match = re.exec(node.name);
7196
7197 if (match) {
7198 if (match[1]) {
7199 if (+match[1] in values) {
7200 let value = values[+match[1]];
7201
7202 if (typeof value === 'string') {
7203 value = { type: 'Identifier', name: value, leadingComments: node.leadingComments, trailingComments: node.trailingComments };
7204 } else if (typeof value === 'number') {
7205 value = { type: 'Literal', value, leadingComments: node.leadingComments, trailingComments: node.trailingComments };
7206 }
7207
7208 this.replace(value || EMPTY);
7209 }
7210 } else {
7211 node.name = `${match[2] ? `@` : `#`}${match[4]}`;
7212 }
7213 }
7214 }
7215
7216 if (node.type === 'Literal') {
7217 if (typeof node.value === 'string') {
7218 re.lastIndex = 0;
7219 node.value = node.value.replace(re, (m, i) => +i in values ? values[+i] : m);
7220 }
7221 }
7222
7223 if (node.type === 'TemplateElement') {
7224 re.lastIndex = 0;
7225 node.value.raw = (node.value.raw ).replace(re, (m, i) => +i in values ? values[+i] : m);
7226 }
7227
7228 if (node.type === 'Program' || node.type === 'BlockStatement') {
7229 node.body = flatten_body(node.body, []);
7230 }
7231
7232 if (node.type === 'ObjectExpression' || node.type === 'ObjectPattern') {
7233 node.properties = flatten_properties(node.properties, []);
7234 }
7235
7236 if (node.type === 'ArrayExpression' || node.type === 'ArrayPattern') {
7237 node.elements = flatten(node.elements, []);
7238 }
7239
7240 if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') {
7241 node.params = flatten(node.params, []);
7242 }
7243
7244 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
7245 node.arguments = flatten(node.arguments, []);
7246 }
7247
7248 if (node.type === 'ImportDeclaration' || node.type === 'ExportNamedDeclaration') {
7249 node.specifiers = flatten(node.specifiers, []);
7250 }
7251
7252 if (node.type === 'ForStatement') {
7253 node.init = node.init === EMPTY ? null : node.init;
7254 node.test = node.test === EMPTY ? null : node.test;
7255 node.update = node.update === EMPTY ? null : node.update;
7256 }
7257
7258 leave(node);
7259 }
7260 });
7261};
7262
7263function b(strings, ...values) {
7264 const str = join$1(strings);
7265 const comments = [];
7266
7267 try {
7268 const ast = parse(str, acorn_opts(comments, str));
7269
7270 inject(str, ast, values, comments);
7271
7272 return ast.body;
7273 } catch (err) {
7274 handle_error(str, err);
7275 }
7276}
7277
7278function x(strings, ...values) {
7279 const str = join$1(strings);
7280 const comments = [];
7281
7282 try {
7283 const expression = parseExpressionAt(str, 0, acorn_opts(comments, str)) ;
7284 const match = /\S+/.exec(str.slice((expression ).end));
7285 if (match) {
7286 throw new Error(`Unexpected token '${match[0]}'`);
7287 }
7288
7289 inject(str, expression, values, comments);
7290
7291 return expression;
7292 } catch (err) {
7293 handle_error(str, err);
7294 }
7295}
7296
7297function p(strings, ...values) {
7298 const str = `{${join$1(strings)}}`;
7299 const comments = [];
7300
7301 try {
7302 const expression = parseExpressionAt(str, 0, acorn_opts(comments, str)) ;
7303
7304 inject(str, expression, values, comments);
7305
7306 return expression.properties[0];
7307 } catch (err) {
7308 handle_error(str, err);
7309 }
7310}
7311
7312function handle_error(str, err) {
7313 // TODO location/code frame
7314
7315 re.lastIndex = 0;
7316
7317 str = str.replace(re, (m, i, at, hash, name) => {
7318 if (at) return `@${name}`;
7319 if (hash) return `#${name}`;
7320
7321 return '${...}';
7322 });
7323
7324 console.log(`failed to parse:\n${str}`);
7325 throw err;
7326}
7327
7328const parse$1 = (source, opts) => {
7329 const comments = [];
7330 const { onComment, enter, leave } = get_comment_handlers(comments, source);
7331 const ast = parse(source, { onComment, ...opts });
7332 walk(ast , { enter, leave });
7333 return ast;
7334};
7335
7336const parseExpressionAt$1 = (source, index, opts) => {
7337 const comments = [];
7338 const { onComment, enter, leave } = get_comment_handlers(comments, source);
7339 const ast = parseExpressionAt(source, index, { onComment, ...opts });
7340 walk(ast , { enter, leave });
7341 return ast;
7342};
7343
7344const parse$2 = (source) => parse$1(source, {
7345 sourceType: 'module',
7346 ecmaVersion: 12,
7347 locations: true
7348});
7349const parse_expression_at = (source, index) => parseExpressionAt$1(source, index, {
7350 sourceType: 'module',
7351 ecmaVersion: 12,
7352 locations: true
7353});
7354
7355const whitespace = /[ \t\r\n]/;
7356const dimensions = /^(?:offset|client)(?:Width|Height)$/;
7357
7358function read_expression(parser) {
7359 try {
7360 const node = parse_expression_at(parser.template, parser.index);
7361 let num_parens = 0;
7362 for (let i = parser.index; i < node.start; i += 1) {
7363 if (parser.template[i] === '(')
7364 num_parens += 1;
7365 }
7366 let index = node.end;
7367 while (num_parens > 0) {
7368 const char = parser.template[index];
7369 if (char === ')') {
7370 num_parens -= 1;
7371 }
7372 else if (!whitespace.test(char)) {
7373 parser.error({
7374 code: 'unexpected-token',
7375 message: 'Expected )'
7376 }, index);
7377 }
7378 index += 1;
7379 }
7380 parser.index = index;
7381 return node;
7382 }
7383 catch (err) {
7384 parser.acorn_error(err);
7385 }
7386}
7387
7388const script_closing_tag = '</script>';
7389function get_context(parser, attributes, start) {
7390 const context = attributes.find(attribute => attribute.name === 'context');
7391 if (!context)
7392 return 'default';
7393 if (context.value.length !== 1 || context.value[0].type !== 'Text') {
7394 parser.error({
7395 code: 'invalid-script',
7396 message: 'context attribute must be static'
7397 }, start);
7398 }
7399 const value = context.value[0].data;
7400 if (value !== 'module') {
7401 parser.error({
7402 code: 'invalid-script',
7403 message: 'If the context attribute is supplied, its value must be "module"'
7404 }, context.start);
7405 }
7406 return value;
7407}
7408function read_script(parser, start, attributes) {
7409 const script_start = parser.index;
7410 const script_end = parser.template.indexOf(script_closing_tag, script_start);
7411 if (script_end === -1) {
7412 parser.error({
7413 code: 'unclosed-script',
7414 message: '<script> must have a closing tag'
7415 });
7416 }
7417 const source = parser.template.slice(0, script_start).replace(/[^\n]/g, ' ') +
7418 parser.template.slice(script_start, script_end);
7419 parser.index = script_end + script_closing_tag.length;
7420 let ast;
7421 try {
7422 ast = parse$2(source);
7423 }
7424 catch (err) {
7425 parser.acorn_error(err);
7426 }
7427 // TODO is this necessary?
7428 ast.start = script_start;
7429 return {
7430 type: 'Script',
7431 start,
7432 end: parser.index,
7433 context: get_context(parser, attributes, start),
7434 content: ast
7435 };
7436}
7437
7438var MAX_LINE_LENGTH = 100;
7439var OFFSET_CORRECTION = 60;
7440var TAB_REPLACEMENT = ' ';
7441
7442function sourceFragment(error, extraLines) {
7443 function processLines(start, end) {
7444 return lines.slice(start, end).map(function(line, idx) {
7445 var num = String(start + idx + 1);
7446
7447 while (num.length < maxNumLength) {
7448 num = ' ' + num;
7449 }
7450
7451 return num + ' |' + line;
7452 }).join('\n');
7453 }
7454
7455 var lines = error.source.split(/\n|\r\n?|\f/);
7456 var line = error.line;
7457 var column = error.column;
7458 var startLine = Math.max(1, line - extraLines) - 1;
7459 var endLine = Math.min(line + extraLines, lines.length + 1);
7460 var maxNumLength = Math.max(4, String(endLine).length) + 1;
7461 var cutLeft = 0;
7462
7463 // correct column according to replaced tab before column
7464 column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;
7465
7466 if (column > MAX_LINE_LENGTH) {
7467 cutLeft = column - OFFSET_CORRECTION + 3;
7468 column = OFFSET_CORRECTION - 2;
7469 }
7470
7471 for (var i = startLine; i <= endLine; i++) {
7472 if (i >= 0 && i < lines.length) {
7473 lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT);
7474 lines[i] =
7475 (cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
7476 lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
7477 (lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
7478 }
7479 }
7480
7481 return [
7482 processLines(startLine, line),
7483 new Array(column + maxNumLength + 2).join('-') + '^',
7484 processLines(line, endLine)
7485 ].join('\n');
7486}
7487
7488var CssSyntaxError = function(message, source, offset, line, column) {
7489 // some VMs prevent setting line/column otherwise (iOS Safari 10 even throw an exception)
7490 var error = Object.create(SyntaxError.prototype);
7491
7492 error.name = 'CssSyntaxError';
7493 error.message = message;
7494 error.stack = (new Error().stack || '').replace(/^.+\n/, error.name + ': ' + error.message + '\n');
7495 error.source = source;
7496 error.offset = offset;
7497 error.line = line;
7498 error.column = column;
7499
7500 error.sourceFragment = function(extraLines) {
7501 return sourceFragment(error, isNaN(extraLines) ? 0 : extraLines);
7502 };
7503 Object.defineProperty(error, 'formattedMessage', {
7504 get: function() {
7505 return (
7506 'Parse error: ' + error.message + '\n' +
7507 sourceFragment(error, 2)
7508 );
7509 }
7510 });
7511
7512 // for backward capability
7513 error.parseError = {
7514 offset: offset,
7515 line: line,
7516 column: column
7517 };
7518
7519 return error;
7520};
7521
7522var error = CssSyntaxError;
7523
7524// token types (note: value shouldn't intersect with used char codes)
7525var WHITESPACE = 1;
7526var IDENTIFIER = 2;
7527var NUMBER = 3;
7528var STRING = 4;
7529var COMMENT = 5;
7530var PUNCTUATOR = 6;
7531var CDO = 7;
7532var CDC = 8;
7533var ATRULE = 14;
7534var FUNCTION = 15;
7535var URL = 16;
7536var RAW = 17;
7537
7538var TAB = 9;
7539var N = 10;
7540var F = 12;
7541var R = 13;
7542var SPACE = 32;
7543
7544var TYPE = {
7545 WhiteSpace: WHITESPACE,
7546 Identifier: IDENTIFIER,
7547 Number: NUMBER,
7548 String: STRING,
7549 Comment: COMMENT,
7550 Punctuator: PUNCTUATOR,
7551 CDO: CDO,
7552 CDC: CDC,
7553 Atrule: ATRULE,
7554 Function: FUNCTION,
7555 Url: URL,
7556 Raw: RAW,
7557
7558 ExclamationMark: 33, // !
7559 QuotationMark: 34, // "
7560 NumberSign: 35, // #
7561 DollarSign: 36, // $
7562 PercentSign: 37, // %
7563 Ampersand: 38, // &
7564 Apostrophe: 39, // '
7565 LeftParenthesis: 40, // (
7566 RightParenthesis: 41, // )
7567 Asterisk: 42, // *
7568 PlusSign: 43, // +
7569 Comma: 44, // ,
7570 HyphenMinus: 45, // -
7571 FullStop: 46, // .
7572 Solidus: 47, // /
7573 Colon: 58, // :
7574 Semicolon: 59, // ;
7575 LessThanSign: 60, // <
7576 EqualsSign: 61, // =
7577 GreaterThanSign: 62, // >
7578 QuestionMark: 63, // ?
7579 CommercialAt: 64, // @
7580 LeftSquareBracket: 91, // [
7581 Backslash: 92, // \
7582 RightSquareBracket: 93, // ]
7583 CircumflexAccent: 94, // ^
7584 LowLine: 95, // _
7585 GraveAccent: 96, // `
7586 LeftCurlyBracket: 123, // {
7587 VerticalLine: 124, // |
7588 RightCurlyBracket: 125, // }
7589 Tilde: 126 // ~
7590};
7591
7592var NAME = Object.keys(TYPE).reduce(function(result, key) {
7593 result[TYPE[key]] = key;
7594 return result;
7595}, {});
7596
7597// https://drafts.csswg.org/css-syntax/#tokenizer-definitions
7598// > non-ASCII code point
7599// > A code point with a value equal to or greater than U+0080 <control>
7600// > name-start code point
7601// > A letter, a non-ASCII code point, or U+005F LOW LINE (_).
7602// > name code point
7603// > A name-start code point, a digit, or U+002D HYPHEN-MINUS (-)
7604// That means only ASCII code points has a special meaning and we a maps for 0..127 codes only
7605var SafeUint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
7606var SYMBOL_TYPE = new SafeUint32Array(0x80);
7607var PUNCTUATION = new SafeUint32Array(0x80);
7608var STOP_URL_RAW = new SafeUint32Array(0x80);
7609
7610for (var i = 0; i < SYMBOL_TYPE.length; i++) {
7611 SYMBOL_TYPE[i] = IDENTIFIER;
7612}
7613
7614// fill categories
7615[
7616 TYPE.ExclamationMark, // !
7617 TYPE.QuotationMark, // "
7618 TYPE.NumberSign, // #
7619 TYPE.DollarSign, // $
7620 TYPE.PercentSign, // %
7621 TYPE.Ampersand, // &
7622 TYPE.Apostrophe, // '
7623 TYPE.LeftParenthesis, // (
7624 TYPE.RightParenthesis, // )
7625 TYPE.Asterisk, // *
7626 TYPE.PlusSign, // +
7627 TYPE.Comma, // ,
7628 TYPE.HyphenMinus, // -
7629 TYPE.FullStop, // .
7630 TYPE.Solidus, // /
7631 TYPE.Colon, // :
7632 TYPE.Semicolon, // ;
7633 TYPE.LessThanSign, // <
7634 TYPE.EqualsSign, // =
7635 TYPE.GreaterThanSign, // >
7636 TYPE.QuestionMark, // ?
7637 TYPE.CommercialAt, // @
7638 TYPE.LeftSquareBracket, // [
7639 // TYPE.Backslash, // \
7640 TYPE.RightSquareBracket, // ]
7641 TYPE.CircumflexAccent, // ^
7642 // TYPE.LowLine, // _
7643 TYPE.GraveAccent, // `
7644 TYPE.LeftCurlyBracket, // {
7645 TYPE.VerticalLine, // |
7646 TYPE.RightCurlyBracket, // }
7647 TYPE.Tilde // ~
7648].forEach(function(key) {
7649 SYMBOL_TYPE[Number(key)] = PUNCTUATOR;
7650 PUNCTUATION[Number(key)] = PUNCTUATOR;
7651});
7652
7653for (var i = 48; i <= 57; i++) {
7654 SYMBOL_TYPE[i] = NUMBER;
7655}
7656
7657SYMBOL_TYPE[SPACE] = WHITESPACE;
7658SYMBOL_TYPE[TAB] = WHITESPACE;
7659SYMBOL_TYPE[N] = WHITESPACE;
7660SYMBOL_TYPE[R] = WHITESPACE;
7661SYMBOL_TYPE[F] = WHITESPACE;
7662
7663SYMBOL_TYPE[TYPE.Apostrophe] = STRING;
7664SYMBOL_TYPE[TYPE.QuotationMark] = STRING;
7665
7666STOP_URL_RAW[SPACE] = 1;
7667STOP_URL_RAW[TAB] = 1;
7668STOP_URL_RAW[N] = 1;
7669STOP_URL_RAW[R] = 1;
7670STOP_URL_RAW[F] = 1;
7671STOP_URL_RAW[TYPE.Apostrophe] = 1;
7672STOP_URL_RAW[TYPE.QuotationMark] = 1;
7673STOP_URL_RAW[TYPE.LeftParenthesis] = 1;
7674STOP_URL_RAW[TYPE.RightParenthesis] = 1;
7675
7676// whitespace is punctuation ...
7677PUNCTUATION[SPACE] = PUNCTUATOR;
7678PUNCTUATION[TAB] = PUNCTUATOR;
7679PUNCTUATION[N] = PUNCTUATOR;
7680PUNCTUATION[R] = PUNCTUATOR;
7681PUNCTUATION[F] = PUNCTUATOR;
7682// ... hyper minus is not
7683PUNCTUATION[TYPE.HyphenMinus] = 0;
7684
7685var _const = {
7686 TYPE: TYPE,
7687 NAME: NAME,
7688
7689 SYMBOL_TYPE: SYMBOL_TYPE,
7690 PUNCTUATION: PUNCTUATION,
7691 STOP_URL_RAW: STOP_URL_RAW
7692};
7693
7694var PUNCTUATION$1 = _const.PUNCTUATION;
7695var STOP_URL_RAW$1 = _const.STOP_URL_RAW;
7696var TYPE$1 = _const.TYPE;
7697var FULLSTOP = TYPE$1.FullStop;
7698var PLUSSIGN = TYPE$1.PlusSign;
7699var HYPHENMINUS = TYPE$1.HyphenMinus;
7700var PUNCTUATOR$1 = TYPE$1.Punctuator;
7701var TAB$1 = 9;
7702var N$1 = 10;
7703var F$1 = 12;
7704var R$1 = 13;
7705var SPACE$1 = 32;
7706var BACK_SLASH = 92;
7707var E = 101; // 'e'.charCodeAt(0)
7708
7709function firstCharOffset(source) {
7710 // detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
7711 if (source.charCodeAt(0) === 0xFEFF || // UTF-16BE
7712 source.charCodeAt(0) === 0xFFFE) { // UTF-16LE
7713 return 1;
7714 }
7715
7716 return 0;
7717}
7718
7719function isHex(code) {
7720 return (code >= 48 && code <= 57) || // 0 .. 9
7721 (code >= 65 && code <= 70) || // A .. F
7722 (code >= 97 && code <= 102); // a .. f
7723}
7724
7725function isNumber(code) {
7726 return code >= 48 && code <= 57;
7727}
7728
7729function isNewline(source, offset, code) {
7730 if (code === N$1 || code === F$1 || code === R$1) {
7731 if (code === R$1 && offset + 1 < source.length && source.charCodeAt(offset + 1) === N$1) {
7732 return 2;
7733 }
7734
7735 return 1;
7736 }
7737
7738 return 0;
7739}
7740
7741function cmpChar(testStr, offset, referenceCode) {
7742 var code = testStr.charCodeAt(offset);
7743
7744 // code.toLowerCase()
7745 if (code >= 65 && code <= 90) {
7746 code = code | 32;
7747 }
7748
7749 return code === referenceCode;
7750}
7751
7752function cmpStr(testStr, start, end, referenceStr) {
7753 if (end - start !== referenceStr.length) {
7754 return false;
7755 }
7756
7757 if (start < 0 || end > testStr.length) {
7758 return false;
7759 }
7760
7761 for (var i = start; i < end; i++) {
7762 var testCode = testStr.charCodeAt(i);
7763 var refCode = referenceStr.charCodeAt(i - start);
7764
7765 // testStr[i].toLowerCase()
7766 if (testCode >= 65 && testCode <= 90) {
7767 testCode = testCode | 32;
7768 }
7769
7770 if (testCode !== refCode) {
7771 return false;
7772 }
7773 }
7774
7775 return true;
7776}
7777
7778function endsWith(testStr, referenceStr) {
7779 return cmpStr(testStr, testStr.length - referenceStr.length, testStr.length, referenceStr);
7780}
7781
7782function findLastNonSpaceLocation(scanner) {
7783 for (var i = scanner.source.length - 1; i >= 0; i--) {
7784 var code = scanner.source.charCodeAt(i);
7785
7786 if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
7787 break;
7788 }
7789 }
7790
7791 return scanner.getLocation(i + 1);
7792}
7793
7794function findWhiteSpaceEnd(source, offset) {
7795 for (; offset < source.length; offset++) {
7796 var code = source.charCodeAt(offset);
7797
7798 if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
7799 break;
7800 }
7801 }
7802
7803 return offset;
7804}
7805
7806function findCommentEnd(source, offset) {
7807 var commentEnd = source.indexOf('*/', offset);
7808
7809 if (commentEnd === -1) {
7810 return source.length;
7811 }
7812
7813 return commentEnd + 2;
7814}
7815
7816function findStringEnd(source, offset, quote) {
7817 for (; offset < source.length; offset++) {
7818 var code = source.charCodeAt(offset);
7819
7820 // TODO: bad string
7821 if (code === BACK_SLASH) {
7822 offset++;
7823 } else if (code === quote) {
7824 offset++;
7825 break;
7826 }
7827 }
7828
7829 return offset;
7830}
7831
7832function findDecimalNumberEnd(source, offset) {
7833 for (; offset < source.length; offset++) {
7834 var code = source.charCodeAt(offset);
7835
7836 if (code < 48 || code > 57) { // not a 0 .. 9
7837 break;
7838 }
7839 }
7840
7841 return offset;
7842}
7843
7844function findNumberEnd(source, offset, allowFraction) {
7845 var code;
7846
7847 offset = findDecimalNumberEnd(source, offset);
7848
7849 // fraction: .\d+
7850 if (allowFraction && offset + 1 < source.length && source.charCodeAt(offset) === FULLSTOP) {
7851 code = source.charCodeAt(offset + 1);
7852
7853 if (isNumber(code)) {
7854 offset = findDecimalNumberEnd(source, offset + 1);
7855 }
7856 }
7857
7858 // exponent: e[+-]\d+
7859 if (offset + 1 < source.length) {
7860 if ((source.charCodeAt(offset) | 32) === E) { // case insensitive check for `e`
7861 code = source.charCodeAt(offset + 1);
7862
7863 if (code === PLUSSIGN || code === HYPHENMINUS) {
7864 if (offset + 2 < source.length) {
7865 code = source.charCodeAt(offset + 2);
7866 }
7867 }
7868
7869 if (isNumber(code)) {
7870 offset = findDecimalNumberEnd(source, offset + 2);
7871 }
7872 }
7873 }
7874
7875 return offset;
7876}
7877
7878// skip escaped unicode sequence that can ends with space
7879// [0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
7880function findEscaseEnd(source, offset) {
7881 for (var i = 0; i < 7 && offset + i < source.length; i++) {
7882 var code = source.charCodeAt(offset + i);
7883
7884 if (i !== 6 && isHex(code)) {
7885 continue;
7886 }
7887
7888 if (i > 0) {
7889 offset += i - 1 + isNewline(source, offset + i, code);
7890 if (code === SPACE$1 || code === TAB$1) {
7891 offset++;
7892 }
7893 }
7894
7895 break;
7896 }
7897
7898 return offset;
7899}
7900
7901function findIdentifierEnd(source, offset) {
7902 for (; offset < source.length; offset++) {
7903 var code = source.charCodeAt(offset);
7904
7905 if (code === BACK_SLASH) {
7906 offset = findEscaseEnd(source, offset + 1);
7907 } else if (code < 0x80 && PUNCTUATION$1[code] === PUNCTUATOR$1) {
7908 break;
7909 }
7910 }
7911
7912 return offset;
7913}
7914
7915function findUrlRawEnd(source, offset) {
7916 for (; offset < source.length; offset++) {
7917 var code = source.charCodeAt(offset);
7918
7919 if (code === BACK_SLASH) {
7920 offset = findEscaseEnd(source, offset + 1);
7921 } else if (code < 0x80 && STOP_URL_RAW$1[code] === 1) {
7922 break;
7923 }
7924 }
7925
7926 return offset;
7927}
7928
7929var utils = {
7930 firstCharOffset: firstCharOffset,
7931
7932 isHex: isHex,
7933 isNumber: isNumber,
7934 isNewline: isNewline,
7935
7936 cmpChar: cmpChar,
7937 cmpStr: cmpStr,
7938 endsWith: endsWith,
7939
7940 findLastNonSpaceLocation: findLastNonSpaceLocation,
7941 findWhiteSpaceEnd: findWhiteSpaceEnd,
7942 findCommentEnd: findCommentEnd,
7943 findStringEnd: findStringEnd,
7944 findDecimalNumberEnd: findDecimalNumberEnd,
7945 findNumberEnd: findNumberEnd,
7946 findEscaseEnd: findEscaseEnd,
7947 findIdentifierEnd: findIdentifierEnd,
7948 findUrlRawEnd: findUrlRawEnd
7949};
7950
7951var TYPE$2 = _const.TYPE;
7952var NAME$1 = _const.NAME;
7953var SYMBOL_TYPE$1 = _const.SYMBOL_TYPE;
7954
7955
7956var firstCharOffset$1 = utils.firstCharOffset;
7957var cmpStr$1 = utils.cmpStr;
7958var isNumber$1 = utils.isNumber;
7959var findLastNonSpaceLocation$1 = utils.findLastNonSpaceLocation;
7960var findWhiteSpaceEnd$1 = utils.findWhiteSpaceEnd;
7961var findCommentEnd$1 = utils.findCommentEnd;
7962var findStringEnd$1 = utils.findStringEnd;
7963var findNumberEnd$1 = utils.findNumberEnd;
7964var findIdentifierEnd$1 = utils.findIdentifierEnd;
7965var findUrlRawEnd$1 = utils.findUrlRawEnd;
7966
7967var NULL = 0;
7968var WHITESPACE$1 = TYPE$2.WhiteSpace;
7969var IDENTIFIER$1 = TYPE$2.Identifier;
7970var NUMBER$1 = TYPE$2.Number;
7971var STRING$1 = TYPE$2.String;
7972var COMMENT$1 = TYPE$2.Comment;
7973var PUNCTUATOR$2 = TYPE$2.Punctuator;
7974var CDO$1 = TYPE$2.CDO;
7975var CDC$1 = TYPE$2.CDC;
7976var ATRULE$1 = TYPE$2.Atrule;
7977var FUNCTION$1 = TYPE$2.Function;
7978var URL$1 = TYPE$2.Url;
7979var RAW$1 = TYPE$2.Raw;
7980
7981var N$2 = 10;
7982var F$2 = 12;
7983var R$2 = 13;
7984var STAR = TYPE$2.Asterisk;
7985var SLASH = TYPE$2.Solidus;
7986var FULLSTOP$1 = TYPE$2.FullStop;
7987var PLUSSIGN$1 = TYPE$2.PlusSign;
7988var HYPHENMINUS$1 = TYPE$2.HyphenMinus;
7989var GREATERTHANSIGN = TYPE$2.GreaterThanSign;
7990var LESSTHANSIGN = TYPE$2.LessThanSign;
7991var EXCLAMATIONMARK = TYPE$2.ExclamationMark;
7992var COMMERCIALAT = TYPE$2.CommercialAt;
7993var QUOTATIONMARK = TYPE$2.QuotationMark;
7994var APOSTROPHE = TYPE$2.Apostrophe;
7995var LEFTPARENTHESIS = TYPE$2.LeftParenthesis;
7996var RIGHTPARENTHESIS = TYPE$2.RightParenthesis;
7997var LEFTCURLYBRACKET = TYPE$2.LeftCurlyBracket;
7998var RIGHTCURLYBRACKET = TYPE$2.RightCurlyBracket;
7999var LEFTSQUAREBRACKET = TYPE$2.LeftSquareBracket;
8000var RIGHTSQUAREBRACKET = TYPE$2.RightSquareBracket;
8001
8002var MIN_BUFFER_SIZE = 16 * 1024;
8003var OFFSET_MASK = 0x00FFFFFF;
8004var TYPE_SHIFT = 24;
8005var SafeUint32Array$1 = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
8006
8007function computeLinesAndColumns(tokenizer, source) {
8008 var sourceLength = source.length;
8009 var start = firstCharOffset$1(source);
8010 var lines = tokenizer.lines;
8011 var line = tokenizer.startLine;
8012 var columns = tokenizer.columns;
8013 var column = tokenizer.startColumn;
8014
8015 if (lines === null || lines.length < sourceLength + 1) {
8016 lines = new SafeUint32Array$1(Math.max(sourceLength + 1024, MIN_BUFFER_SIZE));
8017 columns = new SafeUint32Array$1(lines.length);
8018 }
8019
8020 for (var i = start; i < sourceLength; i++) {
8021 var code = source.charCodeAt(i);
8022
8023 lines[i] = line;
8024 columns[i] = column++;
8025
8026 if (code === N$2 || code === R$2 || code === F$2) {
8027 if (code === R$2 && i + 1 < sourceLength && source.charCodeAt(i + 1) === N$2) {
8028 i++;
8029 lines[i] = line;
8030 columns[i] = column;
8031 }
8032
8033 line++;
8034 column = 1;
8035 }
8036 }
8037
8038 lines[i] = line;
8039 columns[i] = column;
8040
8041 tokenizer.linesAnsColumnsComputed = true;
8042 tokenizer.lines = lines;
8043 tokenizer.columns = columns;
8044}
8045
8046function tokenLayout(tokenizer, source, startPos) {
8047 var sourceLength = source.length;
8048 var offsetAndType = tokenizer.offsetAndType;
8049 var balance = tokenizer.balance;
8050 var tokenCount = 0;
8051 var prevType = 0;
8052 var offset = startPos;
8053 var anchor = 0;
8054 var balanceCloseCode = 0;
8055 var balanceStart = 0;
8056 var balancePrev = 0;
8057
8058 if (offsetAndType === null || offsetAndType.length < sourceLength + 1) {
8059 offsetAndType = new SafeUint32Array$1(sourceLength + 1024);
8060 balance = new SafeUint32Array$1(sourceLength + 1024);
8061 }
8062
8063 while (offset < sourceLength) {
8064 var code = source.charCodeAt(offset);
8065 var type = code < 0x80 ? SYMBOL_TYPE$1[code] : IDENTIFIER$1;
8066
8067 balance[tokenCount] = sourceLength;
8068
8069 switch (type) {
8070 case WHITESPACE$1:
8071 offset = findWhiteSpaceEnd$1(source, offset + 1);
8072 break;
8073
8074 case PUNCTUATOR$2:
8075 switch (code) {
8076 case balanceCloseCode:
8077 balancePrev = balanceStart & OFFSET_MASK;
8078 balanceStart = balance[balancePrev];
8079 balanceCloseCode = balanceStart >> TYPE_SHIFT;
8080 balance[tokenCount] = balancePrev;
8081 balance[balancePrev++] = tokenCount;
8082 for (; balancePrev < tokenCount; balancePrev++) {
8083 if (balance[balancePrev] === sourceLength) {
8084 balance[balancePrev] = tokenCount;
8085 }
8086 }
8087 break;
8088
8089 case LEFTSQUAREBRACKET:
8090 balance[tokenCount] = balanceStart;
8091 balanceCloseCode = RIGHTSQUAREBRACKET;
8092 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8093 break;
8094
8095 case LEFTCURLYBRACKET:
8096 balance[tokenCount] = balanceStart;
8097 balanceCloseCode = RIGHTCURLYBRACKET;
8098 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8099 break;
8100
8101 case LEFTPARENTHESIS:
8102 balance[tokenCount] = balanceStart;
8103 balanceCloseCode = RIGHTPARENTHESIS;
8104 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8105 break;
8106 }
8107
8108 // /*
8109 if (code === STAR && prevType === SLASH) {
8110 type = COMMENT$1;
8111 offset = findCommentEnd$1(source, offset + 1);
8112 tokenCount--; // rewrite prev token
8113 break;
8114 }
8115
8116 // edge case for -.123 and +.123
8117 if (code === FULLSTOP$1 && (prevType === PLUSSIGN$1 || prevType === HYPHENMINUS$1)) {
8118 if (offset + 1 < sourceLength && isNumber$1(source.charCodeAt(offset + 1))) {
8119 type = NUMBER$1;
8120 offset = findNumberEnd$1(source, offset + 2, false);
8121 tokenCount--; // rewrite prev token
8122 break;
8123 }
8124 }
8125
8126 // <!--
8127 if (code === EXCLAMATIONMARK && prevType === LESSTHANSIGN) {
8128 if (offset + 2 < sourceLength &&
8129 source.charCodeAt(offset + 1) === HYPHENMINUS$1 &&
8130 source.charCodeAt(offset + 2) === HYPHENMINUS$1) {
8131 type = CDO$1;
8132 offset = offset + 3;
8133 tokenCount--; // rewrite prev token
8134 break;
8135 }
8136 }
8137
8138 // -->
8139 if (code === HYPHENMINUS$1 && prevType === HYPHENMINUS$1) {
8140 if (offset + 1 < sourceLength && source.charCodeAt(offset + 1) === GREATERTHANSIGN) {
8141 type = CDC$1;
8142 offset = offset + 2;
8143 tokenCount--; // rewrite prev token
8144 break;
8145 }
8146 }
8147
8148 // ident(
8149 if (code === LEFTPARENTHESIS && prevType === IDENTIFIER$1) {
8150 offset = offset + 1;
8151 tokenCount--; // rewrite prev token
8152 balance[tokenCount] = balance[tokenCount + 1];
8153 balanceStart--;
8154
8155 // 4 char length identifier and equal to `url(` (case insensitive)
8156 if (offset - anchor === 4 && cmpStr$1(source, anchor, offset, 'url(')) {
8157 // special case for url() because it can contain any symbols sequence with few exceptions
8158 anchor = findWhiteSpaceEnd$1(source, offset);
8159 code = source.charCodeAt(anchor);
8160 if (code !== LEFTPARENTHESIS &&
8161 code !== RIGHTPARENTHESIS &&
8162 code !== QUOTATIONMARK &&
8163 code !== APOSTROPHE) {
8164 // url(
8165 offsetAndType[tokenCount++] = (URL$1 << TYPE_SHIFT) | offset;
8166 balance[tokenCount] = sourceLength;
8167
8168 // ws*
8169 if (anchor !== offset) {
8170 offsetAndType[tokenCount++] = (WHITESPACE$1 << TYPE_SHIFT) | anchor;
8171 balance[tokenCount] = sourceLength;
8172 }
8173
8174 // raw
8175 type = RAW$1;
8176 offset = findUrlRawEnd$1(source, anchor);
8177 } else {
8178 type = URL$1;
8179 }
8180 } else {
8181 type = FUNCTION$1;
8182 }
8183 break;
8184 }
8185
8186 type = code;
8187 offset = offset + 1;
8188 break;
8189
8190 case NUMBER$1:
8191 offset = findNumberEnd$1(source, offset + 1, prevType !== FULLSTOP$1);
8192
8193 // merge number with a preceding dot, dash or plus
8194 if (prevType === FULLSTOP$1 ||
8195 prevType === HYPHENMINUS$1 ||
8196 prevType === PLUSSIGN$1) {
8197 tokenCount--; // rewrite prev token
8198 }
8199
8200 break;
8201
8202 case STRING$1:
8203 offset = findStringEnd$1(source, offset + 1, code);
8204 break;
8205
8206 default:
8207 anchor = offset;
8208 offset = findIdentifierEnd$1(source, offset);
8209
8210 // merge identifier with a preceding dash
8211 if (prevType === HYPHENMINUS$1) {
8212 // rewrite prev token
8213 tokenCount--;
8214 // restore prev prev token type
8215 // for case @-prefix-ident
8216 prevType = tokenCount === 0 ? 0 : offsetAndType[tokenCount - 1] >> TYPE_SHIFT;
8217 }
8218
8219 if (prevType === COMMERCIALAT) {
8220 // rewrite prev token and change type to <at-keyword-token>
8221 tokenCount--;
8222 type = ATRULE$1;
8223 }
8224 }
8225
8226 offsetAndType[tokenCount++] = (type << TYPE_SHIFT) | offset;
8227 prevType = type;
8228 }
8229
8230 // finalize arrays
8231 offsetAndType[tokenCount] = offset;
8232 balance[tokenCount] = sourceLength;
8233 while (balanceStart !== 0) {
8234 balancePrev = balanceStart & OFFSET_MASK;
8235 balanceStart = balance[balancePrev];
8236 balance[balancePrev] = sourceLength;
8237 }
8238
8239 tokenizer.offsetAndType = offsetAndType;
8240 tokenizer.tokenCount = tokenCount;
8241 tokenizer.balance = balance;
8242}
8243
8244//
8245// tokenizer
8246//
8247
8248var Tokenizer = function(source, startOffset, startLine, startColumn) {
8249 this.offsetAndType = null;
8250 this.balance = null;
8251 this.lines = null;
8252 this.columns = null;
8253
8254 this.setSource(source, startOffset, startLine, startColumn);
8255};
8256
8257Tokenizer.prototype = {
8258 setSource: function(source, startOffset, startLine, startColumn) {
8259 var safeSource = String(source || '');
8260 var start = firstCharOffset$1(safeSource);
8261
8262 this.source = safeSource;
8263 this.firstCharOffset = start;
8264 this.startOffset = typeof startOffset === 'undefined' ? 0 : startOffset;
8265 this.startLine = typeof startLine === 'undefined' ? 1 : startLine;
8266 this.startColumn = typeof startColumn === 'undefined' ? 1 : startColumn;
8267 this.linesAnsColumnsComputed = false;
8268
8269 this.eof = false;
8270 this.currentToken = -1;
8271 this.tokenType = 0;
8272 this.tokenStart = start;
8273 this.tokenEnd = start;
8274
8275 tokenLayout(this, safeSource, start);
8276 this.next();
8277 },
8278
8279 lookupType: function(offset) {
8280 offset += this.currentToken;
8281
8282 if (offset < this.tokenCount) {
8283 return this.offsetAndType[offset] >> TYPE_SHIFT;
8284 }
8285
8286 return NULL;
8287 },
8288 lookupNonWSType: function(offset) {
8289 offset += this.currentToken;
8290
8291 for (var type; offset < this.tokenCount; offset++) {
8292 type = this.offsetAndType[offset] >> TYPE_SHIFT;
8293
8294 if (type !== WHITESPACE$1) {
8295 return type;
8296 }
8297 }
8298
8299 return NULL;
8300 },
8301 lookupValue: function(offset, referenceStr) {
8302 offset += this.currentToken;
8303
8304 if (offset < this.tokenCount) {
8305 return cmpStr$1(
8306 this.source,
8307 this.offsetAndType[offset - 1] & OFFSET_MASK,
8308 this.offsetAndType[offset] & OFFSET_MASK,
8309 referenceStr
8310 );
8311 }
8312
8313 return false;
8314 },
8315 getTokenStart: function(tokenNum) {
8316 if (tokenNum === this.currentToken) {
8317 return this.tokenStart;
8318 }
8319
8320 if (tokenNum > 0) {
8321 return tokenNum < this.tokenCount
8322 ? this.offsetAndType[tokenNum - 1] & OFFSET_MASK
8323 : this.offsetAndType[this.tokenCount] & OFFSET_MASK;
8324 }
8325
8326 return this.firstCharOffset;
8327 },
8328 getOffsetExcludeWS: function() {
8329 if (this.currentToken > 0) {
8330 if ((this.offsetAndType[this.currentToken - 1] >> TYPE_SHIFT) === WHITESPACE$1) {
8331 return this.currentToken > 1
8332 ? this.offsetAndType[this.currentToken - 2] & OFFSET_MASK
8333 : this.firstCharOffset;
8334 }
8335 }
8336 return this.tokenStart;
8337 },
8338 getRawLength: function(startToken, endTokenType1, endTokenType2, includeTokenType2) {
8339 var cursor = startToken;
8340 var balanceEnd;
8341
8342 loop:
8343 for (; cursor < this.tokenCount; cursor++) {
8344 balanceEnd = this.balance[cursor];
8345
8346 // belance end points to offset before start
8347 if (balanceEnd < startToken) {
8348 break loop;
8349 }
8350
8351 // check token is stop type
8352 switch (this.offsetAndType[cursor] >> TYPE_SHIFT) {
8353 case endTokenType1:
8354 break loop;
8355
8356 case endTokenType2:
8357 if (includeTokenType2) {
8358 cursor++;
8359 }
8360 break loop;
8361
8362 default:
8363 // fast forward to the end of balanced block
8364 if (this.balance[balanceEnd] === cursor) {
8365 cursor = balanceEnd;
8366 }
8367 }
8368
8369 }
8370
8371 return cursor - this.currentToken;
8372 },
8373
8374 getTokenValue: function() {
8375 return this.source.substring(this.tokenStart, this.tokenEnd);
8376 },
8377 substrToCursor: function(start) {
8378 return this.source.substring(start, this.tokenStart);
8379 },
8380
8381 skipWS: function() {
8382 for (var i = this.currentToken, skipTokenCount = 0; i < this.tokenCount; i++, skipTokenCount++) {
8383 if ((this.offsetAndType[i] >> TYPE_SHIFT) !== WHITESPACE$1) {
8384 break;
8385 }
8386 }
8387
8388 if (skipTokenCount > 0) {
8389 this.skip(skipTokenCount);
8390 }
8391 },
8392 skipSC: function() {
8393 while (this.tokenType === WHITESPACE$1 || this.tokenType === COMMENT$1) {
8394 this.next();
8395 }
8396 },
8397 skip: function(tokenCount) {
8398 var next = this.currentToken + tokenCount;
8399
8400 if (next < this.tokenCount) {
8401 this.currentToken = next;
8402 this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
8403 next = this.offsetAndType[next];
8404 this.tokenType = next >> TYPE_SHIFT;
8405 this.tokenEnd = next & OFFSET_MASK;
8406 } else {
8407 this.currentToken = this.tokenCount;
8408 this.next();
8409 }
8410 },
8411 next: function() {
8412 var next = this.currentToken + 1;
8413
8414 if (next < this.tokenCount) {
8415 this.currentToken = next;
8416 this.tokenStart = this.tokenEnd;
8417 next = this.offsetAndType[next];
8418 this.tokenType = next >> TYPE_SHIFT;
8419 this.tokenEnd = next & OFFSET_MASK;
8420 } else {
8421 this.currentToken = this.tokenCount;
8422 this.eof = true;
8423 this.tokenType = NULL;
8424 this.tokenStart = this.tokenEnd = this.source.length;
8425 }
8426 },
8427
8428 eat: function(tokenType) {
8429 if (this.tokenType !== tokenType) {
8430 var offset = this.tokenStart;
8431 var message = NAME$1[tokenType] + ' is expected';
8432
8433 // tweak message and offset
8434 if (tokenType === IDENTIFIER$1) {
8435 // when identifier is expected but there is a function or url
8436 if (this.tokenType === FUNCTION$1 || this.tokenType === URL$1) {
8437 offset = this.tokenEnd - 1;
8438 message += ' but function found';
8439 }
8440 } else {
8441 // when test type is part of another token show error for current position + 1
8442 // e.g. eat(HYPHENMINUS) will fail on "-foo", but pointing on "-" is odd
8443 if (this.source.charCodeAt(this.tokenStart) === tokenType) {
8444 offset = offset + 1;
8445 }
8446 }
8447
8448 this.error(message, offset);
8449 }
8450
8451 this.next();
8452 },
8453 eatNonWS: function(tokenType) {
8454 this.skipWS();
8455 this.eat(tokenType);
8456 },
8457
8458 consume: function(tokenType) {
8459 var value = this.getTokenValue();
8460
8461 this.eat(tokenType);
8462
8463 return value;
8464 },
8465 consumeFunctionName: function() {
8466 var name = this.source.substring(this.tokenStart, this.tokenEnd - 1);
8467
8468 this.eat(FUNCTION$1);
8469
8470 return name;
8471 },
8472 consumeNonWS: function(tokenType) {
8473 this.skipWS();
8474
8475 return this.consume(tokenType);
8476 },
8477
8478 expectIdentifier: function(name) {
8479 if (this.tokenType !== IDENTIFIER$1 || cmpStr$1(this.source, this.tokenStart, this.tokenEnd, name) === false) {
8480 this.error('Identifier `' + name + '` is expected');
8481 }
8482
8483 this.next();
8484 },
8485
8486 getLocation: function(offset, filename) {
8487 if (!this.linesAnsColumnsComputed) {
8488 computeLinesAndColumns(this, this.source);
8489 }
8490
8491 return {
8492 source: filename,
8493 offset: this.startOffset + offset,
8494 line: this.lines[offset],
8495 column: this.columns[offset]
8496 };
8497 },
8498
8499 getLocationRange: function(start, end, filename) {
8500 if (!this.linesAnsColumnsComputed) {
8501 computeLinesAndColumns(this, this.source);
8502 }
8503
8504 return {
8505 source: filename,
8506 start: {
8507 offset: this.startOffset + start,
8508 line: this.lines[start],
8509 column: this.columns[start]
8510 },
8511 end: {
8512 offset: this.startOffset + end,
8513 line: this.lines[end],
8514 column: this.columns[end]
8515 }
8516 };
8517 },
8518
8519 error: function(message, offset) {
8520 var location = typeof offset !== 'undefined' && offset < this.source.length
8521 ? this.getLocation(offset)
8522 : this.eof
8523 ? findLastNonSpaceLocation$1(this)
8524 : this.getLocation(this.tokenStart);
8525
8526 throw new error(
8527 message || 'Unexpected input',
8528 this.source,
8529 location.offset,
8530 location.line,
8531 location.column
8532 );
8533 },
8534
8535 dump: function() {
8536 var offset = 0;
8537
8538 return Array.prototype.slice.call(this.offsetAndType, 0, this.tokenCount).map(function(item, idx) {
8539 var start = offset;
8540 var end = item & OFFSET_MASK;
8541
8542 offset = end;
8543
8544 return {
8545 idx: idx,
8546 type: NAME$1[item >> TYPE_SHIFT],
8547 chunk: this.source.substring(start, end),
8548 balance: this.balance[idx]
8549 };
8550 }, this);
8551 }
8552};
8553
8554// extend with error class
8555Tokenizer.CssSyntaxError = error;
8556
8557// extend tokenizer with constants
8558Object.keys(_const).forEach(function(key) {
8559 Tokenizer[key] = _const[key];
8560});
8561
8562// extend tokenizer with static methods from utils
8563Object.keys(utils).forEach(function(key) {
8564 Tokenizer[key] = utils[key];
8565});
8566
8567// warm up tokenizer to elimitate code branches that never execute
8568// fix soft deoptimizations (insufficient type feedback)
8569new Tokenizer('\n\r\r\n\f<!---->//""\'\'/*\r\n\f*/1a;.\\31\t\+2{url(a);func();+1.2e3 -.4e-5 .6e+7}').getLocation();
8570
8571var Tokenizer_1 = Tokenizer;
8572
8573var tokenizer = Tokenizer_1;
8574
8575//
8576// item item item item
8577// /------\ /------\ /------\ /------\
8578// | data | | data | | data | | data |
8579// null <--+-prev |<---+-prev |<---+-prev |<---+-prev |
8580// | next-+--->| next-+--->| next-+--->| next-+--> null
8581// \------/ \------/ \------/ \------/
8582// ^ ^
8583// | list |
8584// | /------\ |
8585// \--------------+-head | |
8586// | tail-+--------------/
8587// \------/
8588//
8589
8590function createItem(data) {
8591 return {
8592 prev: null,
8593 next: null,
8594 data: data
8595 };
8596}
8597
8598var cursors = null;
8599var List = function() {
8600 this.cursor = null;
8601 this.head = null;
8602 this.tail = null;
8603};
8604
8605List.createItem = createItem;
8606List.prototype.createItem = createItem;
8607
8608List.prototype.getSize = function() {
8609 var size = 0;
8610 var cursor = this.head;
8611
8612 while (cursor) {
8613 size++;
8614 cursor = cursor.next;
8615 }
8616
8617 return size;
8618};
8619
8620List.prototype.fromArray = function(array) {
8621 var cursor = null;
8622
8623 this.head = null;
8624
8625 for (var i = 0; i < array.length; i++) {
8626 var item = createItem(array[i]);
8627
8628 if (cursor !== null) {
8629 cursor.next = item;
8630 } else {
8631 this.head = item;
8632 }
8633
8634 item.prev = cursor;
8635 cursor = item;
8636 }
8637
8638 this.tail = cursor;
8639
8640 return this;
8641};
8642
8643List.prototype.toArray = function() {
8644 var cursor = this.head;
8645 var result = [];
8646
8647 while (cursor) {
8648 result.push(cursor.data);
8649 cursor = cursor.next;
8650 }
8651
8652 return result;
8653};
8654
8655List.prototype.toJSON = List.prototype.toArray;
8656
8657List.prototype.isEmpty = function() {
8658 return this.head === null;
8659};
8660
8661List.prototype.first = function() {
8662 return this.head && this.head.data;
8663};
8664
8665List.prototype.last = function() {
8666 return this.tail && this.tail.data;
8667};
8668
8669function allocateCursor(node, prev, next) {
8670 var cursor;
8671
8672 if (cursors !== null) {
8673 cursor = cursors;
8674 cursors = cursors.cursor;
8675 cursor.prev = prev;
8676 cursor.next = next;
8677 cursor.cursor = node.cursor;
8678 } else {
8679 cursor = {
8680 prev: prev,
8681 next: next,
8682 cursor: node.cursor
8683 };
8684 }
8685
8686 node.cursor = cursor;
8687
8688 return cursor;
8689}
8690
8691function releaseCursor(node) {
8692 var cursor = node.cursor;
8693
8694 node.cursor = cursor.cursor;
8695 cursor.prev = null;
8696 cursor.next = null;
8697 cursor.cursor = cursors;
8698 cursors = cursor;
8699}
8700
8701List.prototype.each = function(fn, context) {
8702 var item;
8703
8704 if (context === undefined) {
8705 context = this;
8706 }
8707
8708 // push cursor
8709 var cursor = allocateCursor(this, null, this.head);
8710
8711 while (cursor.next !== null) {
8712 item = cursor.next;
8713 cursor.next = item.next;
8714
8715 fn.call(context, item.data, item, this);
8716 }
8717
8718 // pop cursor
8719 releaseCursor(this);
8720};
8721
8722List.prototype.eachRight = function(fn, context) {
8723 var item;
8724
8725 if (context === undefined) {
8726 context = this;
8727 }
8728
8729 // push cursor
8730 var cursor = allocateCursor(this, this.tail, null);
8731
8732 while (cursor.prev !== null) {
8733 item = cursor.prev;
8734 cursor.prev = item.prev;
8735
8736 fn.call(context, item.data, item, this);
8737 }
8738
8739 // pop cursor
8740 releaseCursor(this);
8741};
8742
8743List.prototype.nextUntil = function(start, fn, context) {
8744 if (start === null) {
8745 return;
8746 }
8747
8748 var item;
8749
8750 if (context === undefined) {
8751 context = this;
8752 }
8753
8754 // push cursor
8755 var cursor = allocateCursor(this, null, start);
8756
8757 while (cursor.next !== null) {
8758 item = cursor.next;
8759 cursor.next = item.next;
8760
8761 if (fn.call(context, item.data, item, this)) {
8762 break;
8763 }
8764 }
8765
8766 // pop cursor
8767 releaseCursor(this);
8768};
8769
8770List.prototype.prevUntil = function(start, fn, context) {
8771 if (start === null) {
8772 return;
8773 }
8774
8775 var item;
8776
8777 if (context === undefined) {
8778 context = this;
8779 }
8780
8781 // push cursor
8782 var cursor = allocateCursor(this, start, null);
8783
8784 while (cursor.prev !== null) {
8785 item = cursor.prev;
8786 cursor.prev = item.prev;
8787
8788 if (fn.call(context, item.data, item, this)) {
8789 break;
8790 }
8791 }
8792
8793 // pop cursor
8794 releaseCursor(this);
8795};
8796
8797List.prototype.some = function(fn, context) {
8798 var cursor = this.head;
8799
8800 if (context === undefined) {
8801 context = this;
8802 }
8803
8804 while (cursor !== null) {
8805 if (fn.call(context, cursor.data, cursor, this)) {
8806 return true;
8807 }
8808
8809 cursor = cursor.next;
8810 }
8811
8812 return false;
8813};
8814
8815List.prototype.map = function(fn, context) {
8816 var result = [];
8817 var cursor = this.head;
8818
8819 if (context === undefined) {
8820 context = this;
8821 }
8822
8823 while (cursor !== null) {
8824 result.push(fn.call(context, cursor.data, cursor, this));
8825 cursor = cursor.next;
8826 }
8827
8828 return result;
8829};
8830
8831List.prototype.clear = function() {
8832 this.head = null;
8833 this.tail = null;
8834};
8835
8836List.prototype.copy = function() {
8837 var result = new List();
8838 var cursor = this.head;
8839
8840 while (cursor !== null) {
8841 result.insert(createItem(cursor.data));
8842 cursor = cursor.next;
8843 }
8844
8845 return result;
8846};
8847
8848List.prototype.updateCursors = function(prevOld, prevNew, nextOld, nextNew) {
8849 var cursor = this.cursor;
8850
8851 while (cursor !== null) {
8852 if (cursor.prev === prevOld) {
8853 cursor.prev = prevNew;
8854 }
8855
8856 if (cursor.next === nextOld) {
8857 cursor.next = nextNew;
8858 }
8859
8860 cursor = cursor.cursor;
8861 }
8862};
8863
8864List.prototype.prepend = function(item) {
8865 // head
8866 // ^
8867 // item
8868 this.updateCursors(null, item, this.head, item);
8869
8870 // insert to the beginning of the list
8871 if (this.head !== null) {
8872 // new item <- first item
8873 this.head.prev = item;
8874
8875 // new item -> first item
8876 item.next = this.head;
8877 } else {
8878 // if list has no head, then it also has no tail
8879 // in this case tail points to the new item
8880 this.tail = item;
8881 }
8882
8883 // head always points to new item
8884 this.head = item;
8885
8886 return this;
8887};
8888
8889List.prototype.prependData = function(data) {
8890 return this.prepend(createItem(data));
8891};
8892
8893List.prototype.append = function(item) {
8894 // tail
8895 // ^
8896 // item
8897 this.updateCursors(this.tail, item, null, item);
8898
8899 // insert to the ending of the list
8900 if (this.tail !== null) {
8901 // last item -> new item
8902 this.tail.next = item;
8903
8904 // last item <- new item
8905 item.prev = this.tail;
8906 } else {
8907 // if list has no tail, then it also has no head
8908 // in this case head points to new item
8909 this.head = item;
8910 }
8911
8912 // tail always points to new item
8913 this.tail = item;
8914
8915 return this;
8916};
8917
8918List.prototype.appendData = function(data) {
8919 return this.append(createItem(data));
8920};
8921
8922List.prototype.insert = function(item, before) {
8923 if (before !== undefined && before !== null) {
8924 // prev before
8925 // ^
8926 // item
8927 this.updateCursors(before.prev, item, before, item);
8928
8929 if (before.prev === null) {
8930 // insert to the beginning of list
8931 if (this.head !== before) {
8932 throw new Error('before doesn\'t belong to list');
8933 }
8934
8935 // since head points to before therefore list doesn't empty
8936 // no need to check tail
8937 this.head = item;
8938 before.prev = item;
8939 item.next = before;
8940
8941 this.updateCursors(null, item);
8942 } else {
8943
8944 // insert between two items
8945 before.prev.next = item;
8946 item.prev = before.prev;
8947
8948 before.prev = item;
8949 item.next = before;
8950 }
8951 } else {
8952 this.append(item);
8953 }
8954};
8955
8956List.prototype.insertData = function(data, before) {
8957 this.insert(createItem(data), before);
8958};
8959
8960List.prototype.remove = function(item) {
8961 // item
8962 // ^
8963 // prev next
8964 this.updateCursors(item, item.prev, item, item.next);
8965
8966 if (item.prev !== null) {
8967 item.prev.next = item.next;
8968 } else {
8969 if (this.head !== item) {
8970 throw new Error('item doesn\'t belong to list');
8971 }
8972
8973 this.head = item.next;
8974 }
8975
8976 if (item.next !== null) {
8977 item.next.prev = item.prev;
8978 } else {
8979 if (this.tail !== item) {
8980 throw new Error('item doesn\'t belong to list');
8981 }
8982
8983 this.tail = item.prev;
8984 }
8985
8986 item.prev = null;
8987 item.next = null;
8988
8989 return item;
8990};
8991
8992List.prototype.appendList = function(list) {
8993 // ignore empty lists
8994 if (list.head === null) {
8995 return;
8996 }
8997
8998 this.updateCursors(this.tail, list.tail, null, list.head);
8999
9000 // insert to end of the list
9001 if (this.tail !== null) {
9002 // if destination list has a tail, then it also has a head,
9003 // but head doesn't change
9004
9005 // dest tail -> source head
9006 this.tail.next = list.head;
9007
9008 // dest tail <- source head
9009 list.head.prev = this.tail;
9010 } else {
9011 // if list has no a tail, then it also has no a head
9012 // in this case points head to new item
9013 this.head = list.head;
9014 }
9015
9016 // tail always start point to new item
9017 this.tail = list.tail;
9018
9019 list.head = null;
9020 list.tail = null;
9021};
9022
9023List.prototype.insertList = function(list, before) {
9024 if (before !== undefined && before !== null) {
9025 // ignore empty lists
9026 if (list.head === null) {
9027 return;
9028 }
9029
9030 this.updateCursors(before.prev, list.tail, before, list.head);
9031
9032 // insert in the middle of dist list
9033 if (before.prev !== null) {
9034 // before.prev <-> list.head
9035 before.prev.next = list.head;
9036 list.head.prev = before.prev;
9037 } else {
9038 this.head = list.head;
9039 }
9040
9041 before.prev = list.tail;
9042 list.tail.next = before;
9043
9044 list.head = null;
9045 list.tail = null;
9046 } else {
9047 this.appendList(list);
9048 }
9049};
9050
9051List.prototype.replace = function(oldItem, newItemOrList) {
9052 if ('head' in newItemOrList) {
9053 this.insertList(newItemOrList, oldItem);
9054 } else {
9055 this.insert(newItemOrList, oldItem);
9056 }
9057 this.remove(oldItem);
9058};
9059
9060var list = List;
9061
9062var TYPE$3 = tokenizer.TYPE;
9063var WHITESPACE$2 = TYPE$3.WhiteSpace;
9064var COMMENT$2 = TYPE$3.Comment;
9065
9066var sequence = function readSequence(recognizer) {
9067 var children = new list();
9068 var child = null;
9069 var context = {
9070 recognizer: recognizer,
9071 space: null,
9072 ignoreWS: false,
9073 ignoreWSAfter: false
9074 };
9075
9076 this.scanner.skipSC();
9077
9078 while (!this.scanner.eof) {
9079 switch (this.scanner.tokenType) {
9080 case COMMENT$2:
9081 this.scanner.next();
9082 continue;
9083
9084 case WHITESPACE$2:
9085 if (context.ignoreWS) {
9086 this.scanner.next();
9087 } else {
9088 context.space = this.WhiteSpace();
9089 }
9090 continue;
9091 }
9092
9093 child = recognizer.getNode.call(this, context);
9094
9095 if (child === undefined) {
9096 break;
9097 }
9098
9099 if (context.space !== null) {
9100 children.appendData(context.space);
9101 context.space = null;
9102 }
9103
9104 children.appendData(child);
9105
9106 if (context.ignoreWSAfter) {
9107 context.ignoreWSAfter = false;
9108 context.ignoreWS = true;
9109 } else {
9110 context.ignoreWS = false;
9111 }
9112 }
9113
9114 return children;
9115};
9116
9117var noop = function() {};
9118
9119function createParseContext(name) {
9120 return function() {
9121 return this[name]();
9122 };
9123}
9124
9125function processConfig(config) {
9126 var parserConfig = {
9127 context: {},
9128 scope: {},
9129 atrule: {},
9130 pseudo: {}
9131 };
9132
9133 if (config.parseContext) {
9134 for (var name in config.parseContext) {
9135 switch (typeof config.parseContext[name]) {
9136 case 'function':
9137 parserConfig.context[name] = config.parseContext[name];
9138 break;
9139
9140 case 'string':
9141 parserConfig.context[name] = createParseContext(config.parseContext[name]);
9142 break;
9143 }
9144 }
9145 }
9146
9147 if (config.scope) {
9148 for (var name in config.scope) {
9149 parserConfig.scope[name] = config.scope[name];
9150 }
9151 }
9152
9153 if (config.atrule) {
9154 for (var name in config.atrule) {
9155 var atrule = config.atrule[name];
9156
9157 if (atrule.parse) {
9158 parserConfig.atrule[name] = atrule.parse;
9159 }
9160 }
9161 }
9162
9163 if (config.pseudo) {
9164 for (var name in config.pseudo) {
9165 var pseudo = config.pseudo[name];
9166
9167 if (pseudo.parse) {
9168 parserConfig.pseudo[name] = pseudo.parse;
9169 }
9170 }
9171 }
9172
9173 if (config.node) {
9174 for (var name in config.node) {
9175 parserConfig[name] = config.node[name].parse;
9176 }
9177 }
9178
9179 return parserConfig;
9180}
9181
9182var create = function createParser(config) {
9183 var parser = {
9184 scanner: new tokenizer(),
9185 filename: '<unknown>',
9186 needPositions: false,
9187 tolerant: false,
9188 onParseError: noop,
9189 parseAtruleExpression: true,
9190 parseSelector: true,
9191 parseValue: true,
9192 parseCustomProperty: false,
9193
9194 readSequence: sequence,
9195
9196 tolerantParse: function(consumer, fallback) {
9197 if (this.tolerant) {
9198 var start = this.scanner.currentToken;
9199
9200 try {
9201 return consumer.call(this);
9202 } catch (e) {
9203 this.onParseError(e);
9204 return fallback.call(this, start);
9205 }
9206 } else {
9207 return consumer.call(this);
9208 }
9209 },
9210
9211 getLocation: function(start, end) {
9212 if (this.needPositions) {
9213 return this.scanner.getLocationRange(
9214 start,
9215 end,
9216 this.filename
9217 );
9218 }
9219
9220 return null;
9221 },
9222 getLocationFromList: function(list) {
9223 if (this.needPositions) {
9224 return this.scanner.getLocationRange(
9225 list.head !== null ? list.first().loc.start.offset - this.scanner.startOffset : this.scanner.tokenStart,
9226 list.head !== null ? list.last().loc.end.offset - this.scanner.startOffset : this.scanner.tokenStart,
9227 this.filename
9228 );
9229 }
9230
9231 return null;
9232 }
9233 };
9234
9235 config = processConfig(config || {});
9236 for (var key in config) {
9237 parser[key] = config[key];
9238 }
9239
9240 return function(source, options) {
9241 options = options || {};
9242
9243 var context = options.context || 'default';
9244 var ast;
9245
9246 parser.scanner.setSource(source, options.offset, options.line, options.column);
9247 parser.filename = options.filename || '<unknown>';
9248 parser.needPositions = Boolean(options.positions);
9249 parser.tolerant = Boolean(options.tolerant);
9250 parser.onParseError = typeof options.onParseError === 'function' ? options.onParseError : noop;
9251 parser.parseAtruleExpression = 'parseAtruleExpression' in options ? Boolean(options.parseAtruleExpression) : true;
9252 parser.parseSelector = 'parseSelector' in options ? Boolean(options.parseSelector) : true;
9253 parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
9254 parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;
9255
9256 if (!parser.context.hasOwnProperty(context)) {
9257 throw new Error('Unknown context `' + context + '`');
9258 }
9259
9260 ast = parser.context[context].call(parser, options);
9261
9262 if (!parser.scanner.eof) {
9263 parser.scanner.error();
9264 }
9265
9266 // console.log(JSON.stringify(ast, null, 4));
9267 return ast;
9268 };
9269};
9270
9271var cmpChar$1 = tokenizer.cmpChar;
9272var TYPE$4 = tokenizer.TYPE;
9273
9274var IDENTIFIER$2 = TYPE$4.Identifier;
9275var STRING$2 = TYPE$4.String;
9276var NUMBER$2 = TYPE$4.Number;
9277var FUNCTION$2 = TYPE$4.Function;
9278var URL$2 = TYPE$4.Url;
9279var NUMBERSIGN = TYPE$4.NumberSign;
9280var LEFTPARENTHESIS$1 = TYPE$4.LeftParenthesis;
9281var LEFTSQUAREBRACKET$1 = TYPE$4.LeftSquareBracket;
9282var PLUSSIGN$2 = TYPE$4.PlusSign;
9283var HYPHENMINUS$2 = TYPE$4.HyphenMinus;
9284var COMMA = TYPE$4.Comma;
9285var SOLIDUS = TYPE$4.Solidus;
9286var ASTERISK = TYPE$4.Asterisk;
9287var PERCENTSIGN = TYPE$4.PercentSign;
9288var BACKSLASH = TYPE$4.Backslash;
9289var U = 117; // 'u'.charCodeAt(0)
9290
9291var _default = function defaultRecognizer(context) {
9292 switch (this.scanner.tokenType) {
9293 case NUMBERSIGN:
9294 return this.HexColor();
9295
9296 case COMMA:
9297 context.space = null;
9298 context.ignoreWSAfter = true;
9299 return this.Operator();
9300
9301 case SOLIDUS:
9302 case ASTERISK:
9303 case PLUSSIGN$2:
9304 case HYPHENMINUS$2:
9305 return this.Operator();
9306
9307 case LEFTPARENTHESIS$1:
9308 return this.Parentheses(this.readSequence, context.recognizer);
9309
9310 case LEFTSQUAREBRACKET$1:
9311 return this.Brackets(this.readSequence, context.recognizer);
9312
9313 case STRING$2:
9314 return this.String();
9315
9316 case NUMBER$2:
9317 switch (this.scanner.lookupType(1)) {
9318 case PERCENTSIGN:
9319 return this.Percentage();
9320
9321 case IDENTIFIER$2:
9322 // edge case: number with folowing \0 and \9 hack shouldn't to be a Dimension
9323 if (cmpChar$1(this.scanner.source, this.scanner.tokenEnd, BACKSLASH)) {
9324 return this.Number();
9325 } else {
9326 return this.Dimension();
9327 }
9328
9329 default:
9330 return this.Number();
9331 }
9332
9333 case FUNCTION$2:
9334 return this.Function(this.readSequence, context.recognizer);
9335
9336 case URL$2:
9337 return this.Url();
9338
9339 case IDENTIFIER$2:
9340 // check for unicode range, it should start with u+ or U+
9341 if (cmpChar$1(this.scanner.source, this.scanner.tokenStart, U) &&
9342 cmpChar$1(this.scanner.source, this.scanner.tokenStart + 1, PLUSSIGN$2)) {
9343 return this.UnicodeRange();
9344 } else {
9345 return this.Identifier();
9346 }
9347 }
9348};
9349
9350var atruleExpression = {
9351 getNode: _default
9352};
9353
9354var TYPE$5 = tokenizer.TYPE;
9355
9356var IDENTIFIER$3 = TYPE$5.Identifier;
9357var NUMBER$3 = TYPE$5.Number;
9358var NUMBERSIGN$1 = TYPE$5.NumberSign;
9359var LEFTSQUAREBRACKET$2 = TYPE$5.LeftSquareBracket;
9360var PLUSSIGN$3 = TYPE$5.PlusSign;
9361var SOLIDUS$1 = TYPE$5.Solidus;
9362var ASTERISK$1 = TYPE$5.Asterisk;
9363var FULLSTOP$2 = TYPE$5.FullStop;
9364var COLON = TYPE$5.Colon;
9365var GREATERTHANSIGN$1 = TYPE$5.GreaterThanSign;
9366var VERTICALLINE = TYPE$5.VerticalLine;
9367var TILDE = TYPE$5.Tilde;
9368
9369function getNode(context) {
9370 switch (this.scanner.tokenType) {
9371 case PLUSSIGN$3:
9372 case GREATERTHANSIGN$1:
9373 case TILDE:
9374 context.space = null;
9375 context.ignoreWSAfter = true;
9376 return this.Combinator();
9377
9378 case SOLIDUS$1: // /deep/
9379 return this.Combinator();
9380
9381 case FULLSTOP$2:
9382 return this.ClassSelector();
9383
9384 case LEFTSQUAREBRACKET$2:
9385 return this.AttributeSelector();
9386
9387 case NUMBERSIGN$1:
9388 return this.IdSelector();
9389
9390 case COLON:
9391 if (this.scanner.lookupType(1) === COLON) {
9392 return this.PseudoElementSelector();
9393 } else {
9394 return this.PseudoClassSelector();
9395 }
9396
9397 case IDENTIFIER$3:
9398 case ASTERISK$1:
9399 case VERTICALLINE:
9400 return this.TypeSelector();
9401
9402 case NUMBER$3:
9403 return this.Percentage();
9404 }
9405}
9406var selector = {
9407 getNode: getNode
9408};
9409
9410// https://drafts.csswg.org/css-images-4/#element-notation
9411// https://developer.mozilla.org/en-US/docs/Web/CSS/element
9412var element = function() {
9413 this.scanner.skipSC();
9414
9415 var id = this.IdSelector();
9416
9417 this.scanner.skipSC();
9418
9419 return new list().appendData(
9420 id
9421 );
9422};
9423
9424// legacy IE function
9425// expression '(' raw ')'
9426var expression = function() {
9427 return new list().appendData(
9428 this.Raw(this.scanner.currentToken, 0, 0, false, false)
9429 );
9430};
9431
9432var TYPE$6 = tokenizer.TYPE;
9433
9434var IDENTIFIER$4 = TYPE$6.Identifier;
9435var COMMA$1 = TYPE$6.Comma;
9436var SEMICOLON = TYPE$6.Semicolon;
9437var HYPHENMINUS$3 = TYPE$6.HyphenMinus;
9438var EXCLAMATIONMARK$1 = TYPE$6.ExclamationMark;
9439
9440// var '(' ident (',' <value>? )? ')'
9441var _var = function() {
9442 var children = new list();
9443
9444 this.scanner.skipSC();
9445
9446 var identStart = this.scanner.tokenStart;
9447
9448 this.scanner.eat(HYPHENMINUS$3);
9449 if (this.scanner.source.charCodeAt(this.scanner.tokenStart) !== HYPHENMINUS$3) {
9450 this.scanner.error('HyphenMinus is expected');
9451 }
9452 this.scanner.eat(IDENTIFIER$4);
9453
9454 children.appendData({
9455 type: 'Identifier',
9456 loc: this.getLocation(identStart, this.scanner.tokenStart),
9457 name: this.scanner.substrToCursor(identStart)
9458 });
9459
9460 this.scanner.skipSC();
9461
9462 if (this.scanner.tokenType === COMMA$1) {
9463 children.appendData(this.Operator());
9464 children.appendData(this.parseCustomProperty
9465 ? this.Value(null)
9466 : this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$1, SEMICOLON, false, false)
9467 );
9468 }
9469
9470 return children;
9471};
9472
9473var value = {
9474 getNode: _default,
9475 '-moz-element': element,
9476 'element': element,
9477 'expression': expression,
9478 'var': _var
9479};
9480
9481var scope = {
9482 AtruleExpression: atruleExpression,
9483 Selector: selector,
9484 Value: value
9485};
9486
9487var fontFace = {
9488 parse: {
9489 expression: null,
9490 block: function() {
9491 return this.Block(this.Declaration);
9492 }
9493 }
9494};
9495
9496var TYPE$7 = tokenizer.TYPE;
9497
9498var STRING$3 = TYPE$7.String;
9499var IDENTIFIER$5 = TYPE$7.Identifier;
9500var URL$3 = TYPE$7.Url;
9501var LEFTPARENTHESIS$2 = TYPE$7.LeftParenthesis;
9502
9503var _import = {
9504 parse: {
9505 expression: function() {
9506 var children = new list();
9507
9508 this.scanner.skipSC();
9509
9510 switch (this.scanner.tokenType) {
9511 case STRING$3:
9512 children.appendData(this.String());
9513 break;
9514
9515 case URL$3:
9516 children.appendData(this.Url());
9517 break;
9518
9519 default:
9520 this.scanner.error('String or url() is expected');
9521 }
9522
9523 if (this.scanner.lookupNonWSType(0) === IDENTIFIER$5 ||
9524 this.scanner.lookupNonWSType(0) === LEFTPARENTHESIS$2) {
9525 children.appendData(this.WhiteSpace());
9526 children.appendData(this.MediaQueryList());
9527 }
9528
9529 return children;
9530 },
9531 block: null
9532 }
9533};
9534
9535var media = {
9536 parse: {
9537 expression: function() {
9538 return new list().appendData(
9539 this.MediaQueryList()
9540 );
9541 },
9542 block: function() {
9543 return this.Block(this.Rule);
9544 }
9545 }
9546};
9547
9548var TYPE$8 = tokenizer.TYPE;
9549var LEFTCURLYBRACKET$1 = TYPE$8.LeftCurlyBracket;
9550
9551var page = {
9552 parse: {
9553 expression: function() {
9554 if (this.scanner.lookupNonWSType(0) === LEFTCURLYBRACKET$1) {
9555 return null;
9556 }
9557
9558 return new list().appendData(
9559 this.SelectorList()
9560 );
9561 },
9562 block: function() {
9563 return this.Block(this.Declaration);
9564 }
9565 }
9566};
9567
9568var TYPE$9 = tokenizer.TYPE;
9569
9570var WHITESPACE$3 = TYPE$9.WhiteSpace;
9571var COMMENT$3 = TYPE$9.Comment;
9572var IDENTIFIER$6 = TYPE$9.Identifier;
9573var FUNCTION$3 = TYPE$9.Function;
9574var LEFTPARENTHESIS$3 = TYPE$9.LeftParenthesis;
9575var HYPHENMINUS$4 = TYPE$9.HyphenMinus;
9576var COLON$1 = TYPE$9.Colon;
9577
9578function consumeRaw() {
9579 return new list().appendData(
9580 this.Raw(this.scanner.currentToken, 0, 0, false, false)
9581 );
9582}
9583
9584function parentheses() {
9585 var index = 0;
9586
9587 this.scanner.skipSC();
9588
9589 // TODO: make it simplier
9590 if (this.scanner.tokenType === IDENTIFIER$6) {
9591 index = 1;
9592 } else if (this.scanner.tokenType === HYPHENMINUS$4 &&
9593 this.scanner.lookupType(1) === IDENTIFIER$6) {
9594 index = 2;
9595 }
9596
9597 if (index !== 0 && this.scanner.lookupNonWSType(index) === COLON$1) {
9598 return new list().appendData(
9599 this.Declaration()
9600 );
9601 }
9602
9603 return readSequence.call(this);
9604}
9605
9606function readSequence() {
9607 var children = new list();
9608 var space = null;
9609 var child;
9610
9611 this.scanner.skipSC();
9612
9613 scan:
9614 while (!this.scanner.eof) {
9615 switch (this.scanner.tokenType) {
9616 case WHITESPACE$3:
9617 space = this.WhiteSpace();
9618 continue;
9619
9620 case COMMENT$3:
9621 this.scanner.next();
9622 continue;
9623
9624 case FUNCTION$3:
9625 child = this.Function(consumeRaw, this.scope.AtruleExpression);
9626 break;
9627
9628 case IDENTIFIER$6:
9629 child = this.Identifier();
9630 break;
9631
9632 case LEFTPARENTHESIS$3:
9633 child = this.Parentheses(parentheses, this.scope.AtruleExpression);
9634 break;
9635
9636 default:
9637 break scan;
9638 }
9639
9640 if (space !== null) {
9641 children.appendData(space);
9642 space = null;
9643 }
9644
9645 children.appendData(child);
9646 }
9647
9648 return children;
9649}
9650
9651var supports = {
9652 parse: {
9653 expression: function() {
9654 var children = readSequence.call(this);
9655
9656 if (children.isEmpty()) {
9657 this.scanner.error('Condition is expected');
9658 }
9659
9660 return children;
9661 },
9662 block: function() {
9663 return this.Block(this.Rule);
9664 }
9665 }
9666};
9667
9668var atrule = {
9669 'font-face': fontFace,
9670 'import': _import,
9671 'media': media,
9672 'page': page,
9673 'supports': supports
9674};
9675
9676var dir = {
9677 parse: function() {
9678 return new list().appendData(
9679 this.Identifier()
9680 );
9681 }
9682};
9683
9684var has$1 = {
9685 parse: function() {
9686 return new list().appendData(
9687 this.SelectorList()
9688 );
9689 }
9690};
9691
9692var lang = {
9693 parse: function() {
9694 return new list().appendData(
9695 this.Identifier()
9696 );
9697 }
9698};
9699
9700var selectorList = {
9701 parse: function selectorList() {
9702 return new list().appendData(
9703 this.SelectorList()
9704 );
9705 }
9706};
9707
9708var matches = selectorList;
9709
9710var not = selectorList;
9711
9712var ALLOW_OF_CLAUSE = true;
9713
9714var nthWithOfClause = {
9715 parse: function() {
9716 return new list().appendData(
9717 this.Nth(ALLOW_OF_CLAUSE)
9718 );
9719 }
9720};
9721
9722var nthChild = nthWithOfClause;
9723
9724var nthLastChild = nthWithOfClause;
9725
9726var DISALLOW_OF_CLAUSE = false;
9727
9728var nth = {
9729 parse: function nth() {
9730 return new list().appendData(
9731 this.Nth(DISALLOW_OF_CLAUSE)
9732 );
9733 }
9734};
9735
9736var nthLastOfType = nth;
9737
9738var nthOfType = nth;
9739
9740var slotted = {
9741 parse: function compoundSelector() {
9742 return new list().appendData(
9743 this.Selector()
9744 );
9745 }
9746};
9747
9748var pseudo = {
9749 'dir': dir,
9750 'has': has$1,
9751 'lang': lang,
9752 'matches': matches,
9753 'not': not,
9754 'nth-child': nthChild,
9755 'nth-last-child': nthLastChild,
9756 'nth-last-of-type': nthLastOfType,
9757 'nth-of-type': nthOfType,
9758 'slotted': slotted
9759};
9760
9761var cmpChar$2 = tokenizer.cmpChar;
9762var isNumber$2 = tokenizer.isNumber;
9763var TYPE$a = tokenizer.TYPE;
9764
9765var IDENTIFIER$7 = TYPE$a.Identifier;
9766var NUMBER$4 = TYPE$a.Number;
9767var PLUSSIGN$4 = TYPE$a.PlusSign;
9768var HYPHENMINUS$5 = TYPE$a.HyphenMinus;
9769var N$3 = 110; // 'n'.charCodeAt(0)
9770var DISALLOW_SIGN = true;
9771var ALLOW_SIGN = false;
9772
9773function checkTokenIsInteger(scanner, disallowSign) {
9774 var pos = scanner.tokenStart;
9775
9776 if (scanner.source.charCodeAt(pos) === PLUSSIGN$4 ||
9777 scanner.source.charCodeAt(pos) === HYPHENMINUS$5) {
9778 if (disallowSign) {
9779 scanner.error();
9780 }
9781 pos++;
9782 }
9783
9784 for (; pos < scanner.tokenEnd; pos++) {
9785 if (!isNumber$2(scanner.source.charCodeAt(pos))) {
9786 scanner.error('Unexpected input', pos);
9787 }
9788 }
9789}
9790
9791// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
9792var AnPlusB = {
9793 name: 'AnPlusB',
9794 structure: {
9795 a: [String, null],
9796 b: [String, null]
9797 },
9798 parse: function() {
9799 var start = this.scanner.tokenStart;
9800 var end = start;
9801 var prefix = '';
9802 var a = null;
9803 var b = null;
9804
9805 if (this.scanner.tokenType === NUMBER$4 ||
9806 this.scanner.tokenType === PLUSSIGN$4) {
9807 checkTokenIsInteger(this.scanner, ALLOW_SIGN);
9808 prefix = this.scanner.getTokenValue();
9809 this.scanner.next();
9810 end = this.scanner.tokenStart;
9811 }
9812
9813 if (this.scanner.tokenType === IDENTIFIER$7) {
9814 var bStart = this.scanner.tokenStart;
9815
9816 if (cmpChar$2(this.scanner.source, bStart, HYPHENMINUS$5)) {
9817 if (prefix === '') {
9818 prefix = '-';
9819 bStart++;
9820 } else {
9821 this.scanner.error('Unexpected hyphen minus');
9822 }
9823 }
9824
9825 if (!cmpChar$2(this.scanner.source, bStart, N$3)) {
9826 this.scanner.error();
9827 }
9828
9829 a = prefix === '' ? '1' :
9830 prefix === '+' ? '+1' :
9831 prefix === '-' ? '-1' :
9832 prefix;
9833
9834 var len = this.scanner.tokenEnd - bStart;
9835 if (len > 1) {
9836 // ..n-..
9837 if (this.scanner.source.charCodeAt(bStart + 1) !== HYPHENMINUS$5) {
9838 this.scanner.error('Unexpected input', bStart + 1);
9839 }
9840
9841 if (len > 2) {
9842 // ..n-{number}..
9843 this.scanner.tokenStart = bStart + 2;
9844 } else {
9845 // ..n- {number}
9846 this.scanner.next();
9847 this.scanner.skipSC();
9848 }
9849
9850 checkTokenIsInteger(this.scanner, DISALLOW_SIGN);
9851 b = '-' + this.scanner.getTokenValue();
9852 this.scanner.next();
9853 end = this.scanner.tokenStart;
9854 } else {
9855 prefix = '';
9856 this.scanner.next();
9857 end = this.scanner.tokenStart;
9858 this.scanner.skipSC();
9859
9860 if (this.scanner.tokenType === HYPHENMINUS$5 ||
9861 this.scanner.tokenType === PLUSSIGN$4) {
9862 prefix = this.scanner.getTokenValue();
9863 this.scanner.next();
9864 this.scanner.skipSC();
9865 }
9866
9867 if (this.scanner.tokenType === NUMBER$4) {
9868 checkTokenIsInteger(this.scanner, prefix !== '');
9869
9870 if (!isNumber$2(this.scanner.source.charCodeAt(this.scanner.tokenStart))) {
9871 prefix = this.scanner.source.charAt(this.scanner.tokenStart);
9872 this.scanner.tokenStart++;
9873 }
9874
9875 if (prefix === '') {
9876 // should be an operator before number
9877 this.scanner.error();
9878 } else if (prefix === '+') {
9879 // plus is using by default
9880 prefix = '';
9881 }
9882
9883 b = prefix + this.scanner.getTokenValue();
9884
9885 this.scanner.next();
9886 end = this.scanner.tokenStart;
9887 } else {
9888 if (prefix) {
9889 this.scanner.eat(NUMBER$4);
9890 }
9891 }
9892 }
9893 } else {
9894 if (prefix === '' || prefix === '+') { // no number
9895 this.scanner.error(
9896 'Number or identifier is expected',
9897 this.scanner.tokenStart + (
9898 this.scanner.tokenType === PLUSSIGN$4 ||
9899 this.scanner.tokenType === HYPHENMINUS$5
9900 )
9901 );
9902 }
9903
9904 b = prefix;
9905 }
9906
9907 return {
9908 type: 'AnPlusB',
9909 loc: this.getLocation(start, end),
9910 a: a,
9911 b: b
9912 };
9913 },
9914 generate: function(processChunk, node) {
9915 var a = node.a !== null && node.a !== undefined;
9916 var b = node.b !== null && node.b !== undefined;
9917
9918 if (a) {
9919 processChunk(
9920 node.a === '+1' ? '+n' :
9921 node.a === '1' ? 'n' :
9922 node.a === '-1' ? '-n' :
9923 node.a + 'n'
9924 );
9925
9926 if (b) {
9927 b = String(node.b);
9928 if (b.charAt(0) === '-' || b.charAt(0) === '+') {
9929 processChunk(b.charAt(0));
9930 processChunk(b.substr(1));
9931 } else {
9932 processChunk('+');
9933 processChunk(b);
9934 }
9935 }
9936 } else {
9937 processChunk(String(node.b));
9938 }
9939 }
9940};
9941
9942var TYPE$b = tokenizer.TYPE;
9943
9944var ATRULE$2 = TYPE$b.Atrule;
9945var SEMICOLON$1 = TYPE$b.Semicolon;
9946var LEFTCURLYBRACKET$2 = TYPE$b.LeftCurlyBracket;
9947var RIGHTCURLYBRACKET$1 = TYPE$b.RightCurlyBracket;
9948
9949function isBlockAtrule() {
9950 for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) {
9951 if (type === RIGHTCURLYBRACKET$1) {
9952 return true;
9953 }
9954
9955 if (type === LEFTCURLYBRACKET$2 ||
9956 type === ATRULE$2) {
9957 return false;
9958 }
9959 }
9960
9961 this.scanner.skip(offset);
9962 this.scanner.eat(RIGHTCURLYBRACKET$1);
9963}
9964
9965var Atrule = {
9966 name: 'Atrule',
9967 structure: {
9968 name: String,
9969 expression: ['AtruleExpression', null],
9970 block: ['Block', null]
9971 },
9972 parse: function() {
9973 var start = this.scanner.tokenStart;
9974 var name;
9975 var nameLowerCase;
9976 var expression = null;
9977 var block = null;
9978
9979 this.scanner.eat(ATRULE$2);
9980
9981 name = this.scanner.substrToCursor(start + 1);
9982 nameLowerCase = name.toLowerCase();
9983 this.scanner.skipSC();
9984
9985 expression = this.AtruleExpression(name);
9986
9987 // turn empty AtruleExpression into null
9988 if (expression.children.head === null) {
9989 expression = null;
9990 }
9991
9992 this.scanner.skipSC();
9993
9994 if (this.atrule.hasOwnProperty(nameLowerCase)) {
9995 if (typeof this.atrule[nameLowerCase].block === 'function') {
9996 if (this.scanner.tokenType !== LEFTCURLYBRACKET$2) {
9997 // FIXME: make tolerant
9998 this.scanner.error('Curly bracket is expected');
9999 }
10000
10001 block = this.atrule[nameLowerCase].block.call(this);
10002 } else {
10003 if (!this.tolerant || !this.scanner.eof) {
10004 this.scanner.eat(SEMICOLON$1);
10005 }
10006 }
10007 } else {
10008 switch (this.scanner.tokenType) {
10009 case SEMICOLON$1:
10010 this.scanner.next();
10011 break;
10012
10013 case LEFTCURLYBRACKET$2:
10014 // TODO: should consume block content as Raw?
10015 block = this.Block(isBlockAtrule.call(this) ? this.Declaration : this.Rule);
10016 break;
10017
10018 default:
10019 if (!this.tolerant) {
10020 this.scanner.error('Semicolon or block is expected');
10021 }
10022 }
10023 }
10024
10025 return {
10026 type: 'Atrule',
10027 loc: this.getLocation(start, this.scanner.tokenStart),
10028 name: name,
10029 expression: expression,
10030 block: block
10031 };
10032 },
10033 generate: function(processChunk, node) {
10034 processChunk('@');
10035 processChunk(node.name);
10036
10037 if (node.expression !== null) {
10038 processChunk(' ');
10039 this.generate(processChunk, node.expression);
10040 }
10041
10042 if (node.block) {
10043 this.generate(processChunk, node.block);
10044 } else {
10045 processChunk(';');
10046 }
10047 },
10048 walkContext: 'atrule'
10049};
10050
10051var TYPE$c = tokenizer.TYPE;
10052var SEMICOLON$2 = TYPE$c.Semicolon;
10053var LEFTCURLYBRACKET$3 = TYPE$c.LeftCurlyBracket;
10054
10055function consumeRaw$1(startToken) {
10056 return new list().appendData(
10057 this.Raw(startToken, SEMICOLON$2, LEFTCURLYBRACKET$3, false, true)
10058 );
10059}
10060
10061function consumeDefaultSequence() {
10062 return this.readSequence(this.scope.AtruleExpression);
10063}
10064
10065var AtruleExpression = {
10066 name: 'AtruleExpression',
10067 structure: {
10068 children: [[]]
10069 },
10070 parse: function(name) {
10071 var children = null;
10072 var startToken = this.scanner.currentToken;
10073
10074 if (name !== null) {
10075 name = name.toLowerCase();
10076 }
10077
10078 if (this.parseAtruleExpression) {
10079 // custom consumer
10080 if (this.atrule.hasOwnProperty(name)) {
10081 if (typeof this.atrule[name].expression === 'function') {
10082 children = this.tolerantParse(this.atrule[name].expression, consumeRaw$1);
10083 }
10084 } else {
10085 // default consumer
10086 this.scanner.skipSC();
10087 children = this.tolerantParse(consumeDefaultSequence, consumeRaw$1);
10088 }
10089
10090 if (this.tolerant) {
10091 if (this.scanner.eof || (this.scanner.tokenType !== SEMICOLON$2 && this.scanner.tokenType !== LEFTCURLYBRACKET$3)) {
10092 children = consumeRaw$1.call(this, startToken);
10093 }
10094 }
10095 } else {
10096 children = consumeRaw$1.call(this, startToken);
10097 }
10098
10099 if (children === null) {
10100 children = new list();
10101 }
10102
10103 return {
10104 type: 'AtruleExpression',
10105 loc: this.getLocationFromList(children),
10106 children: children
10107 };
10108 },
10109 generate: function(processChunk, node) {
10110 this.each(processChunk, node);
10111 },
10112 walkContext: 'atruleExpression'
10113};
10114
10115var TYPE$d = tokenizer.TYPE;
10116
10117var IDENTIFIER$8 = TYPE$d.Identifier;
10118var STRING$4 = TYPE$d.String;
10119var DOLLARSIGN = TYPE$d.DollarSign;
10120var ASTERISK$2 = TYPE$d.Asterisk;
10121var COLON$2 = TYPE$d.Colon;
10122var EQUALSSIGN = TYPE$d.EqualsSign;
10123var LEFTSQUAREBRACKET$3 = TYPE$d.LeftSquareBracket;
10124var RIGHTSQUAREBRACKET$1 = TYPE$d.RightSquareBracket;
10125var CIRCUMFLEXACCENT = TYPE$d.CircumflexAccent;
10126var VERTICALLINE$1 = TYPE$d.VerticalLine;
10127var TILDE$1 = TYPE$d.Tilde;
10128
10129function getAttributeName() {
10130 if (this.scanner.eof) {
10131 this.scanner.error('Unexpected end of input');
10132 }
10133
10134 var start = this.scanner.tokenStart;
10135 var expectIdentifier = false;
10136 var checkColon = true;
10137
10138 if (this.scanner.tokenType === ASTERISK$2) {
10139 expectIdentifier = true;
10140 checkColon = false;
10141 this.scanner.next();
10142 } else if (this.scanner.tokenType !== VERTICALLINE$1) {
10143 this.scanner.eat(IDENTIFIER$8);
10144 }
10145
10146 if (this.scanner.tokenType === VERTICALLINE$1) {
10147 if (this.scanner.lookupType(1) !== EQUALSSIGN) {
10148 this.scanner.next();
10149 this.scanner.eat(IDENTIFIER$8);
10150 } else if (expectIdentifier) {
10151 this.scanner.error('Identifier is expected', this.scanner.tokenEnd);
10152 }
10153 } else if (expectIdentifier) {
10154 this.scanner.error('Vertical line is expected');
10155 }
10156
10157 if (checkColon && this.scanner.tokenType === COLON$2) {
10158 this.scanner.next();
10159 this.scanner.eat(IDENTIFIER$8);
10160 }
10161
10162 return {
10163 type: 'Identifier',
10164 loc: this.getLocation(start, this.scanner.tokenStart),
10165 name: this.scanner.substrToCursor(start)
10166 };
10167}
10168
10169function getOperator() {
10170 var start = this.scanner.tokenStart;
10171 var tokenType = this.scanner.tokenType;
10172
10173 if (tokenType !== EQUALSSIGN && // =
10174 tokenType !== TILDE$1 && // ~=
10175 tokenType !== CIRCUMFLEXACCENT && // ^=
10176 tokenType !== DOLLARSIGN && // $=
10177 tokenType !== ASTERISK$2 && // *=
10178 tokenType !== VERTICALLINE$1 // |=
10179 ) {
10180 this.scanner.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
10181 }
10182
10183 if (tokenType === EQUALSSIGN) {
10184 this.scanner.next();
10185 } else {
10186 this.scanner.next();
10187 this.scanner.eat(EQUALSSIGN);
10188 }
10189
10190 return this.scanner.substrToCursor(start);
10191}
10192
10193// '[' S* attrib_name ']'
10194// '[' S* attrib_name S* attrib_matcher S* [ IDENT | STRING ] S* attrib_flags? S* ']'
10195var AttributeSelector = {
10196 name: 'AttributeSelector',
10197 structure: {
10198 name: 'Identifier',
10199 matcher: [String, null],
10200 value: ['String', 'Identifier', null],
10201 flags: [String, null]
10202 },
10203 parse: function() {
10204 var start = this.scanner.tokenStart;
10205 var name;
10206 var matcher = null;
10207 var value = null;
10208 var flags = null;
10209
10210 this.scanner.eat(LEFTSQUAREBRACKET$3);
10211 this.scanner.skipSC();
10212
10213 name = getAttributeName.call(this);
10214 this.scanner.skipSC();
10215
10216 if (this.scanner.tokenType !== RIGHTSQUAREBRACKET$1) {
10217 // avoid case `[name i]`
10218 if (this.scanner.tokenType !== IDENTIFIER$8) {
10219 matcher = getOperator.call(this);
10220
10221 this.scanner.skipSC();
10222
10223 value = this.scanner.tokenType === STRING$4
10224 ? this.String()
10225 : this.Identifier();
10226
10227 this.scanner.skipSC();
10228 }
10229
10230 // attribute flags
10231 if (this.scanner.tokenType === IDENTIFIER$8) {
10232 flags = this.scanner.getTokenValue();
10233 this.scanner.next();
10234
10235 this.scanner.skipSC();
10236 }
10237 }
10238
10239 this.scanner.eat(RIGHTSQUAREBRACKET$1);
10240
10241 return {
10242 type: 'AttributeSelector',
10243 loc: this.getLocation(start, this.scanner.tokenStart),
10244 name: name,
10245 matcher: matcher,
10246 value: value,
10247 flags: flags
10248 };
10249 },
10250 generate: function(processChunk, node) {
10251 var flagsPrefix = ' ';
10252
10253 processChunk('[');
10254 this.generate(processChunk, node.name);
10255
10256 if (node.matcher !== null) {
10257 processChunk(node.matcher);
10258
10259 if (node.value !== null) {
10260 this.generate(processChunk, node.value);
10261
10262 // space between string and flags is not required
10263 if (node.value.type === 'String') {
10264 flagsPrefix = '';
10265 }
10266 }
10267 }
10268
10269 if (node.flags !== null) {
10270 processChunk(flagsPrefix);
10271 processChunk(node.flags);
10272 }
10273
10274 processChunk(']');
10275 }
10276};
10277
10278var TYPE$e = tokenizer.TYPE;
10279
10280var WHITESPACE$4 = TYPE$e.WhiteSpace;
10281var COMMENT$4 = TYPE$e.Comment;
10282var SEMICOLON$3 = TYPE$e.Semicolon;
10283var ATRULE$3 = TYPE$e.Atrule;
10284var LEFTCURLYBRACKET$4 = TYPE$e.LeftCurlyBracket;
10285var RIGHTCURLYBRACKET$2 = TYPE$e.RightCurlyBracket;
10286
10287function consumeRaw$2(startToken) {
10288 return this.Raw(startToken, 0, SEMICOLON$3, true, true);
10289}
10290
10291var Block = {
10292 name: 'Block',
10293 structure: {
10294 children: [['Atrule', 'Rule', 'Declaration']]
10295 },
10296 parse: function(defaultConsumer) {
10297 if (!defaultConsumer) {
10298 defaultConsumer = this.Declaration;
10299 }
10300
10301 var start = this.scanner.tokenStart;
10302 var children = new list();
10303
10304 this.scanner.eat(LEFTCURLYBRACKET$4);
10305
10306 scan:
10307 while (!this.scanner.eof) {
10308 switch (this.scanner.tokenType) {
10309 case RIGHTCURLYBRACKET$2:
10310 break scan;
10311
10312 case WHITESPACE$4:
10313 case COMMENT$4:
10314 case SEMICOLON$3:
10315 this.scanner.next();
10316 break;
10317
10318 case ATRULE$3:
10319 children.appendData(this.tolerantParse(this.Atrule, consumeRaw$2));
10320 break;
10321
10322 default:
10323 children.appendData(this.tolerantParse(defaultConsumer, consumeRaw$2));
10324 }
10325 }
10326
10327 if (!this.tolerant || !this.scanner.eof) {
10328 this.scanner.eat(RIGHTCURLYBRACKET$2);
10329 }
10330
10331 return {
10332 type: 'Block',
10333 loc: this.getLocation(start, this.scanner.tokenStart),
10334 children: children
10335 };
10336 },
10337 generate: function(processChunk, node) {
10338 processChunk('{');
10339 this.each(processChunk, node);
10340 processChunk('}');
10341 },
10342 walkContext: 'block'
10343};
10344
10345var TYPE$f = tokenizer.TYPE;
10346var LEFTSQUAREBRACKET$4 = TYPE$f.LeftSquareBracket;
10347var RIGHTSQUAREBRACKET$2 = TYPE$f.RightSquareBracket;
10348
10349// currently only Grid Layout uses square brackets, but left it universal
10350// https://drafts.csswg.org/css-grid/#track-sizing
10351// [ ident* ]
10352var Brackets = {
10353 name: 'Brackets',
10354 structure: {
10355 children: [[]]
10356 },
10357 parse: function(readSequence, recognizer) {
10358 var start = this.scanner.tokenStart;
10359 var children = null;
10360
10361 this.scanner.eat(LEFTSQUAREBRACKET$4);
10362 children = readSequence.call(this, recognizer);
10363 this.scanner.eat(RIGHTSQUAREBRACKET$2);
10364
10365 return {
10366 type: 'Brackets',
10367 loc: this.getLocation(start, this.scanner.tokenStart),
10368 children: children
10369 };
10370 },
10371 generate: function(processChunk, node) {
10372 processChunk('[');
10373 this.each(processChunk, node);
10374 processChunk(']');
10375 }
10376};
10377
10378var CDC$2 = tokenizer.TYPE.CDC;
10379
10380var CDC_1 = {
10381 name: 'CDC',
10382 structure: [],
10383 parse: function() {
10384 var start = this.scanner.tokenStart;
10385
10386 this.scanner.eat(CDC$2); // -->
10387
10388 return {
10389 type: 'CDC',
10390 loc: this.getLocation(start, this.scanner.tokenStart)
10391 };
10392 },
10393 generate: function(processChunk) {
10394 processChunk('-->');
10395 }
10396};
10397
10398var CDO$2 = tokenizer.TYPE.CDO;
10399
10400var CDO_1 = {
10401 name: 'CDO',
10402 structure: [],
10403 parse: function() {
10404 var start = this.scanner.tokenStart;
10405
10406 this.scanner.eat(CDO$2); // <!--
10407
10408 return {
10409 type: 'CDO',
10410 loc: this.getLocation(start, this.scanner.tokenStart)
10411 };
10412 },
10413 generate: function(processChunk) {
10414 processChunk('<!--');
10415 }
10416};
10417
10418var TYPE$g = tokenizer.TYPE;
10419var IDENTIFIER$9 = TYPE$g.Identifier;
10420var FULLSTOP$3 = TYPE$g.FullStop;
10421
10422// '.' ident
10423var ClassSelector = {
10424 name: 'ClassSelector',
10425 structure: {
10426 name: String
10427 },
10428 parse: function() {
10429 this.scanner.eat(FULLSTOP$3);
10430
10431 return {
10432 type: 'ClassSelector',
10433 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10434 name: this.scanner.consume(IDENTIFIER$9)
10435 };
10436 },
10437 generate: function(processChunk, node) {
10438 processChunk('.');
10439 processChunk(node.name);
10440 }
10441};
10442
10443var TYPE$h = tokenizer.TYPE;
10444
10445var PLUSSIGN$5 = TYPE$h.PlusSign;
10446var SOLIDUS$2 = TYPE$h.Solidus;
10447var GREATERTHANSIGN$2 = TYPE$h.GreaterThanSign;
10448var TILDE$2 = TYPE$h.Tilde;
10449
10450// + | > | ~ | /deep/
10451var Combinator = {
10452 name: 'Combinator',
10453 structure: {
10454 name: String
10455 },
10456 parse: function() {
10457 var start = this.scanner.tokenStart;
10458
10459 switch (this.scanner.tokenType) {
10460 case GREATERTHANSIGN$2:
10461 case PLUSSIGN$5:
10462 case TILDE$2:
10463 this.scanner.next();
10464 break;
10465
10466 case SOLIDUS$2:
10467 this.scanner.next();
10468 this.scanner.expectIdentifier('deep');
10469 this.scanner.eat(SOLIDUS$2);
10470 break;
10471
10472 default:
10473 this.scanner.error('Combinator is expected');
10474 }
10475
10476 return {
10477 type: 'Combinator',
10478 loc: this.getLocation(start, this.scanner.tokenStart),
10479 name: this.scanner.substrToCursor(start)
10480 };
10481 },
10482 generate: function(processChunk, node) {
10483 processChunk(node.name);
10484 }
10485};
10486
10487var TYPE$i = tokenizer.TYPE;
10488
10489var ASTERISK$3 = TYPE$i.Asterisk;
10490var SOLIDUS$3 = TYPE$i.Solidus;
10491
10492// '/*' .* '*/'
10493var Comment = {
10494 name: 'Comment',
10495 structure: {
10496 value: String
10497 },
10498 parse: function() {
10499 var start = this.scanner.tokenStart;
10500 var end = this.scanner.tokenEnd;
10501
10502 if ((end - start + 2) >= 2 &&
10503 this.scanner.source.charCodeAt(end - 2) === ASTERISK$3 &&
10504 this.scanner.source.charCodeAt(end - 1) === SOLIDUS$3) {
10505 end -= 2;
10506 }
10507
10508 this.scanner.next();
10509
10510 return {
10511 type: 'Comment',
10512 loc: this.getLocation(start, this.scanner.tokenStart),
10513 value: this.scanner.source.substring(start + 2, end)
10514 };
10515 },
10516 generate: function(processChunk, node) {
10517 processChunk('/*');
10518 processChunk(node.value);
10519 processChunk('*/');
10520 }
10521};
10522
10523var TYPE$j = tokenizer.TYPE;
10524
10525var IDENTIFIER$a = TYPE$j.Identifier;
10526var COLON$3 = TYPE$j.Colon;
10527var EXCLAMATIONMARK$2 = TYPE$j.ExclamationMark;
10528var SOLIDUS$4 = TYPE$j.Solidus;
10529var ASTERISK$4 = TYPE$j.Asterisk;
10530var DOLLARSIGN$1 = TYPE$j.DollarSign;
10531var HYPHENMINUS$6 = TYPE$j.HyphenMinus;
10532var SEMICOLON$4 = TYPE$j.Semicolon;
10533var RIGHTCURLYBRACKET$3 = TYPE$j.RightCurlyBracket;
10534var RIGHTPARENTHESIS$1 = TYPE$j.RightParenthesis;
10535var PLUSSIGN$6 = TYPE$j.PlusSign;
10536var NUMBERSIGN$2 = TYPE$j.NumberSign;
10537
10538var Declaration = {
10539 name: 'Declaration',
10540 structure: {
10541 important: [Boolean, String],
10542 property: String,
10543 value: ['Value', 'Raw']
10544 },
10545 parse: function() {
10546 var start = this.scanner.tokenStart;
10547 var property = readProperty.call(this);
10548 var important = false;
10549 var value;
10550
10551 this.scanner.skipSC();
10552 this.scanner.eat(COLON$3);
10553
10554 if (isCustomProperty(property) ? this.parseCustomProperty : this.parseValue) {
10555 value = this.Value(property);
10556 } else {
10557 value = this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$2, SEMICOLON$4, false, false);
10558 }
10559
10560 if (this.scanner.tokenType === EXCLAMATIONMARK$2) {
10561 important = getImportant(this.scanner);
10562 this.scanner.skipSC();
10563 }
10564
10565 // TODO: include or not to include semicolon to range?
10566 // if (this.scanner.tokenType === SEMICOLON) {
10567 // this.scanner.next();
10568 // }
10569
10570 if (!this.scanner.eof &&
10571 this.scanner.tokenType !== SEMICOLON$4 &&
10572 this.scanner.tokenType !== RIGHTPARENTHESIS$1 &&
10573 this.scanner.tokenType !== RIGHTCURLYBRACKET$3) {
10574 this.scanner.error();
10575 }
10576
10577 return {
10578 type: 'Declaration',
10579 loc: this.getLocation(start, this.scanner.tokenStart),
10580 important: important,
10581 property: property,
10582 value: value
10583 };
10584 },
10585 generate: function(processChunk, node, item) {
10586 processChunk(node.property);
10587 processChunk(':');
10588 this.generate(processChunk, node.value);
10589
10590 if (node.important) {
10591 processChunk(node.important === true ? '!important' : '!' + node.important);
10592 }
10593
10594 if (item && item.next) {
10595 processChunk(';');
10596 }
10597 },
10598 walkContext: 'declaration'
10599};
10600
10601function isCustomProperty(name) {
10602 return name.length >= 2 &&
10603 name.charCodeAt(0) === HYPHENMINUS$6 &&
10604 name.charCodeAt(1) === HYPHENMINUS$6;
10605}
10606
10607function readProperty() {
10608 var start = this.scanner.tokenStart;
10609 var prefix = 0;
10610
10611 // hacks
10612 switch (this.scanner.tokenType) {
10613 case ASTERISK$4:
10614 case DOLLARSIGN$1:
10615 case PLUSSIGN$6:
10616 case NUMBERSIGN$2:
10617 prefix = 1;
10618 break;
10619
10620 // TODO: not sure we should support this hack
10621 case SOLIDUS$4:
10622 prefix = this.scanner.lookupType(1) === SOLIDUS$4 ? 2 : 1;
10623 break;
10624 }
10625
10626 if (this.scanner.lookupType(prefix) === HYPHENMINUS$6) {
10627 prefix++;
10628 }
10629
10630 if (prefix) {
10631 this.scanner.skip(prefix);
10632 }
10633
10634 this.scanner.eat(IDENTIFIER$a);
10635
10636 return this.scanner.substrToCursor(start);
10637}
10638
10639// ! ws* important
10640function getImportant(scanner) {
10641 scanner.eat(EXCLAMATIONMARK$2);
10642 scanner.skipSC();
10643
10644 var important = scanner.consume(IDENTIFIER$a);
10645
10646 // store original value in case it differ from `important`
10647 // for better original source restoring and hacks like `!ie` support
10648 return important === 'important' ? true : important;
10649}
10650
10651var TYPE$k = tokenizer.TYPE;
10652
10653var WHITESPACE$5 = TYPE$k.WhiteSpace;
10654var COMMENT$5 = TYPE$k.Comment;
10655var SEMICOLON$5 = TYPE$k.Semicolon;
10656
10657function consumeRaw$3(startToken) {
10658 return this.Raw(startToken, 0, SEMICOLON$5, true, true);
10659}
10660
10661var DeclarationList = {
10662 name: 'DeclarationList',
10663 structure: {
10664 children: [['Declaration']]
10665 },
10666 parse: function() {
10667 var children = new list();
10668
10669
10670 while (!this.scanner.eof) {
10671 switch (this.scanner.tokenType) {
10672 case WHITESPACE$5:
10673 case COMMENT$5:
10674 case SEMICOLON$5:
10675 this.scanner.next();
10676 break;
10677
10678 default:
10679 children.appendData(this.tolerantParse(this.Declaration, consumeRaw$3));
10680 }
10681 }
10682
10683 return {
10684 type: 'DeclarationList',
10685 loc: this.getLocationFromList(children),
10686 children: children
10687 };
10688 },
10689 generate: function(processChunk, node) {
10690 this.each(processChunk, node);
10691 }
10692};
10693
10694var NUMBER$5 = tokenizer.TYPE.Number;
10695
10696// special reader for units to avoid adjoined IE hacks (i.e. '1px\9')
10697function readUnit(scanner) {
10698 var unit = scanner.getTokenValue();
10699 var backSlashPos = unit.indexOf('\\');
10700
10701 if (backSlashPos > 0) {
10702 // patch token offset
10703 scanner.tokenStart += backSlashPos;
10704
10705 // return part before backslash
10706 return unit.substring(0, backSlashPos);
10707 }
10708
10709 // no backslash in unit name
10710 scanner.next();
10711
10712 return unit;
10713}
10714
10715// number ident
10716var Dimension = {
10717 name: 'Dimension',
10718 structure: {
10719 value: String,
10720 unit: String
10721 },
10722 parse: function() {
10723 var start = this.scanner.tokenStart;
10724 var value = this.scanner.consume(NUMBER$5);
10725 var unit = readUnit(this.scanner);
10726
10727 return {
10728 type: 'Dimension',
10729 loc: this.getLocation(start, this.scanner.tokenStart),
10730 value: value,
10731 unit: unit
10732 };
10733 },
10734 generate: function(processChunk, node) {
10735 processChunk(node.value);
10736 processChunk(node.unit);
10737 }
10738};
10739
10740var TYPE$l = tokenizer.TYPE;
10741var RIGHTPARENTHESIS$2 = TYPE$l.RightParenthesis;
10742
10743// <function-token> <sequence> ')'
10744var _Function = {
10745 name: 'Function',
10746 structure: {
10747 name: String,
10748 children: [[]]
10749 },
10750 parse: function(readSequence, recognizer) {
10751 var start = this.scanner.tokenStart;
10752 var name = this.scanner.consumeFunctionName();
10753 var nameLowerCase = name.toLowerCase();
10754 var children;
10755
10756 children = recognizer.hasOwnProperty(nameLowerCase)
10757 ? recognizer[nameLowerCase].call(this, recognizer)
10758 : readSequence.call(this, recognizer);
10759
10760 this.scanner.eat(RIGHTPARENTHESIS$2);
10761
10762 return {
10763 type: 'Function',
10764 loc: this.getLocation(start, this.scanner.tokenStart),
10765 name: name,
10766 children: children
10767 };
10768 },
10769 generate: function(processChunk, node) {
10770 processChunk(node.name);
10771 processChunk('(');
10772 this.each(processChunk, node);
10773 processChunk(')');
10774 },
10775 walkContext: 'function'
10776};
10777
10778var isHex$1 = tokenizer.isHex;
10779var TYPE$m = tokenizer.TYPE;
10780
10781var IDENTIFIER$b = TYPE$m.Identifier;
10782var NUMBER$6 = TYPE$m.Number;
10783var NUMBERSIGN$3 = TYPE$m.NumberSign;
10784
10785function consumeHexSequence(scanner, required) {
10786 if (!isHex$1(scanner.source.charCodeAt(scanner.tokenStart))) {
10787 if (required) {
10788 scanner.error('Unexpected input', scanner.tokenStart);
10789 } else {
10790 return;
10791 }
10792 }
10793
10794 for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
10795 var code = scanner.source.charCodeAt(pos);
10796
10797 // break on non-hex char
10798 if (!isHex$1(code)) {
10799 // break token, exclude symbol
10800 scanner.tokenStart = pos;
10801 return;
10802 }
10803 }
10804
10805 // token is full hex sequence, go to next token
10806 scanner.next();
10807}
10808
10809// # ident
10810var HexColor = {
10811 name: 'HexColor',
10812 structure: {
10813 value: String
10814 },
10815 parse: function() {
10816 var start = this.scanner.tokenStart;
10817
10818 this.scanner.eat(NUMBERSIGN$3);
10819
10820
10821 switch (this.scanner.tokenType) {
10822 case NUMBER$6:
10823 consumeHexSequence(this.scanner, true);
10824
10825 // if token is identifier then number consists of hex only,
10826 // try to add identifier to result
10827 if (this.scanner.tokenType === IDENTIFIER$b) {
10828 consumeHexSequence(this.scanner, false);
10829 }
10830
10831 break;
10832
10833 case IDENTIFIER$b:
10834 consumeHexSequence(this.scanner, true);
10835 break;
10836
10837 default:
10838 this.scanner.error('Number or identifier is expected');
10839 }
10840
10841 return {
10842 type: 'HexColor',
10843 loc: this.getLocation(start, this.scanner.tokenStart),
10844 value: this.scanner.substrToCursor(start + 1) // skip #
10845 };
10846 },
10847 generate: function(processChunk, node) {
10848 processChunk('#');
10849 processChunk(node.value);
10850 }
10851};
10852
10853var TYPE$n = tokenizer.TYPE;
10854var IDENTIFIER$c = TYPE$n.Identifier;
10855
10856var Identifier = {
10857 name: 'Identifier',
10858 structure: {
10859 name: String
10860 },
10861 parse: function() {
10862 return {
10863 type: 'Identifier',
10864 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
10865 name: this.scanner.consume(IDENTIFIER$c)
10866 };
10867 },
10868 generate: function(processChunk, node) {
10869 processChunk(node.name);
10870 }
10871};
10872
10873var TYPE$o = tokenizer.TYPE;
10874var IDENTIFIER$d = TYPE$o.Identifier;
10875var NUMBERSIGN$4 = TYPE$o.NumberSign;
10876
10877// '#' ident
10878var IdSelector = {
10879 name: 'IdSelector',
10880 structure: {
10881 name: String
10882 },
10883 parse: function() {
10884 this.scanner.eat(NUMBERSIGN$4);
10885
10886 return {
10887 type: 'IdSelector',
10888 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10889 name: this.scanner.consume(IDENTIFIER$d)
10890 };
10891 },
10892 generate: function(processChunk, node) {
10893 processChunk('#');
10894 processChunk(node.name);
10895 }
10896};
10897
10898var TYPE$p = tokenizer.TYPE;
10899
10900var IDENTIFIER$e = TYPE$p.Identifier;
10901var NUMBER$7 = TYPE$p.Number;
10902var LEFTPARENTHESIS$4 = TYPE$p.LeftParenthesis;
10903var RIGHTPARENTHESIS$3 = TYPE$p.RightParenthesis;
10904var COLON$4 = TYPE$p.Colon;
10905var SOLIDUS$5 = TYPE$p.Solidus;
10906
10907var MediaFeature = {
10908 name: 'MediaFeature',
10909 structure: {
10910 name: String,
10911 value: ['Identifier', 'Number', 'Dimension', 'Ratio', null]
10912 },
10913 parse: function() {
10914 var start = this.scanner.tokenStart;
10915 var name;
10916 var value = null;
10917
10918 this.scanner.eat(LEFTPARENTHESIS$4);
10919 this.scanner.skipSC();
10920
10921 name = this.scanner.consume(IDENTIFIER$e);
10922 this.scanner.skipSC();
10923
10924 if (this.scanner.tokenType !== RIGHTPARENTHESIS$3) {
10925 this.scanner.eat(COLON$4);
10926 this.scanner.skipSC();
10927
10928 switch (this.scanner.tokenType) {
10929 case NUMBER$7:
10930 if (this.scanner.lookupType(1) === IDENTIFIER$e) {
10931 value = this.Dimension();
10932 } else if (this.scanner.lookupNonWSType(1) === SOLIDUS$5) {
10933 value = this.Ratio();
10934 } else {
10935 value = this.Number();
10936 }
10937
10938 break;
10939
10940 case IDENTIFIER$e:
10941 value = this.Identifier();
10942
10943 break;
10944
10945 default:
10946 this.scanner.error('Number, dimension, ratio or identifier is expected');
10947 }
10948
10949 this.scanner.skipSC();
10950 }
10951
10952 this.scanner.eat(RIGHTPARENTHESIS$3);
10953
10954 return {
10955 type: 'MediaFeature',
10956 loc: this.getLocation(start, this.scanner.tokenStart),
10957 name: name,
10958 value: value
10959 };
10960 },
10961 generate: function(processChunk, node) {
10962 processChunk('(');
10963 processChunk(node.name);
10964 if (node.value !== null) {
10965 processChunk(':');
10966 this.generate(processChunk, node.value);
10967 }
10968 processChunk(')');
10969 }
10970};
10971
10972var TYPE$q = tokenizer.TYPE;
10973
10974var WHITESPACE$6 = TYPE$q.WhiteSpace;
10975var COMMENT$6 = TYPE$q.Comment;
10976var IDENTIFIER$f = TYPE$q.Identifier;
10977var LEFTPARENTHESIS$5 = TYPE$q.LeftParenthesis;
10978
10979var MediaQuery = {
10980 name: 'MediaQuery',
10981 structure: {
10982 children: [['Identifier', 'MediaFeature', 'WhiteSpace']]
10983 },
10984 parse: function() {
10985 this.scanner.skipSC();
10986
10987 var children = new list();
10988 var child = null;
10989 var space = null;
10990
10991 scan:
10992 while (!this.scanner.eof) {
10993 switch (this.scanner.tokenType) {
10994 case COMMENT$6:
10995 this.scanner.next();
10996 continue;
10997
10998 case WHITESPACE$6:
10999 space = this.WhiteSpace();
11000 continue;
11001
11002 case IDENTIFIER$f:
11003 child = this.Identifier();
11004 break;
11005
11006 case LEFTPARENTHESIS$5:
11007 child = this.MediaFeature();
11008 break;
11009
11010 default:
11011 break scan;
11012 }
11013
11014 if (space !== null) {
11015 children.appendData(space);
11016 space = null;
11017 }
11018
11019 children.appendData(child);
11020 }
11021
11022 if (child === null) {
11023 this.scanner.error('Identifier or parenthesis is expected');
11024 }
11025
11026 return {
11027 type: 'MediaQuery',
11028 loc: this.getLocationFromList(children),
11029 children: children
11030 };
11031 },
11032 generate: function(processChunk, node) {
11033 this.each(processChunk, node);
11034 }
11035};
11036
11037var COMMA$2 = tokenizer.TYPE.Comma;
11038
11039var MediaQueryList = {
11040 name: 'MediaQueryList',
11041 structure: {
11042 children: [['MediaQuery']]
11043 },
11044 parse: function(relative) {
11045 var children = new list();
11046
11047 this.scanner.skipSC();
11048
11049 while (!this.scanner.eof) {
11050 children.appendData(this.MediaQuery(relative));
11051
11052 if (this.scanner.tokenType !== COMMA$2) {
11053 break;
11054 }
11055
11056 this.scanner.next();
11057 }
11058
11059 return {
11060 type: 'MediaQueryList',
11061 loc: this.getLocationFromList(children),
11062 children: children
11063 };
11064 },
11065 generate: function(processChunk, node) {
11066 this.eachComma(processChunk, node);
11067 }
11068};
11069
11070// https://drafts.csswg.org/css-syntax-3/#the-anb-type
11071var Nth = {
11072 name: 'Nth',
11073 structure: {
11074 nth: ['AnPlusB', 'Identifier'],
11075 selector: ['SelectorList', null]
11076 },
11077 parse: function(allowOfClause) {
11078 this.scanner.skipSC();
11079
11080 var start = this.scanner.tokenStart;
11081 var end = start;
11082 var selector = null;
11083 var query;
11084
11085 if (this.scanner.lookupValue(0, 'odd') || this.scanner.lookupValue(0, 'even')) {
11086 query = this.Identifier();
11087 } else {
11088 query = this.AnPlusB();
11089 }
11090
11091 this.scanner.skipSC();
11092
11093 if (allowOfClause && this.scanner.lookupValue(0, 'of')) {
11094 this.scanner.next();
11095
11096 selector = this.SelectorList();
11097
11098 if (this.needPositions) {
11099 end = selector.children.last().loc.end.offset;
11100 }
11101 } else {
11102 if (this.needPositions) {
11103 end = query.loc.end.offset;
11104 }
11105 }
11106
11107 return {
11108 type: 'Nth',
11109 loc: this.getLocation(start, end),
11110 nth: query,
11111 selector: selector
11112 };
11113 },
11114 generate: function(processChunk, node) {
11115 this.generate(processChunk, node.nth);
11116 if (node.selector !== null) {
11117 processChunk(' of ');
11118 this.generate(processChunk, node.selector);
11119 }
11120 }
11121};
11122
11123var NUMBER$8 = tokenizer.TYPE.Number;
11124
11125var _Number = {
11126 name: 'Number',
11127 structure: {
11128 value: String
11129 },
11130 parse: function() {
11131 return {
11132 type: 'Number',
11133 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11134 value: this.scanner.consume(NUMBER$8)
11135 };
11136 },
11137 generate: function(processChunk, node) {
11138 processChunk(node.value);
11139 }
11140};
11141
11142// '/' | '*' | ',' | ':' | '+' | '-'
11143var Operator = {
11144 name: 'Operator',
11145 structure: {
11146 value: String
11147 },
11148 parse: function() {
11149 var start = this.scanner.tokenStart;
11150
11151 this.scanner.next();
11152
11153 return {
11154 type: 'Operator',
11155 loc: this.getLocation(start, this.scanner.tokenStart),
11156 value: this.scanner.substrToCursor(start)
11157 };
11158 },
11159 generate: function(processChunk, node) {
11160 processChunk(node.value);
11161 }
11162};
11163
11164var TYPE$r = tokenizer.TYPE;
11165var LEFTPARENTHESIS$6 = TYPE$r.LeftParenthesis;
11166var RIGHTPARENTHESIS$4 = TYPE$r.RightParenthesis;
11167
11168var Parentheses = {
11169 name: 'Parentheses',
11170 structure: {
11171 children: [[]]
11172 },
11173 parse: function(readSequence, recognizer) {
11174 var start = this.scanner.tokenStart;
11175 var children = null;
11176
11177 this.scanner.eat(LEFTPARENTHESIS$6);
11178 children = readSequence.call(this, recognizer);
11179 this.scanner.eat(RIGHTPARENTHESIS$4);
11180
11181 return {
11182 type: 'Parentheses',
11183 loc: this.getLocation(start, this.scanner.tokenStart),
11184 children: children
11185 };
11186 },
11187 generate: function(processChunk, node) {
11188 processChunk('(');
11189 this.each(processChunk, node);
11190 processChunk(')');
11191 }
11192};
11193
11194var TYPE$s = tokenizer.TYPE;
11195
11196var NUMBER$9 = TYPE$s.Number;
11197var PERCENTSIGN$1 = TYPE$s.PercentSign;
11198
11199var Percentage = {
11200 name: 'Percentage',
11201 structure: {
11202 value: String
11203 },
11204 parse: function() {
11205 var start = this.scanner.tokenStart;
11206 var number = this.scanner.consume(NUMBER$9);
11207
11208 this.scanner.eat(PERCENTSIGN$1);
11209
11210 return {
11211 type: 'Percentage',
11212 loc: this.getLocation(start, this.scanner.tokenStart),
11213 value: number
11214 };
11215 },
11216 generate: function(processChunk, node) {
11217 processChunk(node.value);
11218 processChunk('%');
11219 }
11220};
11221
11222var TYPE$t = tokenizer.TYPE;
11223
11224var IDENTIFIER$g = TYPE$t.Identifier;
11225var FUNCTION$4 = TYPE$t.Function;
11226var COLON$5 = TYPE$t.Colon;
11227var RIGHTPARENTHESIS$5 = TYPE$t.RightParenthesis;
11228
11229// : ident [ '(' .. ')' ]?
11230var PseudoClassSelector = {
11231 name: 'PseudoClassSelector',
11232 structure: {
11233 name: String,
11234 children: [['Raw'], null]
11235 },
11236 parse: function() {
11237 var start = this.scanner.tokenStart;
11238 var children = null;
11239 var name;
11240 var nameLowerCase;
11241
11242 this.scanner.eat(COLON$5);
11243
11244 if (this.scanner.tokenType === FUNCTION$4) {
11245 name = this.scanner.consumeFunctionName();
11246 nameLowerCase = name.toLowerCase();
11247
11248 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11249 this.scanner.skipSC();
11250 children = this.pseudo[nameLowerCase].call(this);
11251 this.scanner.skipSC();
11252 } else {
11253 children = new list().appendData(
11254 this.Raw(this.scanner.currentToken, 0, 0, false, false)
11255 );
11256 }
11257
11258 this.scanner.eat(RIGHTPARENTHESIS$5);
11259 } else {
11260 name = this.scanner.consume(IDENTIFIER$g);
11261 }
11262
11263 return {
11264 type: 'PseudoClassSelector',
11265 loc: this.getLocation(start, this.scanner.tokenStart),
11266 name: name,
11267 children: children
11268 };
11269 },
11270 generate: function(processChunk, node) {
11271 processChunk(':');
11272 processChunk(node.name);
11273
11274 if (node.children !== null) {
11275 processChunk('(');
11276 this.each(processChunk, node);
11277 processChunk(')');
11278 }
11279 },
11280 walkContext: 'function'
11281};
11282
11283var TYPE$u = tokenizer.TYPE;
11284
11285var IDENTIFIER$h = TYPE$u.Identifier;
11286var FUNCTION$5 = TYPE$u.Function;
11287var COLON$6 = TYPE$u.Colon;
11288var RIGHTPARENTHESIS$6 = TYPE$u.RightParenthesis;
11289
11290// :: ident [ '(' .. ')' ]?
11291var PseudoElementSelector = {
11292 name: 'PseudoElementSelector',
11293 structure: {
11294 name: String,
11295 children: [['Raw'], null]
11296 },
11297 parse: function() {
11298 var start = this.scanner.tokenStart;
11299 var children = null;
11300 var name;
11301 var nameLowerCase;
11302
11303 this.scanner.eat(COLON$6);
11304 this.scanner.eat(COLON$6);
11305
11306 if (this.scanner.tokenType === FUNCTION$5) {
11307 name = this.scanner.consumeFunctionName();
11308 nameLowerCase = name.toLowerCase();
11309
11310 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11311 this.scanner.skipSC();
11312 children = this.pseudo[nameLowerCase].call(this);
11313 this.scanner.skipSC();
11314 } else {
11315 children = new list().appendData(
11316 this.Raw(this.scanner.currentToken, 0, 0, false, false)
11317 );
11318 }
11319
11320 this.scanner.eat(RIGHTPARENTHESIS$6);
11321 } else {
11322 name = this.scanner.consume(IDENTIFIER$h);
11323 }
11324
11325 return {
11326 type: 'PseudoElementSelector',
11327 loc: this.getLocation(start, this.scanner.tokenStart),
11328 name: name,
11329 children: children
11330 };
11331 },
11332 generate: function(processChunk, node) {
11333 processChunk('::');
11334 processChunk(node.name);
11335
11336 if (node.children !== null) {
11337 processChunk('(');
11338 this.each(processChunk, node);
11339 processChunk(')');
11340 }
11341 },
11342 walkContext: 'function'
11343};
11344
11345var isNumber$3 = tokenizer.isNumber;
11346var TYPE$v = tokenizer.TYPE;
11347var NUMBER$a = TYPE$v.Number;
11348var SOLIDUS$6 = TYPE$v.Solidus;
11349var FULLSTOP$4 = TYPE$v.FullStop;
11350
11351// Terms of <ratio> should to be a positive number (not zero or negative)
11352// (see https://drafts.csswg.org/mediaqueries-3/#values)
11353// However, -o-min-device-pixel-ratio takes fractional values as a ratio's term
11354// and this is using by various sites. Therefore we relax checking on parse
11355// to test a term is unsigned number without exponent part.
11356// Additional checks may to be applied on lexer validation.
11357function consumeNumber(scanner) {
11358 var value = scanner.consumeNonWS(NUMBER$a);
11359
11360 for (var i = 0; i < value.length; i++) {
11361 var code = value.charCodeAt(i);
11362 if (!isNumber$3(code) && code !== FULLSTOP$4) {
11363 scanner.error('Unsigned number is expected', scanner.tokenStart - value.length + i);
11364 }
11365 }
11366
11367 if (Number(value) === 0) {
11368 scanner.error('Zero number is not allowed', scanner.tokenStart - value.length);
11369 }
11370
11371 return value;
11372}
11373
11374// <positive-integer> S* '/' S* <positive-integer>
11375var Ratio = {
11376 name: 'Ratio',
11377 structure: {
11378 left: String,
11379 right: String
11380 },
11381 parse: function() {
11382 var start = this.scanner.tokenStart;
11383 var left = consumeNumber(this.scanner);
11384 var right;
11385
11386 this.scanner.eatNonWS(SOLIDUS$6);
11387 right = consumeNumber(this.scanner);
11388
11389 return {
11390 type: 'Ratio',
11391 loc: this.getLocation(start, this.scanner.tokenStart),
11392 left: left,
11393 right: right
11394 };
11395 },
11396 generate: function(processChunk, node) {
11397 processChunk(node.left);
11398 processChunk('/');
11399 processChunk(node.right);
11400 }
11401};
11402
11403var Raw = {
11404 name: 'Raw',
11405 structure: {
11406 value: String
11407 },
11408 parse: function(startToken, endTokenType1, endTokenType2, includeTokenType2, excludeWhiteSpace) {
11409 var startOffset = this.scanner.getTokenStart(startToken);
11410 var endOffset;
11411
11412 this.scanner.skip(
11413 this.scanner.getRawLength(
11414 startToken,
11415 endTokenType1,
11416 endTokenType2,
11417 includeTokenType2
11418 )
11419 );
11420
11421 if (excludeWhiteSpace && this.scanner.tokenStart > startOffset) {
11422 endOffset = this.scanner.getOffsetExcludeWS();
11423 } else {
11424 endOffset = this.scanner.tokenStart;
11425 }
11426
11427 return {
11428 type: 'Raw',
11429 loc: this.getLocation(startOffset, endOffset),
11430 value: this.scanner.source.substring(startOffset, endOffset)
11431 };
11432 },
11433 generate: function(processChunk, node) {
11434 processChunk(node.value);
11435 }
11436};
11437
11438var TYPE$w = tokenizer.TYPE;
11439
11440var LEFTCURLYBRACKET$5 = TYPE$w.LeftCurlyBracket;
11441
11442function consumeRaw$4(startToken) {
11443 return this.Raw(startToken, LEFTCURLYBRACKET$5, 0, false, true);
11444}
11445
11446var Rule = {
11447 name: 'Rule',
11448 structure: {
11449 selector: ['SelectorList', 'Raw'],
11450 block: ['Block']
11451 },
11452 parse: function() {
11453 var startToken = this.scanner.currentToken;
11454 var startOffset = this.scanner.tokenStart;
11455 var selector = this.parseSelector
11456 ? this.tolerantParse(this.SelectorList, consumeRaw$4)
11457 : consumeRaw$4.call(this, startToken);
11458 var block = this.Block(this.Declaration);
11459
11460 return {
11461 type: 'Rule',
11462 loc: this.getLocation(startOffset, this.scanner.tokenStart),
11463 selector: selector,
11464 block: block
11465 };
11466 },
11467 generate: function(processChunk, node) {
11468 this.generate(processChunk, node.selector);
11469 this.generate(processChunk, node.block);
11470 },
11471 walkContext: 'rule'
11472};
11473
11474var Selector = {
11475 name: 'Selector',
11476 structure: {
11477 children: [[
11478 'TypeSelector',
11479 'IdSelector',
11480 'ClassSelector',
11481 'AttributeSelector',
11482 'PseudoClassSelector',
11483 'PseudoElementSelector',
11484 'Combinator',
11485 'WhiteSpace'
11486 ]]
11487 },
11488 parse: function() {
11489 var children = this.readSequence(this.scope.Selector);
11490
11491 // nothing were consumed
11492 if (children.isEmpty()) {
11493 this.scanner.error('Selector is expected');
11494 }
11495
11496 return {
11497 type: 'Selector',
11498 loc: this.getLocationFromList(children),
11499 children: children
11500 };
11501 },
11502 generate: function(processChunk, node) {
11503 this.each(processChunk, node);
11504 }
11505};
11506
11507var TYPE$x = tokenizer.TYPE;
11508
11509var COMMA$3 = TYPE$x.Comma;
11510var LEFTCURLYBRACKET$6 = TYPE$x.LeftCurlyBracket;
11511
11512var SelectorList = {
11513 name: 'SelectorList',
11514 structure: {
11515 children: [['Selector', 'Raw']]
11516 },
11517 parse: function() {
11518 var children = new list();
11519
11520 while (!this.scanner.eof) {
11521 children.appendData(this.parseSelector
11522 ? this.Selector()
11523 : this.Raw(this.scanner.currentToken, COMMA$3, LEFTCURLYBRACKET$6, false, false)
11524 );
11525
11526 if (this.scanner.tokenType === COMMA$3) {
11527 this.scanner.next();
11528 continue;
11529 }
11530
11531 break;
11532 }
11533
11534 return {
11535 type: 'SelectorList',
11536 loc: this.getLocationFromList(children),
11537 children: children
11538 };
11539 },
11540 generate: function(processChunk, node) {
11541 this.eachComma(processChunk, node);
11542 },
11543 walkContext: 'selector'
11544};
11545
11546var STRING$5 = tokenizer.TYPE.String;
11547
11548var _String = {
11549 name: 'String',
11550 structure: {
11551 value: String
11552 },
11553 parse: function() {
11554 return {
11555 type: 'String',
11556 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11557 value: this.scanner.consume(STRING$5)
11558 };
11559 },
11560 generate: function(processChunk, node) {
11561 processChunk(node.value);
11562 }
11563};
11564
11565var TYPE$y = tokenizer.TYPE;
11566
11567var WHITESPACE$7 = TYPE$y.WhiteSpace;
11568var COMMENT$7 = TYPE$y.Comment;
11569var EXCLAMATIONMARK$3 = TYPE$y.ExclamationMark;
11570var ATRULE$4 = TYPE$y.Atrule;
11571var CDO$3 = TYPE$y.CDO;
11572var CDC$3 = TYPE$y.CDC;
11573
11574function consumeRaw$5(startToken) {
11575 return this.Raw(startToken, 0, 0, false, false);
11576}
11577
11578var StyleSheet = {
11579 name: 'StyleSheet',
11580 structure: {
11581 children: [['Comment', 'Atrule', 'Rule', 'Raw']]
11582 },
11583 parse: function() {
11584 var start = this.scanner.tokenStart;
11585 var children = new list();
11586 var child;
11587
11588
11589 while (!this.scanner.eof) {
11590 switch (this.scanner.tokenType) {
11591 case WHITESPACE$7:
11592 this.scanner.next();
11593 continue;
11594
11595 case COMMENT$7:
11596 // ignore comments except exclamation comments (i.e. /*! .. */) on top level
11597 if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 2) !== EXCLAMATIONMARK$3) {
11598 this.scanner.next();
11599 continue;
11600 }
11601
11602 child = this.Comment();
11603 break;
11604
11605 case CDO$3: // <!--
11606 child = this.CDO();
11607 break;
11608
11609 case CDC$3: // -->
11610 child = this.CDC();
11611 break;
11612
11613 // CSS Syntax Module Level 3
11614 // §2.2 Error handling
11615 // At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule.
11616 case ATRULE$4:
11617 child = this.Atrule();
11618 break;
11619
11620 // Anything else starts a qualified rule ...
11621 default:
11622 child = this.tolerantParse(this.Rule, consumeRaw$5);
11623 }
11624
11625 children.appendData(child);
11626 }
11627
11628 return {
11629 type: 'StyleSheet',
11630 loc: this.getLocation(start, this.scanner.tokenStart),
11631 children: children
11632 };
11633 },
11634 generate: function(processChunk, node) {
11635 this.each(processChunk, node);
11636 },
11637 walkContext: 'stylesheet'
11638};
11639
11640var TYPE$z = tokenizer.TYPE;
11641
11642var IDENTIFIER$i = TYPE$z.Identifier;
11643var ASTERISK$5 = TYPE$z.Asterisk;
11644var VERTICALLINE$2 = TYPE$z.VerticalLine;
11645
11646function eatIdentifierOrAsterisk() {
11647 if (this.scanner.tokenType !== IDENTIFIER$i &&
11648 this.scanner.tokenType !== ASTERISK$5) {
11649 this.scanner.error('Identifier or asterisk is expected');
11650 }
11651
11652 this.scanner.next();
11653}
11654
11655// ident
11656// ident|ident
11657// ident|*
11658// *
11659// *|ident
11660// *|*
11661// |ident
11662// |*
11663var TypeSelector = {
11664 name: 'TypeSelector',
11665 structure: {
11666 name: String
11667 },
11668 parse: function() {
11669 var start = this.scanner.tokenStart;
11670
11671 if (this.scanner.tokenType === VERTICALLINE$2) {
11672 this.scanner.next();
11673 eatIdentifierOrAsterisk.call(this);
11674 } else {
11675 eatIdentifierOrAsterisk.call(this);
11676
11677 if (this.scanner.tokenType === VERTICALLINE$2) {
11678 this.scanner.next();
11679 eatIdentifierOrAsterisk.call(this);
11680 }
11681 }
11682
11683 return {
11684 type: 'TypeSelector',
11685 loc: this.getLocation(start, this.scanner.tokenStart),
11686 name: this.scanner.substrToCursor(start)
11687 };
11688 },
11689 generate: function(processChunk, node) {
11690 processChunk(node.name);
11691 }
11692};
11693
11694var isHex$2 = tokenizer.isHex;
11695var TYPE$A = tokenizer.TYPE;
11696
11697var IDENTIFIER$j = TYPE$A.Identifier;
11698var NUMBER$b = TYPE$A.Number;
11699var PLUSSIGN$7 = TYPE$A.PlusSign;
11700var HYPHENMINUS$7 = TYPE$A.HyphenMinus;
11701var FULLSTOP$5 = TYPE$A.FullStop;
11702var QUESTIONMARK = TYPE$A.QuestionMark;
11703
11704function scanUnicodeNumber(scanner) {
11705 for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
11706 var code = scanner.source.charCodeAt(pos);
11707
11708 // break on fullstop or hyperminus/plussign after exponent
11709 if (code === FULLSTOP$5 || code === PLUSSIGN$7) {
11710 // break token, exclude symbol
11711 scanner.tokenStart = pos;
11712 return false;
11713 }
11714 }
11715
11716 return true;
11717}
11718
11719// https://drafts.csswg.org/css-syntax-3/#urange
11720function scanUnicodeRange(scanner) {
11721 var hexStart = scanner.tokenStart + 1; // skip +
11722 var hexLength = 0;
11723
11724 scan: {
11725 if (scanner.tokenType === NUMBER$b) {
11726 if (scanner.source.charCodeAt(scanner.tokenStart) !== FULLSTOP$5 && scanUnicodeNumber(scanner)) {
11727 scanner.next();
11728 } else if (scanner.source.charCodeAt(scanner.tokenStart) !== HYPHENMINUS$7) {
11729 break scan;
11730 }
11731 } else {
11732 scanner.next(); // PLUSSIGN
11733 }
11734
11735 if (scanner.tokenType === HYPHENMINUS$7) {
11736 scanner.next();
11737 }
11738
11739 if (scanner.tokenType === NUMBER$b) {
11740 scanner.next();
11741 }
11742
11743 if (scanner.tokenType === IDENTIFIER$j) {
11744 scanner.next();
11745 }
11746
11747 if (scanner.tokenStart === hexStart) {
11748 scanner.error('Unexpected input', hexStart);
11749 }
11750 }
11751
11752 // validate for U+x{1,6} or U+x{1,6}-x{1,6}
11753 // where x is [0-9a-fA-F]
11754 for (var i = hexStart, wasHyphenMinus = false; i < scanner.tokenStart; i++) {
11755 var code = scanner.source.charCodeAt(i);
11756
11757 if (isHex$2(code) === false && (code !== HYPHENMINUS$7 || wasHyphenMinus)) {
11758 scanner.error('Unexpected input', i);
11759 }
11760
11761 if (code === HYPHENMINUS$7) {
11762 // hex sequence shouldn't be an empty
11763 if (hexLength === 0) {
11764 scanner.error('Unexpected input', i);
11765 }
11766
11767 wasHyphenMinus = true;
11768 hexLength = 0;
11769 } else {
11770 hexLength++;
11771
11772 // too long hex sequence
11773 if (hexLength > 6) {
11774 scanner.error('Too long hex sequence', i);
11775 }
11776 }
11777
11778 }
11779
11780 // check we have a non-zero sequence
11781 if (hexLength === 0) {
11782 scanner.error('Unexpected input', i - 1);
11783 }
11784
11785 // U+abc???
11786 if (!wasHyphenMinus) {
11787 // consume as many U+003F QUESTION MARK (?) code points as possible
11788 for (; hexLength < 6 && !scanner.eof; scanner.next()) {
11789 if (scanner.tokenType !== QUESTIONMARK) {
11790 break;
11791 }
11792
11793 hexLength++;
11794 }
11795 }
11796}
11797
11798var UnicodeRange = {
11799 name: 'UnicodeRange',
11800 structure: {
11801 value: String
11802 },
11803 parse: function() {
11804 var start = this.scanner.tokenStart;
11805
11806 this.scanner.next(); // U or u
11807 scanUnicodeRange(this.scanner);
11808
11809 return {
11810 type: 'UnicodeRange',
11811 loc: this.getLocation(start, this.scanner.tokenStart),
11812 value: this.scanner.substrToCursor(start)
11813 };
11814 },
11815 generate: function(processChunk, node) {
11816 processChunk(node.value);
11817 }
11818};
11819
11820var TYPE$B = tokenizer.TYPE;
11821
11822var STRING$6 = TYPE$B.String;
11823var URL$4 = TYPE$B.Url;
11824var RAW$2 = TYPE$B.Raw;
11825var RIGHTPARENTHESIS$7 = TYPE$B.RightParenthesis;
11826
11827// url '(' S* (string | raw) S* ')'
11828var Url = {
11829 name: 'Url',
11830 structure: {
11831 value: ['String', 'Raw']
11832 },
11833 parse: function() {
11834 var start = this.scanner.tokenStart;
11835 var value;
11836
11837 this.scanner.eat(URL$4);
11838 this.scanner.skipSC();
11839
11840 switch (this.scanner.tokenType) {
11841 case STRING$6:
11842 value = this.String();
11843 break;
11844
11845 case RAW$2:
11846 value = this.Raw(this.scanner.currentToken, 0, RAW$2, true, false);
11847 break;
11848
11849 default:
11850 this.scanner.error('String or Raw is expected');
11851 }
11852
11853 this.scanner.skipSC();
11854 this.scanner.eat(RIGHTPARENTHESIS$7);
11855
11856 return {
11857 type: 'Url',
11858 loc: this.getLocation(start, this.scanner.tokenStart),
11859 value: value
11860 };
11861 },
11862 generate: function(processChunk, node) {
11863 processChunk('url');
11864 processChunk('(');
11865 this.generate(processChunk, node.value);
11866 processChunk(')');
11867 }
11868};
11869
11870var endsWith$1 = tokenizer.endsWith;
11871var TYPE$C = tokenizer.TYPE;
11872
11873var WHITESPACE$8 = TYPE$C.WhiteSpace;
11874var COMMENT$8 = TYPE$C.Comment;
11875var FUNCTION$6 = TYPE$C.Function;
11876var COLON$7 = TYPE$C.Colon;
11877var SEMICOLON$6 = TYPE$C.Semicolon;
11878var EXCLAMATIONMARK$4 = TYPE$C.ExclamationMark;
11879
11880// 'progid:' ws* 'DXImageTransform.Microsoft.' ident ws* '(' .* ')'
11881function checkProgid(scanner) {
11882 var offset = 0;
11883
11884 for (var type; type = scanner.lookupType(offset); offset++) {
11885 if (type !== WHITESPACE$8 && type !== COMMENT$8) {
11886 break;
11887 }
11888 }
11889
11890 if (scanner.lookupValue(offset, 'alpha(') ||
11891 scanner.lookupValue(offset, 'chroma(') ||
11892 scanner.lookupValue(offset, 'dropshadow(')) {
11893 if (scanner.lookupType(offset) !== FUNCTION$6) {
11894 return false;
11895 }
11896 } else {
11897 if (scanner.lookupValue(offset, 'progid') === false ||
11898 scanner.lookupType(offset + 1) !== COLON$7) {
11899 return false;
11900 }
11901 }
11902
11903 return true;
11904}
11905
11906var Value = {
11907 name: 'Value',
11908 structure: {
11909 children: [[]]
11910 },
11911 parse: function(property) {
11912 // special parser for filter property since it can contains non-standart syntax for old IE
11913 if (property !== null && endsWith$1(property, 'filter') && checkProgid(this.scanner)) {
11914 this.scanner.skipSC();
11915 return this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$4, SEMICOLON$6, false, false);
11916 }
11917
11918 var start = this.scanner.tokenStart;
11919 var children = this.readSequence(this.scope.Value);
11920
11921 return {
11922 type: 'Value',
11923 loc: this.getLocation(start, this.scanner.tokenStart),
11924 children: children
11925 };
11926 },
11927 generate: function(processChunk, node) {
11928 this.each(processChunk, node);
11929 }
11930};
11931
11932var WHITESPACE$9 = tokenizer.TYPE.WhiteSpace;
11933var SPACE$2 = Object.freeze({
11934 type: 'WhiteSpace',
11935 loc: null,
11936 value: ' '
11937});
11938
11939var WhiteSpace = {
11940 name: 'WhiteSpace',
11941 structure: {
11942 value: String
11943 },
11944 parse: function() {
11945 this.scanner.eat(WHITESPACE$9);
11946 return SPACE$2;
11947
11948 // return {
11949 // type: 'WhiteSpace',
11950 // loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11951 // value: this.scanner.consume(WHITESPACE)
11952 // };
11953 },
11954 generate: function(processChunk, node) {
11955 processChunk(node.value);
11956 }
11957};
11958
11959var node = {
11960 AnPlusB: AnPlusB,
11961 Atrule: Atrule,
11962 AtruleExpression: AtruleExpression,
11963 AttributeSelector: AttributeSelector,
11964 Block: Block,
11965 Brackets: Brackets,
11966 CDC: CDC_1,
11967 CDO: CDO_1,
11968 ClassSelector: ClassSelector,
11969 Combinator: Combinator,
11970 Comment: Comment,
11971 Declaration: Declaration,
11972 DeclarationList: DeclarationList,
11973 Dimension: Dimension,
11974 Function: _Function,
11975 HexColor: HexColor,
11976 Identifier: Identifier,
11977 IdSelector: IdSelector,
11978 MediaFeature: MediaFeature,
11979 MediaQuery: MediaQuery,
11980 MediaQueryList: MediaQueryList,
11981 Nth: Nth,
11982 Number: _Number,
11983 Operator: Operator,
11984 Parentheses: Parentheses,
11985 Percentage: Percentage,
11986 PseudoClassSelector: PseudoClassSelector,
11987 PseudoElementSelector: PseudoElementSelector,
11988 Ratio: Ratio,
11989 Raw: Raw,
11990 Rule: Rule,
11991 Selector: Selector,
11992 SelectorList: SelectorList,
11993 String: _String,
11994 StyleSheet: StyleSheet,
11995 TypeSelector: TypeSelector,
11996 UnicodeRange: UnicodeRange,
11997 Url: Url,
11998 Value: Value,
11999 WhiteSpace: WhiteSpace
12000};
12001
12002var parser = {
12003 parseContext: {
12004 default: 'StyleSheet',
12005 stylesheet: 'StyleSheet',
12006 atrule: 'Atrule',
12007 atruleExpression: function(options) {
12008 return this.AtruleExpression(options.atrule ? String(options.atrule) : null);
12009 },
12010 mediaQueryList: 'MediaQueryList',
12011 mediaQuery: 'MediaQuery',
12012 rule: 'Rule',
12013 selectorList: 'SelectorList',
12014 selector: 'Selector',
12015 block: function() {
12016 return this.Block(this.Declaration);
12017 },
12018 declarationList: 'DeclarationList',
12019 declaration: 'Declaration',
12020 value: function(options) {
12021 return this.Value(options.property ? String(options.property) : null);
12022 }
12023 },
12024 scope: scope,
12025 atrule: atrule,
12026 pseudo: pseudo,
12027 node: node
12028};
12029
12030var parser$1 = create(parser);
12031
12032function read_style(parser, start, attributes) {
12033 const content_start = parser.index;
12034 const styles = parser.read_until(/<\/style>/);
12035 const content_end = parser.index;
12036 let ast;
12037 try {
12038 ast = parser$1(styles, {
12039 positions: true,
12040 offset: content_start
12041 });
12042 }
12043 catch (err) {
12044 if (err.name === 'CssSyntaxError') {
12045 parser.error({
12046 code: 'css-syntax-error',
12047 message: err.message
12048 }, err.offset);
12049 }
12050 else {
12051 throw err;
12052 }
12053 }
12054 ast = JSON.parse(JSON.stringify(ast));
12055 // tidy up AST
12056 walk(ast, {
12057 enter: (node) => {
12058 // replace `ref:a` nodes
12059 if (node.type === 'Selector') {
12060 for (let i = 0; i < node.children.length; i += 1) {
12061 const a = node.children[i];
12062 const b = node.children[i + 1];
12063 if (is_ref_selector(a, b)) {
12064 parser.error({
12065 code: 'invalid-ref-selector',
12066 message: 'ref selectors are no longer supported'
12067 }, a.loc.start.offset);
12068 }
12069 }
12070 }
12071 if (node.type === 'Declaration' && node.value.type === 'Value' && node.value.children.length === 0) {
12072 parser.error({
12073 code: 'invalid-declaration',
12074 message: 'Declaration cannot be empty'
12075 }, node.start);
12076 }
12077 if (node.type === 'PseudoClassSelector' && node.name === 'global' && node.children === null) {
12078 parser.error({
12079 code: 'css-syntax-error',
12080 message: ':global() must contain a selector'
12081 }, node.loc.start.offset);
12082 }
12083 if (node.loc) {
12084 node.start = node.loc.start.offset;
12085 node.end = node.loc.end.offset;
12086 delete node.loc;
12087 }
12088 }
12089 });
12090 parser.eat('</style>', true);
12091 const end = parser.index;
12092 return {
12093 type: 'Style',
12094 start,
12095 end,
12096 attributes,
12097 children: ast.children,
12098 content: {
12099 start: content_start,
12100 end: content_end,
12101 styles
12102 }
12103 };
12104}
12105function is_ref_selector(a, b) {
12106 if (!b)
12107 return false;
12108 return (a.type === 'TypeSelector' &&
12109 a.name === 'ref' &&
12110 b.type === 'PseudoClassSelector');
12111}
12112
12113// https://dev.w3.org/html5/html-author/charref
12114var entities = {
12115 CounterClockwiseContourIntegral: 8755,
12116 ClockwiseContourIntegral: 8754,
12117 DoubleLongLeftRightArrow: 10234,
12118 DiacriticalDoubleAcute: 733,
12119 NotSquareSupersetEqual: 8931,
12120 CloseCurlyDoubleQuote: 8221,
12121 DoubleContourIntegral: 8751,
12122 FilledVerySmallSquare: 9642,
12123 NegativeVeryThinSpace: 8203,
12124 NotPrecedesSlantEqual: 8928,
12125 NotRightTriangleEqual: 8941,
12126 NotSucceedsSlantEqual: 8929,
12127 CapitalDifferentialD: 8517,
12128 DoubleLeftRightArrow: 8660,
12129 DoubleLongRightArrow: 10233,
12130 EmptyVerySmallSquare: 9643,
12131 NestedGreaterGreater: 8811,
12132 NotDoubleVerticalBar: 8742,
12133 NotLeftTriangleEqual: 8940,
12134 NotSquareSubsetEqual: 8930,
12135 OpenCurlyDoubleQuote: 8220,
12136 ReverseUpEquilibrium: 10607,
12137 DoubleLongLeftArrow: 10232,
12138 DownLeftRightVector: 10576,
12139 LeftArrowRightArrow: 8646,
12140 NegativeMediumSpace: 8203,
12141 RightArrowLeftArrow: 8644,
12142 SquareSupersetEqual: 8850,
12143 leftrightsquigarrow: 8621,
12144 DownRightTeeVector: 10591,
12145 DownRightVectorBar: 10583,
12146 LongLeftRightArrow: 10231,
12147 Longleftrightarrow: 10234,
12148 NegativeThickSpace: 8203,
12149 PrecedesSlantEqual: 8828,
12150 ReverseEquilibrium: 8651,
12151 RightDoubleBracket: 10215,
12152 RightDownTeeVector: 10589,
12153 RightDownVectorBar: 10581,
12154 RightTriangleEqual: 8885,
12155 SquareIntersection: 8851,
12156 SucceedsSlantEqual: 8829,
12157 blacktriangleright: 9656,
12158 longleftrightarrow: 10231,
12159 DoubleUpDownArrow: 8661,
12160 DoubleVerticalBar: 8741,
12161 DownLeftTeeVector: 10590,
12162 DownLeftVectorBar: 10582,
12163 FilledSmallSquare: 9724,
12164 GreaterSlantEqual: 10878,
12165 LeftDoubleBracket: 10214,
12166 LeftDownTeeVector: 10593,
12167 LeftDownVectorBar: 10585,
12168 LeftTriangleEqual: 8884,
12169 NegativeThinSpace: 8203,
12170 NotReverseElement: 8716,
12171 NotTildeFullEqual: 8775,
12172 RightAngleBracket: 10217,
12173 RightUpDownVector: 10575,
12174 SquareSubsetEqual: 8849,
12175 VerticalSeparator: 10072,
12176 blacktriangledown: 9662,
12177 blacktriangleleft: 9666,
12178 leftrightharpoons: 8651,
12179 rightleftharpoons: 8652,
12180 twoheadrightarrow: 8608,
12181 DiacriticalAcute: 180,
12182 DiacriticalGrave: 96,
12183 DiacriticalTilde: 732,
12184 DoubleRightArrow: 8658,
12185 DownArrowUpArrow: 8693,
12186 EmptySmallSquare: 9723,
12187 GreaterEqualLess: 8923,
12188 GreaterFullEqual: 8807,
12189 LeftAngleBracket: 10216,
12190 LeftUpDownVector: 10577,
12191 LessEqualGreater: 8922,
12192 NonBreakingSpace: 160,
12193 NotRightTriangle: 8939,
12194 NotSupersetEqual: 8841,
12195 RightTriangleBar: 10704,
12196 RightUpTeeVector: 10588,
12197 RightUpVectorBar: 10580,
12198 UnderParenthesis: 9181,
12199 UpArrowDownArrow: 8645,
12200 circlearrowright: 8635,
12201 downharpoonright: 8642,
12202 ntrianglerighteq: 8941,
12203 rightharpoondown: 8641,
12204 rightrightarrows: 8649,
12205 twoheadleftarrow: 8606,
12206 vartriangleright: 8883,
12207 CloseCurlyQuote: 8217,
12208 ContourIntegral: 8750,
12209 DoubleDownArrow: 8659,
12210 DoubleLeftArrow: 8656,
12211 DownRightVector: 8641,
12212 LeftRightVector: 10574,
12213 LeftTriangleBar: 10703,
12214 LeftUpTeeVector: 10592,
12215 LeftUpVectorBar: 10584,
12216 LowerRightArrow: 8600,
12217 NotGreaterEqual: 8817,
12218 NotGreaterTilde: 8821,
12219 NotLeftTriangle: 8938,
12220 OverParenthesis: 9180,
12221 RightDownVector: 8642,
12222 ShortRightArrow: 8594,
12223 UpperRightArrow: 8599,
12224 bigtriangledown: 9661,
12225 circlearrowleft: 8634,
12226 curvearrowright: 8631,
12227 downharpoonleft: 8643,
12228 leftharpoondown: 8637,
12229 leftrightarrows: 8646,
12230 nLeftrightarrow: 8654,
12231 nleftrightarrow: 8622,
12232 ntrianglelefteq: 8940,
12233 rightleftarrows: 8644,
12234 rightsquigarrow: 8605,
12235 rightthreetimes: 8908,
12236 straightepsilon: 1013,
12237 trianglerighteq: 8885,
12238 vartriangleleft: 8882,
12239 DiacriticalDot: 729,
12240 DoubleRightTee: 8872,
12241 DownLeftVector: 8637,
12242 GreaterGreater: 10914,
12243 HorizontalLine: 9472,
12244 InvisibleComma: 8291,
12245 InvisibleTimes: 8290,
12246 LeftDownVector: 8643,
12247 LeftRightArrow: 8596,
12248 Leftrightarrow: 8660,
12249 LessSlantEqual: 10877,
12250 LongRightArrow: 10230,
12251 Longrightarrow: 10233,
12252 LowerLeftArrow: 8601,
12253 NestedLessLess: 8810,
12254 NotGreaterLess: 8825,
12255 NotLessGreater: 8824,
12256 NotSubsetEqual: 8840,
12257 NotVerticalBar: 8740,
12258 OpenCurlyQuote: 8216,
12259 ReverseElement: 8715,
12260 RightTeeVector: 10587,
12261 RightVectorBar: 10579,
12262 ShortDownArrow: 8595,
12263 ShortLeftArrow: 8592,
12264 SquareSuperset: 8848,
12265 TildeFullEqual: 8773,
12266 UpperLeftArrow: 8598,
12267 ZeroWidthSpace: 8203,
12268 curvearrowleft: 8630,
12269 doublebarwedge: 8966,
12270 downdownarrows: 8650,
12271 hookrightarrow: 8618,
12272 leftleftarrows: 8647,
12273 leftrightarrow: 8596,
12274 leftthreetimes: 8907,
12275 longrightarrow: 10230,
12276 looparrowright: 8620,
12277 nshortparallel: 8742,
12278 ntriangleright: 8939,
12279 rightarrowtail: 8611,
12280 rightharpoonup: 8640,
12281 trianglelefteq: 8884,
12282 upharpoonright: 8638,
12283 ApplyFunction: 8289,
12284 DifferentialD: 8518,
12285 DoubleLeftTee: 10980,
12286 DoubleUpArrow: 8657,
12287 LeftTeeVector: 10586,
12288 LeftVectorBar: 10578,
12289 LessFullEqual: 8806,
12290 LongLeftArrow: 10229,
12291 Longleftarrow: 10232,
12292 NotTildeEqual: 8772,
12293 NotTildeTilde: 8777,
12294 Poincareplane: 8460,
12295 PrecedesEqual: 10927,
12296 PrecedesTilde: 8830,
12297 RightArrowBar: 8677,
12298 RightTeeArrow: 8614,
12299 RightTriangle: 8883,
12300 RightUpVector: 8638,
12301 SucceedsEqual: 10928,
12302 SucceedsTilde: 8831,
12303 SupersetEqual: 8839,
12304 UpEquilibrium: 10606,
12305 VerticalTilde: 8768,
12306 VeryThinSpace: 8202,
12307 bigtriangleup: 9651,
12308 blacktriangle: 9652,
12309 divideontimes: 8903,
12310 fallingdotseq: 8786,
12311 hookleftarrow: 8617,
12312 leftarrowtail: 8610,
12313 leftharpoonup: 8636,
12314 longleftarrow: 10229,
12315 looparrowleft: 8619,
12316 measuredangle: 8737,
12317 ntriangleleft: 8938,
12318 shortparallel: 8741,
12319 smallsetminus: 8726,
12320 triangleright: 9657,
12321 upharpoonleft: 8639,
12322 DownArrowBar: 10515,
12323 DownTeeArrow: 8615,
12324 ExponentialE: 8519,
12325 GreaterEqual: 8805,
12326 GreaterTilde: 8819,
12327 HilbertSpace: 8459,
12328 HumpDownHump: 8782,
12329 Intersection: 8898,
12330 LeftArrowBar: 8676,
12331 LeftTeeArrow: 8612,
12332 LeftTriangle: 8882,
12333 LeftUpVector: 8639,
12334 NotCongruent: 8802,
12335 NotLessEqual: 8816,
12336 NotLessTilde: 8820,
12337 Proportional: 8733,
12338 RightCeiling: 8969,
12339 RoundImplies: 10608,
12340 ShortUpArrow: 8593,
12341 SquareSubset: 8847,
12342 UnderBracket: 9141,
12343 VerticalLine: 124,
12344 blacklozenge: 10731,
12345 exponentiale: 8519,
12346 risingdotseq: 8787,
12347 triangledown: 9663,
12348 triangleleft: 9667,
12349 CircleMinus: 8854,
12350 CircleTimes: 8855,
12351 Equilibrium: 8652,
12352 GreaterLess: 8823,
12353 LeftCeiling: 8968,
12354 LessGreater: 8822,
12355 MediumSpace: 8287,
12356 NotPrecedes: 8832,
12357 NotSucceeds: 8833,
12358 OverBracket: 9140,
12359 RightVector: 8640,
12360 Rrightarrow: 8667,
12361 RuleDelayed: 10740,
12362 SmallCircle: 8728,
12363 SquareUnion: 8852,
12364 SubsetEqual: 8838,
12365 UpDownArrow: 8597,
12366 Updownarrow: 8661,
12367 VerticalBar: 8739,
12368 backepsilon: 1014,
12369 blacksquare: 9642,
12370 circledcirc: 8858,
12371 circleddash: 8861,
12372 curlyeqprec: 8926,
12373 curlyeqsucc: 8927,
12374 diamondsuit: 9830,
12375 eqslantless: 10901,
12376 expectation: 8496,
12377 nRightarrow: 8655,
12378 nrightarrow: 8603,
12379 preccurlyeq: 8828,
12380 precnapprox: 10937,
12381 quaternions: 8461,
12382 straightphi: 981,
12383 succcurlyeq: 8829,
12384 succnapprox: 10938,
12385 thickapprox: 8776,
12386 updownarrow: 8597,
12387 Bernoullis: 8492,
12388 CirclePlus: 8853,
12389 EqualTilde: 8770,
12390 Fouriertrf: 8497,
12391 ImaginaryI: 8520,
12392 Laplacetrf: 8466,
12393 LeftVector: 8636,
12394 Lleftarrow: 8666,
12395 NotElement: 8713,
12396 NotGreater: 8815,
12397 Proportion: 8759,
12398 RightArrow: 8594,
12399 RightFloor: 8971,
12400 Rightarrow: 8658,
12401 TildeEqual: 8771,
12402 TildeTilde: 8776,
12403 UnderBrace: 9183,
12404 UpArrowBar: 10514,
12405 UpTeeArrow: 8613,
12406 circledast: 8859,
12407 complement: 8705,
12408 curlywedge: 8911,
12409 eqslantgtr: 10902,
12410 gtreqqless: 10892,
12411 lessapprox: 10885,
12412 lesseqqgtr: 10891,
12413 lmoustache: 9136,
12414 longmapsto: 10236,
12415 mapstodown: 8615,
12416 mapstoleft: 8612,
12417 nLeftarrow: 8653,
12418 nleftarrow: 8602,
12419 precapprox: 10935,
12420 rightarrow: 8594,
12421 rmoustache: 9137,
12422 sqsubseteq: 8849,
12423 sqsupseteq: 8850,
12424 subsetneqq: 10955,
12425 succapprox: 10936,
12426 supsetneqq: 10956,
12427 upuparrows: 8648,
12428 varepsilon: 949,
12429 varnothing: 8709,
12430 Backslash: 8726,
12431 CenterDot: 183,
12432 CircleDot: 8857,
12433 Congruent: 8801,
12434 Coproduct: 8720,
12435 DoubleDot: 168,
12436 DownArrow: 8595,
12437 DownBreve: 785,
12438 Downarrow: 8659,
12439 HumpEqual: 8783,
12440 LeftArrow: 8592,
12441 LeftFloor: 8970,
12442 Leftarrow: 8656,
12443 LessTilde: 8818,
12444 Mellintrf: 8499,
12445 MinusPlus: 8723,
12446 NotCupCap: 8813,
12447 NotExists: 8708,
12448 OverBrace: 9182,
12449 PlusMinus: 177,
12450 Therefore: 8756,
12451 ThinSpace: 8201,
12452 TripleDot: 8411,
12453 UnionPlus: 8846,
12454 backprime: 8245,
12455 backsimeq: 8909,
12456 bigotimes: 10754,
12457 centerdot: 183,
12458 checkmark: 10003,
12459 complexes: 8450,
12460 dotsquare: 8865,
12461 downarrow: 8595,
12462 gtrapprox: 10886,
12463 gtreqless: 8923,
12464 heartsuit: 9829,
12465 leftarrow: 8592,
12466 lesseqgtr: 8922,
12467 nparallel: 8742,
12468 nshortmid: 8740,
12469 nsubseteq: 8840,
12470 nsupseteq: 8841,
12471 pitchfork: 8916,
12472 rationals: 8474,
12473 spadesuit: 9824,
12474 subseteqq: 10949,
12475 subsetneq: 8842,
12476 supseteqq: 10950,
12477 supsetneq: 8843,
12478 therefore: 8756,
12479 triangleq: 8796,
12480 varpropto: 8733,
12481 DDotrahd: 10513,
12482 DotEqual: 8784,
12483 Integral: 8747,
12484 LessLess: 10913,
12485 NotEqual: 8800,
12486 NotTilde: 8769,
12487 PartialD: 8706,
12488 Precedes: 8826,
12489 RightTee: 8866,
12490 Succeeds: 8827,
12491 SuchThat: 8715,
12492 Superset: 8835,
12493 Uarrocir: 10569,
12494 UnderBar: 818,
12495 andslope: 10840,
12496 angmsdaa: 10664,
12497 angmsdab: 10665,
12498 angmsdac: 10666,
12499 angmsdad: 10667,
12500 angmsdae: 10668,
12501 angmsdaf: 10669,
12502 angmsdag: 10670,
12503 angmsdah: 10671,
12504 angrtvbd: 10653,
12505 approxeq: 8778,
12506 awconint: 8755,
12507 backcong: 8780,
12508 barwedge: 8965,
12509 bbrktbrk: 9142,
12510 bigoplus: 10753,
12511 bigsqcup: 10758,
12512 biguplus: 10756,
12513 bigwedge: 8896,
12514 boxminus: 8863,
12515 boxtimes: 8864,
12516 capbrcup: 10825,
12517 circledR: 174,
12518 circledS: 9416,
12519 cirfnint: 10768,
12520 clubsuit: 9827,
12521 cupbrcap: 10824,
12522 curlyvee: 8910,
12523 cwconint: 8754,
12524 doteqdot: 8785,
12525 dotminus: 8760,
12526 drbkarow: 10512,
12527 dzigrarr: 10239,
12528 elinters: 9191,
12529 emptyset: 8709,
12530 eqvparsl: 10725,
12531 fpartint: 10765,
12532 geqslant: 10878,
12533 gesdotol: 10884,
12534 gnapprox: 10890,
12535 hksearow: 10533,
12536 hkswarow: 10534,
12537 imagline: 8464,
12538 imagpart: 8465,
12539 infintie: 10717,
12540 integers: 8484,
12541 intercal: 8890,
12542 intlarhk: 10775,
12543 laemptyv: 10676,
12544 ldrushar: 10571,
12545 leqslant: 10877,
12546 lesdotor: 10883,
12547 llcorner: 8990,
12548 lnapprox: 10889,
12549 lrcorner: 8991,
12550 lurdshar: 10570,
12551 mapstoup: 8613,
12552 multimap: 8888,
12553 naturals: 8469,
12554 otimesas: 10806,
12555 parallel: 8741,
12556 plusacir: 10787,
12557 pointint: 10773,
12558 precneqq: 10933,
12559 precnsim: 8936,
12560 profalar: 9006,
12561 profline: 8978,
12562 profsurf: 8979,
12563 raemptyv: 10675,
12564 realpart: 8476,
12565 rppolint: 10770,
12566 rtriltri: 10702,
12567 scpolint: 10771,
12568 setminus: 8726,
12569 shortmid: 8739,
12570 smeparsl: 10724,
12571 sqsubset: 8847,
12572 sqsupset: 8848,
12573 subseteq: 8838,
12574 succneqq: 10934,
12575 succnsim: 8937,
12576 supseteq: 8839,
12577 thetasym: 977,
12578 thicksim: 8764,
12579 timesbar: 10801,
12580 triangle: 9653,
12581 triminus: 10810,
12582 trpezium: 9186,
12583 ulcorner: 8988,
12584 urcorner: 8989,
12585 varkappa: 1008,
12586 varsigma: 962,
12587 vartheta: 977,
12588 Because: 8757,
12589 Cayleys: 8493,
12590 Cconint: 8752,
12591 Cedilla: 184,
12592 Diamond: 8900,
12593 DownTee: 8868,
12594 Element: 8712,
12595 Epsilon: 917,
12596 Implies: 8658,
12597 LeftTee: 8867,
12598 NewLine: 10,
12599 NoBreak: 8288,
12600 NotLess: 8814,
12601 Omicron: 927,
12602 OverBar: 175,
12603 Product: 8719,
12604 UpArrow: 8593,
12605 Uparrow: 8657,
12606 Upsilon: 933,
12607 alefsym: 8501,
12608 angrtvb: 8894,
12609 angzarr: 9084,
12610 asympeq: 8781,
12611 backsim: 8765,
12612 because: 8757,
12613 bemptyv: 10672,
12614 between: 8812,
12615 bigcirc: 9711,
12616 bigodot: 10752,
12617 bigstar: 9733,
12618 boxplus: 8862,
12619 ccupssm: 10832,
12620 cemptyv: 10674,
12621 cirscir: 10690,
12622 coloneq: 8788,
12623 congdot: 10861,
12624 cudarrl: 10552,
12625 cudarrr: 10549,
12626 cularrp: 10557,
12627 curarrm: 10556,
12628 dbkarow: 10511,
12629 ddagger: 8225,
12630 ddotseq: 10871,
12631 demptyv: 10673,
12632 diamond: 8900,
12633 digamma: 989,
12634 dotplus: 8724,
12635 dwangle: 10662,
12636 epsilon: 949,
12637 eqcolon: 8789,
12638 equivDD: 10872,
12639 gesdoto: 10882,
12640 gtquest: 10876,
12641 gtrless: 8823,
12642 harrcir: 10568,
12643 intprod: 10812,
12644 isindot: 8949,
12645 larrbfs: 10527,
12646 larrsim: 10611,
12647 lbrksld: 10639,
12648 lbrkslu: 10637,
12649 ldrdhar: 10599,
12650 lesdoto: 10881,
12651 lessdot: 8918,
12652 lessgtr: 8822,
12653 lesssim: 8818,
12654 lotimes: 10804,
12655 lozenge: 9674,
12656 ltquest: 10875,
12657 luruhar: 10598,
12658 maltese: 10016,
12659 minusdu: 10794,
12660 napprox: 8777,
12661 natural: 9838,
12662 nearrow: 8599,
12663 nexists: 8708,
12664 notinva: 8713,
12665 notinvb: 8951,
12666 notinvc: 8950,
12667 notniva: 8716,
12668 notnivb: 8958,
12669 notnivc: 8957,
12670 npolint: 10772,
12671 nsqsube: 8930,
12672 nsqsupe: 8931,
12673 nvinfin: 10718,
12674 nwarrow: 8598,
12675 olcross: 10683,
12676 omicron: 959,
12677 orderof: 8500,
12678 orslope: 10839,
12679 pertenk: 8241,
12680 planckh: 8462,
12681 pluscir: 10786,
12682 plussim: 10790,
12683 plustwo: 10791,
12684 precsim: 8830,
12685 quatint: 10774,
12686 questeq: 8799,
12687 rarrbfs: 10528,
12688 rarrsim: 10612,
12689 rbrksld: 10638,
12690 rbrkslu: 10640,
12691 rdldhar: 10601,
12692 realine: 8475,
12693 rotimes: 10805,
12694 ruluhar: 10600,
12695 searrow: 8600,
12696 simplus: 10788,
12697 simrarr: 10610,
12698 subedot: 10947,
12699 submult: 10945,
12700 subplus: 10943,
12701 subrarr: 10617,
12702 succsim: 8831,
12703 supdsub: 10968,
12704 supedot: 10948,
12705 suphsub: 10967,
12706 suplarr: 10619,
12707 supmult: 10946,
12708 supplus: 10944,
12709 swarrow: 8601,
12710 topfork: 10970,
12711 triplus: 10809,
12712 tritime: 10811,
12713 uparrow: 8593,
12714 upsilon: 965,
12715 uwangle: 10663,
12716 vzigzag: 10650,
12717 zigrarr: 8669,
12718 Aacute: 193,
12719 Abreve: 258,
12720 Agrave: 192,
12721 Assign: 8788,
12722 Atilde: 195,
12723 Barwed: 8966,
12724 Bumpeq: 8782,
12725 Cacute: 262,
12726 Ccaron: 268,
12727 Ccedil: 199,
12728 Colone: 10868,
12729 Conint: 8751,
12730 CupCap: 8781,
12731 Dagger: 8225,
12732 Dcaron: 270,
12733 DotDot: 8412,
12734 Dstrok: 272,
12735 Eacute: 201,
12736 Ecaron: 282,
12737 Egrave: 200,
12738 Exists: 8707,
12739 ForAll: 8704,
12740 Gammad: 988,
12741 Gbreve: 286,
12742 Gcedil: 290,
12743 HARDcy: 1066,
12744 Hstrok: 294,
12745 Iacute: 205,
12746 Igrave: 204,
12747 Itilde: 296,
12748 Jsercy: 1032,
12749 Kcedil: 310,
12750 Lacute: 313,
12751 Lambda: 923,
12752 Lcaron: 317,
12753 Lcedil: 315,
12754 Lmidot: 319,
12755 Lstrok: 321,
12756 Nacute: 323,
12757 Ncaron: 327,
12758 Ncedil: 325,
12759 Ntilde: 209,
12760 Oacute: 211,
12761 Odblac: 336,
12762 Ograve: 210,
12763 Oslash: 216,
12764 Otilde: 213,
12765 Otimes: 10807,
12766 Racute: 340,
12767 Rarrtl: 10518,
12768 Rcaron: 344,
12769 Rcedil: 342,
12770 SHCHcy: 1065,
12771 SOFTcy: 1068,
12772 Sacute: 346,
12773 Scaron: 352,
12774 Scedil: 350,
12775 Square: 9633,
12776 Subset: 8912,
12777 Supset: 8913,
12778 Tcaron: 356,
12779 Tcedil: 354,
12780 Tstrok: 358,
12781 Uacute: 218,
12782 Ubreve: 364,
12783 Udblac: 368,
12784 Ugrave: 217,
12785 Utilde: 360,
12786 Vdashl: 10982,
12787 Verbar: 8214,
12788 Vvdash: 8874,
12789 Yacute: 221,
12790 Zacute: 377,
12791 Zcaron: 381,
12792 aacute: 225,
12793 abreve: 259,
12794 agrave: 224,
12795 andand: 10837,
12796 angmsd: 8737,
12797 angsph: 8738,
12798 apacir: 10863,
12799 approx: 8776,
12800 atilde: 227,
12801 barvee: 8893,
12802 barwed: 8965,
12803 becaus: 8757,
12804 bernou: 8492,
12805 bigcap: 8898,
12806 bigcup: 8899,
12807 bigvee: 8897,
12808 bkarow: 10509,
12809 bottom: 8869,
12810 bowtie: 8904,
12811 boxbox: 10697,
12812 bprime: 8245,
12813 brvbar: 166,
12814 bullet: 8226,
12815 bumpeq: 8783,
12816 cacute: 263,
12817 capand: 10820,
12818 capcap: 10827,
12819 capcup: 10823,
12820 capdot: 10816,
12821 ccaron: 269,
12822 ccedil: 231,
12823 circeq: 8791,
12824 cirmid: 10991,
12825 colone: 8788,
12826 commat: 64,
12827 compfn: 8728,
12828 conint: 8750,
12829 coprod: 8720,
12830 copysr: 8471,
12831 cularr: 8630,
12832 cupcap: 10822,
12833 cupcup: 10826,
12834 cupdot: 8845,
12835 curarr: 8631,
12836 curren: 164,
12837 cylcty: 9005,
12838 dagger: 8224,
12839 daleth: 8504,
12840 dcaron: 271,
12841 dfisht: 10623,
12842 divide: 247,
12843 divonx: 8903,
12844 dlcorn: 8990,
12845 dlcrop: 8973,
12846 dollar: 36,
12847 drcorn: 8991,
12848 drcrop: 8972,
12849 dstrok: 273,
12850 eacute: 233,
12851 easter: 10862,
12852 ecaron: 283,
12853 ecolon: 8789,
12854 egrave: 232,
12855 egsdot: 10904,
12856 elsdot: 10903,
12857 emptyv: 8709,
12858 emsp13: 8196,
12859 emsp14: 8197,
12860 eparsl: 10723,
12861 eqcirc: 8790,
12862 equals: 61,
12863 equest: 8799,
12864 female: 9792,
12865 ffilig: 64259,
12866 ffllig: 64260,
12867 forall: 8704,
12868 frac12: 189,
12869 frac13: 8531,
12870 frac14: 188,
12871 frac15: 8533,
12872 frac16: 8537,
12873 frac18: 8539,
12874 frac23: 8532,
12875 frac25: 8534,
12876 frac34: 190,
12877 frac35: 8535,
12878 frac38: 8540,
12879 frac45: 8536,
12880 frac56: 8538,
12881 frac58: 8541,
12882 frac78: 8542,
12883 gacute: 501,
12884 gammad: 989,
12885 gbreve: 287,
12886 gesdot: 10880,
12887 gesles: 10900,
12888 gtlPar: 10645,
12889 gtrarr: 10616,
12890 gtrdot: 8919,
12891 gtrsim: 8819,
12892 hairsp: 8202,
12893 hamilt: 8459,
12894 hardcy: 1098,
12895 hearts: 9829,
12896 hellip: 8230,
12897 hercon: 8889,
12898 homtht: 8763,
12899 horbar: 8213,
12900 hslash: 8463,
12901 hstrok: 295,
12902 hybull: 8259,
12903 hyphen: 8208,
12904 iacute: 237,
12905 igrave: 236,
12906 iiiint: 10764,
12907 iinfin: 10716,
12908 incare: 8453,
12909 inodot: 305,
12910 intcal: 8890,
12911 iquest: 191,
12912 isinsv: 8947,
12913 itilde: 297,
12914 jsercy: 1112,
12915 kappav: 1008,
12916 kcedil: 311,
12917 kgreen: 312,
12918 lAtail: 10523,
12919 lacute: 314,
12920 lagran: 8466,
12921 lambda: 955,
12922 langle: 10216,
12923 larrfs: 10525,
12924 larrhk: 8617,
12925 larrlp: 8619,
12926 larrpl: 10553,
12927 larrtl: 8610,
12928 latail: 10521,
12929 lbrace: 123,
12930 lbrack: 91,
12931 lcaron: 318,
12932 lcedil: 316,
12933 ldquor: 8222,
12934 lesdot: 10879,
12935 lesges: 10899,
12936 lfisht: 10620,
12937 lfloor: 8970,
12938 lharul: 10602,
12939 llhard: 10603,
12940 lmidot: 320,
12941 lmoust: 9136,
12942 loplus: 10797,
12943 lowast: 8727,
12944 lowbar: 95,
12945 lparlt: 10643,
12946 lrhard: 10605,
12947 lsaquo: 8249,
12948 lsquor: 8218,
12949 lstrok: 322,
12950 lthree: 8907,
12951 ltimes: 8905,
12952 ltlarr: 10614,
12953 ltrPar: 10646,
12954 mapsto: 8614,
12955 marker: 9646,
12956 mcomma: 10793,
12957 midast: 42,
12958 midcir: 10992,
12959 middot: 183,
12960 minusb: 8863,
12961 minusd: 8760,
12962 mnplus: 8723,
12963 models: 8871,
12964 mstpos: 8766,
12965 nVDash: 8879,
12966 nVdash: 8878,
12967 nacute: 324,
12968 ncaron: 328,
12969 ncedil: 326,
12970 nearhk: 10532,
12971 nequiv: 8802,
12972 nesear: 10536,
12973 nexist: 8708,
12974 nltrie: 8940,
12975 nprcue: 8928,
12976 nrtrie: 8941,
12977 nsccue: 8929,
12978 nsimeq: 8772,
12979 ntilde: 241,
12980 numero: 8470,
12981 nvDash: 8877,
12982 nvHarr: 10500,
12983 nvdash: 8876,
12984 nvlArr: 10498,
12985 nvrArr: 10499,
12986 nwarhk: 10531,
12987 nwnear: 10535,
12988 oacute: 243,
12989 odblac: 337,
12990 odsold: 10684,
12991 ograve: 242,
12992 ominus: 8854,
12993 origof: 8886,
12994 oslash: 248,
12995 otilde: 245,
12996 otimes: 8855,
12997 parsim: 10995,
12998 percnt: 37,
12999 period: 46,
13000 permil: 8240,
13001 phmmat: 8499,
13002 planck: 8463,
13003 plankv: 8463,
13004 plusdo: 8724,
13005 plusdu: 10789,
13006 plusmn: 177,
13007 preceq: 10927,
13008 primes: 8473,
13009 prnsim: 8936,
13010 propto: 8733,
13011 prurel: 8880,
13012 puncsp: 8200,
13013 qprime: 8279,
13014 rAtail: 10524,
13015 racute: 341,
13016 rangle: 10217,
13017 rarrap: 10613,
13018 rarrfs: 10526,
13019 rarrhk: 8618,
13020 rarrlp: 8620,
13021 rarrpl: 10565,
13022 rarrtl: 8611,
13023 ratail: 10522,
13024 rbrace: 125,
13025 rbrack: 93,
13026 rcaron: 345,
13027 rcedil: 343,
13028 rdquor: 8221,
13029 rfisht: 10621,
13030 rfloor: 8971,
13031 rharul: 10604,
13032 rmoust: 9137,
13033 roplus: 10798,
13034 rpargt: 10644,
13035 rsaquo: 8250,
13036 rsquor: 8217,
13037 rthree: 8908,
13038 rtimes: 8906,
13039 sacute: 347,
13040 scaron: 353,
13041 scedil: 351,
13042 scnsim: 8937,
13043 searhk: 10533,
13044 seswar: 10537,
13045 sfrown: 8994,
13046 shchcy: 1097,
13047 sigmaf: 962,
13048 sigmav: 962,
13049 simdot: 10858,
13050 smashp: 10803,
13051 softcy: 1100,
13052 solbar: 9023,
13053 spades: 9824,
13054 sqsube: 8849,
13055 sqsupe: 8850,
13056 square: 9633,
13057 squarf: 9642,
13058 ssetmn: 8726,
13059 ssmile: 8995,
13060 sstarf: 8902,
13061 subdot: 10941,
13062 subset: 8834,
13063 subsim: 10951,
13064 subsub: 10965,
13065 subsup: 10963,
13066 succeq: 10928,
13067 supdot: 10942,
13068 supset: 8835,
13069 supsim: 10952,
13070 supsub: 10964,
13071 supsup: 10966,
13072 swarhk: 10534,
13073 swnwar: 10538,
13074 target: 8982,
13075 tcaron: 357,
13076 tcedil: 355,
13077 telrec: 8981,
13078 there4: 8756,
13079 thetav: 977,
13080 thinsp: 8201,
13081 thksim: 8764,
13082 timesb: 8864,
13083 timesd: 10800,
13084 topbot: 9014,
13085 topcir: 10993,
13086 tprime: 8244,
13087 tridot: 9708,
13088 tstrok: 359,
13089 uacute: 250,
13090 ubreve: 365,
13091 udblac: 369,
13092 ufisht: 10622,
13093 ugrave: 249,
13094 ulcorn: 8988,
13095 ulcrop: 8975,
13096 urcorn: 8989,
13097 urcrop: 8974,
13098 utilde: 361,
13099 vangrt: 10652,
13100 varphi: 966,
13101 varrho: 1009,
13102 veebar: 8891,
13103 vellip: 8942,
13104 verbar: 124,
13105 wedbar: 10847,
13106 wedgeq: 8793,
13107 weierp: 8472,
13108 wreath: 8768,
13109 xoplus: 10753,
13110 xotime: 10754,
13111 xsqcup: 10758,
13112 xuplus: 10756,
13113 xwedge: 8896,
13114 yacute: 253,
13115 zacute: 378,
13116 zcaron: 382,
13117 zeetrf: 8488,
13118 AElig: 198,
13119 Acirc: 194,
13120 Alpha: 913,
13121 Amacr: 256,
13122 Aogon: 260,
13123 Aring: 197,
13124 Breve: 728,
13125 Ccirc: 264,
13126 Colon: 8759,
13127 Cross: 10799,
13128 Dashv: 10980,
13129 Delta: 916,
13130 Ecirc: 202,
13131 Emacr: 274,
13132 Eogon: 280,
13133 Equal: 10869,
13134 Gamma: 915,
13135 Gcirc: 284,
13136 Hacek: 711,
13137 Hcirc: 292,
13138 IJlig: 306,
13139 Icirc: 206,
13140 Imacr: 298,
13141 Iogon: 302,
13142 Iukcy: 1030,
13143 Jcirc: 308,
13144 Jukcy: 1028,
13145 Kappa: 922,
13146 OElig: 338,
13147 Ocirc: 212,
13148 Omacr: 332,
13149 Omega: 937,
13150 Prime: 8243,
13151 RBarr: 10512,
13152 Scirc: 348,
13153 Sigma: 931,
13154 THORN: 222,
13155 TRADE: 8482,
13156 TSHcy: 1035,
13157 Theta: 920,
13158 Tilde: 8764,
13159 Ubrcy: 1038,
13160 Ucirc: 219,
13161 Umacr: 362,
13162 Union: 8899,
13163 Uogon: 370,
13164 UpTee: 8869,
13165 Uring: 366,
13166 VDash: 8875,
13167 Vdash: 8873,
13168 Wcirc: 372,
13169 Wedge: 8896,
13170 Ycirc: 374,
13171 acirc: 226,
13172 acute: 180,
13173 aelig: 230,
13174 aleph: 8501,
13175 alpha: 945,
13176 amacr: 257,
13177 amalg: 10815,
13178 angle: 8736,
13179 angrt: 8735,
13180 angst: 8491,
13181 aogon: 261,
13182 aring: 229,
13183 asymp: 8776,
13184 awint: 10769,
13185 bcong: 8780,
13186 bdquo: 8222,
13187 bepsi: 1014,
13188 blank: 9251,
13189 blk12: 9618,
13190 blk14: 9617,
13191 blk34: 9619,
13192 block: 9608,
13193 boxDL: 9559,
13194 boxDR: 9556,
13195 boxDl: 9558,
13196 boxDr: 9555,
13197 boxHD: 9574,
13198 boxHU: 9577,
13199 boxHd: 9572,
13200 boxHu: 9575,
13201 boxUL: 9565,
13202 boxUR: 9562,
13203 boxUl: 9564,
13204 boxUr: 9561,
13205 boxVH: 9580,
13206 boxVL: 9571,
13207 boxVR: 9568,
13208 boxVh: 9579,
13209 boxVl: 9570,
13210 boxVr: 9567,
13211 boxdL: 9557,
13212 boxdR: 9554,
13213 boxdl: 9488,
13214 boxdr: 9484,
13215 boxhD: 9573,
13216 boxhU: 9576,
13217 boxhd: 9516,
13218 boxhu: 9524,
13219 boxuL: 9563,
13220 boxuR: 9560,
13221 boxul: 9496,
13222 boxur: 9492,
13223 boxvH: 9578,
13224 boxvL: 9569,
13225 boxvR: 9566,
13226 boxvh: 9532,
13227 boxvl: 9508,
13228 boxvr: 9500,
13229 breve: 728,
13230 bsemi: 8271,
13231 bsime: 8909,
13232 bsolb: 10693,
13233 bumpE: 10926,
13234 bumpe: 8783,
13235 caret: 8257,
13236 caron: 711,
13237 ccaps: 10829,
13238 ccirc: 265,
13239 ccups: 10828,
13240 cedil: 184,
13241 check: 10003,
13242 clubs: 9827,
13243 colon: 58,
13244 comma: 44,
13245 crarr: 8629,
13246 cross: 10007,
13247 csube: 10961,
13248 csupe: 10962,
13249 ctdot: 8943,
13250 cuepr: 8926,
13251 cuesc: 8927,
13252 cupor: 10821,
13253 cuvee: 8910,
13254 cuwed: 8911,
13255 cwint: 8753,
13256 dashv: 8867,
13257 dblac: 733,
13258 ddarr: 8650,
13259 delta: 948,
13260 dharl: 8643,
13261 dharr: 8642,
13262 diams: 9830,
13263 disin: 8946,
13264 doteq: 8784,
13265 dtdot: 8945,
13266 dtrif: 9662,
13267 duarr: 8693,
13268 duhar: 10607,
13269 eDDot: 10871,
13270 ecirc: 234,
13271 efDot: 8786,
13272 emacr: 275,
13273 empty: 8709,
13274 eogon: 281,
13275 eplus: 10865,
13276 epsiv: 949,
13277 eqsim: 8770,
13278 equiv: 8801,
13279 erDot: 8787,
13280 erarr: 10609,
13281 esdot: 8784,
13282 exist: 8707,
13283 fflig: 64256,
13284 filig: 64257,
13285 fllig: 64258,
13286 fltns: 9649,
13287 forkv: 10969,
13288 frasl: 8260,
13289 frown: 8994,
13290 gamma: 947,
13291 gcirc: 285,
13292 gescc: 10921,
13293 gimel: 8503,
13294 gneqq: 8809,
13295 gnsim: 8935,
13296 grave: 96,
13297 gsime: 10894,
13298 gsiml: 10896,
13299 gtcir: 10874,
13300 gtdot: 8919,
13301 harrw: 8621,
13302 hcirc: 293,
13303 hoarr: 8703,
13304 icirc: 238,
13305 iexcl: 161,
13306 iiint: 8749,
13307 iiota: 8489,
13308 ijlig: 307,
13309 imacr: 299,
13310 image: 8465,
13311 imath: 305,
13312 imped: 437,
13313 infin: 8734,
13314 iogon: 303,
13315 iprod: 10812,
13316 isinE: 8953,
13317 isins: 8948,
13318 isinv: 8712,
13319 iukcy: 1110,
13320 jcirc: 309,
13321 jmath: 567,
13322 jukcy: 1108,
13323 kappa: 954,
13324 lAarr: 8666,
13325 lBarr: 10510,
13326 langd: 10641,
13327 laquo: 171,
13328 larrb: 8676,
13329 lbarr: 10508,
13330 lbbrk: 10098,
13331 lbrke: 10635,
13332 lceil: 8968,
13333 ldquo: 8220,
13334 lescc: 10920,
13335 lhard: 8637,
13336 lharu: 8636,
13337 lhblk: 9604,
13338 llarr: 8647,
13339 lltri: 9722,
13340 lneqq: 8808,
13341 lnsim: 8934,
13342 loang: 10220,
13343 loarr: 8701,
13344 lobrk: 10214,
13345 lopar: 10629,
13346 lrarr: 8646,
13347 lrhar: 8651,
13348 lrtri: 8895,
13349 lsime: 10893,
13350 lsimg: 10895,
13351 lsquo: 8216,
13352 ltcir: 10873,
13353 ltdot: 8918,
13354 ltrie: 8884,
13355 ltrif: 9666,
13356 mDDot: 8762,
13357 mdash: 8212,
13358 micro: 181,
13359 minus: 8722,
13360 mumap: 8888,
13361 nabla: 8711,
13362 napos: 329,
13363 natur: 9838,
13364 ncong: 8775,
13365 ndash: 8211,
13366 neArr: 8663,
13367 nearr: 8599,
13368 ngsim: 8821,
13369 nhArr: 8654,
13370 nharr: 8622,
13371 nhpar: 10994,
13372 nlArr: 8653,
13373 nlarr: 8602,
13374 nless: 8814,
13375 nlsim: 8820,
13376 nltri: 8938,
13377 notin: 8713,
13378 notni: 8716,
13379 nprec: 8832,
13380 nrArr: 8655,
13381 nrarr: 8603,
13382 nrtri: 8939,
13383 nsime: 8772,
13384 nsmid: 8740,
13385 nspar: 8742,
13386 nsube: 8840,
13387 nsucc: 8833,
13388 nsupe: 8841,
13389 numsp: 8199,
13390 nwArr: 8662,
13391 nwarr: 8598,
13392 ocirc: 244,
13393 odash: 8861,
13394 oelig: 339,
13395 ofcir: 10687,
13396 ohbar: 10677,
13397 olarr: 8634,
13398 olcir: 10686,
13399 oline: 8254,
13400 omacr: 333,
13401 omega: 969,
13402 operp: 10681,
13403 oplus: 8853,
13404 orarr: 8635,
13405 order: 8500,
13406 ovbar: 9021,
13407 parsl: 11005,
13408 phone: 9742,
13409 plusb: 8862,
13410 pluse: 10866,
13411 pound: 163,
13412 prcue: 8828,
13413 prime: 8242,
13414 prnap: 10937,
13415 prsim: 8830,
13416 quest: 63,
13417 rAarr: 8667,
13418 rBarr: 10511,
13419 radic: 8730,
13420 rangd: 10642,
13421 range: 10661,
13422 raquo: 187,
13423 rarrb: 8677,
13424 rarrc: 10547,
13425 rarrw: 8605,
13426 ratio: 8758,
13427 rbarr: 10509,
13428 rbbrk: 10099,
13429 rbrke: 10636,
13430 rceil: 8969,
13431 rdquo: 8221,
13432 reals: 8477,
13433 rhard: 8641,
13434 rharu: 8640,
13435 rlarr: 8644,
13436 rlhar: 8652,
13437 rnmid: 10990,
13438 roang: 10221,
13439 roarr: 8702,
13440 robrk: 10215,
13441 ropar: 10630,
13442 rrarr: 8649,
13443 rsquo: 8217,
13444 rtrie: 8885,
13445 rtrif: 9656,
13446 sbquo: 8218,
13447 sccue: 8829,
13448 scirc: 349,
13449 scnap: 10938,
13450 scsim: 8831,
13451 sdotb: 8865,
13452 sdote: 10854,
13453 seArr: 8664,
13454 searr: 8600,
13455 setmn: 8726,
13456 sharp: 9839,
13457 sigma: 963,
13458 simeq: 8771,
13459 simgE: 10912,
13460 simlE: 10911,
13461 simne: 8774,
13462 slarr: 8592,
13463 smile: 8995,
13464 sqcap: 8851,
13465 sqcup: 8852,
13466 sqsub: 8847,
13467 sqsup: 8848,
13468 srarr: 8594,
13469 starf: 9733,
13470 strns: 175,
13471 subnE: 10955,
13472 subne: 8842,
13473 supnE: 10956,
13474 supne: 8843,
13475 swArr: 8665,
13476 swarr: 8601,
13477 szlig: 223,
13478 theta: 952,
13479 thkap: 8776,
13480 thorn: 254,
13481 tilde: 732,
13482 times: 215,
13483 trade: 8482,
13484 trisb: 10701,
13485 tshcy: 1115,
13486 twixt: 8812,
13487 ubrcy: 1118,
13488 ucirc: 251,
13489 udarr: 8645,
13490 udhar: 10606,
13491 uharl: 8639,
13492 uharr: 8638,
13493 uhblk: 9600,
13494 ultri: 9720,
13495 umacr: 363,
13496 uogon: 371,
13497 uplus: 8846,
13498 upsih: 978,
13499 uring: 367,
13500 urtri: 9721,
13501 utdot: 8944,
13502 utrif: 9652,
13503 uuarr: 8648,
13504 vBarv: 10985,
13505 vDash: 8872,
13506 varpi: 982,
13507 vdash: 8866,
13508 veeeq: 8794,
13509 vltri: 8882,
13510 vprop: 8733,
13511 vrtri: 8883,
13512 wcirc: 373,
13513 wedge: 8743,
13514 xcirc: 9711,
13515 xdtri: 9661,
13516 xhArr: 10234,
13517 xharr: 10231,
13518 xlArr: 10232,
13519 xlarr: 10229,
13520 xodot: 10752,
13521 xrArr: 10233,
13522 xrarr: 10230,
13523 xutri: 9651,
13524 ycirc: 375,
13525 Aopf: 120120,
13526 Ascr: 119964,
13527 Auml: 196,
13528 Barv: 10983,
13529 Beta: 914,
13530 Bopf: 120121,
13531 Bscr: 8492,
13532 CHcy: 1063,
13533 COPY: 169,
13534 Cdot: 266,
13535 Copf: 8450,
13536 Cscr: 119966,
13537 DJcy: 1026,
13538 DScy: 1029,
13539 DZcy: 1039,
13540 Darr: 8609,
13541 Dopf: 120123,
13542 Dscr: 119967,
13543 Edot: 278,
13544 Eopf: 120124,
13545 Escr: 8496,
13546 Esim: 10867,
13547 Euml: 203,
13548 Fopf: 120125,
13549 Fscr: 8497,
13550 GJcy: 1027,
13551 Gdot: 288,
13552 Gopf: 120126,
13553 Gscr: 119970,
13554 Hopf: 8461,
13555 Hscr: 8459,
13556 IEcy: 1045,
13557 IOcy: 1025,
13558 Idot: 304,
13559 Iopf: 120128,
13560 Iota: 921,
13561 Iscr: 8464,
13562 Iuml: 207,
13563 Jopf: 120129,
13564 Jscr: 119973,
13565 KHcy: 1061,
13566 KJcy: 1036,
13567 Kopf: 120130,
13568 Kscr: 119974,
13569 LJcy: 1033,
13570 Lang: 10218,
13571 Larr: 8606,
13572 Lopf: 120131,
13573 Lscr: 8466,
13574 Mopf: 120132,
13575 Mscr: 8499,
13576 NJcy: 1034,
13577 Nopf: 8469,
13578 Nscr: 119977,
13579 Oopf: 120134,
13580 Oscr: 119978,
13581 Ouml: 214,
13582 Popf: 8473,
13583 Pscr: 119979,
13584 QUOT: 34,
13585 Qopf: 8474,
13586 Qscr: 119980,
13587 Rang: 10219,
13588 Rarr: 8608,
13589 Ropf: 8477,
13590 Rscr: 8475,
13591 SHcy: 1064,
13592 Sopf: 120138,
13593 Sqrt: 8730,
13594 Sscr: 119982,
13595 Star: 8902,
13596 TScy: 1062,
13597 Topf: 120139,
13598 Tscr: 119983,
13599 Uarr: 8607,
13600 Uopf: 120140,
13601 Upsi: 978,
13602 Uscr: 119984,
13603 Uuml: 220,
13604 Vbar: 10987,
13605 Vert: 8214,
13606 Vopf: 120141,
13607 Vscr: 119985,
13608 Wopf: 120142,
13609 Wscr: 119986,
13610 Xopf: 120143,
13611 Xscr: 119987,
13612 YAcy: 1071,
13613 YIcy: 1031,
13614 YUcy: 1070,
13615 Yopf: 120144,
13616 Yscr: 119988,
13617 Yuml: 376,
13618 ZHcy: 1046,
13619 Zdot: 379,
13620 Zeta: 918,
13621 Zopf: 8484,
13622 Zscr: 119989,
13623 andd: 10844,
13624 andv: 10842,
13625 ange: 10660,
13626 aopf: 120146,
13627 apid: 8779,
13628 apos: 39,
13629 ascr: 119990,
13630 auml: 228,
13631 bNot: 10989,
13632 bbrk: 9141,
13633 beta: 946,
13634 beth: 8502,
13635 bnot: 8976,
13636 bopf: 120147,
13637 boxH: 9552,
13638 boxV: 9553,
13639 boxh: 9472,
13640 boxv: 9474,
13641 bscr: 119991,
13642 bsim: 8765,
13643 bsol: 92,
13644 bull: 8226,
13645 bump: 8782,
13646 cdot: 267,
13647 cent: 162,
13648 chcy: 1095,
13649 cirE: 10691,
13650 circ: 710,
13651 cire: 8791,
13652 comp: 8705,
13653 cong: 8773,
13654 copf: 120148,
13655 copy: 169,
13656 cscr: 119992,
13657 csub: 10959,
13658 csup: 10960,
13659 dArr: 8659,
13660 dHar: 10597,
13661 darr: 8595,
13662 dash: 8208,
13663 diam: 8900,
13664 djcy: 1106,
13665 dopf: 120149,
13666 dscr: 119993,
13667 dscy: 1109,
13668 dsol: 10742,
13669 dtri: 9663,
13670 dzcy: 1119,
13671 eDot: 8785,
13672 ecir: 8790,
13673 edot: 279,
13674 emsp: 8195,
13675 ensp: 8194,
13676 eopf: 120150,
13677 epar: 8917,
13678 epsi: 1013,
13679 escr: 8495,
13680 esim: 8770,
13681 euml: 235,
13682 euro: 8364,
13683 excl: 33,
13684 flat: 9837,
13685 fnof: 402,
13686 fopf: 120151,
13687 fork: 8916,
13688 fscr: 119995,
13689 gdot: 289,
13690 geqq: 8807,
13691 gjcy: 1107,
13692 gnap: 10890,
13693 gneq: 10888,
13694 gopf: 120152,
13695 gscr: 8458,
13696 gsim: 8819,
13697 gtcc: 10919,
13698 hArr: 8660,
13699 half: 189,
13700 harr: 8596,
13701 hbar: 8463,
13702 hopf: 120153,
13703 hscr: 119997,
13704 iecy: 1077,
13705 imof: 8887,
13706 iocy: 1105,
13707 iopf: 120154,
13708 iota: 953,
13709 iscr: 119998,
13710 isin: 8712,
13711 iuml: 239,
13712 jopf: 120155,
13713 jscr: 119999,
13714 khcy: 1093,
13715 kjcy: 1116,
13716 kopf: 120156,
13717 kscr: 120000,
13718 lArr: 8656,
13719 lHar: 10594,
13720 lang: 10216,
13721 larr: 8592,
13722 late: 10925,
13723 lcub: 123,
13724 ldca: 10550,
13725 ldsh: 8626,
13726 leqq: 8806,
13727 ljcy: 1113,
13728 lnap: 10889,
13729 lneq: 10887,
13730 lopf: 120157,
13731 lozf: 10731,
13732 lpar: 40,
13733 lscr: 120001,
13734 lsim: 8818,
13735 lsqb: 91,
13736 ltcc: 10918,
13737 ltri: 9667,
13738 macr: 175,
13739 male: 9794,
13740 malt: 10016,
13741 mlcp: 10971,
13742 mldr: 8230,
13743 mopf: 120158,
13744 mscr: 120002,
13745 nbsp: 160,
13746 ncap: 10819,
13747 ncup: 10818,
13748 ngeq: 8817,
13749 ngtr: 8815,
13750 nisd: 8954,
13751 njcy: 1114,
13752 nldr: 8229,
13753 nleq: 8816,
13754 nmid: 8740,
13755 nopf: 120159,
13756 npar: 8742,
13757 nscr: 120003,
13758 nsim: 8769,
13759 nsub: 8836,
13760 nsup: 8837,
13761 ntgl: 8825,
13762 ntlg: 8824,
13763 oast: 8859,
13764 ocir: 8858,
13765 odiv: 10808,
13766 odot: 8857,
13767 ogon: 731,
13768 oint: 8750,
13769 omid: 10678,
13770 oopf: 120160,
13771 opar: 10679,
13772 ordf: 170,
13773 ordm: 186,
13774 oror: 10838,
13775 oscr: 8500,
13776 osol: 8856,
13777 ouml: 246,
13778 para: 182,
13779 part: 8706,
13780 perp: 8869,
13781 phiv: 966,
13782 plus: 43,
13783 popf: 120161,
13784 prap: 10935,
13785 prec: 8826,
13786 prnE: 10933,
13787 prod: 8719,
13788 prop: 8733,
13789 pscr: 120005,
13790 qint: 10764,
13791 qopf: 120162,
13792 qscr: 120006,
13793 quot: 34,
13794 rArr: 8658,
13795 rHar: 10596,
13796 race: 10714,
13797 rang: 10217,
13798 rarr: 8594,
13799 rcub: 125,
13800 rdca: 10551,
13801 rdsh: 8627,
13802 real: 8476,
13803 rect: 9645,
13804 rhov: 1009,
13805 ring: 730,
13806 ropf: 120163,
13807 rpar: 41,
13808 rscr: 120007,
13809 rsqb: 93,
13810 rtri: 9657,
13811 scap: 10936,
13812 scnE: 10934,
13813 sdot: 8901,
13814 sect: 167,
13815 semi: 59,
13816 sext: 10038,
13817 shcy: 1096,
13818 sime: 8771,
13819 simg: 10910,
13820 siml: 10909,
13821 smid: 8739,
13822 smte: 10924,
13823 solb: 10692,
13824 sopf: 120164,
13825 spar: 8741,
13826 squf: 9642,
13827 sscr: 120008,
13828 star: 9734,
13829 subE: 10949,
13830 sube: 8838,
13831 succ: 8827,
13832 sung: 9834,
13833 sup1: 185,
13834 sup2: 178,
13835 sup3: 179,
13836 supE: 10950,
13837 supe: 8839,
13838 tbrk: 9140,
13839 tdot: 8411,
13840 tint: 8749,
13841 toea: 10536,
13842 topf: 120165,
13843 tosa: 10537,
13844 trie: 8796,
13845 tscr: 120009,
13846 tscy: 1094,
13847 uArr: 8657,
13848 uHar: 10595,
13849 uarr: 8593,
13850 uopf: 120166,
13851 upsi: 965,
13852 uscr: 120010,
13853 utri: 9653,
13854 uuml: 252,
13855 vArr: 8661,
13856 vBar: 10984,
13857 varr: 8597,
13858 vert: 124,
13859 vopf: 120167,
13860 vscr: 120011,
13861 wopf: 120168,
13862 wscr: 120012,
13863 xcap: 8898,
13864 xcup: 8899,
13865 xmap: 10236,
13866 xnis: 8955,
13867 xopf: 120169,
13868 xscr: 120013,
13869 xvee: 8897,
13870 yacy: 1103,
13871 yicy: 1111,
13872 yopf: 120170,
13873 yscr: 120014,
13874 yucy: 1102,
13875 yuml: 255,
13876 zdot: 380,
13877 zeta: 950,
13878 zhcy: 1078,
13879 zopf: 120171,
13880 zscr: 120015,
13881 zwnj: 8204,
13882 AMP: 38,
13883 Acy: 1040,
13884 Afr: 120068,
13885 And: 10835,
13886 Bcy: 1041,
13887 Bfr: 120069,
13888 Cap: 8914,
13889 Cfr: 8493,
13890 Chi: 935,
13891 Cup: 8915,
13892 Dcy: 1044,
13893 Del: 8711,
13894 Dfr: 120071,
13895 Dot: 168,
13896 ENG: 330,
13897 ETH: 208,
13898 Ecy: 1069,
13899 Efr: 120072,
13900 Eta: 919,
13901 Fcy: 1060,
13902 Ffr: 120073,
13903 Gcy: 1043,
13904 Gfr: 120074,
13905 Hat: 94,
13906 Hfr: 8460,
13907 Icy: 1048,
13908 Ifr: 8465,
13909 Int: 8748,
13910 Jcy: 1049,
13911 Jfr: 120077,
13912 Kcy: 1050,
13913 Kfr: 120078,
13914 Lcy: 1051,
13915 Lfr: 120079,
13916 Lsh: 8624,
13917 Map: 10501,
13918 Mcy: 1052,
13919 Mfr: 120080,
13920 Ncy: 1053,
13921 Nfr: 120081,
13922 Not: 10988,
13923 Ocy: 1054,
13924 Ofr: 120082,
13925 Pcy: 1055,
13926 Pfr: 120083,
13927 Phi: 934,
13928 Psi: 936,
13929 Qfr: 120084,
13930 REG: 174,
13931 Rcy: 1056,
13932 Rfr: 8476,
13933 Rho: 929,
13934 Rsh: 8625,
13935 Scy: 1057,
13936 Sfr: 120086,
13937 Sub: 8912,
13938 Sum: 8721,
13939 Sup: 8913,
13940 Tab: 9,
13941 Tau: 932,
13942 Tcy: 1058,
13943 Tfr: 120087,
13944 Ucy: 1059,
13945 Ufr: 120088,
13946 Vcy: 1042,
13947 Vee: 8897,
13948 Vfr: 120089,
13949 Wfr: 120090,
13950 Xfr: 120091,
13951 Ycy: 1067,
13952 Yfr: 120092,
13953 Zcy: 1047,
13954 Zfr: 8488,
13955 acd: 8767,
13956 acy: 1072,
13957 afr: 120094,
13958 amp: 38,
13959 and: 8743,
13960 ang: 8736,
13961 apE: 10864,
13962 ape: 8778,
13963 ast: 42,
13964 bcy: 1073,
13965 bfr: 120095,
13966 bot: 8869,
13967 cap: 8745,
13968 cfr: 120096,
13969 chi: 967,
13970 cir: 9675,
13971 cup: 8746,
13972 dcy: 1076,
13973 deg: 176,
13974 dfr: 120097,
13975 die: 168,
13976 div: 247,
13977 dot: 729,
13978 ecy: 1101,
13979 efr: 120098,
13980 egs: 10902,
13981 ell: 8467,
13982 els: 10901,
13983 eng: 331,
13984 eta: 951,
13985 eth: 240,
13986 fcy: 1092,
13987 ffr: 120099,
13988 gEl: 10892,
13989 gap: 10886,
13990 gcy: 1075,
13991 gel: 8923,
13992 geq: 8805,
13993 ges: 10878,
13994 gfr: 120100,
13995 ggg: 8921,
13996 glE: 10898,
13997 gla: 10917,
13998 glj: 10916,
13999 gnE: 8809,
14000 gne: 10888,
14001 hfr: 120101,
14002 icy: 1080,
14003 iff: 8660,
14004 ifr: 120102,
14005 int: 8747,
14006 jcy: 1081,
14007 jfr: 120103,
14008 kcy: 1082,
14009 kfr: 120104,
14010 lEg: 10891,
14011 lap: 10885,
14012 lat: 10923,
14013 lcy: 1083,
14014 leg: 8922,
14015 leq: 8804,
14016 les: 10877,
14017 lfr: 120105,
14018 lgE: 10897,
14019 lnE: 8808,
14020 lne: 10887,
14021 loz: 9674,
14022 lrm: 8206,
14023 lsh: 8624,
14024 map: 8614,
14025 mcy: 1084,
14026 mfr: 120106,
14027 mho: 8487,
14028 mid: 8739,
14029 nap: 8777,
14030 ncy: 1085,
14031 nfr: 120107,
14032 nge: 8817,
14033 ngt: 8815,
14034 nis: 8956,
14035 niv: 8715,
14036 nle: 8816,
14037 nlt: 8814,
14038 not: 172,
14039 npr: 8832,
14040 nsc: 8833,
14041 num: 35,
14042 ocy: 1086,
14043 ofr: 120108,
14044 ogt: 10689,
14045 ohm: 8486,
14046 olt: 10688,
14047 ord: 10845,
14048 orv: 10843,
14049 par: 8741,
14050 pcy: 1087,
14051 pfr: 120109,
14052 phi: 966,
14053 piv: 982,
14054 prE: 10931,
14055 pre: 10927,
14056 psi: 968,
14057 qfr: 120110,
14058 rcy: 1088,
14059 reg: 174,
14060 rfr: 120111,
14061 rho: 961,
14062 rlm: 8207,
14063 rsh: 8625,
14064 scE: 10932,
14065 sce: 10928,
14066 scy: 1089,
14067 sfr: 120112,
14068 shy: 173,
14069 sim: 8764,
14070 smt: 10922,
14071 sol: 47,
14072 squ: 9633,
14073 sub: 8834,
14074 sum: 8721,
14075 sup: 8835,
14076 tau: 964,
14077 tcy: 1090,
14078 tfr: 120113,
14079 top: 8868,
14080 ucy: 1091,
14081 ufr: 120114,
14082 uml: 168,
14083 vcy: 1074,
14084 vee: 8744,
14085 vfr: 120115,
14086 wfr: 120116,
14087 xfr: 120117,
14088 ycy: 1099,
14089 yen: 165,
14090 yfr: 120118,
14091 zcy: 1079,
14092 zfr: 120119,
14093 zwj: 8205,
14094 DD: 8517,
14095 GT: 62,
14096 Gg: 8921,
14097 Gt: 8811,
14098 Im: 8465,
14099 LT: 60,
14100 Ll: 8920,
14101 Lt: 8810,
14102 Mu: 924,
14103 Nu: 925,
14104 Or: 10836,
14105 Pi: 928,
14106 Pr: 10939,
14107 Re: 8476,
14108 Sc: 10940,
14109 Xi: 926,
14110 ac: 8766,
14111 af: 8289,
14112 ap: 8776,
14113 dd: 8518,
14114 ee: 8519,
14115 eg: 10906,
14116 el: 10905,
14117 gE: 8807,
14118 ge: 8805,
14119 gg: 8811,
14120 gl: 8823,
14121 gt: 62,
14122 ic: 8291,
14123 ii: 8520,
14124 in: 8712,
14125 it: 8290,
14126 lE: 8806,
14127 le: 8804,
14128 lg: 8822,
14129 ll: 8810,
14130 lt: 60,
14131 mp: 8723,
14132 mu: 956,
14133 ne: 8800,
14134 ni: 8715,
14135 nu: 957,
14136 oS: 9416,
14137 or: 8744,
14138 pi: 960,
14139 pm: 177,
14140 pr: 8826,
14141 rx: 8478,
14142 sc: 8827,
14143 wp: 8472,
14144 wr: 8768,
14145 xi: 958
14146};
14147
14148const windows_1252 = [
14149 8364,
14150 129,
14151 8218,
14152 402,
14153 8222,
14154 8230,
14155 8224,
14156 8225,
14157 710,
14158 8240,
14159 352,
14160 8249,
14161 338,
14162 141,
14163 381,
14164 143,
14165 144,
14166 8216,
14167 8217,
14168 8220,
14169 8221,
14170 8226,
14171 8211,
14172 8212,
14173 732,
14174 8482,
14175 353,
14176 8250,
14177 339,
14178 157,
14179 382,
14180 376
14181];
14182const entity_pattern = new RegExp(`&(#?(?:x[\\w\\d]+|\\d+|${Object.keys(entities).join('|')}))(?:;|\\b)`, 'g');
14183function decode_character_references(html) {
14184 return html.replace(entity_pattern, (match, entity) => {
14185 let code;
14186 // Handle named entities
14187 if (entity[0] !== '#') {
14188 code = entities[entity];
14189 }
14190 else if (entity[1] === 'x') {
14191 code = parseInt(entity.substring(2), 16);
14192 }
14193 else {
14194 code = parseInt(entity.substring(1), 10);
14195 }
14196 if (!code) {
14197 return match;
14198 }
14199 return String.fromCodePoint(validate_code(code));
14200 });
14201}
14202const NUL = 0;
14203// some code points are verboten. If we were inserting HTML, the browser would replace the illegal
14204// code points with alternatives in some cases - since we're bypassing that mechanism, we need
14205// to replace them ourselves
14206//
14207// Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
14208function validate_code(code) {
14209 // line feed becomes generic whitespace
14210 if (code === 10) {
14211 return 32;
14212 }
14213 // ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
14214 if (code < 128) {
14215 return code;
14216 }
14217 // code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
14218 // to correct the mistake or we'll end up with missing € signs and so on
14219 if (code <= 159) {
14220 return windows_1252[code - 128];
14221 }
14222 // basic multilingual plane
14223 if (code < 55296) {
14224 return code;
14225 }
14226 // UTF-16 surrogate halves
14227 if (code <= 57343) {
14228 return NUL;
14229 }
14230 // rest of the basic multilingual plane
14231 if (code <= 65535) {
14232 return code;
14233 }
14234 // supplementary multilingual plane 0x10000 - 0x1ffff
14235 if (code >= 65536 && code <= 131071) {
14236 return code;
14237 }
14238 // supplementary ideographic plane 0x20000 - 0x2ffff
14239 if (code >= 131072 && code <= 196607) {
14240 return code;
14241 }
14242 return NUL;
14243}
14244// based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
14245const disallowed_contents = new Map([
14246 ['li', new Set(['li'])],
14247 ['dt', new Set(['dt', 'dd'])],
14248 ['dd', new Set(['dt', 'dd'])],
14249 [
14250 'p',
14251 new Set('address article aside blockquote div dl fieldset footer form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav ol p pre section table ul'.split(' '))
14252 ],
14253 ['rt', new Set(['rt', 'rp'])],
14254 ['rp', new Set(['rt', 'rp'])],
14255 ['optgroup', new Set(['optgroup'])],
14256 ['option', new Set(['option', 'optgroup'])],
14257 ['thead', new Set(['tbody', 'tfoot'])],
14258 ['tbody', new Set(['tbody', 'tfoot'])],
14259 ['tfoot', new Set(['tbody'])],
14260 ['tr', new Set(['tr', 'tbody'])],
14261 ['td', new Set(['td', 'th', 'tr'])],
14262 ['th', new Set(['td', 'th', 'tr'])]
14263]);
14264// can this be a child of the parent element, or does it implicitly
14265// close it, like `<li>one<li>two`?
14266function closing_tag_omitted(current, next) {
14267 if (disallowed_contents.has(current)) {
14268 if (!next || disallowed_contents.get(current).has(next)) {
14269 return true;
14270 }
14271 }
14272 return false;
14273}
14274
14275// Adapted from https://github.com/acornjs/acorn/blob/6584815dca7440e00de841d1dad152302fdd7ca5/src/tokenize.js
14276// Reproduced under MIT License https://github.com/acornjs/acorn/blob/master/LICENSE
14277function full_char_code_at(str, i) {
14278 const code = str.charCodeAt(i);
14279 if (code <= 0xd7ff || code >= 0xe000)
14280 return code;
14281 const next = str.charCodeAt(i + 1);
14282 return (code << 10) + next - 0x35fdc00;
14283}
14284
14285const globals = new Set([
14286 'alert',
14287 'Array',
14288 'Boolean',
14289 'clearInterval',
14290 'clearTimeout',
14291 'confirm',
14292 'console',
14293 'Date',
14294 'decodeURI',
14295 'decodeURIComponent',
14296 'document',
14297 'Element',
14298 'encodeURI',
14299 'encodeURIComponent',
14300 'Error',
14301 'EvalError',
14302 'Event',
14303 'EventSource',
14304 'fetch',
14305 'global',
14306 'globalThis',
14307 'history',
14308 'Infinity',
14309 'InternalError',
14310 'Intl',
14311 'isFinite',
14312 'isNaN',
14313 'JSON',
14314 'localStorage',
14315 'location',
14316 'Map',
14317 'Math',
14318 'NaN',
14319 'navigator',
14320 'Number',
14321 'Node',
14322 'Object',
14323 'parseFloat',
14324 'parseInt',
14325 'process',
14326 'Promise',
14327 'prompt',
14328 'RangeError',
14329 'ReferenceError',
14330 'RegExp',
14331 'sessionStorage',
14332 'Set',
14333 'setInterval',
14334 'setTimeout',
14335 'String',
14336 'SyntaxError',
14337 'TypeError',
14338 'undefined',
14339 'URIError',
14340 'URL',
14341 'window'
14342]);
14343const reserved = new Set([
14344 'arguments',
14345 'await',
14346 'break',
14347 'case',
14348 'catch',
14349 'class',
14350 'const',
14351 'continue',
14352 'debugger',
14353 'default',
14354 'delete',
14355 'do',
14356 'else',
14357 'enum',
14358 'eval',
14359 'export',
14360 'extends',
14361 'false',
14362 'finally',
14363 'for',
14364 'function',
14365 'if',
14366 'implements',
14367 'import',
14368 'in',
14369 'instanceof',
14370 'interface',
14371 'let',
14372 'new',
14373 'null',
14374 'package',
14375 'private',
14376 'protected',
14377 'public',
14378 'return',
14379 'static',
14380 'super',
14381 'switch',
14382 'this',
14383 'throw',
14384 'true',
14385 'try',
14386 'typeof',
14387 'var',
14388 'void',
14389 'while',
14390 'with',
14391 'yield'
14392]);
14393const void_element_names = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
14394function is_void(name) {
14395 return void_element_names.test(name) || name.toLowerCase() === '!doctype';
14396}
14397function is_valid(str) {
14398 let i = 0;
14399 while (i < str.length) {
14400 const code = full_char_code_at(str, i);
14401 if (!(i === 0 ? isIdentifierStart : isIdentifierChar)(code, true))
14402 return false;
14403 i += code <= 0xffff ? 1 : 2;
14404 }
14405 return true;
14406}
14407function sanitize(name) {
14408 return name
14409 .replace(/[^a-zA-Z0-9_]+/g, '_')
14410 .replace(/^_/, '')
14411 .replace(/_$/, '')
14412 .replace(/^[0-9]/, '_$&');
14413}
14414
14415function fuzzymatch(name, names) {
14416 const set = new FuzzySet(names);
14417 const matches = set.get(name);
14418 return matches && matches[0] && matches[0][0] > 0.7 ? matches[0][1] : null;
14419}
14420// adapted from https://github.com/Glench/fuzzyset.js/blob/master/lib/fuzzyset.js
14421// BSD Licensed
14422const GRAM_SIZE_LOWER = 2;
14423const GRAM_SIZE_UPPER = 3;
14424// return an edit distance from 0 to 1
14425function _distance(str1, str2) {
14426 if (str1 === null && str2 === null) {
14427 throw 'Trying to compare two null values';
14428 }
14429 if (str1 === null || str2 === null)
14430 return 0;
14431 str1 = String(str1);
14432 str2 = String(str2);
14433 const distance = levenshtein(str1, str2);
14434 if (str1.length > str2.length) {
14435 return 1 - distance / str1.length;
14436 }
14437 else {
14438 return 1 - distance / str2.length;
14439 }
14440}
14441// helper functions
14442function levenshtein(str1, str2) {
14443 const current = [];
14444 let prev;
14445 let value;
14446 for (let i = 0; i <= str2.length; i++) {
14447 for (let j = 0; j <= str1.length; j++) {
14448 if (i && j) {
14449 if (str1.charAt(j - 1) === str2.charAt(i - 1)) {
14450 value = prev;
14451 }
14452 else {
14453 value = Math.min(current[j], current[j - 1], prev) + 1;
14454 }
14455 }
14456 else {
14457 value = i + j;
14458 }
14459 prev = current[j];
14460 current[j] = value;
14461 }
14462 }
14463 return current.pop();
14464}
14465const non_word_regex = /[^\w, ]+/;
14466function iterate_grams(value, gram_size = 2) {
14467 const simplified = '-' + value.toLowerCase().replace(non_word_regex, '') + '-';
14468 const len_diff = gram_size - simplified.length;
14469 const results = [];
14470 if (len_diff > 0) {
14471 for (let i = 0; i < len_diff; ++i) {
14472 value += '-';
14473 }
14474 }
14475 for (let i = 0; i < simplified.length - gram_size + 1; ++i) {
14476 results.push(simplified.slice(i, i + gram_size));
14477 }
14478 return results;
14479}
14480function gram_counter(value, gram_size = 2) {
14481 // return an object where key=gram, value=number of occurrences
14482 const result = {};
14483 const grams = iterate_grams(value, gram_size);
14484 let i = 0;
14485 for (i; i < grams.length; ++i) {
14486 if (grams[i] in result) {
14487 result[grams[i]] += 1;
14488 }
14489 else {
14490 result[grams[i]] = 1;
14491 }
14492 }
14493 return result;
14494}
14495function sort_descending(a, b) {
14496 return b[0] - a[0];
14497}
14498class FuzzySet {
14499 constructor(arr) {
14500 this.exact_set = {};
14501 this.match_dict = {};
14502 this.items = {};
14503 // initialization
14504 for (let i = GRAM_SIZE_LOWER; i < GRAM_SIZE_UPPER + 1; ++i) {
14505 this.items[i] = [];
14506 }
14507 // add all the items to the set
14508 for (let i = 0; i < arr.length; ++i) {
14509 this.add(arr[i]);
14510 }
14511 }
14512 add(value) {
14513 const normalized_value = value.toLowerCase();
14514 if (normalized_value in this.exact_set) {
14515 return false;
14516 }
14517 let i = GRAM_SIZE_LOWER;
14518 for (i; i < GRAM_SIZE_UPPER + 1; ++i) {
14519 this._add(value, i);
14520 }
14521 }
14522 _add(value, gram_size) {
14523 const normalized_value = value.toLowerCase();
14524 const items = this.items[gram_size] || [];
14525 const index = items.length;
14526 items.push(0);
14527 const gram_counts = gram_counter(normalized_value, gram_size);
14528 let sum_of_square_gram_counts = 0;
14529 let gram;
14530 let gram_count;
14531 for (gram in gram_counts) {
14532 gram_count = gram_counts[gram];
14533 sum_of_square_gram_counts += Math.pow(gram_count, 2);
14534 if (gram in this.match_dict) {
14535 this.match_dict[gram].push([index, gram_count]);
14536 }
14537 else {
14538 this.match_dict[gram] = [[index, gram_count]];
14539 }
14540 }
14541 const vector_normal = Math.sqrt(sum_of_square_gram_counts);
14542 items[index] = [vector_normal, normalized_value];
14543 this.items[gram_size] = items;
14544 this.exact_set[normalized_value] = value;
14545 }
14546 get(value) {
14547 const normalized_value = value.toLowerCase();
14548 const result = this.exact_set[normalized_value];
14549 if (result) {
14550 return [[1, result]];
14551 }
14552 let results = [];
14553 // start with high gram size and if there are no results, go to lower gram sizes
14554 for (let gram_size = GRAM_SIZE_UPPER; gram_size >= GRAM_SIZE_LOWER; --gram_size) {
14555 results = this.__get(value, gram_size);
14556 if (results) {
14557 return results;
14558 }
14559 }
14560 return null;
14561 }
14562 __get(value, gram_size) {
14563 const normalized_value = value.toLowerCase();
14564 const matches = {};
14565 const gram_counts = gram_counter(normalized_value, gram_size);
14566 const items = this.items[gram_size];
14567 let sum_of_square_gram_counts = 0;
14568 let gram;
14569 let gram_count;
14570 let i;
14571 let index;
14572 let other_gram_count;
14573 for (gram in gram_counts) {
14574 gram_count = gram_counts[gram];
14575 sum_of_square_gram_counts += Math.pow(gram_count, 2);
14576 if (gram in this.match_dict) {
14577 for (i = 0; i < this.match_dict[gram].length; ++i) {
14578 index = this.match_dict[gram][i][0];
14579 other_gram_count = this.match_dict[gram][i][1];
14580 if (index in matches) {
14581 matches[index] += gram_count * other_gram_count;
14582 }
14583 else {
14584 matches[index] = gram_count * other_gram_count;
14585 }
14586 }
14587 }
14588 }
14589 const vector_normal = Math.sqrt(sum_of_square_gram_counts);
14590 let results = [];
14591 let match_score;
14592 // build a results list of [score, str]
14593 for (const match_index in matches) {
14594 match_score = matches[match_index];
14595 results.push([
14596 match_score / (vector_normal * items[match_index][0]),
14597 items[match_index][1]
14598 ]);
14599 }
14600 results.sort(sort_descending);
14601 let new_results = [];
14602 const end_index = Math.min(50, results.length);
14603 // truncate somewhat arbitrarily to 50
14604 for (let i = 0; i < end_index; ++i) {
14605 new_results.push([
14606 _distance(results[i][1], normalized_value),
14607 results[i][1]
14608 ]);
14609 }
14610 results = new_results;
14611 results.sort(sort_descending);
14612 new_results = [];
14613 for (let i = 0; i < results.length; ++i) {
14614 if (results[i][0] == results[0][0]) {
14615 new_results.push([results[i][0], this.exact_set[results[i][1]]]);
14616 }
14617 }
14618 return new_results;
14619 }
14620}
14621
14622function list$1(items, conjunction = 'or') {
14623 if (items.length === 1)
14624 return items[0];
14625 return `${items.slice(0, -1).join(', ')} ${conjunction} ${items[items.length - 1]}`;
14626}
14627
14628// eslint-disable-next-line no-useless-escape
14629const valid_tag_name = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
14630const meta_tags = new Map([
14631 ['svelte:head', 'Head'],
14632 ['svelte:options', 'Options'],
14633 ['svelte:window', 'Window'],
14634 ['svelte:body', 'Body']
14635]);
14636const valid_meta_tags = Array.from(meta_tags.keys()).concat('svelte:self', 'svelte:component');
14637const specials = new Map([
14638 [
14639 'script',
14640 {
14641 read: read_script,
14642 property: 'js'
14643 }
14644 ],
14645 [
14646 'style',
14647 {
14648 read: read_style,
14649 property: 'css'
14650 }
14651 ]
14652]);
14653const SELF = /^svelte:self(?=[\s/>])/;
14654const COMPONENT = /^svelte:component(?=[\s/>])/;
14655function parent_is_head(stack) {
14656 let i = stack.length;
14657 while (i--) {
14658 const { type } = stack[i];
14659 if (type === 'Head')
14660 return true;
14661 if (type === 'Element' || type === 'InlineComponent')
14662 return false;
14663 }
14664 return false;
14665}
14666function tag(parser) {
14667 const start = parser.index++;
14668 let parent = parser.current();
14669 if (parser.eat('!--')) {
14670 const data = parser.read_until(/-->/);
14671 parser.eat('-->', true, 'comment was left open, expected -->');
14672 parser.current().children.push({
14673 start,
14674 end: parser.index,
14675 type: 'Comment',
14676 data
14677 });
14678 return;
14679 }
14680 const is_closing_tag = parser.eat('/');
14681 const name = read_tag_name(parser);
14682 if (meta_tags.has(name)) {
14683 const slug = meta_tags.get(name).toLowerCase();
14684 if (is_closing_tag) {
14685 if ((name === 'svelte:window' || name === 'svelte:body') &&
14686 parser.current().children.length) {
14687 parser.error({
14688 code: `invalid-${slug}-content`,
14689 message: `<${name}> cannot have children`
14690 }, parser.current().children[0].start);
14691 }
14692 }
14693 else {
14694 if (name in parser.meta_tags) {
14695 parser.error({
14696 code: `duplicate-${slug}`,
14697 message: `A component can only have one <${name}> tag`
14698 }, start);
14699 }
14700 if (parser.stack.length > 1) {
14701 parser.error({
14702 code: `invalid-${slug}-placement`,
14703 message: `<${name}> tags cannot be inside elements or blocks`
14704 }, start);
14705 }
14706 parser.meta_tags[name] = true;
14707 }
14708 }
14709 const type = meta_tags.has(name)
14710 ? meta_tags.get(name)
14711 : (/[A-Z]/.test(name[0]) || name === 'svelte:self' || name === 'svelte:component') ? 'InlineComponent'
14712 : name === 'title' && parent_is_head(parser.stack) ? 'Title'
14713 : name === 'slot' && !parser.customElement ? 'Slot' : 'Element';
14714 const element = {
14715 start,
14716 end: null,
14717 type,
14718 name,
14719 attributes: [],
14720 children: []
14721 };
14722 parser.allow_whitespace();
14723 if (is_closing_tag) {
14724 if (is_void(name)) {
14725 parser.error({
14726 code: 'invalid-void-content',
14727 message: `<${name}> is a void element and cannot have children, or a closing tag`
14728 }, start);
14729 }
14730 parser.eat('>', true);
14731 // close any elements that don't have their own closing tags, e.g. <div><p></div>
14732 while (parent.name !== name) {
14733 if (parent.type !== 'Element') {
14734 const message = parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name
14735 ? `</${name}> attempted to close <${name}> that was already automatically closed by <${parser.last_auto_closed_tag.reason}>`
14736 : `</${name}> attempted to close an element that was not open`;
14737 parser.error({
14738 code: 'invalid-closing-tag',
14739 message
14740 }, start);
14741 }
14742 parent.end = start;
14743 parser.stack.pop();
14744 parent = parser.current();
14745 }
14746 parent.end = parser.index;
14747 parser.stack.pop();
14748 if (parser.last_auto_closed_tag && parser.stack.length < parser.last_auto_closed_tag.depth) {
14749 parser.last_auto_closed_tag = null;
14750 }
14751 return;
14752 }
14753 else if (closing_tag_omitted(parent.name, name)) {
14754 parent.end = start;
14755 parser.stack.pop();
14756 parser.last_auto_closed_tag = {
14757 tag: parent.name,
14758 reason: name,
14759 depth: parser.stack.length
14760 };
14761 }
14762 const unique_names = new Set();
14763 let attribute;
14764 while ((attribute = read_attribute(parser, unique_names))) {
14765 element.attributes.push(attribute);
14766 parser.allow_whitespace();
14767 }
14768 if (name === 'svelte:component') {
14769 const index = element.attributes.findIndex(attr => attr.type === 'Attribute' && attr.name === 'this');
14770 if (!~index) {
14771 parser.error({
14772 code: 'missing-component-definition',
14773 message: "<svelte:component> must have a 'this' attribute"
14774 }, start);
14775 }
14776 const definition = element.attributes.splice(index, 1)[0];
14777 if (definition.value === true || definition.value.length !== 1 || definition.value[0].type === 'Text') {
14778 parser.error({
14779 code: 'invalid-component-definition',
14780 message: 'invalid component definition'
14781 }, definition.start);
14782 }
14783 element.expression = definition.value[0].expression;
14784 }
14785 // special cases – top-level <script> and <style>
14786 if (specials.has(name) && parser.stack.length === 1) {
14787 const special = specials.get(name);
14788 parser.eat('>', true);
14789 const content = special.read(parser, start, element.attributes);
14790 if (content)
14791 parser[special.property].push(content);
14792 return;
14793 }
14794 parser.current().children.push(element);
14795 const self_closing = parser.eat('/') || is_void(name);
14796 parser.eat('>', true);
14797 if (self_closing) {
14798 // don't push self-closing elements onto the stack
14799 element.end = parser.index;
14800 }
14801 else if (name === 'textarea') {
14802 // special case
14803 element.children = read_sequence(parser, () => parser.template.slice(parser.index, parser.index + 11) === '</textarea>');
14804 parser.read(/<\/textarea>/);
14805 element.end = parser.index;
14806 }
14807 else if (name === 'script' || name === 'style') {
14808 // special case
14809 const start = parser.index;
14810 const data = parser.read_until(new RegExp(`</${name}>`));
14811 const end = parser.index;
14812 element.children.push({ start, end, type: 'Text', data });
14813 parser.eat(`</${name}>`, true);
14814 element.end = parser.index;
14815 }
14816 else {
14817 parser.stack.push(element);
14818 }
14819}
14820function read_tag_name(parser) {
14821 const start = parser.index;
14822 if (parser.read(SELF)) {
14823 // check we're inside a block, otherwise this
14824 // will cause infinite recursion
14825 let i = parser.stack.length;
14826 let legal = false;
14827 while (i--) {
14828 const fragment = parser.stack[i];
14829 if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock' || fragment.type === 'InlineComponent') {
14830 legal = true;
14831 break;
14832 }
14833 }
14834 if (!legal) {
14835 parser.error({
14836 code: 'invalid-self-placement',
14837 message: '<svelte:self> components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components'
14838 }, start);
14839 }
14840 return 'svelte:self';
14841 }
14842 if (parser.read(COMPONENT))
14843 return 'svelte:component';
14844 const name = parser.read_until(/(\s|\/|>)/);
14845 if (meta_tags.has(name))
14846 return name;
14847 if (name.startsWith('svelte:')) {
14848 const match = fuzzymatch(name.slice(7), valid_meta_tags);
14849 let message = `Valid <svelte:...> tag names are ${list$1(valid_meta_tags)}`;
14850 if (match)
14851 message += ` (did you mean '${match}'?)`;
14852 parser.error({
14853 code: 'invalid-tag-name',
14854 message
14855 }, start);
14856 }
14857 if (!valid_tag_name.test(name)) {
14858 parser.error({
14859 code: 'invalid-tag-name',
14860 message: 'Expected valid tag name'
14861 }, start);
14862 }
14863 return name;
14864}
14865function read_attribute(parser, unique_names) {
14866 const start = parser.index;
14867 function check_unique(name) {
14868 if (unique_names.has(name)) {
14869 parser.error({
14870 code: 'duplicate-attribute',
14871 message: 'Attributes need to be unique'
14872 }, start);
14873 }
14874 unique_names.add(name);
14875 }
14876 if (parser.eat('{')) {
14877 parser.allow_whitespace();
14878 if (parser.eat('...')) {
14879 const expression = read_expression(parser);
14880 parser.allow_whitespace();
14881 parser.eat('}', true);
14882 return {
14883 start,
14884 end: parser.index,
14885 type: 'Spread',
14886 expression
14887 };
14888 }
14889 else {
14890 const value_start = parser.index;
14891 const name = parser.read_identifier();
14892 parser.allow_whitespace();
14893 parser.eat('}', true);
14894 check_unique(name);
14895 return {
14896 start,
14897 end: parser.index,
14898 type: 'Attribute',
14899 name,
14900 value: [{
14901 start: value_start,
14902 end: value_start + name.length,
14903 type: 'AttributeShorthand',
14904 expression: {
14905 start: value_start,
14906 end: value_start + name.length,
14907 type: 'Identifier',
14908 name
14909 }
14910 }]
14911 };
14912 }
14913 }
14914 // eslint-disable-next-line no-useless-escape
14915 const name = parser.read_until(/[\s=\/>"']/);
14916 if (!name)
14917 return null;
14918 let end = parser.index;
14919 parser.allow_whitespace();
14920 const colon_index = name.indexOf(':');
14921 const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index));
14922 let value = true;
14923 if (parser.eat('=')) {
14924 parser.allow_whitespace();
14925 value = read_attribute_value(parser);
14926 end = parser.index;
14927 }
14928 else if (parser.match_regex(/["']/)) {
14929 parser.error({
14930 code: 'unexpected-token',
14931 message: 'Expected ='
14932 }, parser.index);
14933 }
14934 if (type) {
14935 const [directive_name, ...modifiers] = name.slice(colon_index + 1).split('|');
14936 if (type === 'Binding' && directive_name !== 'this') {
14937 check_unique(directive_name);
14938 }
14939 else if (type !== 'EventHandler') {
14940 check_unique(name);
14941 }
14942 if (type === 'Ref') {
14943 parser.error({
14944 code: 'invalid-ref-directive',
14945 message: `The ref directive is no longer supported — use \`bind:this={${directive_name}}\` instead`
14946 }, start);
14947 }
14948 if (value[0]) {
14949 if (value.length > 1 || value[0].type === 'Text') {
14950 parser.error({
14951 code: 'invalid-directive-value',
14952 message: 'Directive value must be a JavaScript expression enclosed in curly braces'
14953 }, value[0].start);
14954 }
14955 }
14956 const directive = {
14957 start,
14958 end,
14959 type,
14960 name: directive_name,
14961 modifiers,
14962 expression: (value[0] && value[0].expression) || null
14963 };
14964 if (type === 'Transition') {
14965 const direction = name.slice(0, colon_index);
14966 directive.intro = direction === 'in' || direction === 'transition';
14967 directive.outro = direction === 'out' || direction === 'transition';
14968 }
14969 if (!directive.expression && (type === 'Binding' || type === 'Class')) {
14970 directive.expression = {
14971 start: directive.start + colon_index + 1,
14972 end: directive.end,
14973 type: 'Identifier',
14974 name: directive.name
14975 };
14976 }
14977 return directive;
14978 }
14979 check_unique(name);
14980 return {
14981 start,
14982 end,
14983 type: 'Attribute',
14984 name,
14985 value
14986 };
14987}
14988function get_directive_type(name) {
14989 if (name === 'use')
14990 return 'Action';
14991 if (name === 'animate')
14992 return 'Animation';
14993 if (name === 'bind')
14994 return 'Binding';
14995 if (name === 'class')
14996 return 'Class';
14997 if (name === 'on')
14998 return 'EventHandler';
14999 if (name === 'let')
15000 return 'Let';
15001 if (name === 'ref')
15002 return 'Ref';
15003 if (name === 'in' || name === 'out' || name === 'transition')
15004 return 'Transition';
15005}
15006function read_attribute_value(parser) {
15007 const quote_mark = parser.eat("'") ? "'" : parser.eat('"') ? '"' : null;
15008 const regex = (quote_mark === "'" ? /'/ :
15009 quote_mark === '"' ? /"/ :
15010 /(\/>|[\s"'=<>`])/);
15011 const value = read_sequence(parser, () => !!parser.match_regex(regex));
15012 if (quote_mark)
15013 parser.index += 1;
15014 return value;
15015}
15016function read_sequence(parser, done) {
15017 let current_chunk = {
15018 start: parser.index,
15019 end: null,
15020 type: 'Text',
15021 raw: '',
15022 data: null
15023 };
15024 function flush() {
15025 if (current_chunk.raw) {
15026 current_chunk.data = decode_character_references(current_chunk.raw);
15027 current_chunk.end = parser.index;
15028 chunks.push(current_chunk);
15029 }
15030 }
15031 const chunks = [];
15032 while (parser.index < parser.template.length) {
15033 const index = parser.index;
15034 if (done()) {
15035 flush();
15036 return chunks;
15037 }
15038 else if (parser.eat('{')) {
15039 flush();
15040 parser.allow_whitespace();
15041 const expression = read_expression(parser);
15042 parser.allow_whitespace();
15043 parser.eat('}', true);
15044 chunks.push({
15045 start: index,
15046 end: parser.index,
15047 type: 'MustacheTag',
15048 expression
15049 });
15050 current_chunk = {
15051 start: parser.index,
15052 end: null,
15053 type: 'Text',
15054 raw: '',
15055 data: null
15056 };
15057 }
15058 else {
15059 current_chunk.raw += parser.template[parser.index++];
15060 }
15061 }
15062 parser.error({
15063 code: 'unexpected-eof',
15064 message: 'Unexpected end of input'
15065 });
15066}
15067
15068const SQUARE_BRACKET_OPEN = '['.charCodeAt(0);
15069const SQUARE_BRACKET_CLOSE = ']'.charCodeAt(0);
15070const CURLY_BRACKET_OPEN = '{'.charCodeAt(0);
15071const CURLY_BRACKET_CLOSE = '}'.charCodeAt(0);
15072function is_bracket_open(code) {
15073 return code === SQUARE_BRACKET_OPEN || code === CURLY_BRACKET_OPEN;
15074}
15075function is_bracket_close(code) {
15076 return code === SQUARE_BRACKET_CLOSE || code === CURLY_BRACKET_CLOSE;
15077}
15078function is_bracket_pair(open, close) {
15079 return ((open === SQUARE_BRACKET_OPEN && close === SQUARE_BRACKET_CLOSE) ||
15080 (open === CURLY_BRACKET_OPEN && close === CURLY_BRACKET_CLOSE));
15081}
15082function get_bracket_close(open) {
15083 if (open === SQUARE_BRACKET_OPEN) {
15084 return SQUARE_BRACKET_CLOSE;
15085 }
15086 if (open === CURLY_BRACKET_OPEN) {
15087 return CURLY_BRACKET_CLOSE;
15088 }
15089}
15090
15091function read_context(parser) {
15092 const start = parser.index;
15093 let i = parser.index;
15094 const code = full_char_code_at(parser.template, i);
15095 if (isIdentifierStart(code, true)) {
15096 return {
15097 type: 'Identifier',
15098 name: parser.read_identifier(),
15099 start,
15100 end: parser.index
15101 };
15102 }
15103 if (!is_bracket_open(code)) {
15104 parser.error({
15105 code: 'unexpected-token',
15106 message: 'Expected identifier or destructure pattern'
15107 });
15108 }
15109 const bracket_stack = [code];
15110 i += code <= 0xffff ? 1 : 2;
15111 while (i < parser.template.length) {
15112 const code = full_char_code_at(parser.template, i);
15113 if (is_bracket_open(code)) {
15114 bracket_stack.push(code);
15115 }
15116 else if (is_bracket_close(code)) {
15117 if (!is_bracket_pair(bracket_stack[bracket_stack.length - 1], code)) {
15118 parser.error({
15119 code: 'unexpected-token',
15120 message: `Expected ${String.fromCharCode(get_bracket_close(bracket_stack[bracket_stack.length - 1]))}`
15121 });
15122 }
15123 bracket_stack.pop();
15124 if (bracket_stack.length === 0) {
15125 i += code <= 0xffff ? 1 : 2;
15126 break;
15127 }
15128 }
15129 i += code <= 0xffff ? 1 : 2;
15130 }
15131 parser.index = i;
15132 const pattern_string = parser.template.slice(start, i);
15133 try {
15134 // the length of the `space_with_newline` has to be start - 1
15135 // because we added a `(` in front of the pattern_string,
15136 // which shifted the entire string to right by 1
15137 // so we offset it by removing 1 character in the `space_with_newline`
15138 // to achieve that, we remove the 1st space encountered,
15139 // so it will not affect the `column` of the node
15140 let space_with_newline = parser.template.slice(0, start).replace(/[^\n]/g, ' ');
15141 const first_space = space_with_newline.indexOf(' ');
15142 space_with_newline = space_with_newline.slice(0, first_space) + space_with_newline.slice(first_space + 1);
15143 return parse_expression_at(`${space_with_newline}(${pattern_string} = 1)`, start - 1).left;
15144 }
15145 catch (error) {
15146 parser.acorn_error(error);
15147 }
15148}
15149
15150function trim_start(str) {
15151 let i = 0;
15152 while (whitespace.test(str[i]))
15153 i += 1;
15154 return str.slice(i);
15155}
15156function trim_end(str) {
15157 let i = str.length;
15158 while (whitespace.test(str[i - 1]))
15159 i -= 1;
15160 return str.slice(0, i);
15161}
15162
15163function to_string(node) {
15164 switch (node.type) {
15165 case 'IfBlock':
15166 return '{#if} block';
15167 case 'ThenBlock':
15168 return '{:then} block';
15169 case 'ElseBlock':
15170 return '{:else} block';
15171 case 'PendingBlock':
15172 case 'AwaitBlock':
15173 return '{#await} block';
15174 case 'CatchBlock':
15175 return '{:catch} block';
15176 case 'EachBlock':
15177 return '{#each} block';
15178 case 'RawMustacheTag':
15179 return '{@html} block';
15180 case 'DebugTag':
15181 return '{@debug} block';
15182 case 'Element':
15183 case 'InlineComponent':
15184 case 'Slot':
15185 case 'Title':
15186 return `<${node.name}> tag`;
15187 default:
15188 return node.type;
15189 }
15190}
15191
15192function trim_whitespace(block, trim_before, trim_after) {
15193 if (!block.children || block.children.length === 0)
15194 return; // AwaitBlock
15195 const first_child = block.children[0];
15196 const last_child = block.children[block.children.length - 1];
15197 if (first_child.type === 'Text' && trim_before) {
15198 first_child.data = trim_start(first_child.data);
15199 if (!first_child.data)
15200 block.children.shift();
15201 }
15202 if (last_child.type === 'Text' && trim_after) {
15203 last_child.data = trim_end(last_child.data);
15204 if (!last_child.data)
15205 block.children.pop();
15206 }
15207 if (block.else) {
15208 trim_whitespace(block.else, trim_before, trim_after);
15209 }
15210 if (first_child.elseif) {
15211 trim_whitespace(first_child, trim_before, trim_after);
15212 }
15213}
15214function mustache(parser) {
15215 const start = parser.index;
15216 parser.index += 1;
15217 parser.allow_whitespace();
15218 // {/if}, {/each}, {/await} or {/key}
15219 if (parser.eat('/')) {
15220 let block = parser.current();
15221 let expected;
15222 if (closing_tag_omitted(block.name)) {
15223 block.end = start;
15224 parser.stack.pop();
15225 block = parser.current();
15226 }
15227 if (block.type === 'ElseBlock' || block.type === 'PendingBlock' || block.type === 'ThenBlock' || block.type === 'CatchBlock') {
15228 block.end = start;
15229 parser.stack.pop();
15230 block = parser.current();
15231 expected = 'await';
15232 }
15233 if (block.type === 'IfBlock') {
15234 expected = 'if';
15235 }
15236 else if (block.type === 'EachBlock') {
15237 expected = 'each';
15238 }
15239 else if (block.type === 'AwaitBlock') {
15240 expected = 'await';
15241 }
15242 else if (block.type === 'KeyBlock') {
15243 expected = 'key';
15244 }
15245 else {
15246 parser.error({
15247 code: 'unexpected-block-close',
15248 message: 'Unexpected block closing tag'
15249 });
15250 }
15251 parser.eat(expected, true);
15252 parser.allow_whitespace();
15253 parser.eat('}', true);
15254 while (block.elseif) {
15255 block.end = parser.index;
15256 parser.stack.pop();
15257 block = parser.current();
15258 if (block.else) {
15259 block.else.end = start;
15260 }
15261 }
15262 // strip leading/trailing whitespace as necessary
15263 const char_before = parser.template[block.start - 1];
15264 const char_after = parser.template[parser.index];
15265 const trim_before = !char_before || whitespace.test(char_before);
15266 const trim_after = !char_after || whitespace.test(char_after);
15267 trim_whitespace(block, trim_before, trim_after);
15268 block.end = parser.index;
15269 parser.stack.pop();
15270 }
15271 else if (parser.eat(':else')) {
15272 if (parser.eat('if')) {
15273 parser.error({
15274 code: 'invalid-elseif',
15275 message: "'elseif' should be 'else if'"
15276 });
15277 }
15278 parser.allow_whitespace();
15279 // :else if
15280 if (parser.eat('if')) {
15281 const block = parser.current();
15282 if (block.type !== 'IfBlock') {
15283 parser.error({
15284 code: 'invalid-elseif-placement',
15285 message: parser.stack.some(block => block.type === 'IfBlock')
15286 ? `Expected to close ${to_string(block)} before seeing {:else if ...} block`
15287 : 'Cannot have an {:else if ...} block outside an {#if ...} block'
15288 });
15289 }
15290 parser.require_whitespace();
15291 const expression = read_expression(parser);
15292 parser.allow_whitespace();
15293 parser.eat('}', true);
15294 block.else = {
15295 start: parser.index,
15296 end: null,
15297 type: 'ElseBlock',
15298 children: [
15299 {
15300 start: parser.index,
15301 end: null,
15302 type: 'IfBlock',
15303 elseif: true,
15304 expression,
15305 children: []
15306 }
15307 ]
15308 };
15309 parser.stack.push(block.else.children[0]);
15310 }
15311 else {
15312 // :else
15313 const block = parser.current();
15314 if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
15315 parser.error({
15316 code: 'invalid-else-placement',
15317 message: parser.stack.some(block => block.type === 'IfBlock' || block.type === 'EachBlock')
15318 ? `Expected to close ${to_string(block)} before seeing {:else} block`
15319 : 'Cannot have an {:else} block outside an {#if ...} or {#each ...} block'
15320 });
15321 }
15322 parser.allow_whitespace();
15323 parser.eat('}', true);
15324 block.else = {
15325 start: parser.index,
15326 end: null,
15327 type: 'ElseBlock',
15328 children: []
15329 };
15330 parser.stack.push(block.else);
15331 }
15332 }
15333 else if (parser.match(':then') || parser.match(':catch')) {
15334 const block = parser.current();
15335 const is_then = parser.eat(':then') || !parser.eat(':catch');
15336 if (is_then) {
15337 if (block.type !== 'PendingBlock') {
15338 parser.error({
15339 code: 'invalid-then-placement',
15340 message: parser.stack.some(block => block.type === 'PendingBlock')
15341 ? `Expected to close ${to_string(block)} before seeing {:then} block`
15342 : 'Cannot have an {:then} block outside an {#await ...} block'
15343 });
15344 }
15345 }
15346 else {
15347 if (block.type !== 'ThenBlock' && block.type !== 'PendingBlock') {
15348 parser.error({
15349 code: 'invalid-catch-placement',
15350 message: parser.stack.some(block => block.type === 'ThenBlock' || block.type === 'PendingBlock')
15351 ? `Expected to close ${to_string(block)} before seeing {:catch} block`
15352 : 'Cannot have an {:catch} block outside an {#await ...} block'
15353 });
15354 }
15355 }
15356 block.end = start;
15357 parser.stack.pop();
15358 const await_block = parser.current();
15359 if (!parser.eat('}')) {
15360 parser.require_whitespace();
15361 await_block[is_then ? 'value' : 'error'] = read_context(parser);
15362 parser.allow_whitespace();
15363 parser.eat('}', true);
15364 }
15365 const new_block = {
15366 start,
15367 end: null,
15368 type: is_then ? 'ThenBlock' : 'CatchBlock',
15369 children: [],
15370 skip: false
15371 };
15372 await_block[is_then ? 'then' : 'catch'] = new_block;
15373 parser.stack.push(new_block);
15374 }
15375 else if (parser.eat('#')) {
15376 // {#if foo}, {#each foo} or {#await foo}
15377 let type;
15378 if (parser.eat('if')) {
15379 type = 'IfBlock';
15380 }
15381 else if (parser.eat('each')) {
15382 type = 'EachBlock';
15383 }
15384 else if (parser.eat('await')) {
15385 type = 'AwaitBlock';
15386 }
15387 else if (parser.eat('key')) {
15388 type = 'KeyBlock';
15389 }
15390 else {
15391 parser.error({
15392 code: 'expected-block-type',
15393 message: 'Expected if, each, await or key'
15394 });
15395 }
15396 parser.require_whitespace();
15397 const expression = read_expression(parser);
15398 const block = type === 'AwaitBlock' ?
15399 {
15400 start,
15401 end: null,
15402 type,
15403 expression,
15404 value: null,
15405 error: null,
15406 pending: {
15407 start: null,
15408 end: null,
15409 type: 'PendingBlock',
15410 children: [],
15411 skip: true
15412 },
15413 then: {
15414 start: null,
15415 end: null,
15416 type: 'ThenBlock',
15417 children: [],
15418 skip: true
15419 },
15420 catch: {
15421 start: null,
15422 end: null,
15423 type: 'CatchBlock',
15424 children: [],
15425 skip: true
15426 }
15427 } :
15428 {
15429 start,
15430 end: null,
15431 type,
15432 expression,
15433 children: []
15434 };
15435 parser.allow_whitespace();
15436 // {#each} blocks must declare a context – {#each list as item}
15437 if (type === 'EachBlock') {
15438 parser.eat('as', true);
15439 parser.require_whitespace();
15440 block.context = read_context(parser);
15441 parser.allow_whitespace();
15442 if (parser.eat(',')) {
15443 parser.allow_whitespace();
15444 block.index = parser.read_identifier();
15445 if (!block.index) {
15446 parser.error({
15447 code: 'expected-name',
15448 message: 'Expected name'
15449 });
15450 }
15451 parser.allow_whitespace();
15452 }
15453 if (parser.eat('(')) {
15454 parser.allow_whitespace();
15455 block.key = read_expression(parser);
15456 parser.allow_whitespace();
15457 parser.eat(')', true);
15458 parser.allow_whitespace();
15459 }
15460 }
15461 const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then');
15462 if (await_block_shorthand) {
15463 parser.require_whitespace();
15464 block.value = read_context(parser);
15465 parser.allow_whitespace();
15466 }
15467 const await_block_catch_shorthand = !await_block_shorthand && type === 'AwaitBlock' && parser.eat('catch');
15468 if (await_block_catch_shorthand) {
15469 parser.require_whitespace();
15470 block.error = read_context(parser);
15471 parser.allow_whitespace();
15472 }
15473 parser.eat('}', true);
15474 parser.current().children.push(block);
15475 parser.stack.push(block);
15476 if (type === 'AwaitBlock') {
15477 let child_block;
15478 if (await_block_shorthand) {
15479 block.then.skip = false;
15480 child_block = block.then;
15481 }
15482 else if (await_block_catch_shorthand) {
15483 block.catch.skip = false;
15484 child_block = block.catch;
15485 }
15486 else {
15487 block.pending.skip = false;
15488 child_block = block.pending;
15489 }
15490 child_block.start = parser.index;
15491 parser.stack.push(child_block);
15492 }
15493 }
15494 else if (parser.eat('@html')) {
15495 // {@html content} tag
15496 parser.require_whitespace();
15497 const expression = read_expression(parser);
15498 parser.allow_whitespace();
15499 parser.eat('}', true);
15500 parser.current().children.push({
15501 start,
15502 end: parser.index,
15503 type: 'RawMustacheTag',
15504 expression
15505 });
15506 }
15507 else if (parser.eat('@debug')) {
15508 let identifiers;
15509 // Implies {@debug} which indicates "debug all"
15510 if (parser.read(/\s*}/)) {
15511 identifiers = [];
15512 }
15513 else {
15514 const expression = read_expression(parser);
15515 identifiers = expression.type === 'SequenceExpression'
15516 ? expression.expressions
15517 : [expression];
15518 identifiers.forEach(node => {
15519 if (node.type !== 'Identifier') {
15520 parser.error({
15521 code: 'invalid-debug-args',
15522 message: '{@debug ...} arguments must be identifiers, not arbitrary expressions'
15523 }, node.start);
15524 }
15525 });
15526 parser.allow_whitespace();
15527 parser.eat('}', true);
15528 }
15529 parser.current().children.push({
15530 start,
15531 end: parser.index,
15532 type: 'DebugTag',
15533 identifiers
15534 });
15535 }
15536 else {
15537 const expression = read_expression(parser);
15538 parser.allow_whitespace();
15539 parser.eat('}', true);
15540 parser.current().children.push({
15541 start,
15542 end: parser.index,
15543 type: 'MustacheTag',
15544 expression
15545 });
15546 }
15547}
15548
15549function text(parser) {
15550 const start = parser.index;
15551 let data = '';
15552 while (parser.index < parser.template.length &&
15553 !parser.match('<') &&
15554 !parser.match('{')) {
15555 data += parser.template[parser.index++];
15556 }
15557 const node = {
15558 start,
15559 end: parser.index,
15560 type: 'Text',
15561 raw: data,
15562 data: decode_character_references(data)
15563 };
15564 parser.current().children.push(node);
15565}
15566
15567function fragment(parser) {
15568 if (parser.match('<')) {
15569 return tag;
15570 }
15571 if (parser.match('{')) {
15572 return mustache;
15573 }
15574 return text;
15575}
15576
15577function getLocator(source, options) {
15578 if (options === void 0) { options = {}; }
15579 var offsetLine = options.offsetLine || 0;
15580 var offsetColumn = options.offsetColumn || 0;
15581 var originalLines = source.split('\n');
15582 var start = 0;
15583 var lineRanges = originalLines.map(function (line, i) {
15584 var end = start + line.length + 1;
15585 var range = { start: start, end: end, line: i };
15586 start = end;
15587 return range;
15588 });
15589 var i = 0;
15590 function rangeContains(range, index) {
15591 return range.start <= index && index < range.end;
15592 }
15593 function getLocation(range, index) {
15594 return { line: offsetLine + range.line, column: offsetColumn + index - range.start, character: index };
15595 }
15596 function locate(search, startIndex) {
15597 if (typeof search === 'string') {
15598 search = source.indexOf(search, startIndex || 0);
15599 }
15600 var range = lineRanges[i];
15601 var d = search >= range.end ? 1 : -1;
15602 while (range) {
15603 if (rangeContains(range, search))
15604 return getLocation(range, search);
15605 i += d;
15606 range = lineRanges[i];
15607 }
15608 }
15609 return locate;
15610}
15611function locate(source, search, options) {
15612 if (typeof options === 'number') {
15613 throw new Error('locate takes a { startIndex, offsetLine, offsetColumn } object as the third argument');
15614 }
15615 return getLocator(source, options)(search, options && options.startIndex);
15616}
15617
15618function tabs_to_spaces(str) {
15619 return str.replace(/^\t+/, match => match.split('\t').join(' '));
15620}
15621function get_code_frame(source, line, column) {
15622 const lines = source.split('\n');
15623 const frame_start = Math.max(0, line - 2);
15624 const frame_end = Math.min(line + 3, lines.length);
15625 const digits = String(frame_end + 1).length;
15626 return lines
15627 .slice(frame_start, frame_end)
15628 .map((str, i) => {
15629 const isErrorLine = frame_start + i === line;
15630 const line_num = String(i + frame_start + 1).padStart(digits, ' ');
15631 if (isErrorLine) {
15632 const indicator = ' '.repeat(digits + 2 + tabs_to_spaces(str.slice(0, column)).length) + '^';
15633 return `${line_num}: ${tabs_to_spaces(str)}\n${indicator}`;
15634 }
15635 return `${line_num}: ${tabs_to_spaces(str)}`;
15636 })
15637 .join('\n');
15638}
15639
15640class CompileError extends Error {
15641 toString() {
15642 return `${this.message} (${this.start.line}:${this.start.column})\n${this.frame}`;
15643 }
15644}
15645function error$1(message, props) {
15646 const error = new CompileError(message);
15647 error.name = props.name;
15648 const start = locate(props.source, props.start, { offsetLine: 1 });
15649 const end = locate(props.source, props.end || props.start, { offsetLine: 1 });
15650 error.code = props.code;
15651 error.start = start;
15652 error.end = end;
15653 error.pos = props.start;
15654 error.filename = props.filename;
15655 error.frame = get_code_frame(props.source, start.line - 1, start.column);
15656 throw error;
15657}
15658
15659class Parser$1 {
15660 constructor(template, options) {
15661 this.index = 0;
15662 this.stack = [];
15663 this.css = [];
15664 this.js = [];
15665 this.meta_tags = {};
15666 if (typeof template !== 'string') {
15667 throw new TypeError('Template must be a string');
15668 }
15669 this.template = template.replace(/\s+$/, '');
15670 this.filename = options.filename;
15671 this.customElement = options.customElement;
15672 this.html = {
15673 start: null,
15674 end: null,
15675 type: 'Fragment',
15676 children: []
15677 };
15678 this.stack.push(this.html);
15679 let state = fragment;
15680 while (this.index < this.template.length) {
15681 state = state(this) || fragment;
15682 }
15683 if (this.stack.length > 1) {
15684 const current = this.current();
15685 const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
15686 const slug = current.type === 'Element' ? 'element' : 'block';
15687 this.error({
15688 code: `unclosed-${slug}`,
15689 message: `${type} was left open`
15690 }, current.start);
15691 }
15692 if (state !== fragment) {
15693 this.error({
15694 code: 'unexpected-eof',
15695 message: 'Unexpected end of input'
15696 });
15697 }
15698 if (this.html.children.length) {
15699 let start = this.html.children[0].start;
15700 while (whitespace.test(template[start]))
15701 start += 1;
15702 let end = this.html.children[this.html.children.length - 1].end;
15703 while (whitespace.test(template[end - 1]))
15704 end -= 1;
15705 this.html.start = start;
15706 this.html.end = end;
15707 }
15708 else {
15709 this.html.start = this.html.end = null;
15710 }
15711 }
15712 current() {
15713 return this.stack[this.stack.length - 1];
15714 }
15715 acorn_error(err) {
15716 this.error({
15717 code: 'parse-error',
15718 message: err.message.replace(/ \(\d+:\d+\)$/, '')
15719 }, err.pos);
15720 }
15721 error({ code, message }, index = this.index) {
15722 error$1(message, {
15723 name: 'ParseError',
15724 code,
15725 source: this.template,
15726 start: index,
15727 filename: this.filename
15728 });
15729 }
15730 eat(str, required, message) {
15731 if (this.match(str)) {
15732 this.index += str.length;
15733 return true;
15734 }
15735 if (required) {
15736 this.error({
15737 code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`,
15738 message: message || `Expected ${str}`
15739 });
15740 }
15741 return false;
15742 }
15743 match(str) {
15744 return this.template.slice(this.index, this.index + str.length) === str;
15745 }
15746 match_regex(pattern) {
15747 const match = pattern.exec(this.template.slice(this.index));
15748 if (!match || match.index !== 0)
15749 return null;
15750 return match[0];
15751 }
15752 allow_whitespace() {
15753 while (this.index < this.template.length &&
15754 whitespace.test(this.template[this.index])) {
15755 this.index++;
15756 }
15757 }
15758 read(pattern) {
15759 const result = this.match_regex(pattern);
15760 if (result)
15761 this.index += result.length;
15762 return result;
15763 }
15764 read_identifier(allow_reserved = false) {
15765 const start = this.index;
15766 let i = this.index;
15767 const code = full_char_code_at(this.template, i);
15768 if (!isIdentifierStart(code, true))
15769 return null;
15770 i += code <= 0xffff ? 1 : 2;
15771 while (i < this.template.length) {
15772 const code = full_char_code_at(this.template, i);
15773 if (!isIdentifierChar(code, true))
15774 break;
15775 i += code <= 0xffff ? 1 : 2;
15776 }
15777 const identifier = this.template.slice(this.index, this.index = i);
15778 if (!allow_reserved && reserved.has(identifier)) {
15779 this.error({
15780 code: 'unexpected-reserved-word',
15781 message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`
15782 }, start);
15783 }
15784 return identifier;
15785 }
15786 read_until(pattern) {
15787 if (this.index >= this.template.length) {
15788 this.error({
15789 code: 'unexpected-eof',
15790 message: 'Unexpected end of input'
15791 });
15792 }
15793 const start = this.index;
15794 const match = pattern.exec(this.template.slice(start));
15795 if (match) {
15796 this.index = start + match.index;
15797 return this.template.slice(start, this.index);
15798 }
15799 this.index = this.template.length;
15800 return this.template.slice(start);
15801 }
15802 require_whitespace() {
15803 if (!whitespace.test(this.template[this.index])) {
15804 this.error({
15805 code: 'missing-whitespace',
15806 message: 'Expected whitespace'
15807 });
15808 }
15809 this.allow_whitespace();
15810 }
15811}
15812function parse$3(template, options = {}) {
15813 const parser = new Parser$1(template, options);
15814 // TODO we may want to allow multiple <style> tags —
15815 // one scoped, one global. for now, only allow one
15816 if (parser.css.length > 1) {
15817 parser.error({
15818 code: 'duplicate-style',
15819 message: 'You can only have one top-level <style> tag per component'
15820 }, parser.css[1].start);
15821 }
15822 const instance_scripts = parser.js.filter(script => script.context === 'default');
15823 const module_scripts = parser.js.filter(script => script.context === 'module');
15824 if (instance_scripts.length > 1) {
15825 parser.error({
15826 code: 'invalid-script',
15827 message: 'A component can only have one instance-level <script> element'
15828 }, instance_scripts[1].start);
15829 }
15830 if (module_scripts.length > 1) {
15831 parser.error({
15832 code: 'invalid-script',
15833 message: 'A component can only have one <script context="module"> element'
15834 }, module_scripts[1].start);
15835 }
15836 return {
15837 html: parser.html,
15838 css: parser.css[0],
15839 instance: instance_scripts[0],
15840 module: module_scripts[0]
15841 };
15842}
15843
15844function is_head(node) {
15845 return node && node.type === 'MemberExpression' && node.object.name === '@_document' && node.property.name === 'head';
15846}
15847
15848class Block$1 {
15849 constructor(options) {
15850 this.dependencies = new Set();
15851 this.event_listeners = [];
15852 this.variables = new Map();
15853 this.has_update_method = false;
15854 this.parent = options.parent;
15855 this.renderer = options.renderer;
15856 this.name = options.name;
15857 this.type = options.type;
15858 this.comment = options.comment;
15859 this.wrappers = [];
15860 // for keyed each blocks
15861 this.key = options.key;
15862 this.first = null;
15863 this.bindings = options.bindings;
15864 this.chunks = {
15865 declarations: [],
15866 init: [],
15867 create: [],
15868 claim: [],
15869 hydrate: [],
15870 mount: [],
15871 measure: [],
15872 fix: [],
15873 animate: [],
15874 intro: [],
15875 update: [],
15876 outro: [],
15877 destroy: []
15878 };
15879 this.has_animation = false;
15880 this.has_intro_method = false; // a block could have an intro method but not intro transitions, e.g. if a sibling block has intros
15881 this.has_outro_method = false;
15882 this.outros = 0;
15883 this.get_unique_name = this.renderer.component.get_unique_name_maker();
15884 this.aliases = new Map();
15885 if (this.key)
15886 this.aliases.set('key', this.get_unique_name('key'));
15887 }
15888 assign_variable_names() {
15889 const seen = new Set();
15890 const dupes = new Set();
15891 let i = this.wrappers.length;
15892 while (i--) {
15893 const wrapper = this.wrappers[i];
15894 if (!wrapper.var)
15895 continue;
15896 if (seen.has(wrapper.var.name)) {
15897 dupes.add(wrapper.var.name);
15898 }
15899 seen.add(wrapper.var.name);
15900 }
15901 const counts = new Map();
15902 i = this.wrappers.length;
15903 while (i--) {
15904 const wrapper = this.wrappers[i];
15905 if (!wrapper.var)
15906 continue;
15907 let suffix = '';
15908 if (dupes.has(wrapper.var.name)) {
15909 const i = counts.get(wrapper.var.name) || 0;
15910 counts.set(wrapper.var.name, i + 1);
15911 suffix = i;
15912 }
15913 wrapper.var.name = this.get_unique_name(wrapper.var.name + suffix).name;
15914 }
15915 }
15916 add_dependencies(dependencies) {
15917 dependencies.forEach(dependency => {
15918 this.dependencies.add(dependency);
15919 });
15920 this.has_update_method = true;
15921 if (this.parent) {
15922 this.parent.add_dependencies(dependencies);
15923 }
15924 }
15925 add_element(id, render_statement, claim_statement, parent_node, no_detach) {
15926 this.add_variable(id);
15927 this.chunks.create.push(b `${id} = ${render_statement};`);
15928 if (this.renderer.options.hydratable) {
15929 this.chunks.claim.push(b `${id} = ${claim_statement || render_statement};`);
15930 }
15931 if (parent_node) {
15932 this.chunks.mount.push(b `@append(${parent_node}, ${id});`);
15933 if (is_head(parent_node) && !no_detach)
15934 this.chunks.destroy.push(b `@detach(${id});`);
15935 }
15936 else {
15937 this.chunks.mount.push(b `@insert(#target, ${id}, #anchor);`);
15938 if (!no_detach)
15939 this.chunks.destroy.push(b `if (detaching) @detach(${id});`);
15940 }
15941 }
15942 add_intro(local) {
15943 this.has_intros = this.has_intro_method = true;
15944 if (!local && this.parent)
15945 this.parent.add_intro();
15946 }
15947 add_outro(local) {
15948 this.has_outros = this.has_outro_method = true;
15949 this.outros += 1;
15950 if (!local && this.parent)
15951 this.parent.add_outro();
15952 }
15953 add_animation() {
15954 this.has_animation = true;
15955 }
15956 add_variable(id, init) {
15957 if (this.variables.has(id.name)) {
15958 throw new Error(`Variable '${id.name}' already initialised with a different value`);
15959 }
15960 this.variables.set(id.name, { id, init });
15961 }
15962 alias(name) {
15963 if (!this.aliases.has(name)) {
15964 this.aliases.set(name, this.get_unique_name(name));
15965 }
15966 return this.aliases.get(name);
15967 }
15968 child(options) {
15969 return new Block$1(Object.assign({}, this, { key: null }, options, { parent: this }));
15970 }
15971 get_contents(key) {
15972 const { dev } = this.renderer.options;
15973 if (this.has_outros) {
15974 this.add_variable({ type: 'Identifier', name: '#current' });
15975 if (this.chunks.intro.length > 0) {
15976 this.chunks.intro.push(b `#current = true;`);
15977 this.chunks.mount.push(b `#current = true;`);
15978 }
15979 if (this.chunks.outro.length > 0) {
15980 this.chunks.outro.push(b `#current = false;`);
15981 }
15982 }
15983 if (this.autofocus) {
15984 this.chunks.mount.push(b `${this.autofocus}.focus();`);
15985 }
15986 this.render_listeners();
15987 const properties = {};
15988 const noop = x `@noop`;
15989 properties.key = key;
15990 if (this.first) {
15991 properties.first = x `null`;
15992 this.chunks.hydrate.push(b `this.first = ${this.first};`);
15993 }
15994 if (this.chunks.create.length === 0 && this.chunks.hydrate.length === 0) {
15995 properties.create = noop;
15996 }
15997 else {
15998 const hydrate = this.chunks.hydrate.length > 0 && (this.renderer.options.hydratable
15999 ? b `this.h();`
16000 : this.chunks.hydrate);
16001 properties.create = x `function #create() {
16002 ${this.chunks.create}
16003 ${hydrate}
16004 }`;
16005 }
16006 if (this.renderer.options.hydratable || this.chunks.claim.length > 0) {
16007 if (this.chunks.claim.length === 0 && this.chunks.hydrate.length === 0) {
16008 properties.claim = noop;
16009 }
16010 else {
16011 properties.claim = x `function #claim(#nodes) {
16012 ${this.chunks.claim}
16013 ${this.renderer.options.hydratable && this.chunks.hydrate.length > 0 && b `this.h();`}
16014 }`;
16015 }
16016 }
16017 if (this.renderer.options.hydratable && this.chunks.hydrate.length > 0) {
16018 properties.hydrate = x `function #hydrate() {
16019 ${this.chunks.hydrate}
16020 }`;
16021 }
16022 if (this.chunks.mount.length === 0) {
16023 properties.mount = noop;
16024 }
16025 else if (this.event_listeners.length === 0) {
16026 properties.mount = x `function #mount(#target, #anchor) {
16027 ${this.chunks.mount}
16028 }`;
16029 }
16030 else {
16031 properties.mount = x `function #mount(#target, #anchor) {
16032 ${this.chunks.mount}
16033 }`;
16034 }
16035 if (this.has_update_method || this.maintain_context) {
16036 if (this.chunks.update.length === 0 && !this.maintain_context) {
16037 properties.update = noop;
16038 }
16039 else {
16040 const ctx = this.maintain_context ? x `#new_ctx` : x `#ctx`;
16041 let dirty = { type: 'Identifier', name: '#dirty' };
16042 if (!this.renderer.context_overflow && !this.parent) {
16043 dirty = { type: 'ArrayPattern', elements: [dirty] };
16044 }
16045 properties.update = x `function #update(${ctx}, ${dirty}) {
16046 ${this.maintain_context && b `#ctx = ${ctx};`}
16047 ${this.chunks.update}
16048 }`;
16049 }
16050 }
16051 if (this.has_animation) {
16052 properties.measure = x `function #measure() {
16053 ${this.chunks.measure}
16054 }`;
16055 properties.fix = x `function #fix() {
16056 ${this.chunks.fix}
16057 }`;
16058 properties.animate = x `function #animate() {
16059 ${this.chunks.animate}
16060 }`;
16061 }
16062 if (this.has_intro_method || this.has_outro_method) {
16063 if (this.chunks.intro.length === 0) {
16064 properties.intro = noop;
16065 }
16066 else {
16067 properties.intro = x `function #intro(#local) {
16068 ${this.has_outros && b `if (#current) return;`}
16069 ${this.chunks.intro}
16070 }`;
16071 }
16072 if (this.chunks.outro.length === 0) {
16073 properties.outro = noop;
16074 }
16075 else {
16076 properties.outro = x `function #outro(#local) {
16077 ${this.chunks.outro}
16078 }`;
16079 }
16080 }
16081 if (this.chunks.destroy.length === 0) {
16082 properties.destroy = noop;
16083 }
16084 else {
16085 properties.destroy = x `function #destroy(detaching) {
16086 ${this.chunks.destroy}
16087 }`;
16088 }
16089 if (!this.renderer.component.compile_options.dev) {
16090 // allow shorthand names
16091 for (const name in properties) {
16092 const property = properties[name];
16093 if (property)
16094 property.id = null;
16095 }
16096 }
16097 const return_value = x `{
16098 key: ${properties.key},
16099 first: ${properties.first},
16100 c: ${properties.create},
16101 l: ${properties.claim},
16102 h: ${properties.hydrate},
16103 m: ${properties.mount},
16104 p: ${properties.update},
16105 r: ${properties.measure},
16106 f: ${properties.fix},
16107 a: ${properties.animate},
16108 i: ${properties.intro},
16109 o: ${properties.outro},
16110 d: ${properties.destroy}
16111 }`;
16112 const block = dev && this.get_unique_name('block');
16113 const body = b `
16114 ${this.chunks.declarations}
16115
16116 ${Array.from(this.variables.values()).map(({ id, init }) => {
16117 return init
16118 ? b `let ${id} = ${init}`
16119 : b `let ${id}`;
16120 })}
16121
16122 ${this.chunks.init}
16123
16124 ${dev
16125 ? b `
16126 const ${block} = ${return_value};
16127 @dispatch_dev("SvelteRegisterBlock", {
16128 block: ${block},
16129 id: ${this.name || 'create_fragment'}.name,
16130 type: "${this.type}",
16131 source: "${this.comment ? this.comment.replace(/"/g, '\\"') : ''}",
16132 ctx: #ctx
16133 });
16134 return ${block};`
16135 : b `
16136 return ${return_value};`}
16137 `;
16138 return body;
16139 }
16140 has_content() {
16141 return !!this.first ||
16142 this.event_listeners.length > 0 ||
16143 this.chunks.intro.length > 0 ||
16144 this.chunks.outro.length > 0 ||
16145 this.chunks.create.length > 0 ||
16146 this.chunks.hydrate.length > 0 ||
16147 this.chunks.claim.length > 0 ||
16148 this.chunks.mount.length > 0 ||
16149 this.chunks.update.length > 0 ||
16150 this.chunks.destroy.length > 0 ||
16151 this.has_animation;
16152 }
16153 render() {
16154 const key = this.key && this.get_unique_name('key');
16155 const args = [x `#ctx`];
16156 if (key)
16157 args.unshift(key);
16158 const fn = b `function ${this.name}(${args}) {
16159 ${this.get_contents(key)}
16160 }`;
16161 return this.comment
16162 ? b `
16163 // ${this.comment}
16164 ${fn}`
16165 : fn;
16166 }
16167 render_listeners(chunk = '') {
16168 if (this.event_listeners.length > 0) {
16169 this.add_variable({ type: 'Identifier', name: '#mounted' });
16170 this.chunks.destroy.push(b `#mounted = false`);
16171 const dispose = {
16172 type: 'Identifier',
16173 name: `#dispose${chunk}`
16174 };
16175 this.add_variable(dispose);
16176 if (this.event_listeners.length === 1) {
16177 this.chunks.mount.push(b `
16178 if (!#mounted) {
16179 ${dispose} = ${this.event_listeners[0]};
16180 #mounted = true;
16181 }
16182 `);
16183 this.chunks.destroy.push(b `${dispose}();`);
16184 }
16185 else {
16186 this.chunks.mount.push(b `
16187 if (!#mounted) {
16188 ${dispose} = [
16189 ${this.event_listeners}
16190 ];
16191 #mounted = true;
16192 }
16193 `);
16194 this.chunks.destroy.push(b `@run_all(${dispose});`);
16195 }
16196 }
16197 }
16198}
16199
16200class Wrapper {
16201 constructor(renderer, block, parent, node) {
16202 this.node = node;
16203 // make these non-enumerable so that they can be logged sensibly
16204 // (TODO in dev only?)
16205 Object.defineProperties(this, {
16206 renderer: {
16207 value: renderer
16208 },
16209 parent: {
16210 value: parent
16211 }
16212 });
16213 this.can_use_innerhtml = !renderer.options.hydratable;
16214 this.is_static_content = !renderer.options.hydratable;
16215 block.wrappers.push(this);
16216 }
16217 cannot_use_innerhtml() {
16218 this.can_use_innerhtml = false;
16219 if (this.parent)
16220 this.parent.cannot_use_innerhtml();
16221 }
16222 not_static_content() {
16223 this.is_static_content = false;
16224 if (this.parent)
16225 this.parent.not_static_content();
16226 }
16227 get_or_create_anchor(block, parent_node, parent_nodes) {
16228 // TODO use this in EachBlock and IfBlock — tricky because
16229 // children need to be created first
16230 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
16231 const anchor = needs_anchor
16232 ? block.get_unique_name(`${this.var.name}_anchor`)
16233 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16234 if (needs_anchor) {
16235 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16236 }
16237 return anchor;
16238 }
16239 get_update_mount_node(anchor) {
16240 return ((this.parent && this.parent.is_dom_node())
16241 ? this.parent.var
16242 : x `${anchor}.parentNode`);
16243 }
16244 is_dom_node() {
16245 return (this.node.type === 'Element' ||
16246 this.node.type === 'Text' ||
16247 this.node.type === 'MustacheTag');
16248 }
16249 render(_block, _parent_node, _parent_nodes) {
16250 throw Error('Wrapper class is not renderable');
16251 }
16252}
16253
16254function create_debugging_comment(node, component) {
16255 const { locate, source } = component;
16256 let c = node.start;
16257 if (node.type === 'ElseBlock') {
16258 while (source[c - 1] !== '{')
16259 c -= 1;
16260 while (source[c - 1] === '{')
16261 c -= 1;
16262 }
16263 let d;
16264 if (node.type === 'InlineComponent' || node.type === 'Element') {
16265 if (node.children.length) {
16266 d = node.children[0].start;
16267 while (source[d - 1] !== '>')
16268 d -= 1;
16269 }
16270 else {
16271 d = node.start;
16272 while (source[d] !== '>')
16273 d += 1;
16274 d += 1;
16275 }
16276 }
16277 else if (node.type === 'Text' || node.type === 'Comment') {
16278 d = node.end;
16279 }
16280 else {
16281 // @ts-ignore
16282 d = node.expression ? node.expression.node.end : c;
16283 while (source[d] !== '}' && d <= source.length)
16284 d += 1;
16285 while (source[d] === '}')
16286 d += 1;
16287 }
16288 const start = locate(c);
16289 const loc = `(${start.line}:${start.column})`;
16290 return `${loc} ${source.slice(c, d)}`.replace(/\s/g, ' ');
16291}
16292
16293class AwaitBlockBranch extends Wrapper {
16294 constructor(status, renderer, block, parent, node, strip_whitespace, next_sibling) {
16295 super(renderer, block, parent, node);
16296 this.var = null;
16297 this.status = status;
16298 this.block = block.child({
16299 comment: create_debugging_comment(node, this.renderer.component),
16300 name: this.renderer.component.get_unique_name(`create_${status}_block`),
16301 type: status
16302 });
16303 this.add_context(parent.node[status + '_node'], parent.node[status + '_contexts']);
16304 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16305 this.is_dynamic = this.block.dependencies.size > 0;
16306 }
16307 add_context(node, contexts) {
16308 if (!node)
16309 return;
16310 if (node.type === 'Identifier') {
16311 this.value = node.name;
16312 this.renderer.add_to_context(this.value, true);
16313 }
16314 else {
16315 contexts.forEach(context => {
16316 this.renderer.add_to_context(context.key.name, true);
16317 });
16318 this.value = this.block.parent.get_unique_name('value').name;
16319 this.value_contexts = contexts;
16320 this.renderer.add_to_context(this.value, true);
16321 this.is_destructured = true;
16322 }
16323 this.value_index = this.renderer.context_lookup.get(this.value).index;
16324 }
16325 render(block, parent_node, parent_nodes) {
16326 this.fragment.render(block, parent_node, parent_nodes);
16327 if (this.is_destructured) {
16328 this.render_destructure();
16329 }
16330 }
16331 render_destructure() {
16332 const props = this.value_contexts.map(prop => b `#ctx[${this.block.renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x `#ctx[${this.value_index}]`)};`);
16333 const get_context = this.block.renderer.component.get_unique_name(`get_${this.status}_context`);
16334 this.block.renderer.blocks.push(b `
16335 function ${get_context}(#ctx) {
16336 ${props}
16337 }
16338 `);
16339 this.block.chunks.declarations.push(b `${get_context}(#ctx)`);
16340 if (this.block.has_update_method) {
16341 this.block.chunks.update.unshift(b `${get_context}(#ctx)`);
16342 }
16343 }
16344}
16345class AwaitBlockWrapper extends Wrapper {
16346 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16347 super(renderer, block, parent, node);
16348 this.var = { type: 'Identifier', name: 'await_block' };
16349 this.cannot_use_innerhtml();
16350 this.not_static_content();
16351 block.add_dependencies(this.node.expression.dependencies);
16352 let is_dynamic = false;
16353 let has_intros = false;
16354 let has_outros = false;
16355 ['pending', 'then', 'catch'].forEach((status) => {
16356 const child = this.node[status];
16357 const branch = new AwaitBlockBranch(status, renderer, block, this, child, strip_whitespace, next_sibling);
16358 renderer.blocks.push(branch.block);
16359 if (branch.is_dynamic) {
16360 is_dynamic = true;
16361 // TODO should blocks update their own parents?
16362 block.add_dependencies(branch.block.dependencies);
16363 }
16364 if (branch.block.has_intros)
16365 has_intros = true;
16366 if (branch.block.has_outros)
16367 has_outros = true;
16368 this[status] = branch;
16369 });
16370 ['pending', 'then', 'catch'].forEach(status => {
16371 this[status].block.has_update_method = is_dynamic;
16372 this[status].block.has_intro_method = has_intros;
16373 this[status].block.has_outro_method = has_outros;
16374 });
16375 if (has_outros) {
16376 block.add_outro();
16377 }
16378 }
16379 render(block, parent_node, parent_nodes) {
16380 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
16381 const update_mount_node = this.get_update_mount_node(anchor);
16382 const snippet = this.node.expression.manipulate(block);
16383 const info = block.get_unique_name('info');
16384 const promise = block.get_unique_name('promise');
16385 block.add_variable(promise);
16386 block.maintain_context = true;
16387 const info_props = x `{
16388 ctx: #ctx,
16389 current: null,
16390 token: null,
16391 hasCatch: ${this.catch.node.start !== null ? 'true' : 'false'},
16392 pending: ${this.pending.block.name},
16393 then: ${this.then.block.name},
16394 catch: ${this.catch.block.name},
16395 value: ${this.then.value_index},
16396 error: ${this.catch.value_index},
16397 blocks: ${this.pending.block.has_outro_method && x `[,,,]`}
16398 }`;
16399 block.chunks.init.push(b `
16400 let ${info} = ${info_props};
16401 `);
16402 block.chunks.init.push(b `
16403 @handle_promise(${promise} = ${snippet}, ${info});
16404 `);
16405 block.chunks.create.push(b `
16406 ${info}.block.c();
16407 `);
16408 if (parent_nodes && this.renderer.options.hydratable) {
16409 block.chunks.claim.push(b `
16410 ${info}.block.l(${parent_nodes});
16411 `);
16412 }
16413 const initial_mount_node = parent_node || '#target';
16414 const anchor_node = parent_node ? 'null' : '#anchor';
16415 const has_transitions = this.pending.block.has_intro_method || this.pending.block.has_outro_method;
16416 block.chunks.mount.push(b `
16417 ${info}.block.m(${initial_mount_node}, ${info}.anchor = ${anchor_node});
16418 ${info}.mount = () => ${update_mount_node};
16419 ${info}.anchor = ${anchor};
16420 `);
16421 if (has_transitions) {
16422 block.chunks.intro.push(b `@transition_in(${info}.block);`);
16423 }
16424 const dependencies = this.node.expression.dynamic_dependencies();
16425 let update_child_context;
16426 if (this.then.value && this.catch.value) {
16427 update_child_context = b `#child_ctx[${this.then.value_index}] = #child_ctx[${this.catch.value_index}] = ${info}.resolved;`;
16428 }
16429 else if (this.then.value) {
16430 update_child_context = b `#child_ctx[${this.then.value_index}] = ${info}.resolved;`;
16431 }
16432 else if (this.catch.value) {
16433 update_child_context = b `#child_ctx[${this.catch.value_index}] = ${info}.resolved;`;
16434 }
16435 if (dependencies.length > 0) {
16436 const condition = x `
16437 ${block.renderer.dirty(dependencies)} &&
16438 ${promise} !== (${promise} = ${snippet}) &&
16439 @handle_promise(${promise}, ${info})`;
16440 block.chunks.update.push(b `${info}.ctx = #ctx;`);
16441 if (this.pending.block.has_update_method) {
16442 block.chunks.update.push(b `
16443 if (${condition}) {
16444
16445 } else {
16446 const #child_ctx = #ctx.slice();
16447 ${update_child_context}
16448 ${info}.block.p(#child_ctx, #dirty);
16449 }
16450 `);
16451 }
16452 else {
16453 block.chunks.update.push(b `
16454 ${condition}
16455 `);
16456 }
16457 }
16458 else {
16459 if (this.pending.block.has_update_method) {
16460 block.chunks.update.push(b `
16461 {
16462 const #child_ctx = #ctx.slice();
16463 ${update_child_context}
16464 ${info}.block.p(#child_ctx, #dirty);
16465 }
16466 `);
16467 }
16468 }
16469 if (this.pending.block.has_outro_method) {
16470 block.chunks.outro.push(b `
16471 for (let #i = 0; #i < 3; #i += 1) {
16472 const block = ${info}.blocks[#i];
16473 @transition_out(block);
16474 }
16475 `);
16476 }
16477 block.chunks.destroy.push(b `
16478 ${info}.block.d(${parent_node ? null : 'detaching'});
16479 ${info}.token = null;
16480 ${info} = null;
16481 `);
16482 [this.pending, this.then, this.catch].forEach(branch => {
16483 branch.render(branch.block, null, x `#nodes`);
16484 });
16485 }
16486}
16487
16488const TRUE = x `true`;
16489const FALSE = x `false`;
16490class EventHandlerWrapper {
16491 constructor(node, parent) {
16492 this.node = node;
16493 this.parent = parent;
16494 if (!node.expression) {
16495 this.parent.renderer.add_to_context(node.handler_name.name);
16496 this.parent.renderer.component.partly_hoisted.push(b `
16497 function ${node.handler_name.name}(event) {
16498 @bubble($$self, event);
16499 }
16500 `);
16501 }
16502 }
16503 get_snippet(block) {
16504 const snippet = this.node.expression ? this.node.expression.manipulate(block) : block.renderer.reference(this.node.handler_name);
16505 if (this.node.reassigned) {
16506 block.maintain_context = true;
16507 return x `function () { if (@is_function(${snippet})) ${snippet}.apply(this, arguments); }`;
16508 }
16509 return snippet;
16510 }
16511 render(block, target) {
16512 let snippet = this.get_snippet(block);
16513 if (this.node.modifiers.has('preventDefault'))
16514 snippet = x `@prevent_default(${snippet})`;
16515 if (this.node.modifiers.has('stopPropagation'))
16516 snippet = x `@stop_propagation(${snippet})`;
16517 if (this.node.modifiers.has('self'))
16518 snippet = x `@self(${snippet})`;
16519 const args = [];
16520 const opts = ['nonpassive', 'passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod));
16521 if (opts.length) {
16522 if (opts.length === 1 && opts[0] === 'capture') {
16523 args.push(TRUE);
16524 }
16525 else {
16526 args.push(x `{ ${opts.map(opt => opt === 'nonpassive'
16527 ? p `passive: false`
16528 : p `${opt}: true`)} }`);
16529 }
16530 }
16531 else if (block.renderer.options.dev) {
16532 args.push(FALSE);
16533 }
16534 if (block.renderer.options.dev) {
16535 args.push(this.node.modifiers.has('preventDefault') ? TRUE : FALSE);
16536 args.push(this.node.modifiers.has('stopPropagation') ? TRUE : FALSE);
16537 }
16538 block.event_listeners.push(x `@listen(${target}, "${this.node.name}", ${snippet}, ${args})`);
16539 }
16540}
16541
16542function add_event_handlers(block, target, handlers) {
16543 handlers.forEach(handler => add_event_handler(block, target, handler));
16544}
16545function add_event_handler(block, target, handler) {
16546 handler.render(block, target);
16547}
16548
16549class BodyWrapper extends Wrapper {
16550 constructor(renderer, block, parent, node) {
16551 super(renderer, block, parent, node);
16552 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
16553 }
16554 render(block, _parent_node, _parent_nodes) {
16555 add_event_handlers(block, x `@_document.body`, this.handlers);
16556 }
16557}
16558
16559function add_to_set(a, b) {
16560 // @ts-ignore
16561 b.forEach(item => {
16562 a.add(item);
16563 });
16564}
16565
16566class DebugTagWrapper extends Wrapper {
16567 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
16568 super(renderer, block, parent, node);
16569 }
16570 render(block, _parent_node, _parent_nodes) {
16571 const { renderer } = this;
16572 const { component } = renderer;
16573 if (!renderer.options.dev)
16574 return;
16575 const { var_lookup } = component;
16576 const start = component.locate(this.node.start + 1);
16577 const end = { line: start.line, column: start.column + 6 };
16578 const loc = { start, end };
16579 const debug = {
16580 type: 'DebuggerStatement',
16581 loc
16582 };
16583 if (this.node.expressions.length === 0) {
16584 // Debug all
16585 block.chunks.create.push(debug);
16586 block.chunks.update.push(debug);
16587 }
16588 else {
16589 const log = {
16590 type: 'Identifier',
16591 name: 'log',
16592 loc
16593 };
16594 const dependencies = new Set();
16595 this.node.expressions.forEach(expression => {
16596 add_to_set(dependencies, expression.dependencies);
16597 });
16598 const contextual_identifiers = this.node.expressions
16599 .filter(e => {
16600 const variable = var_lookup.get(e.node.name);
16601 return !(variable && variable.hoistable);
16602 })
16603 .map(e => e.node.name);
16604 const logged_identifiers = this.node.expressions.map(e => p `${e.node.name}`);
16605 const debug_statements = b `
16606 ${contextual_identifiers.map(name => b `const ${name} = ${renderer.reference(name)};`)}
16607 @_console.${log}({ ${logged_identifiers} });
16608 debugger;`;
16609 if (dependencies.size) {
16610 const condition = renderer.dirty(Array.from(dependencies));
16611 block.chunks.update.push(b `
16612 if (${condition}) {
16613 ${debug_statements}
16614 }
16615 `);
16616 }
16617 block.chunks.create.push(b `{
16618 ${debug_statements}
16619 }`);
16620 }
16621 }
16622}
16623
16624function get_object(node) {
16625 while (node.type === 'MemberExpression')
16626 node = node.object;
16627 return node;
16628}
16629
16630class ElseBlockWrapper extends Wrapper {
16631 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16632 super(renderer, block, parent, node);
16633 this.var = null;
16634 this.block = block.child({
16635 comment: create_debugging_comment(node, this.renderer.component),
16636 name: this.renderer.component.get_unique_name('create_else_block'),
16637 type: 'else'
16638 });
16639 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16640 this.is_dynamic = this.block.dependencies.size > 0;
16641 }
16642}
16643class EachBlockWrapper extends Wrapper {
16644 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16645 super(renderer, block, parent, node);
16646 this.updates = [];
16647 this.var = { type: 'Identifier', name: 'each' };
16648 this.cannot_use_innerhtml();
16649 this.not_static_content();
16650 const { dependencies } = node.expression;
16651 block.add_dependencies(dependencies);
16652 this.node.contexts.forEach(context => {
16653 renderer.add_to_context(context.key.name, true);
16654 });
16655 this.block = block.child({
16656 comment: create_debugging_comment(this.node, this.renderer.component),
16657 name: renderer.component.get_unique_name('create_each_block'),
16658 type: 'each',
16659 // @ts-ignore todo: probably error
16660 key: node.key,
16661 bindings: new Map(block.bindings)
16662 });
16663 // TODO this seems messy
16664 this.block.has_animation = this.node.has_animation;
16665 this.index_name = this.node.index
16666 ? { type: 'Identifier', name: this.node.index }
16667 : renderer.component.get_unique_name(`${this.node.context}_index`);
16668 const fixed_length = node.expression.node.type === 'ArrayExpression' &&
16669 node.expression.node.elements.every(element => element.type !== 'SpreadElement')
16670 ? node.expression.node.elements.length
16671 : null;
16672 // hack the sourcemap, so that if data is missing the bug
16673 // is easy to find
16674 let c = this.node.start + 2;
16675 while (renderer.component.source[c] !== 'e')
16676 c += 1;
16677 const start = renderer.component.locate(c);
16678 const end = { line: start.line, column: start.column + 4 };
16679 const length = {
16680 type: 'Identifier',
16681 name: 'length',
16682 loc: { start, end }
16683 };
16684 const each_block_value = renderer.component.get_unique_name(`${this.var.name}_value`);
16685 const iterations = block.get_unique_name(`${this.var.name}_blocks`);
16686 renderer.add_to_context(each_block_value.name, true);
16687 renderer.add_to_context(this.index_name.name, true);
16688 this.vars = {
16689 create_each_block: this.block.name,
16690 each_block_value,
16691 get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`),
16692 iterations,
16693 // optimisation for array literal
16694 fixed_length,
16695 data_length: fixed_length === null ? x `${each_block_value}.${length}` : fixed_length,
16696 view_length: fixed_length === null ? x `${iterations}.length` : fixed_length
16697 };
16698 const object = get_object(node.expression.node);
16699 const store = object.type === 'Identifier' && object.name[0] === '$' ? object.name.slice(1) : null;
16700 node.contexts.forEach(prop => {
16701 this.block.bindings.set(prop.key.name, {
16702 object: this.vars.each_block_value,
16703 property: this.index_name,
16704 modifier: prop.modifier,
16705 snippet: prop.modifier(x `${this.vars.each_block_value}[${this.index_name}]`),
16706 store,
16707 tail: prop.modifier(x `[${this.index_name}]`)
16708 });
16709 });
16710 if (this.node.index) {
16711 this.block.get_unique_name(this.node.index); // this prevents name collisions (#1254)
16712 }
16713 renderer.blocks.push(this.block);
16714 this.fragment = new FragmentWrapper(renderer, this.block, node.children, this, strip_whitespace, next_sibling);
16715 if (this.node.else) {
16716 this.else = new ElseBlockWrapper(renderer, block, this, this.node.else, strip_whitespace, next_sibling);
16717 renderer.blocks.push(this.else.block);
16718 if (this.else.is_dynamic) {
16719 this.block.add_dependencies(this.else.block.dependencies);
16720 }
16721 }
16722 block.add_dependencies(this.block.dependencies);
16723 if (this.block.has_outros || (this.else && this.else.block.has_outros)) {
16724 block.add_outro();
16725 }
16726 }
16727 render(block, parent_node, parent_nodes) {
16728 if (this.fragment.nodes.length === 0)
16729 return;
16730 const { renderer } = this;
16731 const { component } = renderer;
16732 const needs_anchor = this.next
16733 ? !this.next.is_dom_node() :
16734 !parent_node || !this.parent.is_dom_node();
16735 const snippet = this.node.expression.manipulate(block);
16736 block.chunks.init.push(b `let ${this.vars.each_block_value} = ${snippet};`);
16737 if (this.renderer.options.dev) {
16738 block.chunks.init.push(b `@validate_each_argument(${this.vars.each_block_value});`);
16739 }
16740 const initial_anchor_node = { type: 'Identifier', name: parent_node ? 'null' : '#anchor' };
16741 const initial_mount_node = parent_node || { type: 'Identifier', name: '#target' };
16742 const update_anchor_node = needs_anchor
16743 ? block.get_unique_name(`${this.var.name}_anchor`)
16744 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16745 const update_mount_node = this.get_update_mount_node(update_anchor_node);
16746 const args = {
16747 block,
16748 parent_node,
16749 parent_nodes,
16750 snippet,
16751 initial_anchor_node,
16752 initial_mount_node,
16753 update_anchor_node,
16754 update_mount_node
16755 };
16756 const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
16757 this.node.expression.dynamic_dependencies().forEach((dependency) => {
16758 all_dependencies.add(dependency);
16759 });
16760 if (this.node.key) {
16761 this.node.key.dynamic_dependencies().forEach((dependency) => {
16762 all_dependencies.add(dependency);
16763 });
16764 }
16765 this.dependencies = all_dependencies;
16766 if (this.node.key) {
16767 this.render_keyed(args);
16768 }
16769 else {
16770 this.render_unkeyed(args);
16771 }
16772 if (this.block.has_intro_method || this.block.has_outro_method) {
16773 block.chunks.intro.push(b `
16774 for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) {
16775 @transition_in(${this.vars.iterations}[#i]);
16776 }
16777 `);
16778 }
16779 if (needs_anchor) {
16780 block.add_element(update_anchor_node, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16781 }
16782 if (this.else) {
16783 const each_block_else = component.get_unique_name(`${this.var.name}_else`);
16784 block.chunks.init.push(b `let ${each_block_else} = null;`);
16785 // TODO neaten this up... will end up with an empty line in the block
16786 block.chunks.init.push(b `
16787 if (!${this.vars.data_length}) {
16788 ${each_block_else} = ${this.else.block.name}(#ctx);
16789 }
16790 `);
16791 block.chunks.create.push(b `
16792 if (${each_block_else}) {
16793 ${each_block_else}.c();
16794 }
16795 `);
16796 if (this.renderer.options.hydratable) {
16797 block.chunks.claim.push(b `
16798 if (${each_block_else}) {
16799 ${each_block_else}.l(${parent_nodes});
16800 }
16801 `);
16802 }
16803 block.chunks.mount.push(b `
16804 if (${each_block_else}) {
16805 ${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node});
16806 }
16807 `);
16808 const has_transitions = !!(this.else.block.has_intro_method || this.else.block.has_outro_method);
16809 const destroy_block_else = this.else.block.has_outro_method
16810 ? b `
16811 @group_outros();
16812 @transition_out(${each_block_else}, 1, 1, () => {
16813 ${each_block_else} = null;
16814 });
16815 @check_outros();`
16816 : b `
16817 ${each_block_else}.d(1);
16818 ${each_block_else} = null;`;
16819 if (this.else.block.has_update_method) {
16820 this.updates.push(b `
16821 if (!${this.vars.data_length} && ${each_block_else}) {
16822 ${each_block_else}.p(#ctx, #dirty);
16823 } else if (!${this.vars.data_length}) {
16824 ${each_block_else} = ${this.else.block.name}(#ctx);
16825 ${each_block_else}.c();
16826 ${has_transitions && b `@transition_in(${each_block_else}, 1);`}
16827 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16828 } else if (${each_block_else}) {
16829 ${destroy_block_else};
16830 }
16831 `);
16832 }
16833 else {
16834 this.updates.push(b `
16835 if (${this.vars.data_length}) {
16836 if (${each_block_else}) {
16837 ${destroy_block_else};
16838 }
16839 } else if (!${each_block_else}) {
16840 ${each_block_else} = ${this.else.block.name}(#ctx);
16841 ${each_block_else}.c();
16842 ${has_transitions && b `@transition_in(${each_block_else}, 1);`}
16843 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16844 }
16845 `);
16846 }
16847 block.chunks.destroy.push(b `
16848 if (${each_block_else}) ${each_block_else}.d(${parent_node ? '' : 'detaching'});
16849 `);
16850 }
16851 if (this.updates.length) {
16852 block.chunks.update.push(b `
16853 if (${block.renderer.dirty(Array.from(all_dependencies))}) {
16854 ${this.updates}
16855 }
16856 `);
16857 }
16858 this.fragment.render(this.block, null, x `#nodes`);
16859 if (this.else) {
16860 this.else.fragment.render(this.else.block, null, x `#nodes`);
16861 }
16862 this.context_props = this.node.contexts.map(prop => b `child_ctx[${renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x `list[i]`)};`);
16863 if (this.node.has_binding)
16864 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`);
16865 if (this.node.has_binding || this.node.has_index_binding || this.node.index)
16866 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`);
16867 // TODO which is better — Object.create(array) or array.slice()?
16868 renderer.blocks.push(b `
16869 function ${this.vars.get_each_context}(#ctx, list, i) {
16870 const child_ctx = #ctx.slice();
16871 ${this.context_props}
16872 return child_ctx;
16873 }
16874 `);
16875 }
16876 render_keyed({ block, parent_node, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
16877 const { create_each_block, iterations, data_length, view_length } = this.vars;
16878 const get_key = block.get_unique_name('get_key');
16879 const lookup = block.get_unique_name(`${this.var.name}_lookup`);
16880 block.add_variable(iterations, x `[]`);
16881 block.add_variable(lookup, x `new @_Map()`);
16882 if (this.fragment.nodes[0].is_dom_node()) {
16883 this.block.first = this.fragment.nodes[0].var;
16884 }
16885 else {
16886 this.block.first = this.block.get_unique_name('first');
16887 this.block.add_element(this.block.first, x `@empty()`, parent_nodes && x `@empty()`, null);
16888 }
16889 block.chunks.init.push(b `
16890 const ${get_key} = #ctx => ${this.node.key.manipulate(block)};
16891
16892 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
16893 for (let #i = 0; #i < ${data_length}; #i += 1) {
16894 let child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
16895 let key = ${get_key}(child_ctx);
16896 ${lookup}.set(key, ${iterations}[#i] = ${create_each_block}(key, child_ctx));
16897 }
16898 `);
16899 block.chunks.create.push(b `
16900 for (let #i = 0; #i < ${view_length}; #i += 1) {
16901 ${iterations}[#i].c();
16902 }
16903 `);
16904 if (parent_nodes && this.renderer.options.hydratable) {
16905 block.chunks.claim.push(b `
16906 for (let #i = 0; #i < ${view_length}; #i += 1) {
16907 ${iterations}[#i].l(${parent_nodes});
16908 }
16909 `);
16910 }
16911 block.chunks.mount.push(b `
16912 for (let #i = 0; #i < ${view_length}; #i += 1) {
16913 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
16914 }
16915 `);
16916 const dynamic = this.block.has_update_method;
16917 const destroy = this.node.has_animation
16918 ? (this.block.has_outros
16919 ? '@fix_and_outro_and_destroy_block'
16920 : '@fix_and_destroy_block')
16921 : this.block.has_outros
16922 ? '@outro_and_destroy_block'
16923 : '@destroy_block';
16924 if (this.dependencies.size) {
16925 this.updates.push(b `
16926 const ${this.vars.each_block_value} = ${snippet};
16927 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
16928
16929 ${this.block.has_outros && b `@group_outros();`}
16930 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`}
16931 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
16932 ${iterations} = @update_keyed_each(${iterations}, #dirty, ${get_key}, ${dynamic ? 1 : 0}, #ctx, ${this.vars.each_block_value}, ${lookup}, ${update_mount_node}, ${destroy}, ${create_each_block}, ${update_anchor_node}, ${this.vars.get_each_context});
16933 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
16934 ${this.block.has_outros && b `@check_outros();`}
16935 `);
16936 }
16937 if (this.block.has_outros) {
16938 block.chunks.outro.push(b `
16939 for (let #i = 0; #i < ${view_length}; #i += 1) {
16940 @transition_out(${iterations}[#i]);
16941 }
16942 `);
16943 }
16944 block.chunks.destroy.push(b `
16945 for (let #i = 0; #i < ${view_length}; #i += 1) {
16946 ${iterations}[#i].d(${parent_node ? null : 'detaching'});
16947 }
16948 `);
16949 }
16950 render_unkeyed({ block, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
16951 const { create_each_block, iterations, fixed_length, data_length, view_length } = this.vars;
16952 block.chunks.init.push(b `
16953 let ${iterations} = [];
16954
16955 for (let #i = 0; #i < ${data_length}; #i += 1) {
16956 ${iterations}[#i] = ${create_each_block}(${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i));
16957 }
16958 `);
16959 block.chunks.create.push(b `
16960 for (let #i = 0; #i < ${view_length}; #i += 1) {
16961 ${iterations}[#i].c();
16962 }
16963 `);
16964 if (parent_nodes && this.renderer.options.hydratable) {
16965 block.chunks.claim.push(b `
16966 for (let #i = 0; #i < ${view_length}; #i += 1) {
16967 ${iterations}[#i].l(${parent_nodes});
16968 }
16969 `);
16970 }
16971 block.chunks.mount.push(b `
16972 for (let #i = 0; #i < ${view_length}; #i += 1) {
16973 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
16974 }
16975 `);
16976 if (this.dependencies.size) {
16977 const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
16978 const for_loop_body = this.block.has_update_method
16979 ? b `
16980 if (${iterations}[#i]) {
16981 ${iterations}[#i].p(child_ctx, #dirty);
16982 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
16983 } else {
16984 ${iterations}[#i] = ${create_each_block}(child_ctx);
16985 ${iterations}[#i].c();
16986 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
16987 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16988 }
16989 `
16990 : has_transitions
16991 ? b `
16992 if (${iterations}[#i]) {
16993 @transition_in(${this.vars.iterations}[#i], 1);
16994 } else {
16995 ${iterations}[#i] = ${create_each_block}(child_ctx);
16996 ${iterations}[#i].c();
16997 @transition_in(${this.vars.iterations}[#i], 1);
16998 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16999 }
17000 `
17001 : b `
17002 if (!${iterations}[#i]) {
17003 ${iterations}[#i] = ${create_each_block}(child_ctx);
17004 ${iterations}[#i].c();
17005 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
17006 }
17007 `;
17008 const start = this.block.has_update_method ? 0 : '#old_length';
17009 let remove_old_blocks;
17010 if (this.block.has_outros) {
17011 const out = block.get_unique_name('out');
17012 block.chunks.init.push(b `
17013 const ${out} = i => @transition_out(${iterations}[i], 1, 1, () => {
17014 ${iterations}[i] = null;
17015 });
17016 `);
17017 remove_old_blocks = b `
17018 @group_outros();
17019 for (#i = ${data_length}; #i < ${view_length}; #i += 1) {
17020 ${out}(#i);
17021 }
17022 @check_outros();
17023 `;
17024 }
17025 else {
17026 remove_old_blocks = b `
17027 for (${this.block.has_update_method ? null : x `#i = ${data_length}`}; #i < ${this.block.has_update_method ? view_length : '#old_length'}; #i += 1) {
17028 ${iterations}[#i].d(1);
17029 }
17030 ${!fixed_length && b `${view_length} = ${data_length};`}
17031 `;
17032 }
17033 // We declare `i` as block scoped here, as the `remove_old_blocks` code
17034 // may rely on continuing where this iteration stopped.
17035 const update = b `
17036 ${!this.block.has_update_method && b `const #old_length = ${this.vars.each_block_value}.length;`}
17037 ${this.vars.each_block_value} = ${snippet};
17038 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
17039
17040 let #i;
17041 for (#i = ${start}; #i < ${data_length}; #i += 1) {
17042 const child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
17043
17044 ${for_loop_body}
17045 }
17046
17047 ${remove_old_blocks}
17048 `;
17049 this.updates.push(update);
17050 }
17051 if (this.block.has_outros) {
17052 block.chunks.outro.push(b `
17053 ${iterations} = ${iterations}.filter(@_Boolean);
17054 for (let #i = 0; #i < ${view_length}; #i += 1) {
17055 @transition_out(${iterations}[#i]);
17056 }
17057 `);
17058 }
17059 block.chunks.destroy.push(b `@destroy_each(${iterations}, detaching);`);
17060 }
17061}
17062
17063function string_literal(data) {
17064 return {
17065 type: 'Literal',
17066 value: data
17067 };
17068}
17069const escaped = {
17070 '"': '&quot;',
17071 "'": '&#39;',
17072 '&': '&amp;',
17073 '<': '&lt;',
17074 '>': '&gt;'
17075};
17076function escape_html(html) {
17077 return String(html).replace(/["'&<>]/g, match => escaped[match]);
17078}
17079function escape_template(str) {
17080 return str.replace(/(\${|`|\\)/g, '\\$1');
17081}
17082
17083class TextWrapper extends Wrapper {
17084 constructor(renderer, block, parent, node, data) {
17085 super(renderer, block, parent, node);
17086 this.skip = this.node.should_skip();
17087 this.data = data;
17088 this.var = (this.skip ? null : x `t`);
17089 }
17090 use_space() {
17091 if (this.renderer.component.component_options.preserveWhitespace)
17092 return false;
17093 if (/[\S\u00A0]/.test(this.data))
17094 return false;
17095 let node = this.parent && this.parent.node;
17096 while (node) {
17097 if (node.type === 'Element' && node.name === 'pre') {
17098 return false;
17099 }
17100 node = node.parent;
17101 }
17102 return true;
17103 }
17104 render(block, parent_node, parent_nodes) {
17105 if (this.skip)
17106 return;
17107 const use_space = this.use_space();
17108 block.add_element(this.var, use_space ? x `@space()` : x `@text("${this.data}")`, parent_nodes && (use_space ? x `@claim_space(${parent_nodes})` : x `@claim_text(${parent_nodes}, "${this.data}")`), parent_node);
17109 }
17110}
17111
17112const svg_attributes = 'accent-height accumulate additive alignment-baseline allowReorder alphabetic amplitude arabic-form ascent attributeName attributeType autoReverse azimuth baseFrequency baseline-shift baseProfile bbox begin bias by calcMode cap-height class clip clipPathUnits clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor cx cy d decelerate descent diffuseConstant direction display divisor dominant-baseline dur dx dy edgeMode elevation enable-background end exponent externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format from fr fx fy g1 g2 glyph-name glyph-orientation-horizontal glyph-orientation-vertical glyphRef gradientTransform gradientUnits hanging height href horiz-adv-x horiz-origin-x id ideographic image-rendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength kerning keyPoints keySplines keyTimes lang lengthAdjust letter-spacing lighting-color limitingConeAngle local marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask maskContentUnits maskUnits mathematical max media method min mode name numOctaves offset onabort onactivate onbegin onclick onend onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onrepeat onresize onscroll onunload opacity operator order orient orientation origin overflow overline-position overline-thickness panose-1 paint-order pathLength patternContentUnits patternTransform patternUnits pointer-events points pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits r radius refX refY rendering-intent repeatCount repeatDur requiredExtensions requiredFeatures restart result rotate rx ry scale seed shape-rendering slope spacing specularConstant specularExponent speed spreadMethod startOffset stdDeviation stemh stemv stitchTiles stop-color stop-opacity strikethrough-position strikethrough-thickness string stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale systemLanguage tabindex tableValues target targetX targetY text-anchor text-decoration text-rendering textLength to transform type u1 u2 underline-position underline-thickness unicode unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical values version vert-adv-y vert-origin-x vert-origin-y viewBox viewTarget visibility width widths word-spacing writing-mode x x-height x1 x2 xChannelSelector xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y y1 y2 yChannelSelector z zoomAndPan'.split(' ');
17113const svg_attribute_lookup = new Map();
17114svg_attributes.forEach(name => {
17115 svg_attribute_lookup.set(name.toLowerCase(), name);
17116});
17117function fix_attribute_casing(name) {
17118 name = name.toLowerCase();
17119 return svg_attribute_lookup.get(name) || name;
17120}
17121
17122const html = 'http://www.w3.org/1999/xhtml';
17123const mathml = 'http://www.w3.org/1998/Math/MathML';
17124const svg = 'http://www.w3.org/2000/svg';
17125const xlink = 'http://www.w3.org/1999/xlink';
17126const xml = 'http://www.w3.org/XML/1998/namespace';
17127const xmlns = 'http://www.w3.org/2000/xmlns';
17128const valid_namespaces = [
17129 'html',
17130 'mathml',
17131 'svg',
17132 'xlink',
17133 'xml',
17134 'xmlns',
17135 html,
17136 mathml,
17137 svg,
17138 xlink,
17139 xml,
17140 xmlns
17141];
17142const namespaces = { html, mathml, svg, xlink, xml, xmlns };
17143
17144function handle_select_value_binding(attr, dependencies) {
17145 const { parent } = attr;
17146 if (parent.node.name === 'select') {
17147 parent.select_binding_dependencies = dependencies;
17148 dependencies.forEach((prop) => {
17149 parent.renderer.component.indirect_dependencies.set(prop, new Set());
17150 });
17151 }
17152}
17153
17154class BaseAttributeWrapper {
17155 constructor(parent, block, node) {
17156 this.node = node;
17157 this.parent = parent;
17158 if (node.dependencies.size > 0) {
17159 parent.cannot_use_innerhtml();
17160 parent.not_static_content();
17161 block.add_dependencies(node.dependencies);
17162 }
17163 }
17164 render(_block) { }
17165}
17166class AttributeWrapper extends BaseAttributeWrapper {
17167 constructor(parent, block, node) {
17168 super(parent, block, node);
17169 if (node.dependencies.size > 0) {
17170 // special case — <option value={foo}> — see below
17171 if (this.parent.node.name === 'option' && node.name === 'value') {
17172 let select = this.parent;
17173 while (select && (select.node.type !== 'Element' || select.node.name !== 'select')) {
17174 // @ts-ignore todo: doublecheck this, but looks to be correct
17175 select = select.parent;
17176 }
17177 if (select && select.select_binding_dependencies) {
17178 select.select_binding_dependencies.forEach(prop => {
17179 this.node.dependencies.forEach((dependency) => {
17180 this.parent.renderer.component.indirect_dependencies.get(prop).add(dependency);
17181 });
17182 });
17183 }
17184 }
17185 if (node.name === 'value') {
17186 handle_select_value_binding(this, node.dependencies);
17187 }
17188 }
17189 this.name = fix_attribute_casing(this.node.name);
17190 this.metadata = this.get_metadata();
17191 this.is_indirectly_bound_value = is_indirectly_bound_value(this);
17192 this.property_name = this.is_indirectly_bound_value
17193 ? '__value'
17194 : this.metadata && this.metadata.property_name;
17195 this.is_src = this.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
17196 this.is_select_value_attribute = this.name === 'value' && this.parent.node.name === 'select';
17197 this.is_input_value = this.name === 'value' && this.parent.node.name === 'input';
17198 this.should_cache = should_cache(this);
17199 }
17200 render(block) {
17201 const element = this.parent;
17202 const { name, property_name, should_cache, is_indirectly_bound_value } = this;
17203 // xlink is a special case... we could maybe extend this to generic
17204 // namespaced attributes but I'm not sure that's applicable in
17205 // HTML5?
17206 const method = /-/.test(element.node.name)
17207 ? '@set_custom_element_data'
17208 : name.slice(0, 6) === 'xlink:'
17209 ? '@xlink_attr'
17210 : '@attr';
17211 const is_legacy_input_type = element.renderer.component.compile_options.legacy && name === 'type' && this.parent.node.name === 'input';
17212 const dependencies = this.get_dependencies();
17213 const value = this.get_value(block);
17214 let updater;
17215 const init = this.get_init(block, value);
17216 if (is_legacy_input_type) {
17217 block.chunks.hydrate.push(b `@set_input_type(${element.var}, ${init});`);
17218 updater = b `@set_input_type(${element.var}, ${should_cache ? this.last : value});`;
17219 }
17220 else if (this.is_select_value_attribute) {
17221 // annoying special case
17222 const is_multiple_select = element.node.get_static_attribute_value('multiple');
17223 if (is_multiple_select) {
17224 updater = b `@select_options(${element.var}, ${value});`;
17225 }
17226 else {
17227 updater = b `@select_option(${element.var}, ${value});`;
17228 }
17229 block.chunks.mount.push(b `
17230 ${updater}
17231 `);
17232 }
17233 else if (this.is_src) {
17234 block.chunks.hydrate.push(b `if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${this.last});`);
17235 updater = b `${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
17236 }
17237 else if (property_name) {
17238 block.chunks.hydrate.push(b `${element.var}.${property_name} = ${init};`);
17239 updater = block.renderer.options.dev
17240 ? b `@prop_dev(${element.var}, "${property_name}", ${should_cache ? this.last : value});`
17241 : b `${element.var}.${property_name} = ${should_cache ? this.last : value};`;
17242 }
17243 else {
17244 block.chunks.hydrate.push(b `${method}(${element.var}, "${name}", ${init});`);
17245 updater = b `${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
17246 }
17247 if (is_indirectly_bound_value) {
17248 const update_value = b `${element.var}.value = ${element.var}.__value;`;
17249 block.chunks.hydrate.push(update_value);
17250 updater = b `
17251 ${updater}
17252 ${update_value};
17253 `;
17254 }
17255 if (dependencies.length > 0) {
17256 const condition = this.get_dom_update_conditions(block, block.renderer.dirty(dependencies));
17257 block.chunks.update.push(b `
17258 if (${condition}) {
17259 ${updater}
17260 }`);
17261 }
17262 // special case – autofocus. has to be handled in a bit of a weird way
17263 if (this.node.is_true && name === 'autofocus') {
17264 block.autofocus = element.var;
17265 }
17266 }
17267 get_init(block, value) {
17268 this.last = this.should_cache && block.get_unique_name(`${this.parent.var.name}_${this.name.replace(/[^a-zA-Z_$]/g, '_')}_value`);
17269 if (this.should_cache)
17270 block.add_variable(this.last);
17271 return this.should_cache ? x `${this.last} = ${value}` : value;
17272 }
17273 get_dom_update_conditions(block, dependency_condition) {
17274 const { property_name, should_cache, last } = this;
17275 const element = this.parent;
17276 const value = this.get_value(block);
17277 let condition = dependency_condition;
17278 if (should_cache) {
17279 condition = this.is_src
17280 ? x `${condition} && (${element.var}.src !== (${last} = ${value}))`
17281 : x `${condition} && (${last} !== (${last} = ${value}))`;
17282 }
17283 if (this.is_input_value) {
17284 const type = element.node.get_static_attribute_value('type');
17285 if (type === null || type === '' || type === 'text' || type === 'email' || type === 'password') {
17286 condition = x `${condition} && ${element.var}.${property_name} !== ${should_cache ? last : value}`;
17287 }
17288 }
17289 if (block.has_outros) {
17290 condition = x `!#current || ${condition}`;
17291 }
17292 return condition;
17293 }
17294 get_dependencies() {
17295 const node_dependencies = this.node.get_dependencies();
17296 const dependencies = new Set(node_dependencies);
17297 node_dependencies.forEach((prop) => {
17298 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17299 if (indirect_dependencies) {
17300 indirect_dependencies.forEach(indirect_dependency => {
17301 dependencies.add(indirect_dependency);
17302 });
17303 }
17304 });
17305 return Array.from(dependencies);
17306 }
17307 get_metadata() {
17308 if (this.parent.node.namespace)
17309 return null;
17310 const metadata = attribute_lookup[this.name];
17311 if (metadata && metadata.applies_to && !metadata.applies_to.includes(this.parent.node.name))
17312 return null;
17313 return metadata;
17314 }
17315 get_value(block) {
17316 if (this.node.is_true) {
17317 if (this.metadata && boolean_attribute.has(this.metadata.property_name.toLowerCase())) {
17318 return x `true`;
17319 }
17320 return x `""`;
17321 }
17322 if (this.node.chunks.length === 0)
17323 return x `""`;
17324 // TODO some of this code is repeated in Tag.ts — would be good to
17325 // DRY it out if that's possible without introducing crazy indirection
17326 if (this.node.chunks.length === 1) {
17327 return this.node.chunks[0].type === 'Text'
17328 ? string_literal(this.node.chunks[0].data)
17329 : this.node.chunks[0].manipulate(block);
17330 }
17331 let value = this.node.name === 'class'
17332 ? this.get_class_name_text(block)
17333 : this.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17334 // '{foo} {bar}' — treat as string concatenation
17335 if (this.node.chunks[0].type !== 'Text') {
17336 value = x `"" + ${value}`;
17337 }
17338 return value;
17339 }
17340 get_class_name_text(block) {
17341 const scoped_css = this.node.chunks.some((chunk) => chunk.synthetic);
17342 const rendered = this.render_chunks(block);
17343 if (scoped_css && rendered.length === 2) {
17344 // we have a situation like class={possiblyUndefined}
17345 rendered[0] = x `@null_to_empty(${rendered[0]})`;
17346 }
17347 return rendered.reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17348 }
17349 render_chunks(block) {
17350 return this.node.chunks.map((chunk) => {
17351 if (chunk.type === 'Text') {
17352 return string_literal(chunk.data);
17353 }
17354 return chunk.manipulate(block);
17355 });
17356 }
17357 stringify() {
17358 if (this.node.is_true)
17359 return '';
17360 const value = this.node.chunks;
17361 if (value.length === 0)
17362 return '=""';
17363 return `="${value.map(chunk => {
17364 return chunk.type === 'Text'
17365 ? chunk.data.replace(/"/g, '\\"')
17366 : `\${${chunk.manipulate()}}`;
17367 }).join('')}"`;
17368 }
17369}
17370// source: https://html.spec.whatwg.org/multipage/indices.html
17371const attribute_lookup = {
17372 allowfullscreen: { property_name: 'allowFullscreen', applies_to: ['iframe'] },
17373 allowpaymentrequest: { property_name: 'allowPaymentRequest', applies_to: ['iframe'] },
17374 async: { applies_to: ['script'] },
17375 autofocus: { applies_to: ['button', 'input', 'keygen', 'select', 'textarea'] },
17376 autoplay: { applies_to: ['audio', 'video'] },
17377 checked: { applies_to: ['input'] },
17378 controls: { applies_to: ['audio', 'video'] },
17379 default: { applies_to: ['track'] },
17380 defer: { applies_to: ['script'] },
17381 disabled: {
17382 applies_to: [
17383 'button',
17384 'fieldset',
17385 'input',
17386 'keygen',
17387 'optgroup',
17388 'option',
17389 'select',
17390 'textarea'
17391 ]
17392 },
17393 formnovalidate: { property_name: 'formNoValidate', applies_to: ['button', 'input'] },
17394 hidden: {},
17395 indeterminate: { applies_to: ['input'] },
17396 ismap: { property_name: 'isMap', applies_to: ['img'] },
17397 loop: { applies_to: ['audio', 'bgsound', 'video'] },
17398 multiple: { applies_to: ['input', 'select'] },
17399 muted: { applies_to: ['audio', 'video'] },
17400 nomodule: { property_name: 'noModule', applies_to: ['script'] },
17401 novalidate: { property_name: 'noValidate', applies_to: ['form'] },
17402 open: { applies_to: ['details', 'dialog'] },
17403 playsinline: { property_name: 'playsInline', applies_to: ['video'] },
17404 readonly: { property_name: 'readOnly', applies_to: ['input', 'textarea'] },
17405 required: { applies_to: ['input', 'select', 'textarea'] },
17406 reversed: { applies_to: ['ol'] },
17407 selected: { applies_to: ['option'] },
17408 value: {
17409 applies_to: [
17410 'button',
17411 'option',
17412 'input',
17413 'li',
17414 'meter',
17415 'progress',
17416 'param',
17417 'select',
17418 'textarea'
17419 ]
17420 }
17421};
17422Object.keys(attribute_lookup).forEach(name => {
17423 const metadata = attribute_lookup[name];
17424 if (!metadata.property_name)
17425 metadata.property_name = name;
17426});
17427// source: https://html.spec.whatwg.org/multipage/indices.html
17428const boolean_attribute = new Set([
17429 'allowfullscreen',
17430 'allowpaymentrequest',
17431 'async',
17432 'autofocus',
17433 'autoplay',
17434 'checked',
17435 'controls',
17436 'default',
17437 'defer',
17438 'disabled',
17439 'formnovalidate',
17440 'hidden',
17441 'ismap',
17442 'itemscope',
17443 'loop',
17444 'multiple',
17445 'muted',
17446 'nomodule',
17447 'novalidate',
17448 'open',
17449 'playsinline',
17450 'readonly',
17451 'required',
17452 'reversed',
17453 'selected'
17454]);
17455function should_cache(attribute) {
17456 return attribute.is_src || attribute.node.should_cache();
17457}
17458function is_indirectly_bound_value(attribute) {
17459 const element = attribute.parent;
17460 return attribute.name === 'value' &&
17461 (element.node.name === 'option' || // TODO check it's actually bound
17462 (element.node.name === 'input' &&
17463 element.node.bindings.some((binding) => /checked|group/.test(binding.name))));
17464}
17465
17466class StyleAttributeWrapper extends AttributeWrapper {
17467 render(block) {
17468 const style_props = optimize_style(this.node.chunks);
17469 if (!style_props)
17470 return super.render(block);
17471 style_props.forEach((prop) => {
17472 let value;
17473 if (is_dynamic(prop.value)) {
17474 const prop_dependencies = new Set();
17475 value = prop.value
17476 .map(chunk => {
17477 if (chunk.type === 'Text') {
17478 return string_literal(chunk.data);
17479 }
17480 else {
17481 add_to_set(prop_dependencies, chunk.dynamic_dependencies());
17482 return chunk.manipulate(block);
17483 }
17484 })
17485 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17486 // TODO is this necessary? style.setProperty always treats value as string, no?
17487 // if (prop.value.length === 1 || prop.value[0].type !== 'Text') {
17488 // value = x`"" + ${value}`;
17489 // }
17490 if (prop_dependencies.size) {
17491 let condition = block.renderer.dirty(Array.from(prop_dependencies));
17492 if (block.has_outros) {
17493 condition = x `!#current || ${condition}`;
17494 }
17495 const update = b `
17496 if (${condition}) {
17497 @set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});
17498 }`;
17499 block.chunks.update.push(update);
17500 }
17501 }
17502 else {
17503 value = string_literal(prop.value[0].data);
17504 }
17505 block.chunks.hydrate.push(b `@set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});`);
17506 });
17507 }
17508}
17509function optimize_style(value) {
17510 const props = [];
17511 let chunks = value.slice();
17512 while (chunks.length) {
17513 const chunk = chunks[0];
17514 if (chunk.type !== 'Text')
17515 return null;
17516 const key_match = /^\s*([\w-]+):\s*/.exec(chunk.data);
17517 if (!key_match)
17518 return null;
17519 const key = key_match[1];
17520 const offset = key_match.index + key_match[0].length;
17521 const remaining_data = chunk.data.slice(offset);
17522 if (remaining_data) {
17523 chunks[0] = {
17524 start: chunk.start + offset,
17525 end: chunk.end,
17526 type: 'Text',
17527 data: remaining_data
17528 };
17529 }
17530 else {
17531 chunks.shift();
17532 }
17533 const result = get_style_value(chunks);
17534 props.push({ key, value: result.value, important: result.important });
17535 chunks = result.chunks;
17536 }
17537 return props;
17538}
17539function get_style_value(chunks) {
17540 const value = [];
17541 let in_url = false;
17542 let quote_mark = null;
17543 let escaped = false;
17544 let closed = false;
17545 while (chunks.length && !closed) {
17546 const chunk = chunks.shift();
17547 if (chunk.type === 'Text') {
17548 let c = 0;
17549 while (c < chunk.data.length) {
17550 const char = chunk.data[c];
17551 if (escaped) {
17552 escaped = false;
17553 }
17554 else if (char === '\\') {
17555 escaped = true;
17556 }
17557 else if (char === quote_mark) {
17558 quote_mark = null;
17559 }
17560 else if (char === '"' || char === "'") {
17561 quote_mark = char;
17562 }
17563 else if (char === ')' && in_url) {
17564 in_url = false;
17565 }
17566 else if (char === 'u' && chunk.data.slice(c, c + 4) === 'url(') {
17567 in_url = true;
17568 }
17569 else if (char === ';' && !in_url && !quote_mark) {
17570 closed = true;
17571 break;
17572 }
17573 c += 1;
17574 }
17575 if (c > 0) {
17576 value.push({
17577 type: 'Text',
17578 start: chunk.start,
17579 end: chunk.start + c,
17580 data: chunk.data.slice(0, c)
17581 });
17582 }
17583 while (/[;\s]/.test(chunk.data[c]))
17584 c += 1;
17585 const remaining_data = chunk.data.slice(c);
17586 if (remaining_data) {
17587 chunks.unshift({
17588 start: chunk.start + c,
17589 end: chunk.end,
17590 type: 'Text',
17591 data: remaining_data
17592 });
17593 break;
17594 }
17595 }
17596 else {
17597 value.push(chunk);
17598 }
17599 }
17600 let important = false;
17601 const last_chunk = value[value.length - 1];
17602 if (last_chunk && last_chunk.type === 'Text' && /\s*!important\s*$/.test(last_chunk.data)) {
17603 important = true;
17604 last_chunk.data = last_chunk.data.replace(/\s*!important\s*$/, '');
17605 if (!last_chunk.data)
17606 value.pop();
17607 }
17608 return {
17609 chunks,
17610 value,
17611 important
17612 };
17613}
17614function is_dynamic(value) {
17615 return value.length > 1 || value[0].type !== 'Text';
17616}
17617
17618class SpreadAttributeWrapper extends BaseAttributeWrapper {
17619}
17620
17621function replace_object(node, replacement) {
17622 if (node.type === 'Identifier')
17623 return replacement;
17624 const ancestor = node;
17625 let parent;
17626 while (node.type === 'MemberExpression') {
17627 parent = node;
17628 node = node.object;
17629 }
17630 parent.object = replacement;
17631 return ancestor;
17632}
17633
17634function flatten_reference(node) {
17635 const nodes = [];
17636 const parts = [];
17637 while (node.type === 'MemberExpression') {
17638 nodes.unshift(node.property);
17639 if (!node.computed) {
17640 parts.unshift(node.property.name);
17641 }
17642 else {
17643 const computed_property = to_string$1(node.property);
17644 if (computed_property) {
17645 parts.unshift(`[${computed_property}]`);
17646 }
17647 }
17648 node = node.object;
17649 }
17650 const name = node.type === 'Identifier'
17651 ? node.name
17652 : node.type === 'ThisExpression' ? 'this' : null;
17653 nodes.unshift(node);
17654 parts.unshift(name);
17655 return { name, nodes, parts };
17656}
17657function to_string$1(node) {
17658 switch (node.type) {
17659 case 'Literal':
17660 return String(node.value);
17661 case 'Identifier':
17662 return node.name;
17663 }
17664}
17665
17666function mark_each_block_bindings(parent, binding) {
17667 // we need to ensure that the each block creates a context including
17668 // the list and the index, if they're not otherwise referenced
17669 binding.expression.references.forEach(name => {
17670 const each_block = parent.node.scope.get_owner(name);
17671 if (each_block) {
17672 each_block.has_binding = true;
17673 }
17674 });
17675 if (binding.name === 'group') {
17676 // for `<input bind:group={} >`, we make sure that all the each blocks creates context with `index`
17677 for (const name of binding.expression.contextual_dependencies) {
17678 const each_block = parent.node.scope.get_owner(name);
17679 each_block.has_index_binding = true;
17680 }
17681 }
17682}
17683
17684class BindingWrapper {
17685 constructor(block, node, parent) {
17686 this.node = node;
17687 this.parent = parent;
17688 const { dependencies } = this.node.expression;
17689 block.add_dependencies(dependencies);
17690 // TODO does this also apply to e.g. `<input type='checkbox' bind:group='foo'>`?
17691 handle_select_value_binding(this, dependencies);
17692 if (node.is_contextual) {
17693 mark_each_block_bindings(this.parent, this.node);
17694 }
17695 this.object = get_object(this.node.expression.node).name;
17696 // view to model
17697 this.handler = get_event_handler(this, parent.renderer, block, this.object, this.node.raw_expression);
17698 this.snippet = this.node.expression.manipulate(block);
17699 this.is_readonly = this.node.is_readonly;
17700 this.needs_lock = this.node.name === 'currentTime'; // TODO others?
17701 }
17702 get_dependencies() {
17703 const dependencies = new Set(this.node.expression.dependencies);
17704 this.node.expression.dependencies.forEach((prop) => {
17705 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17706 if (indirect_dependencies) {
17707 indirect_dependencies.forEach(indirect_dependency => {
17708 dependencies.add(indirect_dependency);
17709 });
17710 }
17711 });
17712 return dependencies;
17713 }
17714 is_readonly_media_attribute() {
17715 return this.node.is_readonly_media_attribute();
17716 }
17717 render(block, lock) {
17718 if (this.is_readonly)
17719 return;
17720 const { parent } = this;
17721 const update_conditions = this.needs_lock ? [x `!${lock}`] : [];
17722 const mount_conditions = [];
17723 const dependency_array = Array.from(this.get_dependencies());
17724 if (dependency_array.length > 0) {
17725 update_conditions.push(block.renderer.dirty(dependency_array));
17726 }
17727 if (parent.node.name === 'input') {
17728 const type = parent.node.get_static_attribute_value('type');
17729 if (type === null ||
17730 type === '' ||
17731 type === 'text' ||
17732 type === 'email' ||
17733 type === 'password') {
17734 update_conditions.push(x `${parent.var}.${this.node.name} !== ${this.snippet}`);
17735 }
17736 else if (type === 'number') {
17737 update_conditions.push(x `@to_number(${parent.var}.${this.node.name}) !== ${this.snippet}`);
17738 }
17739 }
17740 // model to view
17741 let update_dom = get_dom_updater(parent, this);
17742 let mount_dom = update_dom;
17743 // special cases
17744 switch (this.node.name) {
17745 case 'group':
17746 {
17747 const { binding_group, is_context, contexts, index } = get_binding_group(parent.renderer, this.node, block);
17748 block.renderer.add_to_context('$$binding_groups');
17749 if (is_context) {
17750 if (contexts.length > 1) {
17751 let binding_group = x `${block.renderer.reference('$$binding_groups')}[${index}]`;
17752 for (const name of contexts.slice(0, -1)) {
17753 binding_group = x `${binding_group}[${block.renderer.reference(name)}]`;
17754 block.chunks.init.push(b `${binding_group} = ${binding_group} || [];`);
17755 }
17756 }
17757 block.chunks.init.push(b `${binding_group(true)} = [];`);
17758 }
17759 block.chunks.hydrate.push(b `${binding_group(true)}.push(${parent.var});`);
17760 block.chunks.destroy.push(b `${binding_group(true)}.splice(${binding_group(true)}.indexOf(${parent.var}), 1);`);
17761 break;
17762 }
17763 case 'textContent':
17764 update_conditions.push(x `${this.snippet} !== ${parent.var}.textContent`);
17765 mount_conditions.push(x `${this.snippet} !== void 0`);
17766 break;
17767 case 'innerHTML':
17768 update_conditions.push(x `${this.snippet} !== ${parent.var}.innerHTML`);
17769 mount_conditions.push(x `${this.snippet} !== void 0`);
17770 break;
17771 case 'currentTime':
17772 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17773 mount_dom = null;
17774 break;
17775 case 'playbackRate':
17776 case 'volume':
17777 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17778 mount_conditions.push(x `!@_isNaN(${this.snippet})`);
17779 break;
17780 case 'paused':
17781 {
17782 // this is necessary to prevent audio restarting by itself
17783 const last = block.get_unique_name(`${parent.var.name}_is_paused`);
17784 block.add_variable(last, x `true`);
17785 update_conditions.push(x `${last} !== (${last} = ${this.snippet})`);
17786 update_dom = b `${parent.var}[${last} ? "pause" : "play"]();`;
17787 mount_dom = null;
17788 break;
17789 }
17790 case 'value':
17791 if (parent.node.get_static_attribute_value('type') === 'file') {
17792 update_dom = null;
17793 mount_dom = null;
17794 }
17795 }
17796 if (update_dom) {
17797 if (update_conditions.length > 0) {
17798 const condition = update_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17799 block.chunks.update.push(b `
17800 if (${condition}) {
17801 ${update_dom}
17802 }
17803 `);
17804 }
17805 else {
17806 block.chunks.update.push(update_dom);
17807 }
17808 }
17809 if (mount_dom) {
17810 if (mount_conditions.length > 0) {
17811 const condition = mount_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17812 block.chunks.mount.push(b `
17813 if (${condition}) {
17814 ${mount_dom}
17815 }
17816 `);
17817 }
17818 else {
17819 block.chunks.mount.push(mount_dom);
17820 }
17821 }
17822 }
17823}
17824function get_dom_updater(element, binding) {
17825 const { node } = element;
17826 if (binding.is_readonly_media_attribute()) {
17827 return null;
17828 }
17829 if (binding.node.name === 'this') {
17830 return null;
17831 }
17832 if (node.name === 'select') {
17833 return node.get_static_attribute_value('multiple') === true ?
17834 b `@select_options(${element.var}, ${binding.snippet})` :
17835 b `@select_option(${element.var}, ${binding.snippet})`;
17836 }
17837 if (binding.node.name === 'group') {
17838 const type = node.get_static_attribute_value('type');
17839 const condition = type === 'checkbox'
17840 ? x `~${binding.snippet}.indexOf(${element.var}.__value)`
17841 : x `${element.var}.__value === ${binding.snippet}`;
17842 return b `${element.var}.checked = ${condition};`;
17843 }
17844 if (binding.node.name === 'value') {
17845 return b `@set_input_value(${element.var}, ${binding.snippet});`;
17846 }
17847 return b `${element.var}.${binding.node.name} = ${binding.snippet};`;
17848}
17849function get_binding_group(renderer, value, block) {
17850 const { parts } = flatten_reference(value.raw_expression);
17851 let keypath = parts.join('.');
17852 const contexts = [];
17853 for (const dep of value.expression.contextual_dependencies) {
17854 const context = block.bindings.get(dep);
17855 let key;
17856 let name;
17857 if (context) {
17858 key = context.object.name;
17859 name = context.property.name;
17860 }
17861 else {
17862 key = dep;
17863 name = dep;
17864 }
17865 keypath = `${key}@${keypath}`;
17866 contexts.push(name);
17867 }
17868 if (!renderer.binding_groups.has(keypath)) {
17869 const index = renderer.binding_groups.size;
17870 contexts.forEach(context => {
17871 renderer.add_to_context(context, true);
17872 });
17873 renderer.binding_groups.set(keypath, {
17874 binding_group: (to_reference = false) => {
17875 let binding_group = '$$binding_groups';
17876 let _secondary_indexes = contexts;
17877 if (to_reference) {
17878 binding_group = block.renderer.reference(binding_group);
17879 _secondary_indexes = _secondary_indexes.map(name => block.renderer.reference(name));
17880 }
17881 if (_secondary_indexes.length > 0) {
17882 let obj = x `${binding_group}[${index}]`;
17883 _secondary_indexes.forEach(secondary_index => {
17884 obj = x `${obj}[${secondary_index}]`;
17885 });
17886 return obj;
17887 }
17888 else {
17889 return x `${binding_group}[${index}]`;
17890 }
17891 },
17892 is_context: contexts.length > 0,
17893 contexts,
17894 index
17895 });
17896 }
17897 return renderer.binding_groups.get(keypath);
17898}
17899function get_event_handler(binding, renderer, block, name, lhs) {
17900 const contextual_dependencies = new Set(binding.node.expression.contextual_dependencies);
17901 const context = block.bindings.get(name);
17902 let set_store;
17903 if (context) {
17904 const { object, property, store, snippet } = context;
17905 lhs = replace_object(lhs, snippet);
17906 contextual_dependencies.add(object.name);
17907 contextual_dependencies.add(property.name);
17908 contextual_dependencies.delete(name);
17909 if (store) {
17910 set_store = b `${store}.set(${`$${store}`});`;
17911 }
17912 }
17913 else {
17914 const object = get_object(lhs);
17915 if (object.name[0] === '$') {
17916 const store = object.name.slice(1);
17917 set_store = b `${store}.set(${object.name});`;
17918 }
17919 }
17920 const value = get_value_from_dom(renderer, binding.parent, binding, block, contextual_dependencies);
17921 const mutation = b `
17922 ${lhs} = ${value};
17923 ${set_store}
17924 `;
17925 return {
17926 uses_context: binding.node.is_contextual || binding.node.expression.uses_context,
17927 mutation,
17928 contextual_dependencies,
17929 lhs
17930 };
17931}
17932function get_value_from_dom(renderer, element, binding, block, contextual_dependencies) {
17933 const { node } = element;
17934 const { name } = binding.node;
17935 if (name === 'this') {
17936 return x `$$value`;
17937 }
17938 // <select bind:value='selected>
17939 if (node.name === 'select') {
17940 return node.get_static_attribute_value('multiple') === true ?
17941 x `@select_multiple_value(this)` :
17942 x `@select_value(this)`;
17943 }
17944 const type = node.get_static_attribute_value('type');
17945 // <input type='checkbox' bind:group='foo'>
17946 if (name === 'group') {
17947 if (type === 'checkbox') {
17948 const { binding_group, contexts } = get_binding_group(renderer, binding.node, block);
17949 add_to_set(contextual_dependencies, contexts);
17950 return x `@get_binding_group_value(${binding_group()}, this.__value, this.checked)`;
17951 }
17952 return x `this.__value`;
17953 }
17954 // <input type='range|number' bind:value>
17955 if (type === 'range' || type === 'number') {
17956 return x `@to_number(this.${name})`;
17957 }
17958 if ((name === 'buffered' || name === 'seekable' || name === 'played')) {
17959 return x `@time_ranges_to_array(this.${name})`;
17960 }
17961 // everything else
17962 return x `this.${name}`;
17963}
17964
17965function add_actions(block, target, actions) {
17966 actions.forEach(action => add_action(block, target, action));
17967}
17968function add_action(block, target, action) {
17969 const { expression } = action;
17970 let snippet;
17971 let dependencies;
17972 if (expression) {
17973 snippet = expression.manipulate(block);
17974 dependencies = expression.dynamic_dependencies();
17975 }
17976 const id = block.get_unique_name(`${action.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action`);
17977 block.add_variable(id);
17978 const [obj, ...properties] = action.name.split('.');
17979 const fn = block.renderer.reference(obj);
17980 if (properties.length) {
17981 block.event_listeners.push(x `@action_destroyer(${id} = ${fn}.${properties.join('.')}(${target}, ${snippet}))`);
17982 }
17983 else {
17984 block.event_listeners.push(x `@action_destroyer(${id} = ${fn}.call(null, ${target}, ${snippet}))`);
17985 }
17986 if (dependencies && dependencies.length > 0) {
17987 let condition = x `${id} && @is_function(${id}.update)`;
17988 if (dependencies.length > 0) {
17989 condition = x `${condition} && ${block.renderer.dirty(dependencies)}`;
17990 }
17991 block.chunks.update.push(b `if (${condition}) ${id}.update.call(null, ${snippet});`);
17992 }
17993}
17994
17995function compare_node(a, b) {
17996 if (a === b)
17997 return true;
17998 if (!a || !b)
17999 return false;
18000 if (a.type !== b.type)
18001 return false;
18002 switch (a.type) {
18003 case 'Identifier':
18004 return a.name === b.name;
18005 case 'MemberExpression':
18006 return (compare_node(a.object, b.object) &&
18007 compare_node(a.property, b.property) &&
18008 a.computed === b.computed);
18009 case 'Literal':
18010 return a.value === b.value;
18011 }
18012}
18013
18014function bind_this(component, block, binding, variable) {
18015 const fn = component.get_unique_name(`${variable.name}_binding`);
18016 block.renderer.add_to_context(fn.name);
18017 const callee = block.renderer.reference(fn.name);
18018 const { contextual_dependencies, mutation } = binding.handler;
18019 const dependencies = binding.get_dependencies();
18020 const body = b `
18021 ${mutation}
18022 ${Array.from(dependencies)
18023 .filter(dep => dep[0] !== '$')
18024 .filter(dep => !contextual_dependencies.has(dep))
18025 .map(dep => b `${block.renderer.invalidate(dep)};`)}
18026 `;
18027 if (contextual_dependencies.size) {
18028 const params = Array.from(contextual_dependencies).map(name => ({
18029 type: 'Identifier',
18030 name
18031 }));
18032 component.partly_hoisted.push(b `
18033 function ${fn}($$value, ${params}) {
18034 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
18035 ${body}
18036 });
18037 }
18038 `);
18039 const alias_map = new Map();
18040 const args = [];
18041 for (let id of params) {
18042 const value = block.renderer.reference(id.name);
18043 let found = false;
18044 if (block.variables.has(id.name)) {
18045 let alias = id.name;
18046 for (let i = 1; block.variables.has(alias) && !compare_node(block.variables.get(alias).init, value); alias = `${id.name}_${i++}`)
18047 ;
18048 alias_map.set(alias, id.name);
18049 id = { type: 'Identifier', name: alias };
18050 found = block.variables.has(alias);
18051 }
18052 args.push(id);
18053 if (!found) {
18054 block.add_variable(id, value);
18055 }
18056 }
18057 const assign = block.get_unique_name(`assign_${variable.name}`);
18058 const unassign = block.get_unique_name(`unassign_${variable.name}`);
18059 block.chunks.init.push(b `
18060 const ${assign} = () => ${callee}(${variable}, ${args});
18061 const ${unassign} = () => ${callee}(null, ${args});
18062 `);
18063 const condition = Array.from(args)
18064 .map(name => x `${name} !== ${block.renderer.reference(alias_map.get(name.name) || name.name)}`)
18065 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
18066 // we push unassign and unshift assign so that references are
18067 // nulled out before they're created, to avoid glitches
18068 // with shifting indices
18069 block.chunks.update.push(b `
18070 if (${condition}) {
18071 ${unassign}();
18072 ${args.map(a => b `${a} = ${block.renderer.reference(alias_map.get(a.name) || a.name)}`)};
18073 ${assign}();
18074 }`);
18075 block.chunks.destroy.push(b `${unassign}();`);
18076 return b `${assign}();`;
18077 }
18078 component.partly_hoisted.push(b `
18079 function ${fn}($$value) {
18080 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
18081 ${body}
18082 });
18083 }
18084 `);
18085 block.chunks.destroy.push(b `${callee}(null);`);
18086 return b `${callee}(${variable});`;
18087}
18088
18089class Node$1 {
18090 constructor(component, parent, _scope, info) {
18091 this.start = info.start;
18092 this.end = info.end;
18093 this.type = info.type;
18094 // this makes properties non-enumerable, which makes logging
18095 // bearable. might have a performance cost. TODO remove in prod?
18096 Object.defineProperties(this, {
18097 component: {
18098 value: component
18099 },
18100 parent: {
18101 value: parent
18102 }
18103 });
18104 }
18105 cannot_use_innerhtml() {
18106 if (this.can_use_innerhtml !== false) {
18107 this.can_use_innerhtml = false;
18108 if (this.parent)
18109 this.parent.cannot_use_innerhtml();
18110 }
18111 }
18112 find_nearest(selector) {
18113 if (selector.test(this.type))
18114 return this;
18115 if (this.parent)
18116 return this.parent.find_nearest(selector);
18117 }
18118 get_static_attribute_value(name) {
18119 const attribute = this.attributes && this.attributes.find((attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === name);
18120 if (!attribute)
18121 return null;
18122 if (attribute.is_true)
18123 return true;
18124 if (attribute.chunks.length === 0)
18125 return '';
18126 if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
18127 return attribute.chunks[0].data;
18128 }
18129 return null;
18130 }
18131 has_ancestor(type) {
18132 return this.parent ?
18133 this.parent.type === type || this.parent.has_ancestor(type) :
18134 false;
18135 }
18136}
18137
18138function create_scopes(expression) {
18139 return analyze(expression);
18140}
18141
18142const reserved_keywords = new Set(['$$props', '$$restProps', '$$slots']);
18143function is_reserved_keyword(name) {
18144 return reserved_keywords.has(name);
18145}
18146
18147function is_dynamic$1(variable) {
18148 if (variable) {
18149 if (variable.mutated || variable.reassigned)
18150 return true; // dynamic internal state
18151 if (!variable.module && variable.writable && variable.export_name)
18152 return true; // writable props
18153 if (is_reserved_keyword(variable.name))
18154 return true;
18155 }
18156 return false;
18157}
18158
18159function nodes_match(a, b) {
18160 if (!!a !== !!b)
18161 return false;
18162 if (Array.isArray(a) !== Array.isArray(b))
18163 return false;
18164 if (a && typeof a === 'object') {
18165 if (Array.isArray(a)) {
18166 if (a.length !== b.length)
18167 return false;
18168 return a.every((child, i) => nodes_match(child, b[i]));
18169 }
18170 const a_keys = Object.keys(a).sort();
18171 const b_keys = Object.keys(b).sort();
18172 if (a_keys.length !== b_keys.length)
18173 return false;
18174 let i = a_keys.length;
18175 while (i--) {
18176 const key = a_keys[i];
18177 if (b_keys[i] !== key)
18178 return false;
18179 if (key === 'start' || key === 'end')
18180 continue;
18181 if (!nodes_match(a[key], b[key])) {
18182 return false;
18183 }
18184 }
18185 return true;
18186 }
18187 return a === b;
18188}
18189
18190function invalidate(renderer, scope, node, names, main_execution_context = false) {
18191 const { component } = renderer;
18192 const [head, ...tail] = Array.from(names)
18193 .filter(name => {
18194 const owner = scope.find_owner(name);
18195 return !owner || owner === component.instance_scope;
18196 })
18197 .map(name => component.var_lookup.get(name))
18198 .filter(variable => {
18199 return variable && (!variable.hoistable &&
18200 !variable.global &&
18201 !variable.module &&
18202 (variable.referenced ||
18203 variable.subscribable ||
18204 variable.is_reactive_dependency ||
18205 variable.export_name ||
18206 variable.name[0] === '$'));
18207 });
18208 function get_invalidated(variable, node) {
18209 if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') {
18210 return node;
18211 }
18212 return renderer.invalidate(variable.name, undefined, main_execution_context);
18213 }
18214 if (!head) {
18215 return node;
18216 }
18217 component.has_reactive_assignments = true;
18218 if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) {
18219 return get_invalidated(head, node);
18220 }
18221 const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
18222 const extra_args = tail.map(variable => get_invalidated(variable)).filter(Boolean);
18223 if (is_store_value) {
18224 return x `@set_store_value(${head.name.slice(1)}, ${node}, ${head.name}, ${extra_args})`;
18225 }
18226 let invalidate;
18227 if (!main_execution_context) {
18228 const pass_value = (extra_args.length > 0 ||
18229 (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
18230 (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier')));
18231 if (pass_value) {
18232 extra_args.unshift({
18233 type: 'Identifier',
18234 name: head.name
18235 });
18236 }
18237 invalidate = x `$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`;
18238 }
18239 else {
18240 // skip `$$invalidate` if it is in the main execution context
18241 invalidate = extra_args.length ? [node, ...extra_args] : node;
18242 }
18243 if (head.subscribable && head.reassigned) {
18244 const subscribe = `$$subscribe_${head.name}`;
18245 invalidate = x `${subscribe}(${invalidate})`;
18246 }
18247 return invalidate;
18248}
18249
18250class Expression {
18251 constructor(component, owner, template_scope, info, lazy) {
18252 this.type = 'Expression';
18253 this.references = new Set();
18254 this.dependencies = new Set();
18255 this.contextual_dependencies = new Set();
18256 this.declarations = [];
18257 this.uses_context = false;
18258 // TODO revert to direct property access in prod?
18259 Object.defineProperties(this, {
18260 component: {
18261 value: component
18262 }
18263 });
18264 this.node = info;
18265 this.template_scope = template_scope;
18266 this.owner = owner;
18267 const { dependencies, contextual_dependencies, references } = this;
18268 let { map, scope } = create_scopes(info);
18269 this.scope = scope;
18270 this.scope_map = map;
18271 const expression = this;
18272 let function_expression;
18273 // discover dependencies, but don't change the code yet
18274 walk(info, {
18275 enter(node, parent, key) {
18276 // don't manipulate shorthand props twice
18277 if (key === 'value' && parent.shorthand)
18278 return;
18279 // don't manipulate `import.meta`, `new.target`
18280 if (node.type === 'MetaProperty')
18281 return this.skip();
18282 if (map.has(node)) {
18283 scope = map.get(node);
18284 }
18285 if (!function_expression && /FunctionExpression/.test(node.type)) {
18286 function_expression = node;
18287 }
18288 if (isReference(node, parent)) {
18289 const { name, nodes } = flatten_reference(node);
18290 references.add(name);
18291 if (scope.has(name))
18292 return;
18293 if (name[0] === '$') {
18294 const store_name = name.slice(1);
18295 if (template_scope.names.has(store_name) || scope.has(store_name)) {
18296 component.error(node, {
18297 code: 'contextual-store',
18298 message: 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
18299 });
18300 }
18301 }
18302 if (template_scope.is_let(name)) {
18303 if (!function_expression) { // TODO should this be `!lazy` ?
18304 contextual_dependencies.add(name);
18305 dependencies.add(name);
18306 }
18307 }
18308 else if (template_scope.names.has(name)) {
18309 expression.uses_context = true;
18310 contextual_dependencies.add(name);
18311 const owner = template_scope.get_owner(name);
18312 const is_index = owner.type === 'EachBlock' && owner.key && name === owner.index;
18313 if (!lazy || is_index) {
18314 template_scope.dependencies_for_name.get(name).forEach(name => dependencies.add(name));
18315 }
18316 }
18317 else {
18318 if (!lazy) {
18319 dependencies.add(name);
18320 }
18321 component.add_reference(name);
18322 component.warn_if_undefined(name, nodes[0], template_scope);
18323 }
18324 this.skip();
18325 }
18326 // track any assignments from template expressions as mutable
18327 let names;
18328 let deep = false;
18329 if (function_expression) {
18330 if (node.type === 'AssignmentExpression') {
18331 deep = node.left.type === 'MemberExpression';
18332 names = extract_names(deep ? get_object(node.left) : node.left);
18333 }
18334 else if (node.type === 'UpdateExpression') {
18335 names = extract_names(get_object(node.argument));
18336 }
18337 }
18338 if (names) {
18339 names.forEach(name => {
18340 if (template_scope.names.has(name)) {
18341 template_scope.dependencies_for_name.get(name).forEach(name => {
18342 const variable = component.var_lookup.get(name);
18343 if (variable)
18344 variable[deep ? 'mutated' : 'reassigned'] = true;
18345 });
18346 const each_block = template_scope.get_owner(name);
18347 each_block.has_binding = true;
18348 }
18349 else {
18350 component.add_reference(name);
18351 const variable = component.var_lookup.get(name);
18352 if (variable)
18353 variable[deep ? 'mutated' : 'reassigned'] = true;
18354 }
18355 });
18356 }
18357 },
18358 leave(node) {
18359 if (map.has(node)) {
18360 scope = scope.parent;
18361 }
18362 if (node === function_expression) {
18363 function_expression = null;
18364 }
18365 }
18366 });
18367 }
18368 dynamic_dependencies() {
18369 return Array.from(this.dependencies).filter(name => {
18370 if (this.template_scope.is_let(name))
18371 return true;
18372 if (is_reserved_keyword(name))
18373 return true;
18374 const variable = this.component.var_lookup.get(name);
18375 return is_dynamic$1(variable);
18376 });
18377 }
18378 // TODO move this into a render-dom wrapper?
18379 manipulate(block) {
18380 // TODO ideally we wouldn't end up calling this method
18381 // multiple times
18382 if (this.manipulated)
18383 return this.manipulated;
18384 const { component, declarations, scope_map: map, template_scope, owner } = this;
18385 let scope = this.scope;
18386 let function_expression;
18387 let dependencies;
18388 let contextual_dependencies;
18389 const node = walk(this.node, {
18390 enter(node, parent) {
18391 if (node.type === 'Property' && node.shorthand) {
18392 node.value = JSON.parse(JSON.stringify(node.value));
18393 node.shorthand = false;
18394 }
18395 if (map.has(node)) {
18396 scope = map.get(node);
18397 }
18398 if (node.type === 'Identifier' && isReference(node, parent)) {
18399 const { name } = flatten_reference(node);
18400 if (scope.has(name))
18401 return;
18402 if (function_expression) {
18403 if (template_scope.names.has(name)) {
18404 contextual_dependencies.add(name);
18405 template_scope.dependencies_for_name.get(name).forEach(dependency => {
18406 dependencies.add(dependency);
18407 });
18408 }
18409 else {
18410 dependencies.add(name);
18411 component.add_reference(name); // TODO is this redundant/misplaced?
18412 }
18413 }
18414 else if (is_contextual(component, template_scope, name)) {
18415 const reference = block.renderer.reference(node);
18416 this.replace(reference);
18417 }
18418 this.skip();
18419 }
18420 if (!function_expression) {
18421 if (node.type === 'AssignmentExpression') ;
18422 if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
18423 function_expression = node;
18424 dependencies = new Set();
18425 contextual_dependencies = new Set();
18426 }
18427 }
18428 },
18429 leave(node, parent) {
18430 if (map.has(node))
18431 scope = scope.parent;
18432 if (node === function_expression) {
18433 const id = component.get_unique_name(sanitize(get_function_name(node, owner)));
18434 const declaration = b `const ${id} = ${node}`;
18435 if (dependencies.size === 0 && contextual_dependencies.size === 0) {
18436 // we can hoist this out of the component completely
18437 component.fully_hoisted.push(declaration);
18438 this.replace(id);
18439 component.add_var({
18440 name: id.name,
18441 internal: true,
18442 hoistable: true,
18443 referenced: true
18444 });
18445 }
18446 else if (contextual_dependencies.size === 0) {
18447 // function can be hoisted inside the component init
18448 component.partly_hoisted.push(declaration);
18449 block.renderer.add_to_context(id.name);
18450 this.replace(block.renderer.reference(id));
18451 }
18452 else {
18453 // we need a combo block/init recipe
18454 const deps = Array.from(contextual_dependencies);
18455 const function_expression = node;
18456 const has_args = function_expression.params.length > 0;
18457 function_expression.params = [
18458 ...deps.map(name => ({ type: 'Identifier', name })),
18459 ...function_expression.params
18460 ];
18461 const context_args = deps.map(name => block.renderer.reference(name));
18462 component.partly_hoisted.push(declaration);
18463 block.renderer.add_to_context(id.name);
18464 const callee = block.renderer.reference(id);
18465 this.replace(id);
18466 const func_declaration = has_args
18467 ? b `function ${id}(...args) {
18468 return ${callee}(${context_args}, ...args);
18469 }`
18470 : b `function ${id}() {
18471 return ${callee}(${context_args});
18472 }`;
18473 if (owner.type === 'Attribute' && owner.parent.name === 'slot') {
18474 const dep_scopes = new Set(deps.map(name => template_scope.get_owner(name)));
18475 // find the nearest scopes
18476 let node = owner.parent;
18477 while (node && !dep_scopes.has(node)) {
18478 node = node.parent;
18479 }
18480 const func_expression = func_declaration[0];
18481 if (node.type === 'InlineComponent') {
18482 // <Comp let:data />
18483 this.replace(func_expression);
18484 }
18485 else {
18486 // {#each}, {#await}
18487 const func_id = component.get_unique_name(id.name + '_func');
18488 block.renderer.add_to_context(func_id.name, true);
18489 // rename #ctx -> child_ctx;
18490 walk(func_expression, {
18491 enter(node) {
18492 if (node.type === 'Identifier' && node.name === '#ctx') {
18493 node.name = 'child_ctx';
18494 }
18495 }
18496 });
18497 // add to get_xxx_context
18498 // child_ctx[x] = function () { ... }
18499 template_scope.get_owner(deps[0]).contexts.push({
18500 key: func_id,
18501 modifier: () => func_expression
18502 });
18503 this.replace(block.renderer.reference(func_id));
18504 }
18505 }
18506 else {
18507 declarations.push(func_declaration);
18508 }
18509 }
18510 function_expression = null;
18511 dependencies = null;
18512 contextual_dependencies = null;
18513 if (parent && parent.type === 'Property') {
18514 parent.method = false;
18515 }
18516 }
18517 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
18518 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
18519 const object_name = get_object(assignee).name;
18520 if (scope.has(object_name))
18521 return;
18522 // normally (`a = 1`, `b.c = 2`), there'll be a single name
18523 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
18524 // may be more, in which case we need to tack the extra ones
18525 // onto the initial function call
18526 const names = new Set(extract_names(assignee));
18527 const traced = new Set();
18528 names.forEach(name => {
18529 const dependencies = template_scope.dependencies_for_name.get(name);
18530 if (dependencies) {
18531 dependencies.forEach(name => traced.add(name));
18532 }
18533 else {
18534 traced.add(name);
18535 }
18536 });
18537 const context = block.bindings.get(object_name);
18538 if (context) {
18539 // for `{#each array as item}`
18540 // replace `item = 1` to `each_array[each_index] = 1`, this allow us to mutate the array
18541 // rather than mutating the local `item` variable
18542 const { snippet, object, property } = context;
18543 const replaced = replace_object(assignee, snippet);
18544 if (node.type === 'AssignmentExpression') {
18545 node.left = replaced;
18546 }
18547 else {
18548 node.argument = replaced;
18549 }
18550 contextual_dependencies.add(object.name);
18551 contextual_dependencies.add(property.name);
18552 }
18553 this.replace(invalidate(block.renderer, scope, node, traced));
18554 }
18555 }
18556 });
18557 if (declarations.length > 0) {
18558 block.maintain_context = true;
18559 declarations.forEach(declaration => {
18560 block.chunks.init.push(declaration);
18561 });
18562 }
18563 return (this.manipulated = node);
18564 }
18565}
18566function get_function_name(_node, parent) {
18567 if (parent.type === 'EventHandler') {
18568 return `${parent.name}_handler`;
18569 }
18570 if (parent.type === 'Action') {
18571 return `${parent.name}_function`;
18572 }
18573 return 'func';
18574}
18575function is_contextual(component, scope, name) {
18576 if (is_reserved_keyword(name))
18577 return true;
18578 // if it's a name below root scope, it's contextual
18579 if (!scope.is_top_level(name))
18580 return true;
18581 const variable = component.var_lookup.get(name);
18582 // hoistables, module declarations, and imports are non-contextual
18583 if (!variable || variable.hoistable)
18584 return false;
18585 // assume contextual
18586 return true;
18587}
18588
18589class Action extends Node$1 {
18590 constructor(component, parent, scope, info) {
18591 super(component, parent, scope, info);
18592 const object = info.name.split('.')[0];
18593 component.warn_if_undefined(object, info, scope);
18594 this.name = info.name;
18595 component.add_reference(object);
18596 this.expression = info.expression
18597 ? new Expression(component, this, scope, info.expression)
18598 : null;
18599 this.uses_context = this.expression && this.expression.uses_context;
18600 }
18601}
18602
18603class Tag extends Wrapper {
18604 constructor(renderer, block, parent, node) {
18605 super(renderer, block, parent, node);
18606 this.cannot_use_innerhtml();
18607 if (!this.is_dependencies_static()) {
18608 this.not_static_content();
18609 }
18610 block.add_dependencies(node.expression.dependencies);
18611 }
18612 is_dependencies_static() {
18613 return this.node.expression.contextual_dependencies.size === 0 && this.node.expression.dynamic_dependencies().length === 0;
18614 }
18615 rename_this_method(block, update) {
18616 const dependencies = this.node.expression.dynamic_dependencies();
18617 let snippet = this.node.expression.manipulate(block);
18618 const value = this.node.should_cache && block.get_unique_name(`${this.var.name}_value`);
18619 const content = this.node.should_cache ? value : snippet;
18620 snippet = x `${snippet} + ""`;
18621 if (this.node.should_cache)
18622 block.add_variable(value, snippet); // TODO may need to coerce snippet to string
18623 if (dependencies.length > 0) {
18624 let condition = block.renderer.dirty(dependencies);
18625 if (block.has_outros) {
18626 condition = x `!#current || ${condition}`;
18627 }
18628 const update_cached_value = x `${value} !== (${value} = ${snippet})`;
18629 if (this.node.should_cache) {
18630 condition = x `${condition} && ${update_cached_value}`;
18631 }
18632 block.chunks.update.push(b `if (${condition}) ${update(content)}`);
18633 }
18634 return { init: content };
18635 }
18636}
18637
18638class MustacheTagWrapper extends Tag {
18639 constructor(renderer, block, parent, node) {
18640 super(renderer, block, parent, node);
18641 this.var = { type: 'Identifier', name: 't' };
18642 }
18643 render(block, parent_node, parent_nodes) {
18644 const { init } = this.rename_this_method(block, value => x `@set_data(${this.var}, ${value})`);
18645 block.add_element(this.var, x `@text(${init})`, parent_nodes && x `@claim_text(${parent_nodes}, ${init})`, parent_node);
18646 }
18647}
18648
18649class RawMustacheTagWrapper extends Tag {
18650 constructor(renderer, block, parent, node) {
18651 super(renderer, block, parent, node);
18652 this.var = { type: 'Identifier', name: 'raw' };
18653 this.cannot_use_innerhtml();
18654 this.not_static_content();
18655 }
18656 render(block, parent_node, _parent_nodes) {
18657 const in_head = is_head(parent_node);
18658 const can_use_innerhtml = !in_head && parent_node && !this.prev && !this.next;
18659 if (can_use_innerhtml) {
18660 const insert = content => b `${parent_node}.innerHTML = ${content};`[0];
18661 const { init } = this.rename_this_method(block, content => insert(content));
18662 block.chunks.mount.push(insert(init));
18663 }
18664 else {
18665 const needs_anchor = in_head || (this.next ? !this.next.is_dom_node() : (!this.parent || !this.parent.is_dom_node()));
18666 const html_tag = block.get_unique_name('html_tag');
18667 const html_anchor = needs_anchor && block.get_unique_name('html_anchor');
18668 block.add_variable(html_tag);
18669 const { init } = this.rename_this_method(block, content => x `${html_tag}.p(${content})`);
18670 const update_anchor = needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
18671 block.chunks.hydrate.push(b `${html_tag} = new @HtmlTag(${update_anchor});`);
18672 block.chunks.mount.push(b `${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`);
18673 if (needs_anchor) {
18674 block.add_element(html_anchor, x `@empty()`, x `@empty()`, parent_node);
18675 }
18676 if (!parent_node || in_head) {
18677 block.chunks.destroy.push(b `if (detaching) ${html_tag}.d();`);
18678 }
18679 }
18680 }
18681}
18682
18683function get_slot_definition(block, scope, lets) {
18684 if (lets.length === 0)
18685 return { block, scope };
18686 const context_input = {
18687 type: 'ObjectPattern',
18688 properties: lets.map(l => ({
18689 type: 'Property',
18690 kind: 'init',
18691 key: l.name,
18692 value: l.value || l.name
18693 }))
18694 };
18695 const properties = [];
18696 const value_map = new Map();
18697 lets.forEach(l => {
18698 let value;
18699 if (l.names.length > 1) {
18700 // more than one, probably destructuring
18701 const unique_name = block.get_unique_name(l.names.join('_')).name;
18702 value_map.set(l.value, unique_name);
18703 value = { type: 'Identifier', name: unique_name };
18704 }
18705 else {
18706 value = l.value || l.name;
18707 }
18708 properties.push({
18709 type: 'Property',
18710 kind: 'init',
18711 key: l.name,
18712 value
18713 });
18714 });
18715 const changes_input = {
18716 type: 'ObjectPattern',
18717 properties
18718 };
18719 const names = new Set();
18720 const names_lookup = new Map();
18721 lets.forEach(l => {
18722 l.names.forEach(name => {
18723 names.add(name);
18724 if (value_map.has(l.value)) {
18725 names_lookup.set(name, value_map.get(l.value));
18726 }
18727 });
18728 });
18729 const context = {
18730 type: 'ObjectExpression',
18731 properties: Array.from(names).map(name => p `${block.renderer.context_lookup.get(name).index}: ${name}`)
18732 };
18733 const { context_lookup } = block.renderer;
18734 // i am well aware that this code is gross
18735 // TODO: context-overflow make it less gross
18736 const changes = {
18737 type: 'ParenthesizedExpression',
18738 get expression() {
18739 if (block.renderer.context_overflow) {
18740 const grouped = [];
18741 Array.from(names).forEach(name => {
18742 const i = context_lookup.get(name).index.value;
18743 const g = Math.floor(i / 31);
18744 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
18745 if (!grouped[g])
18746 grouped[g] = [];
18747 grouped[g].push({ name: lookup_name, n: i % 31 });
18748 });
18749 const elements = [];
18750 for (let g = 0; g < grouped.length; g += 1) {
18751 elements[g] = grouped[g]
18752 ? grouped[g]
18753 .map(({ name, n }) => x `${name} ? ${1 << n} : 0`)
18754 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`)
18755 : x `0`;
18756 }
18757 return {
18758 type: 'ArrayExpression',
18759 elements
18760 };
18761 }
18762 return Array.from(names)
18763 .map(name => {
18764 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
18765 const i = context_lookup.get(name).index.value;
18766 return x `${lookup_name} ? ${1 << i} : 0`;
18767 })
18768 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
18769 }
18770 };
18771 return {
18772 block,
18773 scope,
18774 get_context: x `${context_input} => ${context}`,
18775 get_changes: x `${changes_input} => ${changes}`
18776 };
18777}
18778
18779function create_slot_block(attribute, element, block) {
18780 const owner = find_slot_owner(element.parent);
18781 if (owner && owner.node.type === 'InlineComponent') {
18782 const name = attribute.get_static_value();
18783 if (!owner.slots.has(name)) {
18784 const child_block = block.child({
18785 comment: create_debugging_comment(element.node, element.renderer.component),
18786 name: element.renderer.component.get_unique_name(`create_${sanitize(name)}_slot`),
18787 type: 'slot'
18788 });
18789 const { scope, lets } = element.node;
18790 const seen = new Set(lets.map(l => l.name.name));
18791 owner.node.lets.forEach(l => {
18792 if (!seen.has(l.name.name))
18793 lets.push(l);
18794 });
18795 owner.slots.set(name, get_slot_definition(child_block, scope, lets));
18796 element.renderer.blocks.push(child_block);
18797 }
18798 element.slot_block = owner.slots.get(name).block;
18799 return element.slot_block;
18800 }
18801 return block;
18802}
18803function find_slot_owner(owner) {
18804 while (owner) {
18805 if (owner.node.type === 'InlineComponent') {
18806 break;
18807 }
18808 if (owner.node.type === 'Element' && /-/.test(owner.node.name)) {
18809 break;
18810 }
18811 owner = owner.parent;
18812 }
18813 return owner;
18814}
18815
18816const events = [
18817 {
18818 event_names: ['input'],
18819 filter: (node, _name) => node.name === 'textarea' ||
18820 node.name === 'input' && !/radio|checkbox|range|file/.test(node.get_static_attribute_value('type'))
18821 },
18822 {
18823 event_names: ['input'],
18824 filter: (node, name) => (name === 'textContent' || name === 'innerHTML') &&
18825 node.attributes.some(attribute => attribute.name === 'contenteditable')
18826 },
18827 {
18828 event_names: ['change'],
18829 filter: (node, _name) => node.name === 'select' ||
18830 node.name === 'input' && /radio|checkbox|file/.test(node.get_static_attribute_value('type'))
18831 },
18832 {
18833 event_names: ['change', 'input'],
18834 filter: (node, _name) => node.name === 'input' && node.get_static_attribute_value('type') === 'range'
18835 },
18836 {
18837 event_names: ['elementresize'],
18838 filter: (_node, name) => dimensions.test(name)
18839 },
18840 // media events
18841 {
18842 event_names: ['timeupdate'],
18843 filter: (node, name) => node.is_media_node() &&
18844 (name === 'currentTime' || name === 'played' || name === 'ended')
18845 },
18846 {
18847 event_names: ['durationchange'],
18848 filter: (node, name) => node.is_media_node() &&
18849 name === 'duration'
18850 },
18851 {
18852 event_names: ['play', 'pause'],
18853 filter: (node, name) => node.is_media_node() &&
18854 name === 'paused'
18855 },
18856 {
18857 event_names: ['progress'],
18858 filter: (node, name) => node.is_media_node() &&
18859 name === 'buffered'
18860 },
18861 {
18862 event_names: ['loadedmetadata'],
18863 filter: (node, name) => node.is_media_node() &&
18864 (name === 'buffered' || name === 'seekable')
18865 },
18866 {
18867 event_names: ['volumechange'],
18868 filter: (node, name) => node.is_media_node() &&
18869 (name === 'volume' || name === 'muted')
18870 },
18871 {
18872 event_names: ['ratechange'],
18873 filter: (node, name) => node.is_media_node() &&
18874 name === 'playbackRate'
18875 },
18876 {
18877 event_names: ['seeking', 'seeked'],
18878 filter: (node, name) => node.is_media_node() &&
18879 (name === 'seeking')
18880 },
18881 {
18882 event_names: ['ended'],
18883 filter: (node, name) => node.is_media_node() &&
18884 name === 'ended'
18885 },
18886 {
18887 event_names: ['resize'],
18888 filter: (node, name) => node.is_media_node() &&
18889 (name === 'videoHeight' || name === 'videoWidth')
18890 },
18891 // details event
18892 {
18893 event_names: ['toggle'],
18894 filter: (node, _name) => node.name === 'details'
18895 }
18896];
18897class ElementWrapper extends Wrapper {
18898 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
18899 super(renderer, block, parent, node);
18900 this.var = {
18901 type: 'Identifier',
18902 name: node.name.replace(/[^a-zA-Z0-9_$]/g, '_')
18903 };
18904 this.void = is_void(node.name);
18905 this.class_dependencies = [];
18906 if (this.node.children.length) {
18907 this.node.lets.forEach(l => {
18908 extract_names(l.value || l.name).forEach(name => {
18909 renderer.add_to_context(name, true);
18910 });
18911 });
18912 }
18913 this.attributes = this.node.attributes.map(attribute => {
18914 if (attribute.name === 'slot') {
18915 block = create_slot_block(attribute, this, block);
18916 }
18917 if (attribute.name === 'style') {
18918 return new StyleAttributeWrapper(this, block, attribute);
18919 }
18920 if (attribute.type === 'Spread') {
18921 return new SpreadAttributeWrapper(this, block, attribute);
18922 }
18923 return new AttributeWrapper(this, block, attribute);
18924 });
18925 // ordinarily, there'll only be one... but we need to handle
18926 // the rare case where an element can have multiple bindings,
18927 // e.g. <audio bind:paused bind:currentTime>
18928 this.bindings = this.node.bindings.map(binding => new BindingWrapper(block, binding, this));
18929 this.event_handlers = this.node.handlers.map(event_handler => new EventHandlerWrapper(event_handler, this));
18930 if (node.intro || node.outro) {
18931 if (node.intro)
18932 block.add_intro(node.intro.is_local);
18933 if (node.outro)
18934 block.add_outro(node.outro.is_local);
18935 }
18936 if (node.animation) {
18937 block.add_animation();
18938 }
18939 // add directive and handler dependencies
18940 [node.animation, node.outro, ...node.actions, ...node.classes].forEach(directive => {
18941 if (directive && directive.expression) {
18942 block.add_dependencies(directive.expression.dependencies);
18943 }
18944 });
18945 node.handlers.forEach(handler => {
18946 if (handler.expression) {
18947 block.add_dependencies(handler.expression.dependencies);
18948 }
18949 });
18950 if (this.parent) {
18951 if (node.actions.length > 0 ||
18952 node.animation ||
18953 node.bindings.length > 0 ||
18954 node.classes.length > 0 ||
18955 node.intro || node.outro ||
18956 node.handlers.length > 0 ||
18957 this.node.name === 'option' ||
18958 renderer.options.dev) {
18959 this.parent.cannot_use_innerhtml(); // need to use add_location
18960 this.parent.not_static_content();
18961 }
18962 }
18963 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
18964 if (this.slot_block) {
18965 block.parent.add_dependencies(block.dependencies);
18966 // appalling hack
18967 const index = block.parent.wrappers.indexOf(this);
18968 block.parent.wrappers.splice(index, 1);
18969 block.wrappers.push(this);
18970 }
18971 }
18972 render(block, parent_node, parent_nodes) {
18973 const { renderer } = this;
18974 if (this.node.name === 'noscript')
18975 return;
18976 if (this.slot_block) {
18977 block = this.slot_block;
18978 }
18979 const node = this.var;
18980 const nodes = parent_nodes && block.get_unique_name(`${this.var.name}_nodes`); // if we're in unclaimable territory, i.e. <head>, parent_nodes is null
18981 const children = x `@children(${this.node.name === 'template' ? x `${node}.content` : node})`;
18982 block.add_variable(node);
18983 const render_statement = this.get_render_statement(block);
18984 block.chunks.create.push(b `${node} = ${render_statement};`);
18985 if (renderer.options.hydratable) {
18986 if (parent_nodes) {
18987 block.chunks.claim.push(b `
18988 ${node} = ${this.get_claim_statement(parent_nodes)};
18989 `);
18990 if (!this.void && this.node.children.length > 0) {
18991 block.chunks.claim.push(b `
18992 var ${nodes} = ${children};
18993 `);
18994 }
18995 }
18996 else {
18997 block.chunks.claim.push(b `${node} = ${render_statement};`);
18998 }
18999 }
19000 if (parent_node) {
19001 block.chunks.mount.push(b `@append(${parent_node}, ${node});`);
19002 if (is_head(parent_node)) {
19003 block.chunks.destroy.push(b `@detach(${node});`);
19004 }
19005 }
19006 else {
19007 block.chunks.mount.push(b `@insert(#target, ${node}, #anchor);`);
19008 // TODO we eventually need to consider what happens to elements
19009 // that belong to the same outgroup as an outroing element...
19010 block.chunks.destroy.push(b `if (detaching) @detach(${node});`);
19011 }
19012 // insert static children with textContent or innerHTML
19013 const can_use_textcontent = this.can_use_textcontent();
19014 if (!this.node.namespace && (this.can_use_innerhtml || can_use_textcontent) && this.fragment.nodes.length > 0) {
19015 if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
19016 block.chunks.create.push(b `${node}.textContent = ${string_literal(this.fragment.nodes[0].data)};`);
19017 }
19018 else {
19019 const state = {
19020 quasi: {
19021 type: 'TemplateElement',
19022 value: { raw: '' }
19023 }
19024 };
19025 const literal = {
19026 type: 'TemplateLiteral',
19027 expressions: [],
19028 quasis: []
19029 };
19030 const can_use_raw_text = !this.can_use_innerhtml && can_use_textcontent;
19031 to_html(this.fragment.nodes, block, literal, state, can_use_raw_text);
19032 literal.quasis.push(state.quasi);
19033 block.chunks.create.push(b `${node}.${this.can_use_innerhtml ? 'innerHTML' : 'textContent'} = ${literal};`);
19034 }
19035 }
19036 else {
19037 this.fragment.nodes.forEach((child) => {
19038 child.render(block, this.node.name === 'template' ? x `${node}.content` : node, nodes);
19039 });
19040 }
19041 const event_handler_or_binding_uses_context = (this.bindings.some(binding => binding.handler.uses_context) ||
19042 this.node.handlers.some(handler => handler.uses_context) ||
19043 this.node.actions.some(action => action.uses_context));
19044 if (event_handler_or_binding_uses_context) {
19045 block.maintain_context = true;
19046 }
19047 this.add_attributes(block);
19048 this.add_directives_in_order(block);
19049 this.add_transitions(block);
19050 this.add_animation(block);
19051 this.add_classes(block);
19052 this.add_manual_style_scoping(block);
19053 if (nodes && this.renderer.options.hydratable && !this.void) {
19054 block.chunks.claim.push(b `${this.node.children.length > 0 ? nodes : children}.forEach(@detach);`);
19055 }
19056 if (renderer.options.dev) {
19057 const loc = renderer.locate(this.node.start);
19058 block.chunks.hydrate.push(b `@add_location(${this.var}, ${renderer.file_var}, ${loc.line - 1}, ${loc.column}, ${this.node.start});`);
19059 }
19060 }
19061 can_use_textcontent() {
19062 return this.is_static_content && this.fragment.nodes.every(node => node.node.type === 'Text' || node.node.type === 'MustacheTag');
19063 }
19064 get_render_statement(block) {
19065 const { name, namespace } = this.node;
19066 if (namespace === namespaces.svg) {
19067 return x `@svg_element("${name}")`;
19068 }
19069 if (namespace) {
19070 return x `@_document.createElementNS("${namespace}", "${name}")`;
19071 }
19072 const is = this.attributes.find(attr => attr.node.name === 'is');
19073 if (is) {
19074 return x `@element_is("${name}", ${is.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`)})`;
19075 }
19076 return x `@element("${name}")`;
19077 }
19078 get_claim_statement(nodes) {
19079 const attributes = this.node.attributes
19080 .filter((attr) => attr.type === 'Attribute')
19081 .map((attr) => p `${attr.name}: true`);
19082 const name = this.node.namespace
19083 ? this.node.name
19084 : this.node.name.toUpperCase();
19085 const svg = this.node.namespace === namespaces.svg ? 1 : null;
19086 return x `@claim_element(${nodes}, "${name}", { ${attributes} }, ${svg})`;
19087 }
19088 add_directives_in_order(block) {
19089 const binding_groups = events
19090 .map(event => ({
19091 events: event.event_names,
19092 bindings: this.bindings
19093 .filter(binding => binding.node.name !== 'this')
19094 .filter(binding => event.filter(this.node, binding.node.name))
19095 }))
19096 .filter(group => group.bindings.length);
19097 const this_binding = this.bindings.find(b => b.node.name === 'this');
19098 function getOrder(item) {
19099 if (item instanceof EventHandlerWrapper) {
19100 return item.node.start;
19101 }
19102 else if (item instanceof BindingWrapper) {
19103 return item.node.start;
19104 }
19105 else if (item instanceof Action) {
19106 return item.start;
19107 }
19108 else {
19109 return item.bindings[0].node.start;
19110 }
19111 }
19112 [
19113 ...binding_groups,
19114 ...this.event_handlers,
19115 this_binding,
19116 ...this.node.actions
19117 ]
19118 .filter(Boolean)
19119 .sort((a, b) => getOrder(a) - getOrder(b))
19120 .forEach(item => {
19121 if (item instanceof EventHandlerWrapper) {
19122 add_event_handler(block, this.var, item);
19123 }
19124 else if (item instanceof BindingWrapper) {
19125 this.add_this_binding(block, item);
19126 }
19127 else if (item instanceof Action) {
19128 add_action(block, this.var, item);
19129 }
19130 else {
19131 this.add_bindings(block, item);
19132 }
19133 });
19134 }
19135 add_bindings(block, binding_group) {
19136 const { renderer } = this;
19137 if (binding_group.bindings.length === 0)
19138 return;
19139 renderer.component.has_reactive_assignments = true;
19140 const lock = binding_group.bindings.some(binding => binding.needs_lock) ?
19141 block.get_unique_name(`${this.var.name}_updating`) :
19142 null;
19143 if (lock)
19144 block.add_variable(lock, x `false`);
19145 const handler = renderer.component.get_unique_name(`${this.var.name}_${binding_group.events.join('_')}_handler`);
19146 renderer.add_to_context(handler.name);
19147 // TODO figure out how to handle locks
19148 const needs_lock = binding_group.bindings.some(binding => binding.needs_lock);
19149 const dependencies = new Set();
19150 const contextual_dependencies = new Set();
19151 binding_group.bindings.forEach(binding => {
19152 // TODO this is a mess
19153 add_to_set(dependencies, binding.get_dependencies());
19154 add_to_set(contextual_dependencies, binding.handler.contextual_dependencies);
19155 binding.render(block, lock);
19156 });
19157 // media bindings — awkward special case. The native timeupdate events
19158 // fire too infrequently, so we need to take matters into our
19159 // own hands
19160 let animation_frame;
19161 if (binding_group.events[0] === 'timeupdate') {
19162 animation_frame = block.get_unique_name(`${this.var.name}_animationframe`);
19163 block.add_variable(animation_frame);
19164 }
19165 const has_local_function = contextual_dependencies.size > 0 || needs_lock || animation_frame;
19166 let callee = renderer.reference(handler);
19167 // TODO dry this out — similar code for event handlers and component bindings
19168 if (has_local_function) {
19169 const args = Array.from(contextual_dependencies).map(name => renderer.reference(name));
19170 // need to create a block-local function that calls an instance-level function
19171 if (animation_frame) {
19172 block.chunks.init.push(b `
19173 function ${handler}() {
19174 @_cancelAnimationFrame(${animation_frame});
19175 if (!${this.var}.paused) {
19176 ${animation_frame} = @raf(${handler});
19177 ${needs_lock && b `${lock} = true;`}
19178 }
19179 ${callee}.call(${this.var}, ${args});
19180 }
19181 `);
19182 }
19183 else {
19184 block.chunks.init.push(b `
19185 function ${handler}() {
19186 ${needs_lock && b `${lock} = true;`}
19187 ${callee}.call(${this.var}, ${args});
19188 }
19189 `);
19190 }
19191 callee = handler;
19192 }
19193 const params = Array.from(contextual_dependencies).map(name => ({
19194 type: 'Identifier',
19195 name
19196 }));
19197 this.renderer.component.partly_hoisted.push(b `
19198 function ${handler}(${params}) {
19199 ${binding_group.bindings.map(b => b.handler.mutation)}
19200 ${Array.from(dependencies)
19201 .filter(dep => dep[0] !== '$')
19202 .filter(dep => !contextual_dependencies.has(dep))
19203 .map(dep => b `${this.renderer.invalidate(dep)};`)}
19204 }
19205 `);
19206 binding_group.events.forEach(name => {
19207 if (name === 'elementresize') {
19208 // special case
19209 const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`);
19210 block.add_variable(resize_listener);
19211 block.chunks.mount.push(b `${resize_listener} = @add_resize_listener(${this.var}, ${callee}.bind(${this.var}));`);
19212 block.chunks.destroy.push(b `${resize_listener}();`);
19213 }
19214 else {
19215 block.event_listeners.push(x `@listen(${this.var}, "${name}", ${callee})`);
19216 }
19217 });
19218 const some_initial_state_is_undefined = binding_group.bindings
19219 .map(binding => x `${binding.snippet} === void 0`)
19220 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
19221 const should_initialise = (this.node.name === 'select' ||
19222 binding_group.bindings.find(binding => {
19223 return (binding.node.name === 'indeterminate' ||
19224 binding.node.name === 'textContent' ||
19225 binding.node.name === 'innerHTML' ||
19226 binding.is_readonly_media_attribute());
19227 }));
19228 if (should_initialise) {
19229 const callback = has_local_function ? handler : x `() => ${callee}.call(${this.var})`;
19230 block.chunks.hydrate.push(b `if (${some_initial_state_is_undefined}) @add_render_callback(${callback});`);
19231 }
19232 if (binding_group.events[0] === 'elementresize') {
19233 block.chunks.hydrate.push(b `@add_render_callback(() => ${callee}.call(${this.var}));`);
19234 }
19235 if (lock) {
19236 block.chunks.update.push(b `${lock} = false;`);
19237 }
19238 }
19239 add_this_binding(block, this_binding) {
19240 const { renderer } = this;
19241 renderer.component.has_reactive_assignments = true;
19242 const binding_callback = bind_this(renderer.component, block, this_binding, this.var);
19243 block.chunks.mount.push(binding_callback);
19244 }
19245 add_attributes(block) {
19246 // Get all the class dependencies first
19247 this.attributes.forEach((attribute) => {
19248 if (attribute.node.name === 'class') {
19249 const dependencies = attribute.node.get_dependencies();
19250 this.class_dependencies.push(...dependencies);
19251 }
19252 });
19253 if (this.node.attributes.some(attr => attr.is_spread)) {
19254 this.add_spread_attributes(block);
19255 return;
19256 }
19257 this.attributes.forEach((attribute) => {
19258 attribute.render(block);
19259 });
19260 }
19261 add_spread_attributes(block) {
19262 const levels = block.get_unique_name(`${this.var.name}_levels`);
19263 const data = block.get_unique_name(`${this.var.name}_data`);
19264 const initial_props = [];
19265 const updates = [];
19266 this.attributes
19267 .forEach(attr => {
19268 const dependencies = attr.node.get_dependencies();
19269 const condition = dependencies.length > 0
19270 ? block.renderer.dirty(dependencies)
19271 : null;
19272 if (attr instanceof SpreadAttributeWrapper) {
19273 const snippet = attr.node.expression.manipulate(block);
19274 initial_props.push(snippet);
19275 updates.push(condition ? x `${condition} && ${snippet}` : snippet);
19276 }
19277 else {
19278 const name = attr.property_name || attr.name;
19279 initial_props.push(x `{ ${name}: ${attr.get_init(block, attr.get_value(block))} }`);
19280 const snippet = x `{ ${name}: ${attr.should_cache ? attr.last : attr.get_value(block)} }`;
19281 updates.push(condition ? x `${attr.get_dom_update_conditions(block, condition)} && ${snippet}` : snippet);
19282 }
19283 });
19284 block.chunks.init.push(b `
19285 let ${levels} = [${initial_props}];
19286
19287 let ${data} = {};
19288 for (let #i = 0; #i < ${levels}.length; #i += 1) {
19289 ${data} = @assign(${data}, ${levels}[#i]);
19290 }
19291 `);
19292 const fn = this.node.namespace === namespaces.svg ? x `@set_svg_attributes` : x `@set_attributes`;
19293 block.chunks.hydrate.push(b `${fn}(${this.var}, ${data});`);
19294 block.chunks.update.push(b `
19295 ${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
19296 ${updates}
19297 ]));
19298 `);
19299 // handle edge cases for elements
19300 if (this.node.name === 'select') {
19301 const dependencies = new Set();
19302 for (const attr of this.attributes) {
19303 for (const dep of attr.node.dependencies) {
19304 dependencies.add(dep);
19305 }
19306 }
19307 block.chunks.mount.push(b `
19308 if (${data}.multiple) @select_options(${this.var}, ${data}.value);
19309 `);
19310 block.chunks.update.push(b `
19311 if (${block.renderer.dirty(Array.from(dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value);
19312 `);
19313 }
19314 else if (this.node.name === 'input' && this.attributes.find(attr => attr.node.name === 'value')) {
19315 const type = this.node.get_static_attribute_value('type');
19316 if (type === null || type === '' || type === 'text' || type === 'email' || type === 'password') {
19317 block.chunks.mount.push(b `
19318 ${this.var}.value = ${data}.value;
19319 `);
19320 block.chunks.update.push(b `
19321 if ('value' in ${data}) {
19322 ${this.var}.value = ${data}.value;
19323 }
19324 `);
19325 }
19326 }
19327 }
19328 add_transitions(block) {
19329 const { intro, outro } = this.node;
19330 if (!intro && !outro)
19331 return;
19332 if (intro === outro) {
19333 // bidirectional transition
19334 const name = block.get_unique_name(`${this.var.name}_transition`);
19335 const snippet = intro.expression
19336 ? intro.expression.manipulate(block)
19337 : x `{}`;
19338 block.add_variable(name);
19339 const fn = this.renderer.reference(intro.name);
19340 const intro_block = b `
19341 @add_render_callback(() => {
19342 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, true);
19343 ${name}.run(1);
19344 });
19345 `;
19346 const outro_block = b `
19347 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, false);
19348 ${name}.run(0);
19349 `;
19350 if (intro.is_local) {
19351 block.chunks.intro.push(b `
19352 if (#local) {
19353 ${intro_block}
19354 }
19355 `);
19356 block.chunks.outro.push(b `
19357 if (#local) {
19358 ${outro_block}
19359 }
19360 `);
19361 }
19362 else {
19363 block.chunks.intro.push(intro_block);
19364 block.chunks.outro.push(outro_block);
19365 }
19366 block.chunks.destroy.push(b `if (detaching && ${name}) ${name}.end();`);
19367 }
19368 else {
19369 const intro_name = intro && block.get_unique_name(`${this.var.name}_intro`);
19370 const outro_name = outro && block.get_unique_name(`${this.var.name}_outro`);
19371 if (intro) {
19372 block.add_variable(intro_name);
19373 const snippet = intro.expression
19374 ? intro.expression.manipulate(block)
19375 : x `{}`;
19376 const fn = this.renderer.reference(intro.name);
19377 let intro_block;
19378 if (outro) {
19379 intro_block = b `
19380 @add_render_callback(() => {
19381 if (${outro_name}) ${outro_name}.end(1);
19382 if (!${intro_name}) ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
19383 ${intro_name}.start();
19384 });
19385 `;
19386 block.chunks.outro.push(b `if (${intro_name}) ${intro_name}.invalidate();`);
19387 }
19388 else {
19389 intro_block = b `
19390 if (!${intro_name}) {
19391 @add_render_callback(() => {
19392 ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
19393 ${intro_name}.start();
19394 });
19395 }
19396 `;
19397 }
19398 if (intro.is_local) {
19399 intro_block = b `
19400 if (#local) {
19401 ${intro_block}
19402 }
19403 `;
19404 }
19405 block.chunks.intro.push(intro_block);
19406 }
19407 if (outro) {
19408 block.add_variable(outro_name);
19409 const snippet = outro.expression
19410 ? outro.expression.manipulate(block)
19411 : x `{}`;
19412 const fn = this.renderer.reference(outro.name);
19413 if (!intro) {
19414 block.chunks.intro.push(b `
19415 if (${outro_name}) ${outro_name}.end(1);
19416 `);
19417 }
19418 // TODO hide elements that have outro'd (unless they belong to a still-outroing
19419 // group) prior to their removal from the DOM
19420 let outro_block = b `
19421 ${outro_name} = @create_out_transition(${this.var}, ${fn}, ${snippet});
19422 `;
19423 if (outro.is_local) {
19424 outro_block = b `
19425 if (#local) {
19426 ${outro_block}
19427 }
19428 `;
19429 }
19430 block.chunks.outro.push(outro_block);
19431 block.chunks.destroy.push(b `if (detaching && ${outro_name}) ${outro_name}.end();`);
19432 }
19433 }
19434 if ((intro && intro.expression && intro.expression.dependencies.size) || (outro && outro.expression && outro.expression.dependencies.size)) {
19435 block.maintain_context = true;
19436 }
19437 }
19438 add_animation(block) {
19439 if (!this.node.animation)
19440 return;
19441 const { outro } = this.node;
19442 const rect = block.get_unique_name('rect');
19443 const stop_animation = block.get_unique_name('stop_animation');
19444 block.add_variable(rect);
19445 block.add_variable(stop_animation, x `@noop`);
19446 block.chunks.measure.push(b `
19447 ${rect} = ${this.var}.getBoundingClientRect();
19448 `);
19449 block.chunks.fix.push(b `
19450 @fix_position(${this.var});
19451 ${stop_animation}();
19452 ${outro && b `@add_transform(${this.var}, ${rect});`}
19453 `);
19454 const params = this.node.animation.expression ? this.node.animation.expression.manipulate(block) : x `{}`;
19455 const name = this.renderer.reference(this.node.animation.name);
19456 block.chunks.animate.push(b `
19457 ${stop_animation}();
19458 ${stop_animation} = @create_animation(${this.var}, ${rect}, ${name}, ${params});
19459 `);
19460 }
19461 add_classes(block) {
19462 const has_spread = this.node.attributes.some(attr => attr.is_spread);
19463 this.node.classes.forEach(class_directive => {
19464 const { expression, name } = class_directive;
19465 let snippet;
19466 let dependencies;
19467 if (expression) {
19468 snippet = expression.manipulate(block);
19469 dependencies = expression.dependencies;
19470 }
19471 else {
19472 snippet = name;
19473 dependencies = new Set([name]);
19474 }
19475 const updater = b `@toggle_class(${this.var}, "${name}", ${snippet});`;
19476 block.chunks.hydrate.push(updater);
19477 if (has_spread) {
19478 block.chunks.update.push(updater);
19479 }
19480 else if ((dependencies && dependencies.size > 0) || this.class_dependencies.length) {
19481 const all_dependencies = this.class_dependencies.concat(...dependencies);
19482 const condition = block.renderer.dirty(all_dependencies);
19483 block.chunks.update.push(b `
19484 if (${condition}) {
19485 ${updater}
19486 }`);
19487 }
19488 });
19489 }
19490 add_manual_style_scoping(block) {
19491 if (this.node.needs_manual_style_scoping) {
19492 const updater = b `@toggle_class(${this.var}, "${this.node.component.stylesheet.id}", true);`;
19493 block.chunks.hydrate.push(updater);
19494 block.chunks.update.push(updater);
19495 }
19496 }
19497}
19498function to_html(wrappers, block, literal, state, can_use_raw_text) {
19499 wrappers.forEach(wrapper => {
19500 if (wrapper instanceof TextWrapper) {
19501 if (wrapper.use_space())
19502 state.quasi.value.raw += ' ';
19503 const parent = wrapper.node.parent;
19504 const raw = parent && (parent.name === 'script' ||
19505 parent.name === 'style' ||
19506 can_use_raw_text);
19507 state.quasi.value.raw += (raw ? wrapper.data : escape_html(wrapper.data))
19508 .replace(/\\/g, '\\\\')
19509 .replace(/`/g, '\\`')
19510 .replace(/\$/g, '\\$');
19511 }
19512 else if (wrapper instanceof MustacheTagWrapper || wrapper instanceof RawMustacheTagWrapper) {
19513 literal.quasis.push(state.quasi);
19514 literal.expressions.push(wrapper.node.expression.manipulate(block));
19515 state.quasi = {
19516 type: 'TemplateElement',
19517 value: { raw: '' }
19518 };
19519 }
19520 else if (wrapper.node.name === 'noscript') ;
19521 else {
19522 // element
19523 state.quasi.value.raw += `<${wrapper.node.name}`;
19524 wrapper.attributes.forEach((attr) => {
19525 state.quasi.value.raw += ` ${fix_attribute_casing(attr.node.name)}="`;
19526 attr.node.chunks.forEach(chunk => {
19527 if (chunk.type === 'Text') {
19528 state.quasi.value.raw += escape_html(chunk.data);
19529 }
19530 else {
19531 literal.quasis.push(state.quasi);
19532 literal.expressions.push(chunk.manipulate(block));
19533 state.quasi = {
19534 type: 'TemplateElement',
19535 value: { raw: '' }
19536 };
19537 }
19538 });
19539 state.quasi.value.raw += '"';
19540 });
19541 if (!wrapper.void) {
19542 state.quasi.value.raw += '>';
19543 to_html(wrapper.fragment.nodes, block, literal, state);
19544 state.quasi.value.raw += `</${wrapper.node.name}>`;
19545 }
19546 else {
19547 state.quasi.value.raw += '/>';
19548 }
19549 }
19550 });
19551}
19552
19553class HeadWrapper extends Wrapper {
19554 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19555 super(renderer, block, parent, node);
19556 this.can_use_innerhtml = false;
19557 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
19558 }
19559 render(block, _parent_node, _parent_nodes) {
19560 let nodes;
19561 if (this.renderer.options.hydratable && this.fragment.nodes.length) {
19562 nodes = block.get_unique_name('head_nodes');
19563 block.chunks.claim.push(b `const ${nodes} = @query_selector_all('[data-svelte="${this.node.id}"]', @_document.head);`);
19564 }
19565 this.fragment.render(block, x `@_document.head`, nodes);
19566 if (nodes && this.renderer.options.hydratable) {
19567 block.chunks.claim.push(b `${nodes}.forEach(@detach);`);
19568 }
19569 }
19570}
19571
19572function is_else_if(node) {
19573 return (node && node.children.length === 1 && node.children[0].type === 'IfBlock');
19574}
19575class IfBlockBranch extends Wrapper {
19576 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19577 super(renderer, block, parent, node);
19578 this.var = null;
19579 const { expression } = node;
19580 const is_else = !expression;
19581 if (expression) {
19582 this.dependencies = expression.dynamic_dependencies();
19583 // TODO is this the right rule? or should any non-reference count?
19584 // const should_cache = !is_reference(expression.node, null) && dependencies.length > 0;
19585 let should_cache = false;
19586 walk(expression.node, {
19587 enter(node) {
19588 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
19589 should_cache = true;
19590 }
19591 }
19592 });
19593 if (should_cache) {
19594 this.condition = block.get_unique_name('show_if');
19595 this.snippet = expression.manipulate(block);
19596 }
19597 else {
19598 this.condition = expression.manipulate(block);
19599 }
19600 }
19601 this.block = block.child({
19602 comment: create_debugging_comment(node, parent.renderer.component),
19603 name: parent.renderer.component.get_unique_name(is_else ? 'create_else_block' : 'create_if_block'),
19604 type: node.expression ? 'if' : 'else'
19605 });
19606 this.fragment = new FragmentWrapper(renderer, this.block, node.children, parent, strip_whitespace, next_sibling);
19607 this.is_dynamic = this.block.dependencies.size > 0;
19608 }
19609}
19610class IfBlockWrapper extends Wrapper {
19611 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19612 super(renderer, block, parent, node);
19613 this.needs_update = false;
19614 this.var = { type: 'Identifier', name: 'if_block' };
19615 this.cannot_use_innerhtml();
19616 this.not_static_content();
19617 this.branches = [];
19618 const blocks = [];
19619 let is_dynamic = false;
19620 let has_intros = false;
19621 let has_outros = false;
19622 const create_branches = (node) => {
19623 const branch = new IfBlockBranch(renderer, block, this, node, strip_whitespace, next_sibling);
19624 this.branches.push(branch);
19625 blocks.push(branch.block);
19626 block.add_dependencies(node.expression.dependencies);
19627 if (branch.block.dependencies.size > 0) {
19628 // the condition, or its contents, is dynamic
19629 is_dynamic = true;
19630 block.add_dependencies(branch.block.dependencies);
19631 }
19632 if (branch.dependencies && branch.dependencies.length > 0) {
19633 // the condition itself is dynamic
19634 this.needs_update = true;
19635 }
19636 if (branch.block.has_intros)
19637 has_intros = true;
19638 if (branch.block.has_outros)
19639 has_outros = true;
19640 if (is_else_if(node.else)) {
19641 create_branches(node.else.children[0]);
19642 }
19643 else if (node.else) {
19644 const branch = new IfBlockBranch(renderer, block, this, node.else, strip_whitespace, next_sibling);
19645 this.branches.push(branch);
19646 blocks.push(branch.block);
19647 if (branch.block.dependencies.size > 0) {
19648 is_dynamic = true;
19649 block.add_dependencies(branch.block.dependencies);
19650 }
19651 if (branch.block.has_intros)
19652 has_intros = true;
19653 if (branch.block.has_outros)
19654 has_outros = true;
19655 }
19656 };
19657 create_branches(this.node);
19658 blocks.forEach(block => {
19659 block.has_update_method = is_dynamic;
19660 block.has_intro_method = has_intros;
19661 block.has_outro_method = has_outros;
19662 });
19663 renderer.blocks.push(...blocks);
19664 }
19665 render(block, parent_node, parent_nodes) {
19666 const name = this.var;
19667 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
19668 const anchor = needs_anchor
19669 ? block.get_unique_name(`${this.var.name}_anchor`)
19670 : (this.next && this.next.var) || 'null';
19671 const has_else = !(this.branches[this.branches.length - 1].condition);
19672 const if_exists_condition = has_else ? null : name;
19673 const dynamic = this.branches[0].block.has_update_method; // can use [0] as proxy for all, since they necessarily have the same value
19674 const has_intros = this.branches[0].block.has_intro_method;
19675 const has_outros = this.branches[0].block.has_outro_method;
19676 const has_transitions = has_intros || has_outros;
19677 const vars = { name, anchor, if_exists_condition, has_else, has_transitions };
19678 const detaching = parent_node && !is_head(parent_node) ? null : 'detaching';
19679 if (this.node.else) {
19680 this.branches.forEach(branch => {
19681 if (branch.snippet)
19682 block.add_variable(branch.condition);
19683 });
19684 if (has_outros) {
19685 this.render_compound_with_outros(block, parent_node, parent_nodes, dynamic, vars, detaching);
19686 block.chunks.outro.push(b `@transition_out(${name});`);
19687 }
19688 else {
19689 this.render_compound(block, parent_node, parent_nodes, dynamic, vars, detaching);
19690 }
19691 }
19692 else {
19693 this.render_simple(block, parent_node, parent_nodes, dynamic, vars, detaching);
19694 if (has_outros) {
19695 block.chunks.outro.push(b `@transition_out(${name});`);
19696 }
19697 }
19698 if (if_exists_condition) {
19699 block.chunks.create.push(b `if (${if_exists_condition}) ${name}.c();`);
19700 }
19701 else {
19702 block.chunks.create.push(b `${name}.c();`);
19703 }
19704 if (parent_nodes && this.renderer.options.hydratable) {
19705 if (if_exists_condition) {
19706 block.chunks.claim.push(b `if (${if_exists_condition}) ${name}.l(${parent_nodes});`);
19707 }
19708 else {
19709 block.chunks.claim.push(b `${name}.l(${parent_nodes});`);
19710 }
19711 }
19712 if (has_intros || has_outros) {
19713 block.chunks.intro.push(b `@transition_in(${name});`);
19714 }
19715 if (needs_anchor) {
19716 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
19717 }
19718 this.branches.forEach(branch => {
19719 branch.fragment.render(branch.block, null, x `#nodes`);
19720 });
19721 }
19722 render_compound(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, if_exists_condition, has_transitions }, detaching) {
19723 const select_block_type = this.renderer.component.get_unique_name('select_block_type');
19724 const current_block_type = block.get_unique_name('current_block_type');
19725 const get_block = has_else
19726 ? x `${current_block_type}(#ctx)`
19727 : x `${current_block_type} && ${current_block_type}(#ctx)`;
19728 if (this.needs_update) {
19729 block.chunks.init.push(b `
19730 function ${select_block_type}(#ctx, #dirty) {
19731 ${this.branches.map(({ dependencies, condition, snippet, block }) => condition
19732 ? b `
19733 ${snippet && (dependencies.length > 0
19734 ? b `if (${condition} == null || ${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
19735 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
19736 if (${condition}) return ${block.name};`
19737 : b `return ${block.name};`)}
19738 }
19739 `);
19740 }
19741 else {
19742 block.chunks.init.push(b `
19743 function ${select_block_type}(#ctx, #dirty) {
19744 ${this.branches.map(({ condition, snippet, block }) => condition
19745 ? b `if (${snippet || condition}) return ${block.name};`
19746 : b `return ${block.name};`)}
19747 }
19748 `);
19749 }
19750 block.chunks.init.push(b `
19751 let ${current_block_type} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
19752 let ${name} = ${get_block};
19753 `);
19754 const initial_mount_node = parent_node || '#target';
19755 const anchor_node = parent_node ? 'null' : '#anchor';
19756 if (if_exists_condition) {
19757 block.chunks.mount.push(b `if (${if_exists_condition}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
19758 }
19759 else {
19760 block.chunks.mount.push(b `${name}.m(${initial_mount_node}, ${anchor_node});`);
19761 }
19762 if (this.needs_update) {
19763 const update_mount_node = this.get_update_mount_node(anchor);
19764 const change_block = b `
19765 ${if_exists_condition ? b `if (${if_exists_condition}) ${name}.d(1)` : b `${name}.d(1)`};
19766 ${name} = ${get_block};
19767 if (${name}) {
19768 ${name}.c();
19769 ${has_transitions && b `@transition_in(${name}, 1);`}
19770 ${name}.m(${update_mount_node}, ${anchor});
19771 }
19772 `;
19773 if (dynamic) {
19774 block.chunks.update.push(b `
19775 if (${current_block_type} === (${current_block_type} = ${select_block_type}(#ctx, #dirty)) && ${name}) {
19776 ${name}.p(#ctx, #dirty);
19777 } else {
19778 ${change_block}
19779 }
19780 `);
19781 }
19782 else {
19783 block.chunks.update.push(b `
19784 if (${current_block_type} !== (${current_block_type} = ${select_block_type}(#ctx, #dirty))) {
19785 ${change_block}
19786 }
19787 `);
19788 }
19789 }
19790 else if (dynamic) {
19791 if (if_exists_condition) {
19792 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
19793 }
19794 else {
19795 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
19796 }
19797 }
19798 if (if_exists_condition) {
19799 block.chunks.destroy.push(b `
19800 if (${if_exists_condition}) {
19801 ${name}.d(${detaching});
19802 }
19803 `);
19804 }
19805 else {
19806 block.chunks.destroy.push(b `
19807 ${name}.d(${detaching});
19808 `);
19809 }
19810 }
19811 // if any of the siblings have outros, we need to keep references to the blocks
19812 // (TODO does this only apply to bidi transitions?)
19813 render_compound_with_outros(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, has_transitions, if_exists_condition }, detaching) {
19814 const select_block_type = this.renderer.component.get_unique_name('select_block_type');
19815 const current_block_type_index = block.get_unique_name('current_block_type_index');
19816 const previous_block_index = block.get_unique_name('previous_block_index');
19817 const if_block_creators = block.get_unique_name('if_block_creators');
19818 const if_blocks = block.get_unique_name('if_blocks');
19819 const if_current_block_type_index = has_else
19820 ? nodes => nodes
19821 : nodes => b `if (~${current_block_type_index}) { ${nodes} }`;
19822 block.add_variable(current_block_type_index);
19823 block.add_variable(name);
19824 block.chunks.init.push(b `
19825 const ${if_block_creators} = [
19826 ${this.branches.map(branch => branch.block.name)}
19827 ];
19828
19829 const ${if_blocks} = [];
19830
19831 ${this.needs_update
19832 ? b `
19833 function ${select_block_type}(#ctx, #dirty) {
19834 ${this.branches.map(({ dependencies, condition, snippet }, i) => condition
19835 ? b `
19836 ${snippet && (dependencies.length > 0
19837 ? b `if (${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
19838 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
19839 if (${condition}) return ${i};`
19840 : b `return ${i};`)}
19841 ${!has_else && b `return -1;`}
19842 }
19843 `
19844 : b `
19845 function ${select_block_type}(#ctx, #dirty) {
19846 ${this.branches.map(({ condition, snippet }, i) => condition
19847 ? b `if (${snippet || condition}) return ${i};`
19848 : b `return ${i};`)}
19849 ${!has_else && b `return -1;`}
19850 }
19851 `}
19852 `);
19853 if (has_else) {
19854 block.chunks.init.push(b `
19855 ${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
19856 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19857 `);
19858 }
19859 else {
19860 block.chunks.init.push(b `
19861 if (~(${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}))) {
19862 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19863 }
19864 `);
19865 }
19866 const initial_mount_node = parent_node || '#target';
19867 const anchor_node = parent_node ? 'null' : '#anchor';
19868 block.chunks.mount.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].m(${initial_mount_node}, ${anchor_node});`));
19869 if (this.needs_update) {
19870 const update_mount_node = this.get_update_mount_node(anchor);
19871 const destroy_old_block = b `
19872 @group_outros();
19873 @transition_out(${if_blocks}[${previous_block_index}], 1, 1, () => {
19874 ${if_blocks}[${previous_block_index}] = null;
19875 });
19876 @check_outros();
19877 `;
19878 const create_new_block = b `
19879 ${name} = ${if_blocks}[${current_block_type_index}];
19880 if (!${name}) {
19881 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19882 ${name}.c();
19883 } else {
19884 ${name}.p(#ctx, #dirty);
19885 }
19886 ${has_transitions && b `@transition_in(${name}, 1);`}
19887 ${name}.m(${update_mount_node}, ${anchor});
19888 `;
19889 const change_block = has_else
19890 ? b `
19891 ${destroy_old_block}
19892
19893 ${create_new_block}
19894 `
19895 : b `
19896 if (${name}) {
19897 ${destroy_old_block}
19898 }
19899
19900 if (~${current_block_type_index}) {
19901 ${create_new_block}
19902 } else {
19903 ${name} = null;
19904 }
19905 `;
19906 if (dynamic) {
19907 block.chunks.update.push(b `
19908 let ${previous_block_index} = ${current_block_type_index};
19909 ${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
19910 if (${current_block_type_index} === ${previous_block_index}) {
19911 ${if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].p(#ctx, #dirty);`)}
19912 } else {
19913 ${change_block}
19914 }
19915 `);
19916 }
19917 else {
19918 block.chunks.update.push(b `
19919 let ${previous_block_index} = ${current_block_type_index};
19920 ${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
19921 if (${current_block_type_index} !== ${previous_block_index}) {
19922 ${change_block}
19923 }
19924 `);
19925 }
19926 }
19927 else if (dynamic) {
19928 if (if_exists_condition) {
19929 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
19930 }
19931 else {
19932 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
19933 }
19934 }
19935 block.chunks.destroy.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].d(${detaching});`));
19936 }
19937 render_simple(block, parent_node, _parent_nodes, dynamic, { name, anchor, if_exists_condition, has_transitions }, detaching) {
19938 const branch = this.branches[0];
19939 if (branch.snippet)
19940 block.add_variable(branch.condition, branch.snippet);
19941 block.chunks.init.push(b `
19942 let ${name} = ${branch.condition} && ${branch.block.name}(#ctx);
19943 `);
19944 const initial_mount_node = parent_node || '#target';
19945 const anchor_node = parent_node ? 'null' : '#anchor';
19946 block.chunks.mount.push(b `if (${name}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
19947 if (branch.dependencies.length > 0) {
19948 const update_mount_node = this.get_update_mount_node(anchor);
19949 const enter = b `
19950 if (${name}) {
19951 ${dynamic && b `${name}.p(#ctx, #dirty);`}
19952 ${has_transitions &&
19953 b `if (${block.renderer.dirty(branch.dependencies)}) {
19954 @transition_in(${name}, 1);
19955 }`}
19956 } else {
19957 ${name} = ${branch.block.name}(#ctx);
19958 ${name}.c();
19959 ${has_transitions && b `@transition_in(${name}, 1);`}
19960 ${name}.m(${update_mount_node}, ${anchor});
19961 }
19962 `;
19963 if (branch.snippet) {
19964 block.chunks.update.push(b `if (${block.renderer.dirty(branch.dependencies)}) ${branch.condition} = ${branch.snippet}`);
19965 }
19966 // no `p()` here — we don't want to update outroing nodes,
19967 // as that will typically result in glitching
19968 if (branch.block.has_outro_method) {
19969 block.chunks.update.push(b `
19970 if (${branch.condition}) {
19971 ${enter}
19972 } else if (${name}) {
19973 @group_outros();
19974 @transition_out(${name}, 1, 1, () => {
19975 ${name} = null;
19976 });
19977 @check_outros();
19978 }
19979 `);
19980 }
19981 else {
19982 block.chunks.update.push(b `
19983 if (${branch.condition}) {
19984 ${enter}
19985 } else if (${name}) {
19986 ${name}.d(1);
19987 ${name} = null;
19988 }
19989 `);
19990 }
19991 }
19992 else if (dynamic) {
19993 block.chunks.update.push(b `
19994 if (${branch.condition}) ${name}.p(#ctx, #dirty);
19995 `);
19996 }
19997 if (if_exists_condition) {
19998 block.chunks.destroy.push(b `
19999 if (${if_exists_condition}) ${name}.d(${detaching});
20000 `);
20001 }
20002 else {
20003 block.chunks.destroy.push(b `
20004 ${name}.d(${detaching});
20005 `);
20006 }
20007 }
20008 get_initial_dirty_bit() {
20009 const _this = this;
20010 // TODO: context-overflow make it less gross
20011 const val = x `-1`;
20012 return {
20013 get type() {
20014 return _this.renderer.context_overflow ? 'ArrayExpression' : 'UnaryExpression';
20015 },
20016 // as [-1]
20017 elements: [val],
20018 // as -1
20019 operator: val.operator,
20020 prefix: val.prefix,
20021 argument: val.argument
20022 };
20023 }
20024}
20025
20026class KeyBlockWrapper extends Wrapper {
20027 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20028 super(renderer, block, parent, node);
20029 this.var = { type: 'Identifier', name: 'key_block' };
20030 this.cannot_use_innerhtml();
20031 this.not_static_content();
20032 this.dependencies = node.expression.dynamic_dependencies();
20033 if (this.dependencies.length) {
20034 block = block.child({
20035 comment: create_debugging_comment(node, renderer.component),
20036 name: renderer.component.get_unique_name('create_key_block'),
20037 type: 'key'
20038 });
20039 renderer.blocks.push(block);
20040 }
20041 this.block = block;
20042 this.fragment = new FragmentWrapper(renderer, this.block, node.children, parent, strip_whitespace, next_sibling);
20043 }
20044 render(block, parent_node, parent_nodes) {
20045 if (this.dependencies.length === 0) {
20046 this.render_static_key(block, parent_node, parent_nodes);
20047 }
20048 else {
20049 this.render_dynamic_key(block, parent_node, parent_nodes);
20050 }
20051 }
20052 render_static_key(_block, parent_node, parent_nodes) {
20053 this.fragment.render(this.block, parent_node, parent_nodes);
20054 }
20055 render_dynamic_key(block, parent_node, parent_nodes) {
20056 this.fragment.render(this.block, null, x `#nodes`);
20057 const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
20058 const dynamic = this.block.has_update_method;
20059 const previous_key = block.get_unique_name('previous_key');
20060 const snippet = this.node.expression.manipulate(block);
20061 block.add_variable(previous_key, snippet);
20062 const not_equal = this.renderer.component.component_options.immutable ? x `@not_equal` : x `@safe_not_equal`;
20063 const condition = x `${this.renderer.dirty(this.dependencies)} && ${not_equal}(${previous_key}, ${previous_key} = ${snippet})`;
20064 block.chunks.init.push(b `
20065 let ${this.var} = ${this.block.name}(#ctx);
20066 `);
20067 block.chunks.create.push(b `${this.var}.c();`);
20068 if (this.renderer.options.hydratable) {
20069 block.chunks.claim.push(b `${this.var}.l(${parent_nodes});`);
20070 }
20071 block.chunks.mount.push(b `${this.var}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});`);
20072 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
20073 const body = b `
20074 ${has_transitions
20075 ? b `
20076 @group_outros();
20077 @transition_out(${this.var}, 1, 1, @noop);
20078 @check_outros();
20079 `
20080 : b `${this.var}.d(1);`}
20081 ${this.var} = ${this.block.name}(#ctx);
20082 ${this.var}.c();
20083 ${has_transitions && b `@transition_in(${this.var})`}
20084 ${this.var}.m(${this.get_update_mount_node(anchor)}, ${anchor});
20085 `;
20086 if (dynamic) {
20087 block.chunks.update.push(b `
20088 if (${condition}) {
20089 ${body}
20090 } else {
20091 ${this.var}.p(#ctx, #dirty);
20092 }
20093 `);
20094 }
20095 else {
20096 block.chunks.update.push(b `
20097 if (${condition}) {
20098 ${body}
20099 }
20100 `);
20101 }
20102 if (has_transitions) {
20103 block.chunks.intro.push(b `@transition_in(${this.var})`);
20104 block.chunks.outro.push(b `@transition_out(${this.var})`);
20105 }
20106 block.chunks.destroy.push(b `${this.var}.d(detaching)`);
20107 }
20108}
20109
20110function string_to_member_expression(name) {
20111 const parts = name.split('.');
20112 let node = {
20113 type: 'Identifier',
20114 name: parts[0]
20115 };
20116 for (let i = 1; i < parts.length; i++) {
20117 node = {
20118 type: 'MemberExpression',
20119 object: node,
20120 property: { type: 'Identifier', name: parts[i] }
20121 };
20122 }
20123 return node;
20124}
20125
20126class InlineComponentWrapper extends Wrapper {
20127 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20128 super(renderer, block, parent, node);
20129 this.slots = new Map();
20130 this.cannot_use_innerhtml();
20131 this.not_static_content();
20132 if (this.node.expression) {
20133 block.add_dependencies(this.node.expression.dependencies);
20134 }
20135 this.node.attributes.forEach(attr => {
20136 block.add_dependencies(attr.dependencies);
20137 });
20138 this.node.bindings.forEach(binding => {
20139 if (binding.is_contextual) {
20140 mark_each_block_bindings(this, binding);
20141 }
20142 block.add_dependencies(binding.expression.dependencies);
20143 });
20144 this.node.handlers.forEach(handler => {
20145 if (handler.expression) {
20146 block.add_dependencies(handler.expression.dependencies);
20147 }
20148 });
20149 this.var = {
20150 type: 'Identifier',
20151 name: (this.node.name === 'svelte:self' ? renderer.component.name.name :
20152 this.node.name === 'svelte:component' ? 'switch_instance' :
20153 sanitize(this.node.name)).toLowerCase()
20154 };
20155 if (this.node.children.length) {
20156 this.node.lets.forEach(l => {
20157 extract_names(l.value || l.name).forEach(name => {
20158 renderer.add_to_context(name, true);
20159 });
20160 });
20161 const default_slot = block.child({
20162 comment: create_debugging_comment(node, renderer.component),
20163 name: renderer.component.get_unique_name('create_default_slot'),
20164 type: 'slot'
20165 });
20166 this.renderer.blocks.push(default_slot);
20167 this.slots.set('default', get_slot_definition(default_slot, this.node.scope, this.node.lets));
20168 this.fragment = new FragmentWrapper(renderer, default_slot, node.children, this, strip_whitespace, next_sibling);
20169 const dependencies = new Set();
20170 // TODO is this filtering necessary? (I *think* so)
20171 default_slot.dependencies.forEach(name => {
20172 if (!this.node.scope.is_let(name)) {
20173 dependencies.add(name);
20174 }
20175 });
20176 block.add_dependencies(dependencies);
20177 }
20178 block.add_outro();
20179 }
20180 warn_if_reactive() {
20181 const { name } = this.node;
20182 const variable = this.renderer.component.var_lookup.get(name);
20183 if (!variable) {
20184 return;
20185 }
20186 if (variable.reassigned || variable.export_name || variable.is_reactive_dependency) {
20187 this.renderer.component.warn(this.node, {
20188 code: 'reactive-component',
20189 message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`
20190 });
20191 }
20192 }
20193 render(block, parent_node, parent_nodes) {
20194 this.warn_if_reactive();
20195 const { renderer } = this;
20196 const { component } = renderer;
20197 const name = this.var;
20198 block.add_variable(name);
20199 const component_opts = x `{}`;
20200 const statements = [];
20201 const updates = [];
20202 if (this.fragment) {
20203 this.renderer.add_to_context('$$scope', true);
20204 const default_slot = this.slots.get('default');
20205 this.fragment.nodes.forEach((child) => {
20206 child.render(default_slot.block, null, x `#nodes`);
20207 });
20208 }
20209 let props;
20210 const name_changes = block.get_unique_name(`${name.name}_changes`);
20211 const uses_spread = !!this.node.attributes.find(a => a.is_spread);
20212 // removing empty slot
20213 for (const slot of this.slots.keys()) {
20214 if (!this.slots.get(slot).block.has_content()) {
20215 this.renderer.remove_block(this.slots.get(slot).block);
20216 this.slots.delete(slot);
20217 }
20218 }
20219 const initial_props = this.slots.size > 0
20220 ? [
20221 p `$$slots: {
20222 ${Array.from(this.slots).map(([name, slot]) => {
20223 return p `${name}: [${slot.block.name}, ${slot.get_context || null}, ${slot.get_changes || null}]`;
20224 })}
20225 }`,
20226 p `$$scope: {
20227 ctx: #ctx
20228 }`
20229 ]
20230 : [];
20231 const attribute_object = uses_spread
20232 ? x `{ ${initial_props} }`
20233 : x `{
20234 ${this.node.attributes.map(attr => p `${attr.name}: ${attr.get_value(block)}`)},
20235 ${initial_props}
20236 }`;
20237 if (this.node.attributes.length || this.node.bindings.length || initial_props.length) {
20238 if (!uses_spread && this.node.bindings.length === 0) {
20239 component_opts.properties.push(p `props: ${attribute_object}`);
20240 }
20241 else {
20242 props = block.get_unique_name(`${name.name}_props`);
20243 component_opts.properties.push(p `props: ${props}`);
20244 }
20245 }
20246 if (component.compile_options.dev) {
20247 // TODO this is a terrible hack, but without it the component
20248 // will complain that options.target is missing. This would
20249 // work better if components had separate public and private
20250 // APIs
20251 component_opts.properties.push(p `$$inline: true`);
20252 }
20253 const fragment_dependencies = new Set(this.fragment ? ['$$scope'] : []);
20254 this.slots.forEach(slot => {
20255 slot.block.dependencies.forEach(name => {
20256 const is_let = slot.scope.is_let(name);
20257 const variable = renderer.component.var_lookup.get(name);
20258 if (is_let || is_dynamic$1(variable))
20259 fragment_dependencies.add(name);
20260 });
20261 });
20262 const dynamic_attributes = this.node.attributes.filter(a => a.get_dependencies().length > 0);
20263 if (!uses_spread && (dynamic_attributes.length > 0 || this.node.bindings.length > 0 || fragment_dependencies.size > 0)) {
20264 updates.push(b `const ${name_changes} = {};`);
20265 }
20266 if (this.node.attributes.length) {
20267 if (uses_spread) {
20268 const levels = block.get_unique_name(`${this.var.name}_spread_levels`);
20269 const initial_props = [];
20270 const changes = [];
20271 const all_dependencies = new Set();
20272 this.node.attributes.forEach(attr => {
20273 add_to_set(all_dependencies, attr.dependencies);
20274 });
20275 this.node.attributes.forEach((attr, i) => {
20276 const { name, dependencies } = attr;
20277 const condition = dependencies.size > 0 && (dependencies.size !== all_dependencies.size)
20278 ? renderer.dirty(Array.from(dependencies))
20279 : null;
20280 const unchanged = dependencies.size === 0;
20281 let change_object;
20282 if (attr.is_spread) {
20283 const value = attr.expression.manipulate(block);
20284 initial_props.push(value);
20285 let value_object = value;
20286 if (attr.expression.node.type !== 'ObjectExpression') {
20287 value_object = x `@get_spread_object(${value})`;
20288 }
20289 change_object = value_object;
20290 }
20291 else {
20292 const obj = x `{ ${name}: ${attr.get_value(block)} }`;
20293 initial_props.push(obj);
20294 change_object = obj;
20295 }
20296 changes.push(unchanged
20297 ? x `${levels}[${i}]`
20298 : condition
20299 ? x `${condition} && ${change_object}`
20300 : change_object);
20301 });
20302 block.chunks.init.push(b `
20303 const ${levels} = [
20304 ${initial_props}
20305 ];
20306 `);
20307 statements.push(b `
20308 for (let #i = 0; #i < ${levels}.length; #i += 1) {
20309 ${props} = @assign(${props}, ${levels}[#i]);
20310 }
20311 `);
20312 if (all_dependencies.size) {
20313 const condition = renderer.dirty(Array.from(all_dependencies));
20314 updates.push(b `
20315 const ${name_changes} = ${condition} ? @get_spread_update(${levels}, [
20316 ${changes}
20317 ]) : {}
20318 `);
20319 }
20320 else {
20321 updates.push(b `
20322 const ${name_changes} = {};
20323 `);
20324 }
20325 }
20326 else {
20327 dynamic_attributes.forEach((attribute) => {
20328 const dependencies = attribute.get_dependencies();
20329 if (dependencies.length > 0) {
20330 const condition = renderer.dirty(dependencies);
20331 updates.push(b `
20332 if (${condition}) ${name_changes}.${attribute.name} = ${attribute.get_value(block)};
20333 `);
20334 }
20335 });
20336 }
20337 }
20338 if (fragment_dependencies.size > 0) {
20339 updates.push(b `
20340 if (${renderer.dirty(Array.from(fragment_dependencies))}) {
20341 ${name_changes}.$$scope = { dirty: #dirty, ctx: #ctx };
20342 }`);
20343 }
20344 const munged_bindings = this.node.bindings.map(binding => {
20345 component.has_reactive_assignments = true;
20346 if (binding.name === 'this') {
20347 return bind_this(component, block, new BindingWrapper(block, binding, this), this.var);
20348 }
20349 const id = component.get_unique_name(`${this.var.name}_${binding.name}_binding`);
20350 renderer.add_to_context(id.name);
20351 const callee = renderer.reference(id);
20352 const updating = block.get_unique_name(`updating_${binding.name}`);
20353 block.add_variable(updating);
20354 const snippet = binding.expression.manipulate(block);
20355 statements.push(b `
20356 if (${snippet} !== void 0) {
20357 ${props}.${binding.name} = ${snippet};
20358 }`);
20359 updates.push(b `
20360 if (!${updating} && ${renderer.dirty(Array.from(binding.expression.dependencies))}) {
20361 ${updating} = true;
20362 ${name_changes}.${binding.name} = ${snippet};
20363 @add_flush_callback(() => ${updating} = false);
20364 }
20365 `);
20366 const contextual_dependencies = Array.from(binding.expression.contextual_dependencies);
20367 const dependencies = Array.from(binding.expression.dependencies);
20368 let lhs = binding.raw_expression;
20369 if (binding.is_contextual && binding.expression.node.type === 'Identifier') {
20370 // bind:x={y} — we can't just do `y = x`, we need to
20371 // to `array[index] = x;
20372 const { name } = binding.expression.node;
20373 const { object, property, snippet } = block.bindings.get(name);
20374 lhs = snippet;
20375 contextual_dependencies.push(object.name, property.name);
20376 }
20377 const params = [x `#value`];
20378 if (contextual_dependencies.length > 0) {
20379 const args = [];
20380 contextual_dependencies.forEach(name => {
20381 params.push({
20382 type: 'Identifier',
20383 name
20384 });
20385 renderer.add_to_context(name, true);
20386 args.push(renderer.reference(name));
20387 });
20388 block.chunks.init.push(b `
20389 function ${id}(#value) {
20390 ${callee}.call(null, #value, ${args});
20391 }
20392 `);
20393 block.maintain_context = true; // TODO put this somewhere more logical
20394 }
20395 else {
20396 block.chunks.init.push(b `
20397 function ${id}(#value) {
20398 ${callee}.call(null, #value);
20399 }
20400 `);
20401 }
20402 const body = b `
20403 function ${id}(${params}) {
20404 ${lhs} = #value;
20405 ${renderer.invalidate(dependencies[0])};
20406 }
20407 `;
20408 component.partly_hoisted.push(body);
20409 return b `@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
20410 });
20411 const munged_handlers = this.node.handlers.map(handler => {
20412 const event_handler = new EventHandlerWrapper(handler, this);
20413 let snippet = event_handler.get_snippet(block);
20414 if (handler.modifiers.has('once'))
20415 snippet = x `@once(${snippet})`;
20416 return b `${name}.$on("${handler.name}", ${snippet});`;
20417 });
20418 if (this.node.name === 'svelte:component') {
20419 const switch_value = block.get_unique_name('switch_value');
20420 const switch_props = block.get_unique_name('switch_props');
20421 const snippet = this.node.expression.manipulate(block);
20422 block.chunks.init.push(b `
20423 var ${switch_value} = ${snippet};
20424
20425 function ${switch_props}(#ctx) {
20426 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
20427 ${props && b `let ${props} = ${attribute_object};`}`}
20428 ${statements}
20429 return ${component_opts};
20430 }
20431
20432 if (${switch_value}) {
20433 ${name} = new ${switch_value}(${switch_props}(#ctx));
20434
20435 ${munged_bindings}
20436 ${munged_handlers}
20437 }
20438 `);
20439 block.chunks.create.push(b `if (${name}) @create_component(${name}.$$.fragment);`);
20440 if (parent_nodes && this.renderer.options.hydratable) {
20441 block.chunks.claim.push(b `if (${name}) @claim_component(${name}.$$.fragment, ${parent_nodes});`);
20442 }
20443 block.chunks.mount.push(b `
20444 if (${name}) {
20445 @mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20446 }
20447 `);
20448 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
20449 const update_mount_node = this.get_update_mount_node(anchor);
20450 if (updates.length) {
20451 block.chunks.update.push(b `
20452 ${updates}
20453 `);
20454 }
20455 block.chunks.update.push(b `
20456 if (${switch_value} !== (${switch_value} = ${snippet})) {
20457 if (${name}) {
20458 @group_outros();
20459 const old_component = ${name};
20460 @transition_out(old_component.$$.fragment, 1, 0, () => {
20461 @destroy_component(old_component, 1);
20462 });
20463 @check_outros();
20464 }
20465
20466 if (${switch_value}) {
20467 ${name} = new ${switch_value}(${switch_props}(#ctx));
20468
20469 ${munged_bindings}
20470 ${munged_handlers}
20471
20472 @create_component(${name}.$$.fragment);
20473 @transition_in(${name}.$$.fragment, 1);
20474 @mount_component(${name}, ${update_mount_node}, ${anchor});
20475 } else {
20476 ${name} = null;
20477 }
20478 } else if (${switch_value}) {
20479 ${updates.length > 0 && b `${name}.$set(${name_changes});`}
20480 }
20481 `);
20482 block.chunks.intro.push(b `
20483 if (${name}) @transition_in(${name}.$$.fragment, #local);
20484 `);
20485 block.chunks.outro.push(b `if (${name}) @transition_out(${name}.$$.fragment, #local);`);
20486 block.chunks.destroy.push(b `if (${name}) @destroy_component(${name}, ${parent_node ? null : 'detaching'});`);
20487 }
20488 else {
20489 const expression = this.node.name === 'svelte:self'
20490 ? component.name
20491 : this.renderer.reference(string_to_member_expression(this.node.name));
20492 block.chunks.init.push(b `
20493 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
20494 ${props && b `let ${props} = ${attribute_object};`}`}
20495 ${statements}
20496 ${name} = new ${expression}(${component_opts});
20497
20498 ${munged_bindings}
20499 ${munged_handlers}
20500 `);
20501 block.chunks.create.push(b `@create_component(${name}.$$.fragment);`);
20502 if (parent_nodes && this.renderer.options.hydratable) {
20503 block.chunks.claim.push(b `@claim_component(${name}.$$.fragment, ${parent_nodes});`);
20504 }
20505 block.chunks.mount.push(b `@mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});`);
20506 block.chunks.intro.push(b `
20507 @transition_in(${name}.$$.fragment, #local);
20508 `);
20509 if (updates.length) {
20510 block.chunks.update.push(b `
20511 ${updates}
20512 ${name}.$set(${name_changes});
20513 `);
20514 }
20515 block.chunks.destroy.push(b `
20516 @destroy_component(${name}, ${parent_node ? null : 'detaching'});
20517 `);
20518 block.chunks.outro.push(b `@transition_out(${name}.$$.fragment, #local);`);
20519 }
20520 }
20521}
20522
20523function get_slot_data(values, block = null) {
20524 return {
20525 type: 'ObjectExpression',
20526 properties: Array.from(values.values())
20527 .filter(attribute => attribute.name !== 'name')
20528 .map(attribute => {
20529 const value = get_value(block, attribute);
20530 return p `${attribute.name}: ${value}`;
20531 })
20532 };
20533}
20534function get_value(block, attribute) {
20535 if (attribute.is_true)
20536 return x `true`;
20537 if (attribute.chunks.length === 0)
20538 return x `""`;
20539 let value = attribute.chunks
20540 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : (block ? chunk.manipulate(block) : chunk.node))
20541 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20542 if (attribute.chunks.length > 1 && attribute.chunks[0].type !== 'Text') {
20543 value = x `"" + ${value}`;
20544 }
20545 return value;
20546}
20547
20548class SlotWrapper extends Wrapper {
20549 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20550 super(renderer, block, parent, node);
20551 this.fallback = null;
20552 this.var = { type: 'Identifier', name: 'slot' };
20553 this.dependencies = new Set(['$$scope']);
20554 this.cannot_use_innerhtml();
20555 this.not_static_content();
20556 if (this.node.children.length) {
20557 this.fallback = block.child({
20558 comment: create_debugging_comment(this.node.children[0], this.renderer.component),
20559 name: this.renderer.component.get_unique_name('fallback_block'),
20560 type: 'fallback'
20561 });
20562 renderer.blocks.push(this.fallback);
20563 }
20564 if (this.node.values.has('slot')) {
20565 block = create_slot_block(this.node.values.get('slot'), this, block);
20566 }
20567 this.fragment = new FragmentWrapper(renderer, this.fallback, node.children, this, strip_whitespace, next_sibling);
20568 this.node.values.forEach(attribute => {
20569 add_to_set(this.dependencies, attribute.dependencies);
20570 });
20571 block.add_dependencies(this.dependencies);
20572 // we have to do this, just in case
20573 block.add_intro();
20574 block.add_outro();
20575 }
20576 render(block, parent_node, parent_nodes) {
20577 const { renderer } = this;
20578 const { slot_name } = this.node;
20579 if (this.slot_block) {
20580 block = this.slot_block;
20581 }
20582 let get_slot_changes_fn;
20583 let get_slot_context_fn;
20584 if (this.node.values.size > 0) {
20585 get_slot_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_changes`);
20586 get_slot_context_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_context`);
20587 const changes = x `{}`;
20588 const dependencies = new Set();
20589 this.node.values.forEach(attribute => {
20590 attribute.chunks.forEach(chunk => {
20591 if (chunk.dependencies) {
20592 add_to_set(dependencies, chunk.contextual_dependencies);
20593 // add_to_set(dependencies, (chunk as Expression).dependencies);
20594 chunk.dependencies.forEach(name => {
20595 const variable = renderer.component.var_lookup.get(name);
20596 if (variable && !variable.hoistable)
20597 dependencies.add(name);
20598 });
20599 }
20600 });
20601 const dynamic_dependencies = Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name));
20602 if (dynamic_dependencies.length > 0) {
20603 changes.properties.push(p `${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`);
20604 }
20605 });
20606 renderer.blocks.push(b `
20607 const ${get_slot_changes_fn} = #dirty => ${changes};
20608 const ${get_slot_context_fn} = #ctx => ${get_slot_data(this.node.values, block)};
20609 `);
20610 }
20611 else {
20612 get_slot_changes_fn = 'null';
20613 get_slot_context_fn = 'null';
20614 }
20615 let has_fallback = !!this.fallback;
20616 if (this.fallback) {
20617 this.fragment.render(this.fallback, null, x `#nodes`);
20618 has_fallback = this.fallback.has_content();
20619 if (!has_fallback) {
20620 renderer.remove_block(this.fallback);
20621 }
20622 }
20623 const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`);
20624 const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
20625 const slot_or_fallback = has_fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot;
20626 block.chunks.init.push(b `
20627 const ${slot_definition} = ${renderer.reference('#slots')}.${slot_name};
20628 const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn});
20629 ${has_fallback ? b `const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
20630 `);
20631 block.chunks.create.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.c();`);
20632 if (renderer.options.hydratable) {
20633 block.chunks.claim.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});`);
20634 }
20635 block.chunks.mount.push(b `
20636 if (${slot_or_fallback}) {
20637 ${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20638 }
20639 `);
20640 block.chunks.intro.push(b `@transition_in(${slot_or_fallback}, #local);`);
20641 block.chunks.outro.push(b `@transition_out(${slot_or_fallback}, #local);`);
20642 const dynamic_dependencies = Array.from(this.dependencies).filter((name) => this.is_dependency_dynamic(name));
20643 const fallback_dynamic_dependencies = has_fallback
20644 ? Array.from(this.fallback.dependencies).filter((name) => this.is_dependency_dynamic(name))
20645 : [];
20646 const slot_update = b `
20647 if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
20648 @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn});
20649 }
20650 `;
20651 const fallback_update = has_fallback && fallback_dynamic_dependencies.length > 0 && b `
20652 if (${slot_or_fallback} && ${slot_or_fallback}.p && ${renderer.dirty(fallback_dynamic_dependencies)}) {
20653 ${slot_or_fallback}.p(#ctx, #dirty);
20654 }
20655 `;
20656 if (fallback_update) {
20657 block.chunks.update.push(b `
20658 if (${slot}) {
20659 ${slot_update}
20660 } else {
20661 ${fallback_update}
20662 }
20663 `);
20664 }
20665 else {
20666 block.chunks.update.push(b `
20667 if (${slot}) {
20668 ${slot_update}
20669 }
20670 `);
20671 }
20672 block.chunks.destroy.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`);
20673 }
20674 is_dependency_dynamic(name) {
20675 if (name === '$$scope')
20676 return true;
20677 if (this.node.scope.is_let(name))
20678 return true;
20679 if (is_reserved_keyword(name))
20680 return true;
20681 const variable = this.renderer.component.var_lookup.get(name);
20682 return is_dynamic$1(variable);
20683 }
20684}
20685
20686class TitleWrapper extends Wrapper {
20687 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
20688 super(renderer, block, parent, node);
20689 }
20690 render(block, _parent_node, _parent_nodes) {
20691 const is_dynamic = !!this.node.children.find(node => node.type !== 'Text');
20692 if (is_dynamic) {
20693 let value;
20694 const all_dependencies = new Set();
20695 // TODO some of this code is repeated in Tag.ts — would be good to
20696 // DRY it out if that's possible without introducing crazy indirection
20697 if (this.node.children.length === 1) {
20698 // single {tag} — may be a non-string
20699 // @ts-ignore todo: check this
20700 const { expression } = this.node.children[0];
20701 value = expression.manipulate(block);
20702 add_to_set(all_dependencies, expression.dependencies);
20703 }
20704 else {
20705 // '{foo} {bar}' — treat as string concatenation
20706 value = this.node.children
20707 .map(chunk => {
20708 if (chunk.type === 'Text')
20709 return string_literal(chunk.data);
20710 chunk.expression.dependencies.forEach(d => {
20711 all_dependencies.add(d);
20712 });
20713 return chunk.expression.manipulate(block);
20714 })
20715 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20716 if (this.node.children[0].type !== 'Text') {
20717 value = x `"" + ${value}`;
20718 }
20719 }
20720 const last = this.node.should_cache && block.get_unique_name('title_value');
20721 if (this.node.should_cache)
20722 block.add_variable(last);
20723 const init = this.node.should_cache ? x `${last} = ${value}` : value;
20724 block.chunks.init.push(b `@_document.title = ${init};`);
20725 const updater = b `@_document.title = ${this.node.should_cache ? last : value};`;
20726 if (all_dependencies.size) {
20727 const dependencies = Array.from(all_dependencies);
20728 let condition = block.renderer.dirty(dependencies);
20729 if (block.has_outros) {
20730 condition = x `!#current || ${condition}`;
20731 }
20732 if (this.node.should_cache) {
20733 condition = x `${condition} && (${last} !== (${last} = ${value}))`;
20734 }
20735 block.chunks.update.push(b `
20736 if (${condition}) {
20737 ${updater}
20738 }`);
20739 }
20740 }
20741 else {
20742 const value = this.node.children.length > 0
20743 ? string_literal(this.node.children[0].data)
20744 : x `""`;
20745 block.chunks.hydrate.push(b `@_document.title = ${value};`);
20746 }
20747 }
20748}
20749
20750const associated_events = {
20751 innerWidth: 'resize',
20752 innerHeight: 'resize',
20753 outerWidth: 'resize',
20754 outerHeight: 'resize',
20755 scrollX: 'scroll',
20756 scrollY: 'scroll'
20757};
20758const properties = {
20759 scrollX: 'pageXOffset',
20760 scrollY: 'pageYOffset'
20761};
20762const readonly = new Set([
20763 'innerWidth',
20764 'innerHeight',
20765 'outerWidth',
20766 'outerHeight',
20767 'online'
20768]);
20769class WindowWrapper extends Wrapper {
20770 constructor(renderer, block, parent, node) {
20771 super(renderer, block, parent, node);
20772 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
20773 }
20774 render(block, _parent_node, _parent_nodes) {
20775 const { renderer } = this;
20776 const { component } = renderer;
20777 const events = {};
20778 const bindings = {};
20779 add_actions(block, '@_window', this.node.actions);
20780 add_event_handlers(block, '@_window', this.handlers);
20781 this.node.bindings.forEach(binding => {
20782 // in dev mode, throw if read-only values are written to
20783 if (readonly.has(binding.name)) {
20784 renderer.readonly.add(binding.expression.node.name);
20785 }
20786 bindings[binding.name] = binding.expression.node.name;
20787 // bind:online is a special case, we need to listen for two separate events
20788 if (binding.name === 'online')
20789 return;
20790 const associated_event = associated_events[binding.name];
20791 const property = properties[binding.name] || binding.name;
20792 if (!events[associated_event])
20793 events[associated_event] = [];
20794 events[associated_event].push({
20795 name: binding.expression.node.name,
20796 value: property
20797 });
20798 });
20799 const scrolling = block.get_unique_name('scrolling');
20800 const clear_scrolling = block.get_unique_name('clear_scrolling');
20801 const scrolling_timeout = block.get_unique_name('scrolling_timeout');
20802 Object.keys(events).forEach(event => {
20803 const id = block.get_unique_name(`onwindow${event}`);
20804 const props = events[event];
20805 renderer.add_to_context(id.name);
20806 const fn = renderer.reference(id.name);
20807 if (event === 'scroll') {
20808 // TODO other bidirectional bindings...
20809 block.add_variable(scrolling, x `false`);
20810 block.add_variable(clear_scrolling, x `() => { ${scrolling} = false }`);
20811 block.add_variable(scrolling_timeout);
20812 const condition = bindings.scrollX && bindings.scrollY
20813 ? x `"${bindings.scrollX}" in this._state || "${bindings.scrollY}" in this._state`
20814 : x `"${bindings.scrollX || bindings.scrollY}" in this._state`;
20815 const scrollX = bindings.scrollX && x `this._state.${bindings.scrollX}`;
20816 const scrollY = bindings.scrollY && x `this._state.${bindings.scrollY}`;
20817 renderer.meta_bindings.push(b `
20818 if (${condition}) {
20819 @_scrollTo(${scrollX || '@_window.pageXOffset'}, ${scrollY || '@_window.pageYOffset'});
20820 }
20821 ${scrollX && `${scrollX} = @_window.pageXOffset;`}
20822 ${scrollY && `${scrollY} = @_window.pageYOffset;`}
20823 `);
20824 block.event_listeners.push(x `
20825 @listen(@_window, "${event}", () => {
20826 ${scrolling} = true;
20827 @_clearTimeout(${scrolling_timeout});
20828 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
20829 ${fn}();
20830 })
20831 `);
20832 }
20833 else {
20834 props.forEach(prop => {
20835 renderer.meta_bindings.push(b `this._state.${prop.name} = @_window.${prop.value};`);
20836 });
20837 block.event_listeners.push(x `
20838 @listen(@_window, "${event}", ${fn})
20839 `);
20840 }
20841 component.partly_hoisted.push(b `
20842 function ${id}() {
20843 ${props.map(prop => renderer.invalidate(prop.name, x `${prop.name} = @_window.${prop.value}`))}
20844 }
20845 `);
20846 block.chunks.init.push(b `
20847 @add_render_callback(${fn});
20848 `);
20849 component.has_reactive_assignments = true;
20850 });
20851 // special case... might need to abstract this out if we add more special cases
20852 if (bindings.scrollX || bindings.scrollY) {
20853 const condition = renderer.dirty([bindings.scrollX, bindings.scrollY].filter(Boolean));
20854 const scrollX = bindings.scrollX ? renderer.reference(bindings.scrollX) : x `@_window.pageXOffset`;
20855 const scrollY = bindings.scrollY ? renderer.reference(bindings.scrollY) : x `@_window.pageYOffset`;
20856 block.chunks.update.push(b `
20857 if (${condition} && !${scrolling}) {
20858 ${scrolling} = true;
20859 @_clearTimeout(${scrolling_timeout});
20860 @_scrollTo(${scrollX}, ${scrollY});
20861 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
20862 }
20863 `);
20864 }
20865 // another special case. (I'm starting to think these are all special cases.)
20866 if (bindings.online) {
20867 const id = block.get_unique_name('onlinestatuschanged');
20868 const name = bindings.online;
20869 renderer.add_to_context(id.name);
20870 const reference = renderer.reference(id.name);
20871 component.partly_hoisted.push(b `
20872 function ${id}() {
20873 ${renderer.invalidate(name, x `${name} = @_navigator.onLine`)}
20874 }
20875 `);
20876 block.chunks.init.push(b `
20877 @add_render_callback(${reference});
20878 `);
20879 block.event_listeners.push(x `@listen(@_window, "online", ${reference})`, x `@listen(@_window, "offline", ${reference})`);
20880 component.has_reactive_assignments = true;
20881 }
20882 }
20883}
20884
20885function link(next, prev) {
20886 prev.next = next;
20887 if (next)
20888 next.prev = prev;
20889}
20890
20891const wrappers = {
20892 AwaitBlock: AwaitBlockWrapper,
20893 Body: BodyWrapper,
20894 Comment: null,
20895 DebugTag: DebugTagWrapper,
20896 EachBlock: EachBlockWrapper,
20897 Element: ElementWrapper,
20898 Head: HeadWrapper,
20899 IfBlock: IfBlockWrapper,
20900 InlineComponent: InlineComponentWrapper,
20901 KeyBlock: KeyBlockWrapper,
20902 MustacheTag: MustacheTagWrapper,
20903 Options: null,
20904 RawMustacheTag: RawMustacheTagWrapper,
20905 Slot: SlotWrapper,
20906 Text: TextWrapper,
20907 Title: TitleWrapper,
20908 Window: WindowWrapper
20909};
20910function trimmable_at(child, next_sibling) {
20911 // Whitespace is trimmable if one of the following is true:
20912 // The child and its sibling share a common nearest each block (not at an each block boundary)
20913 // The next sibling's previous node is an each block
20914 return (next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/)) || next_sibling.node.prev.type === 'EachBlock';
20915}
20916class FragmentWrapper {
20917 constructor(renderer, block, nodes, parent, strip_whitespace, next_sibling) {
20918 this.nodes = [];
20919 let last_child;
20920 let window_wrapper;
20921 let i = nodes.length;
20922 while (i--) {
20923 const child = nodes[i];
20924 if (!child.type) {
20925 throw new Error('missing type');
20926 }
20927 if (!(child.type in wrappers)) {
20928 throw new Error(`TODO implement ${child.type}`);
20929 }
20930 // special case — this is an easy way to remove whitespace surrounding
20931 // <svelte:window/>. lil hacky but it works
20932 if (child.type === 'Window') {
20933 window_wrapper = new WindowWrapper(renderer, block, parent, child);
20934 continue;
20935 }
20936 if (child.type === 'Text') {
20937 let { data } = child;
20938 // We want to remove trailing whitespace inside an element/component/block,
20939 // *unless* there is no whitespace between this node and its next sibling
20940 if (this.nodes.length === 0) {
20941 const should_trim = (next_sibling ? (next_sibling.node.type === 'Text' && /^\s/.test(next_sibling.node.data) && trimmable_at(child, next_sibling)) : !child.has_ancestor('EachBlock'));
20942 if (should_trim) {
20943 data = trim_end(data);
20944 if (!data)
20945 continue;
20946 }
20947 }
20948 // glue text nodes (which could e.g. be separated by comments) together
20949 if (last_child && last_child.node.type === 'Text') {
20950 last_child.data = data + last_child.data;
20951 continue;
20952 }
20953 const wrapper = new TextWrapper(renderer, block, parent, child, data);
20954 if (wrapper.skip)
20955 continue;
20956 this.nodes.unshift(wrapper);
20957 link(last_child, last_child = wrapper);
20958 }
20959 else {
20960 const Wrapper = wrappers[child.type];
20961 if (!Wrapper)
20962 continue;
20963 const wrapper = new Wrapper(renderer, block, parent, child, strip_whitespace, last_child || next_sibling);
20964 this.nodes.unshift(wrapper);
20965 link(last_child, last_child = wrapper);
20966 }
20967 }
20968 if (strip_whitespace) {
20969 const first = this.nodes[0];
20970 if (first && first.node.type === 'Text') {
20971 first.data = trim_start(first.data);
20972 if (!first.data) {
20973 first.var = null;
20974 this.nodes.shift();
20975 if (this.nodes[0]) {
20976 this.nodes[0].prev = null;
20977 }
20978 }
20979 }
20980 }
20981 if (window_wrapper) {
20982 this.nodes.unshift(window_wrapper);
20983 link(last_child, window_wrapper);
20984 }
20985 }
20986 render(block, parent_node, parent_nodes) {
20987 for (let i = 0; i < this.nodes.length; i += 1) {
20988 this.nodes[i].render(block, parent_node, parent_nodes);
20989 }
20990 }
20991}
20992
20993class Renderer {
20994 constructor(component, options) {
20995 this.context = [];
20996 this.initial_context = [];
20997 this.context_lookup = new Map();
20998 this.blocks = [];
20999 this.readonly = new Set();
21000 this.meta_bindings = []; // initial values for e.g. window.innerWidth, if there's a <svelte:window> meta tag
21001 this.binding_groups = new Map();
21002 this.component = component;
21003 this.options = options;
21004 this.locate = component.locate; // TODO messy
21005 this.file_var = options.dev && this.component.get_unique_name('file');
21006 component.vars.filter(v => !v.hoistable || (v.export_name && !v.module)).forEach(v => this.add_to_context(v.name));
21007 // ensure store values are included in context
21008 component.vars.filter(v => v.subscribable).forEach(v => this.add_to_context(`$${v.name}`));
21009 reserved_keywords.forEach(keyword => {
21010 if (component.var_lookup.has(keyword)) {
21011 this.add_to_context(keyword);
21012 }
21013 });
21014 if (component.slots.size > 0) {
21015 this.add_to_context('$$scope');
21016 this.add_to_context('#slots');
21017 }
21018 if (this.binding_groups.size > 0) {
21019 this.add_to_context('$$binding_groups');
21020 }
21021 // main block
21022 this.block = new Block$1({
21023 renderer: this,
21024 name: null,
21025 type: 'component',
21026 key: null,
21027 bindings: new Map(),
21028 dependencies: new Set()
21029 });
21030 this.block.has_update_method = true;
21031 this.fragment = new FragmentWrapper(this, this.block, component.fragment.children, null, true, null);
21032 // TODO messy
21033 this.blocks.forEach(block => {
21034 if (block instanceof Block$1) {
21035 block.assign_variable_names();
21036 }
21037 });
21038 this.block.assign_variable_names();
21039 this.fragment.render(this.block, null, x `#nodes`);
21040 this.context_overflow = this.context.length > 31;
21041 this.context.forEach(member => {
21042 const { variable } = member;
21043 if (variable) {
21044 member.priority += 2;
21045 if (variable.mutated || variable.reassigned)
21046 member.priority += 4;
21047 // these determine whether variable is included in initial context
21048 // array, so must have the highest priority
21049 if (variable.export_name)
21050 member.priority += 16;
21051 if (variable.referenced)
21052 member.priority += 32;
21053 }
21054 else if (member.is_non_contextual) {
21055 // determine whether variable is included in initial context
21056 // array, so must have the highest priority
21057 member.priority += 8;
21058 }
21059 if (!member.is_contextual) {
21060 member.priority += 1;
21061 }
21062 });
21063 this.context.sort((a, b) => (b.priority - a.priority) || (a.index.value - b.index.value));
21064 this.context.forEach((member, i) => member.index.value = i);
21065 let i = this.context.length;
21066 while (i--) {
21067 const member = this.context[i];
21068 if (member.variable) {
21069 if (member.variable.referenced || member.variable.export_name)
21070 break;
21071 }
21072 else if (member.is_non_contextual) {
21073 break;
21074 }
21075 }
21076 this.initial_context = this.context.slice(0, i + 1);
21077 }
21078 add_to_context(name, contextual = false) {
21079 if (!this.context_lookup.has(name)) {
21080 const member = {
21081 name,
21082 index: { type: 'Literal', value: this.context.length },
21083 is_contextual: false,
21084 is_non_contextual: false,
21085 variable: null,
21086 priority: 0
21087 };
21088 this.context_lookup.set(name, member);
21089 this.context.push(member);
21090 }
21091 const member = this.context_lookup.get(name);
21092 if (contextual) {
21093 member.is_contextual = true;
21094 }
21095 else {
21096 member.is_non_contextual = true;
21097 member.variable = this.component.var_lookup.get(name);
21098 }
21099 return member;
21100 }
21101 invalidate(name, value, main_execution_context = false) {
21102 const variable = this.component.var_lookup.get(name);
21103 const member = this.context_lookup.get(name);
21104 if (variable && (variable.subscribable && (variable.reassigned || variable.export_name))) {
21105 return main_execution_context
21106 ? x `${`$$subscribe_${name}`}(${value || name})`
21107 : x `${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
21108 }
21109 if (name[0] === '$' && name[1] !== '$') {
21110 return x `${name.slice(1)}.set(${value || name})`;
21111 }
21112 if (variable && (variable.module || (!variable.referenced &&
21113 !variable.is_reactive_dependency &&
21114 !variable.export_name &&
21115 !name.startsWith('$$')))) {
21116 return value || name;
21117 }
21118 if (value) {
21119 return x `$$invalidate(${member.index}, ${value})`;
21120 }
21121 // if this is a reactive declaration, invalidate dependencies recursively
21122 const deps = new Set([name]);
21123 deps.forEach(name => {
21124 const reactive_declarations = this.component.reactive_declarations.filter(x => x.assignees.has(name));
21125 reactive_declarations.forEach(declaration => {
21126 declaration.dependencies.forEach(name => {
21127 deps.add(name);
21128 });
21129 });
21130 });
21131 // TODO ideally globals etc wouldn't be here in the first place
21132 const filtered = Array.from(deps).filter(n => this.context_lookup.has(n));
21133 if (!filtered.length)
21134 return null;
21135 return filtered
21136 .map(n => x `$$invalidate(${this.context_lookup.get(n).index}, ${n})`)
21137 .reduce((lhs, rhs) => x `${lhs}, ${rhs}`);
21138 }
21139 dirty(names, is_reactive_declaration = false) {
21140 const renderer = this;
21141 const dirty = (is_reactive_declaration
21142 ? x `$$self.$$.dirty`
21143 : x `#dirty`);
21144 const get_bitmask = () => {
21145 const bitmask = [];
21146 names.forEach((name) => {
21147 const member = renderer.context_lookup.get(name);
21148 if (!member)
21149 return;
21150 if (member.index.value === -1) {
21151 throw new Error('unset index');
21152 }
21153 const value = member.index.value;
21154 const i = (value / 31) | 0;
21155 const n = 1 << (value % 31);
21156 if (!bitmask[i])
21157 bitmask[i] = { n: 0, names: [] };
21158 bitmask[i].n |= n;
21159 bitmask[i].names.push(name);
21160 });
21161 return bitmask;
21162 };
21163 // TODO: context-overflow make it less gross
21164 return {
21165 // Using a ParenthesizedExpression allows us to create
21166 // the expression lazily. TODO would be better if
21167 // context was determined before rendering, so that
21168 // this indirection was unnecessary
21169 type: 'ParenthesizedExpression',
21170 get expression() {
21171 const bitmask = get_bitmask();
21172 if (!bitmask.length) {
21173 return x `${dirty} & /*${names.join(', ')}*/ 0`;
21174 }
21175 if (renderer.context_overflow) {
21176 return bitmask
21177 .map((b, i) => ({ b, i }))
21178 .filter(({ b }) => b)
21179 .map(({ b, i }) => x `${dirty}[${i}] & /*${b.names.join(', ')}*/ ${b.n}`)
21180 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
21181 }
21182 return x `${dirty} & /*${names.join(', ')}*/ ${bitmask[0].n}`;
21183 }
21184 };
21185 }
21186 reference(node) {
21187 if (typeof node === 'string') {
21188 node = { type: 'Identifier', name: node };
21189 }
21190 const { name, nodes } = flatten_reference(node);
21191 const member = this.context_lookup.get(name);
21192 // TODO is this correct?
21193 if (this.component.var_lookup.get(name)) {
21194 this.component.add_reference(name);
21195 }
21196 if (member !== undefined) {
21197 const replacement = x `/*${member.name}*/ #ctx[${member.index}]`;
21198 if (nodes[0].loc)
21199 replacement.object.loc = nodes[0].loc;
21200 nodes[0] = replacement;
21201 return nodes.reduce((lhs, rhs) => x `${lhs}.${rhs}`);
21202 }
21203 return node;
21204 }
21205 remove_block(block) {
21206 this.blocks.splice(this.blocks.indexOf(block), 1);
21207 }
21208}
21209
21210function dom(component, options) {
21211 const { name } = component;
21212 const renderer = new Renderer(component, options);
21213 const { block } = renderer;
21214 block.has_outro_method = true;
21215 // prevent fragment being created twice (#1063)
21216 if (options.customElement)
21217 block.chunks.create.push(b `this.c = @noop;`);
21218 const body = [];
21219 if (renderer.file_var) {
21220 const file = component.file ? x `"${component.file}"` : x `undefined`;
21221 body.push(b `const ${renderer.file_var} = ${file};`);
21222 }
21223 const css = component.stylesheet.render(options.filename, !options.customElement);
21224 const styles = component.stylesheet.has_styles && options.dev
21225 ? `${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */`
21226 : css.code;
21227 const add_css = component.get_unique_name('add_css');
21228 const should_add_css = (!options.customElement &&
21229 !!styles &&
21230 options.css !== false);
21231 if (should_add_css) {
21232 body.push(b `
21233 function ${add_css}() {
21234 var style = @element("style");
21235 style.id = "${component.stylesheet.id}-style";
21236 style.textContent = "${styles}";
21237 @append(@_document.head, style);
21238 }
21239 `);
21240 }
21241 // fix order
21242 // TODO the deconflicted names of blocks are reversed... should set them here
21243 const blocks = renderer.blocks.slice().reverse();
21244 body.push(...blocks.map(block => {
21245 // TODO this is a horrible mess — renderer.blocks
21246 // contains a mixture of Blocks and Nodes
21247 if (block.render)
21248 return block.render();
21249 return block;
21250 }));
21251 if (options.dev && !options.hydratable) {
21252 block.chunks.claim.push(b `throw new @_Error("options.hydrate only works if the component was compiled with the \`hydratable: true\` option");`);
21253 }
21254 const uses_slots = component.var_lookup.has('$$slots');
21255 let compute_slots;
21256 if (uses_slots) {
21257 compute_slots = b `
21258 const $$slots = @compute_slots(#slots);
21259 `;
21260 }
21261 const uses_props = component.var_lookup.has('$$props');
21262 const uses_rest = component.var_lookup.has('$$restProps');
21263 const $$props = uses_props || uses_rest ? '$$new_props' : '$$props';
21264 const props = component.vars.filter(variable => !variable.module && variable.export_name);
21265 const writable_props = props.filter(variable => variable.writable);
21266 const omit_props_names = component.get_unique_name('omit_props_names');
21267 const compute_rest = x `@compute_rest_props($$props, ${omit_props_names.name})`;
21268 const rest = uses_rest ? b `
21269 const ${omit_props_names.name} = [${props.map(prop => `"${prop.export_name}"`).join(',')}];
21270 let $$restProps = ${compute_rest};
21271 ` : null;
21272 const set = (uses_props || uses_rest || writable_props.length > 0 || component.slots.size > 0)
21273 ? x `
21274 ${$$props} => {
21275 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`)}
21276 ${uses_rest && !uses_props && x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`}
21277 ${uses_rest && renderer.invalidate('$$restProps', x `$$restProps = ${compute_rest}`)}
21278 ${writable_props.map(prop => b `if ('${prop.export_name}' in ${$$props}) ${renderer.invalidate(prop.name, x `${prop.name} = ${$$props}.${prop.export_name}`)};`)}
21279 ${component.slots.size > 0 &&
21280 b `if ('$$scope' in ${$$props}) ${renderer.invalidate('$$scope', x `$$scope = ${$$props}.$$scope`)};`}
21281 }
21282 `
21283 : null;
21284 const accessors = [];
21285 const not_equal = component.component_options.immutable ? x `@not_equal` : x `@safe_not_equal`;
21286 let dev_props_check;
21287 let inject_state;
21288 let capture_state;
21289 let props_inject;
21290 props.forEach(prop => {
21291 const variable = component.var_lookup.get(prop.name);
21292 if (!variable.writable || component.component_options.accessors) {
21293 accessors.push({
21294 type: 'MethodDefinition',
21295 kind: 'get',
21296 key: { type: 'Identifier', name: prop.export_name },
21297 value: x `function() {
21298 return ${prop.hoistable ? prop.name : x `this.$$.ctx[${renderer.context_lookup.get(prop.name).index}]`}
21299 }`
21300 });
21301 }
21302 else if (component.compile_options.dev) {
21303 accessors.push({
21304 type: 'MethodDefinition',
21305 kind: 'get',
21306 key: { type: 'Identifier', name: prop.export_name },
21307 value: x `function() {
21308 throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
21309 }`
21310 });
21311 }
21312 if (component.component_options.accessors) {
21313 if (variable.writable && !renderer.readonly.has(prop.name)) {
21314 accessors.push({
21315 type: 'MethodDefinition',
21316 kind: 'set',
21317 key: { type: 'Identifier', name: prop.export_name },
21318 value: x `function(${prop.name}) {
21319 this.$set({ ${prop.export_name}: ${prop.name} });
21320 @flush();
21321 }`
21322 });
21323 }
21324 else if (component.compile_options.dev) {
21325 accessors.push({
21326 type: 'MethodDefinition',
21327 kind: 'set',
21328 key: { type: 'Identifier', name: prop.export_name },
21329 value: x `function(value) {
21330 throw new @_Error("<${component.tag}>: Cannot set read-only property '${prop.export_name}'");
21331 }`
21332 });
21333 }
21334 }
21335 else if (component.compile_options.dev) {
21336 accessors.push({
21337 type: 'MethodDefinition',
21338 kind: 'set',
21339 key: { type: 'Identifier', name: prop.export_name },
21340 value: x `function(value) {
21341 throw new @_Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
21342 }`
21343 });
21344 }
21345 });
21346 if (component.compile_options.dev) {
21347 // checking that expected ones were passed
21348 const expected = props.filter(prop => prop.writable && !prop.initialised);
21349 if (expected.length) {
21350 dev_props_check = b `
21351 const { ctx: #ctx } = this.$$;
21352 const props = ${options.customElement ? x `this.attributes` : x `options.props || {}`};
21353 ${expected.map(prop => b `
21354 if (${renderer.reference(prop.name)} === undefined && !('${prop.export_name}' in props)) {
21355 @_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'");
21356 }`)}
21357 `;
21358 }
21359 const capturable_vars = component.vars.filter(v => !v.internal && !v.global && !v.name.startsWith('$$'));
21360 if (capturable_vars.length > 0) {
21361 capture_state = x `() => ({ ${capturable_vars.map(prop => p `${prop.name}`)} })`;
21362 }
21363 const injectable_vars = capturable_vars.filter(v => !v.module && v.writable && v.name[0] !== '$');
21364 if (uses_props || injectable_vars.length > 0) {
21365 inject_state = x `
21366 ${$$props} => {
21367 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), $$new_props)`)}
21368 ${injectable_vars.map(v => b `if ('${v.name}' in $$props) ${renderer.invalidate(v.name, x `${v.name} = ${$$props}.${v.name}`)};`)}
21369 }
21370 `;
21371 props_inject = b `
21372 if ($$props && "$$inject" in $$props) {
21373 $$self.$inject_state($$props.$$inject);
21374 }
21375 `;
21376 }
21377 }
21378 // instrument assignments
21379 if (component.ast.instance) {
21380 let scope = component.instance_scope;
21381 const map = component.instance_scope_map;
21382 let execution_context = null;
21383 walk(component.ast.instance.content, {
21384 enter(node) {
21385 if (map.has(node)) {
21386 scope = map.get(node);
21387 if (!execution_context && !scope.block) {
21388 execution_context = node;
21389 }
21390 }
21391 else if (!execution_context && node.type === 'LabeledStatement' && node.label.name === '$') {
21392 execution_context = node;
21393 }
21394 },
21395 leave(node) {
21396 if (map.has(node)) {
21397 scope = scope.parent;
21398 }
21399 if (execution_context === node) {
21400 execution_context = null;
21401 }
21402 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
21403 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
21404 // normally (`a = 1`, `b.c = 2`), there'll be a single name
21405 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
21406 // may be more, in which case we need to tack the extra ones
21407 // onto the initial function call
21408 const names = new Set(extract_names(assignee));
21409 this.replace(invalidate(renderer, scope, node, names, execution_context === null));
21410 }
21411 }
21412 });
21413 component.rewrite_props(({ name, reassigned, export_name }) => {
21414 const value = `$${name}`;
21415 const i = renderer.context_lookup.get(`$${name}`).index;
21416 const insert = (reassigned || export_name)
21417 ? b `${`$$subscribe_${name}`}()`
21418 : b `@component_subscribe($$self, ${name}, #value => $$invalidate(${i}, ${value} = #value))`;
21419 if (component.compile_options.dev) {
21420 return b `@validate_store(${name}, '${name}'); ${insert}`;
21421 }
21422 return insert;
21423 });
21424 }
21425 const args = [x `$$self`];
21426 const has_invalidate = props.length > 0 ||
21427 component.has_reactive_assignments ||
21428 component.slots.size > 0 ||
21429 capture_state ||
21430 inject_state;
21431 if (has_invalidate) {
21432 args.push(x `$$props`, x `$$invalidate`);
21433 }
21434 else if (component.compile_options.dev) {
21435 // $$props arg is still needed for unknown prop check
21436 args.push(x `$$props`);
21437 }
21438 const has_create_fragment = component.compile_options.dev || block.has_content();
21439 if (has_create_fragment) {
21440 body.push(b `
21441 function create_fragment(#ctx) {
21442 ${block.get_contents()}
21443 }
21444 `);
21445 }
21446 body.push(b `
21447 ${component.extract_javascript(component.ast.module)}
21448
21449 ${component.fully_hoisted}
21450 `);
21451 const filtered_props = props.filter(prop => {
21452 const variable = component.var_lookup.get(prop.name);
21453 if (variable.hoistable)
21454 return false;
21455 return prop.name[0] !== '$';
21456 });
21457 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
21458 const instance_javascript = component.extract_javascript(component.ast.instance);
21459 const has_definition = (component.compile_options.dev ||
21460 (instance_javascript && instance_javascript.length > 0) ||
21461 filtered_props.length > 0 ||
21462 uses_props ||
21463 component.partly_hoisted.length > 0 ||
21464 renderer.initial_context.length > 0 ||
21465 component.reactive_declarations.length > 0 ||
21466 capture_state ||
21467 inject_state);
21468 const definition = has_definition
21469 ? component.alias('instance')
21470 : { type: 'Literal', value: null };
21471 const reactive_store_subscriptions = reactive_stores
21472 .filter(store => {
21473 const variable = component.var_lookup.get(store.name.slice(1));
21474 return !variable || variable.hoistable;
21475 })
21476 .map(({ name }) => b `
21477 ${component.compile_options.dev && b `@validate_store(${name.slice(1)}, '${name.slice(1)}');`}
21478 @component_subscribe($$self, ${name.slice(1)}, $$value => $$invalidate(${renderer.context_lookup.get(name).index}, ${name} = $$value));
21479 `);
21480 const resubscribable_reactive_store_unsubscribers = reactive_stores
21481 .filter(store => {
21482 const variable = component.var_lookup.get(store.name.slice(1));
21483 return variable && (variable.reassigned || variable.export_name);
21484 })
21485 .map(({ name }) => b `$$self.$$.on_destroy.push(() => ${`$$unsubscribe_${name.slice(1)}`}());`);
21486 if (has_definition) {
21487 const reactive_declarations = [];
21488 const fixed_reactive_declarations = []; // not really 'reactive' but whatever
21489 component.reactive_declarations.forEach(d => {
21490 const dependencies = Array.from(d.dependencies);
21491 const uses_rest_or_props = !!dependencies.find(n => n === '$$props' || n === '$$restProps');
21492 const writable = dependencies.filter(n => {
21493 const variable = component.var_lookup.get(n);
21494 return variable && (variable.export_name || variable.mutated || variable.reassigned);
21495 });
21496 const condition = !uses_rest_or_props && writable.length > 0 && renderer.dirty(writable, true);
21497 let statement = d.node; // TODO remove label (use d.node.body) if it's not referenced
21498 if (condition)
21499 statement = b `if (${condition}) { ${statement} }`[0];
21500 if (condition || uses_rest_or_props) {
21501 reactive_declarations.push(statement);
21502 }
21503 else {
21504 fixed_reactive_declarations.push(statement);
21505 }
21506 });
21507 const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
21508 const variable = component.var_lookup.get(name);
21509 return variable.injected && variable.name[0] !== '$';
21510 });
21511 const reactive_store_declarations = reactive_stores.map(variable => {
21512 const $name = variable.name;
21513 const name = $name.slice(1);
21514 const store = component.var_lookup.get(name);
21515 if (store && (store.reassigned || store.export_name)) {
21516 const unsubscribe = `$$unsubscribe_${name}`;
21517 const subscribe = `$$subscribe_${name}`;
21518 const i = renderer.context_lookup.get($name).index;
21519 return b `let ${$name}, ${unsubscribe} = @noop, ${subscribe} = () => (${unsubscribe}(), ${unsubscribe} = @subscribe(${name}, $$value => $$invalidate(${i}, ${$name} = $$value)), ${name})`;
21520 }
21521 return b `let ${$name};`;
21522 });
21523 let unknown_props_check;
21524 if (component.compile_options.dev && !(uses_props || uses_rest)) {
21525 unknown_props_check = b `
21526 const writable_props = [${writable_props.map(prop => x `'${prop.export_name}'`)}];
21527 @_Object.keys($$props).forEach(key => {
21528 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$') @_console.warn(\`<${component.tag}> was created with unknown prop '\${key}'\`);
21529 });
21530 `;
21531 }
21532 const return_value = {
21533 type: 'ArrayExpression',
21534 elements: renderer.initial_context.map(member => ({
21535 type: 'Identifier',
21536 name: member.name
21537 }))
21538 };
21539 body.push(b `
21540 function ${definition}(${args}) {
21541 ${rest}
21542
21543 ${reactive_store_declarations}
21544
21545 ${reactive_store_subscriptions}
21546
21547 ${resubscribable_reactive_store_unsubscribers}
21548
21549 ${component.slots.size || component.compile_options.dev || uses_slots ? b `let { $$slots: #slots = {}, $$scope } = $$props;` : null}
21550 ${component.compile_options.dev && b `@validate_slots('${component.tag}', #slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
21551 ${compute_slots}
21552
21553 ${instance_javascript}
21554
21555 ${unknown_props_check}
21556
21557 ${renderer.binding_groups.size > 0 && b `const $$binding_groups = [${[...renderer.binding_groups.keys()].map(_ => x `[]`)}];`}
21558
21559 ${component.partly_hoisted}
21560
21561 ${set && b `$$self.$$set = ${set};`}
21562
21563 ${capture_state && b `$$self.$capture_state = ${capture_state};`}
21564
21565 ${inject_state && b `$$self.$inject_state = ${inject_state};`}
21566
21567 ${injected.map(name => b `let ${name};`)}
21568
21569 ${ /* before reactive declarations */props_inject}
21570
21571 ${reactive_declarations.length > 0 && b `
21572 $$self.$$.update = () => {
21573 ${reactive_declarations}
21574 };
21575 `}
21576
21577 ${fixed_reactive_declarations}
21578
21579 ${uses_props && b `$$props = @exclude_internal_props($$props);`}
21580
21581 return ${return_value};
21582 }
21583 `);
21584 }
21585 const prop_indexes = x `{
21586 ${props.filter(v => v.export_name && !v.module).map(v => p `${v.export_name}: ${renderer.context_lookup.get(v.name).index}`)}
21587 }`;
21588 let dirty;
21589 if (renderer.context_overflow) {
21590 dirty = x `[]`;
21591 for (let i = 0; i < renderer.context.length; i += 31) {
21592 dirty.elements.push(x `-1`);
21593 }
21594 }
21595 if (options.customElement) {
21596 let init_props = x `@attribute_to_object(this.attributes)`;
21597 if (uses_slots) {
21598 init_props = x `{ ...${init_props}, $$slots: @get_custom_elements_slots(this) }`;
21599 }
21600 const declaration = b `
21601 class ${name} extends @SvelteElement {
21602 constructor(options) {
21603 super();
21604
21605 ${css.code && b `this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
21606
21607 @init(this, { target: this.shadowRoot, props: ${init_props} }, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
21608
21609 ${dev_props_check}
21610
21611 if (options) {
21612 if (options.target) {
21613 @insert(options.target, this, options.anchor);
21614 }
21615
21616 ${(props.length > 0 || uses_props || uses_rest) && b `
21617 if (options.props) {
21618 this.$set(options.props);
21619 @flush();
21620 }`}
21621 }
21622 }
21623 }
21624 `[0];
21625 if (props.length > 0) {
21626 declaration.body.body.push({
21627 type: 'MethodDefinition',
21628 kind: 'get',
21629 static: true,
21630 computed: false,
21631 key: { type: 'Identifier', name: 'observedAttributes' },
21632 value: x `function() {
21633 return [${props.map(prop => x `"${prop.export_name}"`)}];
21634 }`
21635 });
21636 }
21637 declaration.body.body.push(...accessors);
21638 body.push(declaration);
21639 if (component.tag != null) {
21640 body.push(b `
21641 @_customElements.define("${component.tag}", ${name});
21642 `);
21643 }
21644 }
21645 else {
21646 const superclass = {
21647 type: 'Identifier',
21648 name: options.dev ? '@SvelteComponentDev' : '@SvelteComponent'
21649 };
21650 const declaration = b `
21651 class ${name} extends ${superclass} {
21652 constructor(options) {
21653 super(${options.dev && 'options'});
21654 ${should_add_css && b `if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
21655 @init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
21656 ${options.dev && b `@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`}
21657
21658 ${dev_props_check}
21659 }
21660 }
21661 `[0];
21662 declaration.body.body.push(...accessors);
21663 body.push(declaration);
21664 }
21665 return { js: flatten$1(body, []), css };
21666}
21667function flatten$1(nodes, target) {
21668 for (let i = 0; i < nodes.length; i += 1) {
21669 const node = nodes[i];
21670 if (Array.isArray(node)) {
21671 flatten$1(node, target);
21672 }
21673 else {
21674 target.push(node);
21675 }
21676 }
21677 return target;
21678}
21679
21680function AwaitBlock (node, renderer, options) {
21681 renderer.push();
21682 renderer.render(node.pending.children, options);
21683 const pending = renderer.pop();
21684 renderer.push();
21685 renderer.render(node.then.children, options);
21686 const then = renderer.pop();
21687 renderer.add_expression(x `
21688 function(__value) {
21689 if (@is_promise(__value)) return ${pending};
21690 return (function(${node.then_node ? node.then_node : ''}) { return ${then}; }(__value));
21691 }(${node.expression.node})
21692 `);
21693}
21694
21695function Comment$1 (_node, _renderer, _options) {
21696 // TODO preserve comments
21697 // if (options.preserveComments) {
21698 // renderer.append(`<!--${node.data}-->`);
21699 // }
21700}
21701
21702function DebugTag (node, renderer, options) {
21703 if (!options.dev)
21704 return;
21705 const filename = options.filename || null;
21706 const { line, column } = options.locate(node.start + 1);
21707 const obj = x `{
21708 ${node.expressions.map(e => p `${e.node.name}`)}
21709 }`;
21710 renderer.add_expression(x `@debug(${filename ? x `"${filename}"` : x `null`}, ${line - 1}, ${column}, ${obj})`);
21711}
21712
21713function EachBlock (node, renderer, options) {
21714 const args = [node.context_node];
21715 if (node.index)
21716 args.push({ type: 'Identifier', name: node.index });
21717 renderer.push();
21718 renderer.render(node.children, options);
21719 const result = renderer.pop();
21720 const consequent = x `@each(${node.expression.node}, (${args}) => ${result})`;
21721 if (node.else) {
21722 renderer.push();
21723 renderer.render(node.else.children, options);
21724 const alternate = renderer.pop();
21725 renderer.add_expression(x `${node.expression.node}.length ? ${consequent} : ${alternate}`);
21726 }
21727 else {
21728 renderer.add_expression(consequent);
21729 }
21730}
21731
21732function get_class_attribute_value(attribute) {
21733 // handle special case — `class={possiblyUndefined}` with scoped CSS
21734 if (attribute.chunks.length === 2 && attribute.chunks[1].synthetic) {
21735 const value = attribute.chunks[0].node;
21736 return x `@escape(@null_to_empty(${value})) + "${attribute.chunks[1].data}"`;
21737 }
21738 return get_attribute_value(attribute);
21739}
21740function get_attribute_value(attribute) {
21741 if (attribute.chunks.length === 0)
21742 return x `""`;
21743 return attribute.chunks
21744 .map((chunk) => {
21745 return chunk.type === 'Text'
21746 ? string_literal(chunk.data.replace(/"/g, '&quot;'))
21747 : x `@escape(${chunk.node})`;
21748 })
21749 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
21750}
21751
21752function get_slot_scope(lets) {
21753 if (lets.length === 0)
21754 return null;
21755 return {
21756 type: 'ObjectPattern',
21757 properties: lets.map(l => {
21758 return {
21759 type: 'Property',
21760 kind: 'init',
21761 method: false,
21762 shorthand: false,
21763 computed: false,
21764 key: l.name,
21765 value: l.value || l.name
21766 };
21767 })
21768 };
21769}
21770
21771// source: https://html.spec.whatwg.org/multipage/indices.html
21772const boolean_attributes = new Set([
21773 'allowfullscreen',
21774 'allowpaymentrequest',
21775 'async',
21776 'autofocus',
21777 'autoplay',
21778 'checked',
21779 'controls',
21780 'default',
21781 'defer',
21782 'disabled',
21783 'formnovalidate',
21784 'hidden',
21785 'ismap',
21786 'loop',
21787 'multiple',
21788 'muted',
21789 'nomodule',
21790 'novalidate',
21791 'open',
21792 'playsinline',
21793 'readonly',
21794 'required',
21795 'reversed',
21796 'selected'
21797]);
21798
21799// similar logic from `compile/render_dom/wrappers/Fragment`
21800// We want to remove trailing whitespace inside an element/component/block,
21801// *unless* there is no whitespace between this node and its next sibling
21802function remove_whitespace_children(children, next) {
21803 const nodes = [];
21804 let last_child;
21805 let i = children.length;
21806 while (i--) {
21807 const child = children[i];
21808 if (child.type === 'Text') {
21809 if (child.should_skip()) {
21810 continue;
21811 }
21812 let { data } = child;
21813 if (nodes.length === 0) {
21814 const should_trim = next
21815 ? next.type === 'Text' &&
21816 /^\s/.test(next.data) &&
21817 trimmable_at$1(child, next)
21818 : !child.has_ancestor('EachBlock');
21819 if (should_trim) {
21820 data = trim_end(data);
21821 if (!data)
21822 continue;
21823 }
21824 }
21825 // glue text nodes (which could e.g. be separated by comments) together
21826 if (last_child && last_child.type === 'Text') {
21827 last_child.data = data + last_child.data;
21828 continue;
21829 }
21830 nodes.unshift(child);
21831 link(last_child, last_child = child);
21832 }
21833 else {
21834 nodes.unshift(child);
21835 link(last_child, last_child = child);
21836 }
21837 }
21838 const first = nodes[0];
21839 if (first && first.type === 'Text') {
21840 first.data = trim_start(first.data);
21841 if (!first.data) {
21842 first.var = null;
21843 nodes.shift();
21844 if (nodes[0]) {
21845 nodes[0].prev = null;
21846 }
21847 }
21848 }
21849 return nodes;
21850}
21851function trimmable_at$1(child, next_sibling) {
21852 // Whitespace is trimmable if one of the following is true:
21853 // The child and its sibling share a common nearest each block (not at an each block boundary)
21854 // The next sibling's previous node is an each block
21855 return (next_sibling.find_nearest(/EachBlock/) ===
21856 child.find_nearest(/EachBlock/) || next_sibling.prev.type === 'EachBlock');
21857}
21858
21859function Element (node, renderer, options) {
21860 const children = remove_whitespace_children(node.children, node.next);
21861 // awkward special case
21862 let node_contents;
21863 const contenteditable = (node.name !== 'textarea' &&
21864 node.name !== 'input' &&
21865 node.attributes.some((attribute) => attribute.name === 'contenteditable'));
21866 const slot = node.get_static_attribute_value('slot');
21867 const nearest_inline_component = node.find_nearest(/InlineComponent/);
21868 if (slot && nearest_inline_component) {
21869 renderer.push();
21870 }
21871 renderer.add_string(`<${node.name}`);
21872 const class_expression_list = node.classes.map(class_directive => {
21873 const { expression, name } = class_directive;
21874 const snippet = expression ? expression.node : x `#ctx.${name}`; // TODO is this right?
21875 return x `${snippet} ? "${name}" : ""`;
21876 });
21877 if (node.needs_manual_style_scoping) {
21878 class_expression_list.push(x `"${node.component.stylesheet.id}"`);
21879 }
21880 const class_expression = class_expression_list.length > 0 &&
21881 class_expression_list.reduce((lhs, rhs) => x `${lhs} + ' ' + ${rhs}`);
21882 if (node.attributes.some(attr => attr.is_spread)) {
21883 // TODO dry this out
21884 const args = [];
21885 node.attributes.forEach(attribute => {
21886 if (attribute.is_spread) {
21887 args.push(attribute.expression.node);
21888 }
21889 else {
21890 const name = attribute.name.toLowerCase();
21891 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
21892 node_contents = get_attribute_value(attribute);
21893 }
21894 else if (attribute.is_true) {
21895 args.push(x `{ ${attribute.name}: true }`);
21896 }
21897 else if (boolean_attributes.has(name) &&
21898 attribute.chunks.length === 1 &&
21899 attribute.chunks[0].type !== 'Text') {
21900 // a boolean attribute with one non-Text chunk
21901 args.push(x `{ ${attribute.name}: ${attribute.chunks[0].node} || null }`);
21902 }
21903 else {
21904 args.push(x `{ ${attribute.name}: ${get_attribute_value(attribute)} }`);
21905 }
21906 }
21907 });
21908 renderer.add_expression(x `@spread([${args}], ${class_expression})`);
21909 }
21910 else {
21911 let add_class_attribute = !!class_expression;
21912 node.attributes.forEach(attribute => {
21913 const name = attribute.name.toLowerCase();
21914 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
21915 node_contents = get_attribute_value(attribute);
21916 }
21917 else if (attribute.is_true) {
21918 renderer.add_string(` ${attribute.name}`);
21919 }
21920 else if (boolean_attributes.has(name) &&
21921 attribute.chunks.length === 1 &&
21922 attribute.chunks[0].type !== 'Text') {
21923 // a boolean attribute with one non-Text chunk
21924 renderer.add_string(' ');
21925 renderer.add_expression(x `${attribute.chunks[0].node} ? "${attribute.name}" : ""`);
21926 }
21927 else if (name === 'class' && class_expression) {
21928 add_class_attribute = false;
21929 renderer.add_string(` ${attribute.name}="`);
21930 renderer.add_expression(x `[${get_class_attribute_value(attribute)}, ${class_expression}].join(' ').trim()`);
21931 renderer.add_string('"');
21932 }
21933 else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') {
21934 const snippet = attribute.chunks[0].node;
21935 renderer.add_expression(x `@add_attribute("${attribute.name}", ${snippet}, ${boolean_attributes.has(name) ? 1 : 0})`);
21936 }
21937 else {
21938 renderer.add_string(` ${attribute.name}="`);
21939 renderer.add_expression((name === 'class' ? get_class_attribute_value : get_attribute_value)(attribute));
21940 renderer.add_string('"');
21941 }
21942 });
21943 if (add_class_attribute) {
21944 renderer.add_expression(x `@add_classes([${class_expression}].join(' ').trim())`);
21945 }
21946 }
21947 node.bindings.forEach(binding => {
21948 const { name, expression } = binding;
21949 if (binding.is_readonly) {
21950 return;
21951 }
21952 if (name === 'group') ;
21953 else if (contenteditable && (name === 'textContent' || name === 'innerHTML')) {
21954 node_contents = expression.node;
21955 // TODO where was this used?
21956 // value = name === 'textContent' ? x`@escape($$value)` : x`$$value`;
21957 }
21958 else if (binding.name === 'value' && node.name === 'textarea') {
21959 const snippet = expression.node;
21960 node_contents = x `${snippet} || ""`;
21961 }
21962 else {
21963 const snippet = expression.node;
21964 renderer.add_expression(x `@add_attribute("${name}", ${snippet}, 1)`);
21965 }
21966 });
21967 if (options.hydratable && options.head_id) {
21968 renderer.add_string(` data-svelte="${options.head_id}"`);
21969 }
21970 renderer.add_string('>');
21971 if (node_contents !== undefined) {
21972 if (contenteditable) {
21973 renderer.push();
21974 renderer.render(children, options);
21975 const result = renderer.pop();
21976 renderer.add_expression(x `($$value => $$value === void 0 ? ${result} : $$value)(${node_contents})`);
21977 }
21978 else {
21979 renderer.add_expression(node_contents);
21980 }
21981 if (!is_void(node.name)) {
21982 renderer.add_string(`</${node.name}>`);
21983 }
21984 }
21985 else if (slot && nearest_inline_component) {
21986 renderer.render(children, options);
21987 if (!is_void(node.name)) {
21988 renderer.add_string(`</${node.name}>`);
21989 }
21990 const lets = node.lets;
21991 const seen = new Set(lets.map(l => l.name.name));
21992 nearest_inline_component.lets.forEach(l => {
21993 if (!seen.has(l.name.name))
21994 lets.push(l);
21995 });
21996 options.slot_scopes.set(slot, {
21997 input: get_slot_scope(node.lets),
21998 output: renderer.pop()
21999 });
22000 }
22001 else {
22002 renderer.render(children, options);
22003 if (!is_void(node.name)) {
22004 renderer.add_string(`</${node.name}>`);
22005 }
22006 }
22007}
22008
22009function Head (node, renderer, options) {
22010 const head_options = Object.assign({}, options, { head_id: node.id });
22011 renderer.push();
22012 renderer.render(node.children, head_options);
22013 const result = renderer.pop();
22014 renderer.add_expression(x `$$result.head += ${result}, ""`);
22015}
22016
22017function HtmlTag (node, renderer, _options) {
22018 renderer.add_expression(node.expression.node);
22019}
22020
22021function IfBlock (node, renderer, options) {
22022 const condition = node.expression.node;
22023 renderer.push();
22024 renderer.render(node.children, options);
22025 const consequent = renderer.pop();
22026 renderer.push();
22027 if (node.else)
22028 renderer.render(node.else.children, options);
22029 const alternate = renderer.pop();
22030 renderer.add_expression(x `${condition} ? ${consequent} : ${alternate}`);
22031}
22032
22033function get_prop_value(attribute) {
22034 if (attribute.is_true)
22035 return x `true`;
22036 if (attribute.chunks.length === 0)
22037 return x `''`;
22038 return attribute.chunks
22039 .map(chunk => {
22040 if (chunk.type === 'Text')
22041 return string_literal(chunk.data);
22042 return chunk.node;
22043 })
22044 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
22045}
22046function InlineComponent (node, renderer, options) {
22047 const binding_props = [];
22048 const binding_fns = [];
22049 node.bindings.forEach(binding => {
22050 renderer.has_bindings = true;
22051 // TODO this probably won't work for contextual bindings
22052 const snippet = binding.expression.node;
22053 binding_props.push(p `${binding.name}: ${snippet}`);
22054 binding_fns.push(p `${binding.name}: $$value => { ${snippet} = $$value; $$settled = false }`);
22055 });
22056 const uses_spread = node.attributes.find(attr => attr.is_spread);
22057 let props;
22058 if (uses_spread) {
22059 props = x `@_Object.assign(${node.attributes
22060 .map(attribute => {
22061 if (attribute.is_spread) {
22062 return attribute.expression.node;
22063 }
22064 else {
22065 return x `{ ${attribute.name}: ${get_prop_value(attribute)} }`;
22066 }
22067 })
22068 .concat(binding_props.map(p => x `{ ${p} }`))})`;
22069 }
22070 else {
22071 props = x `{
22072 ${node.attributes.map(attribute => p `${attribute.name}: ${get_prop_value(attribute)}`)},
22073 ${binding_props}
22074 }`;
22075 }
22076 const bindings = x `{
22077 ${binding_fns}
22078 }`;
22079 const expression = (node.name === 'svelte:self'
22080 ? renderer.name
22081 : node.name === 'svelte:component'
22082 ? x `(${node.expression.node}) || @missing_component`
22083 : node.name.split('.').reduce(((lhs, rhs) => x `${lhs}.${rhs}`)));
22084 const slot_fns = [];
22085 const children = remove_whitespace_children(node.children, node.next);
22086 if (children.length) {
22087 const slot_scopes = new Map();
22088 renderer.push();
22089 renderer.render(children, Object.assign({}, options, {
22090 slot_scopes
22091 }));
22092 slot_scopes.set('default', {
22093 input: get_slot_scope(node.lets),
22094 output: renderer.pop()
22095 });
22096 slot_scopes.forEach(({ input, output }, name) => {
22097 if (!is_empty_template_literal(output)) {
22098 slot_fns.push(p `${name}: (${input}) => ${output}`);
22099 }
22100 });
22101 }
22102 const slots = x `{
22103 ${slot_fns}
22104 }`;
22105 renderer.add_expression(x `@validate_component(${expression}, "${node.name}").$$render($$result, ${props}, ${bindings}, ${slots})`);
22106}
22107function is_empty_template_literal(template_literal) {
22108 return (template_literal.expressions.length === 0 &&
22109 template_literal.quasis.length === 1 &&
22110 template_literal.quasis[0].value.raw === '');
22111}
22112
22113function KeyBlock (node, renderer, options) {
22114 renderer.render(node.children, options);
22115}
22116
22117function Slot (node, renderer, options) {
22118 const slot_data = get_slot_data(node.values);
22119 const slot = node.get_static_attribute_value('slot');
22120 const nearest_inline_component = node.find_nearest(/InlineComponent/);
22121 if (slot && nearest_inline_component) {
22122 renderer.push();
22123 }
22124 renderer.push();
22125 renderer.render(node.children, options);
22126 const result = renderer.pop();
22127 renderer.add_expression(x `
22128 #slots.${node.slot_name}
22129 ? #slots.${node.slot_name}(${slot_data})
22130 : ${result}
22131 `);
22132 if (slot && nearest_inline_component) {
22133 const lets = node.lets;
22134 const seen = new Set(lets.map(l => l.name.name));
22135 nearest_inline_component.lets.forEach(l => {
22136 if (!seen.has(l.name.name))
22137 lets.push(l);
22138 });
22139 options.slot_scopes.set(slot, {
22140 input: get_slot_scope(node.lets),
22141 output: renderer.pop()
22142 });
22143 }
22144}
22145
22146function Tag$1 (node, renderer, _options) {
22147 const snippet = node.expression.node;
22148 renderer.add_expression(node.parent &&
22149 node.parent.type === 'Element' &&
22150 node.parent.name === 'style'
22151 ? snippet
22152 : x `@escape(${snippet})`);
22153}
22154
22155function Text (node, renderer, _options) {
22156 let text = node.data;
22157 if (!node.parent ||
22158 node.parent.type !== 'Element' ||
22159 (node.parent.name !== 'script' && node.parent.name !== 'style')) {
22160 // unless this Text node is inside a <script> or <style> element, escape &,<,>
22161 text = escape_html(text);
22162 }
22163 renderer.add_string(text);
22164}
22165
22166function Title (node, renderer, options) {
22167 renderer.push();
22168 renderer.add_string('<title>');
22169 renderer.render(node.children, options);
22170 renderer.add_string('</title>');
22171 const result = renderer.pop();
22172 renderer.add_expression(x `$$result.title = ${result}, ""`);
22173}
22174
22175function noop$1() { }
22176const handlers$1 = {
22177 AwaitBlock,
22178 Body: noop$1,
22179 Comment: Comment$1,
22180 DebugTag,
22181 EachBlock,
22182 Element,
22183 Head,
22184 IfBlock,
22185 InlineComponent,
22186 KeyBlock,
22187 MustacheTag: Tag$1,
22188 Options: noop$1,
22189 RawMustacheTag: HtmlTag,
22190 Slot,
22191 Text,
22192 Title,
22193 Window: noop$1
22194};
22195class Renderer$1 {
22196 constructor({ name }) {
22197 this.has_bindings = false;
22198 this.stack = [];
22199 this.targets = [];
22200 this.name = name;
22201 this.push();
22202 }
22203 add_string(str) {
22204 this.current.value += escape_template(str);
22205 }
22206 add_expression(node) {
22207 this.literal.quasis.push({
22208 type: 'TemplateElement',
22209 value: { raw: this.current.value, cooked: null },
22210 tail: false
22211 });
22212 this.literal.expressions.push(node);
22213 this.current.value = '';
22214 }
22215 push() {
22216 const current = this.current = { value: '' };
22217 const literal = this.literal = {
22218 type: 'TemplateLiteral',
22219 expressions: [],
22220 quasis: []
22221 };
22222 this.stack.push({ current, literal });
22223 }
22224 pop() {
22225 this.literal.quasis.push({
22226 type: 'TemplateElement',
22227 value: { raw: this.current.value, cooked: null },
22228 tail: true
22229 });
22230 const popped = this.stack.pop();
22231 const last = this.stack[this.stack.length - 1];
22232 if (last) {
22233 this.literal = last.literal;
22234 this.current = last.current;
22235 }
22236 return popped.literal;
22237 }
22238 render(nodes, options) {
22239 nodes.forEach(node => {
22240 const handler = handlers$1[node.type];
22241 if (!handler) {
22242 throw new Error(`No handler for '${node.type}' nodes`);
22243 }
22244 handler(node, this, options);
22245 });
22246 }
22247}
22248
22249function ssr(component, options) {
22250 const renderer = new Renderer$1({
22251 name: component.name
22252 });
22253 const { name } = component;
22254 // create $$render function
22255 renderer.render(trim(component.fragment.children), Object.assign({
22256 locate: component.locate
22257 }, options));
22258 // TODO put this inside the Renderer class
22259 const literal = renderer.pop();
22260 // TODO concatenate CSS maps
22261 const css = options.customElement ?
22262 { code: null, map: null } :
22263 component.stylesheet.render(options.filename, true);
22264 const uses_rest = component.var_lookup.has('$$restProps');
22265 const props = component.vars.filter(variable => !variable.module && variable.export_name);
22266 const rest = uses_rest ? b `let $$restProps = @compute_rest_props($$props, [${props.map(prop => `"${prop.export_name}"`).join(',')}]);` : null;
22267 const uses_slots = component.var_lookup.has('$$slots');
22268 const slots = uses_slots ? b `let $$slots = @compute_slots(#slots);` : null;
22269 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
22270 const reactive_store_values = reactive_stores
22271 .map(({ name }) => {
22272 const store_name = name.slice(1);
22273 const store = component.var_lookup.get(store_name);
22274 if (store && store.hoistable)
22275 return null;
22276 const assignment = b `${name} = @get_store_value(${store_name});`;
22277 return component.compile_options.dev
22278 ? b `@validate_store(${store_name}, '${store_name}'); ${assignment}`
22279 : assignment;
22280 })
22281 .filter(Boolean);
22282 component.rewrite_props(({ name }) => {
22283 const value = `$${name}`;
22284 let insert = b `${value} = @get_store_value(${name})`;
22285 if (component.compile_options.dev) {
22286 insert = b `@validate_store(${name}, '${name}'); ${insert}`;
22287 }
22288 return insert;
22289 });
22290 const instance_javascript = component.extract_javascript(component.ast.instance);
22291 // TODO only do this for props with a default value
22292 const parent_bindings = instance_javascript
22293 ? component.vars
22294 .filter(variable => !variable.module && variable.export_name)
22295 .map(prop => {
22296 return b `if ($$props.${prop.export_name} === void 0 && $$bindings.${prop.export_name} && ${prop.name} !== void 0) $$bindings.${prop.export_name}(${prop.name});`;
22297 })
22298 : [];
22299 const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
22300 const variable = component.var_lookup.get(name);
22301 return variable.injected;
22302 });
22303 const reactive_declarations = component.reactive_declarations.map(d => {
22304 const body = d.node.body;
22305 let statement = b `${body}`;
22306 if (!d.declaration) { // TODO do not add label if it's not referenced
22307 statement = b `$: { ${statement} }`;
22308 }
22309 return statement;
22310 });
22311 const main = renderer.has_bindings
22312 ? b `
22313 let $$settled;
22314 let $$rendered;
22315
22316 do {
22317 $$settled = true;
22318
22319 ${reactive_store_values}
22320
22321 ${injected.map(name => b `let ${name};`)}
22322
22323 ${reactive_declarations}
22324
22325 $$rendered = ${literal};
22326 } while (!$$settled);
22327
22328 return $$rendered;
22329 `
22330 : b `
22331 ${reactive_store_values}
22332
22333 ${injected.map(name => b `let ${name};`)}
22334
22335 ${reactive_declarations}
22336
22337 return ${literal};`;
22338 const blocks = [
22339 rest,
22340 slots,
22341 ...reactive_stores.map(({ name }) => {
22342 const store_name = name.slice(1);
22343 const store = component.var_lookup.get(store_name);
22344 if (store && store.hoistable) {
22345 return b `let ${name} = @get_store_value(${store_name});`;
22346 }
22347 return b `let ${name};`;
22348 }),
22349 instance_javascript,
22350 ...parent_bindings,
22351 css.code && b `$$result.css.add(#css);`,
22352 main
22353 ].filter(Boolean);
22354 const js = b `
22355 ${css.code ? b `
22356 const #css = {
22357 code: "${css.code}",
22358 map: ${css.map ? string_literal(css.map.toString()) : 'null'}
22359 };` : null}
22360
22361 ${component.extract_javascript(component.ast.module)}
22362
22363 ${component.fully_hoisted}
22364
22365 const ${name} = @create_ssr_component(($$result, $$props, $$bindings, #slots) => {
22366 ${blocks}
22367 });
22368 `;
22369 return { js, css };
22370}
22371function trim(nodes) {
22372 let start = 0;
22373 for (; start < nodes.length; start += 1) {
22374 const node = nodes[start];
22375 if (node.type !== 'Text')
22376 break;
22377 node.data = node.data.replace(/^\s+/, '');
22378 if (node.data)
22379 break;
22380 }
22381 let end = nodes.length;
22382 for (; end > start; end -= 1) {
22383 const node = nodes[end - 1];
22384 if (node.type !== 'Text')
22385 break;
22386 node.data = node.data.replace(/\s+$/, '');
22387 if (node.data)
22388 break;
22389 }
22390 return nodes.slice(start, end);
22391}
22392
22393const wrappers$1 = { esm, cjs };
22394function create_module(program, format, name, banner, sveltePath = 'svelte', helpers, globals, imports, module_exports) {
22395 const internal_path = `${sveltePath}/internal`;
22396 helpers.sort((a, b) => (a.name < b.name) ? -1 : 1);
22397 globals.sort((a, b) => (a.name < b.name) ? -1 : 1);
22398 if (format === 'esm') {
22399 return esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
22400 }
22401 if (format === 'cjs')
22402 return cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
22403 throw new Error(`options.format is invalid (must be ${list$1(Object.keys(wrappers$1))})`);
22404}
22405function edit_source(source, sveltePath) {
22406 return source === 'svelte' || source.startsWith('svelte/')
22407 ? source.replace('svelte', sveltePath)
22408 : source;
22409}
22410function get_internal_globals(globals, helpers) {
22411 return globals.length > 0 && {
22412 type: 'VariableDeclaration',
22413 kind: 'const',
22414 declarations: [{
22415 type: 'VariableDeclarator',
22416 id: {
22417 type: 'ObjectPattern',
22418 properties: globals.map(g => ({
22419 type: 'Property',
22420 method: false,
22421 shorthand: false,
22422 computed: false,
22423 key: { type: 'Identifier', name: g.name },
22424 value: g.alias,
22425 kind: 'init'
22426 }))
22427 },
22428 init: helpers.find(({ name }) => name === 'globals').alias
22429 }]
22430 };
22431}
22432function esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
22433 const import_declaration = {
22434 type: 'ImportDeclaration',
22435 specifiers: helpers.map(h => ({
22436 type: 'ImportSpecifier',
22437 local: h.alias,
22438 imported: { type: 'Identifier', name: h.name }
22439 })),
22440 source: { type: 'Literal', value: internal_path }
22441 };
22442 const internal_globals = get_internal_globals(globals, helpers);
22443 // edit user imports
22444 imports.forEach(node => {
22445 node.source.value = edit_source(node.source.value, sveltePath);
22446 });
22447 const exports = module_exports.length > 0 && {
22448 type: 'ExportNamedDeclaration',
22449 specifiers: module_exports.map(x => ({
22450 type: 'Specifier',
22451 local: { type: 'Identifier', name: x.name },
22452 exported: { type: 'Identifier', name: x.as }
22453 }))
22454 };
22455 program.body = b `
22456 /* ${banner} */
22457
22458 ${import_declaration}
22459 ${internal_globals}
22460 ${imports}
22461
22462 ${program.body}
22463
22464 export default ${name};
22465 ${exports}
22466 `;
22467}
22468function cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
22469 const internal_requires = {
22470 type: 'VariableDeclaration',
22471 kind: 'const',
22472 declarations: [{
22473 type: 'VariableDeclarator',
22474 id: {
22475 type: 'ObjectPattern',
22476 properties: helpers.map(h => ({
22477 type: 'Property',
22478 method: false,
22479 shorthand: false,
22480 computed: false,
22481 key: { type: 'Identifier', name: h.name },
22482 value: h.alias,
22483 kind: 'init'
22484 }))
22485 },
22486 init: x `require("${internal_path}")`
22487 }]
22488 };
22489 const internal_globals = get_internal_globals(globals, helpers);
22490 const user_requires = imports.map(node => {
22491 const init = x `require("${edit_source(node.source.value, sveltePath)}")`;
22492 if (node.specifiers.length === 0) {
22493 return b `${init};`;
22494 }
22495 return {
22496 type: 'VariableDeclaration',
22497 kind: 'const',
22498 declarations: [{
22499 type: 'VariableDeclarator',
22500 id: node.specifiers[0].type === 'ImportNamespaceSpecifier'
22501 ? { type: 'Identifier', name: node.specifiers[0].local.name }
22502 : {
22503 type: 'ObjectPattern',
22504 properties: node.specifiers.map(s => ({
22505 type: 'Property',
22506 method: false,
22507 shorthand: false,
22508 computed: false,
22509 key: s.type === 'ImportSpecifier' ? s.imported : { type: 'Identifier', name: 'default' },
22510 value: s.local,
22511 kind: 'init'
22512 }))
22513 },
22514 init
22515 }]
22516 };
22517 });
22518 const exports = module_exports.map(x => b `exports.${{ type: 'Identifier', name: x.as }} = ${{ type: 'Identifier', name: x.name }};`);
22519 program.body = b `
22520 /* ${banner} */
22521
22522 "use strict";
22523 ${internal_requires}
22524 ${internal_globals}
22525 ${user_requires}
22526
22527 ${program.body}
22528
22529 exports.default = ${name};
22530 ${exports}
22531 `;
22532}
22533
22534var Chunk = function Chunk(start, end, content) {
22535 this.start = start;
22536 this.end = end;
22537 this.original = content;
22538
22539 this.intro = '';
22540 this.outro = '';
22541
22542 this.content = content;
22543 this.storeName = false;
22544 this.edited = false;
22545
22546 // we make these non-enumerable, for sanity while debugging
22547 Object.defineProperties(this, {
22548 previous: { writable: true, value: null },
22549 next: { writable: true, value: null }
22550 });
22551};
22552
22553Chunk.prototype.appendLeft = function appendLeft (content) {
22554 this.outro += content;
22555};
22556
22557Chunk.prototype.appendRight = function appendRight (content) {
22558 this.intro = this.intro + content;
22559};
22560
22561Chunk.prototype.clone = function clone () {
22562 var chunk = new Chunk(this.start, this.end, this.original);
22563
22564 chunk.intro = this.intro;
22565 chunk.outro = this.outro;
22566 chunk.content = this.content;
22567 chunk.storeName = this.storeName;
22568 chunk.edited = this.edited;
22569
22570 return chunk;
22571};
22572
22573Chunk.prototype.contains = function contains (index) {
22574 return this.start < index && index < this.end;
22575};
22576
22577Chunk.prototype.eachNext = function eachNext (fn) {
22578 var chunk = this;
22579 while (chunk) {
22580 fn(chunk);
22581 chunk = chunk.next;
22582 }
22583};
22584
22585Chunk.prototype.eachPrevious = function eachPrevious (fn) {
22586 var chunk = this;
22587 while (chunk) {
22588 fn(chunk);
22589 chunk = chunk.previous;
22590 }
22591};
22592
22593Chunk.prototype.edit = function edit (content, storeName, contentOnly) {
22594 this.content = content;
22595 if (!contentOnly) {
22596 this.intro = '';
22597 this.outro = '';
22598 }
22599 this.storeName = storeName;
22600
22601 this.edited = true;
22602
22603 return this;
22604};
22605
22606Chunk.prototype.prependLeft = function prependLeft (content) {
22607 this.outro = content + this.outro;
22608};
22609
22610Chunk.prototype.prependRight = function prependRight (content) {
22611 this.intro = content + this.intro;
22612};
22613
22614Chunk.prototype.split = function split (index) {
22615 var sliceIndex = index - this.start;
22616
22617 var originalBefore = this.original.slice(0, sliceIndex);
22618 var originalAfter = this.original.slice(sliceIndex);
22619
22620 this.original = originalBefore;
22621
22622 var newChunk = new Chunk(index, this.end, originalAfter);
22623 newChunk.outro = this.outro;
22624 this.outro = '';
22625
22626 this.end = index;
22627
22628 if (this.edited) {
22629 // TODO is this block necessary?...
22630 newChunk.edit('', false);
22631 this.content = '';
22632 } else {
22633 this.content = originalBefore;
22634 }
22635
22636 newChunk.next = this.next;
22637 if (newChunk.next) { newChunk.next.previous = newChunk; }
22638 newChunk.previous = this;
22639 this.next = newChunk;
22640
22641 return newChunk;
22642};
22643
22644Chunk.prototype.toString = function toString () {
22645 return this.intro + this.content + this.outro;
22646};
22647
22648Chunk.prototype.trimEnd = function trimEnd (rx) {
22649 this.outro = this.outro.replace(rx, '');
22650 if (this.outro.length) { return true; }
22651
22652 var trimmed = this.content.replace(rx, '');
22653
22654 if (trimmed.length) {
22655 if (trimmed !== this.content) {
22656 this.split(this.start + trimmed.length).edit('', undefined, true);
22657 }
22658 return true;
22659
22660 } else {
22661 this.edit('', undefined, true);
22662
22663 this.intro = this.intro.replace(rx, '');
22664 if (this.intro.length) { return true; }
22665 }
22666};
22667
22668Chunk.prototype.trimStart = function trimStart (rx) {
22669 this.intro = this.intro.replace(rx, '');
22670 if (this.intro.length) { return true; }
22671
22672 var trimmed = this.content.replace(rx, '');
22673
22674 if (trimmed.length) {
22675 if (trimmed !== this.content) {
22676 this.split(this.end - trimmed.length);
22677 this.edit('', undefined, true);
22678 }
22679 return true;
22680
22681 } else {
22682 this.edit('', undefined, true);
22683
22684 this.outro = this.outro.replace(rx, '');
22685 if (this.outro.length) { return true; }
22686 }
22687};
22688
22689var btoa$1 = function () {
22690 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
22691};
22692if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
22693 btoa$1 = function (str) { return window.btoa(unescape(encodeURIComponent(str))); };
22694} else if (typeof Buffer === 'function') {
22695 btoa$1 = function (str) { return Buffer.from(str, 'utf-8').toString('base64'); };
22696}
22697
22698var SourceMap = function SourceMap(properties) {
22699 this.version = 3;
22700 this.file = properties.file;
22701 this.sources = properties.sources;
22702 this.sourcesContent = properties.sourcesContent;
22703 this.names = properties.names;
22704 this.mappings = encode(properties.mappings);
22705};
22706
22707SourceMap.prototype.toString = function toString () {
22708 return JSON.stringify(this);
22709};
22710
22711SourceMap.prototype.toUrl = function toUrl () {
22712 return 'data:application/json;charset=utf-8;base64,' + btoa$1(this.toString());
22713};
22714
22715function guessIndent(code) {
22716 var lines = code.split('\n');
22717
22718 var tabbed = lines.filter(function (line) { return /^\t+/.test(line); });
22719 var spaced = lines.filter(function (line) { return /^ {2,}/.test(line); });
22720
22721 if (tabbed.length === 0 && spaced.length === 0) {
22722 return null;
22723 }
22724
22725 // More lines tabbed than spaced? Assume tabs, and
22726 // default to tabs in the case of a tie (or nothing
22727 // to go on)
22728 if (tabbed.length >= spaced.length) {
22729 return '\t';
22730 }
22731
22732 // Otherwise, we need to guess the multiple
22733 var min = spaced.reduce(function (previous, current) {
22734 var numSpaces = /^ +/.exec(current)[0].length;
22735 return Math.min(numSpaces, previous);
22736 }, Infinity);
22737
22738 return new Array(min + 1).join(' ');
22739}
22740
22741function getRelativePath(from, to) {
22742 var fromParts = from.split(/[/\\]/);
22743 var toParts = to.split(/[/\\]/);
22744
22745 fromParts.pop(); // get dirname
22746
22747 while (fromParts[0] === toParts[0]) {
22748 fromParts.shift();
22749 toParts.shift();
22750 }
22751
22752 if (fromParts.length) {
22753 var i = fromParts.length;
22754 while (i--) { fromParts[i] = '..'; }
22755 }
22756
22757 return fromParts.concat(toParts).join('/');
22758}
22759
22760var toString$1 = Object.prototype.toString;
22761
22762function isObject(thing) {
22763 return toString$1.call(thing) === '[object Object]';
22764}
22765
22766function getLocator$1(source) {
22767 var originalLines = source.split('\n');
22768 var lineOffsets = [];
22769
22770 for (var i = 0, pos = 0; i < originalLines.length; i++) {
22771 lineOffsets.push(pos);
22772 pos += originalLines[i].length + 1;
22773 }
22774
22775 return function locate(index) {
22776 var i = 0;
22777 var j = lineOffsets.length;
22778 while (i < j) {
22779 var m = (i + j) >> 1;
22780 if (index < lineOffsets[m]) {
22781 j = m;
22782 } else {
22783 i = m + 1;
22784 }
22785 }
22786 var line = i - 1;
22787 var column = index - lineOffsets[line];
22788 return { line: line, column: column };
22789 };
22790}
22791
22792var Mappings = function Mappings(hires) {
22793 this.hires = hires;
22794 this.generatedCodeLine = 0;
22795 this.generatedCodeColumn = 0;
22796 this.raw = [];
22797 this.rawSegments = this.raw[this.generatedCodeLine] = [];
22798 this.pending = null;
22799};
22800
22801Mappings.prototype.addEdit = function addEdit (sourceIndex, content, loc, nameIndex) {
22802 if (content.length) {
22803 var segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
22804 if (nameIndex >= 0) {
22805 segment.push(nameIndex);
22806 }
22807 this.rawSegments.push(segment);
22808 } else if (this.pending) {
22809 this.rawSegments.push(this.pending);
22810 }
22811
22812 this.advance(content);
22813 this.pending = null;
22814};
22815
22816Mappings.prototype.addUneditedChunk = function addUneditedChunk (sourceIndex, chunk, original, loc, sourcemapLocations) {
22817 var originalCharIndex = chunk.start;
22818 var first = true;
22819
22820 while (originalCharIndex < chunk.end) {
22821 if (this.hires || first || sourcemapLocations[originalCharIndex]) {
22822 this.rawSegments.push([this.generatedCodeColumn, sourceIndex, loc.line, loc.column]);
22823 }
22824
22825 if (original[originalCharIndex] === '\n') {
22826 loc.line += 1;
22827 loc.column = 0;
22828 this.generatedCodeLine += 1;
22829 this.raw[this.generatedCodeLine] = this.rawSegments = [];
22830 this.generatedCodeColumn = 0;
22831 } else {
22832 loc.column += 1;
22833 this.generatedCodeColumn += 1;
22834 }
22835
22836 originalCharIndex += 1;
22837 first = false;
22838 }
22839
22840 this.pending = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
22841};
22842
22843Mappings.prototype.advance = function advance (str) {
22844 if (!str) { return; }
22845
22846 var lines = str.split('\n');
22847
22848 if (lines.length > 1) {
22849 for (var i = 0; i < lines.length - 1; i++) {
22850 this.generatedCodeLine++;
22851 this.raw[this.generatedCodeLine] = this.rawSegments = [];
22852 }
22853 this.generatedCodeColumn = 0;
22854 }
22855
22856 this.generatedCodeColumn += lines[lines.length - 1].length;
22857};
22858
22859var n = '\n';
22860
22861var warned = {
22862 insertLeft: false,
22863 insertRight: false,
22864 storeName: false
22865};
22866
22867var MagicString = function MagicString(string, options) {
22868 if ( options === void 0 ) options = {};
22869
22870 var chunk = new Chunk(0, string.length, string);
22871
22872 Object.defineProperties(this, {
22873 original: { writable: true, value: string },
22874 outro: { writable: true, value: '' },
22875 intro: { writable: true, value: '' },
22876 firstChunk: { writable: true, value: chunk },
22877 lastChunk: { writable: true, value: chunk },
22878 lastSearchedChunk: { writable: true, value: chunk },
22879 byStart: { writable: true, value: {} },
22880 byEnd: { writable: true, value: {} },
22881 filename: { writable: true, value: options.filename },
22882 indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
22883 sourcemapLocations: { writable: true, value: {} },
22884 storedNames: { writable: true, value: {} },
22885 indentStr: { writable: true, value: guessIndent(string) }
22886 });
22887
22888 this.byStart[0] = chunk;
22889 this.byEnd[string.length] = chunk;
22890};
22891
22892MagicString.prototype.addSourcemapLocation = function addSourcemapLocation (char) {
22893 this.sourcemapLocations[char] = true;
22894};
22895
22896MagicString.prototype.append = function append (content) {
22897 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
22898
22899 this.outro += content;
22900 return this;
22901};
22902
22903MagicString.prototype.appendLeft = function appendLeft (index, content) {
22904 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22905
22906 this._split(index);
22907
22908 var chunk = this.byEnd[index];
22909
22910 if (chunk) {
22911 chunk.appendLeft(content);
22912 } else {
22913 this.intro += content;
22914 }
22915 return this;
22916};
22917
22918MagicString.prototype.appendRight = function appendRight (index, content) {
22919 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22920
22921 this._split(index);
22922
22923 var chunk = this.byStart[index];
22924
22925 if (chunk) {
22926 chunk.appendRight(content);
22927 } else {
22928 this.outro += content;
22929 }
22930 return this;
22931};
22932
22933MagicString.prototype.clone = function clone () {
22934 var cloned = new MagicString(this.original, { filename: this.filename });
22935
22936 var originalChunk = this.firstChunk;
22937 var clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());
22938
22939 while (originalChunk) {
22940 cloned.byStart[clonedChunk.start] = clonedChunk;
22941 cloned.byEnd[clonedChunk.end] = clonedChunk;
22942
22943 var nextOriginalChunk = originalChunk.next;
22944 var nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
22945
22946 if (nextClonedChunk) {
22947 clonedChunk.next = nextClonedChunk;
22948 nextClonedChunk.previous = clonedChunk;
22949
22950 clonedChunk = nextClonedChunk;
22951 }
22952
22953 originalChunk = nextOriginalChunk;
22954 }
22955
22956 cloned.lastChunk = clonedChunk;
22957
22958 if (this.indentExclusionRanges) {
22959 cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
22960 }
22961
22962 Object.keys(this.sourcemapLocations).forEach(function (loc) {
22963 cloned.sourcemapLocations[loc] = true;
22964 });
22965
22966 return cloned;
22967};
22968
22969MagicString.prototype.generateDecodedMap = function generateDecodedMap (options) {
22970 var this$1 = this;
22971
22972 options = options || {};
22973
22974 var sourceIndex = 0;
22975 var names = Object.keys(this.storedNames);
22976 var mappings = new Mappings(options.hires);
22977
22978 var locate = getLocator$1(this.original);
22979
22980 if (this.intro) {
22981 mappings.advance(this.intro);
22982 }
22983
22984 this.firstChunk.eachNext(function (chunk) {
22985 var loc = locate(chunk.start);
22986
22987 if (chunk.intro.length) { mappings.advance(chunk.intro); }
22988
22989 if (chunk.edited) {
22990 mappings.addEdit(
22991 sourceIndex,
22992 chunk.content,
22993 loc,
22994 chunk.storeName ? names.indexOf(chunk.original) : -1
22995 );
22996 } else {
22997 mappings.addUneditedChunk(sourceIndex, chunk, this$1.original, loc, this$1.sourcemapLocations);
22998 }
22999
23000 if (chunk.outro.length) { mappings.advance(chunk.outro); }
23001 });
23002
23003 return {
23004 file: options.file ? options.file.split(/[/\\]/).pop() : null,
23005 sources: [options.source ? getRelativePath(options.file || '', options.source) : null],
23006 sourcesContent: options.includeContent ? [this.original] : [null],
23007 names: names,
23008 mappings: mappings.raw
23009 };
23010};
23011
23012MagicString.prototype.generateMap = function generateMap (options) {
23013 return new SourceMap(this.generateDecodedMap(options));
23014};
23015
23016MagicString.prototype.getIndentString = function getIndentString () {
23017 return this.indentStr === null ? '\t' : this.indentStr;
23018};
23019
23020MagicString.prototype.indent = function indent (indentStr, options) {
23021 var pattern = /^[^\r\n]/gm;
23022
23023 if (isObject(indentStr)) {
23024 options = indentStr;
23025 indentStr = undefined;
23026 }
23027
23028 indentStr = indentStr !== undefined ? indentStr : this.indentStr || '\t';
23029
23030 if (indentStr === '') { return this; } // noop
23031
23032 options = options || {};
23033
23034 // Process exclusion ranges
23035 var isExcluded = {};
23036
23037 if (options.exclude) {
23038 var exclusions =
23039 typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;
23040 exclusions.forEach(function (exclusion) {
23041 for (var i = exclusion[0]; i < exclusion[1]; i += 1) {
23042 isExcluded[i] = true;
23043 }
23044 });
23045 }
23046
23047 var shouldIndentNextCharacter = options.indentStart !== false;
23048 var replacer = function (match) {
23049 if (shouldIndentNextCharacter) { return ("" + indentStr + match); }
23050 shouldIndentNextCharacter = true;
23051 return match;
23052 };
23053
23054 this.intro = this.intro.replace(pattern, replacer);
23055
23056 var charIndex = 0;
23057 var chunk = this.firstChunk;
23058
23059 while (chunk) {
23060 var end = chunk.end;
23061
23062 if (chunk.edited) {
23063 if (!isExcluded[charIndex]) {
23064 chunk.content = chunk.content.replace(pattern, replacer);
23065
23066 if (chunk.content.length) {
23067 shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';
23068 }
23069 }
23070 } else {
23071 charIndex = chunk.start;
23072
23073 while (charIndex < end) {
23074 if (!isExcluded[charIndex]) {
23075 var char = this.original[charIndex];
23076
23077 if (char === '\n') {
23078 shouldIndentNextCharacter = true;
23079 } else if (char !== '\r' && shouldIndentNextCharacter) {
23080 shouldIndentNextCharacter = false;
23081
23082 if (charIndex === chunk.start) {
23083 chunk.prependRight(indentStr);
23084 } else {
23085 this._splitChunk(chunk, charIndex);
23086 chunk = chunk.next;
23087 chunk.prependRight(indentStr);
23088 }
23089 }
23090 }
23091
23092 charIndex += 1;
23093 }
23094 }
23095
23096 charIndex = chunk.end;
23097 chunk = chunk.next;
23098 }
23099
23100 this.outro = this.outro.replace(pattern, replacer);
23101
23102 return this;
23103};
23104
23105MagicString.prototype.insert = function insert () {
23106 throw new Error('magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)');
23107};
23108
23109MagicString.prototype.insertLeft = function insertLeft (index, content) {
23110 if (!warned.insertLeft) {
23111 console.warn('magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead'); // eslint-disable-line no-console
23112 warned.insertLeft = true;
23113 }
23114
23115 return this.appendLeft(index, content);
23116};
23117
23118MagicString.prototype.insertRight = function insertRight (index, content) {
23119 if (!warned.insertRight) {
23120 console.warn('magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead'); // eslint-disable-line no-console
23121 warned.insertRight = true;
23122 }
23123
23124 return this.prependRight(index, content);
23125};
23126
23127MagicString.prototype.move = function move (start, end, index) {
23128 if (index >= start && index <= end) { throw new Error('Cannot move a selection inside itself'); }
23129
23130 this._split(start);
23131 this._split(end);
23132 this._split(index);
23133
23134 var first = this.byStart[start];
23135 var last = this.byEnd[end];
23136
23137 var oldLeft = first.previous;
23138 var oldRight = last.next;
23139
23140 var newRight = this.byStart[index];
23141 if (!newRight && last === this.lastChunk) { return this; }
23142 var newLeft = newRight ? newRight.previous : this.lastChunk;
23143
23144 if (oldLeft) { oldLeft.next = oldRight; }
23145 if (oldRight) { oldRight.previous = oldLeft; }
23146
23147 if (newLeft) { newLeft.next = first; }
23148 if (newRight) { newRight.previous = last; }
23149
23150 if (!first.previous) { this.firstChunk = last.next; }
23151 if (!last.next) {
23152 this.lastChunk = first.previous;
23153 this.lastChunk.next = null;
23154 }
23155
23156 first.previous = newLeft;
23157 last.next = newRight || null;
23158
23159 if (!newLeft) { this.firstChunk = first; }
23160 if (!newRight) { this.lastChunk = last; }
23161 return this;
23162};
23163
23164MagicString.prototype.overwrite = function overwrite (start, end, content, options) {
23165 if (typeof content !== 'string') { throw new TypeError('replacement content must be a string'); }
23166
23167 while (start < 0) { start += this.original.length; }
23168 while (end < 0) { end += this.original.length; }
23169
23170 if (end > this.original.length) { throw new Error('end is out of bounds'); }
23171 if (start === end)
23172 { throw new Error('Cannot overwrite a zero-length range – use appendLeft or prependRight instead'); }
23173
23174 this._split(start);
23175 this._split(end);
23176
23177 if (options === true) {
23178 if (!warned.storeName) {
23179 console.warn('The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string'); // eslint-disable-line no-console
23180 warned.storeName = true;
23181 }
23182
23183 options = { storeName: true };
23184 }
23185 var storeName = options !== undefined ? options.storeName : false;
23186 var contentOnly = options !== undefined ? options.contentOnly : false;
23187
23188 if (storeName) {
23189 var original = this.original.slice(start, end);
23190 this.storedNames[original] = true;
23191 }
23192
23193 var first = this.byStart[start];
23194 var last = this.byEnd[end];
23195
23196 if (first) {
23197 if (end > first.end && first.next !== this.byStart[first.end]) {
23198 throw new Error('Cannot overwrite across a split point');
23199 }
23200
23201 first.edit(content, storeName, contentOnly);
23202
23203 if (first !== last) {
23204 var chunk = first.next;
23205 while (chunk !== last) {
23206 chunk.edit('', false);
23207 chunk = chunk.next;
23208 }
23209
23210 chunk.edit('', false);
23211 }
23212 } else {
23213 // must be inserting at the end
23214 var newChunk = new Chunk(start, end, '').edit(content, storeName);
23215
23216 // TODO last chunk in the array may not be the last chunk, if it's moved...
23217 last.next = newChunk;
23218 newChunk.previous = last;
23219 }
23220 return this;
23221};
23222
23223MagicString.prototype.prepend = function prepend (content) {
23224 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
23225
23226 this.intro = content + this.intro;
23227 return this;
23228};
23229
23230MagicString.prototype.prependLeft = function prependLeft (index, content) {
23231 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
23232
23233 this._split(index);
23234
23235 var chunk = this.byEnd[index];
23236
23237 if (chunk) {
23238 chunk.prependLeft(content);
23239 } else {
23240 this.intro = content + this.intro;
23241 }
23242 return this;
23243};
23244
23245MagicString.prototype.prependRight = function prependRight (index, content) {
23246 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
23247
23248 this._split(index);
23249
23250 var chunk = this.byStart[index];
23251
23252 if (chunk) {
23253 chunk.prependRight(content);
23254 } else {
23255 this.outro = content + this.outro;
23256 }
23257 return this;
23258};
23259
23260MagicString.prototype.remove = function remove (start, end) {
23261 while (start < 0) { start += this.original.length; }
23262 while (end < 0) { end += this.original.length; }
23263
23264 if (start === end) { return this; }
23265
23266 if (start < 0 || end > this.original.length) { throw new Error('Character is out of bounds'); }
23267 if (start > end) { throw new Error('end must be greater than start'); }
23268
23269 this._split(start);
23270 this._split(end);
23271
23272 var chunk = this.byStart[start];
23273
23274 while (chunk) {
23275 chunk.intro = '';
23276 chunk.outro = '';
23277 chunk.edit('');
23278
23279 chunk = end > chunk.end ? this.byStart[chunk.end] : null;
23280 }
23281 return this;
23282};
23283
23284MagicString.prototype.lastChar = function lastChar () {
23285 if (this.outro.length)
23286 { return this.outro[this.outro.length - 1]; }
23287 var chunk = this.lastChunk;
23288 do {
23289 if (chunk.outro.length)
23290 { return chunk.outro[chunk.outro.length - 1]; }
23291 if (chunk.content.length)
23292 { return chunk.content[chunk.content.length - 1]; }
23293 if (chunk.intro.length)
23294 { return chunk.intro[chunk.intro.length - 1]; }
23295 } while (chunk = chunk.previous);
23296 if (this.intro.length)
23297 { return this.intro[this.intro.length - 1]; }
23298 return '';
23299};
23300
23301MagicString.prototype.lastLine = function lastLine () {
23302 var lineIndex = this.outro.lastIndexOf(n);
23303 if (lineIndex !== -1)
23304 { return this.outro.substr(lineIndex + 1); }
23305 var lineStr = this.outro;
23306 var chunk = this.lastChunk;
23307 do {
23308 if (chunk.outro.length > 0) {
23309 lineIndex = chunk.outro.lastIndexOf(n);
23310 if (lineIndex !== -1)
23311 { return chunk.outro.substr(lineIndex + 1) + lineStr; }
23312 lineStr = chunk.outro + lineStr;
23313 }
23314
23315 if (chunk.content.length > 0) {
23316 lineIndex = chunk.content.lastIndexOf(n);
23317 if (lineIndex !== -1)
23318 { return chunk.content.substr(lineIndex + 1) + lineStr; }
23319 lineStr = chunk.content + lineStr;
23320 }
23321
23322 if (chunk.intro.length > 0) {
23323 lineIndex = chunk.intro.lastIndexOf(n);
23324 if (lineIndex !== -1)
23325 { return chunk.intro.substr(lineIndex + 1) + lineStr; }
23326 lineStr = chunk.intro + lineStr;
23327 }
23328 } while (chunk = chunk.previous);
23329 lineIndex = this.intro.lastIndexOf(n);
23330 if (lineIndex !== -1)
23331 { return this.intro.substr(lineIndex + 1) + lineStr; }
23332 return this.intro + lineStr;
23333};
23334
23335MagicString.prototype.slice = function slice (start, end) {
23336 if ( start === void 0 ) start = 0;
23337 if ( end === void 0 ) end = this.original.length;
23338
23339 while (start < 0) { start += this.original.length; }
23340 while (end < 0) { end += this.original.length; }
23341
23342 var result = '';
23343
23344 // find start chunk
23345 var chunk = this.firstChunk;
23346 while (chunk && (chunk.start > start || chunk.end <= start)) {
23347 // found end chunk before start
23348 if (chunk.start < end && chunk.end >= end) {
23349 return result;
23350 }
23351
23352 chunk = chunk.next;
23353 }
23354
23355 if (chunk && chunk.edited && chunk.start !== start)
23356 { throw new Error(("Cannot use replaced character " + start + " as slice start anchor.")); }
23357
23358 var startChunk = chunk;
23359 while (chunk) {
23360 if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
23361 result += chunk.intro;
23362 }
23363
23364 var containsEnd = chunk.start < end && chunk.end >= end;
23365 if (containsEnd && chunk.edited && chunk.end !== end)
23366 { throw new Error(("Cannot use replaced character " + end + " as slice end anchor.")); }
23367
23368 var sliceStart = startChunk === chunk ? start - chunk.start : 0;
23369 var sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
23370
23371 result += chunk.content.slice(sliceStart, sliceEnd);
23372
23373 if (chunk.outro && (!containsEnd || chunk.end === end)) {
23374 result += chunk.outro;
23375 }
23376
23377 if (containsEnd) {
23378 break;
23379 }
23380
23381 chunk = chunk.next;
23382 }
23383
23384 return result;
23385};
23386
23387// TODO deprecate this? not really very useful
23388MagicString.prototype.snip = function snip (start, end) {
23389 var clone = this.clone();
23390 clone.remove(0, start);
23391 clone.remove(end, clone.original.length);
23392
23393 return clone;
23394};
23395
23396MagicString.prototype._split = function _split (index) {
23397 if (this.byStart[index] || this.byEnd[index]) { return; }
23398
23399 var chunk = this.lastSearchedChunk;
23400 var searchForward = index > chunk.end;
23401
23402 while (chunk) {
23403 if (chunk.contains(index)) { return this._splitChunk(chunk, index); }
23404
23405 chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
23406 }
23407};
23408
23409MagicString.prototype._splitChunk = function _splitChunk (chunk, index) {
23410 if (chunk.edited && chunk.content.length) {
23411 // zero-length edited chunks are a special case (overlapping replacements)
23412 var loc = getLocator$1(this.original)(index);
23413 throw new Error(
23414 ("Cannot split a chunk that has already been edited (" + (loc.line) + ":" + (loc.column) + " – \"" + (chunk.original) + "\")")
23415 );
23416 }
23417
23418 var newChunk = chunk.split(index);
23419
23420 this.byEnd[index] = chunk;
23421 this.byStart[index] = newChunk;
23422 this.byEnd[newChunk.end] = newChunk;
23423
23424 if (chunk === this.lastChunk) { this.lastChunk = newChunk; }
23425
23426 this.lastSearchedChunk = chunk;
23427 return true;
23428};
23429
23430MagicString.prototype.toString = function toString () {
23431 var str = this.intro;
23432
23433 var chunk = this.firstChunk;
23434 while (chunk) {
23435 str += chunk.toString();
23436 chunk = chunk.next;
23437 }
23438
23439 return str + this.outro;
23440};
23441
23442MagicString.prototype.isEmpty = function isEmpty () {
23443 var chunk = this.firstChunk;
23444 do {
23445 if (chunk.intro.length && chunk.intro.trim() ||
23446 chunk.content.length && chunk.content.trim() ||
23447 chunk.outro.length && chunk.outro.trim())
23448 { return false; }
23449 } while (chunk = chunk.next);
23450 return true;
23451};
23452
23453MagicString.prototype.length = function length () {
23454 var chunk = this.firstChunk;
23455 var length = 0;
23456 do {
23457 length += chunk.intro.length + chunk.content.length + chunk.outro.length;
23458 } while (chunk = chunk.next);
23459 return length;
23460};
23461
23462MagicString.prototype.trimLines = function trimLines () {
23463 return this.trim('[\\r\\n]');
23464};
23465
23466MagicString.prototype.trim = function trim (charType) {
23467 return this.trimStart(charType).trimEnd(charType);
23468};
23469
23470MagicString.prototype.trimEndAborted = function trimEndAborted (charType) {
23471 var rx = new RegExp((charType || '\\s') + '+$');
23472
23473 this.outro = this.outro.replace(rx, '');
23474 if (this.outro.length) { return true; }
23475
23476 var chunk = this.lastChunk;
23477
23478 do {
23479 var end = chunk.end;
23480 var aborted = chunk.trimEnd(rx);
23481
23482 // if chunk was trimmed, we have a new lastChunk
23483 if (chunk.end !== end) {
23484 if (this.lastChunk === chunk) {
23485 this.lastChunk = chunk.next;
23486 }
23487
23488 this.byEnd[chunk.end] = chunk;
23489 this.byStart[chunk.next.start] = chunk.next;
23490 this.byEnd[chunk.next.end] = chunk.next;
23491 }
23492
23493 if (aborted) { return true; }
23494 chunk = chunk.previous;
23495 } while (chunk);
23496
23497 return false;
23498};
23499
23500MagicString.prototype.trimEnd = function trimEnd (charType) {
23501 this.trimEndAborted(charType);
23502 return this;
23503};
23504MagicString.prototype.trimStartAborted = function trimStartAborted (charType) {
23505 var rx = new RegExp('^' + (charType || '\\s') + '+');
23506
23507 this.intro = this.intro.replace(rx, '');
23508 if (this.intro.length) { return true; }
23509
23510 var chunk = this.firstChunk;
23511
23512 do {
23513 var end = chunk.end;
23514 var aborted = chunk.trimStart(rx);
23515
23516 if (chunk.end !== end) {
23517 // special case...
23518 if (chunk === this.lastChunk) { this.lastChunk = chunk.next; }
23519
23520 this.byEnd[chunk.end] = chunk;
23521 this.byStart[chunk.next.start] = chunk.next;
23522 this.byEnd[chunk.next.end] = chunk.next;
23523 }
23524
23525 if (aborted) { return true; }
23526 chunk = chunk.next;
23527 } while (chunk);
23528
23529 return false;
23530};
23531
23532MagicString.prototype.trimStart = function trimStart (charType) {
23533 this.trimStartAborted(charType);
23534 return this;
23535};
23536
23537const UNKNOWN = {};
23538function gather_possible_values(node, set) {
23539 if (node.type === 'Literal') {
23540 set.add(node.value);
23541 }
23542 else if (node.type === 'ConditionalExpression') {
23543 gather_possible_values(node.consequent, set);
23544 gather_possible_values(node.alternate, set);
23545 }
23546 else {
23547 set.add(UNKNOWN);
23548 }
23549}
23550
23551var BlockAppliesToNode;
23552(function (BlockAppliesToNode) {
23553 BlockAppliesToNode[BlockAppliesToNode["NotPossible"] = 0] = "NotPossible";
23554 BlockAppliesToNode[BlockAppliesToNode["Possible"] = 1] = "Possible";
23555 BlockAppliesToNode[BlockAppliesToNode["UnknownSelectorType"] = 2] = "UnknownSelectorType";
23556})(BlockAppliesToNode || (BlockAppliesToNode = {}));
23557var NodeExist;
23558(function (NodeExist) {
23559 NodeExist[NodeExist["Probably"] = 1] = "Probably";
23560 NodeExist[NodeExist["Definitely"] = 2] = "Definitely";
23561})(NodeExist || (NodeExist = {}));
23562const whitelist_attribute_selector = new Map([
23563 ['details', new Set(['open'])]
23564]);
23565class Selector$1 {
23566 constructor(node, stylesheet) {
23567 this.node = node;
23568 this.stylesheet = stylesheet;
23569 this.blocks = group_selectors(node);
23570 // take trailing :global(...) selectors out of consideration
23571 let i = this.blocks.length;
23572 while (i > 0) {
23573 if (!this.blocks[i - 1].global)
23574 break;
23575 i -= 1;
23576 }
23577 this.local_blocks = this.blocks.slice(0, i);
23578 this.used = this.local_blocks.length === 0;
23579 }
23580 apply(node) {
23581 const to_encapsulate = [];
23582 apply_selector(this.local_blocks.slice(), node, to_encapsulate);
23583 if (to_encapsulate.length > 0) {
23584 to_encapsulate.forEach(({ node, block }) => {
23585 this.stylesheet.nodes_with_css_class.add(node);
23586 block.should_encapsulate = true;
23587 });
23588 this.used = true;
23589 }
23590 }
23591 minify(code) {
23592 let c = null;
23593 this.blocks.forEach((block, i) => {
23594 if (i > 0) {
23595 if (block.start - c > 1) {
23596 code.overwrite(c, block.start, block.combinator.name || ' ');
23597 }
23598 }
23599 c = block.end;
23600 });
23601 }
23602 transform(code, attr, max_amount_class_specificity_increased) {
23603 const amount_class_specificity_to_increase = max_amount_class_specificity_increased - this.blocks.filter(block => block.should_encapsulate).length;
23604 function encapsulate_block(block, attr) {
23605 let i = block.selectors.length;
23606 while (i--) {
23607 const selector = block.selectors[i];
23608 if (selector.type === 'PseudoElementSelector' || selector.type === 'PseudoClassSelector') {
23609 if (selector.name !== 'root') {
23610 if (i === 0)
23611 code.prependRight(selector.start, attr);
23612 }
23613 continue;
23614 }
23615 if (selector.type === 'TypeSelector' && selector.name === '*') {
23616 code.overwrite(selector.start, selector.end, attr);
23617 }
23618 else {
23619 code.appendLeft(selector.end, attr);
23620 }
23621 break;
23622 }
23623 }
23624 this.blocks.forEach((block, index) => {
23625 if (block.global) {
23626 const selector = block.selectors[0];
23627 const first = selector.children[0];
23628 const last = selector.children[selector.children.length - 1];
23629 code.remove(selector.start, first.start).remove(last.end, selector.end);
23630 }
23631 if (block.should_encapsulate)
23632 encapsulate_block(block, index === this.blocks.length - 1 ? attr.repeat(amount_class_specificity_to_increase + 1) : attr);
23633 });
23634 }
23635 validate(component) {
23636 this.blocks.forEach((block) => {
23637 let i = block.selectors.length;
23638 while (i-- > 1) {
23639 const selector = block.selectors[i];
23640 if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
23641 component.error(selector, {
23642 code: 'css-invalid-global',
23643 message: ':global(...) must be the first element in a compound selector'
23644 });
23645 }
23646 }
23647 });
23648 let start = 0;
23649 let end = this.blocks.length;
23650 for (; start < end; start += 1) {
23651 if (!this.blocks[start].global)
23652 break;
23653 }
23654 for (; end > start; end -= 1) {
23655 if (!this.blocks[end - 1].global)
23656 break;
23657 }
23658 for (let i = start; i < end; i += 1) {
23659 if (this.blocks[i].global) {
23660 component.error(this.blocks[i].selectors[0], {
23661 code: 'css-invalid-global',
23662 message: ':global(...) can be at the start or end of a selector sequence, but not in the middle'
23663 });
23664 }
23665 }
23666 }
23667 get_amount_class_specificity_increased() {
23668 let count = 0;
23669 for (const block of this.blocks) {
23670 if (block.should_encapsulate) {
23671 count++;
23672 }
23673 }
23674 return count;
23675 }
23676}
23677function apply_selector(blocks, node, to_encapsulate) {
23678 const block = blocks.pop();
23679 if (!block)
23680 return false;
23681 if (!node) {
23682 return block.global && blocks.every(block => block.global);
23683 }
23684 switch (block_might_apply_to_node(block, node)) {
23685 case BlockAppliesToNode.NotPossible:
23686 return false;
23687 case BlockAppliesToNode.UnknownSelectorType:
23688 // bail. TODO figure out what these could be
23689 to_encapsulate.push({ node, block });
23690 return true;
23691 }
23692 if (block.combinator) {
23693 if (block.combinator.type === 'WhiteSpace') {
23694 for (const ancestor_block of blocks) {
23695 if (ancestor_block.global) {
23696 continue;
23697 }
23698 let parent = node;
23699 while (parent = get_element_parent(parent)) {
23700 if (block_might_apply_to_node(ancestor_block, parent) !== BlockAppliesToNode.NotPossible) {
23701 to_encapsulate.push({ node: parent, block: ancestor_block });
23702 }
23703 }
23704 if (to_encapsulate.length) {
23705 to_encapsulate.push({ node, block });
23706 return true;
23707 }
23708 }
23709 if (blocks.every(block => block.global)) {
23710 to_encapsulate.push({ node, block });
23711 return true;
23712 }
23713 return false;
23714 }
23715 else if (block.combinator.name === '>') {
23716 if (apply_selector(blocks, get_element_parent(node), to_encapsulate)) {
23717 to_encapsulate.push({ node, block });
23718 return true;
23719 }
23720 return false;
23721 }
23722 else if (block.combinator.name === '+' || block.combinator.name === '~') {
23723 const siblings = get_possible_element_siblings(node, block.combinator.name === '+');
23724 let has_match = false;
23725 for (const possible_sibling of siblings.keys()) {
23726 if (apply_selector(blocks.slice(), possible_sibling, to_encapsulate)) {
23727 to_encapsulate.push({ node, block });
23728 has_match = true;
23729 }
23730 }
23731 return has_match;
23732 }
23733 // TODO other combinators
23734 to_encapsulate.push({ node, block });
23735 return true;
23736 }
23737 to_encapsulate.push({ node, block });
23738 return true;
23739}
23740function block_might_apply_to_node(block, node) {
23741 let i = block.selectors.length;
23742 while (i--) {
23743 const selector = block.selectors[i];
23744 const name = typeof selector.name === 'string' && selector.name.replace(/\\(.)/g, '$1');
23745 if (selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector') {
23746 continue;
23747 }
23748 if (selector.type === 'PseudoClassSelector' && name === 'global') {
23749 // TODO shouldn't see this here... maybe we should enforce that :global(...)
23750 // cannot be sandwiched between non-global selectors?
23751 return BlockAppliesToNode.NotPossible;
23752 }
23753 if (selector.type === 'ClassSelector') {
23754 if (!attribute_matches(node, 'class', name, '~=', false) && !node.classes.some(c => c.name === name))
23755 return BlockAppliesToNode.NotPossible;
23756 }
23757 else if (selector.type === 'IdSelector') {
23758 if (!attribute_matches(node, 'id', name, '=', false))
23759 return BlockAppliesToNode.NotPossible;
23760 }
23761 else if (selector.type === 'AttributeSelector') {
23762 if (!(whitelist_attribute_selector.has(node.name.toLowerCase()) && whitelist_attribute_selector.get(node.name.toLowerCase()).has(selector.name.name.toLowerCase())) &&
23763 !attribute_matches(node, selector.name.name, selector.value && unquote(selector.value), selector.matcher, selector.flags)) {
23764 return BlockAppliesToNode.NotPossible;
23765 }
23766 }
23767 else if (selector.type === 'TypeSelector') {
23768 if (node.name.toLowerCase() !== name.toLowerCase() && name !== '*')
23769 return BlockAppliesToNode.NotPossible;
23770 }
23771 else {
23772 return BlockAppliesToNode.UnknownSelectorType;
23773 }
23774 }
23775 return BlockAppliesToNode.Possible;
23776}
23777function test_attribute(operator, expected_value, case_insensitive, value) {
23778 if (case_insensitive) {
23779 expected_value = expected_value.toLowerCase();
23780 value = value.toLowerCase();
23781 }
23782 switch (operator) {
23783 case '=': return value === expected_value;
23784 case '~=': return value.split(/\s/).includes(expected_value);
23785 case '|=': return `${value}-`.startsWith(`${expected_value}-`);
23786 case '^=': return value.startsWith(expected_value);
23787 case '$=': return value.endsWith(expected_value);
23788 case '*=': return value.includes(expected_value);
23789 default: throw new Error("this shouldn't happen");
23790 }
23791}
23792function attribute_matches(node, name, expected_value, operator, case_insensitive) {
23793 const spread = node.attributes.find(attr => attr.type === 'Spread');
23794 if (spread)
23795 return true;
23796 if (node.bindings.some((binding) => binding.name === name))
23797 return true;
23798 const attr = node.attributes.find((attr) => attr.name === name);
23799 if (!attr)
23800 return false;
23801 if (attr.is_true)
23802 return operator === null;
23803 if (!expected_value)
23804 return true;
23805 if (attr.chunks.length === 1) {
23806 const value = attr.chunks[0];
23807 if (!value)
23808 return false;
23809 if (value.type === 'Text')
23810 return test_attribute(operator, expected_value, case_insensitive, value.data);
23811 }
23812 const possible_values = new Set();
23813 let prev_values = [];
23814 for (const chunk of attr.chunks) {
23815 const current_possible_values = new Set();
23816 if (chunk.type === 'Text') {
23817 current_possible_values.add(chunk.data);
23818 }
23819 else {
23820 gather_possible_values(chunk.node, current_possible_values);
23821 }
23822 // impossible to find out all combinations
23823 if (current_possible_values.has(UNKNOWN))
23824 return true;
23825 if (prev_values.length > 0) {
23826 const start_with_space = [];
23827 const remaining = [];
23828 current_possible_values.forEach((current_possible_value) => {
23829 if (/^\s/.test(current_possible_value)) {
23830 start_with_space.push(current_possible_value);
23831 }
23832 else {
23833 remaining.push(current_possible_value);
23834 }
23835 });
23836 if (remaining.length > 0) {
23837 if (start_with_space.length > 0) {
23838 prev_values.forEach(prev_value => possible_values.add(prev_value));
23839 }
23840 const combined = [];
23841 prev_values.forEach((prev_value) => {
23842 remaining.forEach((value) => {
23843 combined.push(prev_value + value);
23844 });
23845 });
23846 prev_values = combined;
23847 start_with_space.forEach((value) => {
23848 if (/\s$/.test(value)) {
23849 possible_values.add(value);
23850 }
23851 else {
23852 prev_values.push(value);
23853 }
23854 });
23855 continue;
23856 }
23857 else {
23858 prev_values.forEach(prev_value => possible_values.add(prev_value));
23859 prev_values = [];
23860 }
23861 }
23862 current_possible_values.forEach((current_possible_value) => {
23863 if (/\s$/.test(current_possible_value)) {
23864 possible_values.add(current_possible_value);
23865 }
23866 else {
23867 prev_values.push(current_possible_value);
23868 }
23869 });
23870 if (prev_values.length < current_possible_values.size) {
23871 prev_values.push(' ');
23872 }
23873 if (prev_values.length > 20) {
23874 // might grow exponentially, bail out
23875 return true;
23876 }
23877 }
23878 prev_values.forEach(prev_value => possible_values.add(prev_value));
23879 if (possible_values.has(UNKNOWN))
23880 return true;
23881 for (const value of possible_values) {
23882 if (test_attribute(operator, expected_value, case_insensitive, value))
23883 return true;
23884 }
23885 return false;
23886}
23887function unquote(value) {
23888 if (value.type === 'Identifier')
23889 return value.name;
23890 const str = value.value;
23891 if (str[0] === str[str.length - 1] && str[0] === "'" || str[0] === '"') {
23892 return str.slice(1, str.length - 1);
23893 }
23894 return str;
23895}
23896function get_element_parent(node) {
23897 let parent = node;
23898 while ((parent = parent.parent) && parent.type !== 'Element')
23899 ;
23900 return parent;
23901}
23902function get_possible_element_siblings(node, adjacent_only) {
23903 const result = new Map();
23904 let prev = node;
23905 while (prev = prev.prev) {
23906 if (prev.type === 'Element') {
23907 if (!prev.attributes.find(attr => attr.type === 'Attribute' && attr.name.toLowerCase() === 'slot')) {
23908 result.set(prev, NodeExist.Definitely);
23909 }
23910 if (adjacent_only) {
23911 break;
23912 }
23913 }
23914 else if (prev.type === 'EachBlock' || prev.type === 'IfBlock' || prev.type === 'AwaitBlock') {
23915 const possible_last_child = get_possible_last_child(prev, adjacent_only);
23916 add_to_map(possible_last_child, result);
23917 if (adjacent_only && has_definite_elements(possible_last_child)) {
23918 return result;
23919 }
23920 }
23921 }
23922 if (!prev || !adjacent_only) {
23923 let parent = node;
23924 let skip_each_for_last_child = node.type === 'ElseBlock';
23925 while ((parent = parent.parent) && (parent.type === 'EachBlock' || parent.type === 'IfBlock' || parent.type === 'ElseBlock' || parent.type === 'AwaitBlock')) {
23926 const possible_siblings = get_possible_element_siblings(parent, adjacent_only);
23927 add_to_map(possible_siblings, result);
23928 if (parent.type === 'EachBlock') {
23929 // first child of each block can select the last child of each block as previous sibling
23930 if (skip_each_for_last_child) {
23931 skip_each_for_last_child = false;
23932 }
23933 else {
23934 add_to_map(get_possible_last_child(parent, adjacent_only), result);
23935 }
23936 }
23937 else if (parent.type === 'ElseBlock') {
23938 skip_each_for_last_child = true;
23939 parent = parent.parent;
23940 }
23941 if (adjacent_only && has_definite_elements(possible_siblings)) {
23942 break;
23943 }
23944 }
23945 }
23946 return result;
23947}
23948function get_possible_last_child(block, adjacent_only) {
23949 const result = new Map();
23950 if (block.type === 'EachBlock') {
23951 const each_result = loop_child(block.children, adjacent_only);
23952 const else_result = block.else ? loop_child(block.else.children, adjacent_only) : new Map();
23953 const not_exhaustive = !has_definite_elements(else_result);
23954 if (not_exhaustive) {
23955 mark_as_probably(each_result);
23956 mark_as_probably(else_result);
23957 }
23958 add_to_map(each_result, result);
23959 add_to_map(else_result, result);
23960 }
23961 else if (block.type === 'IfBlock') {
23962 const if_result = loop_child(block.children, adjacent_only);
23963 const else_result = block.else ? loop_child(block.else.children, adjacent_only) : new Map();
23964 const not_exhaustive = !has_definite_elements(if_result) || !has_definite_elements(else_result);
23965 if (not_exhaustive) {
23966 mark_as_probably(if_result);
23967 mark_as_probably(else_result);
23968 }
23969 add_to_map(if_result, result);
23970 add_to_map(else_result, result);
23971 }
23972 else if (block.type === 'AwaitBlock') {
23973 const pending_result = block.pending ? loop_child(block.pending.children, adjacent_only) : new Map();
23974 const then_result = block.then ? loop_child(block.then.children, adjacent_only) : new Map();
23975 const catch_result = block.catch ? loop_child(block.catch.children, adjacent_only) : new Map();
23976 const not_exhaustive = !has_definite_elements(pending_result) || !has_definite_elements(then_result) || !has_definite_elements(catch_result);
23977 if (not_exhaustive) {
23978 mark_as_probably(pending_result);
23979 mark_as_probably(then_result);
23980 mark_as_probably(catch_result);
23981 }
23982 add_to_map(pending_result, result);
23983 add_to_map(then_result, result);
23984 add_to_map(catch_result, result);
23985 }
23986 return result;
23987}
23988function has_definite_elements(result) {
23989 if (result.size === 0)
23990 return false;
23991 for (const exist of result.values()) {
23992 if (exist === NodeExist.Definitely) {
23993 return true;
23994 }
23995 }
23996 return false;
23997}
23998function add_to_map(from, to) {
23999 from.forEach((exist, element) => {
24000 to.set(element, higher_existance(exist, to.get(element)));
24001 });
24002}
24003function higher_existance(exist1, exist2) {
24004 if (exist1 === undefined || exist2 === undefined)
24005 return exist1 || exist2;
24006 return exist1 > exist2 ? exist1 : exist2;
24007}
24008function mark_as_probably(result) {
24009 for (const key of result.keys()) {
24010 result.set(key, NodeExist.Probably);
24011 }
24012}
24013function loop_child(children, adjacent_only) {
24014 const result = new Map();
24015 for (let i = children.length - 1; i >= 0; i--) {
24016 const child = children[i];
24017 if (child.type === 'Element') {
24018 result.set(child, NodeExist.Definitely);
24019 if (adjacent_only) {
24020 break;
24021 }
24022 }
24023 else if (child.type === 'EachBlock' || child.type === 'IfBlock' || child.type === 'AwaitBlock') {
24024 const child_result = get_possible_last_child(child, adjacent_only);
24025 add_to_map(child_result, result);
24026 if (adjacent_only && has_definite_elements(child_result)) {
24027 break;
24028 }
24029 }
24030 }
24031 return result;
24032}
24033class Block$2 {
24034 constructor(combinator) {
24035 this.combinator = combinator;
24036 this.global = false;
24037 this.selectors = [];
24038 this.start = null;
24039 this.end = null;
24040 this.should_encapsulate = false;
24041 }
24042 add(selector) {
24043 if (this.selectors.length === 0) {
24044 this.start = selector.start;
24045 this.global = selector.type === 'PseudoClassSelector' && selector.name === 'global';
24046 }
24047 this.selectors.push(selector);
24048 this.end = selector.end;
24049 }
24050}
24051function group_selectors(selector) {
24052 let block = new Block$2(null);
24053 const blocks = [block];
24054 selector.children.forEach((child) => {
24055 if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
24056 block = new Block$2(child);
24057 blocks.push(block);
24058 }
24059 else {
24060 block.add(child);
24061 }
24062 });
24063 return blocks;
24064}
24065
24066// https://github.com/darkskyapp/string-hash/blob/master/index.js
24067function hash(str) {
24068 str = str.replace(/\r/g, '');
24069 let hash = 5381;
24070 let i = str.length;
24071 while (i--)
24072 hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
24073 return (hash >>> 0).toString(36);
24074}
24075
24076function remove_css_prefix(name) {
24077 return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, '');
24078}
24079const is_keyframes_node = (node) => remove_css_prefix(node.name) === 'keyframes';
24080const at_rule_has_declaration = ({ block }) => block &&
24081 block.children &&
24082 block.children.find((node) => node.type === 'Declaration');
24083function minify_declarations(code, start, declarations) {
24084 let c = start;
24085 declarations.forEach((declaration, i) => {
24086 const separator = i > 0 ? ';' : '';
24087 if ((declaration.node.start - c) > separator.length) {
24088 code.overwrite(c, declaration.node.start, separator);
24089 }
24090 declaration.minify(code);
24091 c = declaration.node.end;
24092 });
24093 return c;
24094}
24095class Rule$1 {
24096 constructor(node, stylesheet, parent) {
24097 this.node = node;
24098 this.parent = parent;
24099 this.selectors = node.selector.children.map((node) => new Selector$1(node, stylesheet));
24100 this.declarations = node.block.children.map((node) => new Declaration$1(node));
24101 }
24102 apply(node) {
24103 this.selectors.forEach(selector => selector.apply(node)); // TODO move the logic in here?
24104 }
24105 is_used(dev) {
24106 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
24107 return true;
24108 if (this.declarations.length === 0)
24109 return dev;
24110 return this.selectors.some(s => s.used);
24111 }
24112 minify(code, _dev) {
24113 let c = this.node.start;
24114 let started = false;
24115 this.selectors.forEach((selector) => {
24116 if (selector.used) {
24117 const separator = started ? ',' : '';
24118 if ((selector.node.start - c) > separator.length) {
24119 code.overwrite(c, selector.node.start, separator);
24120 }
24121 selector.minify(code);
24122 c = selector.node.end;
24123 started = true;
24124 }
24125 });
24126 code.remove(c, this.node.block.start);
24127 c = this.node.block.start + 1;
24128 c = minify_declarations(code, c, this.declarations);
24129 code.remove(c, this.node.block.end - 1);
24130 }
24131 transform(code, id, keyframes, max_amount_class_specificity_increased) {
24132 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
24133 return true;
24134 const attr = `.${id}`;
24135 this.selectors.forEach(selector => selector.transform(code, attr, max_amount_class_specificity_increased));
24136 this.declarations.forEach(declaration => declaration.transform(code, keyframes));
24137 }
24138 validate(component) {
24139 this.selectors.forEach(selector => {
24140 selector.validate(component);
24141 });
24142 }
24143 warn_on_unused_selector(handler) {
24144 this.selectors.forEach(selector => {
24145 if (!selector.used)
24146 handler(selector);
24147 });
24148 }
24149 get_max_amount_class_specificity_increased() {
24150 return Math.max(...this.selectors.map(selector => selector.get_amount_class_specificity_increased()));
24151 }
24152}
24153class Declaration$1 {
24154 constructor(node) {
24155 this.node = node;
24156 }
24157 transform(code, keyframes) {
24158 const property = this.node.property && remove_css_prefix(this.node.property.toLowerCase());
24159 if (property === 'animation' || property === 'animation-name') {
24160 this.node.value.children.forEach((block) => {
24161 if (block.type === 'Identifier') {
24162 const name = block.name;
24163 if (keyframes.has(name)) {
24164 code.overwrite(block.start, block.end, keyframes.get(name));
24165 }
24166 }
24167 });
24168 }
24169 }
24170 minify(code) {
24171 if (!this.node.property)
24172 return; // @apply, and possibly other weird cases?
24173 const c = this.node.start + this.node.property.length;
24174 const first = this.node.value.children
24175 ? this.node.value.children[0]
24176 : this.node.value;
24177 let start = first.start;
24178 while (/\s/.test(code.original[start]))
24179 start += 1;
24180 if (start - c > 1) {
24181 code.overwrite(c, start, ':');
24182 }
24183 }
24184}
24185class Atrule$1 {
24186 constructor(node) {
24187 this.node = node;
24188 this.children = [];
24189 this.declarations = [];
24190 }
24191 apply(node) {
24192 if (this.node.name === 'media' || this.node.name === 'supports') {
24193 this.children.forEach(child => {
24194 child.apply(node);
24195 });
24196 }
24197 else if (is_keyframes_node(this.node)) {
24198 this.children.forEach((rule) => {
24199 rule.selectors.forEach(selector => {
24200 selector.used = true;
24201 });
24202 });
24203 }
24204 }
24205 is_used(_dev) {
24206 return true; // TODO
24207 }
24208 minify(code, dev) {
24209 if (this.node.name === 'media') {
24210 const expression_char = code.original[this.node.expression.start];
24211 let c = this.node.start + (expression_char === '(' ? 6 : 7);
24212 if (this.node.expression.start > c)
24213 code.remove(c, this.node.expression.start);
24214 this.node.expression.children.forEach((query) => {
24215 // TODO minify queries
24216 c = query.end;
24217 });
24218 code.remove(c, this.node.block.start);
24219 }
24220 else if (this.node.name === 'supports') {
24221 let c = this.node.start + 9;
24222 if (this.node.expression.start - c > 1)
24223 code.overwrite(c, this.node.expression.start, ' ');
24224 this.node.expression.children.forEach((query) => {
24225 // TODO minify queries
24226 c = query.end;
24227 });
24228 code.remove(c, this.node.block.start);
24229 }
24230 else {
24231 let c = this.node.start + this.node.name.length + 1;
24232 if (this.node.expression) {
24233 if (this.node.expression.start - c > 1)
24234 code.overwrite(c, this.node.expression.start, ' ');
24235 c = this.node.expression.end;
24236 }
24237 if (this.node.block && this.node.block.start - c > 0) {
24238 code.remove(c, this.node.block.start);
24239 }
24240 }
24241 // TODO other atrules
24242 if (this.node.block) {
24243 let c = this.node.block.start + 1;
24244 if (this.declarations.length) {
24245 c = minify_declarations(code, c, this.declarations);
24246 // if the atrule has children, leave the last declaration semicolon alone
24247 if (this.children.length)
24248 c++;
24249 }
24250 this.children.forEach(child => {
24251 if (child.is_used(dev)) {
24252 code.remove(c, child.node.start);
24253 child.minify(code, dev);
24254 c = child.node.end;
24255 }
24256 });
24257 code.remove(c, this.node.block.end - 1);
24258 }
24259 }
24260 transform(code, id, keyframes, max_amount_class_specificity_increased) {
24261 if (is_keyframes_node(this.node)) {
24262 this.node.expression.children.forEach(({ type, name, start, end }) => {
24263 if (type === 'Identifier') {
24264 if (name.startsWith('-global-')) {
24265 code.remove(start, start + 8);
24266 this.children.forEach((rule) => {
24267 rule.selectors.forEach(selector => {
24268 selector.used = true;
24269 });
24270 });
24271 }
24272 else {
24273 code.overwrite(start, end, keyframes.get(name));
24274 }
24275 }
24276 });
24277 }
24278 this.children.forEach(child => {
24279 child.transform(code, id, keyframes, max_amount_class_specificity_increased);
24280 });
24281 }
24282 validate(component) {
24283 this.children.forEach(child => {
24284 child.validate(component);
24285 });
24286 }
24287 warn_on_unused_selector(handler) {
24288 if (this.node.name !== 'media')
24289 return;
24290 this.children.forEach(child => {
24291 child.warn_on_unused_selector(handler);
24292 });
24293 }
24294 get_max_amount_class_specificity_increased() {
24295 return Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
24296 }
24297}
24298class Stylesheet {
24299 constructor(source, ast, filename, dev) {
24300 this.children = [];
24301 this.keyframes = new Map();
24302 this.nodes_with_css_class = new Set();
24303 this.source = source;
24304 this.ast = ast;
24305 this.filename = filename;
24306 this.dev = dev;
24307 if (ast.css && ast.css.children.length) {
24308 this.id = `svelte-${hash(ast.css.content.styles)}`;
24309 this.has_styles = true;
24310 const stack = [];
24311 let depth = 0;
24312 let current_atrule = null;
24313 walk(ast.css, {
24314 enter: (node) => {
24315 if (node.type === 'Atrule') {
24316 const atrule = new Atrule$1(node);
24317 stack.push(atrule);
24318 if (current_atrule) {
24319 current_atrule.children.push(atrule);
24320 }
24321 else if (depth <= 1) {
24322 this.children.push(atrule);
24323 }
24324 if (is_keyframes_node(node)) {
24325 node.expression.children.forEach((expression) => {
24326 if (expression.type === 'Identifier' && !expression.name.startsWith('-global-')) {
24327 this.keyframes.set(expression.name, `${this.id}-${expression.name}`);
24328 }
24329 });
24330 }
24331 else if (at_rule_has_declaration(node)) {
24332 const at_rule_declarations = node.block.children
24333 .filter(node => node.type === 'Declaration')
24334 .map(node => new Declaration$1(node));
24335 atrule.declarations.push(...at_rule_declarations);
24336 }
24337 current_atrule = atrule;
24338 }
24339 if (node.type === 'Rule') {
24340 const rule = new Rule$1(node, this, current_atrule);
24341 if (current_atrule) {
24342 current_atrule.children.push(rule);
24343 }
24344 else if (depth <= 1) {
24345 this.children.push(rule);
24346 }
24347 }
24348 depth += 1;
24349 },
24350 leave: (node) => {
24351 if (node.type === 'Atrule') {
24352 stack.pop();
24353 current_atrule = stack[stack.length - 1];
24354 }
24355 depth -= 1;
24356 }
24357 });
24358 }
24359 else {
24360 this.has_styles = false;
24361 }
24362 }
24363 apply(node) {
24364 if (!this.has_styles)
24365 return;
24366 for (let i = 0; i < this.children.length; i += 1) {
24367 const child = this.children[i];
24368 child.apply(node);
24369 }
24370 }
24371 reify() {
24372 this.nodes_with_css_class.forEach((node) => {
24373 node.add_css_class();
24374 });
24375 }
24376 render(file, should_transform_selectors) {
24377 if (!this.has_styles) {
24378 return { code: null, map: null };
24379 }
24380 const code = new MagicString(this.source);
24381 walk(this.ast.css, {
24382 enter: (node) => {
24383 code.addSourcemapLocation(node.start);
24384 code.addSourcemapLocation(node.end);
24385 }
24386 });
24387 if (should_transform_selectors) {
24388 const max = Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
24389 this.children.forEach((child) => {
24390 child.transform(code, this.id, this.keyframes, max);
24391 });
24392 }
24393 let c = 0;
24394 this.children.forEach(child => {
24395 if (child.is_used(this.dev)) {
24396 code.remove(c, child.node.start);
24397 child.minify(code, this.dev);
24398 c = child.node.end;
24399 }
24400 });
24401 code.remove(c, this.source.length);
24402 return {
24403 code: code.toString(),
24404 map: code.generateMap({
24405 includeContent: true,
24406 source: this.filename,
24407 file
24408 })
24409 };
24410 }
24411 validate(component) {
24412 this.children.forEach(child => {
24413 child.validate(component);
24414 });
24415 }
24416 warn_on_unused_selectors(component) {
24417 this.children.forEach(child => {
24418 child.warn_on_unused_selector((selector) => {
24419 component.warn(selector.node, {
24420 code: 'css-unused-selector',
24421 message: `Unused CSS selector "${this.source.slice(selector.node.start, selector.node.end)}"`
24422 });
24423 });
24424 });
24425 }
24426}
24427
24428const test = typeof process !== 'undefined' && process.env.TEST;
24429
24430class AbstractBlock extends Node$1 {
24431 constructor(component, parent, scope, info) {
24432 super(component, parent, scope, info);
24433 }
24434 warn_if_empty_block() {
24435 if (!this.children || this.children.length > 1)
24436 return;
24437 const child = this.children[0];
24438 if (!child || (child.type === 'Text' && !/[^ \r\n\f\v\t]/.test(child.data))) {
24439 this.component.warn(this, {
24440 code: 'empty-block',
24441 message: 'Empty block'
24442 });
24443 }
24444 }
24445}
24446
24447class PendingBlock extends AbstractBlock {
24448 constructor(component, parent, scope, info) {
24449 super(component, parent, scope, info);
24450 this.children = map_children(component, parent, scope, info.children);
24451 if (!info.skip) {
24452 this.warn_if_empty_block();
24453 }
24454 }
24455}
24456
24457class ThenBlock extends AbstractBlock {
24458 constructor(component, parent, scope, info) {
24459 super(component, parent, scope, info);
24460 this.scope = scope.child();
24461 if (parent.then_node) {
24462 parent.then_contexts.forEach(context => {
24463 this.scope.add(context.key.name, parent.expression.dependencies, this);
24464 });
24465 }
24466 this.children = map_children(component, parent, this.scope, info.children);
24467 if (!info.skip) {
24468 this.warn_if_empty_block();
24469 }
24470 }
24471}
24472
24473class CatchBlock extends AbstractBlock {
24474 constructor(component, parent, scope, info) {
24475 super(component, parent, scope, info);
24476 this.scope = scope.child();
24477 if (parent.catch_node) {
24478 parent.catch_contexts.forEach(context => {
24479 this.scope.add(context.key.name, parent.expression.dependencies, this);
24480 });
24481 }
24482 this.children = map_children(component, parent, this.scope, info.children);
24483 if (!info.skip) {
24484 this.warn_if_empty_block();
24485 }
24486 }
24487}
24488
24489function unpack_destructuring(contexts, node, modifier) {
24490 if (!node)
24491 return;
24492 if (node.type === 'Identifier') {
24493 contexts.push({
24494 key: node,
24495 modifier
24496 });
24497 }
24498 else if (node.type === 'RestElement') {
24499 contexts.push({
24500 key: node.argument,
24501 modifier
24502 });
24503 }
24504 else if (node.type === 'ArrayPattern') {
24505 node.elements.forEach((element, i) => {
24506 if (element && element.type === 'RestElement') {
24507 unpack_destructuring(contexts, element, node => x `${modifier(node)}.slice(${i})`);
24508 }
24509 else if (element && element.type === 'AssignmentPattern') {
24510 unpack_destructuring(contexts, element.left, node => x `${modifier(node)}[${i}] !== undefined ? ${modifier(node)}[${i}] : ${element.right}`);
24511 }
24512 else {
24513 unpack_destructuring(contexts, element, node => x `${modifier(node)}[${i}]`);
24514 }
24515 });
24516 }
24517 else if (node.type === 'ObjectPattern') {
24518 const used_properties = [];
24519 node.properties.forEach((property) => {
24520 if (property.type === 'RestElement') {
24521 unpack_destructuring(contexts, property.argument, node => x `@object_without_properties(${modifier(node)}, [${used_properties}])`);
24522 }
24523 else {
24524 const key = property.key;
24525 const value = property.value;
24526 used_properties.push(x `"${key.name}"`);
24527 if (value.type === 'AssignmentPattern') {
24528 unpack_destructuring(contexts, value.left, node => x `${modifier(node)}.${key.name} !== undefined ? ${modifier(node)}.${key.name} : ${value.right}`);
24529 }
24530 else {
24531 unpack_destructuring(contexts, value, node => x `${modifier(node)}.${key.name}`);
24532 }
24533 }
24534 });
24535 }
24536}
24537
24538class AwaitBlock$1 extends Node$1 {
24539 constructor(component, parent, scope, info) {
24540 super(component, parent, scope, info);
24541 this.expression = new Expression(component, this, scope, info.expression);
24542 this.then_node = info.value;
24543 this.catch_node = info.error;
24544 if (this.then_node) {
24545 this.then_contexts = [];
24546 unpack_destructuring(this.then_contexts, info.value, node => node);
24547 }
24548 if (this.catch_node) {
24549 this.catch_contexts = [];
24550 unpack_destructuring(this.catch_contexts, info.error, node => node);
24551 }
24552 this.pending = new PendingBlock(component, this, scope, info.pending);
24553 this.then = new ThenBlock(component, this, scope, info.then);
24554 this.catch = new CatchBlock(component, this, scope, info.catch);
24555 }
24556}
24557
24558class EventHandler extends Node$1 {
24559 constructor(component, parent, template_scope, info) {
24560 super(component, parent, template_scope, info);
24561 this.uses_context = false;
24562 this.can_make_passive = false;
24563 this.name = info.name;
24564 this.modifiers = new Set(info.modifiers);
24565 if (info.expression) {
24566 this.expression = new Expression(component, this, template_scope, info.expression);
24567 this.uses_context = this.expression.uses_context;
24568 if (/FunctionExpression/.test(info.expression.type) && info.expression.params.length === 0) {
24569 // TODO make this detection more accurate — if `event.preventDefault` isn't called, and
24570 // `event` is passed to another function, we can make it passive
24571 this.can_make_passive = true;
24572 }
24573 else if (info.expression.type === 'Identifier') {
24574 let node = component.node_for_declaration.get(info.expression.name);
24575 if (node) {
24576 if (node.type === 'VariableDeclaration') {
24577 // for `const handleClick = () => {...}`, we want the [arrow] function expression node
24578 const declarator = node.declarations.find(d => d.id.name === info.expression.name);
24579 node = declarator && declarator.init;
24580 }
24581 if (node && (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') && node.params.length === 0) {
24582 this.can_make_passive = true;
24583 }
24584 }
24585 }
24586 }
24587 else {
24588 this.handler_name = component.get_unique_name(`${sanitize(this.name)}_handler`);
24589 }
24590 }
24591 get reassigned() {
24592 if (!this.expression) {
24593 return false;
24594 }
24595 const node = this.expression.node;
24596 if (/FunctionExpression/.test(node.type)) {
24597 return false;
24598 }
24599 return this.expression.dynamic_dependencies().length > 0;
24600 }
24601}
24602
24603class Body extends Node$1 {
24604 constructor(component, parent, scope, info) {
24605 super(component, parent, scope, info);
24606 this.handlers = [];
24607 info.attributes.forEach(node => {
24608 if (node.type === 'EventHandler') {
24609 this.handlers.push(new EventHandler(component, this, scope, node));
24610 }
24611 });
24612 }
24613}
24614
24615const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m;
24616class Comment$2 extends Node$1 {
24617 constructor(component, parent, scope, info) {
24618 super(component, parent, scope, info);
24619 this.data = info.data;
24620 const match = pattern.exec(this.data);
24621 this.ignores = match ? match[1].split(/[^\S]/).map(x => x.trim()).filter(Boolean) : [];
24622 }
24623}
24624
24625class ElseBlock extends AbstractBlock {
24626 constructor(component, parent, scope, info) {
24627 super(component, parent, scope, info);
24628 this.children = map_children(component, this, scope, info.children);
24629 this.warn_if_empty_block();
24630 }
24631}
24632
24633class EachBlock$1 extends AbstractBlock {
24634 constructor(component, parent, scope, info) {
24635 super(component, parent, scope, info);
24636 this.has_binding = false;
24637 this.has_index_binding = false;
24638 this.expression = new Expression(component, this, scope, info.expression);
24639 this.context = info.context.name || 'each'; // TODO this is used to facilitate binding; currently fails with destructuring
24640 this.context_node = info.context;
24641 this.index = info.index;
24642 this.scope = scope.child();
24643 this.contexts = [];
24644 unpack_destructuring(this.contexts, info.context, node => node);
24645 this.contexts.forEach(context => {
24646 this.scope.add(context.key.name, this.expression.dependencies, this);
24647 });
24648 if (this.index) {
24649 // index can only change if this is a keyed each block
24650 const dependencies = info.key ? this.expression.dependencies : new Set([]);
24651 this.scope.add(this.index, dependencies, this);
24652 }
24653 this.key = info.key
24654 ? new Expression(component, this, this.scope, info.key)
24655 : null;
24656 this.has_animation = false;
24657 this.children = map_children(component, this, this.scope, info.children);
24658 if (this.has_animation) {
24659 if (this.children.length !== 1) {
24660 const child = this.children.find(child => !!child.animation);
24661 component.error(child.animation, {
24662 code: 'invalid-animation',
24663 message: 'An element that uses the animate directive must be the sole child of a keyed each block'
24664 });
24665 }
24666 }
24667 this.warn_if_empty_block();
24668 this.else = info.else
24669 ? new ElseBlock(component, this, this.scope, info.else)
24670 : null;
24671 }
24672}
24673
24674class Attribute extends Node$1 {
24675 constructor(component, parent, scope, info) {
24676 super(component, parent, scope, info);
24677 this.scope = scope;
24678 if (info.type === 'Spread') {
24679 this.name = null;
24680 this.is_spread = true;
24681 this.is_true = false;
24682 this.expression = new Expression(component, this, scope, info.expression);
24683 this.dependencies = this.expression.dependencies;
24684 this.chunks = null;
24685 this.is_static = false;
24686 }
24687 else {
24688 this.name = info.name;
24689 this.is_true = info.value === true;
24690 this.is_static = true;
24691 this.dependencies = new Set();
24692 this.chunks = this.is_true
24693 ? []
24694 : info.value.map(node => {
24695 if (node.type === 'Text')
24696 return node;
24697 this.is_static = false;
24698 const expression = new Expression(component, this, scope, node.expression);
24699 add_to_set(this.dependencies, expression.dependencies);
24700 return expression;
24701 });
24702 }
24703 }
24704 get_dependencies() {
24705 if (this.is_spread)
24706 return this.expression.dynamic_dependencies();
24707 const dependencies = new Set();
24708 this.chunks.forEach(chunk => {
24709 if (chunk.type === 'Expression') {
24710 add_to_set(dependencies, chunk.dynamic_dependencies());
24711 }
24712 });
24713 return Array.from(dependencies);
24714 }
24715 get_value(block) {
24716 if (this.is_true)
24717 return x `true`;
24718 if (this.chunks.length === 0)
24719 return x `""`;
24720 if (this.chunks.length === 1) {
24721 return this.chunks[0].type === 'Text'
24722 ? string_literal(this.chunks[0].data)
24723 : this.chunks[0].manipulate(block);
24724 }
24725 let expression = this.chunks
24726 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : chunk.manipulate(block))
24727 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
24728 if (this.chunks[0].type !== 'Text') {
24729 expression = x `"" + ${expression}`;
24730 }
24731 return expression;
24732 }
24733 get_static_value() {
24734 if (this.is_spread || this.dependencies.size > 0)
24735 return null;
24736 return this.is_true
24737 ? true
24738 : this.chunks[0]
24739 // method should be called only when `is_static = true`
24740 ? this.chunks[0].data
24741 : '';
24742 }
24743 should_cache() {
24744 return this.is_static
24745 ? false
24746 : this.chunks.length === 1
24747 // @ts-ignore todo: probably error
24748 ? this.chunks[0].node.type !== 'Identifier' || this.scope.names.has(this.chunks[0].node.name)
24749 : true;
24750 }
24751}
24752
24753// TODO this should live in a specific binding
24754const read_only_media_attributes = new Set([
24755 'duration',
24756 'buffered',
24757 'seekable',
24758 'played',
24759 'seeking',
24760 'ended',
24761 'videoHeight',
24762 'videoWidth'
24763]);
24764class Binding extends Node$1 {
24765 constructor(component, parent, scope, info) {
24766 super(component, parent, scope, info);
24767 if (info.expression.type !== 'Identifier' && info.expression.type !== 'MemberExpression') {
24768 component.error(info, {
24769 code: 'invalid-directive-value',
24770 message: 'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
24771 });
24772 }
24773 this.name = info.name;
24774 this.expression = new Expression(component, this, scope, info.expression);
24775 this.raw_expression = JSON.parse(JSON.stringify(info.expression));
24776 const { name } = get_object(this.expression.node);
24777 this.is_contextual = Array.from(this.expression.references).some(name => scope.names.has(name));
24778 // make sure we track this as a mutable ref
24779 if (scope.is_let(name)) {
24780 component.error(this, {
24781 code: 'invalid-binding',
24782 message: 'Cannot bind to a variable declared with the let: directive'
24783 });
24784 }
24785 else if (scope.names.has(name)) {
24786 if (scope.is_await(name)) {
24787 component.error(this, {
24788 code: 'invalid-binding',
24789 message: 'Cannot bind to a variable declared with {#await ... then} or {:catch} blocks'
24790 });
24791 }
24792 scope.dependencies_for_name.get(name).forEach(name => {
24793 const variable = component.var_lookup.get(name);
24794 if (variable) {
24795 variable.mutated = true;
24796 }
24797 });
24798 }
24799 else {
24800 const variable = component.var_lookup.get(name);
24801 if (!variable || variable.global) {
24802 component.error(this.expression.node, {
24803 code: 'binding-undeclared',
24804 message: `${name} is not declared`
24805 });
24806 }
24807 variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
24808 if (info.expression.type === 'Identifier' && !variable.writable) {
24809 component.error(this.expression.node, {
24810 code: 'invalid-binding',
24811 message: 'Cannot bind to a variable which is not writable'
24812 });
24813 }
24814 }
24815 const type = parent.get_static_attribute_value('type');
24816 this.is_readonly = (dimensions.test(this.name) ||
24817 (parent.is_media_node && parent.is_media_node() && read_only_media_attributes.has(this.name)) ||
24818 (parent.name === 'input' && type === 'file') // TODO others?
24819 );
24820 }
24821 is_readonly_media_attribute() {
24822 return read_only_media_attributes.has(this.name);
24823 }
24824}
24825
24826class Transition extends Node$1 {
24827 constructor(component, parent, scope, info) {
24828 super(component, parent, scope, info);
24829 component.warn_if_undefined(info.name, info, scope);
24830 this.name = info.name;
24831 component.add_reference(info.name.split('.')[0]);
24832 this.directive = info.intro && info.outro ? 'transition' : info.intro ? 'in' : 'out';
24833 this.is_local = info.modifiers.includes('local');
24834 if ((info.intro && parent.intro) || (info.outro && parent.outro)) {
24835 const parent_transition = (parent.intro || parent.outro);
24836 const message = this.directive === parent_transition.directive
24837 ? `An element can only have one '${this.directive}' directive`
24838 : `An element cannot have both ${describe(parent_transition)} directive and ${describe(this)} directive`;
24839 component.error(info, {
24840 code: 'duplicate-transition',
24841 message
24842 });
24843 }
24844 this.expression = info.expression
24845 ? new Expression(component, this, scope, info.expression)
24846 : null;
24847 }
24848}
24849function describe(transition) {
24850 return transition.directive === 'transition'
24851 ? "a 'transition'"
24852 : `an '${transition.directive}'`;
24853}
24854
24855class Animation extends Node$1 {
24856 constructor(component, parent, scope, info) {
24857 super(component, parent, scope, info);
24858 component.warn_if_undefined(info.name, info, scope);
24859 this.name = info.name;
24860 component.add_reference(info.name.split('.')[0]);
24861 if (parent.animation) {
24862 component.error(this, {
24863 code: 'duplicate-animation',
24864 message: "An element can only have one 'animate' directive"
24865 });
24866 }
24867 const block = parent.parent;
24868 if (!block || block.type !== 'EachBlock' || !block.key) {
24869 // TODO can we relax the 'immediate child' rule?
24870 component.error(this, {
24871 code: 'invalid-animation',
24872 message: 'An element that uses the animate directive must be the immediate child of a keyed each block'
24873 });
24874 }
24875 block.has_animation = true;
24876 this.expression = info.expression
24877 ? new Expression(component, this, scope, info.expression, true)
24878 : null;
24879 }
24880}
24881
24882class Class extends Node$1 {
24883 constructor(component, parent, scope, info) {
24884 super(component, parent, scope, info);
24885 this.name = info.name;
24886 this.expression = info.expression
24887 ? new Expression(component, this, scope, info.expression)
24888 : null;
24889 }
24890}
24891
24892// Whitespace inside one of these elements will not result in
24893// a whitespace node being created in any circumstances. (This
24894// list is almost certainly very incomplete)
24895const elements_without_text = new Set([
24896 'audio',
24897 'datalist',
24898 'dl',
24899 'optgroup',
24900 'select',
24901 'video'
24902]);
24903class Text$1 extends Node$1 {
24904 constructor(component, parent, scope, info) {
24905 super(component, parent, scope, info);
24906 this.data = info.data;
24907 this.synthetic = info.synthetic || false;
24908 }
24909 should_skip() {
24910 if (/\S/.test(this.data))
24911 return false;
24912 const parent_element = this.find_nearest(/(?:Element|InlineComponent|Head)/);
24913 if (!parent_element)
24914 return false;
24915 if (parent_element.type === 'Head')
24916 return true;
24917 if (parent_element.type === 'InlineComponent')
24918 return parent_element.children.length === 1 && this === parent_element.children[0];
24919 // svg namespace exclusions
24920 if (/svg$/.test(parent_element.namespace)) {
24921 if (this.prev && this.prev.type === 'Element' && this.prev.name === 'tspan')
24922 return false;
24923 }
24924 return parent_element.namespace || elements_without_text.has(parent_element.name);
24925 }
24926}
24927
24928const applicable = new Set(['Identifier', 'ObjectExpression', 'ArrayExpression', 'Property']);
24929class Let extends Node$1 {
24930 constructor(component, parent, scope, info) {
24931 super(component, parent, scope, info);
24932 this.names = [];
24933 this.name = { type: 'Identifier', name: info.name };
24934 const { names } = this;
24935 if (info.expression) {
24936 this.value = info.expression;
24937 walk(info.expression, {
24938 enter(node) {
24939 if (!applicable.has(node.type)) {
24940 component.error(node, {
24941 code: 'invalid-let',
24942 message: 'let directive value must be an identifier or an object/array pattern'
24943 });
24944 }
24945 if (node.type === 'Identifier') {
24946 names.push(node.name);
24947 }
24948 // slightly unfortunate hack
24949 if (node.type === 'ArrayExpression') {
24950 node.type = 'ArrayPattern';
24951 }
24952 if (node.type === 'ObjectExpression') {
24953 node.type = 'ObjectPattern';
24954 }
24955 }
24956 });
24957 }
24958 else {
24959 names.push(this.name.name);
24960 }
24961 }
24962}
24963
24964const svg$1 = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/;
24965const aria_attributes = 'activedescendant atomic autocomplete busy checked colcount colindex colspan controls current describedby details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowcount rowindex rowspan selected setsize sort valuemax valuemin valuenow valuetext'.split(' ');
24966const aria_attribute_set = new Set(aria_attributes);
24967const aria_roles = 'alert alertdialog application article banner blockquote button caption cell checkbox code columnheader combobox complementary contentinfo definition deletion dialog directory document emphasis feed figure form generic grid gridcell group heading img link list listbox listitem log main marquee math meter menu menubar menuitem menuitemcheckbox menuitemradio navigation none note option paragraph presentation progressbar radio radiogroup region row rowgroup rowheader scrollbar search searchbox separator slider spinbutton status strong subscript superscript switch tab table tablist tabpanel term textbox time timer toolbar tooltip tree treegrid treeitem'.split(' ');
24968const aria_role_set = new Set(aria_roles);
24969const a11y_required_attributes = {
24970 a: ['href'],
24971 area: ['alt', 'aria-label', 'aria-labelledby'],
24972 // html-has-lang
24973 html: ['lang'],
24974 // iframe-has-title
24975 iframe: ['title'],
24976 img: ['alt'],
24977 object: ['title', 'aria-label', 'aria-labelledby']
24978};
24979const a11y_distracting_elements = new Set([
24980 'blink',
24981 'marquee'
24982]);
24983const a11y_required_content = new Set([
24984 // anchor-has-content
24985 'a',
24986 // heading-has-content
24987 'h1',
24988 'h2',
24989 'h3',
24990 'h4',
24991 'h5',
24992 'h6'
24993]);
24994const a11y_no_onchange = new Set([
24995 'select',
24996 'option'
24997]);
24998const a11y_labelable = new Set([
24999 'button',
25000 'input',
25001 'keygen',
25002 'meter',
25003 'output',
25004 'progress',
25005 'select',
25006 'textarea'
25007]);
25008const invisible_elements = new Set(['meta', 'html', 'script', 'style']);
25009const valid_modifiers = new Set([
25010 'preventDefault',
25011 'stopPropagation',
25012 'capture',
25013 'once',
25014 'passive',
25015 'nonpassive',
25016 'self'
25017]);
25018const passive_events = new Set([
25019 'wheel',
25020 'touchstart',
25021 'touchmove',
25022 'touchend',
25023 'touchcancel'
25024]);
25025function get_namespace(parent, element, explicit_namespace) {
25026 const parent_element = parent.find_nearest(/^Element/);
25027 if (!parent_element) {
25028 return explicit_namespace || (svg$1.test(element.name)
25029 ? namespaces.svg
25030 : null);
25031 }
25032 if (svg$1.test(element.name.toLowerCase()))
25033 return namespaces.svg;
25034 if (parent_element.name.toLowerCase() === 'foreignobject')
25035 return null;
25036 return parent_element.namespace;
25037}
25038class Element$1 extends Node$1 {
25039 constructor(component, parent, scope, info) {
25040 super(component, parent, scope, info);
25041 this.attributes = [];
25042 this.actions = [];
25043 this.bindings = [];
25044 this.classes = [];
25045 this.handlers = [];
25046 this.lets = [];
25047 this.intro = null;
25048 this.outro = null;
25049 this.animation = null;
25050 this.name = info.name;
25051 this.namespace = get_namespace(parent, this, component.namespace);
25052 if (this.name === 'textarea') {
25053 if (info.children.length > 0) {
25054 const value_attribute = info.attributes.find(node => node.name === 'value');
25055 if (value_attribute) {
25056 component.error(value_attribute, {
25057 code: 'textarea-duplicate-value',
25058 message: 'A <textarea> can have either a value attribute or (equivalently) child content, but not both'
25059 });
25060 }
25061 // this is an egregious hack, but it's the easiest way to get <textarea>
25062 // children treated the same way as a value attribute
25063 info.attributes.push({
25064 type: 'Attribute',
25065 name: 'value',
25066 value: info.children
25067 });
25068 info.children = [];
25069 }
25070 }
25071 if (this.name === 'option') {
25072 // Special case — treat these the same way:
25073 // <option>{foo}</option>
25074 // <option value={foo}>{foo}</option>
25075 const value_attribute = info.attributes.find(attribute => attribute.name === 'value');
25076 if (!value_attribute) {
25077 info.attributes.push({
25078 type: 'Attribute',
25079 name: 'value',
25080 value: info.children,
25081 synthetic: true
25082 });
25083 }
25084 }
25085 const has_let = info.attributes.some(node => node.type === 'Let');
25086 if (has_let) {
25087 scope = scope.child();
25088 }
25089 // Binding relies on Attribute, defer its evaluation
25090 const order = ['Binding']; // everything else is -1
25091 info.attributes.sort((a, b) => order.indexOf(a.type) - order.indexOf(b.type));
25092 info.attributes.forEach(node => {
25093 switch (node.type) {
25094 case 'Action':
25095 this.actions.push(new Action(component, this, scope, node));
25096 break;
25097 case 'Attribute':
25098 case 'Spread':
25099 // special case
25100 if (node.name === 'xmlns')
25101 this.namespace = node.value[0].data;
25102 this.attributes.push(new Attribute(component, this, scope, node));
25103 break;
25104 case 'Binding':
25105 this.bindings.push(new Binding(component, this, scope, node));
25106 break;
25107 case 'Class':
25108 this.classes.push(new Class(component, this, scope, node));
25109 break;
25110 case 'EventHandler':
25111 this.handlers.push(new EventHandler(component, this, scope, node));
25112 break;
25113 case 'Let': {
25114 const l = new Let(component, this, scope, node);
25115 this.lets.push(l);
25116 const dependencies = new Set([l.name.name]);
25117 l.names.forEach(name => {
25118 scope.add(name, dependencies, this);
25119 });
25120 break;
25121 }
25122 case 'Transition':
25123 {
25124 const transition = new Transition(component, this, scope, node);
25125 if (node.intro)
25126 this.intro = transition;
25127 if (node.outro)
25128 this.outro = transition;
25129 break;
25130 }
25131 case 'Animation':
25132 this.animation = new Animation(component, this, scope, node);
25133 break;
25134 default:
25135 throw new Error(`Not implemented: ${node.type}`);
25136 }
25137 });
25138 this.scope = scope;
25139 this.children = map_children(component, this, this.scope, info.children);
25140 this.validate();
25141 component.apply_stylesheet(this);
25142 }
25143 validate() {
25144 if (this.component.var_lookup.has(this.name) && this.component.var_lookup.get(this.name).imported) {
25145 this.component.warn(this, {
25146 code: 'component-name-lowercase',
25147 message: `<${this.name}> will be treated as an HTML element unless it begins with a capital letter`
25148 });
25149 }
25150 if (a11y_distracting_elements.has(this.name)) {
25151 // no-distracting-elements
25152 this.component.warn(this, {
25153 code: 'a11y-distracting-elements',
25154 message: `A11y: Avoid <${this.name}> elements`
25155 });
25156 }
25157 if (this.name === 'figcaption') {
25158 let { parent } = this;
25159 let is_figure_parent = false;
25160 while (parent) {
25161 if (parent.name === 'figure') {
25162 is_figure_parent = true;
25163 break;
25164 }
25165 if (parent.type === 'Element') {
25166 break;
25167 }
25168 parent = parent.parent;
25169 }
25170 if (!is_figure_parent) {
25171 this.component.warn(this, {
25172 code: 'a11y-structure',
25173 message: 'A11y: <figcaption> must be an immediate child of <figure>'
25174 });
25175 }
25176 }
25177 if (this.name === 'figure') {
25178 const children = this.children.filter(node => {
25179 if (node.type === 'Comment')
25180 return false;
25181 if (node.type === 'Text')
25182 return /\S/.test(node.data);
25183 return true;
25184 });
25185 const index = children.findIndex(child => child.name === 'figcaption');
25186 if (index !== -1 && (index !== 0 && index !== children.length - 1)) {
25187 this.component.warn(children[index], {
25188 code: 'a11y-structure',
25189 message: 'A11y: <figcaption> must be first or last child of <figure>'
25190 });
25191 }
25192 }
25193 this.validate_attributes();
25194 this.validate_special_cases();
25195 this.validate_bindings();
25196 this.validate_content();
25197 this.validate_event_handlers();
25198 }
25199 validate_attributes() {
25200 const { component, parent } = this;
25201 const attribute_map = new Map();
25202 this.attributes.forEach(attribute => {
25203 if (attribute.is_spread)
25204 return;
25205 const name = attribute.name.toLowerCase();
25206 // aria-props
25207 if (name.startsWith('aria-')) {
25208 if (invisible_elements.has(this.name)) {
25209 // aria-unsupported-elements
25210 component.warn(attribute, {
25211 code: 'a11y-aria-attributes',
25212 message: `A11y: <${this.name}> should not have aria-* attributes`
25213 });
25214 }
25215 const type = name.slice(5);
25216 if (!aria_attribute_set.has(type)) {
25217 const match = fuzzymatch(type, aria_attributes);
25218 let message = `A11y: Unknown aria attribute 'aria-${type}'`;
25219 if (match)
25220 message += ` (did you mean '${match}'?)`;
25221 component.warn(attribute, {
25222 code: 'a11y-unknown-aria-attribute',
25223 message
25224 });
25225 }
25226 if (name === 'aria-hidden' && /^h[1-6]$/.test(this.name)) {
25227 component.warn(attribute, {
25228 code: 'a11y-hidden',
25229 message: `A11y: <${this.name}> element should not be hidden`
25230 });
25231 }
25232 }
25233 // aria-role
25234 if (name === 'role') {
25235 if (invisible_elements.has(this.name)) {
25236 // aria-unsupported-elements
25237 component.warn(attribute, {
25238 code: 'a11y-misplaced-role',
25239 message: `A11y: <${this.name}> should not have role attribute`
25240 });
25241 }
25242 const value = attribute.get_static_value();
25243 // @ts-ignore
25244 if (value && !aria_role_set.has(value)) {
25245 // @ts-ignore
25246 const match = fuzzymatch(value, aria_roles);
25247 let message = `A11y: Unknown role '${value}'`;
25248 if (match)
25249 message += ` (did you mean '${match}'?)`;
25250 component.warn(attribute, {
25251 code: 'a11y-unknown-role',
25252 message
25253 });
25254 }
25255 }
25256 // no-access-key
25257 if (name === 'accesskey') {
25258 component.warn(attribute, {
25259 code: 'a11y-accesskey',
25260 message: 'A11y: Avoid using accesskey'
25261 });
25262 }
25263 // no-autofocus
25264 if (name === 'autofocus') {
25265 component.warn(attribute, {
25266 code: 'a11y-autofocus',
25267 message: 'A11y: Avoid using autofocus'
25268 });
25269 }
25270 // scope
25271 if (name === 'scope' && this.name !== 'th') {
25272 component.warn(attribute, {
25273 code: 'a11y-misplaced-scope',
25274 message: 'A11y: The scope attribute should only be used with <th> elements'
25275 });
25276 }
25277 // tabindex-no-positive
25278 if (name === 'tabindex') {
25279 const value = attribute.get_static_value();
25280 // @ts-ignore todo is tabindex=true correct case?
25281 if (!isNaN(value) && +value > 0) {
25282 component.warn(attribute, {
25283 code: 'a11y-positive-tabindex',
25284 message: 'A11y: avoid tabindex values above zero'
25285 });
25286 }
25287 }
25288 if (/(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/.test(name)) {
25289 component.error(attribute, {
25290 code: 'illegal-attribute',
25291 message: `'${name}' is not a valid attribute name`
25292 });
25293 }
25294 if (name === 'slot') {
25295 if (!attribute.is_static) {
25296 component.error(attribute, {
25297 code: 'invalid-slot-attribute',
25298 message: 'slot attribute cannot have a dynamic value'
25299 });
25300 }
25301 if (component.slot_outlets.has(name)) {
25302 component.error(attribute, {
25303 code: 'duplicate-slot-attribute',
25304 message: `Duplicate '${name}' slot`
25305 });
25306 component.slot_outlets.add(name);
25307 }
25308 if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
25309 component.error(attribute, {
25310 code: 'invalid-slotted-content',
25311 message: 'Element with a slot=\'...\' attribute must be a child of a component or a descendant of a custom element'
25312 });
25313 }
25314 }
25315 if (name === 'is') {
25316 component.warn(attribute, {
25317 code: 'avoid-is',
25318 message: 'The \'is\' attribute is not supported cross-browser and should be avoided'
25319 });
25320 }
25321 attribute_map.set(attribute.name, attribute);
25322 });
25323 }
25324 validate_special_cases() {
25325 const { component, attributes, handlers } = this;
25326 const attribute_map = new Map();
25327 const handlers_map = new Map();
25328 attributes.forEach(attribute => (attribute_map.set(attribute.name, attribute)));
25329 handlers.forEach(handler => (handlers_map.set(handler.name, handler)));
25330 if (this.name === 'a') {
25331 const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
25332 const id_attribute = attribute_map.get('id');
25333 const name_attribute = attribute_map.get('name');
25334 if (href_attribute) {
25335 const href_value = href_attribute.get_static_value();
25336 if (href_value === '' || href_value === '#' || /^\W*javascript:/i.test(href_value)) {
25337 component.warn(href_attribute, {
25338 code: 'a11y-invalid-attribute',
25339 message: `A11y: '${href_value}' is not a valid ${href_attribute.name} attribute`
25340 });
25341 }
25342 }
25343 else {
25344 const id_attribute_valid = id_attribute && id_attribute.get_static_value() !== '';
25345 const name_attribute_valid = name_attribute && name_attribute.get_static_value() !== '';
25346 if (!id_attribute_valid && !name_attribute_valid) {
25347 component.warn(this, {
25348 code: 'a11y-missing-attribute',
25349 message: 'A11y: <a> element should have an href attribute'
25350 });
25351 }
25352 }
25353 }
25354 else {
25355 const required_attributes = a11y_required_attributes[this.name];
25356 if (required_attributes) {
25357 const has_attribute = required_attributes.some(name => attribute_map.has(name));
25358 if (!has_attribute) {
25359 should_have_attribute(this, required_attributes);
25360 }
25361 }
25362 }
25363 if (this.name === 'input') {
25364 const type = attribute_map.get('type');
25365 if (type && type.get_static_value() === 'image') {
25366 const required_attributes = ['alt', 'aria-label', 'aria-labelledby'];
25367 const has_attribute = required_attributes.some(name => attribute_map.has(name));
25368 if (!has_attribute) {
25369 should_have_attribute(this, required_attributes, 'input type="image"');
25370 }
25371 }
25372 }
25373 if (this.name === 'img') {
25374 const alt_attribute = attribute_map.get('alt');
25375 const aria_hidden_attribute = attribute_map.get('aria-hidden');
25376 const aria_hidden_exist = aria_hidden_attribute && aria_hidden_attribute.get_static_value();
25377 if (alt_attribute && !aria_hidden_exist) {
25378 const alt_value = alt_attribute.get_static_value();
25379 if (/\b(image|picture|photo)\b/i.test(alt_value)) {
25380 component.warn(this, {
25381 code: 'a11y-img-redundant-alt',
25382 message: 'A11y: Screenreaders already announce <img> elements as an image.'
25383 });
25384 }
25385 }
25386 }
25387 if (this.name === 'label') {
25388 const has_input_child = this.children.some(i => (i instanceof Element$1 && a11y_labelable.has(i.name)));
25389 if (!attribute_map.has('for') && !has_input_child) {
25390 component.warn(this, {
25391 code: 'a11y-label-has-associated-control',
25392 message: 'A11y: A form label must be associated with a control.'
25393 });
25394 }
25395 }
25396 if (this.is_media_node()) {
25397 if (attribute_map.has('muted')) {
25398 return;
25399 }
25400 let has_caption;
25401 const track = this.children.find((i) => i.name === 'track');
25402 if (track) {
25403 has_caption = track.attributes.find(a => a.name === 'kind' && a.get_static_value() === 'captions');
25404 }
25405 if (!has_caption) {
25406 component.warn(this, {
25407 code: 'a11y-media-has-caption',
25408 message: 'A11y: Media elements must have a <track kind="captions">'
25409 });
25410 }
25411 }
25412 if (a11y_no_onchange.has(this.name)) {
25413 if (handlers_map.has('change') && !handlers_map.has('blur')) {
25414 component.warn(this, {
25415 code: 'a11y-no-onchange',
25416 message: 'A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.'
25417 });
25418 }
25419 }
25420 }
25421 validate_bindings() {
25422 const { component } = this;
25423 const check_type_attribute = () => {
25424 const attribute = this.attributes.find((attribute) => attribute.name === 'type');
25425 if (!attribute)
25426 return null;
25427 if (!attribute.is_static) {
25428 component.error(attribute, {
25429 code: 'invalid-type',
25430 message: '\'type\' attribute cannot be dynamic if input uses two-way binding'
25431 });
25432 }
25433 const value = attribute.get_static_value();
25434 if (value === true) {
25435 component.error(attribute, {
25436 code: 'missing-type',
25437 message: '\'type\' attribute must be specified'
25438 });
25439 }
25440 return value;
25441 };
25442 this.bindings.forEach(binding => {
25443 const { name } = binding;
25444 if (name === 'value') {
25445 if (this.name !== 'input' &&
25446 this.name !== 'textarea' &&
25447 this.name !== 'select') {
25448 component.error(binding, {
25449 code: 'invalid-binding',
25450 message: `'value' is not a valid binding on <${this.name}> elements`
25451 });
25452 }
25453 if (this.name === 'select') {
25454 const attribute = this.attributes.find((attribute) => attribute.name === 'multiple');
25455 if (attribute && !attribute.is_static) {
25456 component.error(attribute, {
25457 code: 'dynamic-multiple-attribute',
25458 message: '\'multiple\' attribute cannot be dynamic if select uses two-way binding'
25459 });
25460 }
25461 }
25462 else {
25463 check_type_attribute();
25464 }
25465 }
25466 else if (name === 'checked' || name === 'indeterminate') {
25467 if (this.name !== 'input') {
25468 component.error(binding, {
25469 code: 'invalid-binding',
25470 message: `'${name}' is not a valid binding on <${this.name}> elements`
25471 });
25472 }
25473 const type = check_type_attribute();
25474 if (type !== 'checkbox') {
25475 let message = `'${name}' binding can only be used with <input type="checkbox">`;
25476 if (type === 'radio')
25477 message += ' — for <input type="radio">, use \'group\' binding';
25478 component.error(binding, { code: 'invalid-binding', message });
25479 }
25480 }
25481 else if (name === 'group') {
25482 if (this.name !== 'input') {
25483 component.error(binding, {
25484 code: 'invalid-binding',
25485 message: `'group' is not a valid binding on <${this.name}> elements`
25486 });
25487 }
25488 const type = check_type_attribute();
25489 if (type !== 'checkbox' && type !== 'radio') {
25490 component.error(binding, {
25491 code: 'invalid-binding',
25492 message: '\'group\' binding can only be used with <input type="checkbox"> or <input type="radio">'
25493 });
25494 }
25495 }
25496 else if (name === 'files') {
25497 if (this.name !== 'input') {
25498 component.error(binding, {
25499 code: 'invalid-binding',
25500 message: `'files' is not a valid binding on <${this.name}> elements`
25501 });
25502 }
25503 const type = check_type_attribute();
25504 if (type !== 'file') {
25505 component.error(binding, {
25506 code: 'invalid-binding',
25507 message: '\'files\' binding can only be used with <input type="file">'
25508 });
25509 }
25510 }
25511 else if (name === 'open') {
25512 if (this.name !== 'details') {
25513 component.error(binding, {
25514 code: 'invalid-binding',
25515 message: `'${name}' binding can only be used with <details>`
25516 });
25517 }
25518 }
25519 else if (name === 'currentTime' ||
25520 name === 'duration' ||
25521 name === 'paused' ||
25522 name === 'buffered' ||
25523 name === 'seekable' ||
25524 name === 'played' ||
25525 name === 'volume' ||
25526 name === 'muted' ||
25527 name === 'playbackRate' ||
25528 name === 'seeking' ||
25529 name === 'ended') {
25530 if (this.name !== 'audio' && this.name !== 'video') {
25531 component.error(binding, {
25532 code: 'invalid-binding',
25533 message: `'${name}' binding can only be used with <audio> or <video>`
25534 });
25535 }
25536 }
25537 else if (name === 'videoHeight' ||
25538 name === 'videoWidth') {
25539 if (this.name !== 'video') {
25540 component.error(binding, {
25541 code: 'invalid-binding',
25542 message: `'${name}' binding can only be used with <video>`
25543 });
25544 }
25545 }
25546 else if (dimensions.test(name)) {
25547 if (this.name === 'svg' && (name === 'offsetWidth' || name === 'offsetHeight')) {
25548 component.error(binding, {
25549 code: 'invalid-binding',
25550 message: `'${binding.name}' is not a valid binding on <svg>. Use '${name.replace('offset', 'client')}' instead`
25551 });
25552 }
25553 else if (svg$1.test(this.name)) {
25554 component.error(binding, {
25555 code: 'invalid-binding',
25556 message: `'${binding.name}' is not a valid binding on SVG elements`
25557 });
25558 }
25559 else if (is_void(this.name)) {
25560 component.error(binding, {
25561 code: 'invalid-binding',
25562 message: `'${binding.name}' is not a valid binding on void elements like <${this.name}>. Use a wrapper element instead`
25563 });
25564 }
25565 }
25566 else if (name === 'textContent' ||
25567 name === 'innerHTML') {
25568 const contenteditable = this.attributes.find((attribute) => attribute.name === 'contenteditable');
25569 if (!contenteditable) {
25570 component.error(binding, {
25571 code: 'missing-contenteditable-attribute',
25572 message: '\'contenteditable\' attribute is required for textContent and innerHTML two-way bindings'
25573 });
25574 }
25575 else if (contenteditable && !contenteditable.is_static) {
25576 component.error(contenteditable, {
25577 code: 'dynamic-contenteditable-attribute',
25578 message: '\'contenteditable\' attribute cannot be dynamic if element uses two-way binding'
25579 });
25580 }
25581 }
25582 else if (name !== 'this') {
25583 component.error(binding, {
25584 code: 'invalid-binding',
25585 message: `'${binding.name}' is not a valid binding`
25586 });
25587 }
25588 });
25589 }
25590 validate_content() {
25591 if (!a11y_required_content.has(this.name))
25592 return;
25593 if (this.bindings
25594 .some((binding) => ['textContent', 'innerHTML'].includes(binding.name)))
25595 return;
25596 if (this.children.length === 0) {
25597 this.component.warn(this, {
25598 code: 'a11y-missing-content',
25599 message: `A11y: <${this.name}> element should have child content`
25600 });
25601 }
25602 }
25603 validate_event_handlers() {
25604 const { component } = this;
25605 this.handlers.forEach(handler => {
25606 if (handler.modifiers.has('passive') && handler.modifiers.has('preventDefault')) {
25607 component.error(handler, {
25608 code: 'invalid-event-modifier',
25609 message: 'The \'passive\' and \'preventDefault\' modifiers cannot be used together'
25610 });
25611 }
25612 if (handler.modifiers.has('passive') && handler.modifiers.has('nonpassive')) {
25613 component.error(handler, {
25614 code: 'invalid-event-modifier',
25615 message: 'The \'passive\' and \'nonpassive\' modifiers cannot be used together'
25616 });
25617 }
25618 handler.modifiers.forEach(modifier => {
25619 if (!valid_modifiers.has(modifier)) {
25620 component.error(handler, {
25621 code: 'invalid-event-modifier',
25622 message: `Valid event modifiers are ${list$1(Array.from(valid_modifiers))}`
25623 });
25624 }
25625 if (modifier === 'passive') {
25626 if (passive_events.has(handler.name)) {
25627 if (handler.can_make_passive) {
25628 component.warn(handler, {
25629 code: 'redundant-event-modifier',
25630 message: 'Touch event handlers that don\'t use the \'event\' object are passive by default'
25631 });
25632 }
25633 }
25634 else {
25635 component.warn(handler, {
25636 code: 'redundant-event-modifier',
25637 message: 'The passive modifier only works with wheel and touch events'
25638 });
25639 }
25640 }
25641 if (component.compile_options.legacy && (modifier === 'once' || modifier === 'passive')) {
25642 // TODO this could be supported, but it would need a few changes to
25643 // how event listeners work
25644 component.error(handler, {
25645 code: 'invalid-event-modifier',
25646 message: `The '${modifier}' modifier cannot be used in legacy mode`
25647 });
25648 }
25649 });
25650 if (passive_events.has(handler.name) && handler.can_make_passive && !handler.modifiers.has('preventDefault') && !handler.modifiers.has('nonpassive')) {
25651 // touch/wheel events should be passive by default
25652 handler.modifiers.add('passive');
25653 }
25654 });
25655 }
25656 is_media_node() {
25657 return this.name === 'audio' || this.name === 'video';
25658 }
25659 add_css_class() {
25660 if (this.attributes.some(attr => attr.is_spread)) {
25661 this.needs_manual_style_scoping = true;
25662 return;
25663 }
25664 const { id } = this.component.stylesheet;
25665 const class_attribute = this.attributes.find(a => a.name === 'class');
25666 if (class_attribute && !class_attribute.is_true) {
25667 if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') {
25668 class_attribute.chunks[0].data += ` ${id}`;
25669 }
25670 else {
25671 class_attribute.chunks.push(new Text$1(this.component, this, this.scope, {
25672 type: 'Text',
25673 data: ` ${id}`,
25674 synthetic: true
25675 }));
25676 }
25677 }
25678 else {
25679 this.attributes.push(new Attribute(this.component, this, this.scope, {
25680 type: 'Attribute',
25681 name: 'class',
25682 value: [{ type: 'Text', data: id, synthetic: true }]
25683 }));
25684 }
25685 }
25686}
25687function should_have_attribute(node, attributes, name = node.name) {
25688 const article = /^[aeiou]/.test(attributes[0]) ? 'an' : 'a';
25689 const sequence = attributes.length > 1 ?
25690 attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}` :
25691 attributes[0];
25692 node.component.warn(node, {
25693 code: 'a11y-missing-attribute',
25694 message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
25695 });
25696}
25697function within_custom_element(parent) {
25698 while (parent) {
25699 if (parent.type === 'InlineComponent')
25700 return false;
25701 if (parent.type === 'Element' && /-/.test(parent.name))
25702 return true;
25703 parent = parent.parent;
25704 }
25705 return false;
25706}
25707
25708class Head$1 extends Node$1 {
25709 constructor(component, parent, scope, info) {
25710 super(component, parent, scope, info);
25711 if (info.attributes.length) {
25712 component.error(info.attributes[0], {
25713 code: 'invalid-attribute',
25714 message: '<svelte:head> should not have any attributes or directives'
25715 });
25716 }
25717 this.children = map_children(component, parent, scope, info.children.filter(child => {
25718 return (child.type !== 'Text' || /\S/.test(child.data));
25719 }));
25720 if (this.children.length > 0) {
25721 this.id = `svelte-${hash(this.component.source.slice(this.start, this.end))}`;
25722 }
25723 }
25724}
25725
25726class IfBlock$1 extends AbstractBlock {
25727 constructor(component, parent, scope, info) {
25728 super(component, parent, scope, info);
25729 this.expression = new Expression(component, this, scope, info.expression);
25730 this.children = map_children(component, this, scope, info.children);
25731 this.else = info.else
25732 ? new ElseBlock(component, this, scope, info.else)
25733 : null;
25734 this.warn_if_empty_block();
25735 }
25736}
25737
25738class InlineComponent$1 extends Node$1 {
25739 constructor(component, parent, scope, info) {
25740 super(component, parent, scope, info);
25741 this.attributes = [];
25742 this.bindings = [];
25743 this.handlers = [];
25744 this.lets = [];
25745 if (info.name !== 'svelte:component' && info.name !== 'svelte:self') {
25746 const name = info.name.split('.')[0]; // accommodate namespaces
25747 component.warn_if_undefined(name, info, scope);
25748 component.add_reference(name);
25749 }
25750 this.name = info.name;
25751 this.expression = this.name === 'svelte:component'
25752 ? new Expression(component, this, scope, info.expression)
25753 : null;
25754 info.attributes.forEach(node => {
25755 /* eslint-disable no-fallthrough */
25756 switch (node.type) {
25757 case 'Action':
25758 component.error(node, {
25759 code: 'invalid-action',
25760 message: 'Actions can only be applied to DOM elements, not components'
25761 });
25762 case 'Attribute':
25763 if (node.name === 'slot') {
25764 component.error(node, {
25765 code: 'invalid-prop',
25766 message: "'slot' is reserved for future use in named slots"
25767 });
25768 }
25769 // fallthrough
25770 case 'Spread':
25771 this.attributes.push(new Attribute(component, this, scope, node));
25772 break;
25773 case 'Binding':
25774 this.bindings.push(new Binding(component, this, scope, node));
25775 break;
25776 case 'Class':
25777 component.error(node, {
25778 code: 'invalid-class',
25779 message: 'Classes can only be applied to DOM elements, not components'
25780 });
25781 case 'EventHandler':
25782 this.handlers.push(new EventHandler(component, this, scope, node));
25783 break;
25784 case 'Let':
25785 this.lets.push(new Let(component, this, scope, node));
25786 break;
25787 case 'Transition':
25788 component.error(node, {
25789 code: 'invalid-transition',
25790 message: 'Transitions can only be applied to DOM elements, not components'
25791 });
25792 default:
25793 throw new Error(`Not implemented: ${node.type}`);
25794 }
25795 /* eslint-enable no-fallthrough */
25796 });
25797 if (this.lets.length > 0) {
25798 this.scope = scope.child();
25799 this.lets.forEach(l => {
25800 const dependencies = new Set([l.name.name]);
25801 l.names.forEach(name => {
25802 this.scope.add(name, dependencies, this);
25803 });
25804 });
25805 }
25806 else {
25807 this.scope = scope;
25808 }
25809 this.handlers.forEach(handler => {
25810 handler.modifiers.forEach(modifier => {
25811 if (modifier !== 'once') {
25812 component.error(handler, {
25813 code: 'invalid-event-modifier',
25814 message: "Event modifiers other than 'once' can only be used on DOM elements"
25815 });
25816 }
25817 });
25818 });
25819 this.children = map_children(component, this, this.scope, info.children);
25820 }
25821}
25822
25823class KeyBlock$1 extends AbstractBlock {
25824 constructor(component, parent, scope, info) {
25825 super(component, parent, scope, info);
25826 this.expression = new Expression(component, this, scope, info.expression);
25827 this.children = map_children(component, this, scope, info.children);
25828 this.warn_if_empty_block();
25829 }
25830}
25831
25832class Tag$2 extends Node$1 {
25833 constructor(component, parent, scope, info) {
25834 super(component, parent, scope, info);
25835 this.expression = new Expression(component, this, scope, info.expression);
25836 this.should_cache = (info.expression.type !== 'Identifier' ||
25837 (this.expression.dependencies.size && scope.names.has(info.expression.name)));
25838 }
25839}
25840
25841class MustacheTag extends Tag$2 {
25842}
25843
25844class Options extends Node$1 {
25845}
25846
25847class RawMustacheTag extends Tag$2 {
25848}
25849
25850class DebugTag$1 extends Node$1 {
25851 constructor(component, parent, scope, info) {
25852 super(component, parent, scope, info);
25853 this.expressions = info.identifiers.map(node => {
25854 return new Expression(component, parent, scope, node);
25855 });
25856 }
25857}
25858
25859class Slot$1 extends Element$1 {
25860 constructor(component, parent, scope, info) {
25861 super(component, parent, scope, info);
25862 this.values = new Map();
25863 info.attributes.forEach(attr => {
25864 if (attr.type !== 'Attribute') {
25865 component.error(attr, {
25866 code: 'invalid-slot-directive',
25867 message: '<slot> cannot have directives'
25868 });
25869 }
25870 if (attr.name === 'name') {
25871 if (attr.value.length !== 1 || attr.value[0].type !== 'Text') {
25872 component.error(attr, {
25873 code: 'dynamic-slot-name',
25874 message: '<slot> name cannot be dynamic'
25875 });
25876 }
25877 this.slot_name = attr.value[0].data;
25878 if (this.slot_name === 'default') {
25879 component.error(attr, {
25880 code: 'invalid-slot-name',
25881 message: 'default is a reserved word — it cannot be used as a slot name'
25882 });
25883 }
25884 }
25885 this.values.set(attr.name, new Attribute(component, this, scope, attr));
25886 });
25887 if (!this.slot_name)
25888 this.slot_name = 'default';
25889 if (this.slot_name === 'default') {
25890 // if this is the default slot, add our dependencies to any
25891 // other slots (which inherit our slot values) that were
25892 // previously encountered
25893 component.slots.forEach((slot) => {
25894 this.values.forEach((attribute, name) => {
25895 if (!slot.values.has(name)) {
25896 slot.values.set(name, attribute);
25897 }
25898 });
25899 });
25900 }
25901 else if (component.slots.has('default')) {
25902 // otherwise, go the other way — inherit values from
25903 // a previously encountered default slot
25904 const default_slot = component.slots.get('default');
25905 default_slot.values.forEach((attribute, name) => {
25906 if (!this.values.has(name)) {
25907 this.values.set(name, attribute);
25908 }
25909 });
25910 }
25911 component.slots.set(this.slot_name, this);
25912 }
25913}
25914
25915class Title$1 extends Node$1 {
25916 constructor(component, parent, scope, info) {
25917 super(component, parent, scope, info);
25918 this.children = map_children(component, parent, scope, info.children);
25919 if (info.attributes.length > 0) {
25920 component.error(info.attributes[0], {
25921 code: 'illegal-attribute',
25922 message: '<title> cannot have attributes'
25923 });
25924 }
25925 info.children.forEach(child => {
25926 if (child.type !== 'Text' && child.type !== 'MustacheTag') {
25927 component.error(child, {
25928 code: 'illegal-structure',
25929 message: '<title> can only contain text and {tags}'
25930 });
25931 }
25932 });
25933 this.should_cache = info.children.length === 1
25934 ? (info.children[0].type !== 'Identifier' ||
25935 scope.names.has(info.children[0].name))
25936 : true;
25937 }
25938}
25939
25940const valid_bindings = [
25941 'innerWidth',
25942 'innerHeight',
25943 'outerWidth',
25944 'outerHeight',
25945 'scrollX',
25946 'scrollY',
25947 'online'
25948];
25949class Window extends Node$1 {
25950 constructor(component, parent, scope, info) {
25951 super(component, parent, scope, info);
25952 this.handlers = [];
25953 this.bindings = [];
25954 this.actions = [];
25955 info.attributes.forEach(node => {
25956 if (node.type === 'EventHandler') {
25957 this.handlers.push(new EventHandler(component, this, scope, node));
25958 }
25959 else if (node.type === 'Binding') {
25960 if (node.expression.type !== 'Identifier') {
25961 const { parts } = flatten_reference(node.expression);
25962 // TODO is this constraint necessary?
25963 component.error(node.expression, {
25964 code: 'invalid-binding',
25965 message: `Bindings on <svelte:window> must be to top-level properties, e.g. '${parts[parts.length - 1]}' rather than '${parts.join('.')}'`
25966 });
25967 }
25968 if (!~valid_bindings.indexOf(node.name)) {
25969 const match = (node.name === 'width' ? 'innerWidth' :
25970 node.name === 'height' ? 'innerHeight' :
25971 fuzzymatch(node.name, valid_bindings));
25972 const message = `'${node.name}' is not a valid binding on <svelte:window>`;
25973 if (match) {
25974 component.error(node, {
25975 code: 'invalid-binding',
25976 message: `${message} (did you mean '${match}'?)`
25977 });
25978 }
25979 else {
25980 component.error(node, {
25981 code: 'invalid-binding',
25982 message: `${message} — valid bindings are ${list$1(valid_bindings)}`
25983 });
25984 }
25985 }
25986 this.bindings.push(new Binding(component, this, scope, node));
25987 }
25988 else if (node.type === 'Action') {
25989 this.actions.push(new Action(component, this, scope, node));
25990 }
25991 });
25992 }
25993}
25994
25995function get_constructor(type) {
25996 switch (type) {
25997 case 'AwaitBlock': return AwaitBlock$1;
25998 case 'Body': return Body;
25999 case 'Comment': return Comment$2;
26000 case 'EachBlock': return EachBlock$1;
26001 case 'Element': return Element$1;
26002 case 'Head': return Head$1;
26003 case 'IfBlock': return IfBlock$1;
26004 case 'InlineComponent': return InlineComponent$1;
26005 case 'KeyBlock': return KeyBlock$1;
26006 case 'MustacheTag': return MustacheTag;
26007 case 'Options': return Options;
26008 case 'RawMustacheTag': return RawMustacheTag;
26009 case 'DebugTag': return DebugTag$1;
26010 case 'Slot': return Slot$1;
26011 case 'Text': return Text$1;
26012 case 'Title': return Title$1;
26013 case 'Window': return Window;
26014 default: throw new Error(`Not implemented: ${type}`);
26015 }
26016}
26017function map_children(component, parent, scope, children) {
26018 let last = null;
26019 let ignores = [];
26020 return children.map(child => {
26021 const constructor = get_constructor(child.type);
26022 const use_ignores = child.type !== 'Text' && child.type !== 'Comment' && ignores.length;
26023 if (use_ignores)
26024 component.push_ignores(ignores);
26025 const node = new constructor(component, parent, scope, child);
26026 if (use_ignores)
26027 component.pop_ignores(), ignores = [];
26028 if (node.type === 'Comment' && node.ignores.length) {
26029 ignores.push(...node.ignores);
26030 }
26031 if (last)
26032 last.next = node;
26033 node.prev = last;
26034 last = node;
26035 return node;
26036 });
26037}
26038
26039class TemplateScope {
26040 constructor(parent) {
26041 this.owners = new Map();
26042 this.parent = parent;
26043 this.names = new Set(parent ? parent.names : []);
26044 this.dependencies_for_name = new Map(parent ? parent.dependencies_for_name : []);
26045 }
26046 add(name, dependencies, owner) {
26047 this.names.add(name);
26048 this.dependencies_for_name.set(name, dependencies);
26049 this.owners.set(name, owner);
26050 return this;
26051 }
26052 child() {
26053 const child = new TemplateScope(this);
26054 return child;
26055 }
26056 is_top_level(name) {
26057 return !this.parent || !this.names.has(name) && this.parent.is_top_level(name);
26058 }
26059 get_owner(name) {
26060 return this.owners.get(name) || (this.parent && this.parent.get_owner(name));
26061 }
26062 is_let(name) {
26063 const owner = this.get_owner(name);
26064 return owner && (owner.type === 'Element' || owner.type === 'InlineComponent');
26065 }
26066 is_await(name) {
26067 const owner = this.get_owner(name);
26068 return owner && (owner.type === 'ThenBlock' || owner.type === 'CatchBlock');
26069 }
26070}
26071
26072class Fragment extends Node$1 {
26073 constructor(component, info) {
26074 const scope = new TemplateScope();
26075 super(component, null, scope, info);
26076 this.scope = scope;
26077 this.children = map_children(component, this, scope, info.children);
26078 }
26079}
26080
26081// This file is automatically generated
26082var internal_exports = new Set(["HtmlTag", "SvelteComponent", "SvelteComponentDev", "SvelteElement", "action_destroyer", "add_attribute", "add_classes", "add_flush_callback", "add_location", "add_render_callback", "add_resize_listener", "add_transform", "afterUpdate", "append", "append_dev", "assign", "attr", "attr_dev", "attribute_to_object", "beforeUpdate", "bind", "binding_callbacks", "blank_object", "bubble", "check_outros", "children", "claim_component", "claim_element", "claim_space", "claim_text", "clear_loops", "component_subscribe", "compute_rest_props", "compute_slots", "createEventDispatcher", "create_animation", "create_bidirectional_transition", "create_component", "create_in_transition", "create_out_transition", "create_slot", "create_ssr_component", "current_component", "custom_event", "dataset_dev", "debug", "destroy_block", "destroy_component", "destroy_each", "detach", "detach_after_dev", "detach_before_dev", "detach_between_dev", "detach_dev", "dirty_components", "dispatch_dev", "each", "element", "element_is", "empty", "escape", "escaped", "exclude_internal_props", "fix_and_destroy_block", "fix_and_outro_and_destroy_block", "fix_position", "flush", "getContext", "get_binding_group_value", "get_current_component", "get_custom_elements_slots", "get_slot_changes", "get_slot_context", "get_spread_object", "get_spread_update", "get_store_value", "globals", "group_outros", "handle_promise", "has_prop", "identity", "init", "insert", "insert_dev", "intros", "invalid_attribute_name_character", "is_client", "is_crossorigin", "is_empty", "is_function", "is_promise", "listen", "listen_dev", "loop", "loop_guard", "missing_component", "mount_component", "noop", "not_equal", "now", "null_to_empty", "object_without_properties", "onDestroy", "onMount", "once", "outro_and_destroy_block", "prevent_default", "prop_dev", "query_selector_all", "raf", "run", "run_all", "safe_not_equal", "schedule_update", "select_multiple_value", "select_option", "select_options", "select_value", "self", "setContext", "set_attributes", "set_current_component", "set_custom_element_data", "set_data", "set_data_dev", "set_input_type", "set_input_value", "set_now", "set_raf", "set_store_value", "set_style", "set_svg_attributes", "space", "spread", "stop_propagation", "subscribe", "svg_element", "text", "tick", "time_ranges_to_array", "to_number", "toggle_class", "transition_in", "transition_out", "update_keyed_each", "update_slot", "validate_component", "validate_each_argument", "validate_each_keys", "validate_slots", "validate_store", "xlink_attr"]);
26083
26084function is_used_as_reference(node, parent) {
26085 if (!isReference(node, parent)) {
26086 return false;
26087 }
26088 if (!parent) {
26089 return true;
26090 }
26091 /* eslint-disable no-fallthrough */
26092 switch (parent.type) {
26093 // disregard the `foo` in `const foo = bar`
26094 case 'VariableDeclarator':
26095 return node !== parent.id;
26096 // disregard the `foo`, `bar` in `function foo(bar){}`
26097 case 'FunctionDeclaration':
26098 // disregard the `foo` in `import { foo } from 'foo'`
26099 case 'ImportSpecifier':
26100 // disregard the `foo` in `import foo from 'foo'`
26101 case 'ImportDefaultSpecifier':
26102 // disregard the `foo` in `import * as foo from 'foo'`
26103 case 'ImportNamespaceSpecifier':
26104 // disregard the `foo` in `export { foo }`
26105 case 'ExportSpecifier':
26106 return false;
26107 default:
26108 return true;
26109 }
26110}
26111
26112function check_graph_for_cycles(edges) {
26113 const graph = edges.reduce((g, edge) => {
26114 const [u, v] = edge;
26115 if (!g.has(u))
26116 g.set(u, []);
26117 if (!g.has(v))
26118 g.set(v, []);
26119 g.get(u).push(v);
26120 return g;
26121 }, new Map());
26122 const visited = new Set();
26123 const on_stack = new Set();
26124 const cycles = [];
26125 function visit(v) {
26126 visited.add(v);
26127 on_stack.add(v);
26128 graph.get(v).forEach(w => {
26129 if (!visited.has(w)) {
26130 visit(w);
26131 }
26132 else if (on_stack.has(w)) {
26133 cycles.push([...on_stack, w]);
26134 }
26135 });
26136 on_stack.delete(v);
26137 }
26138 graph.forEach((_, v) => {
26139 if (!visited.has(v)) {
26140 visit(v);
26141 }
26142 });
26143 return cycles[0];
26144}
26145
26146class Component {
26147 constructor(ast, source, name, compile_options, stats, warnings) {
26148 this.ignore_stack = [];
26149 this.vars = [];
26150 this.var_lookup = new Map();
26151 this.imports = [];
26152 this.hoistable_nodes = new Set();
26153 this.node_for_declaration = new Map();
26154 this.partly_hoisted = [];
26155 this.fully_hoisted = [];
26156 this.reactive_declarations = [];
26157 this.reactive_declaration_nodes = new Set();
26158 this.has_reactive_assignments = false;
26159 this.injected_reactive_declaration_vars = new Set();
26160 this.helpers = new Map();
26161 this.globals = new Map();
26162 this.indirect_dependencies = new Map();
26163 this.elements = [];
26164 this.aliases = new Map();
26165 this.used_names = new Set();
26166 this.globally_used_names = new Set();
26167 this.slots = new Map();
26168 this.slot_outlets = new Set();
26169 this.name = { type: 'Identifier', name };
26170 this.stats = stats;
26171 this.warnings = warnings;
26172 this.ast = ast;
26173 this.source = source;
26174 this.compile_options = compile_options;
26175 // the instance JS gets mutated, so we park
26176 // a copy here for later. TODO this feels gross
26177 this.original_ast = {
26178 html: ast.html,
26179 css: ast.css,
26180 instance: ast.instance && JSON.parse(JSON.stringify(ast.instance)),
26181 module: ast.module
26182 };
26183 this.file =
26184 compile_options.filename &&
26185 (typeof process !== 'undefined'
26186 ? compile_options.filename
26187 .replace(process.cwd(), '')
26188 .replace(/^[/\\]/, '')
26189 : compile_options.filename);
26190 this.locate = getLocator(this.source, { offsetLine: 1 });
26191 // styles
26192 this.stylesheet = new Stylesheet(source, ast, compile_options.filename, compile_options.dev);
26193 this.stylesheet.validate(this);
26194 this.component_options = process_component_options(this, this.ast.html.children);
26195 this.namespace =
26196 namespaces[this.component_options.namespace] ||
26197 this.component_options.namespace;
26198 if (compile_options.customElement) {
26199 if (this.component_options.tag === undefined &&
26200 compile_options.tag === undefined) {
26201 const svelteOptions = ast.html.children.find(child => child.name === 'svelte:options') || { start: 0, end: 0 };
26202 this.warn(svelteOptions, {
26203 code: 'custom-element-no-tag',
26204 message: 'No custom element \'tag\' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. <svelte:options tag="my-thing"/>. To hide this warning, use <svelte:options tag={null}/>'
26205 });
26206 }
26207 this.tag = this.component_options.tag || compile_options.tag;
26208 }
26209 else {
26210 this.tag = this.name.name;
26211 }
26212 this.walk_module_js();
26213 this.walk_instance_js_pre_template();
26214 this.fragment = new Fragment(this, ast.html);
26215 this.name = this.get_unique_name(name);
26216 this.walk_instance_js_post_template();
26217 this.elements.forEach(element => this.stylesheet.apply(element));
26218 if (!compile_options.customElement)
26219 this.stylesheet.reify();
26220 this.stylesheet.warn_on_unused_selectors(this);
26221 }
26222 add_var(variable) {
26223 this.vars.push(variable);
26224 this.var_lookup.set(variable.name, variable);
26225 }
26226 add_reference(name) {
26227 const variable = this.var_lookup.get(name);
26228 if (variable) {
26229 variable.referenced = true;
26230 }
26231 else if (is_reserved_keyword(name)) {
26232 this.add_var({
26233 name,
26234 injected: true,
26235 referenced: true
26236 });
26237 }
26238 else if (name[0] === '$') {
26239 this.add_var({
26240 name,
26241 injected: true,
26242 referenced: true,
26243 mutated: true,
26244 writable: true
26245 });
26246 const subscribable_name = name.slice(1);
26247 const variable = this.var_lookup.get(subscribable_name);
26248 if (variable) {
26249 variable.referenced = true;
26250 variable.subscribable = true;
26251 }
26252 }
26253 else {
26254 this.used_names.add(name);
26255 }
26256 }
26257 alias(name) {
26258 if (!this.aliases.has(name)) {
26259 this.aliases.set(name, this.get_unique_name(name));
26260 }
26261 return this.aliases.get(name);
26262 }
26263 apply_stylesheet(element) {
26264 this.elements.push(element);
26265 }
26266 global(name) {
26267 const alias = this.alias(name);
26268 this.globals.set(name, alias);
26269 return alias;
26270 }
26271 generate(result) {
26272 let js = null;
26273 let css = null;
26274 if (result) {
26275 const { compile_options, name } = this;
26276 const { format = 'esm' } = compile_options;
26277 const banner = `${this.file ? `${this.file} ` : ''}generated by Svelte v${'3.29.5'}`;
26278 const program = { type: 'Program', body: result.js };
26279 walk(program, {
26280 enter: (node, parent, key) => {
26281 if (node.type === 'Identifier') {
26282 if (node.name[0] === '@') {
26283 if (node.name[1] === '_') {
26284 const alias = this.global(node.name.slice(2));
26285 node.name = alias.name;
26286 }
26287 else {
26288 let name = node.name.slice(1);
26289 if (compile_options.dev) {
26290 if (internal_exports.has(`${name}_dev`)) {
26291 name += '_dev';
26292 }
26293 else if (internal_exports.has(`${name}Dev`)) {
26294 name += 'Dev';
26295 }
26296 }
26297 const alias = this.alias(name);
26298 this.helpers.set(name, alias);
26299 node.name = alias.name;
26300 }
26301 }
26302 else if (node.name[0] !== '#' && !is_valid(node.name)) {
26303 // this hack allows x`foo.${bar}` where bar could be invalid
26304 const literal = { type: 'Literal', value: node.name };
26305 if (parent.type === 'Property' && key === 'key') {
26306 parent.key = literal;
26307 }
26308 else if (parent.type === 'MemberExpression' && key === 'property') {
26309 parent.property = literal;
26310 parent.computed = true;
26311 }
26312 }
26313 }
26314 }
26315 });
26316 const referenced_globals = Array.from(this.globals, ([name, alias]) => name !== alias.name && { name, alias }).filter(Boolean);
26317 if (referenced_globals.length) {
26318 this.helpers.set('globals', this.alias('globals'));
26319 }
26320 const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({
26321 name,
26322 alias
26323 }));
26324 create_module(program, format, name, banner, compile_options.sveltePath, imported_helpers, referenced_globals, this.imports, this.vars
26325 .filter(variable => variable.module && variable.export_name)
26326 .map(variable => ({
26327 name: variable.name,
26328 as: variable.export_name
26329 })));
26330 css = compile_options.customElement
26331 ? { code: null, map: null }
26332 : result.css;
26333 js = print(program, {
26334 sourceMapSource: compile_options.filename
26335 });
26336 js.map.sources = [
26337 compile_options.filename ? get_relative_path(compile_options.outputFilename || '', compile_options.filename) : null
26338 ];
26339 js.map.sourcesContent = [
26340 this.source
26341 ];
26342 }
26343 return {
26344 js,
26345 css,
26346 ast: this.original_ast,
26347 warnings: this.warnings,
26348 vars: this.vars
26349 .filter(v => !v.global && !v.internal)
26350 .map(v => ({
26351 name: v.name,
26352 export_name: v.export_name || null,
26353 injected: v.injected || false,
26354 module: v.module || false,
26355 mutated: v.mutated || false,
26356 reassigned: v.reassigned || false,
26357 referenced: v.referenced || false,
26358 writable: v.writable || false,
26359 referenced_from_script: v.referenced_from_script || false
26360 })),
26361 stats: this.stats.render()
26362 };
26363 }
26364 get_unique_name(name, scope) {
26365 if (test)
26366 name = `${name}$`;
26367 let alias = name;
26368 for (let i = 1; reserved.has(alias) ||
26369 this.var_lookup.has(alias) ||
26370 this.used_names.has(alias) ||
26371 this.globally_used_names.has(alias) ||
26372 (scope && scope.has(alias)); alias = `${name}_${i++}`)
26373 ;
26374 this.used_names.add(alias);
26375 return { type: 'Identifier', name: alias };
26376 }
26377 get_unique_name_maker() {
26378 const local_used_names = new Set();
26379 function add(name) {
26380 local_used_names.add(name);
26381 }
26382 reserved.forEach(add);
26383 internal_exports.forEach(add);
26384 this.var_lookup.forEach((_value, key) => add(key));
26385 return (name) => {
26386 if (test)
26387 name = `${name}$`;
26388 let alias = name;
26389 for (let i = 1; this.used_names.has(alias) || local_used_names.has(alias); alias = `${name}_${i++}`)
26390 ;
26391 local_used_names.add(alias);
26392 this.globally_used_names.add(alias);
26393 return {
26394 type: 'Identifier',
26395 name: alias
26396 };
26397 };
26398 }
26399 error(pos, e) {
26400 error$1(e.message, {
26401 name: 'ValidationError',
26402 code: e.code,
26403 source: this.source,
26404 start: pos.start,
26405 end: pos.end,
26406 filename: this.compile_options.filename
26407 });
26408 }
26409 warn(pos, warning) {
26410 if (this.ignores && this.ignores.has(warning.code)) {
26411 return;
26412 }
26413 const start = this.locate(pos.start);
26414 const end = this.locate(pos.end);
26415 const frame = get_code_frame(this.source, start.line - 1, start.column);
26416 this.warnings.push({
26417 code: warning.code,
26418 message: warning.message,
26419 frame,
26420 start,
26421 end,
26422 pos: pos.start,
26423 filename: this.compile_options.filename,
26424 toString: () => `${warning.message} (${start.line}:${start.column})\n${frame}`
26425 });
26426 }
26427 extract_imports(node) {
26428 this.imports.push(node);
26429 }
26430 extract_exports(node) {
26431 if (node.type === 'ExportDefaultDeclaration') {
26432 this.error(node, {
26433 code: 'default-export',
26434 message: 'A component cannot have a default export'
26435 });
26436 }
26437 if (node.type === 'ExportNamedDeclaration') {
26438 if (node.source) {
26439 this.error(node, {
26440 code: 'not-implemented',
26441 message: 'A component currently cannot have an export ... from'
26442 });
26443 }
26444 if (node.declaration) {
26445 if (node.declaration.type === 'VariableDeclaration') {
26446 node.declaration.declarations.forEach(declarator => {
26447 extract_names(declarator.id).forEach(name => {
26448 const variable = this.var_lookup.get(name);
26449 variable.export_name = name;
26450 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
26451 this.warn(declarator, {
26452 code: 'unused-export-let',
26453 message: `${this.name.name} has unused export property '${name}'. If it is for external reference only, please consider using \`export const ${name}\``
26454 });
26455 }
26456 });
26457 });
26458 }
26459 else {
26460 const { name } = node.declaration.id;
26461 const variable = this.var_lookup.get(name);
26462 variable.export_name = name;
26463 }
26464 return node.declaration;
26465 }
26466 else {
26467 node.specifiers.forEach(specifier => {
26468 const variable = this.var_lookup.get(specifier.local.name);
26469 if (variable) {
26470 variable.export_name = specifier.exported.name;
26471 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
26472 this.warn(specifier, {
26473 code: 'unused-export-let',
26474 message: `${this.name.name} has unused export property '${specifier.exported.name}'. If it is for external reference only, please consider using \`export const ${specifier.exported.name}\``
26475 });
26476 }
26477 }
26478 });
26479 return null;
26480 }
26481 }
26482 }
26483 extract_javascript(script) {
26484 if (!script)
26485 return null;
26486 return script.content.body.filter(node => {
26487 if (!node)
26488 return false;
26489 if (this.hoistable_nodes.has(node))
26490 return false;
26491 if (this.reactive_declaration_nodes.has(node))
26492 return false;
26493 if (node.type === 'ImportDeclaration')
26494 return false;
26495 if (node.type === 'ExportDeclaration' && node.specifiers.length > 0)
26496 return false;
26497 return true;
26498 });
26499 }
26500 walk_module_js() {
26501 const component = this;
26502 const script = this.ast.module;
26503 if (!script)
26504 return;
26505 walk(script.content, {
26506 enter(node) {
26507 if (node.type === 'LabeledStatement' && node.label.name === '$') {
26508 component.warn(node, {
26509 code: 'module-script-reactive-declaration',
26510 message: '$: has no effect in a module script'
26511 });
26512 }
26513 }
26514 });
26515 const { scope, globals } = create_scopes(script.content);
26516 this.module_scope = scope;
26517 scope.declarations.forEach((node, name) => {
26518 if (name[0] === '$') {
26519 this.error(node, {
26520 code: 'illegal-declaration',
26521 message: 'The $ prefix is reserved, and cannot be used for variable and import names'
26522 });
26523 }
26524 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
26525 this.add_var({
26526 name,
26527 module: true,
26528 hoistable: true,
26529 writable
26530 });
26531 });
26532 globals.forEach((node, name) => {
26533 if (name[0] === '$') {
26534 this.error(node, {
26535 code: 'illegal-subscription',
26536 message: 'Cannot reference store value inside <script context="module">'
26537 });
26538 }
26539 else {
26540 this.add_var({
26541 name,
26542 global: true,
26543 hoistable: true
26544 });
26545 }
26546 });
26547 const { body } = script.content;
26548 let i = body.length;
26549 while (--i >= 0) {
26550 const node = body[i];
26551 if (node.type === 'ImportDeclaration') {
26552 this.extract_imports(node);
26553 body.splice(i, 1);
26554 }
26555 if (/^Export/.test(node.type)) {
26556 const replacement = this.extract_exports(node);
26557 if (replacement) {
26558 body[i] = replacement;
26559 }
26560 else {
26561 body.splice(i, 1);
26562 }
26563 }
26564 }
26565 }
26566 walk_instance_js_pre_template() {
26567 const script = this.ast.instance;
26568 if (!script)
26569 return;
26570 // inject vars for reactive declarations
26571 script.content.body.forEach(node => {
26572 if (node.type !== 'LabeledStatement')
26573 return;
26574 if (node.body.type !== 'ExpressionStatement')
26575 return;
26576 const { expression } = node.body;
26577 if (expression.type !== 'AssignmentExpression')
26578 return;
26579 if (expression.left.type === 'MemberExpression')
26580 return;
26581 extract_names(expression.left).forEach(name => {
26582 if (!this.var_lookup.has(name) && name[0] !== '$') {
26583 this.injected_reactive_declaration_vars.add(name);
26584 }
26585 });
26586 });
26587 const { scope: instance_scope, map, globals } = create_scopes(script.content);
26588 this.instance_scope = instance_scope;
26589 this.instance_scope_map = map;
26590 instance_scope.declarations.forEach((node, name) => {
26591 if (name[0] === '$') {
26592 this.error(node, {
26593 code: 'illegal-declaration',
26594 message: 'The $ prefix is reserved, and cannot be used for variable and import names'
26595 });
26596 }
26597 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
26598 const imported = node.type.startsWith('Import');
26599 this.add_var({
26600 name,
26601 initialised: instance_scope.initialised_declarations.has(name),
26602 writable,
26603 imported
26604 });
26605 this.node_for_declaration.set(name, node);
26606 });
26607 globals.forEach((node, name) => {
26608 if (this.var_lookup.has(name))
26609 return;
26610 if (this.injected_reactive_declaration_vars.has(name)) {
26611 this.add_var({
26612 name,
26613 injected: true,
26614 writable: true,
26615 reassigned: true,
26616 initialised: true
26617 });
26618 }
26619 else if (is_reserved_keyword(name)) {
26620 this.add_var({
26621 name,
26622 injected: true
26623 });
26624 }
26625 else if (name[0] === '$') {
26626 if (name === '$' || name[1] === '$') {
26627 this.error(node, {
26628 code: 'illegal-global',
26629 message: `${name} is an illegal variable name`
26630 });
26631 }
26632 this.add_var({
26633 name,
26634 injected: true,
26635 mutated: true,
26636 writable: true
26637 });
26638 this.add_reference(name.slice(1));
26639 const variable = this.var_lookup.get(name.slice(1));
26640 if (variable) {
26641 variable.subscribable = true;
26642 variable.referenced_from_script = true;
26643 }
26644 }
26645 else {
26646 this.add_var({
26647 name,
26648 global: true,
26649 hoistable: true
26650 });
26651 }
26652 });
26653 this.track_references_and_mutations();
26654 }
26655 walk_instance_js_post_template() {
26656 const script = this.ast.instance;
26657 if (!script)
26658 return;
26659 this.post_template_walk();
26660 this.hoist_instance_declarations();
26661 this.extract_reactive_declarations();
26662 }
26663 post_template_walk() {
26664 const script = this.ast.instance;
26665 if (!script)
26666 return;
26667 const component = this;
26668 const { content } = script;
26669 const { instance_scope, instance_scope_map: map } = this;
26670 let scope = instance_scope;
26671 const to_remove = [];
26672 const remove = (parent, prop, index) => {
26673 to_remove.unshift([parent, prop, index]);
26674 };
26675 let scope_updated = false;
26676 let generator_count = 0;
26677 walk(content, {
26678 enter(node, parent, prop, index) {
26679 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
26680 generator_count++;
26681 }
26682 if (map.has(node)) {
26683 scope = map.get(node);
26684 }
26685 if (node.type === 'ImportDeclaration') {
26686 component.extract_imports(node);
26687 // TODO: to use actual remove
26688 remove(parent, prop, index);
26689 return this.skip();
26690 }
26691 if (/^Export/.test(node.type)) {
26692 const replacement = component.extract_exports(node);
26693 if (replacement) {
26694 this.replace(replacement);
26695 }
26696 else {
26697 // TODO: to use actual remove
26698 remove(parent, prop, index);
26699 }
26700 return this.skip();
26701 }
26702 component.warn_on_undefined_store_value_references(node, parent, scope);
26703 },
26704 leave(node) {
26705 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
26706 generator_count--;
26707 }
26708 // do it on leave, to prevent infinite loop
26709 if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0 && generator_count <= 0) {
26710 const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout);
26711 if (to_replace_for_loop_protect) {
26712 this.replace(to_replace_for_loop_protect);
26713 scope_updated = true;
26714 }
26715 }
26716 if (map.has(node)) {
26717 scope = scope.parent;
26718 }
26719 }
26720 });
26721 for (const [parent, prop, index] of to_remove) {
26722 if (parent) {
26723 if (index !== null) {
26724 parent[prop].splice(index, 1);
26725 }
26726 else {
26727 delete parent[prop];
26728 }
26729 }
26730 }
26731 if (scope_updated) {
26732 const { scope, map } = create_scopes(script.content);
26733 this.instance_scope = scope;
26734 this.instance_scope_map = map;
26735 }
26736 }
26737 track_references_and_mutations() {
26738 const script = this.ast.instance;
26739 if (!script)
26740 return;
26741 const component = this;
26742 const { content } = script;
26743 const { instance_scope, module_scope, instance_scope_map: map } = this;
26744 let scope = instance_scope;
26745 walk(content, {
26746 enter(node, parent) {
26747 if (map.has(node)) {
26748 scope = map.get(node);
26749 }
26750 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
26751 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
26752 const names = extract_names(assignee);
26753 const deep = assignee.type === 'MemberExpression';
26754 names.forEach(name => {
26755 const scope_owner = scope.find_owner(name);
26756 if (scope_owner !== null
26757 ? scope_owner === instance_scope
26758 : module_scope && module_scope.has(name)) {
26759 const variable = component.var_lookup.get(name);
26760 variable[deep ? 'mutated' : 'reassigned'] = true;
26761 }
26762 });
26763 }
26764 if (is_used_as_reference(node, parent)) {
26765 const object = get_object(node);
26766 if (scope.find_owner(object.name) === instance_scope) {
26767 const variable = component.var_lookup.get(object.name);
26768 variable.referenced_from_script = true;
26769 }
26770 }
26771 },
26772 leave(node) {
26773 if (map.has(node)) {
26774 scope = scope.parent;
26775 }
26776 }
26777 });
26778 }
26779 warn_on_undefined_store_value_references(node, parent, scope) {
26780 if (node.type === 'LabeledStatement' &&
26781 node.label.name === '$' &&
26782 parent.type !== 'Program') {
26783 this.warn(node, {
26784 code: 'non-top-level-reactive-declaration',
26785 message: '$: has no effect outside of the top-level'
26786 });
26787 }
26788 if (isReference(node, parent)) {
26789 const object = get_object(node);
26790 const { name } = object;
26791 if (name[0] === '$') {
26792 if (!scope.has(name)) {
26793 this.warn_if_undefined(name, object, null);
26794 }
26795 if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
26796 this.error(node, {
26797 code: 'contextual-store',
26798 message: 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
26799 });
26800 }
26801 }
26802 }
26803 }
26804 loop_protect(node, scope, timeout) {
26805 if (node.type === 'WhileStatement' ||
26806 node.type === 'ForStatement' ||
26807 node.type === 'DoWhileStatement') {
26808 const guard = this.get_unique_name('guard', scope);
26809 this.used_names.add(guard.name);
26810 const before = b `const ${guard} = @loop_guard(${timeout})`;
26811 const inside = b `${guard}();`;
26812 // wrap expression statement with BlockStatement
26813 if (node.body.type !== 'BlockStatement') {
26814 node.body = {
26815 type: 'BlockStatement',
26816 body: [node.body]
26817 };
26818 }
26819 node.body.body.push(inside[0]);
26820 return {
26821 type: 'BlockStatement',
26822 body: [
26823 before[0],
26824 node
26825 ]
26826 };
26827 }
26828 return null;
26829 }
26830 rewrite_props(get_insert) {
26831 if (!this.ast.instance)
26832 return;
26833 const component = this;
26834 const { instance_scope, instance_scope_map: map } = this;
26835 let scope = instance_scope;
26836 walk(this.ast.instance.content, {
26837 enter(node, parent, key, index) {
26838 if (/Function/.test(node.type)) {
26839 return this.skip();
26840 }
26841 if (map.has(node)) {
26842 scope = map.get(node);
26843 }
26844 if (node.type === 'VariableDeclaration') {
26845 if (node.kind === 'var' || scope === instance_scope) {
26846 node.declarations.forEach(declarator => {
26847 if (declarator.id.type !== 'Identifier') {
26848 const inserts = [];
26849 extract_names(declarator.id).forEach(name => {
26850 const variable = component.var_lookup.get(name);
26851 if (variable.export_name) {
26852 // TODO is this still true post-#3539?
26853 component.error(declarator, {
26854 code: 'destructured-prop',
26855 message: 'Cannot declare props in destructured declaration'
26856 });
26857 }
26858 if (variable.subscribable) {
26859 inserts.push(get_insert(variable));
26860 }
26861 });
26862 if (inserts.length) {
26863 parent[key].splice(index + 1, 0, ...inserts);
26864 }
26865 return;
26866 }
26867 const { name } = declarator.id;
26868 const variable = component.var_lookup.get(name);
26869 if (variable.export_name && variable.writable) {
26870 declarator.id = {
26871 type: 'ObjectPattern',
26872 properties: [{
26873 type: 'Property',
26874 method: false,
26875 shorthand: false,
26876 computed: false,
26877 kind: 'init',
26878 key: { type: 'Identifier', name: variable.export_name },
26879 value: declarator.init
26880 ? {
26881 type: 'AssignmentPattern',
26882 left: declarator.id,
26883 right: declarator.init
26884 }
26885 : declarator.id
26886 }]
26887 };
26888 declarator.init = x `$$props`;
26889 }
26890 if (variable.subscribable && declarator.init) {
26891 const insert = get_insert(variable);
26892 parent[key].splice(index + 1, 0, ...insert);
26893 }
26894 });
26895 }
26896 }
26897 },
26898 leave(node, parent, _key, index) {
26899 if (map.has(node)) {
26900 scope = scope.parent;
26901 }
26902 if (node.type === 'ExportNamedDeclaration' && node.declaration) {
26903 parent.body[index] = node.declaration;
26904 }
26905 }
26906 });
26907 }
26908 hoist_instance_declarations() {
26909 // we can safely hoist variable declarations that are
26910 // initialised to literals, and functions that don't
26911 // reference instance variables other than other
26912 // hoistable functions. TODO others?
26913 const { hoistable_nodes, var_lookup, injected_reactive_declaration_vars, imports } = this;
26914 const top_level_function_declarations = new Map();
26915 const { body } = this.ast.instance.content;
26916 for (let i = 0; i < body.length; i += 1) {
26917 const node = body[i];
26918 if (node.type === 'VariableDeclaration') {
26919 const all_hoistable = node.declarations.every(d => {
26920 if (!d.init)
26921 return false;
26922 if (d.init.type !== 'Literal')
26923 return false;
26924 // everything except const values can be changed by e.g. svelte devtools
26925 // which means we can't hoist it
26926 if (node.kind !== 'const' && this.compile_options.dev)
26927 return false;
26928 const { name } = d.id;
26929 const v = this.var_lookup.get(name);
26930 if (v.reassigned)
26931 return false;
26932 if (v.export_name)
26933 return false;
26934 if (this.var_lookup.get(name).reassigned)
26935 return false;
26936 if (this.vars.find(variable => variable.name === name && variable.module)) {
26937 return false;
26938 }
26939 return true;
26940 });
26941 if (all_hoistable) {
26942 node.declarations.forEach(d => {
26943 const variable = this.var_lookup.get(d.id.name);
26944 variable.hoistable = true;
26945 });
26946 hoistable_nodes.add(node);
26947 body.splice(i--, 1);
26948 this.fully_hoisted.push(node);
26949 }
26950 }
26951 if (node.type === 'ExportNamedDeclaration' &&
26952 node.declaration &&
26953 node.declaration.type === 'FunctionDeclaration') {
26954 top_level_function_declarations.set(node.declaration.id.name, node);
26955 }
26956 if (node.type === 'FunctionDeclaration') {
26957 top_level_function_declarations.set(node.id.name, node);
26958 }
26959 }
26960 const checked = new Set();
26961 const walking = new Set();
26962 const is_hoistable = fn_declaration => {
26963 if (fn_declaration.type === 'ExportNamedDeclaration') {
26964 fn_declaration = fn_declaration.declaration;
26965 }
26966 const instance_scope = this.instance_scope;
26967 let scope = this.instance_scope;
26968 const map = this.instance_scope_map;
26969 let hoistable = true;
26970 // handle cycles
26971 walking.add(fn_declaration);
26972 walk(fn_declaration, {
26973 enter(node, parent) {
26974 if (!hoistable)
26975 return this.skip();
26976 if (map.has(node)) {
26977 scope = map.get(node);
26978 }
26979 if (isReference(node, parent)) {
26980 const { name } = flatten_reference(node);
26981 const owner = scope.find_owner(name);
26982 if (injected_reactive_declaration_vars.has(name)) {
26983 hoistable = false;
26984 }
26985 else if (name[0] === '$' && !owner) {
26986 hoistable = false;
26987 }
26988 else if (owner === instance_scope) {
26989 const variable = var_lookup.get(name);
26990 if (variable.reassigned || variable.mutated)
26991 hoistable = false;
26992 if (name === fn_declaration.id.name)
26993 return;
26994 if (variable.hoistable)
26995 return;
26996 if (top_level_function_declarations.has(name)) {
26997 const other_declaration = top_level_function_declarations.get(name);
26998 if (walking.has(other_declaration)) {
26999 hoistable = false;
27000 }
27001 else if (other_declaration.type === 'ExportNamedDeclaration' &&
27002 walking.has(other_declaration.declaration)) {
27003 hoistable = false;
27004 }
27005 else if (!is_hoistable(other_declaration)) {
27006 hoistable = false;
27007 }
27008 }
27009 else {
27010 hoistable = false;
27011 }
27012 }
27013 this.skip();
27014 }
27015 },
27016 leave(node) {
27017 if (map.has(node)) {
27018 scope = scope.parent;
27019 }
27020 }
27021 });
27022 checked.add(fn_declaration);
27023 walking.delete(fn_declaration);
27024 return hoistable;
27025 };
27026 for (const [name, node] of top_level_function_declarations) {
27027 if (is_hoistable(node)) {
27028 const variable = this.var_lookup.get(name);
27029 variable.hoistable = true;
27030 hoistable_nodes.add(node);
27031 const i = body.indexOf(node);
27032 body.splice(i, 1);
27033 this.fully_hoisted.push(node);
27034 }
27035 }
27036 for (const { specifiers } of imports) {
27037 for (const specifier of specifiers) {
27038 const variable = var_lookup.get(specifier.local.name);
27039 if (!variable.mutated || variable.subscribable) {
27040 variable.hoistable = true;
27041 }
27042 }
27043 }
27044 }
27045 extract_reactive_declarations() {
27046 const component = this;
27047 const unsorted_reactive_declarations = [];
27048 this.ast.instance.content.body.forEach(node => {
27049 if (node.type === 'LabeledStatement' && node.label.name === '$') {
27050 this.reactive_declaration_nodes.add(node);
27051 const assignees = new Set();
27052 const assignee_nodes = new Set();
27053 const dependencies = new Set();
27054 let scope = this.instance_scope;
27055 const map = this.instance_scope_map;
27056 walk(node.body, {
27057 enter(node, parent) {
27058 if (map.has(node)) {
27059 scope = map.get(node);
27060 }
27061 if (node.type === 'AssignmentExpression') {
27062 const left = get_object(node.left);
27063 extract_identifiers(left).forEach(node => {
27064 assignee_nodes.add(node);
27065 assignees.add(node.name);
27066 });
27067 if (node.operator !== '=') {
27068 dependencies.add(left.name);
27069 }
27070 }
27071 else if (node.type === 'UpdateExpression') {
27072 const identifier = get_object(node.argument);
27073 assignees.add(identifier.name);
27074 }
27075 else if (isReference(node, parent)) {
27076 const identifier = get_object(node);
27077 if (!assignee_nodes.has(identifier)) {
27078 const { name } = identifier;
27079 const owner = scope.find_owner(name);
27080 const variable = component.var_lookup.get(name);
27081 if (variable)
27082 variable.is_reactive_dependency = true;
27083 const is_writable_or_mutated = variable && (variable.writable || variable.mutated);
27084 if ((!owner || owner === component.instance_scope) &&
27085 (name[0] === '$' || is_writable_or_mutated)) {
27086 dependencies.add(name);
27087 }
27088 }
27089 this.skip();
27090 }
27091 },
27092 leave(node) {
27093 if (map.has(node)) {
27094 scope = scope.parent;
27095 }
27096 }
27097 });
27098 const { expression } = node.body;
27099 const declaration = expression && expression.left;
27100 unsorted_reactive_declarations.push({
27101 assignees,
27102 dependencies,
27103 node,
27104 declaration
27105 });
27106 }
27107 });
27108 const lookup = new Map();
27109 unsorted_reactive_declarations.forEach(declaration => {
27110 declaration.assignees.forEach(name => {
27111 if (!lookup.has(name)) {
27112 lookup.set(name, []);
27113 }
27114 // TODO warn or error if a name is assigned to in
27115 // multiple reactive declarations?
27116 lookup.get(name).push(declaration);
27117 });
27118 });
27119 const cycle = check_graph_for_cycles(unsorted_reactive_declarations.reduce((acc, declaration) => {
27120 declaration.assignees.forEach(v => {
27121 declaration.dependencies.forEach(w => {
27122 if (!declaration.assignees.has(w)) {
27123 acc.push([v, w]);
27124 }
27125 });
27126 });
27127 return acc;
27128 }, []));
27129 if (cycle && cycle.length) {
27130 const declarationList = lookup.get(cycle[0]);
27131 const declaration = declarationList[0];
27132 this.error(declaration.node, {
27133 code: 'cyclical-reactive-declaration',
27134 message: `Cyclical dependency detected: ${cycle.join(' → ')}`
27135 });
27136 }
27137 const add_declaration = declaration => {
27138 if (this.reactive_declarations.includes(declaration))
27139 return;
27140 declaration.dependencies.forEach(name => {
27141 if (declaration.assignees.has(name))
27142 return;
27143 const earlier_declarations = lookup.get(name);
27144 if (earlier_declarations) {
27145 earlier_declarations.forEach(add_declaration);
27146 }
27147 });
27148 this.reactive_declarations.push(declaration);
27149 };
27150 unsorted_reactive_declarations.forEach(add_declaration);
27151 }
27152 warn_if_undefined(name, node, template_scope) {
27153 if (name[0] === '$') {
27154 if (name === '$' || name[1] === '$' && !is_reserved_keyword(name)) {
27155 this.error(node, {
27156 code: 'illegal-global',
27157 message: `${name} is an illegal variable name`
27158 });
27159 }
27160 this.has_reactive_assignments = true; // TODO does this belong here?
27161 if (is_reserved_keyword(name))
27162 return;
27163 name = name.slice(1);
27164 }
27165 if (this.var_lookup.has(name) && !this.var_lookup.get(name).global)
27166 return;
27167 if (template_scope && template_scope.names.has(name))
27168 return;
27169 if (globals.has(name) && node.type !== 'InlineComponent')
27170 return;
27171 let message = `'${name}' is not defined`;
27172 if (!this.ast.instance) {
27173 message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;
27174 }
27175 this.warn(node, {
27176 code: 'missing-declaration',
27177 message
27178 });
27179 }
27180 push_ignores(ignores) {
27181 this.ignores = new Set(this.ignores || []);
27182 add_to_set(this.ignores, ignores);
27183 this.ignore_stack.push(this.ignores);
27184 }
27185 pop_ignores() {
27186 this.ignore_stack.pop();
27187 this.ignores = this.ignore_stack[this.ignore_stack.length - 1];
27188 }
27189}
27190function process_component_options(component, nodes) {
27191 const component_options = {
27192 immutable: component.compile_options.immutable || false,
27193 accessors: 'accessors' in component.compile_options
27194 ? component.compile_options.accessors
27195 : !!component.compile_options.customElement,
27196 preserveWhitespace: !!component.compile_options.preserveWhitespace
27197 };
27198 const node = nodes.find(node => node.name === 'svelte:options');
27199 function get_value(attribute, code, message) {
27200 const { value } = attribute;
27201 const chunk = value[0];
27202 if (!chunk)
27203 return true;
27204 if (value.length > 1) {
27205 component.error(attribute, { code, message });
27206 }
27207 if (chunk.type === 'Text')
27208 return chunk.data;
27209 if (chunk.expression.type !== 'Literal') {
27210 component.error(attribute, { code, message });
27211 }
27212 return chunk.expression.value;
27213 }
27214 if (node) {
27215 node.attributes.forEach(attribute => {
27216 if (attribute.type === 'Attribute') {
27217 const { name } = attribute;
27218 switch (name) {
27219 case 'tag': {
27220 const code = 'invalid-tag-attribute';
27221 const message = "'tag' must be a string literal";
27222 const tag = get_value(attribute, code, message);
27223 if (typeof tag !== 'string' && tag !== null) {
27224 component.error(attribute, { code, message });
27225 }
27226 if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
27227 component.error(attribute, {
27228 code: 'invalid-tag-property',
27229 message: "tag name must be two or more words joined by the '-' character"
27230 });
27231 }
27232 if (tag && !component.compile_options.customElement) {
27233 component.warn(attribute, {
27234 code: 'missing-custom-element-compile-options',
27235 message: "The 'tag' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?"
27236 });
27237 }
27238 component_options.tag = tag;
27239 break;
27240 }
27241 case 'namespace': {
27242 const code = 'invalid-namespace-attribute';
27243 const message = "The 'namespace' attribute must be a string literal representing a valid namespace";
27244 const ns = get_value(attribute, code, message);
27245 if (typeof ns !== 'string') {
27246 component.error(attribute, { code, message });
27247 }
27248 if (valid_namespaces.indexOf(ns) === -1) {
27249 const match = fuzzymatch(ns, valid_namespaces);
27250 if (match) {
27251 component.error(attribute, {
27252 code: 'invalid-namespace-property',
27253 message: `Invalid namespace '${ns}' (did you mean '${match}'?)`
27254 });
27255 }
27256 else {
27257 component.error(attribute, {
27258 code: 'invalid-namespace-property',
27259 message: `Invalid namespace '${ns}'`
27260 });
27261 }
27262 }
27263 component_options.namespace = ns;
27264 break;
27265 }
27266 case 'accessors':
27267 case 'immutable':
27268 case 'preserveWhitespace': {
27269 const code = `invalid-${name}-value`;
27270 const message = `${name} attribute must be true or false`;
27271 const value = get_value(attribute, code, message);
27272 if (typeof value !== 'boolean') {
27273 component.error(attribute, { code, message });
27274 }
27275 component_options[name] = value;
27276 break;
27277 }
27278 default:
27279 component.error(attribute, {
27280 code: 'invalid-options-attribute',
27281 message: '<svelte:options> unknown attribute'
27282 });
27283 }
27284 }
27285 else {
27286 component.error(attribute, {
27287 code: 'invalid-options-attribute',
27288 message: "<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes"
27289 });
27290 }
27291 });
27292 }
27293 return component_options;
27294}
27295function get_relative_path(from, to) {
27296 const from_parts = from.split(/[/\\]/);
27297 const to_parts = to.split(/[/\\]/);
27298 from_parts.pop(); // get dirname
27299 while (from_parts[0] === to_parts[0]) {
27300 from_parts.shift();
27301 to_parts.shift();
27302 }
27303 if (from_parts.length) {
27304 let i = from_parts.length;
27305 while (i--)
27306 from_parts[i] = '..';
27307 }
27308 return from_parts.concat(to_parts).join('/');
27309}
27310
27311function get_name_from_filename(filename) {
27312 if (!filename)
27313 return null;
27314 const parts = filename.split(/[/\\]/).map(encodeURI);
27315 if (parts.length > 1) {
27316 const index_match = parts[parts.length - 1].match(/^index(\.\w+)/);
27317 if (index_match) {
27318 parts.pop();
27319 parts[parts.length - 1] += index_match[1];
27320 }
27321 }
27322 const base = parts.pop()
27323 .replace(/%/g, 'u')
27324 .replace(/\.[^.]+$/, '')
27325 .replace(/[^a-zA-Z_$0-9]+/g, '_')
27326 .replace(/^_/, '')
27327 .replace(/_$/, '')
27328 .replace(/^(\d)/, '_$1');
27329 if (!base) {
27330 throw new Error(`Could not derive component name from file ${filename}`);
27331 }
27332 return base[0].toUpperCase() + base.slice(1);
27333}
27334
27335const valid_options = [
27336 'format',
27337 'name',
27338 'filename',
27339 'generate',
27340 'outputFilename',
27341 'cssOutputFilename',
27342 'sveltePath',
27343 'dev',
27344 'accessors',
27345 'immutable',
27346 'hydratable',
27347 'legacy',
27348 'customElement',
27349 'tag',
27350 'css',
27351 'loopGuardTimeout',
27352 'preserveComments',
27353 'preserveWhitespace'
27354];
27355function validate_options(options, warnings) {
27356 const { name, filename, loopGuardTimeout, dev } = options;
27357 Object.keys(options).forEach(key => {
27358 if (!valid_options.includes(key)) {
27359 const match = fuzzymatch(key, valid_options);
27360 let message = `Unrecognized option '${key}'`;
27361 if (match)
27362 message += ` (did you mean '${match}'?)`;
27363 throw new Error(message);
27364 }
27365 });
27366 if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) {
27367 throw new Error(`options.name must be a valid identifier (got '${name}')`);
27368 }
27369 if (name && /^[a-z]/.test(name)) {
27370 const message = 'options.name should be capitalised';
27371 warnings.push({
27372 code: 'options-lowercase-name',
27373 message,
27374 filename,
27375 toString: () => message
27376 });
27377 }
27378 if (loopGuardTimeout && !dev) {
27379 const message = 'options.loopGuardTimeout is for options.dev = true only';
27380 warnings.push({
27381 code: 'options-loop-guard-timeout',
27382 message,
27383 filename,
27384 toString: () => message
27385 });
27386 }
27387}
27388function compile(source, options = {}) {
27389 options = Object.assign({ generate: 'dom', dev: false }, options);
27390 const stats = new Stats();
27391 const warnings = [];
27392 validate_options(options, warnings);
27393 stats.start('parse');
27394 const ast = parse$3(source, options);
27395 stats.stop('parse');
27396 stats.start('create component');
27397 const component = new Component(ast, source, options.name || get_name_from_filename(options.filename) || 'Component', options, stats, warnings);
27398 stats.stop('create component');
27399 const result = options.generate === false
27400 ? null
27401 : options.generate === 'ssr'
27402 ? ssr(component, options)
27403 : dom(component, options);
27404 return component.generate(result);
27405}
27406
27407function parse_attributes(str) {
27408 const attrs = {};
27409 str.split(/\s+/).filter(Boolean).forEach(attr => {
27410 const p = attr.indexOf('=');
27411 if (p === -1) {
27412 attrs[attr] = true;
27413 }
27414 else {
27415 attrs[attr.slice(0, p)] = '\'"'.includes(attr[p + 1]) ?
27416 attr.slice(p + 2, -1) :
27417 attr.slice(p + 1);
27418 }
27419 });
27420 return attrs;
27421}
27422async function replace_async(str, re, func) {
27423 const replacements = [];
27424 str.replace(re, (...args) => {
27425 replacements.push(func(...args).then(res => ({
27426 offset: args[args.length - 2],
27427 length: args[0].length,
27428 replacement: res
27429 })));
27430 return '';
27431 });
27432 let out = '';
27433 let last_end = 0;
27434 for (const { offset, length, replacement } of await Promise.all(replacements)) {
27435 out += str.slice(last_end, offset) + replacement;
27436 last_end = offset + length;
27437 }
27438 out += str.slice(last_end);
27439 return out;
27440}
27441async function preprocess(source, preprocessor, options) {
27442 // @ts-ignore todo: doublecheck
27443 const filename = (options && options.filename) || preprocessor.filename; // legacy
27444 const dependencies = [];
27445 const preprocessors = Array.isArray(preprocessor) ? preprocessor : [preprocessor];
27446 const markup = preprocessors.map(p => p.markup).filter(Boolean);
27447 const script = preprocessors.map(p => p.script).filter(Boolean);
27448 const style = preprocessors.map(p => p.style).filter(Boolean);
27449 for (const fn of markup) {
27450 const processed = await fn({
27451 content: source,
27452 filename
27453 });
27454 if (processed && processed.dependencies)
27455 dependencies.push(...processed.dependencies);
27456 source = processed ? processed.code : source;
27457 }
27458 for (const fn of script) {
27459 source = await replace_async(source, /<!--[^]*?-->|<script(\s[^]*?)?(?:>([^]*?)<\/script>|\/>)/gi, async (match, attributes = '', content = '') => {
27460 if (!attributes && !content) {
27461 return match;
27462 }
27463 attributes = attributes || '';
27464 const processed = await fn({
27465 content,
27466 attributes: parse_attributes(attributes),
27467 filename
27468 });
27469 if (processed && processed.dependencies)
27470 dependencies.push(...processed.dependencies);
27471 return processed ? `<script${attributes}>${processed.code}</script>` : match;
27472 });
27473 }
27474 for (const fn of style) {
27475 source = await replace_async(source, /<!--[^]*?-->|<style(\s[^]*?)?(?:>([^]*?)<\/style>|\/>)/gi, async (match, attributes = '', content = '') => {
27476 if (!attributes && !content) {
27477 return match;
27478 }
27479 const processed = await fn({
27480 content,
27481 attributes: parse_attributes(attributes),
27482 filename
27483 });
27484 if (processed && processed.dependencies)
27485 dependencies.push(...processed.dependencies);
27486 return processed ? `<style${attributes}>${processed.code}</style>` : match;
27487 });
27488 }
27489 return {
27490 // TODO return separated output, in future version where svelte.compile supports it:
27491 // style: { code: styleCode, map: styleMap },
27492 // script { code: scriptCode, map: scriptMap },
27493 // markup { code: markupCode, map: markupMap },
27494 code: source,
27495 dependencies: [...new Set(dependencies)],
27496 toString() {
27497 return source;
27498 }
27499 };
27500}
27501
27502const VERSION = '3.29.5';
27503
27504export { VERSION, compile, parse$3 as parse, preprocess, walk };
27505//# sourceMappingURL=compiler.mjs.map
27506
\No newline at end of file