UNPKG

969 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 charToInteger = {};
5520var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
5521for (var i = 0; i < chars.length; i++) {
5522 charToInteger[chars.charCodeAt(i)] = i;
5523}
5524function decode(mappings) {
5525 var decoded = [];
5526 var line = [];
5527 var segment = [
5528 0,
5529 0,
5530 0,
5531 0,
5532 0,
5533 ];
5534 var j = 0;
5535 for (var i = 0, shift = 0, value = 0; i < mappings.length; i++) {
5536 var c = mappings.charCodeAt(i);
5537 if (c === 44) { // ","
5538 segmentify(line, segment, j);
5539 j = 0;
5540 }
5541 else if (c === 59) { // ";"
5542 segmentify(line, segment, j);
5543 j = 0;
5544 decoded.push(line);
5545 line = [];
5546 segment[0] = 0;
5547 }
5548 else {
5549 var integer = charToInteger[c];
5550 if (integer === undefined) {
5551 throw new Error('Invalid character (' + String.fromCharCode(c) + ')');
5552 }
5553 var hasContinuationBit = integer & 32;
5554 integer &= 31;
5555 value += integer << shift;
5556 if (hasContinuationBit) {
5557 shift += 5;
5558 }
5559 else {
5560 var shouldNegate = value & 1;
5561 value >>>= 1;
5562 if (shouldNegate) {
5563 value = value === 0 ? -0x80000000 : -value;
5564 }
5565 segment[j] += value;
5566 j++;
5567 value = shift = 0; // reset
5568 }
5569 }
5570 }
5571 segmentify(line, segment, j);
5572 decoded.push(line);
5573 return decoded;
5574}
5575function segmentify(line, segment, j) {
5576 // This looks ugly, but we're creating specialized arrays with a specific
5577 // length. This is much faster than creating a new array (which v8 expands to
5578 // a capacity of 17 after pushing the first item), or slicing out a subarray
5579 // (which is slow). Length 4 is assumed to be the most frequent, followed by
5580 // length 5 (since not everything will have an associated name), followed by
5581 // length 1 (it's probably rare for a source substring to not have an
5582 // associated segment data).
5583 if (j === 4)
5584 line.push([segment[0], segment[1], segment[2], segment[3]]);
5585 else if (j === 5)
5586 line.push([segment[0], segment[1], segment[2], segment[3], segment[4]]);
5587 else if (j === 1)
5588 line.push([segment[0]]);
5589}
5590function encode(decoded) {
5591 var sourceFileIndex = 0; // second field
5592 var sourceCodeLine = 0; // third field
5593 var sourceCodeColumn = 0; // fourth field
5594 var nameIndex = 0; // fifth field
5595 var mappings = '';
5596 for (var i = 0; i < decoded.length; i++) {
5597 var line = decoded[i];
5598 if (i > 0)
5599 mappings += ';';
5600 if (line.length === 0)
5601 continue;
5602 var generatedCodeColumn = 0; // first field
5603 var lineMappings = [];
5604 for (var _i = 0, line_1 = line; _i < line_1.length; _i++) {
5605 var segment = line_1[_i];
5606 var segmentMappings = encodeInteger(segment[0] - generatedCodeColumn);
5607 generatedCodeColumn = segment[0];
5608 if (segment.length > 1) {
5609 segmentMappings +=
5610 encodeInteger(segment[1] - sourceFileIndex) +
5611 encodeInteger(segment[2] - sourceCodeLine) +
5612 encodeInteger(segment[3] - sourceCodeColumn);
5613 sourceFileIndex = segment[1];
5614 sourceCodeLine = segment[2];
5615 sourceCodeColumn = segment[3];
5616 }
5617 if (segment.length === 5) {
5618 segmentMappings += encodeInteger(segment[4] - nameIndex);
5619 nameIndex = segment[4];
5620 }
5621 lineMappings.push(segmentMappings);
5622 }
5623 mappings += lineMappings.join(',');
5624 }
5625 return mappings;
5626}
5627function encodeInteger(num) {
5628 var result = '';
5629 num = num < 0 ? (-num << 1) | 1 : num << 1;
5630 do {
5631 var clamped = num & 31;
5632 num >>>= 5;
5633 if (num > 0) {
5634 clamped |= 32;
5635 }
5636 result += chars[clamped];
5637 } while (num > 0);
5638 return result;
5639}
5640
5641// generate an ID that is, to all intents and purposes, unique
5642const id = (Math.round(Math.random() * 1e20)).toString(36);
5643const re = new RegExp(`_${id}_(?:(\\d+)|(AT)|(HASH))_(\\w+)?`, 'g');
5644
5645const get_comment_handlers = (comments, raw) => ({
5646
5647 // pass to acorn options
5648 onComment: (block, value, start, end) => {
5649 if (block && /\n/.test(value)) {
5650 let a = start;
5651 while (a > 0 && raw[a - 1] !== '\n') a -= 1;
5652
5653 let b = a;
5654 while (/[ \t]/.test(raw[b])) b += 1;
5655
5656 const indentation = raw.slice(a, b);
5657 value = value.replace(new RegExp(`^${indentation}`, 'gm'), '');
5658 }
5659
5660 comments.push({ type: block ? 'Block' : 'Line', value, start, end });
5661 },
5662
5663 // pass to estree-walker options
5664 enter(node) {
5665 let comment;
5666
5667 while (comments[0] && comments[0].start < (node ).start) {
5668 comment = comments.shift();
5669
5670 comment.value = comment.value.replace(re, (match, id, at, hash, value) => {
5671 if (hash) return `#${value}`;
5672 if (at) return `@${value}`;
5673
5674 return match;
5675 });
5676
5677 const next = comments[0] || node;
5678 (comment ).has_trailing_newline = (
5679 comment.type === 'Line' ||
5680 /\n/.test(raw.slice(comment.end, (next ).start))
5681 );
5682
5683 (node.leadingComments || (node.leadingComments = [])).push(comment);
5684 }
5685 },
5686 leave(node) {
5687 if (comments[0]) {
5688 const slice = raw.slice((node ).end, comments[0].start);
5689
5690 if (/^[,) \t]*$/.test(slice)) {
5691 node.trailingComments = [comments.shift()];
5692 }
5693 }
5694 }
5695
5696});
5697
5698function handle(node, state) {
5699 const handler = handlers[node.type];
5700
5701 if (!handler) {
5702 throw new Error(`Not implemented ${node.type}`);
5703 }
5704
5705 const result = handler(node, state);
5706
5707 if (node.leadingComments) {
5708 result.unshift(c(node.leadingComments.map(comment => comment.type === 'Block'
5709 ? `/*${comment.value}*/${(comment ).has_trailing_newline ? `\n${state.indent}` : ` `}`
5710 : `//${comment.value}${(comment ).has_trailing_newline ? `\n${state.indent}` : ` `}`).join(``)));
5711 }
5712
5713 if (node.trailingComments) {
5714 state.comments.push(node.trailingComments[0]); // there is only ever one
5715 }
5716
5717 return result;
5718}
5719
5720function c(content, node) {
5721 return {
5722 content,
5723 loc: node && node.loc,
5724 has_newline: /\n/.test(content)
5725 };
5726}
5727
5728const OPERATOR_PRECEDENCE = {
5729 '||': 2,
5730 '&&': 3,
5731 '??': 4,
5732 '|': 5,
5733 '^': 6,
5734 '&': 7,
5735 '==': 8,
5736 '!=': 8,
5737 '===': 8,
5738 '!==': 8,
5739 '<': 9,
5740 '>': 9,
5741 '<=': 9,
5742 '>=': 9,
5743 in: 9,
5744 instanceof: 9,
5745 '<<': 10,
5746 '>>': 10,
5747 '>>>': 10,
5748 '+': 11,
5749 '-': 11,
5750 '*': 12,
5751 '%': 12,
5752 '/': 12,
5753 '**': 13,
5754};
5755
5756const EXPRESSIONS_PRECEDENCE = {
5757 ArrayExpression: 20,
5758 TaggedTemplateExpression: 20,
5759 ThisExpression: 20,
5760 Identifier: 20,
5761 Literal: 18,
5762 TemplateLiteral: 20,
5763 Super: 20,
5764 SequenceExpression: 20,
5765 MemberExpression: 19,
5766 CallExpression: 19,
5767 NewExpression: 19,
5768 AwaitExpression: 17,
5769 ClassExpression: 17,
5770 FunctionExpression: 17,
5771 ObjectExpression: 17,
5772 UpdateExpression: 16,
5773 UnaryExpression: 15,
5774 BinaryExpression: 14,
5775 LogicalExpression: 13,
5776 ConditionalExpression: 4,
5777 ArrowFunctionExpression: 3,
5778 AssignmentExpression: 3,
5779 YieldExpression: 2,
5780 RestElement: 1
5781};
5782
5783function needs_parens(node, parent, is_right) {
5784 // special case where logical expressions and coalesce expressions cannot be mixed,
5785 // either of them need to be wrapped with parentheses
5786 if (
5787 node.type === 'LogicalExpression' &&
5788 parent.type === 'LogicalExpression' &&
5789 ((parent.operator === '??' && node.operator !== '??') ||
5790 (parent.operator !== '??' && node.operator === '??'))
5791 ) {
5792 return true;
5793 }
5794
5795 const precedence = EXPRESSIONS_PRECEDENCE[node.type];
5796 const parent_precedence = EXPRESSIONS_PRECEDENCE[parent.type];
5797
5798 if (precedence !== parent_precedence) {
5799 // Different node types
5800 return (
5801 (!is_right &&
5802 precedence === 15 &&
5803 parent_precedence === 14 &&
5804 parent.operator === '**') ||
5805 precedence < parent_precedence
5806 );
5807 }
5808
5809 if (precedence !== 13 && precedence !== 14) {
5810 // Not a `LogicalExpression` or `BinaryExpression`
5811 return false;
5812 }
5813
5814 if ((node ).operator === '**' && parent.operator === '**') {
5815 // Exponentiation operator has right-to-left associativity
5816 return !is_right;
5817 }
5818
5819 if (is_right) {
5820 // Parenthesis are used if both operators have the same precedence
5821 return (
5822 OPERATOR_PRECEDENCE[(node ).operator] <=
5823 OPERATOR_PRECEDENCE[parent.operator]
5824 );
5825 }
5826
5827 return (
5828 OPERATOR_PRECEDENCE[(node ).operator] <
5829 OPERATOR_PRECEDENCE[parent.operator]
5830 );
5831}
5832
5833function has_call_expression(node) {
5834 while (node) {
5835 if (node.type[0] === 'CallExpression') {
5836 return true;
5837 } else if (node.type === 'MemberExpression') {
5838 node = node.object;
5839 } else {
5840 return false;
5841 }
5842 }
5843}
5844
5845const has_newline = (chunks) => {
5846 for (let i = 0; i < chunks.length; i += 1) {
5847 if (chunks[i].has_newline) return true;
5848 }
5849 return false;
5850};
5851
5852const get_length = (chunks) => {
5853 let total = 0;
5854 for (let i = 0; i < chunks.length; i += 1) {
5855 total += chunks[i].content.length;
5856 }
5857 return total;
5858};
5859
5860const sum = (a, b) => a + b;
5861
5862const join = (nodes, separator) => {
5863 if (nodes.length === 0) return [];
5864 const joined = [...nodes[0]];
5865 for (let i = 1; i < nodes.length; i += 1) {
5866 joined.push(separator, ...nodes[i] );
5867 }
5868 return joined;
5869};
5870
5871const scoped = (fn) => {
5872 return (node, state) => {
5873 return fn(node, {
5874 ...state,
5875 scope: state.scope_map.get(node)
5876 });
5877 };
5878};
5879
5880const deconflict = (name, names) => {
5881 const original = name;
5882 let i = 1;
5883
5884 while (names.has(name)) {
5885 name = `${original}$${i++}`;
5886 }
5887
5888 return name;
5889};
5890
5891const handle_body = (nodes, state) => {
5892 const chunks = [];
5893
5894 const body = nodes.map(statement => {
5895 const chunks = handle(statement, {
5896 ...state,
5897 indent: state.indent
5898 });
5899
5900 let add_newline = false;
5901
5902 while (state.comments.length) {
5903 const comment = state.comments.shift();
5904 const prefix = add_newline ? `\n${state.indent}` : ` `;
5905
5906 chunks.push(c(comment.type === 'Block'
5907 ? `${prefix}/*${comment.value}*/`
5908 : `${prefix}//${comment.value}`));
5909
5910 add_newline = (comment.type === 'Line');
5911 }
5912
5913 return chunks;
5914 });
5915
5916 let needed_padding = false;
5917
5918 for (let i = 0; i < body.length; i += 1) {
5919 const needs_padding = has_newline(body[i]);
5920
5921 if (i > 0) {
5922 chunks.push(
5923 c(needs_padding || needed_padding ? `\n\n${state.indent}` : `\n${state.indent}`)
5924 );
5925 }
5926
5927 chunks.push(
5928 ...body[i]
5929 );
5930
5931 needed_padding = needs_padding;
5932 }
5933
5934 return chunks;
5935};
5936
5937const handle_var_declaration = (node, state) => {
5938 const chunks = [c(`${node.kind} `)];
5939
5940 const declarators = node.declarations.map(d => handle(d, {
5941 ...state,
5942 indent: state.indent + (node.declarations.length === 1 ? '' : '\t')
5943 }));
5944
5945 const multiple_lines = (
5946 declarators.some(has_newline) ||
5947 (declarators.map(get_length).reduce(sum, 0) + (state.indent.length + declarators.length - 1) * 2) > 80
5948 );
5949
5950 const separator = c(multiple_lines ? `,\n${state.indent}\t` : ', ');
5951
5952 if (multiple_lines) {
5953 chunks.push(...join(declarators, separator));
5954 } else {
5955 chunks.push(
5956 ...join(declarators, separator)
5957 );
5958 }
5959
5960 return chunks;
5961};
5962
5963const handlers = {
5964 Program(node, state) {
5965 return handle_body(node.body, state);
5966 },
5967
5968 BlockStatement: scoped((node, state) => {
5969 return [
5970 c(`{\n${state.indent}\t`),
5971 ...handle_body(node.body, { ...state, indent: state.indent + '\t' }),
5972 c(`\n${state.indent}}`)
5973 ];
5974 }),
5975
5976 EmptyStatement(node, state) {
5977 return [];
5978 },
5979
5980 ParenthesizedExpression(node, state) {
5981 return handle(node.expression, state);
5982 },
5983
5984 ExpressionStatement(node, state) {
5985 if (
5986 node.expression.type === 'AssignmentExpression' &&
5987 node.expression.left.type === 'ObjectPattern'
5988 ) {
5989 // is an AssignmentExpression to an ObjectPattern
5990 return [
5991 c('('),
5992 ...handle(node.expression, state),
5993 c(');')
5994 ];
5995 }
5996
5997 return [
5998 ...handle(node.expression, state),
5999 c(';')
6000 ];
6001 },
6002
6003 IfStatement(node, state) {
6004 const chunks = [
6005 c('if ('),
6006 ...handle(node.test, state),
6007 c(') '),
6008 ...handle(node.consequent, state)
6009 ];
6010
6011 if (node.alternate) {
6012 chunks.push(
6013 c(' else '),
6014 ...handle(node.alternate, state)
6015 );
6016 }
6017
6018 return chunks;
6019 },
6020
6021 LabeledStatement(node, state) {
6022 return [
6023 ...handle(node.label, state),
6024 c(': '),
6025 ...handle(node.body, state)
6026 ];
6027 },
6028
6029 BreakStatement(node, state) {
6030 return node.label
6031 ? [c('break '), ...handle(node.label, state), c(';')]
6032 : [c('break;')];
6033 },
6034
6035 ContinueStatement(node, state) {
6036 return node.label
6037 ? [c('continue '), ...handle(node.label, state), c(';')]
6038 : [c('continue;')];
6039 },
6040
6041 WithStatement(node, state) {
6042 return [
6043 c('with ('),
6044 ...handle(node.object, state),
6045 c(') '),
6046 ...handle(node.body, state)
6047 ];
6048 },
6049
6050 SwitchStatement(node, state) {
6051 const chunks = [
6052 c('switch ('),
6053 ...handle(node.discriminant, state),
6054 c(') {')
6055 ];
6056
6057 node.cases.forEach(block => {
6058 if (block.test) {
6059 chunks.push(
6060 c(`\n${state.indent}\tcase `),
6061 ...handle(block.test, { ...state, indent: `${state.indent}\t` }),
6062 c(':')
6063 );
6064 } else {
6065 chunks.push(c(`\n${state.indent}\tdefault:`));
6066 }
6067
6068 block.consequent.forEach(statement => {
6069 chunks.push(
6070 c(`\n${state.indent}\t\t`),
6071 ...handle(statement, { ...state, indent: `${state.indent}\t\t` })
6072 );
6073 });
6074 });
6075
6076 chunks.push(c(`\n${state.indent}}`));
6077
6078 return chunks;
6079 },
6080
6081 ReturnStatement(node, state) {
6082 if (node.argument) {
6083 return [
6084 c('return '),
6085 ...handle(node.argument, state),
6086 c(';')
6087 ];
6088 } else {
6089 return [c('return;')];
6090 }
6091 },
6092
6093 ThrowStatement(node, state) {
6094 return [
6095 c('throw '),
6096 ...handle(node.argument, state),
6097 c(';')
6098 ];
6099 },
6100
6101 TryStatement(node, state) {
6102 const chunks = [
6103 c('try '),
6104 ...handle(node.block, state)
6105 ];
6106
6107 if (node.handler) {
6108 if (node.handler.param) {
6109 chunks.push(
6110 c(' catch('),
6111 ...handle(node.handler.param, state),
6112 c(') ')
6113 );
6114 } else {
6115 chunks.push(c(' catch '));
6116 }
6117
6118 chunks.push(...handle(node.handler.body, state));
6119 }
6120
6121 if (node.finalizer) {
6122 chunks.push(c(' finally '), ...handle(node.finalizer, state));
6123 }
6124
6125 return chunks;
6126 },
6127
6128 WhileStatement(node, state) {
6129 return [
6130 c('while ('),
6131 ...handle(node.test, state),
6132 c(') '),
6133 ...handle(node.body, state)
6134 ];
6135 },
6136
6137 DoWhileStatement(node, state) {
6138 return [
6139 c('do '),
6140 ...handle(node.body, state),
6141 c(' while ('),
6142 ...handle(node.test, state),
6143 c(');')
6144 ];
6145 },
6146
6147 ForStatement: scoped((node, state) => {
6148 const chunks = [c('for (')];
6149
6150 if (node.init) {
6151 if ((node.init ).type === 'VariableDeclaration') {
6152 chunks.push(...handle_var_declaration(node.init , state));
6153 } else {
6154 chunks.push(...handle(node.init, state));
6155 }
6156 }
6157
6158 chunks.push(c('; '));
6159 if (node.test) chunks.push(...handle(node.test, state));
6160 chunks.push(c('; '));
6161 if (node.update) chunks.push(...handle(node.update, state));
6162
6163 chunks.push(
6164 c(') '),
6165 ...handle(node.body, state)
6166 );
6167
6168 return chunks;
6169 }),
6170
6171 ForInStatement: scoped((node, state) => {
6172 const chunks = [
6173 c(`for ${(node ).await ? 'await ' : ''}(`)
6174 ];
6175
6176 if ((node.left ).type === 'VariableDeclaration') {
6177 chunks.push(...handle_var_declaration(node.left , state));
6178 } else {
6179 chunks.push(...handle(node.left, state));
6180 }
6181
6182 chunks.push(
6183 c(node.type === 'ForInStatement' ? ` in ` : ` of `),
6184 ...handle(node.right, state),
6185 c(') '),
6186 ...handle(node.body, state)
6187 );
6188
6189 return chunks;
6190 }),
6191
6192 DebuggerStatement(node, state) {
6193 return [c('debugger', node), c(';')];
6194 },
6195
6196 FunctionDeclaration: scoped((node, state) => {
6197 const chunks = [];
6198
6199 if (node.async) chunks.push(c('async '));
6200 chunks.push(c(node.generator ? 'function* ' : 'function '));
6201 if (node.id) chunks.push(...handle(node.id, state));
6202 chunks.push(c('('));
6203
6204 const params = node.params.map(p => handle(p, {
6205 ...state,
6206 indent: state.indent + '\t'
6207 }));
6208
6209 const multiple_lines = (
6210 params.some(has_newline) ||
6211 (params.map(get_length).reduce(sum, 0) + (state.indent.length + params.length - 1) * 2) > 80
6212 );
6213
6214 const separator = c(multiple_lines ? `,\n${state.indent}` : ', ');
6215
6216 if (multiple_lines) {
6217 chunks.push(
6218 c(`\n${state.indent}\t`),
6219 ...join(params, separator),
6220 c(`\n${state.indent}`)
6221 );
6222 } else {
6223 chunks.push(
6224 ...join(params, separator)
6225 );
6226 }
6227
6228 chunks.push(
6229 c(') '),
6230 ...handle(node.body, state)
6231 );
6232
6233 return chunks;
6234 }),
6235
6236 VariableDeclaration(node, state) {
6237 return handle_var_declaration(node, state).concat(c(';'));
6238 },
6239
6240 VariableDeclarator(node, state) {
6241 if (node.init) {
6242 return [
6243 ...handle(node.id, state),
6244 c(' = '),
6245 ...handle(node.init, state)
6246 ];
6247 } else {
6248 return handle(node.id, state);
6249 }
6250 },
6251
6252 ClassDeclaration(node, state) {
6253 const chunks = [c('class ')];
6254
6255 if (node.id) chunks.push(...handle(node.id, state), c(' '));
6256
6257 if (node.superClass) {
6258 chunks.push(
6259 c('extends '),
6260 ...handle(node.superClass, state),
6261 c(' ')
6262 );
6263 }
6264
6265 chunks.push(...handle(node.body, state));
6266
6267 return chunks;
6268 },
6269
6270 ImportDeclaration(node, state) {
6271 const chunks = [c('import ')];
6272
6273 const { length } = node.specifiers;
6274 const source = handle(node.source, state);
6275
6276 if (length > 0) {
6277 let i = 0;
6278
6279 while (i < length) {
6280 if (i > 0) {
6281 chunks.push(c(', '));
6282 }
6283
6284 const specifier = node.specifiers[i];
6285
6286 if (specifier.type === 'ImportDefaultSpecifier') {
6287 chunks.push(c(specifier.local.name, specifier));
6288 i += 1;
6289 } else if (specifier.type === 'ImportNamespaceSpecifier') {
6290 chunks.push(c('* as ' + specifier.local.name, specifier));
6291 i += 1;
6292 } else {
6293 break;
6294 }
6295 }
6296
6297 if (i < length) {
6298 // we have named specifiers
6299 const specifiers = node.specifiers.slice(i).map((specifier) => {
6300 const name = handle(specifier.imported, state)[0];
6301 const as = handle(specifier.local, state)[0];
6302
6303 if (name.content === as.content) {
6304 return [as];
6305 }
6306
6307 return [name, c(' as '), as];
6308 });
6309
6310 const width = get_length(chunks) + specifiers.map(get_length).reduce(sum, 0) + (2 * specifiers.length) + 6 + get_length(source);
6311
6312 if (width > 80) {
6313 chunks.push(
6314 c(`{\n\t`),
6315 ...join(specifiers, c(',\n\t')),
6316 c('\n}')
6317 );
6318 } else {
6319 chunks.push(
6320 c(`{ `),
6321 ...join(specifiers, c(', ')),
6322 c(' }')
6323 );
6324 }
6325 }
6326
6327 chunks.push(c(' from '));
6328 }
6329
6330 chunks.push(
6331 ...source,
6332 c(';')
6333 );
6334
6335 return chunks;
6336 },
6337
6338 ImportExpression(node, state) {
6339 return [c('import('), ...handle(node.source, state), c(')')];
6340 },
6341
6342 ExportDefaultDeclaration(node, state) {
6343 const chunks = [
6344 c(`export default `),
6345 ...handle(node.declaration, state)
6346 ];
6347
6348 if (node.declaration.type !== 'FunctionDeclaration') {
6349 chunks.push(c(';'));
6350 }
6351
6352 return chunks;
6353 },
6354
6355 ExportNamedDeclaration(node, state) {
6356 const chunks = [c('export ')];
6357
6358 if (node.declaration) {
6359 chunks.push(...handle(node.declaration, state));
6360 } else {
6361 const specifiers = node.specifiers.map(specifier => {
6362 const name = handle(specifier.local, state)[0];
6363 const as = handle(specifier.exported, state)[0];
6364
6365 if (name.content === as.content) {
6366 return [name];
6367 }
6368
6369 return [name, c(' as '), as];
6370 });
6371
6372 const width = 7 + specifiers.map(get_length).reduce(sum, 0) + 2 * specifiers.length;
6373
6374 if (width > 80) {
6375 chunks.push(
6376 c('{\n\t'),
6377 ...join(specifiers, c(',\n\t')),
6378 c('\n}')
6379 );
6380 } else {
6381 chunks.push(
6382 c('{ '),
6383 ...join(specifiers, c(', ')),
6384 c(' }')
6385 );
6386 }
6387
6388 if (node.source) {
6389 chunks.push(
6390 c(' from '),
6391 ...handle(node.source, state)
6392 );
6393 }
6394 }
6395
6396 chunks.push(c(';'));
6397
6398 return chunks;
6399 },
6400
6401 ExportAllDeclaration(node, state) {
6402 return [
6403 c(`export * from `),
6404 ...handle(node.source, state),
6405 c(`;`)
6406 ];
6407 },
6408
6409 MethodDefinition(node, state) {
6410 const chunks = [];
6411
6412 if (node.static) {
6413 chunks.push(c('static '));
6414 }
6415
6416 if (node.kind === 'get' || node.kind === 'set') {
6417 // Getter or setter
6418 chunks.push(c(node.kind + ' '));
6419 }
6420
6421 if (node.value.async) {
6422 chunks.push(c('async '));
6423 }
6424
6425 if (node.value.generator) {
6426 chunks.push(c('*'));
6427 }
6428
6429 if (node.computed) {
6430 chunks.push(
6431 c('['),
6432 ...handle(node.key, state),
6433 c(']')
6434 );
6435 } else {
6436 chunks.push(...handle(node.key, state));
6437 }
6438
6439 chunks.push(c('('));
6440
6441 const { params } = node.value;
6442 for (let i = 0; i < params.length; i += 1) {
6443 chunks.push(...handle(params[i], state));
6444 if (i < params.length - 1) chunks.push(c(', '));
6445 }
6446
6447 chunks.push(
6448 c(') '),
6449 ...handle(node.value.body, state)
6450 );
6451
6452 return chunks;
6453 },
6454
6455 ArrowFunctionExpression: scoped((node, state) => {
6456 const chunks = [];
6457
6458 if (node.async) chunks.push(c('async '));
6459
6460 if (node.params.length === 1 && node.params[0].type === 'Identifier') {
6461 chunks.push(...handle(node.params[0], state));
6462 } else {
6463 const params = node.params.map(param => handle(param, {
6464 ...state,
6465 indent: state.indent + '\t'
6466 }));
6467
6468 chunks.push(
6469 c('('),
6470 ...join(params, c(', ')),
6471 c(')')
6472 );
6473 }
6474
6475 chunks.push(c(' => '));
6476
6477 if (node.body.type === 'ObjectExpression') {
6478 chunks.push(
6479 c('('),
6480 ...handle(node.body, state),
6481 c(')')
6482 );
6483 } else {
6484 chunks.push(...handle(node.body, state));
6485 }
6486
6487 return chunks;
6488 }),
6489
6490 ThisExpression(node, state) {
6491 return [c('this', node)];
6492 },
6493
6494 Super(node, state) {
6495 return [c('super', node)];
6496 },
6497
6498 RestElement(node, state) {
6499 return [c('...'), ...handle(node.argument, state)];
6500 },
6501
6502 YieldExpression(node, state) {
6503 if (node.argument) {
6504 return [c(node.delegate ? `yield* ` : `yield `), ...handle(node.argument, state)];
6505 }
6506
6507 return [c(node.delegate ? `yield*` : `yield`)];
6508 },
6509
6510 AwaitExpression(node, state) {
6511 if (node.argument) {
6512 const precedence = EXPRESSIONS_PRECEDENCE[node.argument.type];
6513
6514 if (precedence && (precedence < EXPRESSIONS_PRECEDENCE.AwaitExpression)) {
6515 return [c('await ('), ...handle(node.argument, state), c(')')];
6516 } else {
6517 return [c('await '), ...handle(node.argument, state)];
6518 }
6519 }
6520
6521 return [c('await')];
6522 },
6523
6524 TemplateLiteral(node, state) {
6525 const chunks = [c('`')];
6526
6527 const { quasis, expressions } = node;
6528
6529 for (let i = 0; i < expressions.length; i++) {
6530 chunks.push(
6531 c(quasis[i].value.raw),
6532 c('${'),
6533 ...handle(expressions[i], state),
6534 c('}')
6535 );
6536 }
6537
6538 chunks.push(
6539 c(quasis[quasis.length - 1].value.raw),
6540 c('`')
6541 );
6542
6543 return chunks;
6544 },
6545
6546 TaggedTemplateExpression(node, state) {
6547 return handle(node.tag, state).concat(handle(node.quasi, state));
6548 },
6549
6550 ArrayExpression(node, state) {
6551 const chunks = [c('[')];
6552
6553 const elements = [];
6554 let sparse_commas = [];
6555
6556 for (let i = 0; i < node.elements.length; i += 1) {
6557 // can't use map/forEach because of sparse arrays
6558 const element = node.elements[i];
6559 if (element) {
6560 elements.push([...sparse_commas, ...handle(element, {
6561 ...state,
6562 indent: state.indent + '\t'
6563 })]);
6564 sparse_commas = [];
6565 } else {
6566 sparse_commas.push(c(','));
6567 }
6568 }
6569
6570 const multiple_lines = (
6571 elements.some(has_newline) ||
6572 (elements.map(get_length).reduce(sum, 0) + (state.indent.length + elements.length - 1) * 2) > 80
6573 );
6574
6575 if (multiple_lines) {
6576 chunks.push(
6577 c(`\n${state.indent}\t`),
6578 ...join(elements, c(`,\n${state.indent}\t`)),
6579 c(`\n${state.indent}`),
6580 ...sparse_commas
6581 );
6582 } else {
6583 chunks.push(...join(elements, c(', ')), ...sparse_commas);
6584 }
6585
6586 chunks.push(c(']'));
6587
6588 return chunks;
6589 },
6590
6591 ObjectExpression(node, state) {
6592 if (node.properties.length === 0) {
6593 return [c('{}')];
6594 }
6595
6596 let has_inline_comment = false;
6597
6598 const chunks = [];
6599 const separator = c(', ');
6600
6601 node.properties.forEach((p, i) => {
6602 chunks.push(...handle(p, {
6603 ...state,
6604 indent: state.indent + '\t'
6605 }));
6606
6607 if (state.comments.length) {
6608 // TODO generalise this, so it works with ArrayExpressions and other things.
6609 // At present, stuff will just get appended to the closest statement/declaration
6610 chunks.push(c(', '));
6611
6612 while (state.comments.length) {
6613 const comment = state.comments.shift();
6614
6615 chunks.push(c(comment.type === 'Block'
6616 ? `/*${comment.value}*/\n${state.indent}\t`
6617 : `//${comment.value}\n${state.indent}\t`));
6618
6619 if (comment.type === 'Line') {
6620 has_inline_comment = true;
6621 }
6622 }
6623 } else {
6624 if (i < node.properties.length - 1) {
6625 chunks.push(separator);
6626 }
6627 }
6628 });
6629
6630 const multiple_lines = (
6631 has_inline_comment ||
6632 has_newline(chunks) ||
6633 get_length(chunks) > 40
6634 );
6635
6636 if (multiple_lines) {
6637 separator.content = `,\n${state.indent}\t`;
6638 }
6639
6640 return [
6641 c(multiple_lines ? `{\n${state.indent}\t` : `{ `),
6642 ...chunks,
6643 c(multiple_lines ? `\n${state.indent}}` : ` }`)
6644 ];
6645 },
6646
6647 Property(node, state) {
6648 const value = handle(node.value, state);
6649
6650 if (node.key === node.value) {
6651 return value;
6652 }
6653
6654 // special case
6655 if (
6656 !node.computed &&
6657 node.value.type === 'AssignmentPattern' &&
6658 node.value.left.type === 'Identifier' &&
6659 node.value.left.name === (node.key ).name
6660 ) {
6661 return value;
6662 }
6663
6664 if (node.value.type === 'Identifier' && (
6665 (node.key.type === 'Identifier' && node.key.name === value[0].content) ||
6666 (node.key.type === 'Literal' && node.key.value === value[0].content)
6667 )) {
6668 return value;
6669 }
6670
6671 const key = handle(node.key, state);
6672
6673 if (node.value.type === 'FunctionExpression' && !node.value.id) {
6674 state = {
6675 ...state,
6676 scope: state.scope_map.get(node.value)
6677 };
6678
6679 const chunks = node.kind !== 'init'
6680 ? [c(`${node.kind} `)]
6681 : [];
6682
6683 if (node.value.async) {
6684 chunks.push(c('async '));
6685 }
6686 if (node.value.generator) {
6687 chunks.push(c('*'));
6688 }
6689
6690 chunks.push(
6691 ...(node.computed ? [c('['), ...key, c(']')] : key),
6692 c('('),
6693 ...join((node.value ).params.map(param => handle(param, state)), c(', ')),
6694 c(') '),
6695 ...handle((node.value ).body, state)
6696 );
6697
6698 return chunks;
6699 }
6700
6701 if (node.computed) {
6702 return [
6703 c('['),
6704 ...key,
6705 c(']: '),
6706 ...value
6707 ];
6708 }
6709
6710 return [
6711 ...key,
6712 c(': '),
6713 ...value
6714 ];
6715 },
6716
6717 ObjectPattern(node, state) {
6718 const chunks = [c('{ ')];
6719
6720 for (let i = 0; i < node.properties.length; i += 1) {
6721 chunks.push(...handle(node.properties[i], state));
6722 if (i < node.properties.length - 1) chunks.push(c(', '));
6723 }
6724
6725 chunks.push(c(' }'));
6726
6727 return chunks;
6728 },
6729
6730 SequenceExpression(node, state) {
6731 const expressions = node.expressions.map(e => handle(e, state));
6732
6733 return [
6734 c('('),
6735 ...join(expressions, c(', ')),
6736 c(')')
6737 ];
6738 },
6739
6740 UnaryExpression(node, state) {
6741 const chunks = [c(node.operator)];
6742
6743 if (node.operator.length > 1) {
6744 chunks.push(c(' '));
6745 }
6746
6747 if (
6748 EXPRESSIONS_PRECEDENCE[node.argument.type] <
6749 EXPRESSIONS_PRECEDENCE.UnaryExpression
6750 ) {
6751 chunks.push(
6752 c('('),
6753 ...handle(node.argument, state),
6754 c(')')
6755 );
6756 } else {
6757 chunks.push(...handle(node.argument, state));
6758 }
6759
6760 return chunks;
6761 },
6762
6763 UpdateExpression(node, state) {
6764 return node.prefix
6765 ? [c(node.operator), ...handle(node.argument, state)]
6766 : [...handle(node.argument, state), c(node.operator)];
6767 },
6768
6769 AssignmentExpression(node, state) {
6770 return [
6771 ...handle(node.left, state),
6772 c(` ${node.operator || '='} `),
6773 ...handle(node.right, state)
6774 ];
6775 },
6776
6777 BinaryExpression(node, state) {
6778 const chunks = [];
6779
6780 // TODO
6781 // const is_in = node.operator === 'in';
6782 // if (is_in) {
6783 // // Avoids confusion in `for` loops initializers
6784 // chunks.push(c('('));
6785 // }
6786
6787 if (needs_parens(node.left, node, false)) {
6788 chunks.push(
6789 c('('),
6790 ...handle(node.left, state),
6791 c(')')
6792 );
6793 } else {
6794 chunks.push(...handle(node.left, state));
6795 }
6796
6797 chunks.push(c(` ${node.operator} `));
6798
6799 if (needs_parens(node.right, node, true)) {
6800 chunks.push(
6801 c('('),
6802 ...handle(node.right, state),
6803 c(')')
6804 );
6805 } else {
6806 chunks.push(...handle(node.right, state));
6807 }
6808
6809 return chunks;
6810 },
6811
6812 ConditionalExpression(node, state) {
6813 const chunks = [];
6814
6815 if (
6816 EXPRESSIONS_PRECEDENCE[node.test.type] >
6817 EXPRESSIONS_PRECEDENCE.ConditionalExpression
6818 ) {
6819 chunks.push(...handle(node.test, state));
6820 } else {
6821 chunks.push(
6822 c('('),
6823 ...handle(node.test, state),
6824 c(')')
6825 );
6826 }
6827
6828 const child_state = { ...state, indent: state.indent + '\t' };
6829
6830 const consequent = handle(node.consequent, child_state);
6831 const alternate = handle(node.alternate, child_state);
6832
6833 const multiple_lines = (
6834 has_newline(consequent) || has_newline(alternate) ||
6835 get_length(chunks) + get_length(consequent) + get_length(alternate) > 50
6836 );
6837
6838 if (multiple_lines) {
6839 chunks.push(
6840 c(`\n${state.indent}? `),
6841 ...consequent,
6842 c(`\n${state.indent}: `),
6843 ...alternate
6844 );
6845 } else {
6846 chunks.push(
6847 c(` ? `),
6848 ...consequent,
6849 c(` : `),
6850 ...alternate
6851 );
6852 }
6853
6854 return chunks;
6855 },
6856
6857 NewExpression(node, state) {
6858 const chunks = [c('new ')];
6859
6860 if (
6861 EXPRESSIONS_PRECEDENCE[node.callee.type] <
6862 EXPRESSIONS_PRECEDENCE.CallExpression || has_call_expression(node.callee)
6863 ) {
6864 chunks.push(
6865 c('('),
6866 ...handle(node.callee, state),
6867 c(')')
6868 );
6869 } else {
6870 chunks.push(...handle(node.callee, state));
6871 }
6872
6873 // TODO this is copied from CallExpression — DRY it out
6874 const args = node.arguments.map(arg => handle(arg, {
6875 ...state,
6876 indent: state.indent + '\t'
6877 }));
6878
6879 const separator = args.some(has_newline) // TODO or length exceeds 80
6880 ? c(',\n' + state.indent)
6881 : c(', ');
6882
6883 chunks.push(
6884 c('('),
6885 ...join(args, separator) ,
6886 c(')')
6887 );
6888
6889 return chunks;
6890 },
6891
6892 ChainExpression(node, state) {
6893 return handle(node.expression, state);
6894 },
6895
6896 CallExpression(node, state) {
6897 const chunks = [];
6898
6899 if (
6900 EXPRESSIONS_PRECEDENCE[node.callee.type] <
6901 EXPRESSIONS_PRECEDENCE.CallExpression
6902 ) {
6903 chunks.push(
6904 c('('),
6905 ...handle(node.callee, state),
6906 c(')')
6907 );
6908 } else {
6909 chunks.push(...handle(node.callee, state));
6910 }
6911
6912 if ((node ).optional) {
6913 chunks.push(c('?.'));
6914 }
6915
6916 const args = node.arguments.map(arg => handle(arg, state));
6917
6918 const multiple_lines = args.slice(0, -1).some(has_newline); // TODO or length exceeds 80
6919
6920 if (multiple_lines) {
6921 // need to handle args again. TODO find alternative approach?
6922 const args = node.arguments.map(arg => handle(arg, {
6923 ...state,
6924 indent: `${state.indent}\t`
6925 }));
6926
6927 chunks.push(
6928 c(`(\n${state.indent}\t`),
6929 ...join(args, c(`,\n${state.indent}\t`)),
6930 c(`\n${state.indent})`)
6931 );
6932 } else {
6933 chunks.push(
6934 c('('),
6935 ...join(args, c(', ')),
6936 c(')')
6937 );
6938 }
6939
6940 return chunks;
6941 },
6942
6943 MemberExpression(node, state) {
6944 const chunks = [];
6945
6946 if (EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression) {
6947 chunks.push(
6948 c('('),
6949 ...handle(node.object, state),
6950 c(')')
6951 );
6952 } else {
6953 chunks.push(...handle(node.object, state));
6954 }
6955
6956 if (node.computed) {
6957 if (node.optional) {
6958 chunks.push(c('?.'));
6959 }
6960 chunks.push(
6961 c('['),
6962 ...handle(node.property, state),
6963 c(']')
6964 );
6965 } else {
6966 chunks.push(
6967 c(node.optional ? '?.' : '.'),
6968 ...handle(node.property, state)
6969 );
6970 }
6971
6972 return chunks;
6973 },
6974
6975 MetaProperty(node, state) {
6976 return [...handle(node.meta, state), c('.'), ...handle(node.property, state)];
6977 },
6978
6979 Identifier(node, state) {
6980 let name = node.name;
6981
6982 if (name[0] === '@') {
6983 name = state.getName(name.slice(1));
6984 } else if (node.name[0] === '#') {
6985 const owner = state.scope.find_owner(node.name);
6986
6987 if (!owner) {
6988 throw new Error(`Could not find owner for node`);
6989 }
6990
6991 if (!state.deconflicted.has(owner)) {
6992 state.deconflicted.set(owner, new Map());
6993 }
6994
6995 const deconflict_map = state.deconflicted.get(owner);
6996
6997 if (!deconflict_map.has(node.name)) {
6998 deconflict_map.set(node.name, deconflict(node.name.slice(1), owner.references));
6999 }
7000
7001 name = deconflict_map.get(node.name);
7002 }
7003
7004 return [c(name, node)];
7005 },
7006
7007 Literal(node, state) {
7008 if (typeof node.value === 'string') {
7009 return [
7010 // TODO do we need to handle weird unicode characters somehow?
7011 // str.replace(/\\u(\d{4})/g, (m, n) => String.fromCharCode(+n))
7012 c(JSON.stringify(node.value).replace(re, (_m, _i, at, hash, name) => {
7013 if (at) return '@' + name;
7014 if (hash) return '#' + name;
7015 throw new Error(`this shouldn't happen`);
7016 }), node)
7017 ];
7018 }
7019
7020 const { regex } = node ; // TODO is this right?
7021 if (regex) {
7022 return [c(`/${regex.pattern}/${regex.flags}`, node)];
7023 }
7024
7025 return [c(String(node.value), node)];
7026 }
7027};
7028
7029handlers.ForOfStatement = handlers.ForInStatement;
7030handlers.FunctionExpression = handlers.FunctionDeclaration;
7031handlers.ClassExpression = handlers.ClassDeclaration;
7032handlers.ClassBody = handlers.BlockStatement;
7033handlers.SpreadElement = handlers.RestElement;
7034handlers.ArrayPattern = handlers.ArrayExpression;
7035handlers.LogicalExpression = handlers.BinaryExpression;
7036handlers.AssignmentPattern = handlers.AssignmentExpression;
7037
7038let btoa$1 = () => {
7039 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
7040};
7041if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
7042 btoa$1 = (str) => window.btoa(unescape(encodeURIComponent(str)));
7043} else if (typeof Buffer === 'function') {
7044 btoa$1 = (str) => Buffer.from(str, 'utf-8').toString('base64');
7045}
7046
7047
7048
7049
7050
7051
7052
7053
7054function print(node, opts = {}) {
7055 if (Array.isArray(node)) {
7056 return print({
7057 type: 'Program',
7058 body: node
7059 } , opts);
7060 }
7061
7062 const {
7063 getName = (x) => {
7064 throw new Error(`Unhandled sigil @${x}`);
7065 }
7066 } = opts;
7067
7068 let { map: scope_map, scope } = analyze(node);
7069 const deconflicted = new WeakMap();
7070
7071 const chunks = handle(node, {
7072 indent: '',
7073 getName,
7074 scope,
7075 scope_map,
7076 deconflicted,
7077 comments: []
7078 });
7079
7080
7081
7082 let code = '';
7083 let mappings = [];
7084 let current_line = [];
7085 let current_column = 0;
7086
7087 for (let i = 0; i < chunks.length; i += 1) {
7088 const chunk = chunks[i];
7089
7090 code += chunk.content;
7091
7092 if (chunk.loc) {
7093 current_line.push([
7094 current_column,
7095 0, // source index is always zero
7096 chunk.loc.start.line - 1,
7097 chunk.loc.start.column,
7098 ]);
7099 }
7100
7101 for (let i = 0; i < chunk.content.length; i += 1) {
7102 if (chunk.content[i] === '\n') {
7103 mappings.push(current_line);
7104 current_line = [];
7105 current_column = 0;
7106 } else {
7107 current_column += 1;
7108 }
7109 }
7110
7111 if (chunk.loc) {
7112 current_line.push([
7113 current_column,
7114 0, // source index is always zero
7115 chunk.loc.end.line - 1,
7116 chunk.loc.end.column,
7117 ]);
7118 }
7119 }
7120
7121 mappings.push(current_line);
7122
7123 const map = {
7124 version: 3,
7125 names: [] ,
7126 sources: [opts.sourceMapSource || null],
7127 sourcesContent: [opts.sourceMapContent || null],
7128 mappings: encode(mappings)
7129 };
7130
7131 Object.defineProperties(map, {
7132 toString: {
7133 enumerable: false,
7134 value: function toString() {
7135 return JSON.stringify(this);
7136 }
7137 },
7138 toUrl: {
7139 enumerable: false,
7140 value: function toUrl() {
7141 return 'data:application/json;charset=utf-8;base64,' + btoa$1(this.toString());
7142 }
7143 }
7144 });
7145
7146 return {
7147 code,
7148 map
7149 };
7150}
7151
7152const sigils = {
7153 '@': 'AT',
7154 '#': 'HASH'
7155};
7156
7157const join$1 = (strings) => {
7158 let str = strings[0];
7159 for (let i = 1; i < strings.length; i += 1) {
7160 str += `_${id}_${i - 1}_${strings[i]}`;
7161 }
7162 return str.replace(/([@#])(\w+)/g, (_m, sigil, name) => `_${id}_${sigils[sigil]}_${name}`);
7163};
7164
7165const flatten_body = (array, target) => {
7166 for (let i = 0; i < array.length; i += 1) {
7167 const statement = array[i];
7168 if (Array.isArray(statement)) {
7169 flatten_body(statement, target);
7170 continue;
7171 }
7172
7173 if (statement.type === 'ExpressionStatement') {
7174 if (statement.expression === EMPTY) continue;
7175
7176 if (Array.isArray(statement.expression)) {
7177 // TODO this is hacktacular
7178 let node = statement.expression[0];
7179 while (Array.isArray(node)) node = node[0];
7180 if (node) node.leadingComments = statement.leadingComments;
7181
7182 flatten_body(statement.expression, target);
7183 continue;
7184 }
7185
7186 if (/(Expression|Literal)$/.test(statement.expression.type)) {
7187 target.push(statement);
7188 continue;
7189 }
7190
7191 if (statement.leadingComments) statement.expression.leadingComments = statement.leadingComments;
7192 if (statement.trailingComments) statement.expression.trailingComments = statement.trailingComments;
7193
7194 target.push(statement.expression);
7195 continue;
7196 }
7197
7198 target.push(statement);
7199 }
7200
7201 return target;
7202};
7203
7204const flatten_properties = (array, target) => {
7205 for (let i = 0; i < array.length; i += 1) {
7206 const property = array[i];
7207
7208 if (property.value === EMPTY) continue;
7209
7210 if (property.key === property.value && Array.isArray(property.key)) {
7211 flatten_properties(property.key, target);
7212 continue;
7213 }
7214
7215 target.push(property);
7216 }
7217
7218 return target;
7219};
7220
7221const flatten = (nodes, target) => {
7222 for (let i = 0; i < nodes.length; i += 1) {
7223 const node = nodes[i];
7224
7225 if (node === EMPTY) continue;
7226
7227 if (Array.isArray(node)) {
7228 flatten(node, target);
7229 continue;
7230 }
7231
7232 target.push(node);
7233 }
7234
7235 return target;
7236};
7237
7238const EMPTY = { type: 'Empty' };
7239
7240const acorn_opts = (comments, raw) => {
7241 const { onComment } = get_comment_handlers(comments, raw);
7242 return {
7243 ecmaVersion: 2020,
7244 sourceType: 'module',
7245 allowAwaitOutsideFunction: true,
7246 allowImportExportEverywhere: true,
7247 allowReturnOutsideFunction: true,
7248 onComment
7249 } ;
7250};
7251
7252const inject = (raw, node, values, comments) => {
7253 comments.forEach(comment => {
7254 comment.value = comment.value.replace(re, (m, i) => +i in values ? values[+i] : m);
7255 });
7256
7257 const { enter, leave } = get_comment_handlers(comments, raw);
7258
7259 walk(node, {
7260 enter,
7261
7262 leave(node, parent, key, index) {
7263 if (node.type === 'Identifier') {
7264 re.lastIndex = 0;
7265 const match = re.exec(node.name);
7266
7267 if (match) {
7268 if (match[1]) {
7269 if (+match[1] in values) {
7270 let value = values[+match[1]];
7271
7272 if (typeof value === 'string') {
7273 value = { type: 'Identifier', name: value, leadingComments: node.leadingComments, trailingComments: node.trailingComments };
7274 } else if (typeof value === 'number') {
7275 value = { type: 'Literal', value, leadingComments: node.leadingComments, trailingComments: node.trailingComments };
7276 }
7277
7278 this.replace(value || EMPTY);
7279 }
7280 } else {
7281 node.name = `${match[2] ? `@` : `#`}${match[4]}`;
7282 }
7283 }
7284 }
7285
7286 if (node.type === 'Literal') {
7287 if (typeof node.value === 'string') {
7288 re.lastIndex = 0;
7289 node.value = node.value.replace(re, (m, i) => +i in values ? values[+i] : m);
7290 }
7291 }
7292
7293 if (node.type === 'TemplateElement') {
7294 re.lastIndex = 0;
7295 node.value.raw = (node.value.raw ).replace(re, (m, i) => +i in values ? values[+i] : m);
7296 }
7297
7298 if (node.type === 'Program' || node.type === 'BlockStatement') {
7299 node.body = flatten_body(node.body, []);
7300 }
7301
7302 if (node.type === 'ObjectExpression' || node.type === 'ObjectPattern') {
7303 node.properties = flatten_properties(node.properties, []);
7304 }
7305
7306 if (node.type === 'ArrayExpression' || node.type === 'ArrayPattern') {
7307 node.elements = flatten(node.elements, []);
7308 }
7309
7310 if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') {
7311 node.params = flatten(node.params, []);
7312 }
7313
7314 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
7315 node.arguments = flatten(node.arguments, []);
7316 }
7317
7318 if (node.type === 'ImportDeclaration' || node.type === 'ExportNamedDeclaration') {
7319 node.specifiers = flatten(node.specifiers, []);
7320 }
7321
7322 if (node.type === 'ForStatement') {
7323 node.init = node.init === EMPTY ? null : node.init;
7324 node.test = node.test === EMPTY ? null : node.test;
7325 node.update = node.update === EMPTY ? null : node.update;
7326 }
7327
7328 leave(node);
7329 }
7330 });
7331};
7332
7333function b(strings, ...values) {
7334 const str = join$1(strings);
7335 const comments = [];
7336
7337 try {
7338 const ast = parse(str, acorn_opts(comments, str));
7339
7340 inject(str, ast, values, comments);
7341
7342 return ast.body;
7343 } catch (err) {
7344 handle_error(str, err);
7345 }
7346}
7347
7348function x(strings, ...values) {
7349 const str = join$1(strings);
7350 const comments = [];
7351
7352 try {
7353 const expression = parseExpressionAt(str, 0, acorn_opts(comments, str)) ;
7354 const match = /\S+/.exec(str.slice((expression ).end));
7355 if (match) {
7356 throw new Error(`Unexpected token '${match[0]}'`);
7357 }
7358
7359 inject(str, expression, values, comments);
7360
7361 return expression;
7362 } catch (err) {
7363 handle_error(str, err);
7364 }
7365}
7366
7367function p(strings, ...values) {
7368 const str = `{${join$1(strings)}}`;
7369 const comments = [];
7370
7371 try {
7372 const expression = parseExpressionAt(str, 0, acorn_opts(comments, str)) ;
7373
7374 inject(str, expression, values, comments);
7375
7376 return expression.properties[0];
7377 } catch (err) {
7378 handle_error(str, err);
7379 }
7380}
7381
7382function handle_error(str, err) {
7383 // TODO location/code frame
7384
7385 re.lastIndex = 0;
7386
7387 str = str.replace(re, (m, i, at, hash, name) => {
7388 if (at) return `@${name}`;
7389 if (hash) return `#${name}`;
7390
7391 return '${...}';
7392 });
7393
7394 console.log(`failed to parse:\n${str}`);
7395 throw err;
7396}
7397
7398const parse$1 = (source, opts) => {
7399 const comments = [];
7400 const { onComment, enter, leave } = get_comment_handlers(comments, source);
7401 const ast = parse(source, { onComment, ...opts });
7402 walk(ast , { enter, leave });
7403 return ast;
7404};
7405
7406const parseExpressionAt$1 = (source, index, opts) => {
7407 const comments = [];
7408 const { onComment, enter, leave } = get_comment_handlers(comments, source);
7409 const ast = parseExpressionAt(source, index, { onComment, ...opts });
7410 walk(ast , { enter, leave });
7411 return ast;
7412};
7413
7414const parse$2 = (source) => parse$1(source, {
7415 sourceType: 'module',
7416 ecmaVersion: 12,
7417 locations: true
7418});
7419const parse_expression_at = (source, index) => parseExpressionAt$1(source, index, {
7420 sourceType: 'module',
7421 ecmaVersion: 12,
7422 locations: true
7423});
7424
7425const whitespace = /[ \t\r\n]/;
7426const dimensions = /^(?:offset|client)(?:Width|Height)$/;
7427
7428function read_expression(parser) {
7429 try {
7430 const node = parse_expression_at(parser.template, parser.index);
7431 let num_parens = 0;
7432 for (let i = parser.index; i < node.start; i += 1) {
7433 if (parser.template[i] === '(')
7434 num_parens += 1;
7435 }
7436 let index = node.end;
7437 while (num_parens > 0) {
7438 const char = parser.template[index];
7439 if (char === ')') {
7440 num_parens -= 1;
7441 }
7442 else if (!whitespace.test(char)) {
7443 parser.error({
7444 code: 'unexpected-token',
7445 message: 'Expected )'
7446 }, index);
7447 }
7448 index += 1;
7449 }
7450 parser.index = index;
7451 return node;
7452 }
7453 catch (err) {
7454 parser.acorn_error(err);
7455 }
7456}
7457
7458const script_closing_tag = '</script>';
7459function get_context(parser, attributes, start) {
7460 const context = attributes.find(attribute => attribute.name === 'context');
7461 if (!context)
7462 return 'default';
7463 if (context.value.length !== 1 || context.value[0].type !== 'Text') {
7464 parser.error({
7465 code: 'invalid-script',
7466 message: 'context attribute must be static'
7467 }, start);
7468 }
7469 const value = context.value[0].data;
7470 if (value !== 'module') {
7471 parser.error({
7472 code: 'invalid-script',
7473 message: 'If the context attribute is supplied, its value must be "module"'
7474 }, context.start);
7475 }
7476 return value;
7477}
7478function read_script(parser, start, attributes) {
7479 const script_start = parser.index;
7480 const script_end = parser.template.indexOf(script_closing_tag, script_start);
7481 if (script_end === -1) {
7482 parser.error({
7483 code: 'unclosed-script',
7484 message: '<script> must have a closing tag'
7485 });
7486 }
7487 const source = parser.template.slice(0, script_start).replace(/[^\n]/g, ' ') +
7488 parser.template.slice(script_start, script_end);
7489 parser.index = script_end + script_closing_tag.length;
7490 let ast;
7491 try {
7492 ast = parse$2(source);
7493 }
7494 catch (err) {
7495 parser.acorn_error(err);
7496 }
7497 // TODO is this necessary?
7498 ast.start = script_start;
7499 return {
7500 type: 'Script',
7501 start,
7502 end: parser.index,
7503 context: get_context(parser, attributes, start),
7504 content: ast
7505 };
7506}
7507
7508var MAX_LINE_LENGTH = 100;
7509var OFFSET_CORRECTION = 60;
7510var TAB_REPLACEMENT = ' ';
7511
7512function sourceFragment(error, extraLines) {
7513 function processLines(start, end) {
7514 return lines.slice(start, end).map(function(line, idx) {
7515 var num = String(start + idx + 1);
7516
7517 while (num.length < maxNumLength) {
7518 num = ' ' + num;
7519 }
7520
7521 return num + ' |' + line;
7522 }).join('\n');
7523 }
7524
7525 var lines = error.source.split(/\n|\r\n?|\f/);
7526 var line = error.line;
7527 var column = error.column;
7528 var startLine = Math.max(1, line - extraLines) - 1;
7529 var endLine = Math.min(line + extraLines, lines.length + 1);
7530 var maxNumLength = Math.max(4, String(endLine).length) + 1;
7531 var cutLeft = 0;
7532
7533 // correct column according to replaced tab before column
7534 column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;
7535
7536 if (column > MAX_LINE_LENGTH) {
7537 cutLeft = column - OFFSET_CORRECTION + 3;
7538 column = OFFSET_CORRECTION - 2;
7539 }
7540
7541 for (var i = startLine; i <= endLine; i++) {
7542 if (i >= 0 && i < lines.length) {
7543 lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT);
7544 lines[i] =
7545 (cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
7546 lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
7547 (lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
7548 }
7549 }
7550
7551 return [
7552 processLines(startLine, line),
7553 new Array(column + maxNumLength + 2).join('-') + '^',
7554 processLines(line, endLine)
7555 ].join('\n');
7556}
7557
7558var CssSyntaxError = function(message, source, offset, line, column) {
7559 // some VMs prevent setting line/column otherwise (iOS Safari 10 even throw an exception)
7560 var error = Object.create(SyntaxError.prototype);
7561
7562 error.name = 'CssSyntaxError';
7563 error.message = message;
7564 error.stack = (new Error().stack || '').replace(/^.+\n/, error.name + ': ' + error.message + '\n');
7565 error.source = source;
7566 error.offset = offset;
7567 error.line = line;
7568 error.column = column;
7569
7570 error.sourceFragment = function(extraLines) {
7571 return sourceFragment(error, isNaN(extraLines) ? 0 : extraLines);
7572 };
7573 Object.defineProperty(error, 'formattedMessage', {
7574 get: function() {
7575 return (
7576 'Parse error: ' + error.message + '\n' +
7577 sourceFragment(error, 2)
7578 );
7579 }
7580 });
7581
7582 // for backward capability
7583 error.parseError = {
7584 offset: offset,
7585 line: line,
7586 column: column
7587 };
7588
7589 return error;
7590};
7591
7592var error = CssSyntaxError;
7593
7594// token types (note: value shouldn't intersect with used char codes)
7595var WHITESPACE = 1;
7596var IDENTIFIER = 2;
7597var NUMBER = 3;
7598var STRING = 4;
7599var COMMENT = 5;
7600var PUNCTUATOR = 6;
7601var CDO = 7;
7602var CDC = 8;
7603var ATRULE = 14;
7604var FUNCTION = 15;
7605var URL$1 = 16;
7606var RAW = 17;
7607
7608var TAB = 9;
7609var N = 10;
7610var F = 12;
7611var R = 13;
7612var SPACE = 32;
7613
7614var TYPE = {
7615 WhiteSpace: WHITESPACE,
7616 Identifier: IDENTIFIER,
7617 Number: NUMBER,
7618 String: STRING,
7619 Comment: COMMENT,
7620 Punctuator: PUNCTUATOR,
7621 CDO: CDO,
7622 CDC: CDC,
7623 Atrule: ATRULE,
7624 Function: FUNCTION,
7625 Url: URL$1,
7626 Raw: RAW,
7627
7628 ExclamationMark: 33, // !
7629 QuotationMark: 34, // "
7630 NumberSign: 35, // #
7631 DollarSign: 36, // $
7632 PercentSign: 37, // %
7633 Ampersand: 38, // &
7634 Apostrophe: 39, // '
7635 LeftParenthesis: 40, // (
7636 RightParenthesis: 41, // )
7637 Asterisk: 42, // *
7638 PlusSign: 43, // +
7639 Comma: 44, // ,
7640 HyphenMinus: 45, // -
7641 FullStop: 46, // .
7642 Solidus: 47, // /
7643 Colon: 58, // :
7644 Semicolon: 59, // ;
7645 LessThanSign: 60, // <
7646 EqualsSign: 61, // =
7647 GreaterThanSign: 62, // >
7648 QuestionMark: 63, // ?
7649 CommercialAt: 64, // @
7650 LeftSquareBracket: 91, // [
7651 Backslash: 92, // \
7652 RightSquareBracket: 93, // ]
7653 CircumflexAccent: 94, // ^
7654 LowLine: 95, // _
7655 GraveAccent: 96, // `
7656 LeftCurlyBracket: 123, // {
7657 VerticalLine: 124, // |
7658 RightCurlyBracket: 125, // }
7659 Tilde: 126 // ~
7660};
7661
7662var NAME = Object.keys(TYPE).reduce(function(result, key) {
7663 result[TYPE[key]] = key;
7664 return result;
7665}, {});
7666
7667// https://drafts.csswg.org/css-syntax/#tokenizer-definitions
7668// > non-ASCII code point
7669// > A code point with a value equal to or greater than U+0080 <control>
7670// > name-start code point
7671// > A letter, a non-ASCII code point, or U+005F LOW LINE (_).
7672// > name code point
7673// > A name-start code point, a digit, or U+002D HYPHEN-MINUS (-)
7674// That means only ASCII code points has a special meaning and we a maps for 0..127 codes only
7675var SafeUint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
7676var SYMBOL_TYPE = new SafeUint32Array(0x80);
7677var PUNCTUATION = new SafeUint32Array(0x80);
7678var STOP_URL_RAW = new SafeUint32Array(0x80);
7679
7680for (var i$1 = 0; i$1 < SYMBOL_TYPE.length; i$1++) {
7681 SYMBOL_TYPE[i$1] = IDENTIFIER;
7682}
7683
7684// fill categories
7685[
7686 TYPE.ExclamationMark, // !
7687 TYPE.QuotationMark, // "
7688 TYPE.NumberSign, // #
7689 TYPE.DollarSign, // $
7690 TYPE.PercentSign, // %
7691 TYPE.Ampersand, // &
7692 TYPE.Apostrophe, // '
7693 TYPE.LeftParenthesis, // (
7694 TYPE.RightParenthesis, // )
7695 TYPE.Asterisk, // *
7696 TYPE.PlusSign, // +
7697 TYPE.Comma, // ,
7698 TYPE.HyphenMinus, // -
7699 TYPE.FullStop, // .
7700 TYPE.Solidus, // /
7701 TYPE.Colon, // :
7702 TYPE.Semicolon, // ;
7703 TYPE.LessThanSign, // <
7704 TYPE.EqualsSign, // =
7705 TYPE.GreaterThanSign, // >
7706 TYPE.QuestionMark, // ?
7707 TYPE.CommercialAt, // @
7708 TYPE.LeftSquareBracket, // [
7709 // TYPE.Backslash, // \
7710 TYPE.RightSquareBracket, // ]
7711 TYPE.CircumflexAccent, // ^
7712 // TYPE.LowLine, // _
7713 TYPE.GraveAccent, // `
7714 TYPE.LeftCurlyBracket, // {
7715 TYPE.VerticalLine, // |
7716 TYPE.RightCurlyBracket, // }
7717 TYPE.Tilde // ~
7718].forEach(function(key) {
7719 SYMBOL_TYPE[Number(key)] = PUNCTUATOR;
7720 PUNCTUATION[Number(key)] = PUNCTUATOR;
7721});
7722
7723for (var i$1 = 48; i$1 <= 57; i$1++) {
7724 SYMBOL_TYPE[i$1] = NUMBER;
7725}
7726
7727SYMBOL_TYPE[SPACE] = WHITESPACE;
7728SYMBOL_TYPE[TAB] = WHITESPACE;
7729SYMBOL_TYPE[N] = WHITESPACE;
7730SYMBOL_TYPE[R] = WHITESPACE;
7731SYMBOL_TYPE[F] = WHITESPACE;
7732
7733SYMBOL_TYPE[TYPE.Apostrophe] = STRING;
7734SYMBOL_TYPE[TYPE.QuotationMark] = STRING;
7735
7736STOP_URL_RAW[SPACE] = 1;
7737STOP_URL_RAW[TAB] = 1;
7738STOP_URL_RAW[N] = 1;
7739STOP_URL_RAW[R] = 1;
7740STOP_URL_RAW[F] = 1;
7741STOP_URL_RAW[TYPE.Apostrophe] = 1;
7742STOP_URL_RAW[TYPE.QuotationMark] = 1;
7743STOP_URL_RAW[TYPE.LeftParenthesis] = 1;
7744STOP_URL_RAW[TYPE.RightParenthesis] = 1;
7745
7746// whitespace is punctuation ...
7747PUNCTUATION[SPACE] = PUNCTUATOR;
7748PUNCTUATION[TAB] = PUNCTUATOR;
7749PUNCTUATION[N] = PUNCTUATOR;
7750PUNCTUATION[R] = PUNCTUATOR;
7751PUNCTUATION[F] = PUNCTUATOR;
7752// ... hyper minus is not
7753PUNCTUATION[TYPE.HyphenMinus] = 0;
7754
7755var _const = {
7756 TYPE: TYPE,
7757 NAME: NAME,
7758
7759 SYMBOL_TYPE: SYMBOL_TYPE,
7760 PUNCTUATION: PUNCTUATION,
7761 STOP_URL_RAW: STOP_URL_RAW
7762};
7763
7764var PUNCTUATION$1 = _const.PUNCTUATION;
7765var STOP_URL_RAW$1 = _const.STOP_URL_RAW;
7766var TYPE$1 = _const.TYPE;
7767var FULLSTOP = TYPE$1.FullStop;
7768var PLUSSIGN = TYPE$1.PlusSign;
7769var HYPHENMINUS = TYPE$1.HyphenMinus;
7770var PUNCTUATOR$1 = TYPE$1.Punctuator;
7771var TAB$1 = 9;
7772var N$1 = 10;
7773var F$1 = 12;
7774var R$1 = 13;
7775var SPACE$1 = 32;
7776var BACK_SLASH = 92;
7777var E = 101; // 'e'.charCodeAt(0)
7778
7779function firstCharOffset(source) {
7780 // detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
7781 if (source.charCodeAt(0) === 0xFEFF || // UTF-16BE
7782 source.charCodeAt(0) === 0xFFFE) { // UTF-16LE
7783 return 1;
7784 }
7785
7786 return 0;
7787}
7788
7789function isHex(code) {
7790 return (code >= 48 && code <= 57) || // 0 .. 9
7791 (code >= 65 && code <= 70) || // A .. F
7792 (code >= 97 && code <= 102); // a .. f
7793}
7794
7795function isNumber(code) {
7796 return code >= 48 && code <= 57;
7797}
7798
7799function isNewline(source, offset, code) {
7800 if (code === N$1 || code === F$1 || code === R$1) {
7801 if (code === R$1 && offset + 1 < source.length && source.charCodeAt(offset + 1) === N$1) {
7802 return 2;
7803 }
7804
7805 return 1;
7806 }
7807
7808 return 0;
7809}
7810
7811function cmpChar(testStr, offset, referenceCode) {
7812 var code = testStr.charCodeAt(offset);
7813
7814 // code.toLowerCase()
7815 if (code >= 65 && code <= 90) {
7816 code = code | 32;
7817 }
7818
7819 return code === referenceCode;
7820}
7821
7822function cmpStr(testStr, start, end, referenceStr) {
7823 if (end - start !== referenceStr.length) {
7824 return false;
7825 }
7826
7827 if (start < 0 || end > testStr.length) {
7828 return false;
7829 }
7830
7831 for (var i = start; i < end; i++) {
7832 var testCode = testStr.charCodeAt(i);
7833 var refCode = referenceStr.charCodeAt(i - start);
7834
7835 // testStr[i].toLowerCase()
7836 if (testCode >= 65 && testCode <= 90) {
7837 testCode = testCode | 32;
7838 }
7839
7840 if (testCode !== refCode) {
7841 return false;
7842 }
7843 }
7844
7845 return true;
7846}
7847
7848function endsWith(testStr, referenceStr) {
7849 return cmpStr(testStr, testStr.length - referenceStr.length, testStr.length, referenceStr);
7850}
7851
7852function findLastNonSpaceLocation(scanner) {
7853 for (var i = scanner.source.length - 1; i >= 0; i--) {
7854 var code = scanner.source.charCodeAt(i);
7855
7856 if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
7857 break;
7858 }
7859 }
7860
7861 return scanner.getLocation(i + 1);
7862}
7863
7864function findWhiteSpaceEnd(source, offset) {
7865 for (; offset < source.length; offset++) {
7866 var code = source.charCodeAt(offset);
7867
7868 if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
7869 break;
7870 }
7871 }
7872
7873 return offset;
7874}
7875
7876function findCommentEnd(source, offset) {
7877 var commentEnd = source.indexOf('*/', offset);
7878
7879 if (commentEnd === -1) {
7880 return source.length;
7881 }
7882
7883 return commentEnd + 2;
7884}
7885
7886function findStringEnd(source, offset, quote) {
7887 for (; offset < source.length; offset++) {
7888 var code = source.charCodeAt(offset);
7889
7890 // TODO: bad string
7891 if (code === BACK_SLASH) {
7892 offset++;
7893 } else if (code === quote) {
7894 offset++;
7895 break;
7896 }
7897 }
7898
7899 return offset;
7900}
7901
7902function findDecimalNumberEnd(source, offset) {
7903 for (; offset < source.length; offset++) {
7904 var code = source.charCodeAt(offset);
7905
7906 if (code < 48 || code > 57) { // not a 0 .. 9
7907 break;
7908 }
7909 }
7910
7911 return offset;
7912}
7913
7914function findNumberEnd(source, offset, allowFraction) {
7915 var code;
7916
7917 offset = findDecimalNumberEnd(source, offset);
7918
7919 // fraction: .\d+
7920 if (allowFraction && offset + 1 < source.length && source.charCodeAt(offset) === FULLSTOP) {
7921 code = source.charCodeAt(offset + 1);
7922
7923 if (isNumber(code)) {
7924 offset = findDecimalNumberEnd(source, offset + 1);
7925 }
7926 }
7927
7928 // exponent: e[+-]\d+
7929 if (offset + 1 < source.length) {
7930 if ((source.charCodeAt(offset) | 32) === E) { // case insensitive check for `e`
7931 code = source.charCodeAt(offset + 1);
7932
7933 if (code === PLUSSIGN || code === HYPHENMINUS) {
7934 if (offset + 2 < source.length) {
7935 code = source.charCodeAt(offset + 2);
7936 }
7937 }
7938
7939 if (isNumber(code)) {
7940 offset = findDecimalNumberEnd(source, offset + 2);
7941 }
7942 }
7943 }
7944
7945 return offset;
7946}
7947
7948// skip escaped unicode sequence that can ends with space
7949// [0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
7950function findEscaseEnd(source, offset) {
7951 for (var i = 0; i < 7 && offset + i < source.length; i++) {
7952 var code = source.charCodeAt(offset + i);
7953
7954 if (i !== 6 && isHex(code)) {
7955 continue;
7956 }
7957
7958 if (i > 0) {
7959 offset += i - 1 + isNewline(source, offset + i, code);
7960 if (code === SPACE$1 || code === TAB$1) {
7961 offset++;
7962 }
7963 }
7964
7965 break;
7966 }
7967
7968 return offset;
7969}
7970
7971function findIdentifierEnd(source, offset) {
7972 for (; offset < source.length; offset++) {
7973 var code = source.charCodeAt(offset);
7974
7975 if (code === BACK_SLASH) {
7976 offset = findEscaseEnd(source, offset + 1);
7977 } else if (code < 0x80 && PUNCTUATION$1[code] === PUNCTUATOR$1) {
7978 break;
7979 }
7980 }
7981
7982 return offset;
7983}
7984
7985function findUrlRawEnd(source, offset) {
7986 for (; offset < source.length; offset++) {
7987 var code = source.charCodeAt(offset);
7988
7989 if (code === BACK_SLASH) {
7990 offset = findEscaseEnd(source, offset + 1);
7991 } else if (code < 0x80 && STOP_URL_RAW$1[code] === 1) {
7992 break;
7993 }
7994 }
7995
7996 return offset;
7997}
7998
7999var utils = {
8000 firstCharOffset: firstCharOffset,
8001
8002 isHex: isHex,
8003 isNumber: isNumber,
8004 isNewline: isNewline,
8005
8006 cmpChar: cmpChar,
8007 cmpStr: cmpStr,
8008 endsWith: endsWith,
8009
8010 findLastNonSpaceLocation: findLastNonSpaceLocation,
8011 findWhiteSpaceEnd: findWhiteSpaceEnd,
8012 findCommentEnd: findCommentEnd,
8013 findStringEnd: findStringEnd,
8014 findDecimalNumberEnd: findDecimalNumberEnd,
8015 findNumberEnd: findNumberEnd,
8016 findEscaseEnd: findEscaseEnd,
8017 findIdentifierEnd: findIdentifierEnd,
8018 findUrlRawEnd: findUrlRawEnd
8019};
8020
8021var TYPE$2 = _const.TYPE;
8022var NAME$1 = _const.NAME;
8023var SYMBOL_TYPE$1 = _const.SYMBOL_TYPE;
8024
8025
8026var firstCharOffset$1 = utils.firstCharOffset;
8027var cmpStr$1 = utils.cmpStr;
8028var isNumber$1 = utils.isNumber;
8029var findLastNonSpaceLocation$1 = utils.findLastNonSpaceLocation;
8030var findWhiteSpaceEnd$1 = utils.findWhiteSpaceEnd;
8031var findCommentEnd$1 = utils.findCommentEnd;
8032var findStringEnd$1 = utils.findStringEnd;
8033var findNumberEnd$1 = utils.findNumberEnd;
8034var findIdentifierEnd$1 = utils.findIdentifierEnd;
8035var findUrlRawEnd$1 = utils.findUrlRawEnd;
8036
8037var NULL = 0;
8038var WHITESPACE$1 = TYPE$2.WhiteSpace;
8039var IDENTIFIER$1 = TYPE$2.Identifier;
8040var NUMBER$1 = TYPE$2.Number;
8041var STRING$1 = TYPE$2.String;
8042var COMMENT$1 = TYPE$2.Comment;
8043var PUNCTUATOR$2 = TYPE$2.Punctuator;
8044var CDO$1 = TYPE$2.CDO;
8045var CDC$1 = TYPE$2.CDC;
8046var ATRULE$1 = TYPE$2.Atrule;
8047var FUNCTION$1 = TYPE$2.Function;
8048var URL$2 = TYPE$2.Url;
8049var RAW$1 = TYPE$2.Raw;
8050
8051var N$2 = 10;
8052var F$2 = 12;
8053var R$2 = 13;
8054var STAR = TYPE$2.Asterisk;
8055var SLASH = TYPE$2.Solidus;
8056var FULLSTOP$1 = TYPE$2.FullStop;
8057var PLUSSIGN$1 = TYPE$2.PlusSign;
8058var HYPHENMINUS$1 = TYPE$2.HyphenMinus;
8059var GREATERTHANSIGN = TYPE$2.GreaterThanSign;
8060var LESSTHANSIGN = TYPE$2.LessThanSign;
8061var EXCLAMATIONMARK = TYPE$2.ExclamationMark;
8062var COMMERCIALAT = TYPE$2.CommercialAt;
8063var QUOTATIONMARK = TYPE$2.QuotationMark;
8064var APOSTROPHE = TYPE$2.Apostrophe;
8065var LEFTPARENTHESIS = TYPE$2.LeftParenthesis;
8066var RIGHTPARENTHESIS = TYPE$2.RightParenthesis;
8067var LEFTCURLYBRACKET = TYPE$2.LeftCurlyBracket;
8068var RIGHTCURLYBRACKET = TYPE$2.RightCurlyBracket;
8069var LEFTSQUAREBRACKET = TYPE$2.LeftSquareBracket;
8070var RIGHTSQUAREBRACKET = TYPE$2.RightSquareBracket;
8071
8072var MIN_BUFFER_SIZE = 16 * 1024;
8073var OFFSET_MASK = 0x00FFFFFF;
8074var TYPE_SHIFT = 24;
8075var SafeUint32Array$1 = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
8076
8077function computeLinesAndColumns(tokenizer, source) {
8078 var sourceLength = source.length;
8079 var start = firstCharOffset$1(source);
8080 var lines = tokenizer.lines;
8081 var line = tokenizer.startLine;
8082 var columns = tokenizer.columns;
8083 var column = tokenizer.startColumn;
8084
8085 if (lines === null || lines.length < sourceLength + 1) {
8086 lines = new SafeUint32Array$1(Math.max(sourceLength + 1024, MIN_BUFFER_SIZE));
8087 columns = new SafeUint32Array$1(lines.length);
8088 }
8089
8090 for (var i = start; i < sourceLength; i++) {
8091 var code = source.charCodeAt(i);
8092
8093 lines[i] = line;
8094 columns[i] = column++;
8095
8096 if (code === N$2 || code === R$2 || code === F$2) {
8097 if (code === R$2 && i + 1 < sourceLength && source.charCodeAt(i + 1) === N$2) {
8098 i++;
8099 lines[i] = line;
8100 columns[i] = column;
8101 }
8102
8103 line++;
8104 column = 1;
8105 }
8106 }
8107
8108 lines[i] = line;
8109 columns[i] = column;
8110
8111 tokenizer.linesAnsColumnsComputed = true;
8112 tokenizer.lines = lines;
8113 tokenizer.columns = columns;
8114}
8115
8116function tokenLayout(tokenizer, source, startPos) {
8117 var sourceLength = source.length;
8118 var offsetAndType = tokenizer.offsetAndType;
8119 var balance = tokenizer.balance;
8120 var tokenCount = 0;
8121 var prevType = 0;
8122 var offset = startPos;
8123 var anchor = 0;
8124 var balanceCloseCode = 0;
8125 var balanceStart = 0;
8126 var balancePrev = 0;
8127
8128 if (offsetAndType === null || offsetAndType.length < sourceLength + 1) {
8129 offsetAndType = new SafeUint32Array$1(sourceLength + 1024);
8130 balance = new SafeUint32Array$1(sourceLength + 1024);
8131 }
8132
8133 while (offset < sourceLength) {
8134 var code = source.charCodeAt(offset);
8135 var type = code < 0x80 ? SYMBOL_TYPE$1[code] : IDENTIFIER$1;
8136
8137 balance[tokenCount] = sourceLength;
8138
8139 switch (type) {
8140 case WHITESPACE$1:
8141 offset = findWhiteSpaceEnd$1(source, offset + 1);
8142 break;
8143
8144 case PUNCTUATOR$2:
8145 switch (code) {
8146 case balanceCloseCode:
8147 balancePrev = balanceStart & OFFSET_MASK;
8148 balanceStart = balance[balancePrev];
8149 balanceCloseCode = balanceStart >> TYPE_SHIFT;
8150 balance[tokenCount] = balancePrev;
8151 balance[balancePrev++] = tokenCount;
8152 for (; balancePrev < tokenCount; balancePrev++) {
8153 if (balance[balancePrev] === sourceLength) {
8154 balance[balancePrev] = tokenCount;
8155 }
8156 }
8157 break;
8158
8159 case LEFTSQUAREBRACKET:
8160 balance[tokenCount] = balanceStart;
8161 balanceCloseCode = RIGHTSQUAREBRACKET;
8162 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8163 break;
8164
8165 case LEFTCURLYBRACKET:
8166 balance[tokenCount] = balanceStart;
8167 balanceCloseCode = RIGHTCURLYBRACKET;
8168 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8169 break;
8170
8171 case LEFTPARENTHESIS:
8172 balance[tokenCount] = balanceStart;
8173 balanceCloseCode = RIGHTPARENTHESIS;
8174 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8175 break;
8176 }
8177
8178 // /*
8179 if (code === STAR && prevType === SLASH) {
8180 type = COMMENT$1;
8181 offset = findCommentEnd$1(source, offset + 1);
8182 tokenCount--; // rewrite prev token
8183 break;
8184 }
8185
8186 // edge case for -.123 and +.123
8187 if (code === FULLSTOP$1 && (prevType === PLUSSIGN$1 || prevType === HYPHENMINUS$1)) {
8188 if (offset + 1 < sourceLength && isNumber$1(source.charCodeAt(offset + 1))) {
8189 type = NUMBER$1;
8190 offset = findNumberEnd$1(source, offset + 2, false);
8191 tokenCount--; // rewrite prev token
8192 break;
8193 }
8194 }
8195
8196 // <!--
8197 if (code === EXCLAMATIONMARK && prevType === LESSTHANSIGN) {
8198 if (offset + 2 < sourceLength &&
8199 source.charCodeAt(offset + 1) === HYPHENMINUS$1 &&
8200 source.charCodeAt(offset + 2) === HYPHENMINUS$1) {
8201 type = CDO$1;
8202 offset = offset + 3;
8203 tokenCount--; // rewrite prev token
8204 break;
8205 }
8206 }
8207
8208 // -->
8209 if (code === HYPHENMINUS$1 && prevType === HYPHENMINUS$1) {
8210 if (offset + 1 < sourceLength && source.charCodeAt(offset + 1) === GREATERTHANSIGN) {
8211 type = CDC$1;
8212 offset = offset + 2;
8213 tokenCount--; // rewrite prev token
8214 break;
8215 }
8216 }
8217
8218 // ident(
8219 if (code === LEFTPARENTHESIS && prevType === IDENTIFIER$1) {
8220 offset = offset + 1;
8221 tokenCount--; // rewrite prev token
8222 balance[tokenCount] = balance[tokenCount + 1];
8223 balanceStart--;
8224
8225 // 4 char length identifier and equal to `url(` (case insensitive)
8226 if (offset - anchor === 4 && cmpStr$1(source, anchor, offset, 'url(')) {
8227 // special case for url() because it can contain any symbols sequence with few exceptions
8228 anchor = findWhiteSpaceEnd$1(source, offset);
8229 code = source.charCodeAt(anchor);
8230 if (code !== LEFTPARENTHESIS &&
8231 code !== RIGHTPARENTHESIS &&
8232 code !== QUOTATIONMARK &&
8233 code !== APOSTROPHE) {
8234 // url(
8235 offsetAndType[tokenCount++] = (URL$2 << TYPE_SHIFT) | offset;
8236 balance[tokenCount] = sourceLength;
8237
8238 // ws*
8239 if (anchor !== offset) {
8240 offsetAndType[tokenCount++] = (WHITESPACE$1 << TYPE_SHIFT) | anchor;
8241 balance[tokenCount] = sourceLength;
8242 }
8243
8244 // raw
8245 type = RAW$1;
8246 offset = findUrlRawEnd$1(source, anchor);
8247 } else {
8248 type = URL$2;
8249 }
8250 } else {
8251 type = FUNCTION$1;
8252 }
8253 break;
8254 }
8255
8256 type = code;
8257 offset = offset + 1;
8258 break;
8259
8260 case NUMBER$1:
8261 offset = findNumberEnd$1(source, offset + 1, prevType !== FULLSTOP$1);
8262
8263 // merge number with a preceding dot, dash or plus
8264 if (prevType === FULLSTOP$1 ||
8265 prevType === HYPHENMINUS$1 ||
8266 prevType === PLUSSIGN$1) {
8267 tokenCount--; // rewrite prev token
8268 }
8269
8270 break;
8271
8272 case STRING$1:
8273 offset = findStringEnd$1(source, offset + 1, code);
8274 break;
8275
8276 default:
8277 anchor = offset;
8278 offset = findIdentifierEnd$1(source, offset);
8279
8280 // merge identifier with a preceding dash
8281 if (prevType === HYPHENMINUS$1) {
8282 // rewrite prev token
8283 tokenCount--;
8284 // restore prev prev token type
8285 // for case @-prefix-ident
8286 prevType = tokenCount === 0 ? 0 : offsetAndType[tokenCount - 1] >> TYPE_SHIFT;
8287 }
8288
8289 if (prevType === COMMERCIALAT) {
8290 // rewrite prev token and change type to <at-keyword-token>
8291 tokenCount--;
8292 type = ATRULE$1;
8293 }
8294 }
8295
8296 offsetAndType[tokenCount++] = (type << TYPE_SHIFT) | offset;
8297 prevType = type;
8298 }
8299
8300 // finalize arrays
8301 offsetAndType[tokenCount] = offset;
8302 balance[tokenCount] = sourceLength;
8303 while (balanceStart !== 0) {
8304 balancePrev = balanceStart & OFFSET_MASK;
8305 balanceStart = balance[balancePrev];
8306 balance[balancePrev] = sourceLength;
8307 }
8308
8309 tokenizer.offsetAndType = offsetAndType;
8310 tokenizer.tokenCount = tokenCount;
8311 tokenizer.balance = balance;
8312}
8313
8314//
8315// tokenizer
8316//
8317
8318var Tokenizer = function(source, startOffset, startLine, startColumn) {
8319 this.offsetAndType = null;
8320 this.balance = null;
8321 this.lines = null;
8322 this.columns = null;
8323
8324 this.setSource(source, startOffset, startLine, startColumn);
8325};
8326
8327Tokenizer.prototype = {
8328 setSource: function(source, startOffset, startLine, startColumn) {
8329 var safeSource = String(source || '');
8330 var start = firstCharOffset$1(safeSource);
8331
8332 this.source = safeSource;
8333 this.firstCharOffset = start;
8334 this.startOffset = typeof startOffset === 'undefined' ? 0 : startOffset;
8335 this.startLine = typeof startLine === 'undefined' ? 1 : startLine;
8336 this.startColumn = typeof startColumn === 'undefined' ? 1 : startColumn;
8337 this.linesAnsColumnsComputed = false;
8338
8339 this.eof = false;
8340 this.currentToken = -1;
8341 this.tokenType = 0;
8342 this.tokenStart = start;
8343 this.tokenEnd = start;
8344
8345 tokenLayout(this, safeSource, start);
8346 this.next();
8347 },
8348
8349 lookupType: function(offset) {
8350 offset += this.currentToken;
8351
8352 if (offset < this.tokenCount) {
8353 return this.offsetAndType[offset] >> TYPE_SHIFT;
8354 }
8355
8356 return NULL;
8357 },
8358 lookupNonWSType: function(offset) {
8359 offset += this.currentToken;
8360
8361 for (var type; offset < this.tokenCount; offset++) {
8362 type = this.offsetAndType[offset] >> TYPE_SHIFT;
8363
8364 if (type !== WHITESPACE$1) {
8365 return type;
8366 }
8367 }
8368
8369 return NULL;
8370 },
8371 lookupValue: function(offset, referenceStr) {
8372 offset += this.currentToken;
8373
8374 if (offset < this.tokenCount) {
8375 return cmpStr$1(
8376 this.source,
8377 this.offsetAndType[offset - 1] & OFFSET_MASK,
8378 this.offsetAndType[offset] & OFFSET_MASK,
8379 referenceStr
8380 );
8381 }
8382
8383 return false;
8384 },
8385 getTokenStart: function(tokenNum) {
8386 if (tokenNum === this.currentToken) {
8387 return this.tokenStart;
8388 }
8389
8390 if (tokenNum > 0) {
8391 return tokenNum < this.tokenCount
8392 ? this.offsetAndType[tokenNum - 1] & OFFSET_MASK
8393 : this.offsetAndType[this.tokenCount] & OFFSET_MASK;
8394 }
8395
8396 return this.firstCharOffset;
8397 },
8398 getOffsetExcludeWS: function() {
8399 if (this.currentToken > 0) {
8400 if ((this.offsetAndType[this.currentToken - 1] >> TYPE_SHIFT) === WHITESPACE$1) {
8401 return this.currentToken > 1
8402 ? this.offsetAndType[this.currentToken - 2] & OFFSET_MASK
8403 : this.firstCharOffset;
8404 }
8405 }
8406 return this.tokenStart;
8407 },
8408 getRawLength: function(startToken, endTokenType1, endTokenType2, includeTokenType2) {
8409 var cursor = startToken;
8410 var balanceEnd;
8411
8412 loop:
8413 for (; cursor < this.tokenCount; cursor++) {
8414 balanceEnd = this.balance[cursor];
8415
8416 // belance end points to offset before start
8417 if (balanceEnd < startToken) {
8418 break loop;
8419 }
8420
8421 // check token is stop type
8422 switch (this.offsetAndType[cursor] >> TYPE_SHIFT) {
8423 case endTokenType1:
8424 break loop;
8425
8426 case endTokenType2:
8427 if (includeTokenType2) {
8428 cursor++;
8429 }
8430 break loop;
8431
8432 default:
8433 // fast forward to the end of balanced block
8434 if (this.balance[balanceEnd] === cursor) {
8435 cursor = balanceEnd;
8436 }
8437 }
8438
8439 }
8440
8441 return cursor - this.currentToken;
8442 },
8443
8444 getTokenValue: function() {
8445 return this.source.substring(this.tokenStart, this.tokenEnd);
8446 },
8447 substrToCursor: function(start) {
8448 return this.source.substring(start, this.tokenStart);
8449 },
8450
8451 skipWS: function() {
8452 for (var i = this.currentToken, skipTokenCount = 0; i < this.tokenCount; i++, skipTokenCount++) {
8453 if ((this.offsetAndType[i] >> TYPE_SHIFT) !== WHITESPACE$1) {
8454 break;
8455 }
8456 }
8457
8458 if (skipTokenCount > 0) {
8459 this.skip(skipTokenCount);
8460 }
8461 },
8462 skipSC: function() {
8463 while (this.tokenType === WHITESPACE$1 || this.tokenType === COMMENT$1) {
8464 this.next();
8465 }
8466 },
8467 skip: function(tokenCount) {
8468 var next = this.currentToken + tokenCount;
8469
8470 if (next < this.tokenCount) {
8471 this.currentToken = next;
8472 this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
8473 next = this.offsetAndType[next];
8474 this.tokenType = next >> TYPE_SHIFT;
8475 this.tokenEnd = next & OFFSET_MASK;
8476 } else {
8477 this.currentToken = this.tokenCount;
8478 this.next();
8479 }
8480 },
8481 next: function() {
8482 var next = this.currentToken + 1;
8483
8484 if (next < this.tokenCount) {
8485 this.currentToken = next;
8486 this.tokenStart = this.tokenEnd;
8487 next = this.offsetAndType[next];
8488 this.tokenType = next >> TYPE_SHIFT;
8489 this.tokenEnd = next & OFFSET_MASK;
8490 } else {
8491 this.currentToken = this.tokenCount;
8492 this.eof = true;
8493 this.tokenType = NULL;
8494 this.tokenStart = this.tokenEnd = this.source.length;
8495 }
8496 },
8497
8498 eat: function(tokenType) {
8499 if (this.tokenType !== tokenType) {
8500 var offset = this.tokenStart;
8501 var message = NAME$1[tokenType] + ' is expected';
8502
8503 // tweak message and offset
8504 if (tokenType === IDENTIFIER$1) {
8505 // when identifier is expected but there is a function or url
8506 if (this.tokenType === FUNCTION$1 || this.tokenType === URL$2) {
8507 offset = this.tokenEnd - 1;
8508 message += ' but function found';
8509 }
8510 } else {
8511 // when test type is part of another token show error for current position + 1
8512 // e.g. eat(HYPHENMINUS) will fail on "-foo", but pointing on "-" is odd
8513 if (this.source.charCodeAt(this.tokenStart) === tokenType) {
8514 offset = offset + 1;
8515 }
8516 }
8517
8518 this.error(message, offset);
8519 }
8520
8521 this.next();
8522 },
8523 eatNonWS: function(tokenType) {
8524 this.skipWS();
8525 this.eat(tokenType);
8526 },
8527
8528 consume: function(tokenType) {
8529 var value = this.getTokenValue();
8530
8531 this.eat(tokenType);
8532
8533 return value;
8534 },
8535 consumeFunctionName: function() {
8536 var name = this.source.substring(this.tokenStart, this.tokenEnd - 1);
8537
8538 this.eat(FUNCTION$1);
8539
8540 return name;
8541 },
8542 consumeNonWS: function(tokenType) {
8543 this.skipWS();
8544
8545 return this.consume(tokenType);
8546 },
8547
8548 expectIdentifier: function(name) {
8549 if (this.tokenType !== IDENTIFIER$1 || cmpStr$1(this.source, this.tokenStart, this.tokenEnd, name) === false) {
8550 this.error('Identifier `' + name + '` is expected');
8551 }
8552
8553 this.next();
8554 },
8555
8556 getLocation: function(offset, filename) {
8557 if (!this.linesAnsColumnsComputed) {
8558 computeLinesAndColumns(this, this.source);
8559 }
8560
8561 return {
8562 source: filename,
8563 offset: this.startOffset + offset,
8564 line: this.lines[offset],
8565 column: this.columns[offset]
8566 };
8567 },
8568
8569 getLocationRange: function(start, end, filename) {
8570 if (!this.linesAnsColumnsComputed) {
8571 computeLinesAndColumns(this, this.source);
8572 }
8573
8574 return {
8575 source: filename,
8576 start: {
8577 offset: this.startOffset + start,
8578 line: this.lines[start],
8579 column: this.columns[start]
8580 },
8581 end: {
8582 offset: this.startOffset + end,
8583 line: this.lines[end],
8584 column: this.columns[end]
8585 }
8586 };
8587 },
8588
8589 error: function(message, offset) {
8590 var location = typeof offset !== 'undefined' && offset < this.source.length
8591 ? this.getLocation(offset)
8592 : this.eof
8593 ? findLastNonSpaceLocation$1(this)
8594 : this.getLocation(this.tokenStart);
8595
8596 throw new error(
8597 message || 'Unexpected input',
8598 this.source,
8599 location.offset,
8600 location.line,
8601 location.column
8602 );
8603 },
8604
8605 dump: function() {
8606 var offset = 0;
8607
8608 return Array.prototype.slice.call(this.offsetAndType, 0, this.tokenCount).map(function(item, idx) {
8609 var start = offset;
8610 var end = item & OFFSET_MASK;
8611
8612 offset = end;
8613
8614 return {
8615 idx: idx,
8616 type: NAME$1[item >> TYPE_SHIFT],
8617 chunk: this.source.substring(start, end),
8618 balance: this.balance[idx]
8619 };
8620 }, this);
8621 }
8622};
8623
8624// extend with error class
8625Tokenizer.CssSyntaxError = error;
8626
8627// extend tokenizer with constants
8628Object.keys(_const).forEach(function(key) {
8629 Tokenizer[key] = _const[key];
8630});
8631
8632// extend tokenizer with static methods from utils
8633Object.keys(utils).forEach(function(key) {
8634 Tokenizer[key] = utils[key];
8635});
8636
8637// warm up tokenizer to elimitate code branches that never execute
8638// fix soft deoptimizations (insufficient type feedback)
8639new Tokenizer('\n\r\r\n\f<!---->//""\'\'/*\r\n\f*/1a;.\\31\t\+2{url(a);func();+1.2e3 -.4e-5 .6e+7}').getLocation();
8640
8641var Tokenizer_1 = Tokenizer;
8642
8643var tokenizer = Tokenizer_1;
8644
8645//
8646// item item item item
8647// /------\ /------\ /------\ /------\
8648// | data | | data | | data | | data |
8649// null <--+-prev |<---+-prev |<---+-prev |<---+-prev |
8650// | next-+--->| next-+--->| next-+--->| next-+--> null
8651// \------/ \------/ \------/ \------/
8652// ^ ^
8653// | list |
8654// | /------\ |
8655// \--------------+-head | |
8656// | tail-+--------------/
8657// \------/
8658//
8659
8660function createItem(data) {
8661 return {
8662 prev: null,
8663 next: null,
8664 data: data
8665 };
8666}
8667
8668var cursors = null;
8669var List = function() {
8670 this.cursor = null;
8671 this.head = null;
8672 this.tail = null;
8673};
8674
8675List.createItem = createItem;
8676List.prototype.createItem = createItem;
8677
8678List.prototype.getSize = function() {
8679 var size = 0;
8680 var cursor = this.head;
8681
8682 while (cursor) {
8683 size++;
8684 cursor = cursor.next;
8685 }
8686
8687 return size;
8688};
8689
8690List.prototype.fromArray = function(array) {
8691 var cursor = null;
8692
8693 this.head = null;
8694
8695 for (var i = 0; i < array.length; i++) {
8696 var item = createItem(array[i]);
8697
8698 if (cursor !== null) {
8699 cursor.next = item;
8700 } else {
8701 this.head = item;
8702 }
8703
8704 item.prev = cursor;
8705 cursor = item;
8706 }
8707
8708 this.tail = cursor;
8709
8710 return this;
8711};
8712
8713List.prototype.toArray = function() {
8714 var cursor = this.head;
8715 var result = [];
8716
8717 while (cursor) {
8718 result.push(cursor.data);
8719 cursor = cursor.next;
8720 }
8721
8722 return result;
8723};
8724
8725List.prototype.toJSON = List.prototype.toArray;
8726
8727List.prototype.isEmpty = function() {
8728 return this.head === null;
8729};
8730
8731List.prototype.first = function() {
8732 return this.head && this.head.data;
8733};
8734
8735List.prototype.last = function() {
8736 return this.tail && this.tail.data;
8737};
8738
8739function allocateCursor(node, prev, next) {
8740 var cursor;
8741
8742 if (cursors !== null) {
8743 cursor = cursors;
8744 cursors = cursors.cursor;
8745 cursor.prev = prev;
8746 cursor.next = next;
8747 cursor.cursor = node.cursor;
8748 } else {
8749 cursor = {
8750 prev: prev,
8751 next: next,
8752 cursor: node.cursor
8753 };
8754 }
8755
8756 node.cursor = cursor;
8757
8758 return cursor;
8759}
8760
8761function releaseCursor(node) {
8762 var cursor = node.cursor;
8763
8764 node.cursor = cursor.cursor;
8765 cursor.prev = null;
8766 cursor.next = null;
8767 cursor.cursor = cursors;
8768 cursors = cursor;
8769}
8770
8771List.prototype.each = function(fn, context) {
8772 var item;
8773
8774 if (context === undefined) {
8775 context = this;
8776 }
8777
8778 // push cursor
8779 var cursor = allocateCursor(this, null, this.head);
8780
8781 while (cursor.next !== null) {
8782 item = cursor.next;
8783 cursor.next = item.next;
8784
8785 fn.call(context, item.data, item, this);
8786 }
8787
8788 // pop cursor
8789 releaseCursor(this);
8790};
8791
8792List.prototype.eachRight = function(fn, context) {
8793 var item;
8794
8795 if (context === undefined) {
8796 context = this;
8797 }
8798
8799 // push cursor
8800 var cursor = allocateCursor(this, this.tail, null);
8801
8802 while (cursor.prev !== null) {
8803 item = cursor.prev;
8804 cursor.prev = item.prev;
8805
8806 fn.call(context, item.data, item, this);
8807 }
8808
8809 // pop cursor
8810 releaseCursor(this);
8811};
8812
8813List.prototype.nextUntil = function(start, fn, context) {
8814 if (start === null) {
8815 return;
8816 }
8817
8818 var item;
8819
8820 if (context === undefined) {
8821 context = this;
8822 }
8823
8824 // push cursor
8825 var cursor = allocateCursor(this, null, start);
8826
8827 while (cursor.next !== null) {
8828 item = cursor.next;
8829 cursor.next = item.next;
8830
8831 if (fn.call(context, item.data, item, this)) {
8832 break;
8833 }
8834 }
8835
8836 // pop cursor
8837 releaseCursor(this);
8838};
8839
8840List.prototype.prevUntil = function(start, fn, context) {
8841 if (start === null) {
8842 return;
8843 }
8844
8845 var item;
8846
8847 if (context === undefined) {
8848 context = this;
8849 }
8850
8851 // push cursor
8852 var cursor = allocateCursor(this, start, null);
8853
8854 while (cursor.prev !== null) {
8855 item = cursor.prev;
8856 cursor.prev = item.prev;
8857
8858 if (fn.call(context, item.data, item, this)) {
8859 break;
8860 }
8861 }
8862
8863 // pop cursor
8864 releaseCursor(this);
8865};
8866
8867List.prototype.some = function(fn, context) {
8868 var cursor = this.head;
8869
8870 if (context === undefined) {
8871 context = this;
8872 }
8873
8874 while (cursor !== null) {
8875 if (fn.call(context, cursor.data, cursor, this)) {
8876 return true;
8877 }
8878
8879 cursor = cursor.next;
8880 }
8881
8882 return false;
8883};
8884
8885List.prototype.map = function(fn, context) {
8886 var result = [];
8887 var cursor = this.head;
8888
8889 if (context === undefined) {
8890 context = this;
8891 }
8892
8893 while (cursor !== null) {
8894 result.push(fn.call(context, cursor.data, cursor, this));
8895 cursor = cursor.next;
8896 }
8897
8898 return result;
8899};
8900
8901List.prototype.clear = function() {
8902 this.head = null;
8903 this.tail = null;
8904};
8905
8906List.prototype.copy = function() {
8907 var result = new List();
8908 var cursor = this.head;
8909
8910 while (cursor !== null) {
8911 result.insert(createItem(cursor.data));
8912 cursor = cursor.next;
8913 }
8914
8915 return result;
8916};
8917
8918List.prototype.updateCursors = function(prevOld, prevNew, nextOld, nextNew) {
8919 var cursor = this.cursor;
8920
8921 while (cursor !== null) {
8922 if (cursor.prev === prevOld) {
8923 cursor.prev = prevNew;
8924 }
8925
8926 if (cursor.next === nextOld) {
8927 cursor.next = nextNew;
8928 }
8929
8930 cursor = cursor.cursor;
8931 }
8932};
8933
8934List.prototype.prepend = function(item) {
8935 // head
8936 // ^
8937 // item
8938 this.updateCursors(null, item, this.head, item);
8939
8940 // insert to the beginning of the list
8941 if (this.head !== null) {
8942 // new item <- first item
8943 this.head.prev = item;
8944
8945 // new item -> first item
8946 item.next = this.head;
8947 } else {
8948 // if list has no head, then it also has no tail
8949 // in this case tail points to the new item
8950 this.tail = item;
8951 }
8952
8953 // head always points to new item
8954 this.head = item;
8955
8956 return this;
8957};
8958
8959List.prototype.prependData = function(data) {
8960 return this.prepend(createItem(data));
8961};
8962
8963List.prototype.append = function(item) {
8964 // tail
8965 // ^
8966 // item
8967 this.updateCursors(this.tail, item, null, item);
8968
8969 // insert to the ending of the list
8970 if (this.tail !== null) {
8971 // last item -> new item
8972 this.tail.next = item;
8973
8974 // last item <- new item
8975 item.prev = this.tail;
8976 } else {
8977 // if list has no tail, then it also has no head
8978 // in this case head points to new item
8979 this.head = item;
8980 }
8981
8982 // tail always points to new item
8983 this.tail = item;
8984
8985 return this;
8986};
8987
8988List.prototype.appendData = function(data) {
8989 return this.append(createItem(data));
8990};
8991
8992List.prototype.insert = function(item, before) {
8993 if (before !== undefined && before !== null) {
8994 // prev before
8995 // ^
8996 // item
8997 this.updateCursors(before.prev, item, before, item);
8998
8999 if (before.prev === null) {
9000 // insert to the beginning of list
9001 if (this.head !== before) {
9002 throw new Error('before doesn\'t belong to list');
9003 }
9004
9005 // since head points to before therefore list doesn't empty
9006 // no need to check tail
9007 this.head = item;
9008 before.prev = item;
9009 item.next = before;
9010
9011 this.updateCursors(null, item);
9012 } else {
9013
9014 // insert between two items
9015 before.prev.next = item;
9016 item.prev = before.prev;
9017
9018 before.prev = item;
9019 item.next = before;
9020 }
9021 } else {
9022 this.append(item);
9023 }
9024};
9025
9026List.prototype.insertData = function(data, before) {
9027 this.insert(createItem(data), before);
9028};
9029
9030List.prototype.remove = function(item) {
9031 // item
9032 // ^
9033 // prev next
9034 this.updateCursors(item, item.prev, item, item.next);
9035
9036 if (item.prev !== null) {
9037 item.prev.next = item.next;
9038 } else {
9039 if (this.head !== item) {
9040 throw new Error('item doesn\'t belong to list');
9041 }
9042
9043 this.head = item.next;
9044 }
9045
9046 if (item.next !== null) {
9047 item.next.prev = item.prev;
9048 } else {
9049 if (this.tail !== item) {
9050 throw new Error('item doesn\'t belong to list');
9051 }
9052
9053 this.tail = item.prev;
9054 }
9055
9056 item.prev = null;
9057 item.next = null;
9058
9059 return item;
9060};
9061
9062List.prototype.appendList = function(list) {
9063 // ignore empty lists
9064 if (list.head === null) {
9065 return;
9066 }
9067
9068 this.updateCursors(this.tail, list.tail, null, list.head);
9069
9070 // insert to end of the list
9071 if (this.tail !== null) {
9072 // if destination list has a tail, then it also has a head,
9073 // but head doesn't change
9074
9075 // dest tail -> source head
9076 this.tail.next = list.head;
9077
9078 // dest tail <- source head
9079 list.head.prev = this.tail;
9080 } else {
9081 // if list has no a tail, then it also has no a head
9082 // in this case points head to new item
9083 this.head = list.head;
9084 }
9085
9086 // tail always start point to new item
9087 this.tail = list.tail;
9088
9089 list.head = null;
9090 list.tail = null;
9091};
9092
9093List.prototype.insertList = function(list, before) {
9094 if (before !== undefined && before !== null) {
9095 // ignore empty lists
9096 if (list.head === null) {
9097 return;
9098 }
9099
9100 this.updateCursors(before.prev, list.tail, before, list.head);
9101
9102 // insert in the middle of dist list
9103 if (before.prev !== null) {
9104 // before.prev <-> list.head
9105 before.prev.next = list.head;
9106 list.head.prev = before.prev;
9107 } else {
9108 this.head = list.head;
9109 }
9110
9111 before.prev = list.tail;
9112 list.tail.next = before;
9113
9114 list.head = null;
9115 list.tail = null;
9116 } else {
9117 this.appendList(list);
9118 }
9119};
9120
9121List.prototype.replace = function(oldItem, newItemOrList) {
9122 if ('head' in newItemOrList) {
9123 this.insertList(newItemOrList, oldItem);
9124 } else {
9125 this.insert(newItemOrList, oldItem);
9126 }
9127 this.remove(oldItem);
9128};
9129
9130var list = List;
9131
9132var TYPE$3 = tokenizer.TYPE;
9133var WHITESPACE$2 = TYPE$3.WhiteSpace;
9134var COMMENT$2 = TYPE$3.Comment;
9135
9136var sequence = function readSequence(recognizer) {
9137 var children = new list();
9138 var child = null;
9139 var context = {
9140 recognizer: recognizer,
9141 space: null,
9142 ignoreWS: false,
9143 ignoreWSAfter: false
9144 };
9145
9146 this.scanner.skipSC();
9147
9148 while (!this.scanner.eof) {
9149 switch (this.scanner.tokenType) {
9150 case COMMENT$2:
9151 this.scanner.next();
9152 continue;
9153
9154 case WHITESPACE$2:
9155 if (context.ignoreWS) {
9156 this.scanner.next();
9157 } else {
9158 context.space = this.WhiteSpace();
9159 }
9160 continue;
9161 }
9162
9163 child = recognizer.getNode.call(this, context);
9164
9165 if (child === undefined) {
9166 break;
9167 }
9168
9169 if (context.space !== null) {
9170 children.appendData(context.space);
9171 context.space = null;
9172 }
9173
9174 children.appendData(child);
9175
9176 if (context.ignoreWSAfter) {
9177 context.ignoreWSAfter = false;
9178 context.ignoreWS = true;
9179 } else {
9180 context.ignoreWS = false;
9181 }
9182 }
9183
9184 return children;
9185};
9186
9187var noop = function() {};
9188
9189function createParseContext(name) {
9190 return function() {
9191 return this[name]();
9192 };
9193}
9194
9195function processConfig(config) {
9196 var parserConfig = {
9197 context: {},
9198 scope: {},
9199 atrule: {},
9200 pseudo: {}
9201 };
9202
9203 if (config.parseContext) {
9204 for (var name in config.parseContext) {
9205 switch (typeof config.parseContext[name]) {
9206 case 'function':
9207 parserConfig.context[name] = config.parseContext[name];
9208 break;
9209
9210 case 'string':
9211 parserConfig.context[name] = createParseContext(config.parseContext[name]);
9212 break;
9213 }
9214 }
9215 }
9216
9217 if (config.scope) {
9218 for (var name in config.scope) {
9219 parserConfig.scope[name] = config.scope[name];
9220 }
9221 }
9222
9223 if (config.atrule) {
9224 for (var name in config.atrule) {
9225 var atrule = config.atrule[name];
9226
9227 if (atrule.parse) {
9228 parserConfig.atrule[name] = atrule.parse;
9229 }
9230 }
9231 }
9232
9233 if (config.pseudo) {
9234 for (var name in config.pseudo) {
9235 var pseudo = config.pseudo[name];
9236
9237 if (pseudo.parse) {
9238 parserConfig.pseudo[name] = pseudo.parse;
9239 }
9240 }
9241 }
9242
9243 if (config.node) {
9244 for (var name in config.node) {
9245 parserConfig[name] = config.node[name].parse;
9246 }
9247 }
9248
9249 return parserConfig;
9250}
9251
9252var create = function createParser(config) {
9253 var parser = {
9254 scanner: new tokenizer(),
9255 filename: '<unknown>',
9256 needPositions: false,
9257 tolerant: false,
9258 onParseError: noop,
9259 parseAtruleExpression: true,
9260 parseSelector: true,
9261 parseValue: true,
9262 parseCustomProperty: false,
9263
9264 readSequence: sequence,
9265
9266 tolerantParse: function(consumer, fallback) {
9267 if (this.tolerant) {
9268 var start = this.scanner.currentToken;
9269
9270 try {
9271 return consumer.call(this);
9272 } catch (e) {
9273 this.onParseError(e);
9274 return fallback.call(this, start);
9275 }
9276 } else {
9277 return consumer.call(this);
9278 }
9279 },
9280
9281 getLocation: function(start, end) {
9282 if (this.needPositions) {
9283 return this.scanner.getLocationRange(
9284 start,
9285 end,
9286 this.filename
9287 );
9288 }
9289
9290 return null;
9291 },
9292 getLocationFromList: function(list) {
9293 if (this.needPositions) {
9294 return this.scanner.getLocationRange(
9295 list.head !== null ? list.first().loc.start.offset - this.scanner.startOffset : this.scanner.tokenStart,
9296 list.head !== null ? list.last().loc.end.offset - this.scanner.startOffset : this.scanner.tokenStart,
9297 this.filename
9298 );
9299 }
9300
9301 return null;
9302 }
9303 };
9304
9305 config = processConfig(config || {});
9306 for (var key in config) {
9307 parser[key] = config[key];
9308 }
9309
9310 return function(source, options) {
9311 options = options || {};
9312
9313 var context = options.context || 'default';
9314 var ast;
9315
9316 parser.scanner.setSource(source, options.offset, options.line, options.column);
9317 parser.filename = options.filename || '<unknown>';
9318 parser.needPositions = Boolean(options.positions);
9319 parser.tolerant = Boolean(options.tolerant);
9320 parser.onParseError = typeof options.onParseError === 'function' ? options.onParseError : noop;
9321 parser.parseAtruleExpression = 'parseAtruleExpression' in options ? Boolean(options.parseAtruleExpression) : true;
9322 parser.parseSelector = 'parseSelector' in options ? Boolean(options.parseSelector) : true;
9323 parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
9324 parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;
9325
9326 if (!parser.context.hasOwnProperty(context)) {
9327 throw new Error('Unknown context `' + context + '`');
9328 }
9329
9330 ast = parser.context[context].call(parser, options);
9331
9332 if (!parser.scanner.eof) {
9333 parser.scanner.error();
9334 }
9335
9336 // console.log(JSON.stringify(ast, null, 4));
9337 return ast;
9338 };
9339};
9340
9341var cmpChar$1 = tokenizer.cmpChar;
9342var TYPE$4 = tokenizer.TYPE;
9343
9344var IDENTIFIER$2 = TYPE$4.Identifier;
9345var STRING$2 = TYPE$4.String;
9346var NUMBER$2 = TYPE$4.Number;
9347var FUNCTION$2 = TYPE$4.Function;
9348var URL$3 = TYPE$4.Url;
9349var NUMBERSIGN = TYPE$4.NumberSign;
9350var LEFTPARENTHESIS$1 = TYPE$4.LeftParenthesis;
9351var LEFTSQUAREBRACKET$1 = TYPE$4.LeftSquareBracket;
9352var PLUSSIGN$2 = TYPE$4.PlusSign;
9353var HYPHENMINUS$2 = TYPE$4.HyphenMinus;
9354var COMMA = TYPE$4.Comma;
9355var SOLIDUS = TYPE$4.Solidus;
9356var ASTERISK = TYPE$4.Asterisk;
9357var PERCENTSIGN = TYPE$4.PercentSign;
9358var BACKSLASH = TYPE$4.Backslash;
9359var U = 117; // 'u'.charCodeAt(0)
9360
9361var _default = function defaultRecognizer(context) {
9362 switch (this.scanner.tokenType) {
9363 case NUMBERSIGN:
9364 return this.HexColor();
9365
9366 case COMMA:
9367 context.space = null;
9368 context.ignoreWSAfter = true;
9369 return this.Operator();
9370
9371 case SOLIDUS:
9372 case ASTERISK:
9373 case PLUSSIGN$2:
9374 case HYPHENMINUS$2:
9375 return this.Operator();
9376
9377 case LEFTPARENTHESIS$1:
9378 return this.Parentheses(this.readSequence, context.recognizer);
9379
9380 case LEFTSQUAREBRACKET$1:
9381 return this.Brackets(this.readSequence, context.recognizer);
9382
9383 case STRING$2:
9384 return this.String();
9385
9386 case NUMBER$2:
9387 switch (this.scanner.lookupType(1)) {
9388 case PERCENTSIGN:
9389 return this.Percentage();
9390
9391 case IDENTIFIER$2:
9392 // edge case: number with folowing \0 and \9 hack shouldn't to be a Dimension
9393 if (cmpChar$1(this.scanner.source, this.scanner.tokenEnd, BACKSLASH)) {
9394 return this.Number();
9395 } else {
9396 return this.Dimension();
9397 }
9398
9399 default:
9400 return this.Number();
9401 }
9402
9403 case FUNCTION$2:
9404 return this.Function(this.readSequence, context.recognizer);
9405
9406 case URL$3:
9407 return this.Url();
9408
9409 case IDENTIFIER$2:
9410 // check for unicode range, it should start with u+ or U+
9411 if (cmpChar$1(this.scanner.source, this.scanner.tokenStart, U) &&
9412 cmpChar$1(this.scanner.source, this.scanner.tokenStart + 1, PLUSSIGN$2)) {
9413 return this.UnicodeRange();
9414 } else {
9415 return this.Identifier();
9416 }
9417 }
9418};
9419
9420var atruleExpression = {
9421 getNode: _default
9422};
9423
9424var TYPE$5 = tokenizer.TYPE;
9425
9426var IDENTIFIER$3 = TYPE$5.Identifier;
9427var NUMBER$3 = TYPE$5.Number;
9428var NUMBERSIGN$1 = TYPE$5.NumberSign;
9429var LEFTSQUAREBRACKET$2 = TYPE$5.LeftSquareBracket;
9430var PLUSSIGN$3 = TYPE$5.PlusSign;
9431var SOLIDUS$1 = TYPE$5.Solidus;
9432var ASTERISK$1 = TYPE$5.Asterisk;
9433var FULLSTOP$2 = TYPE$5.FullStop;
9434var COLON = TYPE$5.Colon;
9435var GREATERTHANSIGN$1 = TYPE$5.GreaterThanSign;
9436var VERTICALLINE = TYPE$5.VerticalLine;
9437var TILDE = TYPE$5.Tilde;
9438
9439function getNode(context) {
9440 switch (this.scanner.tokenType) {
9441 case PLUSSIGN$3:
9442 case GREATERTHANSIGN$1:
9443 case TILDE:
9444 context.space = null;
9445 context.ignoreWSAfter = true;
9446 return this.Combinator();
9447
9448 case SOLIDUS$1: // /deep/
9449 return this.Combinator();
9450
9451 case FULLSTOP$2:
9452 return this.ClassSelector();
9453
9454 case LEFTSQUAREBRACKET$2:
9455 return this.AttributeSelector();
9456
9457 case NUMBERSIGN$1:
9458 return this.IdSelector();
9459
9460 case COLON:
9461 if (this.scanner.lookupType(1) === COLON) {
9462 return this.PseudoElementSelector();
9463 } else {
9464 return this.PseudoClassSelector();
9465 }
9466
9467 case IDENTIFIER$3:
9468 case ASTERISK$1:
9469 case VERTICALLINE:
9470 return this.TypeSelector();
9471
9472 case NUMBER$3:
9473 return this.Percentage();
9474 }
9475}
9476var selector = {
9477 getNode: getNode
9478};
9479
9480// https://drafts.csswg.org/css-images-4/#element-notation
9481// https://developer.mozilla.org/en-US/docs/Web/CSS/element
9482var element = function() {
9483 this.scanner.skipSC();
9484
9485 var id = this.IdSelector();
9486
9487 this.scanner.skipSC();
9488
9489 return new list().appendData(
9490 id
9491 );
9492};
9493
9494// legacy IE function
9495// expression '(' raw ')'
9496var expression = function() {
9497 return new list().appendData(
9498 this.Raw(this.scanner.currentToken, 0, 0, false, false)
9499 );
9500};
9501
9502var TYPE$6 = tokenizer.TYPE;
9503
9504var IDENTIFIER$4 = TYPE$6.Identifier;
9505var COMMA$1 = TYPE$6.Comma;
9506var SEMICOLON = TYPE$6.Semicolon;
9507var HYPHENMINUS$3 = TYPE$6.HyphenMinus;
9508var EXCLAMATIONMARK$1 = TYPE$6.ExclamationMark;
9509
9510// var '(' ident (',' <value>? )? ')'
9511var _var = function() {
9512 var children = new list();
9513
9514 this.scanner.skipSC();
9515
9516 var identStart = this.scanner.tokenStart;
9517
9518 this.scanner.eat(HYPHENMINUS$3);
9519 if (this.scanner.source.charCodeAt(this.scanner.tokenStart) !== HYPHENMINUS$3) {
9520 this.scanner.error('HyphenMinus is expected');
9521 }
9522 this.scanner.eat(IDENTIFIER$4);
9523
9524 children.appendData({
9525 type: 'Identifier',
9526 loc: this.getLocation(identStart, this.scanner.tokenStart),
9527 name: this.scanner.substrToCursor(identStart)
9528 });
9529
9530 this.scanner.skipSC();
9531
9532 if (this.scanner.tokenType === COMMA$1) {
9533 children.appendData(this.Operator());
9534 children.appendData(this.parseCustomProperty
9535 ? this.Value(null)
9536 : this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$1, SEMICOLON, false, false)
9537 );
9538 }
9539
9540 return children;
9541};
9542
9543var value = {
9544 getNode: _default,
9545 '-moz-element': element,
9546 'element': element,
9547 'expression': expression,
9548 'var': _var
9549};
9550
9551var scope = {
9552 AtruleExpression: atruleExpression,
9553 Selector: selector,
9554 Value: value
9555};
9556
9557var fontFace = {
9558 parse: {
9559 expression: null,
9560 block: function() {
9561 return this.Block(this.Declaration);
9562 }
9563 }
9564};
9565
9566var TYPE$7 = tokenizer.TYPE;
9567
9568var STRING$3 = TYPE$7.String;
9569var IDENTIFIER$5 = TYPE$7.Identifier;
9570var URL$4 = TYPE$7.Url;
9571var LEFTPARENTHESIS$2 = TYPE$7.LeftParenthesis;
9572
9573var _import = {
9574 parse: {
9575 expression: function() {
9576 var children = new list();
9577
9578 this.scanner.skipSC();
9579
9580 switch (this.scanner.tokenType) {
9581 case STRING$3:
9582 children.appendData(this.String());
9583 break;
9584
9585 case URL$4:
9586 children.appendData(this.Url());
9587 break;
9588
9589 default:
9590 this.scanner.error('String or url() is expected');
9591 }
9592
9593 if (this.scanner.lookupNonWSType(0) === IDENTIFIER$5 ||
9594 this.scanner.lookupNonWSType(0) === LEFTPARENTHESIS$2) {
9595 children.appendData(this.WhiteSpace());
9596 children.appendData(this.MediaQueryList());
9597 }
9598
9599 return children;
9600 },
9601 block: null
9602 }
9603};
9604
9605var media = {
9606 parse: {
9607 expression: function() {
9608 return new list().appendData(
9609 this.MediaQueryList()
9610 );
9611 },
9612 block: function() {
9613 return this.Block(this.Rule);
9614 }
9615 }
9616};
9617
9618var TYPE$8 = tokenizer.TYPE;
9619var LEFTCURLYBRACKET$1 = TYPE$8.LeftCurlyBracket;
9620
9621var page = {
9622 parse: {
9623 expression: function() {
9624 if (this.scanner.lookupNonWSType(0) === LEFTCURLYBRACKET$1) {
9625 return null;
9626 }
9627
9628 return new list().appendData(
9629 this.SelectorList()
9630 );
9631 },
9632 block: function() {
9633 return this.Block(this.Declaration);
9634 }
9635 }
9636};
9637
9638var TYPE$9 = tokenizer.TYPE;
9639
9640var WHITESPACE$3 = TYPE$9.WhiteSpace;
9641var COMMENT$3 = TYPE$9.Comment;
9642var IDENTIFIER$6 = TYPE$9.Identifier;
9643var FUNCTION$3 = TYPE$9.Function;
9644var LEFTPARENTHESIS$3 = TYPE$9.LeftParenthesis;
9645var HYPHENMINUS$4 = TYPE$9.HyphenMinus;
9646var COLON$1 = TYPE$9.Colon;
9647
9648function consumeRaw() {
9649 return new list().appendData(
9650 this.Raw(this.scanner.currentToken, 0, 0, false, false)
9651 );
9652}
9653
9654function parentheses() {
9655 var index = 0;
9656
9657 this.scanner.skipSC();
9658
9659 // TODO: make it simplier
9660 if (this.scanner.tokenType === IDENTIFIER$6) {
9661 index = 1;
9662 } else if (this.scanner.tokenType === HYPHENMINUS$4 &&
9663 this.scanner.lookupType(1) === IDENTIFIER$6) {
9664 index = 2;
9665 }
9666
9667 if (index !== 0 && this.scanner.lookupNonWSType(index) === COLON$1) {
9668 return new list().appendData(
9669 this.Declaration()
9670 );
9671 }
9672
9673 return readSequence.call(this);
9674}
9675
9676function readSequence() {
9677 var children = new list();
9678 var space = null;
9679 var child;
9680
9681 this.scanner.skipSC();
9682
9683 scan:
9684 while (!this.scanner.eof) {
9685 switch (this.scanner.tokenType) {
9686 case WHITESPACE$3:
9687 space = this.WhiteSpace();
9688 continue;
9689
9690 case COMMENT$3:
9691 this.scanner.next();
9692 continue;
9693
9694 case FUNCTION$3:
9695 child = this.Function(consumeRaw, this.scope.AtruleExpression);
9696 break;
9697
9698 case IDENTIFIER$6:
9699 child = this.Identifier();
9700 break;
9701
9702 case LEFTPARENTHESIS$3:
9703 child = this.Parentheses(parentheses, this.scope.AtruleExpression);
9704 break;
9705
9706 default:
9707 break scan;
9708 }
9709
9710 if (space !== null) {
9711 children.appendData(space);
9712 space = null;
9713 }
9714
9715 children.appendData(child);
9716 }
9717
9718 return children;
9719}
9720
9721var supports = {
9722 parse: {
9723 expression: function() {
9724 var children = readSequence.call(this);
9725
9726 if (children.isEmpty()) {
9727 this.scanner.error('Condition is expected');
9728 }
9729
9730 return children;
9731 },
9732 block: function() {
9733 return this.Block(this.Rule);
9734 }
9735 }
9736};
9737
9738var atrule = {
9739 'font-face': fontFace,
9740 'import': _import,
9741 'media': media,
9742 'page': page,
9743 'supports': supports
9744};
9745
9746var dir = {
9747 parse: function() {
9748 return new list().appendData(
9749 this.Identifier()
9750 );
9751 }
9752};
9753
9754var has$1 = {
9755 parse: function() {
9756 return new list().appendData(
9757 this.SelectorList()
9758 );
9759 }
9760};
9761
9762var lang = {
9763 parse: function() {
9764 return new list().appendData(
9765 this.Identifier()
9766 );
9767 }
9768};
9769
9770var selectorList = {
9771 parse: function selectorList() {
9772 return new list().appendData(
9773 this.SelectorList()
9774 );
9775 }
9776};
9777
9778var matches = selectorList;
9779
9780var not = selectorList;
9781
9782var ALLOW_OF_CLAUSE = true;
9783
9784var nthWithOfClause = {
9785 parse: function() {
9786 return new list().appendData(
9787 this.Nth(ALLOW_OF_CLAUSE)
9788 );
9789 }
9790};
9791
9792var nthChild = nthWithOfClause;
9793
9794var nthLastChild = nthWithOfClause;
9795
9796var DISALLOW_OF_CLAUSE = false;
9797
9798var nth = {
9799 parse: function nth() {
9800 return new list().appendData(
9801 this.Nth(DISALLOW_OF_CLAUSE)
9802 );
9803 }
9804};
9805
9806var nthLastOfType = nth;
9807
9808var nthOfType = nth;
9809
9810var slotted = {
9811 parse: function compoundSelector() {
9812 return new list().appendData(
9813 this.Selector()
9814 );
9815 }
9816};
9817
9818var pseudo = {
9819 'dir': dir,
9820 'has': has$1,
9821 'lang': lang,
9822 'matches': matches,
9823 'not': not,
9824 'nth-child': nthChild,
9825 'nth-last-child': nthLastChild,
9826 'nth-last-of-type': nthLastOfType,
9827 'nth-of-type': nthOfType,
9828 'slotted': slotted
9829};
9830
9831var cmpChar$2 = tokenizer.cmpChar;
9832var isNumber$2 = tokenizer.isNumber;
9833var TYPE$a = tokenizer.TYPE;
9834
9835var IDENTIFIER$7 = TYPE$a.Identifier;
9836var NUMBER$4 = TYPE$a.Number;
9837var PLUSSIGN$4 = TYPE$a.PlusSign;
9838var HYPHENMINUS$5 = TYPE$a.HyphenMinus;
9839var N$3 = 110; // 'n'.charCodeAt(0)
9840var DISALLOW_SIGN = true;
9841var ALLOW_SIGN = false;
9842
9843function checkTokenIsInteger(scanner, disallowSign) {
9844 var pos = scanner.tokenStart;
9845
9846 if (scanner.source.charCodeAt(pos) === PLUSSIGN$4 ||
9847 scanner.source.charCodeAt(pos) === HYPHENMINUS$5) {
9848 if (disallowSign) {
9849 scanner.error();
9850 }
9851 pos++;
9852 }
9853
9854 for (; pos < scanner.tokenEnd; pos++) {
9855 if (!isNumber$2(scanner.source.charCodeAt(pos))) {
9856 scanner.error('Unexpected input', pos);
9857 }
9858 }
9859}
9860
9861// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
9862var AnPlusB = {
9863 name: 'AnPlusB',
9864 structure: {
9865 a: [String, null],
9866 b: [String, null]
9867 },
9868 parse: function() {
9869 var start = this.scanner.tokenStart;
9870 var end = start;
9871 var prefix = '';
9872 var a = null;
9873 var b = null;
9874
9875 if (this.scanner.tokenType === NUMBER$4 ||
9876 this.scanner.tokenType === PLUSSIGN$4) {
9877 checkTokenIsInteger(this.scanner, ALLOW_SIGN);
9878 prefix = this.scanner.getTokenValue();
9879 this.scanner.next();
9880 end = this.scanner.tokenStart;
9881 }
9882
9883 if (this.scanner.tokenType === IDENTIFIER$7) {
9884 var bStart = this.scanner.tokenStart;
9885
9886 if (cmpChar$2(this.scanner.source, bStart, HYPHENMINUS$5)) {
9887 if (prefix === '') {
9888 prefix = '-';
9889 bStart++;
9890 } else {
9891 this.scanner.error('Unexpected hyphen minus');
9892 }
9893 }
9894
9895 if (!cmpChar$2(this.scanner.source, bStart, N$3)) {
9896 this.scanner.error();
9897 }
9898
9899 a = prefix === '' ? '1' :
9900 prefix === '+' ? '+1' :
9901 prefix === '-' ? '-1' :
9902 prefix;
9903
9904 var len = this.scanner.tokenEnd - bStart;
9905 if (len > 1) {
9906 // ..n-..
9907 if (this.scanner.source.charCodeAt(bStart + 1) !== HYPHENMINUS$5) {
9908 this.scanner.error('Unexpected input', bStart + 1);
9909 }
9910
9911 if (len > 2) {
9912 // ..n-{number}..
9913 this.scanner.tokenStart = bStart + 2;
9914 } else {
9915 // ..n- {number}
9916 this.scanner.next();
9917 this.scanner.skipSC();
9918 }
9919
9920 checkTokenIsInteger(this.scanner, DISALLOW_SIGN);
9921 b = '-' + this.scanner.getTokenValue();
9922 this.scanner.next();
9923 end = this.scanner.tokenStart;
9924 } else {
9925 prefix = '';
9926 this.scanner.next();
9927 end = this.scanner.tokenStart;
9928 this.scanner.skipSC();
9929
9930 if (this.scanner.tokenType === HYPHENMINUS$5 ||
9931 this.scanner.tokenType === PLUSSIGN$4) {
9932 prefix = this.scanner.getTokenValue();
9933 this.scanner.next();
9934 this.scanner.skipSC();
9935 }
9936
9937 if (this.scanner.tokenType === NUMBER$4) {
9938 checkTokenIsInteger(this.scanner, prefix !== '');
9939
9940 if (!isNumber$2(this.scanner.source.charCodeAt(this.scanner.tokenStart))) {
9941 prefix = this.scanner.source.charAt(this.scanner.tokenStart);
9942 this.scanner.tokenStart++;
9943 }
9944
9945 if (prefix === '') {
9946 // should be an operator before number
9947 this.scanner.error();
9948 } else if (prefix === '+') {
9949 // plus is using by default
9950 prefix = '';
9951 }
9952
9953 b = prefix + this.scanner.getTokenValue();
9954
9955 this.scanner.next();
9956 end = this.scanner.tokenStart;
9957 } else {
9958 if (prefix) {
9959 this.scanner.eat(NUMBER$4);
9960 }
9961 }
9962 }
9963 } else {
9964 if (prefix === '' || prefix === '+') { // no number
9965 this.scanner.error(
9966 'Number or identifier is expected',
9967 this.scanner.tokenStart + (
9968 this.scanner.tokenType === PLUSSIGN$4 ||
9969 this.scanner.tokenType === HYPHENMINUS$5
9970 )
9971 );
9972 }
9973
9974 b = prefix;
9975 }
9976
9977 return {
9978 type: 'AnPlusB',
9979 loc: this.getLocation(start, end),
9980 a: a,
9981 b: b
9982 };
9983 },
9984 generate: function(processChunk, node) {
9985 var a = node.a !== null && node.a !== undefined;
9986 var b = node.b !== null && node.b !== undefined;
9987
9988 if (a) {
9989 processChunk(
9990 node.a === '+1' ? '+n' :
9991 node.a === '1' ? 'n' :
9992 node.a === '-1' ? '-n' :
9993 node.a + 'n'
9994 );
9995
9996 if (b) {
9997 b = String(node.b);
9998 if (b.charAt(0) === '-' || b.charAt(0) === '+') {
9999 processChunk(b.charAt(0));
10000 processChunk(b.substr(1));
10001 } else {
10002 processChunk('+');
10003 processChunk(b);
10004 }
10005 }
10006 } else {
10007 processChunk(String(node.b));
10008 }
10009 }
10010};
10011
10012var TYPE$b = tokenizer.TYPE;
10013
10014var ATRULE$2 = TYPE$b.Atrule;
10015var SEMICOLON$1 = TYPE$b.Semicolon;
10016var LEFTCURLYBRACKET$2 = TYPE$b.LeftCurlyBracket;
10017var RIGHTCURLYBRACKET$1 = TYPE$b.RightCurlyBracket;
10018
10019function isBlockAtrule() {
10020 for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) {
10021 if (type === RIGHTCURLYBRACKET$1) {
10022 return true;
10023 }
10024
10025 if (type === LEFTCURLYBRACKET$2 ||
10026 type === ATRULE$2) {
10027 return false;
10028 }
10029 }
10030
10031 this.scanner.skip(offset);
10032 this.scanner.eat(RIGHTCURLYBRACKET$1);
10033}
10034
10035var Atrule = {
10036 name: 'Atrule',
10037 structure: {
10038 name: String,
10039 expression: ['AtruleExpression', null],
10040 block: ['Block', null]
10041 },
10042 parse: function() {
10043 var start = this.scanner.tokenStart;
10044 var name;
10045 var nameLowerCase;
10046 var expression = null;
10047 var block = null;
10048
10049 this.scanner.eat(ATRULE$2);
10050
10051 name = this.scanner.substrToCursor(start + 1);
10052 nameLowerCase = name.toLowerCase();
10053 this.scanner.skipSC();
10054
10055 expression = this.AtruleExpression(name);
10056
10057 // turn empty AtruleExpression into null
10058 if (expression.children.head === null) {
10059 expression = null;
10060 }
10061
10062 this.scanner.skipSC();
10063
10064 if (this.atrule.hasOwnProperty(nameLowerCase)) {
10065 if (typeof this.atrule[nameLowerCase].block === 'function') {
10066 if (this.scanner.tokenType !== LEFTCURLYBRACKET$2) {
10067 // FIXME: make tolerant
10068 this.scanner.error('Curly bracket is expected');
10069 }
10070
10071 block = this.atrule[nameLowerCase].block.call(this);
10072 } else {
10073 if (!this.tolerant || !this.scanner.eof) {
10074 this.scanner.eat(SEMICOLON$1);
10075 }
10076 }
10077 } else {
10078 switch (this.scanner.tokenType) {
10079 case SEMICOLON$1:
10080 this.scanner.next();
10081 break;
10082
10083 case LEFTCURLYBRACKET$2:
10084 // TODO: should consume block content as Raw?
10085 block = this.Block(isBlockAtrule.call(this) ? this.Declaration : this.Rule);
10086 break;
10087
10088 default:
10089 if (!this.tolerant) {
10090 this.scanner.error('Semicolon or block is expected');
10091 }
10092 }
10093 }
10094
10095 return {
10096 type: 'Atrule',
10097 loc: this.getLocation(start, this.scanner.tokenStart),
10098 name: name,
10099 expression: expression,
10100 block: block
10101 };
10102 },
10103 generate: function(processChunk, node) {
10104 processChunk('@');
10105 processChunk(node.name);
10106
10107 if (node.expression !== null) {
10108 processChunk(' ');
10109 this.generate(processChunk, node.expression);
10110 }
10111
10112 if (node.block) {
10113 this.generate(processChunk, node.block);
10114 } else {
10115 processChunk(';');
10116 }
10117 },
10118 walkContext: 'atrule'
10119};
10120
10121var TYPE$c = tokenizer.TYPE;
10122var SEMICOLON$2 = TYPE$c.Semicolon;
10123var LEFTCURLYBRACKET$3 = TYPE$c.LeftCurlyBracket;
10124
10125function consumeRaw$1(startToken) {
10126 return new list().appendData(
10127 this.Raw(startToken, SEMICOLON$2, LEFTCURLYBRACKET$3, false, true)
10128 );
10129}
10130
10131function consumeDefaultSequence() {
10132 return this.readSequence(this.scope.AtruleExpression);
10133}
10134
10135var AtruleExpression = {
10136 name: 'AtruleExpression',
10137 structure: {
10138 children: [[]]
10139 },
10140 parse: function(name) {
10141 var children = null;
10142 var startToken = this.scanner.currentToken;
10143
10144 if (name !== null) {
10145 name = name.toLowerCase();
10146 }
10147
10148 if (this.parseAtruleExpression) {
10149 // custom consumer
10150 if (this.atrule.hasOwnProperty(name)) {
10151 if (typeof this.atrule[name].expression === 'function') {
10152 children = this.tolerantParse(this.atrule[name].expression, consumeRaw$1);
10153 }
10154 } else {
10155 // default consumer
10156 this.scanner.skipSC();
10157 children = this.tolerantParse(consumeDefaultSequence, consumeRaw$1);
10158 }
10159
10160 if (this.tolerant) {
10161 if (this.scanner.eof || (this.scanner.tokenType !== SEMICOLON$2 && this.scanner.tokenType !== LEFTCURLYBRACKET$3)) {
10162 children = consumeRaw$1.call(this, startToken);
10163 }
10164 }
10165 } else {
10166 children = consumeRaw$1.call(this, startToken);
10167 }
10168
10169 if (children === null) {
10170 children = new list();
10171 }
10172
10173 return {
10174 type: 'AtruleExpression',
10175 loc: this.getLocationFromList(children),
10176 children: children
10177 };
10178 },
10179 generate: function(processChunk, node) {
10180 this.each(processChunk, node);
10181 },
10182 walkContext: 'atruleExpression'
10183};
10184
10185var TYPE$d = tokenizer.TYPE;
10186
10187var IDENTIFIER$8 = TYPE$d.Identifier;
10188var STRING$4 = TYPE$d.String;
10189var DOLLARSIGN = TYPE$d.DollarSign;
10190var ASTERISK$2 = TYPE$d.Asterisk;
10191var COLON$2 = TYPE$d.Colon;
10192var EQUALSSIGN = TYPE$d.EqualsSign;
10193var LEFTSQUAREBRACKET$3 = TYPE$d.LeftSquareBracket;
10194var RIGHTSQUAREBRACKET$1 = TYPE$d.RightSquareBracket;
10195var CIRCUMFLEXACCENT = TYPE$d.CircumflexAccent;
10196var VERTICALLINE$1 = TYPE$d.VerticalLine;
10197var TILDE$1 = TYPE$d.Tilde;
10198
10199function getAttributeName() {
10200 if (this.scanner.eof) {
10201 this.scanner.error('Unexpected end of input');
10202 }
10203
10204 var start = this.scanner.tokenStart;
10205 var expectIdentifier = false;
10206 var checkColon = true;
10207
10208 if (this.scanner.tokenType === ASTERISK$2) {
10209 expectIdentifier = true;
10210 checkColon = false;
10211 this.scanner.next();
10212 } else if (this.scanner.tokenType !== VERTICALLINE$1) {
10213 this.scanner.eat(IDENTIFIER$8);
10214 }
10215
10216 if (this.scanner.tokenType === VERTICALLINE$1) {
10217 if (this.scanner.lookupType(1) !== EQUALSSIGN) {
10218 this.scanner.next();
10219 this.scanner.eat(IDENTIFIER$8);
10220 } else if (expectIdentifier) {
10221 this.scanner.error('Identifier is expected', this.scanner.tokenEnd);
10222 }
10223 } else if (expectIdentifier) {
10224 this.scanner.error('Vertical line is expected');
10225 }
10226
10227 if (checkColon && this.scanner.tokenType === COLON$2) {
10228 this.scanner.next();
10229 this.scanner.eat(IDENTIFIER$8);
10230 }
10231
10232 return {
10233 type: 'Identifier',
10234 loc: this.getLocation(start, this.scanner.tokenStart),
10235 name: this.scanner.substrToCursor(start)
10236 };
10237}
10238
10239function getOperator() {
10240 var start = this.scanner.tokenStart;
10241 var tokenType = this.scanner.tokenType;
10242
10243 if (tokenType !== EQUALSSIGN && // =
10244 tokenType !== TILDE$1 && // ~=
10245 tokenType !== CIRCUMFLEXACCENT && // ^=
10246 tokenType !== DOLLARSIGN && // $=
10247 tokenType !== ASTERISK$2 && // *=
10248 tokenType !== VERTICALLINE$1 // |=
10249 ) {
10250 this.scanner.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
10251 }
10252
10253 if (tokenType === EQUALSSIGN) {
10254 this.scanner.next();
10255 } else {
10256 this.scanner.next();
10257 this.scanner.eat(EQUALSSIGN);
10258 }
10259
10260 return this.scanner.substrToCursor(start);
10261}
10262
10263// '[' S* attrib_name ']'
10264// '[' S* attrib_name S* attrib_matcher S* [ IDENT | STRING ] S* attrib_flags? S* ']'
10265var AttributeSelector = {
10266 name: 'AttributeSelector',
10267 structure: {
10268 name: 'Identifier',
10269 matcher: [String, null],
10270 value: ['String', 'Identifier', null],
10271 flags: [String, null]
10272 },
10273 parse: function() {
10274 var start = this.scanner.tokenStart;
10275 var name;
10276 var matcher = null;
10277 var value = null;
10278 var flags = null;
10279
10280 this.scanner.eat(LEFTSQUAREBRACKET$3);
10281 this.scanner.skipSC();
10282
10283 name = getAttributeName.call(this);
10284 this.scanner.skipSC();
10285
10286 if (this.scanner.tokenType !== RIGHTSQUAREBRACKET$1) {
10287 // avoid case `[name i]`
10288 if (this.scanner.tokenType !== IDENTIFIER$8) {
10289 matcher = getOperator.call(this);
10290
10291 this.scanner.skipSC();
10292
10293 value = this.scanner.tokenType === STRING$4
10294 ? this.String()
10295 : this.Identifier();
10296
10297 this.scanner.skipSC();
10298 }
10299
10300 // attribute flags
10301 if (this.scanner.tokenType === IDENTIFIER$8) {
10302 flags = this.scanner.getTokenValue();
10303 this.scanner.next();
10304
10305 this.scanner.skipSC();
10306 }
10307 }
10308
10309 this.scanner.eat(RIGHTSQUAREBRACKET$1);
10310
10311 return {
10312 type: 'AttributeSelector',
10313 loc: this.getLocation(start, this.scanner.tokenStart),
10314 name: name,
10315 matcher: matcher,
10316 value: value,
10317 flags: flags
10318 };
10319 },
10320 generate: function(processChunk, node) {
10321 var flagsPrefix = ' ';
10322
10323 processChunk('[');
10324 this.generate(processChunk, node.name);
10325
10326 if (node.matcher !== null) {
10327 processChunk(node.matcher);
10328
10329 if (node.value !== null) {
10330 this.generate(processChunk, node.value);
10331
10332 // space between string and flags is not required
10333 if (node.value.type === 'String') {
10334 flagsPrefix = '';
10335 }
10336 }
10337 }
10338
10339 if (node.flags !== null) {
10340 processChunk(flagsPrefix);
10341 processChunk(node.flags);
10342 }
10343
10344 processChunk(']');
10345 }
10346};
10347
10348var TYPE$e = tokenizer.TYPE;
10349
10350var WHITESPACE$4 = TYPE$e.WhiteSpace;
10351var COMMENT$4 = TYPE$e.Comment;
10352var SEMICOLON$3 = TYPE$e.Semicolon;
10353var ATRULE$3 = TYPE$e.Atrule;
10354var LEFTCURLYBRACKET$4 = TYPE$e.LeftCurlyBracket;
10355var RIGHTCURLYBRACKET$2 = TYPE$e.RightCurlyBracket;
10356
10357function consumeRaw$2(startToken) {
10358 return this.Raw(startToken, 0, SEMICOLON$3, true, true);
10359}
10360
10361var Block = {
10362 name: 'Block',
10363 structure: {
10364 children: [['Atrule', 'Rule', 'Declaration']]
10365 },
10366 parse: function(defaultConsumer) {
10367 if (!defaultConsumer) {
10368 defaultConsumer = this.Declaration;
10369 }
10370
10371 var start = this.scanner.tokenStart;
10372 var children = new list();
10373
10374 this.scanner.eat(LEFTCURLYBRACKET$4);
10375
10376 scan:
10377 while (!this.scanner.eof) {
10378 switch (this.scanner.tokenType) {
10379 case RIGHTCURLYBRACKET$2:
10380 break scan;
10381
10382 case WHITESPACE$4:
10383 case COMMENT$4:
10384 case SEMICOLON$3:
10385 this.scanner.next();
10386 break;
10387
10388 case ATRULE$3:
10389 children.appendData(this.tolerantParse(this.Atrule, consumeRaw$2));
10390 break;
10391
10392 default:
10393 children.appendData(this.tolerantParse(defaultConsumer, consumeRaw$2));
10394 }
10395 }
10396
10397 if (!this.tolerant || !this.scanner.eof) {
10398 this.scanner.eat(RIGHTCURLYBRACKET$2);
10399 }
10400
10401 return {
10402 type: 'Block',
10403 loc: this.getLocation(start, this.scanner.tokenStart),
10404 children: children
10405 };
10406 },
10407 generate: function(processChunk, node) {
10408 processChunk('{');
10409 this.each(processChunk, node);
10410 processChunk('}');
10411 },
10412 walkContext: 'block'
10413};
10414
10415var TYPE$f = tokenizer.TYPE;
10416var LEFTSQUAREBRACKET$4 = TYPE$f.LeftSquareBracket;
10417var RIGHTSQUAREBRACKET$2 = TYPE$f.RightSquareBracket;
10418
10419// currently only Grid Layout uses square brackets, but left it universal
10420// https://drafts.csswg.org/css-grid/#track-sizing
10421// [ ident* ]
10422var Brackets = {
10423 name: 'Brackets',
10424 structure: {
10425 children: [[]]
10426 },
10427 parse: function(readSequence, recognizer) {
10428 var start = this.scanner.tokenStart;
10429 var children = null;
10430
10431 this.scanner.eat(LEFTSQUAREBRACKET$4);
10432 children = readSequence.call(this, recognizer);
10433 this.scanner.eat(RIGHTSQUAREBRACKET$2);
10434
10435 return {
10436 type: 'Brackets',
10437 loc: this.getLocation(start, this.scanner.tokenStart),
10438 children: children
10439 };
10440 },
10441 generate: function(processChunk, node) {
10442 processChunk('[');
10443 this.each(processChunk, node);
10444 processChunk(']');
10445 }
10446};
10447
10448var CDC$2 = tokenizer.TYPE.CDC;
10449
10450var CDC_1 = {
10451 name: 'CDC',
10452 structure: [],
10453 parse: function() {
10454 var start = this.scanner.tokenStart;
10455
10456 this.scanner.eat(CDC$2); // -->
10457
10458 return {
10459 type: 'CDC',
10460 loc: this.getLocation(start, this.scanner.tokenStart)
10461 };
10462 },
10463 generate: function(processChunk) {
10464 processChunk('-->');
10465 }
10466};
10467
10468var CDO$2 = tokenizer.TYPE.CDO;
10469
10470var CDO_1 = {
10471 name: 'CDO',
10472 structure: [],
10473 parse: function() {
10474 var start = this.scanner.tokenStart;
10475
10476 this.scanner.eat(CDO$2); // <!--
10477
10478 return {
10479 type: 'CDO',
10480 loc: this.getLocation(start, this.scanner.tokenStart)
10481 };
10482 },
10483 generate: function(processChunk) {
10484 processChunk('<!--');
10485 }
10486};
10487
10488var TYPE$g = tokenizer.TYPE;
10489var IDENTIFIER$9 = TYPE$g.Identifier;
10490var FULLSTOP$3 = TYPE$g.FullStop;
10491
10492// '.' ident
10493var ClassSelector = {
10494 name: 'ClassSelector',
10495 structure: {
10496 name: String
10497 },
10498 parse: function() {
10499 this.scanner.eat(FULLSTOP$3);
10500
10501 return {
10502 type: 'ClassSelector',
10503 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10504 name: this.scanner.consume(IDENTIFIER$9)
10505 };
10506 },
10507 generate: function(processChunk, node) {
10508 processChunk('.');
10509 processChunk(node.name);
10510 }
10511};
10512
10513var TYPE$h = tokenizer.TYPE;
10514
10515var PLUSSIGN$5 = TYPE$h.PlusSign;
10516var SOLIDUS$2 = TYPE$h.Solidus;
10517var GREATERTHANSIGN$2 = TYPE$h.GreaterThanSign;
10518var TILDE$2 = TYPE$h.Tilde;
10519
10520// + | > | ~ | /deep/
10521var Combinator = {
10522 name: 'Combinator',
10523 structure: {
10524 name: String
10525 },
10526 parse: function() {
10527 var start = this.scanner.tokenStart;
10528
10529 switch (this.scanner.tokenType) {
10530 case GREATERTHANSIGN$2:
10531 case PLUSSIGN$5:
10532 case TILDE$2:
10533 this.scanner.next();
10534 break;
10535
10536 case SOLIDUS$2:
10537 this.scanner.next();
10538 this.scanner.expectIdentifier('deep');
10539 this.scanner.eat(SOLIDUS$2);
10540 break;
10541
10542 default:
10543 this.scanner.error('Combinator is expected');
10544 }
10545
10546 return {
10547 type: 'Combinator',
10548 loc: this.getLocation(start, this.scanner.tokenStart),
10549 name: this.scanner.substrToCursor(start)
10550 };
10551 },
10552 generate: function(processChunk, node) {
10553 processChunk(node.name);
10554 }
10555};
10556
10557var TYPE$i = tokenizer.TYPE;
10558
10559var ASTERISK$3 = TYPE$i.Asterisk;
10560var SOLIDUS$3 = TYPE$i.Solidus;
10561
10562// '/*' .* '*/'
10563var Comment = {
10564 name: 'Comment',
10565 structure: {
10566 value: String
10567 },
10568 parse: function() {
10569 var start = this.scanner.tokenStart;
10570 var end = this.scanner.tokenEnd;
10571
10572 if ((end - start + 2) >= 2 &&
10573 this.scanner.source.charCodeAt(end - 2) === ASTERISK$3 &&
10574 this.scanner.source.charCodeAt(end - 1) === SOLIDUS$3) {
10575 end -= 2;
10576 }
10577
10578 this.scanner.next();
10579
10580 return {
10581 type: 'Comment',
10582 loc: this.getLocation(start, this.scanner.tokenStart),
10583 value: this.scanner.source.substring(start + 2, end)
10584 };
10585 },
10586 generate: function(processChunk, node) {
10587 processChunk('/*');
10588 processChunk(node.value);
10589 processChunk('*/');
10590 }
10591};
10592
10593var TYPE$j = tokenizer.TYPE;
10594
10595var IDENTIFIER$a = TYPE$j.Identifier;
10596var COLON$3 = TYPE$j.Colon;
10597var EXCLAMATIONMARK$2 = TYPE$j.ExclamationMark;
10598var SOLIDUS$4 = TYPE$j.Solidus;
10599var ASTERISK$4 = TYPE$j.Asterisk;
10600var DOLLARSIGN$1 = TYPE$j.DollarSign;
10601var HYPHENMINUS$6 = TYPE$j.HyphenMinus;
10602var SEMICOLON$4 = TYPE$j.Semicolon;
10603var RIGHTCURLYBRACKET$3 = TYPE$j.RightCurlyBracket;
10604var RIGHTPARENTHESIS$1 = TYPE$j.RightParenthesis;
10605var PLUSSIGN$6 = TYPE$j.PlusSign;
10606var NUMBERSIGN$2 = TYPE$j.NumberSign;
10607
10608var Declaration = {
10609 name: 'Declaration',
10610 structure: {
10611 important: [Boolean, String],
10612 property: String,
10613 value: ['Value', 'Raw']
10614 },
10615 parse: function() {
10616 var start = this.scanner.tokenStart;
10617 var property = readProperty.call(this);
10618 var important = false;
10619 var value;
10620
10621 this.scanner.skipSC();
10622 this.scanner.eat(COLON$3);
10623
10624 if (isCustomProperty(property) ? this.parseCustomProperty : this.parseValue) {
10625 value = this.Value(property);
10626 } else {
10627 value = this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$2, SEMICOLON$4, false, false);
10628 }
10629
10630 if (this.scanner.tokenType === EXCLAMATIONMARK$2) {
10631 important = getImportant(this.scanner);
10632 this.scanner.skipSC();
10633 }
10634
10635 // TODO: include or not to include semicolon to range?
10636 // if (this.scanner.tokenType === SEMICOLON) {
10637 // this.scanner.next();
10638 // }
10639
10640 if (!this.scanner.eof &&
10641 this.scanner.tokenType !== SEMICOLON$4 &&
10642 this.scanner.tokenType !== RIGHTPARENTHESIS$1 &&
10643 this.scanner.tokenType !== RIGHTCURLYBRACKET$3) {
10644 this.scanner.error();
10645 }
10646
10647 return {
10648 type: 'Declaration',
10649 loc: this.getLocation(start, this.scanner.tokenStart),
10650 important: important,
10651 property: property,
10652 value: value
10653 };
10654 },
10655 generate: function(processChunk, node, item) {
10656 processChunk(node.property);
10657 processChunk(':');
10658 this.generate(processChunk, node.value);
10659
10660 if (node.important) {
10661 processChunk(node.important === true ? '!important' : '!' + node.important);
10662 }
10663
10664 if (item && item.next) {
10665 processChunk(';');
10666 }
10667 },
10668 walkContext: 'declaration'
10669};
10670
10671function isCustomProperty(name) {
10672 return name.length >= 2 &&
10673 name.charCodeAt(0) === HYPHENMINUS$6 &&
10674 name.charCodeAt(1) === HYPHENMINUS$6;
10675}
10676
10677function readProperty() {
10678 var start = this.scanner.tokenStart;
10679 var prefix = 0;
10680
10681 // hacks
10682 switch (this.scanner.tokenType) {
10683 case ASTERISK$4:
10684 case DOLLARSIGN$1:
10685 case PLUSSIGN$6:
10686 case NUMBERSIGN$2:
10687 prefix = 1;
10688 break;
10689
10690 // TODO: not sure we should support this hack
10691 case SOLIDUS$4:
10692 prefix = this.scanner.lookupType(1) === SOLIDUS$4 ? 2 : 1;
10693 break;
10694 }
10695
10696 if (this.scanner.lookupType(prefix) === HYPHENMINUS$6) {
10697 prefix++;
10698 }
10699
10700 if (prefix) {
10701 this.scanner.skip(prefix);
10702 }
10703
10704 this.scanner.eat(IDENTIFIER$a);
10705
10706 return this.scanner.substrToCursor(start);
10707}
10708
10709// ! ws* important
10710function getImportant(scanner) {
10711 scanner.eat(EXCLAMATIONMARK$2);
10712 scanner.skipSC();
10713
10714 var important = scanner.consume(IDENTIFIER$a);
10715
10716 // store original value in case it differ from `important`
10717 // for better original source restoring and hacks like `!ie` support
10718 return important === 'important' ? true : important;
10719}
10720
10721var TYPE$k = tokenizer.TYPE;
10722
10723var WHITESPACE$5 = TYPE$k.WhiteSpace;
10724var COMMENT$5 = TYPE$k.Comment;
10725var SEMICOLON$5 = TYPE$k.Semicolon;
10726
10727function consumeRaw$3(startToken) {
10728 return this.Raw(startToken, 0, SEMICOLON$5, true, true);
10729}
10730
10731var DeclarationList = {
10732 name: 'DeclarationList',
10733 structure: {
10734 children: [['Declaration']]
10735 },
10736 parse: function() {
10737 var children = new list();
10738
10739
10740 while (!this.scanner.eof) {
10741 switch (this.scanner.tokenType) {
10742 case WHITESPACE$5:
10743 case COMMENT$5:
10744 case SEMICOLON$5:
10745 this.scanner.next();
10746 break;
10747
10748 default:
10749 children.appendData(this.tolerantParse(this.Declaration, consumeRaw$3));
10750 }
10751 }
10752
10753 return {
10754 type: 'DeclarationList',
10755 loc: this.getLocationFromList(children),
10756 children: children
10757 };
10758 },
10759 generate: function(processChunk, node) {
10760 this.each(processChunk, node);
10761 }
10762};
10763
10764var NUMBER$5 = tokenizer.TYPE.Number;
10765
10766// special reader for units to avoid adjoined IE hacks (i.e. '1px\9')
10767function readUnit(scanner) {
10768 var unit = scanner.getTokenValue();
10769 var backSlashPos = unit.indexOf('\\');
10770
10771 if (backSlashPos > 0) {
10772 // patch token offset
10773 scanner.tokenStart += backSlashPos;
10774
10775 // return part before backslash
10776 return unit.substring(0, backSlashPos);
10777 }
10778
10779 // no backslash in unit name
10780 scanner.next();
10781
10782 return unit;
10783}
10784
10785// number ident
10786var Dimension = {
10787 name: 'Dimension',
10788 structure: {
10789 value: String,
10790 unit: String
10791 },
10792 parse: function() {
10793 var start = this.scanner.tokenStart;
10794 var value = this.scanner.consume(NUMBER$5);
10795 var unit = readUnit(this.scanner);
10796
10797 return {
10798 type: 'Dimension',
10799 loc: this.getLocation(start, this.scanner.tokenStart),
10800 value: value,
10801 unit: unit
10802 };
10803 },
10804 generate: function(processChunk, node) {
10805 processChunk(node.value);
10806 processChunk(node.unit);
10807 }
10808};
10809
10810var TYPE$l = tokenizer.TYPE;
10811var RIGHTPARENTHESIS$2 = TYPE$l.RightParenthesis;
10812
10813// <function-token> <sequence> ')'
10814var _Function = {
10815 name: 'Function',
10816 structure: {
10817 name: String,
10818 children: [[]]
10819 },
10820 parse: function(readSequence, recognizer) {
10821 var start = this.scanner.tokenStart;
10822 var name = this.scanner.consumeFunctionName();
10823 var nameLowerCase = name.toLowerCase();
10824 var children;
10825
10826 children = recognizer.hasOwnProperty(nameLowerCase)
10827 ? recognizer[nameLowerCase].call(this, recognizer)
10828 : readSequence.call(this, recognizer);
10829
10830 this.scanner.eat(RIGHTPARENTHESIS$2);
10831
10832 return {
10833 type: 'Function',
10834 loc: this.getLocation(start, this.scanner.tokenStart),
10835 name: name,
10836 children: children
10837 };
10838 },
10839 generate: function(processChunk, node) {
10840 processChunk(node.name);
10841 processChunk('(');
10842 this.each(processChunk, node);
10843 processChunk(')');
10844 },
10845 walkContext: 'function'
10846};
10847
10848var isHex$1 = tokenizer.isHex;
10849var TYPE$m = tokenizer.TYPE;
10850
10851var IDENTIFIER$b = TYPE$m.Identifier;
10852var NUMBER$6 = TYPE$m.Number;
10853var NUMBERSIGN$3 = TYPE$m.NumberSign;
10854
10855function consumeHexSequence(scanner, required) {
10856 if (!isHex$1(scanner.source.charCodeAt(scanner.tokenStart))) {
10857 if (required) {
10858 scanner.error('Unexpected input', scanner.tokenStart);
10859 } else {
10860 return;
10861 }
10862 }
10863
10864 for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
10865 var code = scanner.source.charCodeAt(pos);
10866
10867 // break on non-hex char
10868 if (!isHex$1(code)) {
10869 // break token, exclude symbol
10870 scanner.tokenStart = pos;
10871 return;
10872 }
10873 }
10874
10875 // token is full hex sequence, go to next token
10876 scanner.next();
10877}
10878
10879// # ident
10880var HexColor = {
10881 name: 'HexColor',
10882 structure: {
10883 value: String
10884 },
10885 parse: function() {
10886 var start = this.scanner.tokenStart;
10887
10888 this.scanner.eat(NUMBERSIGN$3);
10889
10890
10891 switch (this.scanner.tokenType) {
10892 case NUMBER$6:
10893 consumeHexSequence(this.scanner, true);
10894
10895 // if token is identifier then number consists of hex only,
10896 // try to add identifier to result
10897 if (this.scanner.tokenType === IDENTIFIER$b) {
10898 consumeHexSequence(this.scanner, false);
10899 }
10900
10901 break;
10902
10903 case IDENTIFIER$b:
10904 consumeHexSequence(this.scanner, true);
10905 break;
10906
10907 default:
10908 this.scanner.error('Number or identifier is expected');
10909 }
10910
10911 return {
10912 type: 'HexColor',
10913 loc: this.getLocation(start, this.scanner.tokenStart),
10914 value: this.scanner.substrToCursor(start + 1) // skip #
10915 };
10916 },
10917 generate: function(processChunk, node) {
10918 processChunk('#');
10919 processChunk(node.value);
10920 }
10921};
10922
10923var TYPE$n = tokenizer.TYPE;
10924var IDENTIFIER$c = TYPE$n.Identifier;
10925
10926var Identifier = {
10927 name: 'Identifier',
10928 structure: {
10929 name: String
10930 },
10931 parse: function() {
10932 return {
10933 type: 'Identifier',
10934 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
10935 name: this.scanner.consume(IDENTIFIER$c)
10936 };
10937 },
10938 generate: function(processChunk, node) {
10939 processChunk(node.name);
10940 }
10941};
10942
10943var TYPE$o = tokenizer.TYPE;
10944var IDENTIFIER$d = TYPE$o.Identifier;
10945var NUMBERSIGN$4 = TYPE$o.NumberSign;
10946
10947// '#' ident
10948var IdSelector = {
10949 name: 'IdSelector',
10950 structure: {
10951 name: String
10952 },
10953 parse: function() {
10954 this.scanner.eat(NUMBERSIGN$4);
10955
10956 return {
10957 type: 'IdSelector',
10958 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10959 name: this.scanner.consume(IDENTIFIER$d)
10960 };
10961 },
10962 generate: function(processChunk, node) {
10963 processChunk('#');
10964 processChunk(node.name);
10965 }
10966};
10967
10968var TYPE$p = tokenizer.TYPE;
10969
10970var IDENTIFIER$e = TYPE$p.Identifier;
10971var NUMBER$7 = TYPE$p.Number;
10972var LEFTPARENTHESIS$4 = TYPE$p.LeftParenthesis;
10973var RIGHTPARENTHESIS$3 = TYPE$p.RightParenthesis;
10974var COLON$4 = TYPE$p.Colon;
10975var SOLIDUS$5 = TYPE$p.Solidus;
10976
10977var MediaFeature = {
10978 name: 'MediaFeature',
10979 structure: {
10980 name: String,
10981 value: ['Identifier', 'Number', 'Dimension', 'Ratio', null]
10982 },
10983 parse: function() {
10984 var start = this.scanner.tokenStart;
10985 var name;
10986 var value = null;
10987
10988 this.scanner.eat(LEFTPARENTHESIS$4);
10989 this.scanner.skipSC();
10990
10991 name = this.scanner.consume(IDENTIFIER$e);
10992 this.scanner.skipSC();
10993
10994 if (this.scanner.tokenType !== RIGHTPARENTHESIS$3) {
10995 this.scanner.eat(COLON$4);
10996 this.scanner.skipSC();
10997
10998 switch (this.scanner.tokenType) {
10999 case NUMBER$7:
11000 if (this.scanner.lookupType(1) === IDENTIFIER$e) {
11001 value = this.Dimension();
11002 } else if (this.scanner.lookupNonWSType(1) === SOLIDUS$5) {
11003 value = this.Ratio();
11004 } else {
11005 value = this.Number();
11006 }
11007
11008 break;
11009
11010 case IDENTIFIER$e:
11011 value = this.Identifier();
11012
11013 break;
11014
11015 default:
11016 this.scanner.error('Number, dimension, ratio or identifier is expected');
11017 }
11018
11019 this.scanner.skipSC();
11020 }
11021
11022 this.scanner.eat(RIGHTPARENTHESIS$3);
11023
11024 return {
11025 type: 'MediaFeature',
11026 loc: this.getLocation(start, this.scanner.tokenStart),
11027 name: name,
11028 value: value
11029 };
11030 },
11031 generate: function(processChunk, node) {
11032 processChunk('(');
11033 processChunk(node.name);
11034 if (node.value !== null) {
11035 processChunk(':');
11036 this.generate(processChunk, node.value);
11037 }
11038 processChunk(')');
11039 }
11040};
11041
11042var TYPE$q = tokenizer.TYPE;
11043
11044var WHITESPACE$6 = TYPE$q.WhiteSpace;
11045var COMMENT$6 = TYPE$q.Comment;
11046var IDENTIFIER$f = TYPE$q.Identifier;
11047var LEFTPARENTHESIS$5 = TYPE$q.LeftParenthesis;
11048
11049var MediaQuery = {
11050 name: 'MediaQuery',
11051 structure: {
11052 children: [['Identifier', 'MediaFeature', 'WhiteSpace']]
11053 },
11054 parse: function() {
11055 this.scanner.skipSC();
11056
11057 var children = new list();
11058 var child = null;
11059 var space = null;
11060
11061 scan:
11062 while (!this.scanner.eof) {
11063 switch (this.scanner.tokenType) {
11064 case COMMENT$6:
11065 this.scanner.next();
11066 continue;
11067
11068 case WHITESPACE$6:
11069 space = this.WhiteSpace();
11070 continue;
11071
11072 case IDENTIFIER$f:
11073 child = this.Identifier();
11074 break;
11075
11076 case LEFTPARENTHESIS$5:
11077 child = this.MediaFeature();
11078 break;
11079
11080 default:
11081 break scan;
11082 }
11083
11084 if (space !== null) {
11085 children.appendData(space);
11086 space = null;
11087 }
11088
11089 children.appendData(child);
11090 }
11091
11092 if (child === null) {
11093 this.scanner.error('Identifier or parenthesis is expected');
11094 }
11095
11096 return {
11097 type: 'MediaQuery',
11098 loc: this.getLocationFromList(children),
11099 children: children
11100 };
11101 },
11102 generate: function(processChunk, node) {
11103 this.each(processChunk, node);
11104 }
11105};
11106
11107var COMMA$2 = tokenizer.TYPE.Comma;
11108
11109var MediaQueryList = {
11110 name: 'MediaQueryList',
11111 structure: {
11112 children: [['MediaQuery']]
11113 },
11114 parse: function(relative) {
11115 var children = new list();
11116
11117 this.scanner.skipSC();
11118
11119 while (!this.scanner.eof) {
11120 children.appendData(this.MediaQuery(relative));
11121
11122 if (this.scanner.tokenType !== COMMA$2) {
11123 break;
11124 }
11125
11126 this.scanner.next();
11127 }
11128
11129 return {
11130 type: 'MediaQueryList',
11131 loc: this.getLocationFromList(children),
11132 children: children
11133 };
11134 },
11135 generate: function(processChunk, node) {
11136 this.eachComma(processChunk, node);
11137 }
11138};
11139
11140// https://drafts.csswg.org/css-syntax-3/#the-anb-type
11141var Nth = {
11142 name: 'Nth',
11143 structure: {
11144 nth: ['AnPlusB', 'Identifier'],
11145 selector: ['SelectorList', null]
11146 },
11147 parse: function(allowOfClause) {
11148 this.scanner.skipSC();
11149
11150 var start = this.scanner.tokenStart;
11151 var end = start;
11152 var selector = null;
11153 var query;
11154
11155 if (this.scanner.lookupValue(0, 'odd') || this.scanner.lookupValue(0, 'even')) {
11156 query = this.Identifier();
11157 } else {
11158 query = this.AnPlusB();
11159 }
11160
11161 this.scanner.skipSC();
11162
11163 if (allowOfClause && this.scanner.lookupValue(0, 'of')) {
11164 this.scanner.next();
11165
11166 selector = this.SelectorList();
11167
11168 if (this.needPositions) {
11169 end = selector.children.last().loc.end.offset;
11170 }
11171 } else {
11172 if (this.needPositions) {
11173 end = query.loc.end.offset;
11174 }
11175 }
11176
11177 return {
11178 type: 'Nth',
11179 loc: this.getLocation(start, end),
11180 nth: query,
11181 selector: selector
11182 };
11183 },
11184 generate: function(processChunk, node) {
11185 this.generate(processChunk, node.nth);
11186 if (node.selector !== null) {
11187 processChunk(' of ');
11188 this.generate(processChunk, node.selector);
11189 }
11190 }
11191};
11192
11193var NUMBER$8 = tokenizer.TYPE.Number;
11194
11195var _Number = {
11196 name: 'Number',
11197 structure: {
11198 value: String
11199 },
11200 parse: function() {
11201 return {
11202 type: 'Number',
11203 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11204 value: this.scanner.consume(NUMBER$8)
11205 };
11206 },
11207 generate: function(processChunk, node) {
11208 processChunk(node.value);
11209 }
11210};
11211
11212// '/' | '*' | ',' | ':' | '+' | '-'
11213var Operator = {
11214 name: 'Operator',
11215 structure: {
11216 value: String
11217 },
11218 parse: function() {
11219 var start = this.scanner.tokenStart;
11220
11221 this.scanner.next();
11222
11223 return {
11224 type: 'Operator',
11225 loc: this.getLocation(start, this.scanner.tokenStart),
11226 value: this.scanner.substrToCursor(start)
11227 };
11228 },
11229 generate: function(processChunk, node) {
11230 processChunk(node.value);
11231 }
11232};
11233
11234var TYPE$r = tokenizer.TYPE;
11235var LEFTPARENTHESIS$6 = TYPE$r.LeftParenthesis;
11236var RIGHTPARENTHESIS$4 = TYPE$r.RightParenthesis;
11237
11238var Parentheses = {
11239 name: 'Parentheses',
11240 structure: {
11241 children: [[]]
11242 },
11243 parse: function(readSequence, recognizer) {
11244 var start = this.scanner.tokenStart;
11245 var children = null;
11246
11247 this.scanner.eat(LEFTPARENTHESIS$6);
11248 children = readSequence.call(this, recognizer);
11249 this.scanner.eat(RIGHTPARENTHESIS$4);
11250
11251 return {
11252 type: 'Parentheses',
11253 loc: this.getLocation(start, this.scanner.tokenStart),
11254 children: children
11255 };
11256 },
11257 generate: function(processChunk, node) {
11258 processChunk('(');
11259 this.each(processChunk, node);
11260 processChunk(')');
11261 }
11262};
11263
11264var TYPE$s = tokenizer.TYPE;
11265
11266var NUMBER$9 = TYPE$s.Number;
11267var PERCENTSIGN$1 = TYPE$s.PercentSign;
11268
11269var Percentage = {
11270 name: 'Percentage',
11271 structure: {
11272 value: String
11273 },
11274 parse: function() {
11275 var start = this.scanner.tokenStart;
11276 var number = this.scanner.consume(NUMBER$9);
11277
11278 this.scanner.eat(PERCENTSIGN$1);
11279
11280 return {
11281 type: 'Percentage',
11282 loc: this.getLocation(start, this.scanner.tokenStart),
11283 value: number
11284 };
11285 },
11286 generate: function(processChunk, node) {
11287 processChunk(node.value);
11288 processChunk('%');
11289 }
11290};
11291
11292var TYPE$t = tokenizer.TYPE;
11293
11294var IDENTIFIER$g = TYPE$t.Identifier;
11295var FUNCTION$4 = TYPE$t.Function;
11296var COLON$5 = TYPE$t.Colon;
11297var RIGHTPARENTHESIS$5 = TYPE$t.RightParenthesis;
11298
11299// : ident [ '(' .. ')' ]?
11300var PseudoClassSelector = {
11301 name: 'PseudoClassSelector',
11302 structure: {
11303 name: String,
11304 children: [['Raw'], null]
11305 },
11306 parse: function() {
11307 var start = this.scanner.tokenStart;
11308 var children = null;
11309 var name;
11310 var nameLowerCase;
11311
11312 this.scanner.eat(COLON$5);
11313
11314 if (this.scanner.tokenType === FUNCTION$4) {
11315 name = this.scanner.consumeFunctionName();
11316 nameLowerCase = name.toLowerCase();
11317
11318 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11319 this.scanner.skipSC();
11320 children = this.pseudo[nameLowerCase].call(this);
11321 this.scanner.skipSC();
11322 } else {
11323 children = new list().appendData(
11324 this.Raw(this.scanner.currentToken, 0, 0, false, false)
11325 );
11326 }
11327
11328 this.scanner.eat(RIGHTPARENTHESIS$5);
11329 } else {
11330 name = this.scanner.consume(IDENTIFIER$g);
11331 }
11332
11333 return {
11334 type: 'PseudoClassSelector',
11335 loc: this.getLocation(start, this.scanner.tokenStart),
11336 name: name,
11337 children: children
11338 };
11339 },
11340 generate: function(processChunk, node) {
11341 processChunk(':');
11342 processChunk(node.name);
11343
11344 if (node.children !== null) {
11345 processChunk('(');
11346 this.each(processChunk, node);
11347 processChunk(')');
11348 }
11349 },
11350 walkContext: 'function'
11351};
11352
11353var TYPE$u = tokenizer.TYPE;
11354
11355var IDENTIFIER$h = TYPE$u.Identifier;
11356var FUNCTION$5 = TYPE$u.Function;
11357var COLON$6 = TYPE$u.Colon;
11358var RIGHTPARENTHESIS$6 = TYPE$u.RightParenthesis;
11359
11360// :: ident [ '(' .. ')' ]?
11361var PseudoElementSelector = {
11362 name: 'PseudoElementSelector',
11363 structure: {
11364 name: String,
11365 children: [['Raw'], null]
11366 },
11367 parse: function() {
11368 var start = this.scanner.tokenStart;
11369 var children = null;
11370 var name;
11371 var nameLowerCase;
11372
11373 this.scanner.eat(COLON$6);
11374 this.scanner.eat(COLON$6);
11375
11376 if (this.scanner.tokenType === FUNCTION$5) {
11377 name = this.scanner.consumeFunctionName();
11378 nameLowerCase = name.toLowerCase();
11379
11380 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11381 this.scanner.skipSC();
11382 children = this.pseudo[nameLowerCase].call(this);
11383 this.scanner.skipSC();
11384 } else {
11385 children = new list().appendData(
11386 this.Raw(this.scanner.currentToken, 0, 0, false, false)
11387 );
11388 }
11389
11390 this.scanner.eat(RIGHTPARENTHESIS$6);
11391 } else {
11392 name = this.scanner.consume(IDENTIFIER$h);
11393 }
11394
11395 return {
11396 type: 'PseudoElementSelector',
11397 loc: this.getLocation(start, this.scanner.tokenStart),
11398 name: name,
11399 children: children
11400 };
11401 },
11402 generate: function(processChunk, node) {
11403 processChunk('::');
11404 processChunk(node.name);
11405
11406 if (node.children !== null) {
11407 processChunk('(');
11408 this.each(processChunk, node);
11409 processChunk(')');
11410 }
11411 },
11412 walkContext: 'function'
11413};
11414
11415var isNumber$3 = tokenizer.isNumber;
11416var TYPE$v = tokenizer.TYPE;
11417var NUMBER$a = TYPE$v.Number;
11418var SOLIDUS$6 = TYPE$v.Solidus;
11419var FULLSTOP$4 = TYPE$v.FullStop;
11420
11421// Terms of <ratio> should to be a positive number (not zero or negative)
11422// (see https://drafts.csswg.org/mediaqueries-3/#values)
11423// However, -o-min-device-pixel-ratio takes fractional values as a ratio's term
11424// and this is using by various sites. Therefore we relax checking on parse
11425// to test a term is unsigned number without exponent part.
11426// Additional checks may to be applied on lexer validation.
11427function consumeNumber(scanner) {
11428 var value = scanner.consumeNonWS(NUMBER$a);
11429
11430 for (var i = 0; i < value.length; i++) {
11431 var code = value.charCodeAt(i);
11432 if (!isNumber$3(code) && code !== FULLSTOP$4) {
11433 scanner.error('Unsigned number is expected', scanner.tokenStart - value.length + i);
11434 }
11435 }
11436
11437 if (Number(value) === 0) {
11438 scanner.error('Zero number is not allowed', scanner.tokenStart - value.length);
11439 }
11440
11441 return value;
11442}
11443
11444// <positive-integer> S* '/' S* <positive-integer>
11445var Ratio = {
11446 name: 'Ratio',
11447 structure: {
11448 left: String,
11449 right: String
11450 },
11451 parse: function() {
11452 var start = this.scanner.tokenStart;
11453 var left = consumeNumber(this.scanner);
11454 var right;
11455
11456 this.scanner.eatNonWS(SOLIDUS$6);
11457 right = consumeNumber(this.scanner);
11458
11459 return {
11460 type: 'Ratio',
11461 loc: this.getLocation(start, this.scanner.tokenStart),
11462 left: left,
11463 right: right
11464 };
11465 },
11466 generate: function(processChunk, node) {
11467 processChunk(node.left);
11468 processChunk('/');
11469 processChunk(node.right);
11470 }
11471};
11472
11473var Raw = {
11474 name: 'Raw',
11475 structure: {
11476 value: String
11477 },
11478 parse: function(startToken, endTokenType1, endTokenType2, includeTokenType2, excludeWhiteSpace) {
11479 var startOffset = this.scanner.getTokenStart(startToken);
11480 var endOffset;
11481
11482 this.scanner.skip(
11483 this.scanner.getRawLength(
11484 startToken,
11485 endTokenType1,
11486 endTokenType2,
11487 includeTokenType2
11488 )
11489 );
11490
11491 if (excludeWhiteSpace && this.scanner.tokenStart > startOffset) {
11492 endOffset = this.scanner.getOffsetExcludeWS();
11493 } else {
11494 endOffset = this.scanner.tokenStart;
11495 }
11496
11497 return {
11498 type: 'Raw',
11499 loc: this.getLocation(startOffset, endOffset),
11500 value: this.scanner.source.substring(startOffset, endOffset)
11501 };
11502 },
11503 generate: function(processChunk, node) {
11504 processChunk(node.value);
11505 }
11506};
11507
11508var TYPE$w = tokenizer.TYPE;
11509
11510var LEFTCURLYBRACKET$5 = TYPE$w.LeftCurlyBracket;
11511
11512function consumeRaw$4(startToken) {
11513 return this.Raw(startToken, LEFTCURLYBRACKET$5, 0, false, true);
11514}
11515
11516var Rule = {
11517 name: 'Rule',
11518 structure: {
11519 selector: ['SelectorList', 'Raw'],
11520 block: ['Block']
11521 },
11522 parse: function() {
11523 var startToken = this.scanner.currentToken;
11524 var startOffset = this.scanner.tokenStart;
11525 var selector = this.parseSelector
11526 ? this.tolerantParse(this.SelectorList, consumeRaw$4)
11527 : consumeRaw$4.call(this, startToken);
11528 var block = this.Block(this.Declaration);
11529
11530 return {
11531 type: 'Rule',
11532 loc: this.getLocation(startOffset, this.scanner.tokenStart),
11533 selector: selector,
11534 block: block
11535 };
11536 },
11537 generate: function(processChunk, node) {
11538 this.generate(processChunk, node.selector);
11539 this.generate(processChunk, node.block);
11540 },
11541 walkContext: 'rule'
11542};
11543
11544var Selector = {
11545 name: 'Selector',
11546 structure: {
11547 children: [[
11548 'TypeSelector',
11549 'IdSelector',
11550 'ClassSelector',
11551 'AttributeSelector',
11552 'PseudoClassSelector',
11553 'PseudoElementSelector',
11554 'Combinator',
11555 'WhiteSpace'
11556 ]]
11557 },
11558 parse: function() {
11559 var children = this.readSequence(this.scope.Selector);
11560
11561 // nothing were consumed
11562 if (children.isEmpty()) {
11563 this.scanner.error('Selector is expected');
11564 }
11565
11566 return {
11567 type: 'Selector',
11568 loc: this.getLocationFromList(children),
11569 children: children
11570 };
11571 },
11572 generate: function(processChunk, node) {
11573 this.each(processChunk, node);
11574 }
11575};
11576
11577var TYPE$x = tokenizer.TYPE;
11578
11579var COMMA$3 = TYPE$x.Comma;
11580var LEFTCURLYBRACKET$6 = TYPE$x.LeftCurlyBracket;
11581
11582var SelectorList = {
11583 name: 'SelectorList',
11584 structure: {
11585 children: [['Selector', 'Raw']]
11586 },
11587 parse: function() {
11588 var children = new list();
11589
11590 while (!this.scanner.eof) {
11591 children.appendData(this.parseSelector
11592 ? this.Selector()
11593 : this.Raw(this.scanner.currentToken, COMMA$3, LEFTCURLYBRACKET$6, false, false)
11594 );
11595
11596 if (this.scanner.tokenType === COMMA$3) {
11597 this.scanner.next();
11598 continue;
11599 }
11600
11601 break;
11602 }
11603
11604 return {
11605 type: 'SelectorList',
11606 loc: this.getLocationFromList(children),
11607 children: children
11608 };
11609 },
11610 generate: function(processChunk, node) {
11611 this.eachComma(processChunk, node);
11612 },
11613 walkContext: 'selector'
11614};
11615
11616var STRING$5 = tokenizer.TYPE.String;
11617
11618var _String = {
11619 name: 'String',
11620 structure: {
11621 value: String
11622 },
11623 parse: function() {
11624 return {
11625 type: 'String',
11626 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11627 value: this.scanner.consume(STRING$5)
11628 };
11629 },
11630 generate: function(processChunk, node) {
11631 processChunk(node.value);
11632 }
11633};
11634
11635var TYPE$y = tokenizer.TYPE;
11636
11637var WHITESPACE$7 = TYPE$y.WhiteSpace;
11638var COMMENT$7 = TYPE$y.Comment;
11639var EXCLAMATIONMARK$3 = TYPE$y.ExclamationMark;
11640var ATRULE$4 = TYPE$y.Atrule;
11641var CDO$3 = TYPE$y.CDO;
11642var CDC$3 = TYPE$y.CDC;
11643
11644function consumeRaw$5(startToken) {
11645 return this.Raw(startToken, 0, 0, false, false);
11646}
11647
11648var StyleSheet = {
11649 name: 'StyleSheet',
11650 structure: {
11651 children: [['Comment', 'Atrule', 'Rule', 'Raw']]
11652 },
11653 parse: function() {
11654 var start = this.scanner.tokenStart;
11655 var children = new list();
11656 var child;
11657
11658
11659 while (!this.scanner.eof) {
11660 switch (this.scanner.tokenType) {
11661 case WHITESPACE$7:
11662 this.scanner.next();
11663 continue;
11664
11665 case COMMENT$7:
11666 // ignore comments except exclamation comments (i.e. /*! .. */) on top level
11667 if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 2) !== EXCLAMATIONMARK$3) {
11668 this.scanner.next();
11669 continue;
11670 }
11671
11672 child = this.Comment();
11673 break;
11674
11675 case CDO$3: // <!--
11676 child = this.CDO();
11677 break;
11678
11679 case CDC$3: // -->
11680 child = this.CDC();
11681 break;
11682
11683 // CSS Syntax Module Level 3
11684 // §2.2 Error handling
11685 // At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule.
11686 case ATRULE$4:
11687 child = this.Atrule();
11688 break;
11689
11690 // Anything else starts a qualified rule ...
11691 default:
11692 child = this.tolerantParse(this.Rule, consumeRaw$5);
11693 }
11694
11695 children.appendData(child);
11696 }
11697
11698 return {
11699 type: 'StyleSheet',
11700 loc: this.getLocation(start, this.scanner.tokenStart),
11701 children: children
11702 };
11703 },
11704 generate: function(processChunk, node) {
11705 this.each(processChunk, node);
11706 },
11707 walkContext: 'stylesheet'
11708};
11709
11710var TYPE$z = tokenizer.TYPE;
11711
11712var IDENTIFIER$i = TYPE$z.Identifier;
11713var ASTERISK$5 = TYPE$z.Asterisk;
11714var VERTICALLINE$2 = TYPE$z.VerticalLine;
11715
11716function eatIdentifierOrAsterisk() {
11717 if (this.scanner.tokenType !== IDENTIFIER$i &&
11718 this.scanner.tokenType !== ASTERISK$5) {
11719 this.scanner.error('Identifier or asterisk is expected');
11720 }
11721
11722 this.scanner.next();
11723}
11724
11725// ident
11726// ident|ident
11727// ident|*
11728// *
11729// *|ident
11730// *|*
11731// |ident
11732// |*
11733var TypeSelector = {
11734 name: 'TypeSelector',
11735 structure: {
11736 name: String
11737 },
11738 parse: function() {
11739 var start = this.scanner.tokenStart;
11740
11741 if (this.scanner.tokenType === VERTICALLINE$2) {
11742 this.scanner.next();
11743 eatIdentifierOrAsterisk.call(this);
11744 } else {
11745 eatIdentifierOrAsterisk.call(this);
11746
11747 if (this.scanner.tokenType === VERTICALLINE$2) {
11748 this.scanner.next();
11749 eatIdentifierOrAsterisk.call(this);
11750 }
11751 }
11752
11753 return {
11754 type: 'TypeSelector',
11755 loc: this.getLocation(start, this.scanner.tokenStart),
11756 name: this.scanner.substrToCursor(start)
11757 };
11758 },
11759 generate: function(processChunk, node) {
11760 processChunk(node.name);
11761 }
11762};
11763
11764var isHex$2 = tokenizer.isHex;
11765var TYPE$A = tokenizer.TYPE;
11766
11767var IDENTIFIER$j = TYPE$A.Identifier;
11768var NUMBER$b = TYPE$A.Number;
11769var PLUSSIGN$7 = TYPE$A.PlusSign;
11770var HYPHENMINUS$7 = TYPE$A.HyphenMinus;
11771var FULLSTOP$5 = TYPE$A.FullStop;
11772var QUESTIONMARK = TYPE$A.QuestionMark;
11773
11774function scanUnicodeNumber(scanner) {
11775 for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
11776 var code = scanner.source.charCodeAt(pos);
11777
11778 // break on fullstop or hyperminus/plussign after exponent
11779 if (code === FULLSTOP$5 || code === PLUSSIGN$7) {
11780 // break token, exclude symbol
11781 scanner.tokenStart = pos;
11782 return false;
11783 }
11784 }
11785
11786 return true;
11787}
11788
11789// https://drafts.csswg.org/css-syntax-3/#urange
11790function scanUnicodeRange(scanner) {
11791 var hexStart = scanner.tokenStart + 1; // skip +
11792 var hexLength = 0;
11793
11794 scan: {
11795 if (scanner.tokenType === NUMBER$b) {
11796 if (scanner.source.charCodeAt(scanner.tokenStart) !== FULLSTOP$5 && scanUnicodeNumber(scanner)) {
11797 scanner.next();
11798 } else if (scanner.source.charCodeAt(scanner.tokenStart) !== HYPHENMINUS$7) {
11799 break scan;
11800 }
11801 } else {
11802 scanner.next(); // PLUSSIGN
11803 }
11804
11805 if (scanner.tokenType === HYPHENMINUS$7) {
11806 scanner.next();
11807 }
11808
11809 if (scanner.tokenType === NUMBER$b) {
11810 scanner.next();
11811 }
11812
11813 if (scanner.tokenType === IDENTIFIER$j) {
11814 scanner.next();
11815 }
11816
11817 if (scanner.tokenStart === hexStart) {
11818 scanner.error('Unexpected input', hexStart);
11819 }
11820 }
11821
11822 // validate for U+x{1,6} or U+x{1,6}-x{1,6}
11823 // where x is [0-9a-fA-F]
11824 for (var i = hexStart, wasHyphenMinus = false; i < scanner.tokenStart; i++) {
11825 var code = scanner.source.charCodeAt(i);
11826
11827 if (isHex$2(code) === false && (code !== HYPHENMINUS$7 || wasHyphenMinus)) {
11828 scanner.error('Unexpected input', i);
11829 }
11830
11831 if (code === HYPHENMINUS$7) {
11832 // hex sequence shouldn't be an empty
11833 if (hexLength === 0) {
11834 scanner.error('Unexpected input', i);
11835 }
11836
11837 wasHyphenMinus = true;
11838 hexLength = 0;
11839 } else {
11840 hexLength++;
11841
11842 // too long hex sequence
11843 if (hexLength > 6) {
11844 scanner.error('Too long hex sequence', i);
11845 }
11846 }
11847
11848 }
11849
11850 // check we have a non-zero sequence
11851 if (hexLength === 0) {
11852 scanner.error('Unexpected input', i - 1);
11853 }
11854
11855 // U+abc???
11856 if (!wasHyphenMinus) {
11857 // consume as many U+003F QUESTION MARK (?) code points as possible
11858 for (; hexLength < 6 && !scanner.eof; scanner.next()) {
11859 if (scanner.tokenType !== QUESTIONMARK) {
11860 break;
11861 }
11862
11863 hexLength++;
11864 }
11865 }
11866}
11867
11868var UnicodeRange = {
11869 name: 'UnicodeRange',
11870 structure: {
11871 value: String
11872 },
11873 parse: function() {
11874 var start = this.scanner.tokenStart;
11875
11876 this.scanner.next(); // U or u
11877 scanUnicodeRange(this.scanner);
11878
11879 return {
11880 type: 'UnicodeRange',
11881 loc: this.getLocation(start, this.scanner.tokenStart),
11882 value: this.scanner.substrToCursor(start)
11883 };
11884 },
11885 generate: function(processChunk, node) {
11886 processChunk(node.value);
11887 }
11888};
11889
11890var TYPE$B = tokenizer.TYPE;
11891
11892var STRING$6 = TYPE$B.String;
11893var URL$5 = TYPE$B.Url;
11894var RAW$2 = TYPE$B.Raw;
11895var RIGHTPARENTHESIS$7 = TYPE$B.RightParenthesis;
11896
11897// url '(' S* (string | raw) S* ')'
11898var Url = {
11899 name: 'Url',
11900 structure: {
11901 value: ['String', 'Raw']
11902 },
11903 parse: function() {
11904 var start = this.scanner.tokenStart;
11905 var value;
11906
11907 this.scanner.eat(URL$5);
11908 this.scanner.skipSC();
11909
11910 switch (this.scanner.tokenType) {
11911 case STRING$6:
11912 value = this.String();
11913 break;
11914
11915 case RAW$2:
11916 value = this.Raw(this.scanner.currentToken, 0, RAW$2, true, false);
11917 break;
11918
11919 default:
11920 this.scanner.error('String or Raw is expected');
11921 }
11922
11923 this.scanner.skipSC();
11924 this.scanner.eat(RIGHTPARENTHESIS$7);
11925
11926 return {
11927 type: 'Url',
11928 loc: this.getLocation(start, this.scanner.tokenStart),
11929 value: value
11930 };
11931 },
11932 generate: function(processChunk, node) {
11933 processChunk('url');
11934 processChunk('(');
11935 this.generate(processChunk, node.value);
11936 processChunk(')');
11937 }
11938};
11939
11940var endsWith$1 = tokenizer.endsWith;
11941var TYPE$C = tokenizer.TYPE;
11942
11943var WHITESPACE$8 = TYPE$C.WhiteSpace;
11944var COMMENT$8 = TYPE$C.Comment;
11945var FUNCTION$6 = TYPE$C.Function;
11946var COLON$7 = TYPE$C.Colon;
11947var SEMICOLON$6 = TYPE$C.Semicolon;
11948var EXCLAMATIONMARK$4 = TYPE$C.ExclamationMark;
11949
11950// 'progid:' ws* 'DXImageTransform.Microsoft.' ident ws* '(' .* ')'
11951function checkProgid(scanner) {
11952 var offset = 0;
11953
11954 for (var type; type = scanner.lookupType(offset); offset++) {
11955 if (type !== WHITESPACE$8 && type !== COMMENT$8) {
11956 break;
11957 }
11958 }
11959
11960 if (scanner.lookupValue(offset, 'alpha(') ||
11961 scanner.lookupValue(offset, 'chroma(') ||
11962 scanner.lookupValue(offset, 'dropshadow(')) {
11963 if (scanner.lookupType(offset) !== FUNCTION$6) {
11964 return false;
11965 }
11966 } else {
11967 if (scanner.lookupValue(offset, 'progid') === false ||
11968 scanner.lookupType(offset + 1) !== COLON$7) {
11969 return false;
11970 }
11971 }
11972
11973 return true;
11974}
11975
11976var Value = {
11977 name: 'Value',
11978 structure: {
11979 children: [[]]
11980 },
11981 parse: function(property) {
11982 // special parser for filter property since it can contains non-standart syntax for old IE
11983 if (property !== null && endsWith$1(property, 'filter') && checkProgid(this.scanner)) {
11984 this.scanner.skipSC();
11985 return this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$4, SEMICOLON$6, false, false);
11986 }
11987
11988 var start = this.scanner.tokenStart;
11989 var children = this.readSequence(this.scope.Value);
11990
11991 return {
11992 type: 'Value',
11993 loc: this.getLocation(start, this.scanner.tokenStart),
11994 children: children
11995 };
11996 },
11997 generate: function(processChunk, node) {
11998 this.each(processChunk, node);
11999 }
12000};
12001
12002var WHITESPACE$9 = tokenizer.TYPE.WhiteSpace;
12003var SPACE$2 = Object.freeze({
12004 type: 'WhiteSpace',
12005 loc: null,
12006 value: ' '
12007});
12008
12009var WhiteSpace = {
12010 name: 'WhiteSpace',
12011 structure: {
12012 value: String
12013 },
12014 parse: function() {
12015 this.scanner.eat(WHITESPACE$9);
12016 return SPACE$2;
12017
12018 // return {
12019 // type: 'WhiteSpace',
12020 // loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
12021 // value: this.scanner.consume(WHITESPACE)
12022 // };
12023 },
12024 generate: function(processChunk, node) {
12025 processChunk(node.value);
12026 }
12027};
12028
12029var node = {
12030 AnPlusB: AnPlusB,
12031 Atrule: Atrule,
12032 AtruleExpression: AtruleExpression,
12033 AttributeSelector: AttributeSelector,
12034 Block: Block,
12035 Brackets: Brackets,
12036 CDC: CDC_1,
12037 CDO: CDO_1,
12038 ClassSelector: ClassSelector,
12039 Combinator: Combinator,
12040 Comment: Comment,
12041 Declaration: Declaration,
12042 DeclarationList: DeclarationList,
12043 Dimension: Dimension,
12044 Function: _Function,
12045 HexColor: HexColor,
12046 Identifier: Identifier,
12047 IdSelector: IdSelector,
12048 MediaFeature: MediaFeature,
12049 MediaQuery: MediaQuery,
12050 MediaQueryList: MediaQueryList,
12051 Nth: Nth,
12052 Number: _Number,
12053 Operator: Operator,
12054 Parentheses: Parentheses,
12055 Percentage: Percentage,
12056 PseudoClassSelector: PseudoClassSelector,
12057 PseudoElementSelector: PseudoElementSelector,
12058 Ratio: Ratio,
12059 Raw: Raw,
12060 Rule: Rule,
12061 Selector: Selector,
12062 SelectorList: SelectorList,
12063 String: _String,
12064 StyleSheet: StyleSheet,
12065 TypeSelector: TypeSelector,
12066 UnicodeRange: UnicodeRange,
12067 Url: Url,
12068 Value: Value,
12069 WhiteSpace: WhiteSpace
12070};
12071
12072var parser = {
12073 parseContext: {
12074 default: 'StyleSheet',
12075 stylesheet: 'StyleSheet',
12076 atrule: 'Atrule',
12077 atruleExpression: function(options) {
12078 return this.AtruleExpression(options.atrule ? String(options.atrule) : null);
12079 },
12080 mediaQueryList: 'MediaQueryList',
12081 mediaQuery: 'MediaQuery',
12082 rule: 'Rule',
12083 selectorList: 'SelectorList',
12084 selector: 'Selector',
12085 block: function() {
12086 return this.Block(this.Declaration);
12087 },
12088 declarationList: 'DeclarationList',
12089 declaration: 'Declaration',
12090 value: function(options) {
12091 return this.Value(options.property ? String(options.property) : null);
12092 }
12093 },
12094 scope: scope,
12095 atrule: atrule,
12096 pseudo: pseudo,
12097 node: node
12098};
12099
12100var parser$1 = create(parser);
12101
12102function read_style(parser, start, attributes) {
12103 const content_start = parser.index;
12104 const styles = parser.read_until(/<\/style>/);
12105 const content_end = parser.index;
12106 let ast;
12107 try {
12108 ast = parser$1(styles, {
12109 positions: true,
12110 offset: content_start
12111 });
12112 }
12113 catch (err) {
12114 if (err.name === 'CssSyntaxError') {
12115 parser.error({
12116 code: 'css-syntax-error',
12117 message: err.message
12118 }, err.offset);
12119 }
12120 else {
12121 throw err;
12122 }
12123 }
12124 ast = JSON.parse(JSON.stringify(ast));
12125 // tidy up AST
12126 walk(ast, {
12127 enter: (node) => {
12128 // replace `ref:a` nodes
12129 if (node.type === 'Selector') {
12130 for (let i = 0; i < node.children.length; i += 1) {
12131 const a = node.children[i];
12132 const b = node.children[i + 1];
12133 if (is_ref_selector(a, b)) {
12134 parser.error({
12135 code: 'invalid-ref-selector',
12136 message: 'ref selectors are no longer supported'
12137 }, a.loc.start.offset);
12138 }
12139 }
12140 }
12141 if (node.type === 'Declaration' && node.value.type === 'Value' && node.value.children.length === 0) {
12142 parser.error({
12143 code: 'invalid-declaration',
12144 message: 'Declaration cannot be empty'
12145 }, node.start);
12146 }
12147 if (node.type === 'PseudoClassSelector' && node.name === 'global' && node.children === null) {
12148 parser.error({
12149 code: 'css-syntax-error',
12150 message: ':global() must contain a selector'
12151 }, node.loc.start.offset);
12152 }
12153 if (node.loc) {
12154 node.start = node.loc.start.offset;
12155 node.end = node.loc.end.offset;
12156 delete node.loc;
12157 }
12158 }
12159 });
12160 parser.eat('</style>', true);
12161 const end = parser.index;
12162 return {
12163 type: 'Style',
12164 start,
12165 end,
12166 attributes,
12167 children: ast.children,
12168 content: {
12169 start: content_start,
12170 end: content_end,
12171 styles
12172 }
12173 };
12174}
12175function is_ref_selector(a, b) {
12176 if (!b)
12177 return false;
12178 return (a.type === 'TypeSelector' &&
12179 a.name === 'ref' &&
12180 b.type === 'PseudoClassSelector');
12181}
12182
12183// https://dev.w3.org/html5/html-author/charref
12184var entities = {
12185 CounterClockwiseContourIntegral: 8755,
12186 ClockwiseContourIntegral: 8754,
12187 DoubleLongLeftRightArrow: 10234,
12188 DiacriticalDoubleAcute: 733,
12189 NotSquareSupersetEqual: 8931,
12190 CloseCurlyDoubleQuote: 8221,
12191 DoubleContourIntegral: 8751,
12192 FilledVerySmallSquare: 9642,
12193 NegativeVeryThinSpace: 8203,
12194 NotPrecedesSlantEqual: 8928,
12195 NotRightTriangleEqual: 8941,
12196 NotSucceedsSlantEqual: 8929,
12197 CapitalDifferentialD: 8517,
12198 DoubleLeftRightArrow: 8660,
12199 DoubleLongRightArrow: 10233,
12200 EmptyVerySmallSquare: 9643,
12201 NestedGreaterGreater: 8811,
12202 NotDoubleVerticalBar: 8742,
12203 NotLeftTriangleEqual: 8940,
12204 NotSquareSubsetEqual: 8930,
12205 OpenCurlyDoubleQuote: 8220,
12206 ReverseUpEquilibrium: 10607,
12207 DoubleLongLeftArrow: 10232,
12208 DownLeftRightVector: 10576,
12209 LeftArrowRightArrow: 8646,
12210 NegativeMediumSpace: 8203,
12211 RightArrowLeftArrow: 8644,
12212 SquareSupersetEqual: 8850,
12213 leftrightsquigarrow: 8621,
12214 DownRightTeeVector: 10591,
12215 DownRightVectorBar: 10583,
12216 LongLeftRightArrow: 10231,
12217 Longleftrightarrow: 10234,
12218 NegativeThickSpace: 8203,
12219 PrecedesSlantEqual: 8828,
12220 ReverseEquilibrium: 8651,
12221 RightDoubleBracket: 10215,
12222 RightDownTeeVector: 10589,
12223 RightDownVectorBar: 10581,
12224 RightTriangleEqual: 8885,
12225 SquareIntersection: 8851,
12226 SucceedsSlantEqual: 8829,
12227 blacktriangleright: 9656,
12228 longleftrightarrow: 10231,
12229 DoubleUpDownArrow: 8661,
12230 DoubleVerticalBar: 8741,
12231 DownLeftTeeVector: 10590,
12232 DownLeftVectorBar: 10582,
12233 FilledSmallSquare: 9724,
12234 GreaterSlantEqual: 10878,
12235 LeftDoubleBracket: 10214,
12236 LeftDownTeeVector: 10593,
12237 LeftDownVectorBar: 10585,
12238 LeftTriangleEqual: 8884,
12239 NegativeThinSpace: 8203,
12240 NotReverseElement: 8716,
12241 NotTildeFullEqual: 8775,
12242 RightAngleBracket: 10217,
12243 RightUpDownVector: 10575,
12244 SquareSubsetEqual: 8849,
12245 VerticalSeparator: 10072,
12246 blacktriangledown: 9662,
12247 blacktriangleleft: 9666,
12248 leftrightharpoons: 8651,
12249 rightleftharpoons: 8652,
12250 twoheadrightarrow: 8608,
12251 DiacriticalAcute: 180,
12252 DiacriticalGrave: 96,
12253 DiacriticalTilde: 732,
12254 DoubleRightArrow: 8658,
12255 DownArrowUpArrow: 8693,
12256 EmptySmallSquare: 9723,
12257 GreaterEqualLess: 8923,
12258 GreaterFullEqual: 8807,
12259 LeftAngleBracket: 10216,
12260 LeftUpDownVector: 10577,
12261 LessEqualGreater: 8922,
12262 NonBreakingSpace: 160,
12263 NotRightTriangle: 8939,
12264 NotSupersetEqual: 8841,
12265 RightTriangleBar: 10704,
12266 RightUpTeeVector: 10588,
12267 RightUpVectorBar: 10580,
12268 UnderParenthesis: 9181,
12269 UpArrowDownArrow: 8645,
12270 circlearrowright: 8635,
12271 downharpoonright: 8642,
12272 ntrianglerighteq: 8941,
12273 rightharpoondown: 8641,
12274 rightrightarrows: 8649,
12275 twoheadleftarrow: 8606,
12276 vartriangleright: 8883,
12277 CloseCurlyQuote: 8217,
12278 ContourIntegral: 8750,
12279 DoubleDownArrow: 8659,
12280 DoubleLeftArrow: 8656,
12281 DownRightVector: 8641,
12282 LeftRightVector: 10574,
12283 LeftTriangleBar: 10703,
12284 LeftUpTeeVector: 10592,
12285 LeftUpVectorBar: 10584,
12286 LowerRightArrow: 8600,
12287 NotGreaterEqual: 8817,
12288 NotGreaterTilde: 8821,
12289 NotLeftTriangle: 8938,
12290 OverParenthesis: 9180,
12291 RightDownVector: 8642,
12292 ShortRightArrow: 8594,
12293 UpperRightArrow: 8599,
12294 bigtriangledown: 9661,
12295 circlearrowleft: 8634,
12296 curvearrowright: 8631,
12297 downharpoonleft: 8643,
12298 leftharpoondown: 8637,
12299 leftrightarrows: 8646,
12300 nLeftrightarrow: 8654,
12301 nleftrightarrow: 8622,
12302 ntrianglelefteq: 8940,
12303 rightleftarrows: 8644,
12304 rightsquigarrow: 8605,
12305 rightthreetimes: 8908,
12306 straightepsilon: 1013,
12307 trianglerighteq: 8885,
12308 vartriangleleft: 8882,
12309 DiacriticalDot: 729,
12310 DoubleRightTee: 8872,
12311 DownLeftVector: 8637,
12312 GreaterGreater: 10914,
12313 HorizontalLine: 9472,
12314 InvisibleComma: 8291,
12315 InvisibleTimes: 8290,
12316 LeftDownVector: 8643,
12317 LeftRightArrow: 8596,
12318 Leftrightarrow: 8660,
12319 LessSlantEqual: 10877,
12320 LongRightArrow: 10230,
12321 Longrightarrow: 10233,
12322 LowerLeftArrow: 8601,
12323 NestedLessLess: 8810,
12324 NotGreaterLess: 8825,
12325 NotLessGreater: 8824,
12326 NotSubsetEqual: 8840,
12327 NotVerticalBar: 8740,
12328 OpenCurlyQuote: 8216,
12329 ReverseElement: 8715,
12330 RightTeeVector: 10587,
12331 RightVectorBar: 10579,
12332 ShortDownArrow: 8595,
12333 ShortLeftArrow: 8592,
12334 SquareSuperset: 8848,
12335 TildeFullEqual: 8773,
12336 UpperLeftArrow: 8598,
12337 ZeroWidthSpace: 8203,
12338 curvearrowleft: 8630,
12339 doublebarwedge: 8966,
12340 downdownarrows: 8650,
12341 hookrightarrow: 8618,
12342 leftleftarrows: 8647,
12343 leftrightarrow: 8596,
12344 leftthreetimes: 8907,
12345 longrightarrow: 10230,
12346 looparrowright: 8620,
12347 nshortparallel: 8742,
12348 ntriangleright: 8939,
12349 rightarrowtail: 8611,
12350 rightharpoonup: 8640,
12351 trianglelefteq: 8884,
12352 upharpoonright: 8638,
12353 ApplyFunction: 8289,
12354 DifferentialD: 8518,
12355 DoubleLeftTee: 10980,
12356 DoubleUpArrow: 8657,
12357 LeftTeeVector: 10586,
12358 LeftVectorBar: 10578,
12359 LessFullEqual: 8806,
12360 LongLeftArrow: 10229,
12361 Longleftarrow: 10232,
12362 NotTildeEqual: 8772,
12363 NotTildeTilde: 8777,
12364 Poincareplane: 8460,
12365 PrecedesEqual: 10927,
12366 PrecedesTilde: 8830,
12367 RightArrowBar: 8677,
12368 RightTeeArrow: 8614,
12369 RightTriangle: 8883,
12370 RightUpVector: 8638,
12371 SucceedsEqual: 10928,
12372 SucceedsTilde: 8831,
12373 SupersetEqual: 8839,
12374 UpEquilibrium: 10606,
12375 VerticalTilde: 8768,
12376 VeryThinSpace: 8202,
12377 bigtriangleup: 9651,
12378 blacktriangle: 9652,
12379 divideontimes: 8903,
12380 fallingdotseq: 8786,
12381 hookleftarrow: 8617,
12382 leftarrowtail: 8610,
12383 leftharpoonup: 8636,
12384 longleftarrow: 10229,
12385 looparrowleft: 8619,
12386 measuredangle: 8737,
12387 ntriangleleft: 8938,
12388 shortparallel: 8741,
12389 smallsetminus: 8726,
12390 triangleright: 9657,
12391 upharpoonleft: 8639,
12392 DownArrowBar: 10515,
12393 DownTeeArrow: 8615,
12394 ExponentialE: 8519,
12395 GreaterEqual: 8805,
12396 GreaterTilde: 8819,
12397 HilbertSpace: 8459,
12398 HumpDownHump: 8782,
12399 Intersection: 8898,
12400 LeftArrowBar: 8676,
12401 LeftTeeArrow: 8612,
12402 LeftTriangle: 8882,
12403 LeftUpVector: 8639,
12404 NotCongruent: 8802,
12405 NotLessEqual: 8816,
12406 NotLessTilde: 8820,
12407 Proportional: 8733,
12408 RightCeiling: 8969,
12409 RoundImplies: 10608,
12410 ShortUpArrow: 8593,
12411 SquareSubset: 8847,
12412 UnderBracket: 9141,
12413 VerticalLine: 124,
12414 blacklozenge: 10731,
12415 exponentiale: 8519,
12416 risingdotseq: 8787,
12417 triangledown: 9663,
12418 triangleleft: 9667,
12419 CircleMinus: 8854,
12420 CircleTimes: 8855,
12421 Equilibrium: 8652,
12422 GreaterLess: 8823,
12423 LeftCeiling: 8968,
12424 LessGreater: 8822,
12425 MediumSpace: 8287,
12426 NotPrecedes: 8832,
12427 NotSucceeds: 8833,
12428 OverBracket: 9140,
12429 RightVector: 8640,
12430 Rrightarrow: 8667,
12431 RuleDelayed: 10740,
12432 SmallCircle: 8728,
12433 SquareUnion: 8852,
12434 SubsetEqual: 8838,
12435 UpDownArrow: 8597,
12436 Updownarrow: 8661,
12437 VerticalBar: 8739,
12438 backepsilon: 1014,
12439 blacksquare: 9642,
12440 circledcirc: 8858,
12441 circleddash: 8861,
12442 curlyeqprec: 8926,
12443 curlyeqsucc: 8927,
12444 diamondsuit: 9830,
12445 eqslantless: 10901,
12446 expectation: 8496,
12447 nRightarrow: 8655,
12448 nrightarrow: 8603,
12449 preccurlyeq: 8828,
12450 precnapprox: 10937,
12451 quaternions: 8461,
12452 straightphi: 981,
12453 succcurlyeq: 8829,
12454 succnapprox: 10938,
12455 thickapprox: 8776,
12456 updownarrow: 8597,
12457 Bernoullis: 8492,
12458 CirclePlus: 8853,
12459 EqualTilde: 8770,
12460 Fouriertrf: 8497,
12461 ImaginaryI: 8520,
12462 Laplacetrf: 8466,
12463 LeftVector: 8636,
12464 Lleftarrow: 8666,
12465 NotElement: 8713,
12466 NotGreater: 8815,
12467 Proportion: 8759,
12468 RightArrow: 8594,
12469 RightFloor: 8971,
12470 Rightarrow: 8658,
12471 TildeEqual: 8771,
12472 TildeTilde: 8776,
12473 UnderBrace: 9183,
12474 UpArrowBar: 10514,
12475 UpTeeArrow: 8613,
12476 circledast: 8859,
12477 complement: 8705,
12478 curlywedge: 8911,
12479 eqslantgtr: 10902,
12480 gtreqqless: 10892,
12481 lessapprox: 10885,
12482 lesseqqgtr: 10891,
12483 lmoustache: 9136,
12484 longmapsto: 10236,
12485 mapstodown: 8615,
12486 mapstoleft: 8612,
12487 nLeftarrow: 8653,
12488 nleftarrow: 8602,
12489 precapprox: 10935,
12490 rightarrow: 8594,
12491 rmoustache: 9137,
12492 sqsubseteq: 8849,
12493 sqsupseteq: 8850,
12494 subsetneqq: 10955,
12495 succapprox: 10936,
12496 supsetneqq: 10956,
12497 upuparrows: 8648,
12498 varepsilon: 949,
12499 varnothing: 8709,
12500 Backslash: 8726,
12501 CenterDot: 183,
12502 CircleDot: 8857,
12503 Congruent: 8801,
12504 Coproduct: 8720,
12505 DoubleDot: 168,
12506 DownArrow: 8595,
12507 DownBreve: 785,
12508 Downarrow: 8659,
12509 HumpEqual: 8783,
12510 LeftArrow: 8592,
12511 LeftFloor: 8970,
12512 Leftarrow: 8656,
12513 LessTilde: 8818,
12514 Mellintrf: 8499,
12515 MinusPlus: 8723,
12516 NotCupCap: 8813,
12517 NotExists: 8708,
12518 OverBrace: 9182,
12519 PlusMinus: 177,
12520 Therefore: 8756,
12521 ThinSpace: 8201,
12522 TripleDot: 8411,
12523 UnionPlus: 8846,
12524 backprime: 8245,
12525 backsimeq: 8909,
12526 bigotimes: 10754,
12527 centerdot: 183,
12528 checkmark: 10003,
12529 complexes: 8450,
12530 dotsquare: 8865,
12531 downarrow: 8595,
12532 gtrapprox: 10886,
12533 gtreqless: 8923,
12534 heartsuit: 9829,
12535 leftarrow: 8592,
12536 lesseqgtr: 8922,
12537 nparallel: 8742,
12538 nshortmid: 8740,
12539 nsubseteq: 8840,
12540 nsupseteq: 8841,
12541 pitchfork: 8916,
12542 rationals: 8474,
12543 spadesuit: 9824,
12544 subseteqq: 10949,
12545 subsetneq: 8842,
12546 supseteqq: 10950,
12547 supsetneq: 8843,
12548 therefore: 8756,
12549 triangleq: 8796,
12550 varpropto: 8733,
12551 DDotrahd: 10513,
12552 DotEqual: 8784,
12553 Integral: 8747,
12554 LessLess: 10913,
12555 NotEqual: 8800,
12556 NotTilde: 8769,
12557 PartialD: 8706,
12558 Precedes: 8826,
12559 RightTee: 8866,
12560 Succeeds: 8827,
12561 SuchThat: 8715,
12562 Superset: 8835,
12563 Uarrocir: 10569,
12564 UnderBar: 818,
12565 andslope: 10840,
12566 angmsdaa: 10664,
12567 angmsdab: 10665,
12568 angmsdac: 10666,
12569 angmsdad: 10667,
12570 angmsdae: 10668,
12571 angmsdaf: 10669,
12572 angmsdag: 10670,
12573 angmsdah: 10671,
12574 angrtvbd: 10653,
12575 approxeq: 8778,
12576 awconint: 8755,
12577 backcong: 8780,
12578 barwedge: 8965,
12579 bbrktbrk: 9142,
12580 bigoplus: 10753,
12581 bigsqcup: 10758,
12582 biguplus: 10756,
12583 bigwedge: 8896,
12584 boxminus: 8863,
12585 boxtimes: 8864,
12586 capbrcup: 10825,
12587 circledR: 174,
12588 circledS: 9416,
12589 cirfnint: 10768,
12590 clubsuit: 9827,
12591 cupbrcap: 10824,
12592 curlyvee: 8910,
12593 cwconint: 8754,
12594 doteqdot: 8785,
12595 dotminus: 8760,
12596 drbkarow: 10512,
12597 dzigrarr: 10239,
12598 elinters: 9191,
12599 emptyset: 8709,
12600 eqvparsl: 10725,
12601 fpartint: 10765,
12602 geqslant: 10878,
12603 gesdotol: 10884,
12604 gnapprox: 10890,
12605 hksearow: 10533,
12606 hkswarow: 10534,
12607 imagline: 8464,
12608 imagpart: 8465,
12609 infintie: 10717,
12610 integers: 8484,
12611 intercal: 8890,
12612 intlarhk: 10775,
12613 laemptyv: 10676,
12614 ldrushar: 10571,
12615 leqslant: 10877,
12616 lesdotor: 10883,
12617 llcorner: 8990,
12618 lnapprox: 10889,
12619 lrcorner: 8991,
12620 lurdshar: 10570,
12621 mapstoup: 8613,
12622 multimap: 8888,
12623 naturals: 8469,
12624 otimesas: 10806,
12625 parallel: 8741,
12626 plusacir: 10787,
12627 pointint: 10773,
12628 precneqq: 10933,
12629 precnsim: 8936,
12630 profalar: 9006,
12631 profline: 8978,
12632 profsurf: 8979,
12633 raemptyv: 10675,
12634 realpart: 8476,
12635 rppolint: 10770,
12636 rtriltri: 10702,
12637 scpolint: 10771,
12638 setminus: 8726,
12639 shortmid: 8739,
12640 smeparsl: 10724,
12641 sqsubset: 8847,
12642 sqsupset: 8848,
12643 subseteq: 8838,
12644 succneqq: 10934,
12645 succnsim: 8937,
12646 supseteq: 8839,
12647 thetasym: 977,
12648 thicksim: 8764,
12649 timesbar: 10801,
12650 triangle: 9653,
12651 triminus: 10810,
12652 trpezium: 9186,
12653 ulcorner: 8988,
12654 urcorner: 8989,
12655 varkappa: 1008,
12656 varsigma: 962,
12657 vartheta: 977,
12658 Because: 8757,
12659 Cayleys: 8493,
12660 Cconint: 8752,
12661 Cedilla: 184,
12662 Diamond: 8900,
12663 DownTee: 8868,
12664 Element: 8712,
12665 Epsilon: 917,
12666 Implies: 8658,
12667 LeftTee: 8867,
12668 NewLine: 10,
12669 NoBreak: 8288,
12670 NotLess: 8814,
12671 Omicron: 927,
12672 OverBar: 175,
12673 Product: 8719,
12674 UpArrow: 8593,
12675 Uparrow: 8657,
12676 Upsilon: 933,
12677 alefsym: 8501,
12678 angrtvb: 8894,
12679 angzarr: 9084,
12680 asympeq: 8781,
12681 backsim: 8765,
12682 because: 8757,
12683 bemptyv: 10672,
12684 between: 8812,
12685 bigcirc: 9711,
12686 bigodot: 10752,
12687 bigstar: 9733,
12688 boxplus: 8862,
12689 ccupssm: 10832,
12690 cemptyv: 10674,
12691 cirscir: 10690,
12692 coloneq: 8788,
12693 congdot: 10861,
12694 cudarrl: 10552,
12695 cudarrr: 10549,
12696 cularrp: 10557,
12697 curarrm: 10556,
12698 dbkarow: 10511,
12699 ddagger: 8225,
12700 ddotseq: 10871,
12701 demptyv: 10673,
12702 diamond: 8900,
12703 digamma: 989,
12704 dotplus: 8724,
12705 dwangle: 10662,
12706 epsilon: 949,
12707 eqcolon: 8789,
12708 equivDD: 10872,
12709 gesdoto: 10882,
12710 gtquest: 10876,
12711 gtrless: 8823,
12712 harrcir: 10568,
12713 intprod: 10812,
12714 isindot: 8949,
12715 larrbfs: 10527,
12716 larrsim: 10611,
12717 lbrksld: 10639,
12718 lbrkslu: 10637,
12719 ldrdhar: 10599,
12720 lesdoto: 10881,
12721 lessdot: 8918,
12722 lessgtr: 8822,
12723 lesssim: 8818,
12724 lotimes: 10804,
12725 lozenge: 9674,
12726 ltquest: 10875,
12727 luruhar: 10598,
12728 maltese: 10016,
12729 minusdu: 10794,
12730 napprox: 8777,
12731 natural: 9838,
12732 nearrow: 8599,
12733 nexists: 8708,
12734 notinva: 8713,
12735 notinvb: 8951,
12736 notinvc: 8950,
12737 notniva: 8716,
12738 notnivb: 8958,
12739 notnivc: 8957,
12740 npolint: 10772,
12741 nsqsube: 8930,
12742 nsqsupe: 8931,
12743 nvinfin: 10718,
12744 nwarrow: 8598,
12745 olcross: 10683,
12746 omicron: 959,
12747 orderof: 8500,
12748 orslope: 10839,
12749 pertenk: 8241,
12750 planckh: 8462,
12751 pluscir: 10786,
12752 plussim: 10790,
12753 plustwo: 10791,
12754 precsim: 8830,
12755 quatint: 10774,
12756 questeq: 8799,
12757 rarrbfs: 10528,
12758 rarrsim: 10612,
12759 rbrksld: 10638,
12760 rbrkslu: 10640,
12761 rdldhar: 10601,
12762 realine: 8475,
12763 rotimes: 10805,
12764 ruluhar: 10600,
12765 searrow: 8600,
12766 simplus: 10788,
12767 simrarr: 10610,
12768 subedot: 10947,
12769 submult: 10945,
12770 subplus: 10943,
12771 subrarr: 10617,
12772 succsim: 8831,
12773 supdsub: 10968,
12774 supedot: 10948,
12775 suphsub: 10967,
12776 suplarr: 10619,
12777 supmult: 10946,
12778 supplus: 10944,
12779 swarrow: 8601,
12780 topfork: 10970,
12781 triplus: 10809,
12782 tritime: 10811,
12783 uparrow: 8593,
12784 upsilon: 965,
12785 uwangle: 10663,
12786 vzigzag: 10650,
12787 zigrarr: 8669,
12788 Aacute: 193,
12789 Abreve: 258,
12790 Agrave: 192,
12791 Assign: 8788,
12792 Atilde: 195,
12793 Barwed: 8966,
12794 Bumpeq: 8782,
12795 Cacute: 262,
12796 Ccaron: 268,
12797 Ccedil: 199,
12798 Colone: 10868,
12799 Conint: 8751,
12800 CupCap: 8781,
12801 Dagger: 8225,
12802 Dcaron: 270,
12803 DotDot: 8412,
12804 Dstrok: 272,
12805 Eacute: 201,
12806 Ecaron: 282,
12807 Egrave: 200,
12808 Exists: 8707,
12809 ForAll: 8704,
12810 Gammad: 988,
12811 Gbreve: 286,
12812 Gcedil: 290,
12813 HARDcy: 1066,
12814 Hstrok: 294,
12815 Iacute: 205,
12816 Igrave: 204,
12817 Itilde: 296,
12818 Jsercy: 1032,
12819 Kcedil: 310,
12820 Lacute: 313,
12821 Lambda: 923,
12822 Lcaron: 317,
12823 Lcedil: 315,
12824 Lmidot: 319,
12825 Lstrok: 321,
12826 Nacute: 323,
12827 Ncaron: 327,
12828 Ncedil: 325,
12829 Ntilde: 209,
12830 Oacute: 211,
12831 Odblac: 336,
12832 Ograve: 210,
12833 Oslash: 216,
12834 Otilde: 213,
12835 Otimes: 10807,
12836 Racute: 340,
12837 Rarrtl: 10518,
12838 Rcaron: 344,
12839 Rcedil: 342,
12840 SHCHcy: 1065,
12841 SOFTcy: 1068,
12842 Sacute: 346,
12843 Scaron: 352,
12844 Scedil: 350,
12845 Square: 9633,
12846 Subset: 8912,
12847 Supset: 8913,
12848 Tcaron: 356,
12849 Tcedil: 354,
12850 Tstrok: 358,
12851 Uacute: 218,
12852 Ubreve: 364,
12853 Udblac: 368,
12854 Ugrave: 217,
12855 Utilde: 360,
12856 Vdashl: 10982,
12857 Verbar: 8214,
12858 Vvdash: 8874,
12859 Yacute: 221,
12860 Zacute: 377,
12861 Zcaron: 381,
12862 aacute: 225,
12863 abreve: 259,
12864 agrave: 224,
12865 andand: 10837,
12866 angmsd: 8737,
12867 angsph: 8738,
12868 apacir: 10863,
12869 approx: 8776,
12870 atilde: 227,
12871 barvee: 8893,
12872 barwed: 8965,
12873 becaus: 8757,
12874 bernou: 8492,
12875 bigcap: 8898,
12876 bigcup: 8899,
12877 bigvee: 8897,
12878 bkarow: 10509,
12879 bottom: 8869,
12880 bowtie: 8904,
12881 boxbox: 10697,
12882 bprime: 8245,
12883 brvbar: 166,
12884 bullet: 8226,
12885 bumpeq: 8783,
12886 cacute: 263,
12887 capand: 10820,
12888 capcap: 10827,
12889 capcup: 10823,
12890 capdot: 10816,
12891 ccaron: 269,
12892 ccedil: 231,
12893 circeq: 8791,
12894 cirmid: 10991,
12895 colone: 8788,
12896 commat: 64,
12897 compfn: 8728,
12898 conint: 8750,
12899 coprod: 8720,
12900 copysr: 8471,
12901 cularr: 8630,
12902 cupcap: 10822,
12903 cupcup: 10826,
12904 cupdot: 8845,
12905 curarr: 8631,
12906 curren: 164,
12907 cylcty: 9005,
12908 dagger: 8224,
12909 daleth: 8504,
12910 dcaron: 271,
12911 dfisht: 10623,
12912 divide: 247,
12913 divonx: 8903,
12914 dlcorn: 8990,
12915 dlcrop: 8973,
12916 dollar: 36,
12917 drcorn: 8991,
12918 drcrop: 8972,
12919 dstrok: 273,
12920 eacute: 233,
12921 easter: 10862,
12922 ecaron: 283,
12923 ecolon: 8789,
12924 egrave: 232,
12925 egsdot: 10904,
12926 elsdot: 10903,
12927 emptyv: 8709,
12928 emsp13: 8196,
12929 emsp14: 8197,
12930 eparsl: 10723,
12931 eqcirc: 8790,
12932 equals: 61,
12933 equest: 8799,
12934 female: 9792,
12935 ffilig: 64259,
12936 ffllig: 64260,
12937 forall: 8704,
12938 frac12: 189,
12939 frac13: 8531,
12940 frac14: 188,
12941 frac15: 8533,
12942 frac16: 8537,
12943 frac18: 8539,
12944 frac23: 8532,
12945 frac25: 8534,
12946 frac34: 190,
12947 frac35: 8535,
12948 frac38: 8540,
12949 frac45: 8536,
12950 frac56: 8538,
12951 frac58: 8541,
12952 frac78: 8542,
12953 gacute: 501,
12954 gammad: 989,
12955 gbreve: 287,
12956 gesdot: 10880,
12957 gesles: 10900,
12958 gtlPar: 10645,
12959 gtrarr: 10616,
12960 gtrdot: 8919,
12961 gtrsim: 8819,
12962 hairsp: 8202,
12963 hamilt: 8459,
12964 hardcy: 1098,
12965 hearts: 9829,
12966 hellip: 8230,
12967 hercon: 8889,
12968 homtht: 8763,
12969 horbar: 8213,
12970 hslash: 8463,
12971 hstrok: 295,
12972 hybull: 8259,
12973 hyphen: 8208,
12974 iacute: 237,
12975 igrave: 236,
12976 iiiint: 10764,
12977 iinfin: 10716,
12978 incare: 8453,
12979 inodot: 305,
12980 intcal: 8890,
12981 iquest: 191,
12982 isinsv: 8947,
12983 itilde: 297,
12984 jsercy: 1112,
12985 kappav: 1008,
12986 kcedil: 311,
12987 kgreen: 312,
12988 lAtail: 10523,
12989 lacute: 314,
12990 lagran: 8466,
12991 lambda: 955,
12992 langle: 10216,
12993 larrfs: 10525,
12994 larrhk: 8617,
12995 larrlp: 8619,
12996 larrpl: 10553,
12997 larrtl: 8610,
12998 latail: 10521,
12999 lbrace: 123,
13000 lbrack: 91,
13001 lcaron: 318,
13002 lcedil: 316,
13003 ldquor: 8222,
13004 lesdot: 10879,
13005 lesges: 10899,
13006 lfisht: 10620,
13007 lfloor: 8970,
13008 lharul: 10602,
13009 llhard: 10603,
13010 lmidot: 320,
13011 lmoust: 9136,
13012 loplus: 10797,
13013 lowast: 8727,
13014 lowbar: 95,
13015 lparlt: 10643,
13016 lrhard: 10605,
13017 lsaquo: 8249,
13018 lsquor: 8218,
13019 lstrok: 322,
13020 lthree: 8907,
13021 ltimes: 8905,
13022 ltlarr: 10614,
13023 ltrPar: 10646,
13024 mapsto: 8614,
13025 marker: 9646,
13026 mcomma: 10793,
13027 midast: 42,
13028 midcir: 10992,
13029 middot: 183,
13030 minusb: 8863,
13031 minusd: 8760,
13032 mnplus: 8723,
13033 models: 8871,
13034 mstpos: 8766,
13035 nVDash: 8879,
13036 nVdash: 8878,
13037 nacute: 324,
13038 ncaron: 328,
13039 ncedil: 326,
13040 nearhk: 10532,
13041 nequiv: 8802,
13042 nesear: 10536,
13043 nexist: 8708,
13044 nltrie: 8940,
13045 nprcue: 8928,
13046 nrtrie: 8941,
13047 nsccue: 8929,
13048 nsimeq: 8772,
13049 ntilde: 241,
13050 numero: 8470,
13051 nvDash: 8877,
13052 nvHarr: 10500,
13053 nvdash: 8876,
13054 nvlArr: 10498,
13055 nvrArr: 10499,
13056 nwarhk: 10531,
13057 nwnear: 10535,
13058 oacute: 243,
13059 odblac: 337,
13060 odsold: 10684,
13061 ograve: 242,
13062 ominus: 8854,
13063 origof: 8886,
13064 oslash: 248,
13065 otilde: 245,
13066 otimes: 8855,
13067 parsim: 10995,
13068 percnt: 37,
13069 period: 46,
13070 permil: 8240,
13071 phmmat: 8499,
13072 planck: 8463,
13073 plankv: 8463,
13074 plusdo: 8724,
13075 plusdu: 10789,
13076 plusmn: 177,
13077 preceq: 10927,
13078 primes: 8473,
13079 prnsim: 8936,
13080 propto: 8733,
13081 prurel: 8880,
13082 puncsp: 8200,
13083 qprime: 8279,
13084 rAtail: 10524,
13085 racute: 341,
13086 rangle: 10217,
13087 rarrap: 10613,
13088 rarrfs: 10526,
13089 rarrhk: 8618,
13090 rarrlp: 8620,
13091 rarrpl: 10565,
13092 rarrtl: 8611,
13093 ratail: 10522,
13094 rbrace: 125,
13095 rbrack: 93,
13096 rcaron: 345,
13097 rcedil: 343,
13098 rdquor: 8221,
13099 rfisht: 10621,
13100 rfloor: 8971,
13101 rharul: 10604,
13102 rmoust: 9137,
13103 roplus: 10798,
13104 rpargt: 10644,
13105 rsaquo: 8250,
13106 rsquor: 8217,
13107 rthree: 8908,
13108 rtimes: 8906,
13109 sacute: 347,
13110 scaron: 353,
13111 scedil: 351,
13112 scnsim: 8937,
13113 searhk: 10533,
13114 seswar: 10537,
13115 sfrown: 8994,
13116 shchcy: 1097,
13117 sigmaf: 962,
13118 sigmav: 962,
13119 simdot: 10858,
13120 smashp: 10803,
13121 softcy: 1100,
13122 solbar: 9023,
13123 spades: 9824,
13124 sqsube: 8849,
13125 sqsupe: 8850,
13126 square: 9633,
13127 squarf: 9642,
13128 ssetmn: 8726,
13129 ssmile: 8995,
13130 sstarf: 8902,
13131 subdot: 10941,
13132 subset: 8834,
13133 subsim: 10951,
13134 subsub: 10965,
13135 subsup: 10963,
13136 succeq: 10928,
13137 supdot: 10942,
13138 supset: 8835,
13139 supsim: 10952,
13140 supsub: 10964,
13141 supsup: 10966,
13142 swarhk: 10534,
13143 swnwar: 10538,
13144 target: 8982,
13145 tcaron: 357,
13146 tcedil: 355,
13147 telrec: 8981,
13148 there4: 8756,
13149 thetav: 977,
13150 thinsp: 8201,
13151 thksim: 8764,
13152 timesb: 8864,
13153 timesd: 10800,
13154 topbot: 9014,
13155 topcir: 10993,
13156 tprime: 8244,
13157 tridot: 9708,
13158 tstrok: 359,
13159 uacute: 250,
13160 ubreve: 365,
13161 udblac: 369,
13162 ufisht: 10622,
13163 ugrave: 249,
13164 ulcorn: 8988,
13165 ulcrop: 8975,
13166 urcorn: 8989,
13167 urcrop: 8974,
13168 utilde: 361,
13169 vangrt: 10652,
13170 varphi: 966,
13171 varrho: 1009,
13172 veebar: 8891,
13173 vellip: 8942,
13174 verbar: 124,
13175 wedbar: 10847,
13176 wedgeq: 8793,
13177 weierp: 8472,
13178 wreath: 8768,
13179 xoplus: 10753,
13180 xotime: 10754,
13181 xsqcup: 10758,
13182 xuplus: 10756,
13183 xwedge: 8896,
13184 yacute: 253,
13185 zacute: 378,
13186 zcaron: 382,
13187 zeetrf: 8488,
13188 AElig: 198,
13189 Acirc: 194,
13190 Alpha: 913,
13191 Amacr: 256,
13192 Aogon: 260,
13193 Aring: 197,
13194 Breve: 728,
13195 Ccirc: 264,
13196 Colon: 8759,
13197 Cross: 10799,
13198 Dashv: 10980,
13199 Delta: 916,
13200 Ecirc: 202,
13201 Emacr: 274,
13202 Eogon: 280,
13203 Equal: 10869,
13204 Gamma: 915,
13205 Gcirc: 284,
13206 Hacek: 711,
13207 Hcirc: 292,
13208 IJlig: 306,
13209 Icirc: 206,
13210 Imacr: 298,
13211 Iogon: 302,
13212 Iukcy: 1030,
13213 Jcirc: 308,
13214 Jukcy: 1028,
13215 Kappa: 922,
13216 OElig: 338,
13217 Ocirc: 212,
13218 Omacr: 332,
13219 Omega: 937,
13220 Prime: 8243,
13221 RBarr: 10512,
13222 Scirc: 348,
13223 Sigma: 931,
13224 THORN: 222,
13225 TRADE: 8482,
13226 TSHcy: 1035,
13227 Theta: 920,
13228 Tilde: 8764,
13229 Ubrcy: 1038,
13230 Ucirc: 219,
13231 Umacr: 362,
13232 Union: 8899,
13233 Uogon: 370,
13234 UpTee: 8869,
13235 Uring: 366,
13236 VDash: 8875,
13237 Vdash: 8873,
13238 Wcirc: 372,
13239 Wedge: 8896,
13240 Ycirc: 374,
13241 acirc: 226,
13242 acute: 180,
13243 aelig: 230,
13244 aleph: 8501,
13245 alpha: 945,
13246 amacr: 257,
13247 amalg: 10815,
13248 angle: 8736,
13249 angrt: 8735,
13250 angst: 8491,
13251 aogon: 261,
13252 aring: 229,
13253 asymp: 8776,
13254 awint: 10769,
13255 bcong: 8780,
13256 bdquo: 8222,
13257 bepsi: 1014,
13258 blank: 9251,
13259 blk12: 9618,
13260 blk14: 9617,
13261 blk34: 9619,
13262 block: 9608,
13263 boxDL: 9559,
13264 boxDR: 9556,
13265 boxDl: 9558,
13266 boxDr: 9555,
13267 boxHD: 9574,
13268 boxHU: 9577,
13269 boxHd: 9572,
13270 boxHu: 9575,
13271 boxUL: 9565,
13272 boxUR: 9562,
13273 boxUl: 9564,
13274 boxUr: 9561,
13275 boxVH: 9580,
13276 boxVL: 9571,
13277 boxVR: 9568,
13278 boxVh: 9579,
13279 boxVl: 9570,
13280 boxVr: 9567,
13281 boxdL: 9557,
13282 boxdR: 9554,
13283 boxdl: 9488,
13284 boxdr: 9484,
13285 boxhD: 9573,
13286 boxhU: 9576,
13287 boxhd: 9516,
13288 boxhu: 9524,
13289 boxuL: 9563,
13290 boxuR: 9560,
13291 boxul: 9496,
13292 boxur: 9492,
13293 boxvH: 9578,
13294 boxvL: 9569,
13295 boxvR: 9566,
13296 boxvh: 9532,
13297 boxvl: 9508,
13298 boxvr: 9500,
13299 breve: 728,
13300 bsemi: 8271,
13301 bsime: 8909,
13302 bsolb: 10693,
13303 bumpE: 10926,
13304 bumpe: 8783,
13305 caret: 8257,
13306 caron: 711,
13307 ccaps: 10829,
13308 ccirc: 265,
13309 ccups: 10828,
13310 cedil: 184,
13311 check: 10003,
13312 clubs: 9827,
13313 colon: 58,
13314 comma: 44,
13315 crarr: 8629,
13316 cross: 10007,
13317 csube: 10961,
13318 csupe: 10962,
13319 ctdot: 8943,
13320 cuepr: 8926,
13321 cuesc: 8927,
13322 cupor: 10821,
13323 cuvee: 8910,
13324 cuwed: 8911,
13325 cwint: 8753,
13326 dashv: 8867,
13327 dblac: 733,
13328 ddarr: 8650,
13329 delta: 948,
13330 dharl: 8643,
13331 dharr: 8642,
13332 diams: 9830,
13333 disin: 8946,
13334 doteq: 8784,
13335 dtdot: 8945,
13336 dtrif: 9662,
13337 duarr: 8693,
13338 duhar: 10607,
13339 eDDot: 10871,
13340 ecirc: 234,
13341 efDot: 8786,
13342 emacr: 275,
13343 empty: 8709,
13344 eogon: 281,
13345 eplus: 10865,
13346 epsiv: 949,
13347 eqsim: 8770,
13348 equiv: 8801,
13349 erDot: 8787,
13350 erarr: 10609,
13351 esdot: 8784,
13352 exist: 8707,
13353 fflig: 64256,
13354 filig: 64257,
13355 fllig: 64258,
13356 fltns: 9649,
13357 forkv: 10969,
13358 frasl: 8260,
13359 frown: 8994,
13360 gamma: 947,
13361 gcirc: 285,
13362 gescc: 10921,
13363 gimel: 8503,
13364 gneqq: 8809,
13365 gnsim: 8935,
13366 grave: 96,
13367 gsime: 10894,
13368 gsiml: 10896,
13369 gtcir: 10874,
13370 gtdot: 8919,
13371 harrw: 8621,
13372 hcirc: 293,
13373 hoarr: 8703,
13374 icirc: 238,
13375 iexcl: 161,
13376 iiint: 8749,
13377 iiota: 8489,
13378 ijlig: 307,
13379 imacr: 299,
13380 image: 8465,
13381 imath: 305,
13382 imped: 437,
13383 infin: 8734,
13384 iogon: 303,
13385 iprod: 10812,
13386 isinE: 8953,
13387 isins: 8948,
13388 isinv: 8712,
13389 iukcy: 1110,
13390 jcirc: 309,
13391 jmath: 567,
13392 jukcy: 1108,
13393 kappa: 954,
13394 lAarr: 8666,
13395 lBarr: 10510,
13396 langd: 10641,
13397 laquo: 171,
13398 larrb: 8676,
13399 lbarr: 10508,
13400 lbbrk: 10098,
13401 lbrke: 10635,
13402 lceil: 8968,
13403 ldquo: 8220,
13404 lescc: 10920,
13405 lhard: 8637,
13406 lharu: 8636,
13407 lhblk: 9604,
13408 llarr: 8647,
13409 lltri: 9722,
13410 lneqq: 8808,
13411 lnsim: 8934,
13412 loang: 10220,
13413 loarr: 8701,
13414 lobrk: 10214,
13415 lopar: 10629,
13416 lrarr: 8646,
13417 lrhar: 8651,
13418 lrtri: 8895,
13419 lsime: 10893,
13420 lsimg: 10895,
13421 lsquo: 8216,
13422 ltcir: 10873,
13423 ltdot: 8918,
13424 ltrie: 8884,
13425 ltrif: 9666,
13426 mDDot: 8762,
13427 mdash: 8212,
13428 micro: 181,
13429 minus: 8722,
13430 mumap: 8888,
13431 nabla: 8711,
13432 napos: 329,
13433 natur: 9838,
13434 ncong: 8775,
13435 ndash: 8211,
13436 neArr: 8663,
13437 nearr: 8599,
13438 ngsim: 8821,
13439 nhArr: 8654,
13440 nharr: 8622,
13441 nhpar: 10994,
13442 nlArr: 8653,
13443 nlarr: 8602,
13444 nless: 8814,
13445 nlsim: 8820,
13446 nltri: 8938,
13447 notin: 8713,
13448 notni: 8716,
13449 nprec: 8832,
13450 nrArr: 8655,
13451 nrarr: 8603,
13452 nrtri: 8939,
13453 nsime: 8772,
13454 nsmid: 8740,
13455 nspar: 8742,
13456 nsube: 8840,
13457 nsucc: 8833,
13458 nsupe: 8841,
13459 numsp: 8199,
13460 nwArr: 8662,
13461 nwarr: 8598,
13462 ocirc: 244,
13463 odash: 8861,
13464 oelig: 339,
13465 ofcir: 10687,
13466 ohbar: 10677,
13467 olarr: 8634,
13468 olcir: 10686,
13469 oline: 8254,
13470 omacr: 333,
13471 omega: 969,
13472 operp: 10681,
13473 oplus: 8853,
13474 orarr: 8635,
13475 order: 8500,
13476 ovbar: 9021,
13477 parsl: 11005,
13478 phone: 9742,
13479 plusb: 8862,
13480 pluse: 10866,
13481 pound: 163,
13482 prcue: 8828,
13483 prime: 8242,
13484 prnap: 10937,
13485 prsim: 8830,
13486 quest: 63,
13487 rAarr: 8667,
13488 rBarr: 10511,
13489 radic: 8730,
13490 rangd: 10642,
13491 range: 10661,
13492 raquo: 187,
13493 rarrb: 8677,
13494 rarrc: 10547,
13495 rarrw: 8605,
13496 ratio: 8758,
13497 rbarr: 10509,
13498 rbbrk: 10099,
13499 rbrke: 10636,
13500 rceil: 8969,
13501 rdquo: 8221,
13502 reals: 8477,
13503 rhard: 8641,
13504 rharu: 8640,
13505 rlarr: 8644,
13506 rlhar: 8652,
13507 rnmid: 10990,
13508 roang: 10221,
13509 roarr: 8702,
13510 robrk: 10215,
13511 ropar: 10630,
13512 rrarr: 8649,
13513 rsquo: 8217,
13514 rtrie: 8885,
13515 rtrif: 9656,
13516 sbquo: 8218,
13517 sccue: 8829,
13518 scirc: 349,
13519 scnap: 10938,
13520 scsim: 8831,
13521 sdotb: 8865,
13522 sdote: 10854,
13523 seArr: 8664,
13524 searr: 8600,
13525 setmn: 8726,
13526 sharp: 9839,
13527 sigma: 963,
13528 simeq: 8771,
13529 simgE: 10912,
13530 simlE: 10911,
13531 simne: 8774,
13532 slarr: 8592,
13533 smile: 8995,
13534 sqcap: 8851,
13535 sqcup: 8852,
13536 sqsub: 8847,
13537 sqsup: 8848,
13538 srarr: 8594,
13539 starf: 9733,
13540 strns: 175,
13541 subnE: 10955,
13542 subne: 8842,
13543 supnE: 10956,
13544 supne: 8843,
13545 swArr: 8665,
13546 swarr: 8601,
13547 szlig: 223,
13548 theta: 952,
13549 thkap: 8776,
13550 thorn: 254,
13551 tilde: 732,
13552 times: 215,
13553 trade: 8482,
13554 trisb: 10701,
13555 tshcy: 1115,
13556 twixt: 8812,
13557 ubrcy: 1118,
13558 ucirc: 251,
13559 udarr: 8645,
13560 udhar: 10606,
13561 uharl: 8639,
13562 uharr: 8638,
13563 uhblk: 9600,
13564 ultri: 9720,
13565 umacr: 363,
13566 uogon: 371,
13567 uplus: 8846,
13568 upsih: 978,
13569 uring: 367,
13570 urtri: 9721,
13571 utdot: 8944,
13572 utrif: 9652,
13573 uuarr: 8648,
13574 vBarv: 10985,
13575 vDash: 8872,
13576 varpi: 982,
13577 vdash: 8866,
13578 veeeq: 8794,
13579 vltri: 8882,
13580 vprop: 8733,
13581 vrtri: 8883,
13582 wcirc: 373,
13583 wedge: 8743,
13584 xcirc: 9711,
13585 xdtri: 9661,
13586 xhArr: 10234,
13587 xharr: 10231,
13588 xlArr: 10232,
13589 xlarr: 10229,
13590 xodot: 10752,
13591 xrArr: 10233,
13592 xrarr: 10230,
13593 xutri: 9651,
13594 ycirc: 375,
13595 Aopf: 120120,
13596 Ascr: 119964,
13597 Auml: 196,
13598 Barv: 10983,
13599 Beta: 914,
13600 Bopf: 120121,
13601 Bscr: 8492,
13602 CHcy: 1063,
13603 COPY: 169,
13604 Cdot: 266,
13605 Copf: 8450,
13606 Cscr: 119966,
13607 DJcy: 1026,
13608 DScy: 1029,
13609 DZcy: 1039,
13610 Darr: 8609,
13611 Dopf: 120123,
13612 Dscr: 119967,
13613 Edot: 278,
13614 Eopf: 120124,
13615 Escr: 8496,
13616 Esim: 10867,
13617 Euml: 203,
13618 Fopf: 120125,
13619 Fscr: 8497,
13620 GJcy: 1027,
13621 Gdot: 288,
13622 Gopf: 120126,
13623 Gscr: 119970,
13624 Hopf: 8461,
13625 Hscr: 8459,
13626 IEcy: 1045,
13627 IOcy: 1025,
13628 Idot: 304,
13629 Iopf: 120128,
13630 Iota: 921,
13631 Iscr: 8464,
13632 Iuml: 207,
13633 Jopf: 120129,
13634 Jscr: 119973,
13635 KHcy: 1061,
13636 KJcy: 1036,
13637 Kopf: 120130,
13638 Kscr: 119974,
13639 LJcy: 1033,
13640 Lang: 10218,
13641 Larr: 8606,
13642 Lopf: 120131,
13643 Lscr: 8466,
13644 Mopf: 120132,
13645 Mscr: 8499,
13646 NJcy: 1034,
13647 Nopf: 8469,
13648 Nscr: 119977,
13649 Oopf: 120134,
13650 Oscr: 119978,
13651 Ouml: 214,
13652 Popf: 8473,
13653 Pscr: 119979,
13654 QUOT: 34,
13655 Qopf: 8474,
13656 Qscr: 119980,
13657 Rang: 10219,
13658 Rarr: 8608,
13659 Ropf: 8477,
13660 Rscr: 8475,
13661 SHcy: 1064,
13662 Sopf: 120138,
13663 Sqrt: 8730,
13664 Sscr: 119982,
13665 Star: 8902,
13666 TScy: 1062,
13667 Topf: 120139,
13668 Tscr: 119983,
13669 Uarr: 8607,
13670 Uopf: 120140,
13671 Upsi: 978,
13672 Uscr: 119984,
13673 Uuml: 220,
13674 Vbar: 10987,
13675 Vert: 8214,
13676 Vopf: 120141,
13677 Vscr: 119985,
13678 Wopf: 120142,
13679 Wscr: 119986,
13680 Xopf: 120143,
13681 Xscr: 119987,
13682 YAcy: 1071,
13683 YIcy: 1031,
13684 YUcy: 1070,
13685 Yopf: 120144,
13686 Yscr: 119988,
13687 Yuml: 376,
13688 ZHcy: 1046,
13689 Zdot: 379,
13690 Zeta: 918,
13691 Zopf: 8484,
13692 Zscr: 119989,
13693 andd: 10844,
13694 andv: 10842,
13695 ange: 10660,
13696 aopf: 120146,
13697 apid: 8779,
13698 apos: 39,
13699 ascr: 119990,
13700 auml: 228,
13701 bNot: 10989,
13702 bbrk: 9141,
13703 beta: 946,
13704 beth: 8502,
13705 bnot: 8976,
13706 bopf: 120147,
13707 boxH: 9552,
13708 boxV: 9553,
13709 boxh: 9472,
13710 boxv: 9474,
13711 bscr: 119991,
13712 bsim: 8765,
13713 bsol: 92,
13714 bull: 8226,
13715 bump: 8782,
13716 cdot: 267,
13717 cent: 162,
13718 chcy: 1095,
13719 cirE: 10691,
13720 circ: 710,
13721 cire: 8791,
13722 comp: 8705,
13723 cong: 8773,
13724 copf: 120148,
13725 copy: 169,
13726 cscr: 119992,
13727 csub: 10959,
13728 csup: 10960,
13729 dArr: 8659,
13730 dHar: 10597,
13731 darr: 8595,
13732 dash: 8208,
13733 diam: 8900,
13734 djcy: 1106,
13735 dopf: 120149,
13736 dscr: 119993,
13737 dscy: 1109,
13738 dsol: 10742,
13739 dtri: 9663,
13740 dzcy: 1119,
13741 eDot: 8785,
13742 ecir: 8790,
13743 edot: 279,
13744 emsp: 8195,
13745 ensp: 8194,
13746 eopf: 120150,
13747 epar: 8917,
13748 epsi: 1013,
13749 escr: 8495,
13750 esim: 8770,
13751 euml: 235,
13752 euro: 8364,
13753 excl: 33,
13754 flat: 9837,
13755 fnof: 402,
13756 fopf: 120151,
13757 fork: 8916,
13758 fscr: 119995,
13759 gdot: 289,
13760 geqq: 8807,
13761 gjcy: 1107,
13762 gnap: 10890,
13763 gneq: 10888,
13764 gopf: 120152,
13765 gscr: 8458,
13766 gsim: 8819,
13767 gtcc: 10919,
13768 hArr: 8660,
13769 half: 189,
13770 harr: 8596,
13771 hbar: 8463,
13772 hopf: 120153,
13773 hscr: 119997,
13774 iecy: 1077,
13775 imof: 8887,
13776 iocy: 1105,
13777 iopf: 120154,
13778 iota: 953,
13779 iscr: 119998,
13780 isin: 8712,
13781 iuml: 239,
13782 jopf: 120155,
13783 jscr: 119999,
13784 khcy: 1093,
13785 kjcy: 1116,
13786 kopf: 120156,
13787 kscr: 120000,
13788 lArr: 8656,
13789 lHar: 10594,
13790 lang: 10216,
13791 larr: 8592,
13792 late: 10925,
13793 lcub: 123,
13794 ldca: 10550,
13795 ldsh: 8626,
13796 leqq: 8806,
13797 ljcy: 1113,
13798 lnap: 10889,
13799 lneq: 10887,
13800 lopf: 120157,
13801 lozf: 10731,
13802 lpar: 40,
13803 lscr: 120001,
13804 lsim: 8818,
13805 lsqb: 91,
13806 ltcc: 10918,
13807 ltri: 9667,
13808 macr: 175,
13809 male: 9794,
13810 malt: 10016,
13811 mlcp: 10971,
13812 mldr: 8230,
13813 mopf: 120158,
13814 mscr: 120002,
13815 nbsp: 160,
13816 ncap: 10819,
13817 ncup: 10818,
13818 ngeq: 8817,
13819 ngtr: 8815,
13820 nisd: 8954,
13821 njcy: 1114,
13822 nldr: 8229,
13823 nleq: 8816,
13824 nmid: 8740,
13825 nopf: 120159,
13826 npar: 8742,
13827 nscr: 120003,
13828 nsim: 8769,
13829 nsub: 8836,
13830 nsup: 8837,
13831 ntgl: 8825,
13832 ntlg: 8824,
13833 oast: 8859,
13834 ocir: 8858,
13835 odiv: 10808,
13836 odot: 8857,
13837 ogon: 731,
13838 oint: 8750,
13839 omid: 10678,
13840 oopf: 120160,
13841 opar: 10679,
13842 ordf: 170,
13843 ordm: 186,
13844 oror: 10838,
13845 oscr: 8500,
13846 osol: 8856,
13847 ouml: 246,
13848 para: 182,
13849 part: 8706,
13850 perp: 8869,
13851 phiv: 966,
13852 plus: 43,
13853 popf: 120161,
13854 prap: 10935,
13855 prec: 8826,
13856 prnE: 10933,
13857 prod: 8719,
13858 prop: 8733,
13859 pscr: 120005,
13860 qint: 10764,
13861 qopf: 120162,
13862 qscr: 120006,
13863 quot: 34,
13864 rArr: 8658,
13865 rHar: 10596,
13866 race: 10714,
13867 rang: 10217,
13868 rarr: 8594,
13869 rcub: 125,
13870 rdca: 10551,
13871 rdsh: 8627,
13872 real: 8476,
13873 rect: 9645,
13874 rhov: 1009,
13875 ring: 730,
13876 ropf: 120163,
13877 rpar: 41,
13878 rscr: 120007,
13879 rsqb: 93,
13880 rtri: 9657,
13881 scap: 10936,
13882 scnE: 10934,
13883 sdot: 8901,
13884 sect: 167,
13885 semi: 59,
13886 sext: 10038,
13887 shcy: 1096,
13888 sime: 8771,
13889 simg: 10910,
13890 siml: 10909,
13891 smid: 8739,
13892 smte: 10924,
13893 solb: 10692,
13894 sopf: 120164,
13895 spar: 8741,
13896 squf: 9642,
13897 sscr: 120008,
13898 star: 9734,
13899 subE: 10949,
13900 sube: 8838,
13901 succ: 8827,
13902 sung: 9834,
13903 sup1: 185,
13904 sup2: 178,
13905 sup3: 179,
13906 supE: 10950,
13907 supe: 8839,
13908 tbrk: 9140,
13909 tdot: 8411,
13910 tint: 8749,
13911 toea: 10536,
13912 topf: 120165,
13913 tosa: 10537,
13914 trie: 8796,
13915 tscr: 120009,
13916 tscy: 1094,
13917 uArr: 8657,
13918 uHar: 10595,
13919 uarr: 8593,
13920 uopf: 120166,
13921 upsi: 965,
13922 uscr: 120010,
13923 utri: 9653,
13924 uuml: 252,
13925 vArr: 8661,
13926 vBar: 10984,
13927 varr: 8597,
13928 vert: 124,
13929 vopf: 120167,
13930 vscr: 120011,
13931 wopf: 120168,
13932 wscr: 120012,
13933 xcap: 8898,
13934 xcup: 8899,
13935 xmap: 10236,
13936 xnis: 8955,
13937 xopf: 120169,
13938 xscr: 120013,
13939 xvee: 8897,
13940 yacy: 1103,
13941 yicy: 1111,
13942 yopf: 120170,
13943 yscr: 120014,
13944 yucy: 1102,
13945 yuml: 255,
13946 zdot: 380,
13947 zeta: 950,
13948 zhcy: 1078,
13949 zopf: 120171,
13950 zscr: 120015,
13951 zwnj: 8204,
13952 AMP: 38,
13953 Acy: 1040,
13954 Afr: 120068,
13955 And: 10835,
13956 Bcy: 1041,
13957 Bfr: 120069,
13958 Cap: 8914,
13959 Cfr: 8493,
13960 Chi: 935,
13961 Cup: 8915,
13962 Dcy: 1044,
13963 Del: 8711,
13964 Dfr: 120071,
13965 Dot: 168,
13966 ENG: 330,
13967 ETH: 208,
13968 Ecy: 1069,
13969 Efr: 120072,
13970 Eta: 919,
13971 Fcy: 1060,
13972 Ffr: 120073,
13973 Gcy: 1043,
13974 Gfr: 120074,
13975 Hat: 94,
13976 Hfr: 8460,
13977 Icy: 1048,
13978 Ifr: 8465,
13979 Int: 8748,
13980 Jcy: 1049,
13981 Jfr: 120077,
13982 Kcy: 1050,
13983 Kfr: 120078,
13984 Lcy: 1051,
13985 Lfr: 120079,
13986 Lsh: 8624,
13987 Map: 10501,
13988 Mcy: 1052,
13989 Mfr: 120080,
13990 Ncy: 1053,
13991 Nfr: 120081,
13992 Not: 10988,
13993 Ocy: 1054,
13994 Ofr: 120082,
13995 Pcy: 1055,
13996 Pfr: 120083,
13997 Phi: 934,
13998 Psi: 936,
13999 Qfr: 120084,
14000 REG: 174,
14001 Rcy: 1056,
14002 Rfr: 8476,
14003 Rho: 929,
14004 Rsh: 8625,
14005 Scy: 1057,
14006 Sfr: 120086,
14007 Sub: 8912,
14008 Sum: 8721,
14009 Sup: 8913,
14010 Tab: 9,
14011 Tau: 932,
14012 Tcy: 1058,
14013 Tfr: 120087,
14014 Ucy: 1059,
14015 Ufr: 120088,
14016 Vcy: 1042,
14017 Vee: 8897,
14018 Vfr: 120089,
14019 Wfr: 120090,
14020 Xfr: 120091,
14021 Ycy: 1067,
14022 Yfr: 120092,
14023 Zcy: 1047,
14024 Zfr: 8488,
14025 acd: 8767,
14026 acy: 1072,
14027 afr: 120094,
14028 amp: 38,
14029 and: 8743,
14030 ang: 8736,
14031 apE: 10864,
14032 ape: 8778,
14033 ast: 42,
14034 bcy: 1073,
14035 bfr: 120095,
14036 bot: 8869,
14037 cap: 8745,
14038 cfr: 120096,
14039 chi: 967,
14040 cir: 9675,
14041 cup: 8746,
14042 dcy: 1076,
14043 deg: 176,
14044 dfr: 120097,
14045 die: 168,
14046 div: 247,
14047 dot: 729,
14048 ecy: 1101,
14049 efr: 120098,
14050 egs: 10902,
14051 ell: 8467,
14052 els: 10901,
14053 eng: 331,
14054 eta: 951,
14055 eth: 240,
14056 fcy: 1092,
14057 ffr: 120099,
14058 gEl: 10892,
14059 gap: 10886,
14060 gcy: 1075,
14061 gel: 8923,
14062 geq: 8805,
14063 ges: 10878,
14064 gfr: 120100,
14065 ggg: 8921,
14066 glE: 10898,
14067 gla: 10917,
14068 glj: 10916,
14069 gnE: 8809,
14070 gne: 10888,
14071 hfr: 120101,
14072 icy: 1080,
14073 iff: 8660,
14074 ifr: 120102,
14075 int: 8747,
14076 jcy: 1081,
14077 jfr: 120103,
14078 kcy: 1082,
14079 kfr: 120104,
14080 lEg: 10891,
14081 lap: 10885,
14082 lat: 10923,
14083 lcy: 1083,
14084 leg: 8922,
14085 leq: 8804,
14086 les: 10877,
14087 lfr: 120105,
14088 lgE: 10897,
14089 lnE: 8808,
14090 lne: 10887,
14091 loz: 9674,
14092 lrm: 8206,
14093 lsh: 8624,
14094 map: 8614,
14095 mcy: 1084,
14096 mfr: 120106,
14097 mho: 8487,
14098 mid: 8739,
14099 nap: 8777,
14100 ncy: 1085,
14101 nfr: 120107,
14102 nge: 8817,
14103 ngt: 8815,
14104 nis: 8956,
14105 niv: 8715,
14106 nle: 8816,
14107 nlt: 8814,
14108 not: 172,
14109 npr: 8832,
14110 nsc: 8833,
14111 num: 35,
14112 ocy: 1086,
14113 ofr: 120108,
14114 ogt: 10689,
14115 ohm: 8486,
14116 olt: 10688,
14117 ord: 10845,
14118 orv: 10843,
14119 par: 8741,
14120 pcy: 1087,
14121 pfr: 120109,
14122 phi: 966,
14123 piv: 982,
14124 prE: 10931,
14125 pre: 10927,
14126 psi: 968,
14127 qfr: 120110,
14128 rcy: 1088,
14129 reg: 174,
14130 rfr: 120111,
14131 rho: 961,
14132 rlm: 8207,
14133 rsh: 8625,
14134 scE: 10932,
14135 sce: 10928,
14136 scy: 1089,
14137 sfr: 120112,
14138 shy: 173,
14139 sim: 8764,
14140 smt: 10922,
14141 sol: 47,
14142 squ: 9633,
14143 sub: 8834,
14144 sum: 8721,
14145 sup: 8835,
14146 tau: 964,
14147 tcy: 1090,
14148 tfr: 120113,
14149 top: 8868,
14150 ucy: 1091,
14151 ufr: 120114,
14152 uml: 168,
14153 vcy: 1074,
14154 vee: 8744,
14155 vfr: 120115,
14156 wfr: 120116,
14157 xfr: 120117,
14158 ycy: 1099,
14159 yen: 165,
14160 yfr: 120118,
14161 zcy: 1079,
14162 zfr: 120119,
14163 zwj: 8205,
14164 DD: 8517,
14165 GT: 62,
14166 Gg: 8921,
14167 Gt: 8811,
14168 Im: 8465,
14169 LT: 60,
14170 Ll: 8920,
14171 Lt: 8810,
14172 Mu: 924,
14173 Nu: 925,
14174 Or: 10836,
14175 Pi: 928,
14176 Pr: 10939,
14177 Re: 8476,
14178 Sc: 10940,
14179 Xi: 926,
14180 ac: 8766,
14181 af: 8289,
14182 ap: 8776,
14183 dd: 8518,
14184 ee: 8519,
14185 eg: 10906,
14186 el: 10905,
14187 gE: 8807,
14188 ge: 8805,
14189 gg: 8811,
14190 gl: 8823,
14191 gt: 62,
14192 ic: 8291,
14193 ii: 8520,
14194 in: 8712,
14195 it: 8290,
14196 lE: 8806,
14197 le: 8804,
14198 lg: 8822,
14199 ll: 8810,
14200 lt: 60,
14201 mp: 8723,
14202 mu: 956,
14203 ne: 8800,
14204 ni: 8715,
14205 nu: 957,
14206 oS: 9416,
14207 or: 8744,
14208 pi: 960,
14209 pm: 177,
14210 pr: 8826,
14211 rx: 8478,
14212 sc: 8827,
14213 wp: 8472,
14214 wr: 8768,
14215 xi: 958
14216};
14217
14218const windows_1252 = [
14219 8364,
14220 129,
14221 8218,
14222 402,
14223 8222,
14224 8230,
14225 8224,
14226 8225,
14227 710,
14228 8240,
14229 352,
14230 8249,
14231 338,
14232 141,
14233 381,
14234 143,
14235 144,
14236 8216,
14237 8217,
14238 8220,
14239 8221,
14240 8226,
14241 8211,
14242 8212,
14243 732,
14244 8482,
14245 353,
14246 8250,
14247 339,
14248 157,
14249 382,
14250 376
14251];
14252const entity_pattern = new RegExp(`&(#?(?:x[\\w\\d]+|\\d+|${Object.keys(entities).join('|')}))(?:;|\\b)`, 'g');
14253function decode_character_references(html) {
14254 return html.replace(entity_pattern, (match, entity) => {
14255 let code;
14256 // Handle named entities
14257 if (entity[0] !== '#') {
14258 code = entities[entity];
14259 }
14260 else if (entity[1] === 'x') {
14261 code = parseInt(entity.substring(2), 16);
14262 }
14263 else {
14264 code = parseInt(entity.substring(1), 10);
14265 }
14266 if (!code) {
14267 return match;
14268 }
14269 return String.fromCodePoint(validate_code(code));
14270 });
14271}
14272const NUL = 0;
14273// some code points are verboten. If we were inserting HTML, the browser would replace the illegal
14274// code points with alternatives in some cases - since we're bypassing that mechanism, we need
14275// to replace them ourselves
14276//
14277// Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
14278function validate_code(code) {
14279 // line feed becomes generic whitespace
14280 if (code === 10) {
14281 return 32;
14282 }
14283 // ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
14284 if (code < 128) {
14285 return code;
14286 }
14287 // code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
14288 // to correct the mistake or we'll end up with missing € signs and so on
14289 if (code <= 159) {
14290 return windows_1252[code - 128];
14291 }
14292 // basic multilingual plane
14293 if (code < 55296) {
14294 return code;
14295 }
14296 // UTF-16 surrogate halves
14297 if (code <= 57343) {
14298 return NUL;
14299 }
14300 // rest of the basic multilingual plane
14301 if (code <= 65535) {
14302 return code;
14303 }
14304 // supplementary multilingual plane 0x10000 - 0x1ffff
14305 if (code >= 65536 && code <= 131071) {
14306 return code;
14307 }
14308 // supplementary ideographic plane 0x20000 - 0x2ffff
14309 if (code >= 131072 && code <= 196607) {
14310 return code;
14311 }
14312 return NUL;
14313}
14314// based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
14315const disallowed_contents = new Map([
14316 ['li', new Set(['li'])],
14317 ['dt', new Set(['dt', 'dd'])],
14318 ['dd', new Set(['dt', 'dd'])],
14319 [
14320 'p',
14321 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(' '))
14322 ],
14323 ['rt', new Set(['rt', 'rp'])],
14324 ['rp', new Set(['rt', 'rp'])],
14325 ['optgroup', new Set(['optgroup'])],
14326 ['option', new Set(['option', 'optgroup'])],
14327 ['thead', new Set(['tbody', 'tfoot'])],
14328 ['tbody', new Set(['tbody', 'tfoot'])],
14329 ['tfoot', new Set(['tbody'])],
14330 ['tr', new Set(['tr', 'tbody'])],
14331 ['td', new Set(['td', 'th', 'tr'])],
14332 ['th', new Set(['td', 'th', 'tr'])]
14333]);
14334// can this be a child of the parent element, or does it implicitly
14335// close it, like `<li>one<li>two`?
14336function closing_tag_omitted(current, next) {
14337 if (disallowed_contents.has(current)) {
14338 if (!next || disallowed_contents.get(current).has(next)) {
14339 return true;
14340 }
14341 }
14342 return false;
14343}
14344
14345// Adapted from https://github.com/acornjs/acorn/blob/6584815dca7440e00de841d1dad152302fdd7ca5/src/tokenize.js
14346// Reproduced under MIT License https://github.com/acornjs/acorn/blob/master/LICENSE
14347function full_char_code_at(str, i) {
14348 const code = str.charCodeAt(i);
14349 if (code <= 0xd7ff || code >= 0xe000)
14350 return code;
14351 const next = str.charCodeAt(i + 1);
14352 return (code << 10) + next - 0x35fdc00;
14353}
14354
14355const globals = new Set([
14356 'alert',
14357 'Array',
14358 'Boolean',
14359 'clearInterval',
14360 'clearTimeout',
14361 'confirm',
14362 'console',
14363 'Date',
14364 'decodeURI',
14365 'decodeURIComponent',
14366 'document',
14367 'Element',
14368 'encodeURI',
14369 'encodeURIComponent',
14370 'Error',
14371 'EvalError',
14372 'Event',
14373 'EventSource',
14374 'fetch',
14375 'global',
14376 'globalThis',
14377 'history',
14378 'Infinity',
14379 'InternalError',
14380 'Intl',
14381 'isFinite',
14382 'isNaN',
14383 'JSON',
14384 'localStorage',
14385 'location',
14386 'Map',
14387 'Math',
14388 'NaN',
14389 'navigator',
14390 'Number',
14391 'Node',
14392 'Object',
14393 'parseFloat',
14394 'parseInt',
14395 'process',
14396 'Promise',
14397 'prompt',
14398 'RangeError',
14399 'ReferenceError',
14400 'RegExp',
14401 'sessionStorage',
14402 'Set',
14403 'setInterval',
14404 'setTimeout',
14405 'String',
14406 'SyntaxError',
14407 'TypeError',
14408 'undefined',
14409 'URIError',
14410 'URL',
14411 'window'
14412]);
14413const reserved = new Set([
14414 'arguments',
14415 'await',
14416 'break',
14417 'case',
14418 'catch',
14419 'class',
14420 'const',
14421 'continue',
14422 'debugger',
14423 'default',
14424 'delete',
14425 'do',
14426 'else',
14427 'enum',
14428 'eval',
14429 'export',
14430 'extends',
14431 'false',
14432 'finally',
14433 'for',
14434 'function',
14435 'if',
14436 'implements',
14437 'import',
14438 'in',
14439 'instanceof',
14440 'interface',
14441 'let',
14442 'new',
14443 'null',
14444 'package',
14445 'private',
14446 'protected',
14447 'public',
14448 'return',
14449 'static',
14450 'super',
14451 'switch',
14452 'this',
14453 'throw',
14454 'true',
14455 'try',
14456 'typeof',
14457 'var',
14458 'void',
14459 'while',
14460 'with',
14461 'yield'
14462]);
14463const void_element_names = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
14464function is_void(name) {
14465 return void_element_names.test(name) || name.toLowerCase() === '!doctype';
14466}
14467function is_valid(str) {
14468 let i = 0;
14469 while (i < str.length) {
14470 const code = full_char_code_at(str, i);
14471 if (!(i === 0 ? isIdentifierStart : isIdentifierChar)(code, true))
14472 return false;
14473 i += code <= 0xffff ? 1 : 2;
14474 }
14475 return true;
14476}
14477function sanitize(name) {
14478 return name
14479 .replace(/[^a-zA-Z0-9_]+/g, '_')
14480 .replace(/^_/, '')
14481 .replace(/_$/, '')
14482 .replace(/^[0-9]/, '_$&');
14483}
14484
14485function fuzzymatch(name, names) {
14486 const set = new FuzzySet(names);
14487 const matches = set.get(name);
14488 return matches && matches[0] && matches[0][0] > 0.7 ? matches[0][1] : null;
14489}
14490// adapted from https://github.com/Glench/fuzzyset.js/blob/master/lib/fuzzyset.js
14491// BSD Licensed
14492const GRAM_SIZE_LOWER = 2;
14493const GRAM_SIZE_UPPER = 3;
14494// return an edit distance from 0 to 1
14495function _distance(str1, str2) {
14496 if (str1 === null && str2 === null) {
14497 throw 'Trying to compare two null values';
14498 }
14499 if (str1 === null || str2 === null)
14500 return 0;
14501 str1 = String(str1);
14502 str2 = String(str2);
14503 const distance = levenshtein(str1, str2);
14504 if (str1.length > str2.length) {
14505 return 1 - distance / str1.length;
14506 }
14507 else {
14508 return 1 - distance / str2.length;
14509 }
14510}
14511// helper functions
14512function levenshtein(str1, str2) {
14513 const current = [];
14514 let prev;
14515 let value;
14516 for (let i = 0; i <= str2.length; i++) {
14517 for (let j = 0; j <= str1.length; j++) {
14518 if (i && j) {
14519 if (str1.charAt(j - 1) === str2.charAt(i - 1)) {
14520 value = prev;
14521 }
14522 else {
14523 value = Math.min(current[j], current[j - 1], prev) + 1;
14524 }
14525 }
14526 else {
14527 value = i + j;
14528 }
14529 prev = current[j];
14530 current[j] = value;
14531 }
14532 }
14533 return current.pop();
14534}
14535const non_word_regex = /[^\w, ]+/;
14536function iterate_grams(value, gram_size = 2) {
14537 const simplified = '-' + value.toLowerCase().replace(non_word_regex, '') + '-';
14538 const len_diff = gram_size - simplified.length;
14539 const results = [];
14540 if (len_diff > 0) {
14541 for (let i = 0; i < len_diff; ++i) {
14542 value += '-';
14543 }
14544 }
14545 for (let i = 0; i < simplified.length - gram_size + 1; ++i) {
14546 results.push(simplified.slice(i, i + gram_size));
14547 }
14548 return results;
14549}
14550function gram_counter(value, gram_size = 2) {
14551 // return an object where key=gram, value=number of occurrences
14552 const result = {};
14553 const grams = iterate_grams(value, gram_size);
14554 let i = 0;
14555 for (i; i < grams.length; ++i) {
14556 if (grams[i] in result) {
14557 result[grams[i]] += 1;
14558 }
14559 else {
14560 result[grams[i]] = 1;
14561 }
14562 }
14563 return result;
14564}
14565function sort_descending(a, b) {
14566 return b[0] - a[0];
14567}
14568class FuzzySet {
14569 constructor(arr) {
14570 this.exact_set = {};
14571 this.match_dict = {};
14572 this.items = {};
14573 // initialization
14574 for (let i = GRAM_SIZE_LOWER; i < GRAM_SIZE_UPPER + 1; ++i) {
14575 this.items[i] = [];
14576 }
14577 // add all the items to the set
14578 for (let i = 0; i < arr.length; ++i) {
14579 this.add(arr[i]);
14580 }
14581 }
14582 add(value) {
14583 const normalized_value = value.toLowerCase();
14584 if (normalized_value in this.exact_set) {
14585 return false;
14586 }
14587 let i = GRAM_SIZE_LOWER;
14588 for (i; i < GRAM_SIZE_UPPER + 1; ++i) {
14589 this._add(value, i);
14590 }
14591 }
14592 _add(value, gram_size) {
14593 const normalized_value = value.toLowerCase();
14594 const items = this.items[gram_size] || [];
14595 const index = items.length;
14596 items.push(0);
14597 const gram_counts = gram_counter(normalized_value, gram_size);
14598 let sum_of_square_gram_counts = 0;
14599 let gram;
14600 let gram_count;
14601 for (gram in gram_counts) {
14602 gram_count = gram_counts[gram];
14603 sum_of_square_gram_counts += Math.pow(gram_count, 2);
14604 if (gram in this.match_dict) {
14605 this.match_dict[gram].push([index, gram_count]);
14606 }
14607 else {
14608 this.match_dict[gram] = [[index, gram_count]];
14609 }
14610 }
14611 const vector_normal = Math.sqrt(sum_of_square_gram_counts);
14612 items[index] = [vector_normal, normalized_value];
14613 this.items[gram_size] = items;
14614 this.exact_set[normalized_value] = value;
14615 }
14616 get(value) {
14617 const normalized_value = value.toLowerCase();
14618 const result = this.exact_set[normalized_value];
14619 if (result) {
14620 return [[1, result]];
14621 }
14622 let results = [];
14623 // start with high gram size and if there are no results, go to lower gram sizes
14624 for (let gram_size = GRAM_SIZE_UPPER; gram_size >= GRAM_SIZE_LOWER; --gram_size) {
14625 results = this.__get(value, gram_size);
14626 if (results) {
14627 return results;
14628 }
14629 }
14630 return null;
14631 }
14632 __get(value, gram_size) {
14633 const normalized_value = value.toLowerCase();
14634 const matches = {};
14635 const gram_counts = gram_counter(normalized_value, gram_size);
14636 const items = this.items[gram_size];
14637 let sum_of_square_gram_counts = 0;
14638 let gram;
14639 let gram_count;
14640 let i;
14641 let index;
14642 let other_gram_count;
14643 for (gram in gram_counts) {
14644 gram_count = gram_counts[gram];
14645 sum_of_square_gram_counts += Math.pow(gram_count, 2);
14646 if (gram in this.match_dict) {
14647 for (i = 0; i < this.match_dict[gram].length; ++i) {
14648 index = this.match_dict[gram][i][0];
14649 other_gram_count = this.match_dict[gram][i][1];
14650 if (index in matches) {
14651 matches[index] += gram_count * other_gram_count;
14652 }
14653 else {
14654 matches[index] = gram_count * other_gram_count;
14655 }
14656 }
14657 }
14658 }
14659 const vector_normal = Math.sqrt(sum_of_square_gram_counts);
14660 let results = [];
14661 let match_score;
14662 // build a results list of [score, str]
14663 for (const match_index in matches) {
14664 match_score = matches[match_index];
14665 results.push([
14666 match_score / (vector_normal * items[match_index][0]),
14667 items[match_index][1]
14668 ]);
14669 }
14670 results.sort(sort_descending);
14671 let new_results = [];
14672 const end_index = Math.min(50, results.length);
14673 // truncate somewhat arbitrarily to 50
14674 for (let i = 0; i < end_index; ++i) {
14675 new_results.push([
14676 _distance(results[i][1], normalized_value),
14677 results[i][1]
14678 ]);
14679 }
14680 results = new_results;
14681 results.sort(sort_descending);
14682 new_results = [];
14683 for (let i = 0; i < results.length; ++i) {
14684 if (results[i][0] == results[0][0]) {
14685 new_results.push([results[i][0], this.exact_set[results[i][1]]]);
14686 }
14687 }
14688 return new_results;
14689 }
14690}
14691
14692function list$1(items, conjunction = 'or') {
14693 if (items.length === 1)
14694 return items[0];
14695 return `${items.slice(0, -1).join(', ')} ${conjunction} ${items[items.length - 1]}`;
14696}
14697
14698// eslint-disable-next-line no-useless-escape
14699const valid_tag_name = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
14700const meta_tags = new Map([
14701 ['svelte:head', 'Head'],
14702 ['svelte:options', 'Options'],
14703 ['svelte:window', 'Window'],
14704 ['svelte:body', 'Body']
14705]);
14706const valid_meta_tags = Array.from(meta_tags.keys()).concat('svelte:self', 'svelte:component');
14707const specials = new Map([
14708 [
14709 'script',
14710 {
14711 read: read_script,
14712 property: 'js'
14713 }
14714 ],
14715 [
14716 'style',
14717 {
14718 read: read_style,
14719 property: 'css'
14720 }
14721 ]
14722]);
14723const SELF = /^svelte:self(?=[\s/>])/;
14724const COMPONENT = /^svelte:component(?=[\s/>])/;
14725function parent_is_head(stack) {
14726 let i = stack.length;
14727 while (i--) {
14728 const { type } = stack[i];
14729 if (type === 'Head')
14730 return true;
14731 if (type === 'Element' || type === 'InlineComponent')
14732 return false;
14733 }
14734 return false;
14735}
14736function tag(parser) {
14737 const start = parser.index++;
14738 let parent = parser.current();
14739 if (parser.eat('!--')) {
14740 const data = parser.read_until(/-->/);
14741 parser.eat('-->', true, 'comment was left open, expected -->');
14742 parser.current().children.push({
14743 start,
14744 end: parser.index,
14745 type: 'Comment',
14746 data
14747 });
14748 return;
14749 }
14750 const is_closing_tag = parser.eat('/');
14751 const name = read_tag_name(parser);
14752 if (meta_tags.has(name)) {
14753 const slug = meta_tags.get(name).toLowerCase();
14754 if (is_closing_tag) {
14755 if ((name === 'svelte:window' || name === 'svelte:body') &&
14756 parser.current().children.length) {
14757 parser.error({
14758 code: `invalid-${slug}-content`,
14759 message: `<${name}> cannot have children`
14760 }, parser.current().children[0].start);
14761 }
14762 }
14763 else {
14764 if (name in parser.meta_tags) {
14765 parser.error({
14766 code: `duplicate-${slug}`,
14767 message: `A component can only have one <${name}> tag`
14768 }, start);
14769 }
14770 if (parser.stack.length > 1) {
14771 parser.error({
14772 code: `invalid-${slug}-placement`,
14773 message: `<${name}> tags cannot be inside elements or blocks`
14774 }, start);
14775 }
14776 parser.meta_tags[name] = true;
14777 }
14778 }
14779 const type = meta_tags.has(name)
14780 ? meta_tags.get(name)
14781 : (/[A-Z]/.test(name[0]) || name === 'svelte:self' || name === 'svelte:component') ? 'InlineComponent'
14782 : name === 'title' && parent_is_head(parser.stack) ? 'Title'
14783 : name === 'slot' && !parser.customElement ? 'Slot' : 'Element';
14784 const element = {
14785 start,
14786 end: null,
14787 type,
14788 name,
14789 attributes: [],
14790 children: []
14791 };
14792 parser.allow_whitespace();
14793 if (is_closing_tag) {
14794 if (is_void(name)) {
14795 parser.error({
14796 code: 'invalid-void-content',
14797 message: `<${name}> is a void element and cannot have children, or a closing tag`
14798 }, start);
14799 }
14800 parser.eat('>', true);
14801 // close any elements that don't have their own closing tags, e.g. <div><p></div>
14802 while (parent.name !== name) {
14803 if (parent.type !== 'Element') {
14804 const message = parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name
14805 ? `</${name}> attempted to close <${name}> that was already automatically closed by <${parser.last_auto_closed_tag.reason}>`
14806 : `</${name}> attempted to close an element that was not open`;
14807 parser.error({
14808 code: 'invalid-closing-tag',
14809 message
14810 }, start);
14811 }
14812 parent.end = start;
14813 parser.stack.pop();
14814 parent = parser.current();
14815 }
14816 parent.end = parser.index;
14817 parser.stack.pop();
14818 if (parser.last_auto_closed_tag && parser.stack.length < parser.last_auto_closed_tag.depth) {
14819 parser.last_auto_closed_tag = null;
14820 }
14821 return;
14822 }
14823 else if (closing_tag_omitted(parent.name, name)) {
14824 parent.end = start;
14825 parser.stack.pop();
14826 parser.last_auto_closed_tag = {
14827 tag: parent.name,
14828 reason: name,
14829 depth: parser.stack.length
14830 };
14831 }
14832 const unique_names = new Set();
14833 let attribute;
14834 while ((attribute = read_attribute(parser, unique_names))) {
14835 element.attributes.push(attribute);
14836 parser.allow_whitespace();
14837 }
14838 if (name === 'svelte:component') {
14839 const index = element.attributes.findIndex(attr => attr.type === 'Attribute' && attr.name === 'this');
14840 if (!~index) {
14841 parser.error({
14842 code: 'missing-component-definition',
14843 message: "<svelte:component> must have a 'this' attribute"
14844 }, start);
14845 }
14846 const definition = element.attributes.splice(index, 1)[0];
14847 if (definition.value === true || definition.value.length !== 1 || definition.value[0].type === 'Text') {
14848 parser.error({
14849 code: 'invalid-component-definition',
14850 message: 'invalid component definition'
14851 }, definition.start);
14852 }
14853 element.expression = definition.value[0].expression;
14854 }
14855 // special cases – top-level <script> and <style>
14856 if (specials.has(name) && parser.stack.length === 1) {
14857 const special = specials.get(name);
14858 parser.eat('>', true);
14859 const content = special.read(parser, start, element.attributes);
14860 if (content)
14861 parser[special.property].push(content);
14862 return;
14863 }
14864 parser.current().children.push(element);
14865 const self_closing = parser.eat('/') || is_void(name);
14866 parser.eat('>', true);
14867 if (self_closing) {
14868 // don't push self-closing elements onto the stack
14869 element.end = parser.index;
14870 }
14871 else if (name === 'textarea') {
14872 // special case
14873 element.children = read_sequence(parser, () => parser.template.slice(parser.index, parser.index + 11) === '</textarea>');
14874 parser.read(/<\/textarea>/);
14875 element.end = parser.index;
14876 }
14877 else if (name === 'script' || name === 'style') {
14878 // special case
14879 const start = parser.index;
14880 const data = parser.read_until(new RegExp(`</${name}>`));
14881 const end = parser.index;
14882 element.children.push({ start, end, type: 'Text', data });
14883 parser.eat(`</${name}>`, true);
14884 element.end = parser.index;
14885 }
14886 else {
14887 parser.stack.push(element);
14888 }
14889}
14890function read_tag_name(parser) {
14891 const start = parser.index;
14892 if (parser.read(SELF)) {
14893 // check we're inside a block, otherwise this
14894 // will cause infinite recursion
14895 let i = parser.stack.length;
14896 let legal = false;
14897 while (i--) {
14898 const fragment = parser.stack[i];
14899 if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock' || fragment.type === 'InlineComponent') {
14900 legal = true;
14901 break;
14902 }
14903 }
14904 if (!legal) {
14905 parser.error({
14906 code: 'invalid-self-placement',
14907 message: '<svelte:self> components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components'
14908 }, start);
14909 }
14910 return 'svelte:self';
14911 }
14912 if (parser.read(COMPONENT))
14913 return 'svelte:component';
14914 const name = parser.read_until(/(\s|\/|>)/);
14915 if (meta_tags.has(name))
14916 return name;
14917 if (name.startsWith('svelte:')) {
14918 const match = fuzzymatch(name.slice(7), valid_meta_tags);
14919 let message = `Valid <svelte:...> tag names are ${list$1(valid_meta_tags)}`;
14920 if (match)
14921 message += ` (did you mean '${match}'?)`;
14922 parser.error({
14923 code: 'invalid-tag-name',
14924 message
14925 }, start);
14926 }
14927 if (!valid_tag_name.test(name)) {
14928 parser.error({
14929 code: 'invalid-tag-name',
14930 message: 'Expected valid tag name'
14931 }, start);
14932 }
14933 return name;
14934}
14935function read_attribute(parser, unique_names) {
14936 const start = parser.index;
14937 function check_unique(name) {
14938 if (unique_names.has(name)) {
14939 parser.error({
14940 code: 'duplicate-attribute',
14941 message: 'Attributes need to be unique'
14942 }, start);
14943 }
14944 unique_names.add(name);
14945 }
14946 if (parser.eat('{')) {
14947 parser.allow_whitespace();
14948 if (parser.eat('...')) {
14949 const expression = read_expression(parser);
14950 parser.allow_whitespace();
14951 parser.eat('}', true);
14952 return {
14953 start,
14954 end: parser.index,
14955 type: 'Spread',
14956 expression
14957 };
14958 }
14959 else {
14960 const value_start = parser.index;
14961 const name = parser.read_identifier();
14962 parser.allow_whitespace();
14963 parser.eat('}', true);
14964 check_unique(name);
14965 return {
14966 start,
14967 end: parser.index,
14968 type: 'Attribute',
14969 name,
14970 value: [{
14971 start: value_start,
14972 end: value_start + name.length,
14973 type: 'AttributeShorthand',
14974 expression: {
14975 start: value_start,
14976 end: value_start + name.length,
14977 type: 'Identifier',
14978 name
14979 }
14980 }]
14981 };
14982 }
14983 }
14984 // eslint-disable-next-line no-useless-escape
14985 const name = parser.read_until(/[\s=\/>"']/);
14986 if (!name)
14987 return null;
14988 let end = parser.index;
14989 parser.allow_whitespace();
14990 const colon_index = name.indexOf(':');
14991 const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index));
14992 let value = true;
14993 if (parser.eat('=')) {
14994 parser.allow_whitespace();
14995 value = read_attribute_value(parser);
14996 end = parser.index;
14997 }
14998 else if (parser.match_regex(/["']/)) {
14999 parser.error({
15000 code: 'unexpected-token',
15001 message: 'Expected ='
15002 }, parser.index);
15003 }
15004 if (type) {
15005 const [directive_name, ...modifiers] = name.slice(colon_index + 1).split('|');
15006 if (type === 'Binding' && directive_name !== 'this') {
15007 check_unique(directive_name);
15008 }
15009 else if (type !== 'EventHandler') {
15010 check_unique(name);
15011 }
15012 if (type === 'Ref') {
15013 parser.error({
15014 code: 'invalid-ref-directive',
15015 message: `The ref directive is no longer supported — use \`bind:this={${directive_name}}\` instead`
15016 }, start);
15017 }
15018 if (value[0]) {
15019 if (value.length > 1 || value[0].type === 'Text') {
15020 parser.error({
15021 code: 'invalid-directive-value',
15022 message: 'Directive value must be a JavaScript expression enclosed in curly braces'
15023 }, value[0].start);
15024 }
15025 }
15026 const directive = {
15027 start,
15028 end,
15029 type,
15030 name: directive_name,
15031 modifiers,
15032 expression: (value[0] && value[0].expression) || null
15033 };
15034 if (type === 'Transition') {
15035 const direction = name.slice(0, colon_index);
15036 directive.intro = direction === 'in' || direction === 'transition';
15037 directive.outro = direction === 'out' || direction === 'transition';
15038 }
15039 if (!directive.expression && (type === 'Binding' || type === 'Class')) {
15040 directive.expression = {
15041 start: directive.start + colon_index + 1,
15042 end: directive.end,
15043 type: 'Identifier',
15044 name: directive.name
15045 };
15046 }
15047 return directive;
15048 }
15049 check_unique(name);
15050 return {
15051 start,
15052 end,
15053 type: 'Attribute',
15054 name,
15055 value
15056 };
15057}
15058function get_directive_type(name) {
15059 if (name === 'use')
15060 return 'Action';
15061 if (name === 'animate')
15062 return 'Animation';
15063 if (name === 'bind')
15064 return 'Binding';
15065 if (name === 'class')
15066 return 'Class';
15067 if (name === 'on')
15068 return 'EventHandler';
15069 if (name === 'let')
15070 return 'Let';
15071 if (name === 'ref')
15072 return 'Ref';
15073 if (name === 'in' || name === 'out' || name === 'transition')
15074 return 'Transition';
15075}
15076function read_attribute_value(parser) {
15077 const quote_mark = parser.eat("'") ? "'" : parser.eat('"') ? '"' : null;
15078 const regex = (quote_mark === "'" ? /'/ :
15079 quote_mark === '"' ? /"/ :
15080 /(\/>|[\s"'=<>`])/);
15081 const value = read_sequence(parser, () => !!parser.match_regex(regex));
15082 if (quote_mark)
15083 parser.index += 1;
15084 return value;
15085}
15086function read_sequence(parser, done) {
15087 let current_chunk = {
15088 start: parser.index,
15089 end: null,
15090 type: 'Text',
15091 raw: '',
15092 data: null
15093 };
15094 function flush() {
15095 if (current_chunk.raw) {
15096 current_chunk.data = decode_character_references(current_chunk.raw);
15097 current_chunk.end = parser.index;
15098 chunks.push(current_chunk);
15099 }
15100 }
15101 const chunks = [];
15102 while (parser.index < parser.template.length) {
15103 const index = parser.index;
15104 if (done()) {
15105 flush();
15106 return chunks;
15107 }
15108 else if (parser.eat('{')) {
15109 flush();
15110 parser.allow_whitespace();
15111 const expression = read_expression(parser);
15112 parser.allow_whitespace();
15113 parser.eat('}', true);
15114 chunks.push({
15115 start: index,
15116 end: parser.index,
15117 type: 'MustacheTag',
15118 expression
15119 });
15120 current_chunk = {
15121 start: parser.index,
15122 end: null,
15123 type: 'Text',
15124 raw: '',
15125 data: null
15126 };
15127 }
15128 else {
15129 current_chunk.raw += parser.template[parser.index++];
15130 }
15131 }
15132 parser.error({
15133 code: 'unexpected-eof',
15134 message: 'Unexpected end of input'
15135 });
15136}
15137
15138const SQUARE_BRACKET_OPEN = '['.charCodeAt(0);
15139const SQUARE_BRACKET_CLOSE = ']'.charCodeAt(0);
15140const CURLY_BRACKET_OPEN = '{'.charCodeAt(0);
15141const CURLY_BRACKET_CLOSE = '}'.charCodeAt(0);
15142function is_bracket_open(code) {
15143 return code === SQUARE_BRACKET_OPEN || code === CURLY_BRACKET_OPEN;
15144}
15145function is_bracket_close(code) {
15146 return code === SQUARE_BRACKET_CLOSE || code === CURLY_BRACKET_CLOSE;
15147}
15148function is_bracket_pair(open, close) {
15149 return ((open === SQUARE_BRACKET_OPEN && close === SQUARE_BRACKET_CLOSE) ||
15150 (open === CURLY_BRACKET_OPEN && close === CURLY_BRACKET_CLOSE));
15151}
15152function get_bracket_close(open) {
15153 if (open === SQUARE_BRACKET_OPEN) {
15154 return SQUARE_BRACKET_CLOSE;
15155 }
15156 if (open === CURLY_BRACKET_OPEN) {
15157 return CURLY_BRACKET_CLOSE;
15158 }
15159}
15160
15161function read_context(parser) {
15162 const start = parser.index;
15163 let i = parser.index;
15164 const code = full_char_code_at(parser.template, i);
15165 if (isIdentifierStart(code, true)) {
15166 return {
15167 type: 'Identifier',
15168 name: parser.read_identifier(),
15169 start,
15170 end: parser.index
15171 };
15172 }
15173 if (!is_bracket_open(code)) {
15174 parser.error({
15175 code: 'unexpected-token',
15176 message: 'Expected identifier or destructure pattern'
15177 });
15178 }
15179 const bracket_stack = [code];
15180 i += code <= 0xffff ? 1 : 2;
15181 while (i < parser.template.length) {
15182 const code = full_char_code_at(parser.template, i);
15183 if (is_bracket_open(code)) {
15184 bracket_stack.push(code);
15185 }
15186 else if (is_bracket_close(code)) {
15187 if (!is_bracket_pair(bracket_stack[bracket_stack.length - 1], code)) {
15188 parser.error({
15189 code: 'unexpected-token',
15190 message: `Expected ${String.fromCharCode(get_bracket_close(bracket_stack[bracket_stack.length - 1]))}`
15191 });
15192 }
15193 bracket_stack.pop();
15194 if (bracket_stack.length === 0) {
15195 i += code <= 0xffff ? 1 : 2;
15196 break;
15197 }
15198 }
15199 i += code <= 0xffff ? 1 : 2;
15200 }
15201 parser.index = i;
15202 const pattern_string = parser.template.slice(start, i);
15203 try {
15204 // the length of the `space_with_newline` has to be start - 1
15205 // because we added a `(` in front of the pattern_string,
15206 // which shifted the entire string to right by 1
15207 // so we offset it by removing 1 character in the `space_with_newline`
15208 // to achieve that, we remove the 1st space encountered,
15209 // so it will not affect the `column` of the node
15210 let space_with_newline = parser.template.slice(0, start).replace(/[^\n]/g, ' ');
15211 const first_space = space_with_newline.indexOf(' ');
15212 space_with_newline = space_with_newline.slice(0, first_space) + space_with_newline.slice(first_space + 1);
15213 return parse_expression_at(`${space_with_newline}(${pattern_string} = 1)`, start - 1).left;
15214 }
15215 catch (error) {
15216 parser.acorn_error(error);
15217 }
15218}
15219
15220function trim_start(str) {
15221 let i = 0;
15222 while (whitespace.test(str[i]))
15223 i += 1;
15224 return str.slice(i);
15225}
15226function trim_end(str) {
15227 let i = str.length;
15228 while (whitespace.test(str[i - 1]))
15229 i -= 1;
15230 return str.slice(0, i);
15231}
15232
15233function to_string(node) {
15234 switch (node.type) {
15235 case 'IfBlock':
15236 return '{#if} block';
15237 case 'ThenBlock':
15238 return '{:then} block';
15239 case 'ElseBlock':
15240 return '{:else} block';
15241 case 'PendingBlock':
15242 case 'AwaitBlock':
15243 return '{#await} block';
15244 case 'CatchBlock':
15245 return '{:catch} block';
15246 case 'EachBlock':
15247 return '{#each} block';
15248 case 'RawMustacheTag':
15249 return '{@html} block';
15250 case 'DebugTag':
15251 return '{@debug} block';
15252 case 'Element':
15253 case 'InlineComponent':
15254 case 'Slot':
15255 case 'Title':
15256 return `<${node.name}> tag`;
15257 default:
15258 return node.type;
15259 }
15260}
15261
15262function trim_whitespace(block, trim_before, trim_after) {
15263 if (!block.children || block.children.length === 0)
15264 return; // AwaitBlock
15265 const first_child = block.children[0];
15266 const last_child = block.children[block.children.length - 1];
15267 if (first_child.type === 'Text' && trim_before) {
15268 first_child.data = trim_start(first_child.data);
15269 if (!first_child.data)
15270 block.children.shift();
15271 }
15272 if (last_child.type === 'Text' && trim_after) {
15273 last_child.data = trim_end(last_child.data);
15274 if (!last_child.data)
15275 block.children.pop();
15276 }
15277 if (block.else) {
15278 trim_whitespace(block.else, trim_before, trim_after);
15279 }
15280 if (first_child.elseif) {
15281 trim_whitespace(first_child, trim_before, trim_after);
15282 }
15283}
15284function mustache(parser) {
15285 const start = parser.index;
15286 parser.index += 1;
15287 parser.allow_whitespace();
15288 // {/if}, {/each}, {/await} or {/key}
15289 if (parser.eat('/')) {
15290 let block = parser.current();
15291 let expected;
15292 if (closing_tag_omitted(block.name)) {
15293 block.end = start;
15294 parser.stack.pop();
15295 block = parser.current();
15296 }
15297 if (block.type === 'ElseBlock' || block.type === 'PendingBlock' || block.type === 'ThenBlock' || block.type === 'CatchBlock') {
15298 block.end = start;
15299 parser.stack.pop();
15300 block = parser.current();
15301 expected = 'await';
15302 }
15303 if (block.type === 'IfBlock') {
15304 expected = 'if';
15305 }
15306 else if (block.type === 'EachBlock') {
15307 expected = 'each';
15308 }
15309 else if (block.type === 'AwaitBlock') {
15310 expected = 'await';
15311 }
15312 else if (block.type === 'KeyBlock') {
15313 expected = 'key';
15314 }
15315 else {
15316 parser.error({
15317 code: 'unexpected-block-close',
15318 message: 'Unexpected block closing tag'
15319 });
15320 }
15321 parser.eat(expected, true);
15322 parser.allow_whitespace();
15323 parser.eat('}', true);
15324 while (block.elseif) {
15325 block.end = parser.index;
15326 parser.stack.pop();
15327 block = parser.current();
15328 if (block.else) {
15329 block.else.end = start;
15330 }
15331 }
15332 // strip leading/trailing whitespace as necessary
15333 const char_before = parser.template[block.start - 1];
15334 const char_after = parser.template[parser.index];
15335 const trim_before = !char_before || whitespace.test(char_before);
15336 const trim_after = !char_after || whitespace.test(char_after);
15337 trim_whitespace(block, trim_before, trim_after);
15338 block.end = parser.index;
15339 parser.stack.pop();
15340 }
15341 else if (parser.eat(':else')) {
15342 if (parser.eat('if')) {
15343 parser.error({
15344 code: 'invalid-elseif',
15345 message: "'elseif' should be 'else if'"
15346 });
15347 }
15348 parser.allow_whitespace();
15349 // :else if
15350 if (parser.eat('if')) {
15351 const block = parser.current();
15352 if (block.type !== 'IfBlock') {
15353 parser.error({
15354 code: 'invalid-elseif-placement',
15355 message: parser.stack.some(block => block.type === 'IfBlock')
15356 ? `Expected to close ${to_string(block)} before seeing {:else if ...} block`
15357 : 'Cannot have an {:else if ...} block outside an {#if ...} block'
15358 });
15359 }
15360 parser.require_whitespace();
15361 const expression = read_expression(parser);
15362 parser.allow_whitespace();
15363 parser.eat('}', true);
15364 block.else = {
15365 start: parser.index,
15366 end: null,
15367 type: 'ElseBlock',
15368 children: [
15369 {
15370 start: parser.index,
15371 end: null,
15372 type: 'IfBlock',
15373 elseif: true,
15374 expression,
15375 children: []
15376 }
15377 ]
15378 };
15379 parser.stack.push(block.else.children[0]);
15380 }
15381 else {
15382 // :else
15383 const block = parser.current();
15384 if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
15385 parser.error({
15386 code: 'invalid-else-placement',
15387 message: parser.stack.some(block => block.type === 'IfBlock' || block.type === 'EachBlock')
15388 ? `Expected to close ${to_string(block)} before seeing {:else} block`
15389 : 'Cannot have an {:else} block outside an {#if ...} or {#each ...} block'
15390 });
15391 }
15392 parser.allow_whitespace();
15393 parser.eat('}', true);
15394 block.else = {
15395 start: parser.index,
15396 end: null,
15397 type: 'ElseBlock',
15398 children: []
15399 };
15400 parser.stack.push(block.else);
15401 }
15402 }
15403 else if (parser.match(':then') || parser.match(':catch')) {
15404 const block = parser.current();
15405 const is_then = parser.eat(':then') || !parser.eat(':catch');
15406 if (is_then) {
15407 if (block.type !== 'PendingBlock') {
15408 parser.error({
15409 code: 'invalid-then-placement',
15410 message: parser.stack.some(block => block.type === 'PendingBlock')
15411 ? `Expected to close ${to_string(block)} before seeing {:then} block`
15412 : 'Cannot have an {:then} block outside an {#await ...} block'
15413 });
15414 }
15415 }
15416 else {
15417 if (block.type !== 'ThenBlock' && block.type !== 'PendingBlock') {
15418 parser.error({
15419 code: 'invalid-catch-placement',
15420 message: parser.stack.some(block => block.type === 'ThenBlock' || block.type === 'PendingBlock')
15421 ? `Expected to close ${to_string(block)} before seeing {:catch} block`
15422 : 'Cannot have an {:catch} block outside an {#await ...} block'
15423 });
15424 }
15425 }
15426 block.end = start;
15427 parser.stack.pop();
15428 const await_block = parser.current();
15429 if (!parser.eat('}')) {
15430 parser.require_whitespace();
15431 await_block[is_then ? 'value' : 'error'] = read_context(parser);
15432 parser.allow_whitespace();
15433 parser.eat('}', true);
15434 }
15435 const new_block = {
15436 start,
15437 end: null,
15438 type: is_then ? 'ThenBlock' : 'CatchBlock',
15439 children: [],
15440 skip: false
15441 };
15442 await_block[is_then ? 'then' : 'catch'] = new_block;
15443 parser.stack.push(new_block);
15444 }
15445 else if (parser.eat('#')) {
15446 // {#if foo}, {#each foo} or {#await foo}
15447 let type;
15448 if (parser.eat('if')) {
15449 type = 'IfBlock';
15450 }
15451 else if (parser.eat('each')) {
15452 type = 'EachBlock';
15453 }
15454 else if (parser.eat('await')) {
15455 type = 'AwaitBlock';
15456 }
15457 else if (parser.eat('key')) {
15458 type = 'KeyBlock';
15459 }
15460 else {
15461 parser.error({
15462 code: 'expected-block-type',
15463 message: 'Expected if, each, await or key'
15464 });
15465 }
15466 parser.require_whitespace();
15467 const expression = read_expression(parser);
15468 const block = type === 'AwaitBlock' ?
15469 {
15470 start,
15471 end: null,
15472 type,
15473 expression,
15474 value: null,
15475 error: null,
15476 pending: {
15477 start: null,
15478 end: null,
15479 type: 'PendingBlock',
15480 children: [],
15481 skip: true
15482 },
15483 then: {
15484 start: null,
15485 end: null,
15486 type: 'ThenBlock',
15487 children: [],
15488 skip: true
15489 },
15490 catch: {
15491 start: null,
15492 end: null,
15493 type: 'CatchBlock',
15494 children: [],
15495 skip: true
15496 }
15497 } :
15498 {
15499 start,
15500 end: null,
15501 type,
15502 expression,
15503 children: []
15504 };
15505 parser.allow_whitespace();
15506 // {#each} blocks must declare a context – {#each list as item}
15507 if (type === 'EachBlock') {
15508 parser.eat('as', true);
15509 parser.require_whitespace();
15510 block.context = read_context(parser);
15511 parser.allow_whitespace();
15512 if (parser.eat(',')) {
15513 parser.allow_whitespace();
15514 block.index = parser.read_identifier();
15515 if (!block.index) {
15516 parser.error({
15517 code: 'expected-name',
15518 message: 'Expected name'
15519 });
15520 }
15521 parser.allow_whitespace();
15522 }
15523 if (parser.eat('(')) {
15524 parser.allow_whitespace();
15525 block.key = read_expression(parser);
15526 parser.allow_whitespace();
15527 parser.eat(')', true);
15528 parser.allow_whitespace();
15529 }
15530 }
15531 const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then');
15532 if (await_block_shorthand) {
15533 parser.require_whitespace();
15534 block.value = read_context(parser);
15535 parser.allow_whitespace();
15536 }
15537 const await_block_catch_shorthand = !await_block_shorthand && type === 'AwaitBlock' && parser.eat('catch');
15538 if (await_block_catch_shorthand) {
15539 parser.require_whitespace();
15540 block.error = read_context(parser);
15541 parser.allow_whitespace();
15542 }
15543 parser.eat('}', true);
15544 parser.current().children.push(block);
15545 parser.stack.push(block);
15546 if (type === 'AwaitBlock') {
15547 let child_block;
15548 if (await_block_shorthand) {
15549 block.then.skip = false;
15550 child_block = block.then;
15551 }
15552 else if (await_block_catch_shorthand) {
15553 block.catch.skip = false;
15554 child_block = block.catch;
15555 }
15556 else {
15557 block.pending.skip = false;
15558 child_block = block.pending;
15559 }
15560 child_block.start = parser.index;
15561 parser.stack.push(child_block);
15562 }
15563 }
15564 else if (parser.eat('@html')) {
15565 // {@html content} tag
15566 parser.require_whitespace();
15567 const expression = read_expression(parser);
15568 parser.allow_whitespace();
15569 parser.eat('}', true);
15570 parser.current().children.push({
15571 start,
15572 end: parser.index,
15573 type: 'RawMustacheTag',
15574 expression
15575 });
15576 }
15577 else if (parser.eat('@debug')) {
15578 let identifiers;
15579 // Implies {@debug} which indicates "debug all"
15580 if (parser.read(/\s*}/)) {
15581 identifiers = [];
15582 }
15583 else {
15584 const expression = read_expression(parser);
15585 identifiers = expression.type === 'SequenceExpression'
15586 ? expression.expressions
15587 : [expression];
15588 identifiers.forEach(node => {
15589 if (node.type !== 'Identifier') {
15590 parser.error({
15591 code: 'invalid-debug-args',
15592 message: '{@debug ...} arguments must be identifiers, not arbitrary expressions'
15593 }, node.start);
15594 }
15595 });
15596 parser.allow_whitespace();
15597 parser.eat('}', true);
15598 }
15599 parser.current().children.push({
15600 start,
15601 end: parser.index,
15602 type: 'DebugTag',
15603 identifiers
15604 });
15605 }
15606 else {
15607 const expression = read_expression(parser);
15608 parser.allow_whitespace();
15609 parser.eat('}', true);
15610 parser.current().children.push({
15611 start,
15612 end: parser.index,
15613 type: 'MustacheTag',
15614 expression
15615 });
15616 }
15617}
15618
15619function text(parser) {
15620 const start = parser.index;
15621 let data = '';
15622 while (parser.index < parser.template.length &&
15623 !parser.match('<') &&
15624 !parser.match('{')) {
15625 data += parser.template[parser.index++];
15626 }
15627 const node = {
15628 start,
15629 end: parser.index,
15630 type: 'Text',
15631 raw: data,
15632 data: decode_character_references(data)
15633 };
15634 parser.current().children.push(node);
15635}
15636
15637function fragment(parser) {
15638 if (parser.match('<')) {
15639 return tag;
15640 }
15641 if (parser.match('{')) {
15642 return mustache;
15643 }
15644 return text;
15645}
15646
15647function getLocator(source, options) {
15648 if (options === void 0) { options = {}; }
15649 var offsetLine = options.offsetLine || 0;
15650 var offsetColumn = options.offsetColumn || 0;
15651 var originalLines = source.split('\n');
15652 var start = 0;
15653 var lineRanges = originalLines.map(function (line, i) {
15654 var end = start + line.length + 1;
15655 var range = { start: start, end: end, line: i };
15656 start = end;
15657 return range;
15658 });
15659 var i = 0;
15660 function rangeContains(range, index) {
15661 return range.start <= index && index < range.end;
15662 }
15663 function getLocation(range, index) {
15664 return { line: offsetLine + range.line, column: offsetColumn + index - range.start, character: index };
15665 }
15666 function locate(search, startIndex) {
15667 if (typeof search === 'string') {
15668 search = source.indexOf(search, startIndex || 0);
15669 }
15670 var range = lineRanges[i];
15671 var d = search >= range.end ? 1 : -1;
15672 while (range) {
15673 if (rangeContains(range, search))
15674 return getLocation(range, search);
15675 i += d;
15676 range = lineRanges[i];
15677 }
15678 }
15679 return locate;
15680}
15681function locate(source, search, options) {
15682 if (typeof options === 'number') {
15683 throw new Error('locate takes a { startIndex, offsetLine, offsetColumn } object as the third argument');
15684 }
15685 return getLocator(source, options)(search, options && options.startIndex);
15686}
15687
15688function tabs_to_spaces(str) {
15689 return str.replace(/^\t+/, match => match.split('\t').join(' '));
15690}
15691function get_code_frame(source, line, column) {
15692 const lines = source.split('\n');
15693 const frame_start = Math.max(0, line - 2);
15694 const frame_end = Math.min(line + 3, lines.length);
15695 const digits = String(frame_end + 1).length;
15696 return lines
15697 .slice(frame_start, frame_end)
15698 .map((str, i) => {
15699 const isErrorLine = frame_start + i === line;
15700 const line_num = String(i + frame_start + 1).padStart(digits, ' ');
15701 if (isErrorLine) {
15702 const indicator = ' '.repeat(digits + 2 + tabs_to_spaces(str.slice(0, column)).length) + '^';
15703 return `${line_num}: ${tabs_to_spaces(str)}\n${indicator}`;
15704 }
15705 return `${line_num}: ${tabs_to_spaces(str)}`;
15706 })
15707 .join('\n');
15708}
15709
15710class CompileError extends Error {
15711 toString() {
15712 return `${this.message} (${this.start.line}:${this.start.column})\n${this.frame}`;
15713 }
15714}
15715function error$1(message, props) {
15716 const error = new CompileError(message);
15717 error.name = props.name;
15718 const start = locate(props.source, props.start, { offsetLine: 1 });
15719 const end = locate(props.source, props.end || props.start, { offsetLine: 1 });
15720 error.code = props.code;
15721 error.start = start;
15722 error.end = end;
15723 error.pos = props.start;
15724 error.filename = props.filename;
15725 error.frame = get_code_frame(props.source, start.line - 1, start.column);
15726 throw error;
15727}
15728
15729class Parser$1 {
15730 constructor(template, options) {
15731 this.index = 0;
15732 this.stack = [];
15733 this.css = [];
15734 this.js = [];
15735 this.meta_tags = {};
15736 if (typeof template !== 'string') {
15737 throw new TypeError('Template must be a string');
15738 }
15739 this.template = template.replace(/\s+$/, '');
15740 this.filename = options.filename;
15741 this.customElement = options.customElement;
15742 this.html = {
15743 start: null,
15744 end: null,
15745 type: 'Fragment',
15746 children: []
15747 };
15748 this.stack.push(this.html);
15749 let state = fragment;
15750 while (this.index < this.template.length) {
15751 state = state(this) || fragment;
15752 }
15753 if (this.stack.length > 1) {
15754 const current = this.current();
15755 const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
15756 const slug = current.type === 'Element' ? 'element' : 'block';
15757 this.error({
15758 code: `unclosed-${slug}`,
15759 message: `${type} was left open`
15760 }, current.start);
15761 }
15762 if (state !== fragment) {
15763 this.error({
15764 code: 'unexpected-eof',
15765 message: 'Unexpected end of input'
15766 });
15767 }
15768 if (this.html.children.length) {
15769 let start = this.html.children[0].start;
15770 while (whitespace.test(template[start]))
15771 start += 1;
15772 let end = this.html.children[this.html.children.length - 1].end;
15773 while (whitespace.test(template[end - 1]))
15774 end -= 1;
15775 this.html.start = start;
15776 this.html.end = end;
15777 }
15778 else {
15779 this.html.start = this.html.end = null;
15780 }
15781 }
15782 current() {
15783 return this.stack[this.stack.length - 1];
15784 }
15785 acorn_error(err) {
15786 this.error({
15787 code: 'parse-error',
15788 message: err.message.replace(/ \(\d+:\d+\)$/, '')
15789 }, err.pos);
15790 }
15791 error({ code, message }, index = this.index) {
15792 error$1(message, {
15793 name: 'ParseError',
15794 code,
15795 source: this.template,
15796 start: index,
15797 filename: this.filename
15798 });
15799 }
15800 eat(str, required, message) {
15801 if (this.match(str)) {
15802 this.index += str.length;
15803 return true;
15804 }
15805 if (required) {
15806 this.error({
15807 code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`,
15808 message: message || `Expected ${str}`
15809 });
15810 }
15811 return false;
15812 }
15813 match(str) {
15814 return this.template.slice(this.index, this.index + str.length) === str;
15815 }
15816 match_regex(pattern) {
15817 const match = pattern.exec(this.template.slice(this.index));
15818 if (!match || match.index !== 0)
15819 return null;
15820 return match[0];
15821 }
15822 allow_whitespace() {
15823 while (this.index < this.template.length &&
15824 whitespace.test(this.template[this.index])) {
15825 this.index++;
15826 }
15827 }
15828 read(pattern) {
15829 const result = this.match_regex(pattern);
15830 if (result)
15831 this.index += result.length;
15832 return result;
15833 }
15834 read_identifier(allow_reserved = false) {
15835 const start = this.index;
15836 let i = this.index;
15837 const code = full_char_code_at(this.template, i);
15838 if (!isIdentifierStart(code, true))
15839 return null;
15840 i += code <= 0xffff ? 1 : 2;
15841 while (i < this.template.length) {
15842 const code = full_char_code_at(this.template, i);
15843 if (!isIdentifierChar(code, true))
15844 break;
15845 i += code <= 0xffff ? 1 : 2;
15846 }
15847 const identifier = this.template.slice(this.index, this.index = i);
15848 if (!allow_reserved && reserved.has(identifier)) {
15849 this.error({
15850 code: 'unexpected-reserved-word',
15851 message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`
15852 }, start);
15853 }
15854 return identifier;
15855 }
15856 read_until(pattern) {
15857 if (this.index >= this.template.length) {
15858 this.error({
15859 code: 'unexpected-eof',
15860 message: 'Unexpected end of input'
15861 });
15862 }
15863 const start = this.index;
15864 const match = pattern.exec(this.template.slice(start));
15865 if (match) {
15866 this.index = start + match.index;
15867 return this.template.slice(start, this.index);
15868 }
15869 this.index = this.template.length;
15870 return this.template.slice(start);
15871 }
15872 require_whitespace() {
15873 if (!whitespace.test(this.template[this.index])) {
15874 this.error({
15875 code: 'missing-whitespace',
15876 message: 'Expected whitespace'
15877 });
15878 }
15879 this.allow_whitespace();
15880 }
15881}
15882function parse$3(template, options = {}) {
15883 const parser = new Parser$1(template, options);
15884 // TODO we may want to allow multiple <style> tags —
15885 // one scoped, one global. for now, only allow one
15886 if (parser.css.length > 1) {
15887 parser.error({
15888 code: 'duplicate-style',
15889 message: 'You can only have one top-level <style> tag per component'
15890 }, parser.css[1].start);
15891 }
15892 const instance_scripts = parser.js.filter(script => script.context === 'default');
15893 const module_scripts = parser.js.filter(script => script.context === 'module');
15894 if (instance_scripts.length > 1) {
15895 parser.error({
15896 code: 'invalid-script',
15897 message: 'A component can only have one instance-level <script> element'
15898 }, instance_scripts[1].start);
15899 }
15900 if (module_scripts.length > 1) {
15901 parser.error({
15902 code: 'invalid-script',
15903 message: 'A component can only have one <script context="module"> element'
15904 }, module_scripts[1].start);
15905 }
15906 return {
15907 html: parser.html,
15908 css: parser.css[0],
15909 instance: instance_scripts[0],
15910 module: module_scripts[0]
15911 };
15912}
15913
15914function is_head(node) {
15915 return node && node.type === 'MemberExpression' && node.object.name === '@_document' && node.property.name === 'head';
15916}
15917
15918class Block$1 {
15919 constructor(options) {
15920 this.dependencies = new Set();
15921 this.binding_group_initialised = new Set();
15922 this.event_listeners = [];
15923 this.variables = new Map();
15924 this.has_update_method = false;
15925 this.parent = options.parent;
15926 this.renderer = options.renderer;
15927 this.name = options.name;
15928 this.type = options.type;
15929 this.comment = options.comment;
15930 this.wrappers = [];
15931 // for keyed each blocks
15932 this.key = options.key;
15933 this.first = null;
15934 this.bindings = options.bindings;
15935 this.chunks = {
15936 declarations: [],
15937 init: [],
15938 create: [],
15939 claim: [],
15940 hydrate: [],
15941 mount: [],
15942 measure: [],
15943 fix: [],
15944 animate: [],
15945 intro: [],
15946 update: [],
15947 outro: [],
15948 destroy: []
15949 };
15950 this.has_animation = false;
15951 this.has_intro_method = false; // a block could have an intro method but not intro transitions, e.g. if a sibling block has intros
15952 this.has_outro_method = false;
15953 this.outros = 0;
15954 this.get_unique_name = this.renderer.component.get_unique_name_maker();
15955 this.aliases = new Map();
15956 if (this.key)
15957 this.aliases.set('key', this.get_unique_name('key'));
15958 }
15959 assign_variable_names() {
15960 const seen = new Set();
15961 const dupes = new Set();
15962 let i = this.wrappers.length;
15963 while (i--) {
15964 const wrapper = this.wrappers[i];
15965 if (!wrapper.var)
15966 continue;
15967 if (seen.has(wrapper.var.name)) {
15968 dupes.add(wrapper.var.name);
15969 }
15970 seen.add(wrapper.var.name);
15971 }
15972 const counts = new Map();
15973 i = this.wrappers.length;
15974 while (i--) {
15975 const wrapper = this.wrappers[i];
15976 if (!wrapper.var)
15977 continue;
15978 let suffix = '';
15979 if (dupes.has(wrapper.var.name)) {
15980 const i = counts.get(wrapper.var.name) || 0;
15981 counts.set(wrapper.var.name, i + 1);
15982 suffix = i;
15983 }
15984 wrapper.var.name = this.get_unique_name(wrapper.var.name + suffix).name;
15985 }
15986 }
15987 add_dependencies(dependencies) {
15988 dependencies.forEach(dependency => {
15989 this.dependencies.add(dependency);
15990 });
15991 this.has_update_method = true;
15992 if (this.parent) {
15993 this.parent.add_dependencies(dependencies);
15994 }
15995 }
15996 add_element(id, render_statement, claim_statement, parent_node, no_detach) {
15997 this.add_variable(id);
15998 this.chunks.create.push(b `${id} = ${render_statement};`);
15999 if (this.renderer.options.hydratable) {
16000 this.chunks.claim.push(b `${id} = ${claim_statement || render_statement};`);
16001 }
16002 if (parent_node) {
16003 this.chunks.mount.push(b `@append(${parent_node}, ${id});`);
16004 if (is_head(parent_node) && !no_detach)
16005 this.chunks.destroy.push(b `@detach(${id});`);
16006 }
16007 else {
16008 this.chunks.mount.push(b `@insert(#target, ${id}, #anchor);`);
16009 if (!no_detach)
16010 this.chunks.destroy.push(b `if (detaching) @detach(${id});`);
16011 }
16012 }
16013 add_intro(local) {
16014 this.has_intros = this.has_intro_method = true;
16015 if (!local && this.parent)
16016 this.parent.add_intro();
16017 }
16018 add_outro(local) {
16019 this.has_outros = this.has_outro_method = true;
16020 this.outros += 1;
16021 if (!local && this.parent)
16022 this.parent.add_outro();
16023 }
16024 add_animation() {
16025 this.has_animation = true;
16026 }
16027 add_variable(id, init) {
16028 if (this.variables.has(id.name)) {
16029 throw new Error(`Variable '${id.name}' already initialised with a different value`);
16030 }
16031 this.variables.set(id.name, { id, init });
16032 }
16033 alias(name) {
16034 if (!this.aliases.has(name)) {
16035 this.aliases.set(name, this.get_unique_name(name));
16036 }
16037 return this.aliases.get(name);
16038 }
16039 child(options) {
16040 return new Block$1(Object.assign({}, this, { key: null }, options, { parent: this }));
16041 }
16042 get_contents(key) {
16043 const { dev } = this.renderer.options;
16044 if (this.has_outros) {
16045 this.add_variable({ type: 'Identifier', name: '#current' });
16046 if (this.chunks.intro.length > 0) {
16047 this.chunks.intro.push(b `#current = true;`);
16048 this.chunks.mount.push(b `#current = true;`);
16049 }
16050 if (this.chunks.outro.length > 0) {
16051 this.chunks.outro.push(b `#current = false;`);
16052 }
16053 }
16054 if (this.autofocus) {
16055 this.chunks.mount.push(b `${this.autofocus}.focus();`);
16056 }
16057 this.render_listeners();
16058 const properties = {};
16059 const noop = x `@noop`;
16060 properties.key = key;
16061 if (this.first) {
16062 properties.first = x `null`;
16063 this.chunks.hydrate.push(b `this.first = ${this.first};`);
16064 }
16065 if (this.chunks.create.length === 0 && this.chunks.hydrate.length === 0) {
16066 properties.create = noop;
16067 }
16068 else {
16069 const hydrate = this.chunks.hydrate.length > 0 && (this.renderer.options.hydratable
16070 ? b `this.h();`
16071 : this.chunks.hydrate);
16072 properties.create = x `function #create() {
16073 ${this.chunks.create}
16074 ${hydrate}
16075 }`;
16076 }
16077 if (this.renderer.options.hydratable || this.chunks.claim.length > 0) {
16078 if (this.chunks.claim.length === 0 && this.chunks.hydrate.length === 0) {
16079 properties.claim = noop;
16080 }
16081 else {
16082 properties.claim = x `function #claim(#nodes) {
16083 ${this.chunks.claim}
16084 ${this.renderer.options.hydratable && this.chunks.hydrate.length > 0 && b `this.h();`}
16085 }`;
16086 }
16087 }
16088 if (this.renderer.options.hydratable && this.chunks.hydrate.length > 0) {
16089 properties.hydrate = x `function #hydrate() {
16090 ${this.chunks.hydrate}
16091 }`;
16092 }
16093 if (this.chunks.mount.length === 0) {
16094 properties.mount = noop;
16095 }
16096 else if (this.event_listeners.length === 0) {
16097 properties.mount = x `function #mount(#target, #anchor) {
16098 ${this.chunks.mount}
16099 }`;
16100 }
16101 else {
16102 properties.mount = x `function #mount(#target, #anchor) {
16103 ${this.chunks.mount}
16104 }`;
16105 }
16106 if (this.has_update_method || this.maintain_context) {
16107 if (this.chunks.update.length === 0 && !this.maintain_context) {
16108 properties.update = noop;
16109 }
16110 else {
16111 const ctx = this.maintain_context ? x `#new_ctx` : x `#ctx`;
16112 let dirty = { type: 'Identifier', name: '#dirty' };
16113 if (!this.renderer.context_overflow && !this.parent) {
16114 dirty = { type: 'ArrayPattern', elements: [dirty] };
16115 }
16116 properties.update = x `function #update(${ctx}, ${dirty}) {
16117 ${this.maintain_context && b `#ctx = ${ctx};`}
16118 ${this.chunks.update}
16119 }`;
16120 }
16121 }
16122 if (this.has_animation) {
16123 properties.measure = x `function #measure() {
16124 ${this.chunks.measure}
16125 }`;
16126 properties.fix = x `function #fix() {
16127 ${this.chunks.fix}
16128 }`;
16129 properties.animate = x `function #animate() {
16130 ${this.chunks.animate}
16131 }`;
16132 }
16133 if (this.has_intro_method || this.has_outro_method) {
16134 if (this.chunks.intro.length === 0) {
16135 properties.intro = noop;
16136 }
16137 else {
16138 properties.intro = x `function #intro(#local) {
16139 ${this.has_outros && b `if (#current) return;`}
16140 ${this.chunks.intro}
16141 }`;
16142 }
16143 if (this.chunks.outro.length === 0) {
16144 properties.outro = noop;
16145 }
16146 else {
16147 properties.outro = x `function #outro(#local) {
16148 ${this.chunks.outro}
16149 }`;
16150 }
16151 }
16152 if (this.chunks.destroy.length === 0) {
16153 properties.destroy = noop;
16154 }
16155 else {
16156 properties.destroy = x `function #destroy(detaching) {
16157 ${this.chunks.destroy}
16158 }`;
16159 }
16160 if (!this.renderer.component.compile_options.dev) {
16161 // allow shorthand names
16162 for (const name in properties) {
16163 const property = properties[name];
16164 if (property)
16165 property.id = null;
16166 }
16167 }
16168 const return_value = x `{
16169 key: ${properties.key},
16170 first: ${properties.first},
16171 c: ${properties.create},
16172 l: ${properties.claim},
16173 h: ${properties.hydrate},
16174 m: ${properties.mount},
16175 p: ${properties.update},
16176 r: ${properties.measure},
16177 f: ${properties.fix},
16178 a: ${properties.animate},
16179 i: ${properties.intro},
16180 o: ${properties.outro},
16181 d: ${properties.destroy}
16182 }`;
16183 const block = dev && this.get_unique_name('block');
16184 const body = b `
16185 ${this.chunks.declarations}
16186
16187 ${Array.from(this.variables.values()).map(({ id, init }) => {
16188 return init
16189 ? b `let ${id} = ${init}`
16190 : b `let ${id}`;
16191 })}
16192
16193 ${this.chunks.init}
16194
16195 ${dev
16196 ? b `
16197 const ${block} = ${return_value};
16198 @dispatch_dev("SvelteRegisterBlock", {
16199 block: ${block},
16200 id: ${this.name || 'create_fragment'}.name,
16201 type: "${this.type}",
16202 source: "${this.comment ? this.comment.replace(/"/g, '\\"') : ''}",
16203 ctx: #ctx
16204 });
16205 return ${block};`
16206 : b `
16207 return ${return_value};`}
16208 `;
16209 return body;
16210 }
16211 has_content() {
16212 return !!this.first ||
16213 this.event_listeners.length > 0 ||
16214 this.chunks.intro.length > 0 ||
16215 this.chunks.outro.length > 0 ||
16216 this.chunks.create.length > 0 ||
16217 this.chunks.hydrate.length > 0 ||
16218 this.chunks.claim.length > 0 ||
16219 this.chunks.mount.length > 0 ||
16220 this.chunks.update.length > 0 ||
16221 this.chunks.destroy.length > 0 ||
16222 this.has_animation;
16223 }
16224 render() {
16225 const key = this.key && this.get_unique_name('key');
16226 const args = [x `#ctx`];
16227 if (key)
16228 args.unshift(key);
16229 const fn = b `function ${this.name}(${args}) {
16230 ${this.get_contents(key)}
16231 }`;
16232 return this.comment
16233 ? b `
16234 // ${this.comment}
16235 ${fn}`
16236 : fn;
16237 }
16238 render_listeners(chunk = '') {
16239 if (this.event_listeners.length > 0) {
16240 this.add_variable({ type: 'Identifier', name: '#mounted' });
16241 this.chunks.destroy.push(b `#mounted = false`);
16242 const dispose = {
16243 type: 'Identifier',
16244 name: `#dispose${chunk}`
16245 };
16246 this.add_variable(dispose);
16247 if (this.event_listeners.length === 1) {
16248 this.chunks.mount.push(b `
16249 if (!#mounted) {
16250 ${dispose} = ${this.event_listeners[0]};
16251 #mounted = true;
16252 }
16253 `);
16254 this.chunks.destroy.push(b `${dispose}();`);
16255 }
16256 else {
16257 this.chunks.mount.push(b `
16258 if (!#mounted) {
16259 ${dispose} = [
16260 ${this.event_listeners}
16261 ];
16262 #mounted = true;
16263 }
16264 `);
16265 this.chunks.destroy.push(b `@run_all(${dispose});`);
16266 }
16267 }
16268 }
16269}
16270
16271class Wrapper {
16272 constructor(renderer, block, parent, node) {
16273 this.node = node;
16274 // make these non-enumerable so that they can be logged sensibly
16275 // (TODO in dev only?)
16276 Object.defineProperties(this, {
16277 renderer: {
16278 value: renderer
16279 },
16280 parent: {
16281 value: parent
16282 }
16283 });
16284 this.can_use_innerhtml = !renderer.options.hydratable;
16285 this.is_static_content = !renderer.options.hydratable;
16286 block.wrappers.push(this);
16287 }
16288 cannot_use_innerhtml() {
16289 this.can_use_innerhtml = false;
16290 if (this.parent)
16291 this.parent.cannot_use_innerhtml();
16292 }
16293 not_static_content() {
16294 this.is_static_content = false;
16295 if (this.parent)
16296 this.parent.not_static_content();
16297 }
16298 get_or_create_anchor(block, parent_node, parent_nodes) {
16299 // TODO use this in EachBlock and IfBlock — tricky because
16300 // children need to be created first
16301 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
16302 const anchor = needs_anchor
16303 ? block.get_unique_name(`${this.var.name}_anchor`)
16304 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16305 if (needs_anchor) {
16306 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16307 }
16308 return anchor;
16309 }
16310 get_update_mount_node(anchor) {
16311 return ((this.parent && this.parent.is_dom_node())
16312 ? this.parent.var
16313 : x `${anchor}.parentNode`);
16314 }
16315 is_dom_node() {
16316 return (this.node.type === 'Element' ||
16317 this.node.type === 'Text' ||
16318 this.node.type === 'MustacheTag');
16319 }
16320 render(_block, _parent_node, _parent_nodes) {
16321 throw Error('Wrapper class is not renderable');
16322 }
16323}
16324
16325function create_debugging_comment(node, component) {
16326 const { locate, source } = component;
16327 let c = node.start;
16328 if (node.type === 'ElseBlock') {
16329 while (source[c - 1] !== '{')
16330 c -= 1;
16331 while (source[c - 1] === '{')
16332 c -= 1;
16333 }
16334 let d;
16335 if (node.type === 'InlineComponent' || node.type === 'Element') {
16336 if (node.children.length) {
16337 d = node.children[0].start;
16338 while (source[d - 1] !== '>')
16339 d -= 1;
16340 }
16341 else {
16342 d = node.start;
16343 while (source[d] !== '>')
16344 d += 1;
16345 d += 1;
16346 }
16347 }
16348 else if (node.type === 'Text' || node.type === 'Comment') {
16349 d = node.end;
16350 }
16351 else {
16352 // @ts-ignore
16353 d = node.expression ? node.expression.node.end : c;
16354 while (source[d] !== '}' && d <= source.length)
16355 d += 1;
16356 while (source[d] === '}')
16357 d += 1;
16358 }
16359 const start = locate(c);
16360 const loc = `(${start.line}:${start.column})`;
16361 return `${loc} ${source.slice(c, d)}`.replace(/\s/g, ' ');
16362}
16363
16364class AwaitBlockBranch extends Wrapper {
16365 constructor(status, renderer, block, parent, node, strip_whitespace, next_sibling) {
16366 super(renderer, block, parent, node);
16367 this.var = null;
16368 this.status = status;
16369 this.block = block.child({
16370 comment: create_debugging_comment(node, this.renderer.component),
16371 name: this.renderer.component.get_unique_name(`create_${status}_block`),
16372 type: status
16373 });
16374 this.add_context(parent.node[status + '_node'], parent.node[status + '_contexts']);
16375 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16376 this.is_dynamic = this.block.dependencies.size > 0;
16377 }
16378 add_context(node, contexts) {
16379 if (!node)
16380 return;
16381 if (node.type === 'Identifier') {
16382 this.value = node.name;
16383 this.renderer.add_to_context(this.value, true);
16384 }
16385 else {
16386 contexts.forEach(context => {
16387 this.renderer.add_to_context(context.key.name, true);
16388 });
16389 this.value = this.block.parent.get_unique_name('value').name;
16390 this.value_contexts = contexts;
16391 this.renderer.add_to_context(this.value, true);
16392 this.is_destructured = true;
16393 }
16394 this.value_index = this.renderer.context_lookup.get(this.value).index;
16395 }
16396 render(block, parent_node, parent_nodes) {
16397 this.fragment.render(block, parent_node, parent_nodes);
16398 if (this.is_destructured) {
16399 this.render_destructure();
16400 }
16401 }
16402 render_destructure() {
16403 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}]`)};`);
16404 const get_context = this.block.renderer.component.get_unique_name(`get_${this.status}_context`);
16405 this.block.renderer.blocks.push(b `
16406 function ${get_context}(#ctx) {
16407 ${props}
16408 }
16409 `);
16410 this.block.chunks.declarations.push(b `${get_context}(#ctx)`);
16411 if (this.block.has_update_method) {
16412 this.block.chunks.update.unshift(b `${get_context}(#ctx)`);
16413 }
16414 }
16415}
16416class AwaitBlockWrapper extends Wrapper {
16417 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16418 super(renderer, block, parent, node);
16419 this.var = { type: 'Identifier', name: 'await_block' };
16420 this.cannot_use_innerhtml();
16421 this.not_static_content();
16422 block.add_dependencies(this.node.expression.dependencies);
16423 let is_dynamic = false;
16424 let has_intros = false;
16425 let has_outros = false;
16426 ['pending', 'then', 'catch'].forEach((status) => {
16427 const child = this.node[status];
16428 const branch = new AwaitBlockBranch(status, renderer, block, this, child, strip_whitespace, next_sibling);
16429 renderer.blocks.push(branch.block);
16430 if (branch.is_dynamic) {
16431 is_dynamic = true;
16432 // TODO should blocks update their own parents?
16433 block.add_dependencies(branch.block.dependencies);
16434 }
16435 if (branch.block.has_intros)
16436 has_intros = true;
16437 if (branch.block.has_outros)
16438 has_outros = true;
16439 this[status] = branch;
16440 });
16441 ['pending', 'then', 'catch'].forEach(status => {
16442 this[status].block.has_update_method = is_dynamic;
16443 this[status].block.has_intro_method = has_intros;
16444 this[status].block.has_outro_method = has_outros;
16445 });
16446 if (has_outros) {
16447 block.add_outro();
16448 }
16449 }
16450 render(block, parent_node, parent_nodes) {
16451 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
16452 const update_mount_node = this.get_update_mount_node(anchor);
16453 const snippet = this.node.expression.manipulate(block);
16454 const info = block.get_unique_name('info');
16455 const promise = block.get_unique_name('promise');
16456 block.add_variable(promise);
16457 block.maintain_context = true;
16458 const info_props = x `{
16459 ctx: #ctx,
16460 current: null,
16461 token: null,
16462 hasCatch: ${this.catch.node.start !== null ? 'true' : 'false'},
16463 pending: ${this.pending.block.name},
16464 then: ${this.then.block.name},
16465 catch: ${this.catch.block.name},
16466 value: ${this.then.value_index},
16467 error: ${this.catch.value_index},
16468 blocks: ${this.pending.block.has_outro_method && x `[,,,]`}
16469 }`;
16470 block.chunks.init.push(b `
16471 let ${info} = ${info_props};
16472 `);
16473 block.chunks.init.push(b `
16474 @handle_promise(${promise} = ${snippet}, ${info});
16475 `);
16476 block.chunks.create.push(b `
16477 ${info}.block.c();
16478 `);
16479 if (parent_nodes && this.renderer.options.hydratable) {
16480 block.chunks.claim.push(b `
16481 ${info}.block.l(${parent_nodes});
16482 `);
16483 }
16484 const initial_mount_node = parent_node || '#target';
16485 const anchor_node = parent_node ? 'null' : '#anchor';
16486 const has_transitions = this.pending.block.has_intro_method || this.pending.block.has_outro_method;
16487 block.chunks.mount.push(b `
16488 ${info}.block.m(${initial_mount_node}, ${info}.anchor = ${anchor_node});
16489 ${info}.mount = () => ${update_mount_node};
16490 ${info}.anchor = ${anchor};
16491 `);
16492 if (has_transitions) {
16493 block.chunks.intro.push(b `@transition_in(${info}.block);`);
16494 }
16495 const dependencies = this.node.expression.dynamic_dependencies();
16496 let update_child_context;
16497 if (this.then.value && this.catch.value) {
16498 update_child_context = b `#child_ctx[${this.then.value_index}] = #child_ctx[${this.catch.value_index}] = ${info}.resolved;`;
16499 }
16500 else if (this.then.value) {
16501 update_child_context = b `#child_ctx[${this.then.value_index}] = ${info}.resolved;`;
16502 }
16503 else if (this.catch.value) {
16504 update_child_context = b `#child_ctx[${this.catch.value_index}] = ${info}.resolved;`;
16505 }
16506 if (dependencies.length > 0) {
16507 const condition = x `
16508 ${block.renderer.dirty(dependencies)} &&
16509 ${promise} !== (${promise} = ${snippet}) &&
16510 @handle_promise(${promise}, ${info})`;
16511 block.chunks.update.push(b `${info}.ctx = #ctx;`);
16512 if (this.pending.block.has_update_method) {
16513 block.chunks.update.push(b `
16514 if (${condition}) {
16515
16516 } else {
16517 const #child_ctx = #ctx.slice();
16518 ${update_child_context}
16519 ${info}.block.p(#child_ctx, #dirty);
16520 }
16521 `);
16522 }
16523 else {
16524 block.chunks.update.push(b `
16525 ${condition}
16526 `);
16527 }
16528 }
16529 else {
16530 if (this.pending.block.has_update_method) {
16531 block.chunks.update.push(b `
16532 {
16533 const #child_ctx = #ctx.slice();
16534 ${update_child_context}
16535 ${info}.block.p(#child_ctx, #dirty);
16536 }
16537 `);
16538 }
16539 }
16540 if (this.pending.block.has_outro_method) {
16541 block.chunks.outro.push(b `
16542 for (let #i = 0; #i < 3; #i += 1) {
16543 const block = ${info}.blocks[#i];
16544 @transition_out(block);
16545 }
16546 `);
16547 }
16548 block.chunks.destroy.push(b `
16549 ${info}.block.d(${parent_node ? null : 'detaching'});
16550 ${info}.token = null;
16551 ${info} = null;
16552 `);
16553 [this.pending, this.then, this.catch].forEach(branch => {
16554 branch.render(branch.block, null, x `#nodes`);
16555 });
16556 }
16557}
16558
16559const TRUE = x `true`;
16560const FALSE = x `false`;
16561class EventHandlerWrapper {
16562 constructor(node, parent) {
16563 this.node = node;
16564 this.parent = parent;
16565 if (!node.expression) {
16566 this.parent.renderer.add_to_context(node.handler_name.name);
16567 this.parent.renderer.component.partly_hoisted.push(b `
16568 function ${node.handler_name.name}(event) {
16569 @bubble($$self, event);
16570 }
16571 `);
16572 }
16573 }
16574 get_snippet(block) {
16575 const snippet = this.node.expression ? this.node.expression.manipulate(block) : block.renderer.reference(this.node.handler_name);
16576 if (this.node.reassigned) {
16577 block.maintain_context = true;
16578 return x `function () { if (@is_function(${snippet})) ${snippet}.apply(this, arguments); }`;
16579 }
16580 return snippet;
16581 }
16582 render(block, target) {
16583 let snippet = this.get_snippet(block);
16584 if (this.node.modifiers.has('preventDefault'))
16585 snippet = x `@prevent_default(${snippet})`;
16586 if (this.node.modifiers.has('stopPropagation'))
16587 snippet = x `@stop_propagation(${snippet})`;
16588 if (this.node.modifiers.has('self'))
16589 snippet = x `@self(${snippet})`;
16590 const args = [];
16591 const opts = ['nonpassive', 'passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod));
16592 if (opts.length) {
16593 if (opts.length === 1 && opts[0] === 'capture') {
16594 args.push(TRUE);
16595 }
16596 else {
16597 args.push(x `{ ${opts.map(opt => opt === 'nonpassive'
16598 ? p `passive: false`
16599 : p `${opt}: true`)} }`);
16600 }
16601 }
16602 else if (block.renderer.options.dev) {
16603 args.push(FALSE);
16604 }
16605 if (block.renderer.options.dev) {
16606 args.push(this.node.modifiers.has('preventDefault') ? TRUE : FALSE);
16607 args.push(this.node.modifiers.has('stopPropagation') ? TRUE : FALSE);
16608 }
16609 block.event_listeners.push(x `@listen(${target}, "${this.node.name}", ${snippet}, ${args})`);
16610 }
16611}
16612
16613function add_event_handlers(block, target, handlers) {
16614 handlers.forEach(handler => add_event_handler(block, target, handler));
16615}
16616function add_event_handler(block, target, handler) {
16617 handler.render(block, target);
16618}
16619
16620class BodyWrapper extends Wrapper {
16621 constructor(renderer, block, parent, node) {
16622 super(renderer, block, parent, node);
16623 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
16624 }
16625 render(block, _parent_node, _parent_nodes) {
16626 add_event_handlers(block, x `@_document.body`, this.handlers);
16627 }
16628}
16629
16630function add_to_set(a, b) {
16631 // @ts-ignore
16632 b.forEach(item => {
16633 a.add(item);
16634 });
16635}
16636
16637class DebugTagWrapper extends Wrapper {
16638 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
16639 super(renderer, block, parent, node);
16640 }
16641 render(block, _parent_node, _parent_nodes) {
16642 const { renderer } = this;
16643 const { component } = renderer;
16644 if (!renderer.options.dev)
16645 return;
16646 const { var_lookup } = component;
16647 const start = component.locate(this.node.start + 1);
16648 const end = { line: start.line, column: start.column + 6 };
16649 const loc = { start, end };
16650 const debug = {
16651 type: 'DebuggerStatement',
16652 loc
16653 };
16654 if (this.node.expressions.length === 0) {
16655 // Debug all
16656 block.chunks.create.push(debug);
16657 block.chunks.update.push(debug);
16658 }
16659 else {
16660 const log = {
16661 type: 'Identifier',
16662 name: 'log',
16663 loc
16664 };
16665 const dependencies = new Set();
16666 this.node.expressions.forEach(expression => {
16667 add_to_set(dependencies, expression.dependencies);
16668 });
16669 const contextual_identifiers = this.node.expressions
16670 .filter(e => {
16671 const variable = var_lookup.get(e.node.name);
16672 return !(variable && variable.hoistable);
16673 })
16674 .map(e => e.node.name);
16675 const logged_identifiers = this.node.expressions.map(e => p `${e.node.name}`);
16676 const debug_statements = b `
16677 ${contextual_identifiers.map(name => b `const ${name} = ${renderer.reference(name)};`)}
16678 @_console.${log}({ ${logged_identifiers} });
16679 debugger;`;
16680 if (dependencies.size) {
16681 const condition = renderer.dirty(Array.from(dependencies));
16682 block.chunks.update.push(b `
16683 if (${condition}) {
16684 ${debug_statements}
16685 }
16686 `);
16687 }
16688 block.chunks.create.push(b `{
16689 ${debug_statements}
16690 }`);
16691 }
16692 }
16693}
16694
16695function get_object(node) {
16696 while (node.type === 'MemberExpression')
16697 node = node.object;
16698 return node;
16699}
16700
16701class ElseBlockWrapper extends Wrapper {
16702 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16703 super(renderer, block, parent, node);
16704 this.var = null;
16705 this.block = block.child({
16706 comment: create_debugging_comment(node, this.renderer.component),
16707 name: this.renderer.component.get_unique_name('create_else_block'),
16708 type: 'else'
16709 });
16710 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16711 this.is_dynamic = this.block.dependencies.size > 0;
16712 }
16713}
16714class EachBlockWrapper extends Wrapper {
16715 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16716 super(renderer, block, parent, node);
16717 this.updates = [];
16718 this.var = { type: 'Identifier', name: 'each' };
16719 this.cannot_use_innerhtml();
16720 this.not_static_content();
16721 const { dependencies } = node.expression;
16722 block.add_dependencies(dependencies);
16723 this.node.contexts.forEach(context => {
16724 renderer.add_to_context(context.key.name, true);
16725 });
16726 this.block = block.child({
16727 comment: create_debugging_comment(this.node, this.renderer.component),
16728 name: renderer.component.get_unique_name('create_each_block'),
16729 type: 'each',
16730 // @ts-ignore todo: probably error
16731 key: node.key,
16732 bindings: new Map(block.bindings)
16733 });
16734 // TODO this seems messy
16735 this.block.has_animation = this.node.has_animation;
16736 this.index_name = this.node.index
16737 ? { type: 'Identifier', name: this.node.index }
16738 : renderer.component.get_unique_name(`${this.node.context}_index`);
16739 const fixed_length = node.expression.node.type === 'ArrayExpression' &&
16740 node.expression.node.elements.every(element => element.type !== 'SpreadElement')
16741 ? node.expression.node.elements.length
16742 : null;
16743 // hack the sourcemap, so that if data is missing the bug
16744 // is easy to find
16745 let c = this.node.start + 2;
16746 while (renderer.component.source[c] !== 'e')
16747 c += 1;
16748 const start = renderer.component.locate(c);
16749 const end = { line: start.line, column: start.column + 4 };
16750 const length = {
16751 type: 'Identifier',
16752 name: 'length',
16753 loc: { start, end }
16754 };
16755 const each_block_value = renderer.component.get_unique_name(`${this.var.name}_value`);
16756 const iterations = block.get_unique_name(`${this.var.name}_blocks`);
16757 renderer.add_to_context(each_block_value.name, true);
16758 renderer.add_to_context(this.index_name.name, true);
16759 this.vars = {
16760 create_each_block: this.block.name,
16761 each_block_value,
16762 get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`),
16763 iterations,
16764 // optimisation for array literal
16765 fixed_length,
16766 data_length: fixed_length === null ? x `${each_block_value}.${length}` : fixed_length,
16767 view_length: fixed_length === null ? x `${iterations}.length` : fixed_length
16768 };
16769 const object = get_object(node.expression.node);
16770 const store = object.type === 'Identifier' && object.name[0] === '$' ? object.name.slice(1) : null;
16771 node.contexts.forEach(prop => {
16772 this.block.bindings.set(prop.key.name, {
16773 object: this.vars.each_block_value,
16774 property: this.index_name,
16775 modifier: prop.modifier,
16776 snippet: prop.modifier(x `${this.vars.each_block_value}[${this.index_name}]`),
16777 store,
16778 tail: prop.modifier(x `[${this.index_name}]`)
16779 });
16780 });
16781 if (this.node.index) {
16782 this.block.get_unique_name(this.node.index); // this prevents name collisions (#1254)
16783 }
16784 renderer.blocks.push(this.block);
16785 this.fragment = new FragmentWrapper(renderer, this.block, node.children, this, strip_whitespace, next_sibling);
16786 if (this.node.else) {
16787 this.else = new ElseBlockWrapper(renderer, block, this, this.node.else, strip_whitespace, next_sibling);
16788 renderer.blocks.push(this.else.block);
16789 if (this.else.is_dynamic) {
16790 this.block.add_dependencies(this.else.block.dependencies);
16791 }
16792 }
16793 block.add_dependencies(this.block.dependencies);
16794 if (this.block.has_outros || (this.else && this.else.block.has_outros)) {
16795 block.add_outro();
16796 }
16797 }
16798 render(block, parent_node, parent_nodes) {
16799 if (this.fragment.nodes.length === 0)
16800 return;
16801 const { renderer } = this;
16802 const { component } = renderer;
16803 const needs_anchor = this.next
16804 ? !this.next.is_dom_node() :
16805 !parent_node || !this.parent.is_dom_node();
16806 const snippet = this.node.expression.manipulate(block);
16807 block.chunks.init.push(b `let ${this.vars.each_block_value} = ${snippet};`);
16808 if (this.renderer.options.dev) {
16809 block.chunks.init.push(b `@validate_each_argument(${this.vars.each_block_value});`);
16810 }
16811 const initial_anchor_node = { type: 'Identifier', name: parent_node ? 'null' : '#anchor' };
16812 const initial_mount_node = parent_node || { type: 'Identifier', name: '#target' };
16813 const update_anchor_node = needs_anchor
16814 ? block.get_unique_name(`${this.var.name}_anchor`)
16815 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16816 const update_mount_node = this.get_update_mount_node(update_anchor_node);
16817 const args = {
16818 block,
16819 parent_node,
16820 parent_nodes,
16821 snippet,
16822 initial_anchor_node,
16823 initial_mount_node,
16824 update_anchor_node,
16825 update_mount_node
16826 };
16827 const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
16828 this.node.expression.dynamic_dependencies().forEach((dependency) => {
16829 all_dependencies.add(dependency);
16830 });
16831 if (this.node.key) {
16832 this.node.key.dynamic_dependencies().forEach((dependency) => {
16833 all_dependencies.add(dependency);
16834 });
16835 }
16836 this.dependencies = all_dependencies;
16837 if (this.node.key) {
16838 this.render_keyed(args);
16839 }
16840 else {
16841 this.render_unkeyed(args);
16842 }
16843 if (this.block.has_intro_method || this.block.has_outro_method) {
16844 block.chunks.intro.push(b `
16845 for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) {
16846 @transition_in(${this.vars.iterations}[#i]);
16847 }
16848 `);
16849 }
16850 if (needs_anchor) {
16851 block.add_element(update_anchor_node, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16852 }
16853 if (this.else) {
16854 const each_block_else = component.get_unique_name(`${this.var.name}_else`);
16855 block.chunks.init.push(b `let ${each_block_else} = null;`);
16856 // TODO neaten this up... will end up with an empty line in the block
16857 block.chunks.init.push(b `
16858 if (!${this.vars.data_length}) {
16859 ${each_block_else} = ${this.else.block.name}(#ctx);
16860 }
16861 `);
16862 block.chunks.create.push(b `
16863 if (${each_block_else}) {
16864 ${each_block_else}.c();
16865 }
16866 `);
16867 if (this.renderer.options.hydratable) {
16868 block.chunks.claim.push(b `
16869 if (${each_block_else}) {
16870 ${each_block_else}.l(${parent_nodes});
16871 }
16872 `);
16873 }
16874 block.chunks.mount.push(b `
16875 if (${each_block_else}) {
16876 ${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node});
16877 }
16878 `);
16879 const has_transitions = !!(this.else.block.has_intro_method || this.else.block.has_outro_method);
16880 const destroy_block_else = this.else.block.has_outro_method
16881 ? b `
16882 @group_outros();
16883 @transition_out(${each_block_else}, 1, 1, () => {
16884 ${each_block_else} = null;
16885 });
16886 @check_outros();`
16887 : b `
16888 ${each_block_else}.d(1);
16889 ${each_block_else} = null;`;
16890 if (this.else.block.has_update_method) {
16891 this.updates.push(b `
16892 if (!${this.vars.data_length} && ${each_block_else}) {
16893 ${each_block_else}.p(#ctx, #dirty);
16894 } else if (!${this.vars.data_length}) {
16895 ${each_block_else} = ${this.else.block.name}(#ctx);
16896 ${each_block_else}.c();
16897 ${has_transitions && b `@transition_in(${each_block_else}, 1);`}
16898 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16899 } else if (${each_block_else}) {
16900 ${destroy_block_else};
16901 }
16902 `);
16903 }
16904 else {
16905 this.updates.push(b `
16906 if (${this.vars.data_length}) {
16907 if (${each_block_else}) {
16908 ${destroy_block_else};
16909 }
16910 } else if (!${each_block_else}) {
16911 ${each_block_else} = ${this.else.block.name}(#ctx);
16912 ${each_block_else}.c();
16913 ${has_transitions && b `@transition_in(${each_block_else}, 1);`}
16914 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16915 }
16916 `);
16917 }
16918 block.chunks.destroy.push(b `
16919 if (${each_block_else}) ${each_block_else}.d(${parent_node ? '' : 'detaching'});
16920 `);
16921 }
16922 if (this.updates.length) {
16923 block.chunks.update.push(b `
16924 if (${block.renderer.dirty(Array.from(all_dependencies))}) {
16925 ${this.updates}
16926 }
16927 `);
16928 }
16929 this.fragment.render(this.block, null, x `#nodes`);
16930 if (this.else) {
16931 this.else.fragment.render(this.else.block, null, x `#nodes`);
16932 }
16933 this.context_props = this.node.contexts.map(prop => b `child_ctx[${renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x `list[i]`)};`);
16934 if (this.node.has_binding)
16935 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`);
16936 if (this.node.has_binding || this.node.has_index_binding || this.node.index)
16937 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`);
16938 // TODO which is better — Object.create(array) or array.slice()?
16939 renderer.blocks.push(b `
16940 function ${this.vars.get_each_context}(#ctx, list, i) {
16941 const child_ctx = #ctx.slice();
16942 ${this.context_props}
16943 return child_ctx;
16944 }
16945 `);
16946 }
16947 render_keyed({ block, parent_node, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
16948 const { create_each_block, iterations, data_length, view_length } = this.vars;
16949 const get_key = block.get_unique_name('get_key');
16950 const lookup = block.get_unique_name(`${this.var.name}_lookup`);
16951 block.add_variable(iterations, x `[]`);
16952 block.add_variable(lookup, x `new @_Map()`);
16953 if (this.fragment.nodes[0].is_dom_node()) {
16954 this.block.first = this.fragment.nodes[0].var;
16955 }
16956 else {
16957 this.block.first = this.block.get_unique_name('first');
16958 this.block.add_element(this.block.first, x `@empty()`, parent_nodes && x `@empty()`, null);
16959 }
16960 block.chunks.init.push(b `
16961 const ${get_key} = #ctx => ${this.node.key.manipulate(block)};
16962
16963 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
16964 for (let #i = 0; #i < ${data_length}; #i += 1) {
16965 let child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
16966 let key = ${get_key}(child_ctx);
16967 ${lookup}.set(key, ${iterations}[#i] = ${create_each_block}(key, child_ctx));
16968 }
16969 `);
16970 block.chunks.create.push(b `
16971 for (let #i = 0; #i < ${view_length}; #i += 1) {
16972 ${iterations}[#i].c();
16973 }
16974 `);
16975 if (parent_nodes && this.renderer.options.hydratable) {
16976 block.chunks.claim.push(b `
16977 for (let #i = 0; #i < ${view_length}; #i += 1) {
16978 ${iterations}[#i].l(${parent_nodes});
16979 }
16980 `);
16981 }
16982 block.chunks.mount.push(b `
16983 for (let #i = 0; #i < ${view_length}; #i += 1) {
16984 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
16985 }
16986 `);
16987 const dynamic = this.block.has_update_method;
16988 const destroy = this.node.has_animation
16989 ? (this.block.has_outros
16990 ? '@fix_and_outro_and_destroy_block'
16991 : '@fix_and_destroy_block')
16992 : this.block.has_outros
16993 ? '@outro_and_destroy_block'
16994 : '@destroy_block';
16995 if (this.dependencies.size) {
16996 this.block.maintain_context = true;
16997 this.updates.push(b `
16998 ${this.vars.each_block_value} = ${snippet};
16999 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
17000
17001 ${this.block.has_outros && b `@group_outros();`}
17002 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`}
17003 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
17004 ${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});
17005 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
17006 ${this.block.has_outros && b `@check_outros();`}
17007 `);
17008 }
17009 if (this.block.has_outros) {
17010 block.chunks.outro.push(b `
17011 for (let #i = 0; #i < ${view_length}; #i += 1) {
17012 @transition_out(${iterations}[#i]);
17013 }
17014 `);
17015 }
17016 block.chunks.destroy.push(b `
17017 for (let #i = 0; #i < ${view_length}; #i += 1) {
17018 ${iterations}[#i].d(${parent_node ? null : 'detaching'});
17019 }
17020 `);
17021 }
17022 render_unkeyed({ block, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
17023 const { create_each_block, iterations, fixed_length, data_length, view_length } = this.vars;
17024 block.chunks.init.push(b `
17025 let ${iterations} = [];
17026
17027 for (let #i = 0; #i < ${data_length}; #i += 1) {
17028 ${iterations}[#i] = ${create_each_block}(${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i));
17029 }
17030 `);
17031 block.chunks.create.push(b `
17032 for (let #i = 0; #i < ${view_length}; #i += 1) {
17033 ${iterations}[#i].c();
17034 }
17035 `);
17036 if (parent_nodes && this.renderer.options.hydratable) {
17037 block.chunks.claim.push(b `
17038 for (let #i = 0; #i < ${view_length}; #i += 1) {
17039 ${iterations}[#i].l(${parent_nodes});
17040 }
17041 `);
17042 }
17043 block.chunks.mount.push(b `
17044 for (let #i = 0; #i < ${view_length}; #i += 1) {
17045 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
17046 }
17047 `);
17048 if (this.dependencies.size) {
17049 const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
17050 const for_loop_body = this.block.has_update_method
17051 ? b `
17052 if (${iterations}[#i]) {
17053 ${iterations}[#i].p(child_ctx, #dirty);
17054 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
17055 } else {
17056 ${iterations}[#i] = ${create_each_block}(child_ctx);
17057 ${iterations}[#i].c();
17058 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
17059 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
17060 }
17061 `
17062 : has_transitions
17063 ? b `
17064 if (${iterations}[#i]) {
17065 @transition_in(${this.vars.iterations}[#i], 1);
17066 } else {
17067 ${iterations}[#i] = ${create_each_block}(child_ctx);
17068 ${iterations}[#i].c();
17069 @transition_in(${this.vars.iterations}[#i], 1);
17070 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
17071 }
17072 `
17073 : b `
17074 if (!${iterations}[#i]) {
17075 ${iterations}[#i] = ${create_each_block}(child_ctx);
17076 ${iterations}[#i].c();
17077 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
17078 }
17079 `;
17080 const start = this.block.has_update_method ? 0 : '#old_length';
17081 let remove_old_blocks;
17082 if (this.block.has_outros) {
17083 const out = block.get_unique_name('out');
17084 block.chunks.init.push(b `
17085 const ${out} = i => @transition_out(${iterations}[i], 1, 1, () => {
17086 ${iterations}[i] = null;
17087 });
17088 `);
17089 remove_old_blocks = b `
17090 @group_outros();
17091 for (#i = ${data_length}; #i < ${view_length}; #i += 1) {
17092 ${out}(#i);
17093 }
17094 @check_outros();
17095 `;
17096 }
17097 else {
17098 remove_old_blocks = b `
17099 for (${this.block.has_update_method ? null : x `#i = ${data_length}`}; #i < ${this.block.has_update_method ? view_length : '#old_length'}; #i += 1) {
17100 ${iterations}[#i].d(1);
17101 }
17102 ${!fixed_length && b `${view_length} = ${data_length};`}
17103 `;
17104 }
17105 // We declare `i` as block scoped here, as the `remove_old_blocks` code
17106 // may rely on continuing where this iteration stopped.
17107 const update = b `
17108 ${!this.block.has_update_method && b `const #old_length = ${this.vars.each_block_value}.length;`}
17109 ${this.vars.each_block_value} = ${snippet};
17110 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
17111
17112 let #i;
17113 for (#i = ${start}; #i < ${data_length}; #i += 1) {
17114 const child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
17115
17116 ${for_loop_body}
17117 }
17118
17119 ${remove_old_blocks}
17120 `;
17121 this.updates.push(update);
17122 }
17123 if (this.block.has_outros) {
17124 block.chunks.outro.push(b `
17125 ${iterations} = ${iterations}.filter(@_Boolean);
17126 for (let #i = 0; #i < ${view_length}; #i += 1) {
17127 @transition_out(${iterations}[#i]);
17128 }
17129 `);
17130 }
17131 block.chunks.destroy.push(b `@destroy_each(${iterations}, detaching);`);
17132 }
17133}
17134
17135function string_literal(data) {
17136 return {
17137 type: 'Literal',
17138 value: data
17139 };
17140}
17141const escaped = {
17142 '"': '&quot;',
17143 "'": '&#39;',
17144 '&': '&amp;',
17145 '<': '&lt;',
17146 '>': '&gt;'
17147};
17148function escape_html(html) {
17149 return String(html).replace(/["'&<>]/g, match => escaped[match]);
17150}
17151function escape_template(str) {
17152 return str.replace(/(\${|`|\\)/g, '\\$1');
17153}
17154
17155class TextWrapper extends Wrapper {
17156 constructor(renderer, block, parent, node, data) {
17157 super(renderer, block, parent, node);
17158 this.skip = this.node.should_skip();
17159 this.data = data;
17160 this.var = (this.skip ? null : x `t`);
17161 }
17162 use_space() {
17163 if (this.renderer.component.component_options.preserveWhitespace)
17164 return false;
17165 if (/[\S\u00A0]/.test(this.data))
17166 return false;
17167 let node = this.parent && this.parent.node;
17168 while (node) {
17169 if (node.type === 'Element' && node.name === 'pre') {
17170 return false;
17171 }
17172 node = node.parent;
17173 }
17174 return true;
17175 }
17176 render(block, parent_node, parent_nodes) {
17177 if (this.skip)
17178 return;
17179 const use_space = this.use_space();
17180 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);
17181 }
17182}
17183
17184const 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(' ');
17185const svg_attribute_lookup = new Map();
17186svg_attributes.forEach(name => {
17187 svg_attribute_lookup.set(name.toLowerCase(), name);
17188});
17189function fix_attribute_casing(name) {
17190 name = name.toLowerCase();
17191 return svg_attribute_lookup.get(name) || name;
17192}
17193
17194const html = 'http://www.w3.org/1999/xhtml';
17195const mathml = 'http://www.w3.org/1998/Math/MathML';
17196const svg = 'http://www.w3.org/2000/svg';
17197const xlink = 'http://www.w3.org/1999/xlink';
17198const xml = 'http://www.w3.org/XML/1998/namespace';
17199const xmlns = 'http://www.w3.org/2000/xmlns';
17200const valid_namespaces = [
17201 'html',
17202 'mathml',
17203 'svg',
17204 'xlink',
17205 'xml',
17206 'xmlns',
17207 html,
17208 mathml,
17209 svg,
17210 xlink,
17211 xml,
17212 xmlns
17213];
17214const namespaces = { html, mathml, svg, xlink, xml, xmlns };
17215
17216function handle_select_value_binding(attr, dependencies) {
17217 const { parent } = attr;
17218 if (parent.node.name === 'select') {
17219 parent.select_binding_dependencies = dependencies;
17220 dependencies.forEach((prop) => {
17221 parent.renderer.component.indirect_dependencies.set(prop, new Set());
17222 });
17223 }
17224}
17225
17226class BaseAttributeWrapper {
17227 constructor(parent, block, node) {
17228 this.node = node;
17229 this.parent = parent;
17230 if (node.dependencies.size > 0) {
17231 parent.cannot_use_innerhtml();
17232 parent.not_static_content();
17233 block.add_dependencies(node.dependencies);
17234 }
17235 }
17236 render(_block) { }
17237}
17238class AttributeWrapper extends BaseAttributeWrapper {
17239 constructor(parent, block, node) {
17240 super(parent, block, node);
17241 if (node.dependencies.size > 0) {
17242 // special case — <option value={foo}> — see below
17243 if (this.parent.node.name === 'option' && node.name === 'value') {
17244 let select = this.parent;
17245 while (select && (select.node.type !== 'Element' || select.node.name !== 'select')) {
17246 // @ts-ignore todo: doublecheck this, but looks to be correct
17247 select = select.parent;
17248 }
17249 if (select && select.select_binding_dependencies) {
17250 select.select_binding_dependencies.forEach(prop => {
17251 this.node.dependencies.forEach((dependency) => {
17252 this.parent.renderer.component.indirect_dependencies.get(prop).add(dependency);
17253 });
17254 });
17255 }
17256 }
17257 if (node.name === 'value') {
17258 handle_select_value_binding(this, node.dependencies);
17259 }
17260 }
17261 this.name = fix_attribute_casing(this.node.name);
17262 this.metadata = this.get_metadata();
17263 this.is_indirectly_bound_value = is_indirectly_bound_value(this);
17264 this.property_name = this.is_indirectly_bound_value
17265 ? '__value'
17266 : this.metadata && this.metadata.property_name;
17267 this.is_src = this.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
17268 this.is_select_value_attribute = this.name === 'value' && this.parent.node.name === 'select';
17269 this.is_input_value = this.name === 'value' && this.parent.node.name === 'input';
17270 this.should_cache = should_cache(this);
17271 }
17272 render(block) {
17273 const element = this.parent;
17274 const { name, property_name, should_cache, is_indirectly_bound_value } = this;
17275 // xlink is a special case... we could maybe extend this to generic
17276 // namespaced attributes but I'm not sure that's applicable in
17277 // HTML5?
17278 const method = /-/.test(element.node.name)
17279 ? '@set_custom_element_data'
17280 : name.slice(0, 6) === 'xlink:'
17281 ? '@xlink_attr'
17282 : '@attr';
17283 const is_legacy_input_type = element.renderer.component.compile_options.legacy && name === 'type' && this.parent.node.name === 'input';
17284 const dependencies = this.get_dependencies();
17285 const value = this.get_value(block);
17286 let updater;
17287 const init = this.get_init(block, value);
17288 if (is_legacy_input_type) {
17289 block.chunks.hydrate.push(b `@set_input_type(${element.var}, ${init});`);
17290 updater = b `@set_input_type(${element.var}, ${should_cache ? this.last : value});`;
17291 }
17292 else if (this.is_select_value_attribute) {
17293 // annoying special case
17294 const is_multiple_select = element.node.get_static_attribute_value('multiple');
17295 if (is_multiple_select) {
17296 updater = b `@select_options(${element.var}, ${value});`;
17297 }
17298 else {
17299 updater = b `@select_option(${element.var}, ${value});`;
17300 }
17301 block.chunks.mount.push(b `
17302 ${updater}
17303 `);
17304 }
17305 else if (this.is_src) {
17306 block.chunks.hydrate.push(b `if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${this.last});`);
17307 updater = b `${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
17308 }
17309 else if (property_name) {
17310 block.chunks.hydrate.push(b `${element.var}.${property_name} = ${init};`);
17311 updater = block.renderer.options.dev
17312 ? b `@prop_dev(${element.var}, "${property_name}", ${should_cache ? this.last : value});`
17313 : b `${element.var}.${property_name} = ${should_cache ? this.last : value};`;
17314 }
17315 else {
17316 block.chunks.hydrate.push(b `${method}(${element.var}, "${name}", ${init});`);
17317 updater = b `${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
17318 }
17319 if (is_indirectly_bound_value) {
17320 const update_value = b `${element.var}.value = ${element.var}.__value;`;
17321 block.chunks.hydrate.push(update_value);
17322 updater = b `
17323 ${updater}
17324 ${update_value};
17325 `;
17326 }
17327 if (dependencies.length > 0) {
17328 const condition = this.get_dom_update_conditions(block, block.renderer.dirty(dependencies));
17329 block.chunks.update.push(b `
17330 if (${condition}) {
17331 ${updater}
17332 }`);
17333 }
17334 // special case – autofocus. has to be handled in a bit of a weird way
17335 if (this.node.is_true && name === 'autofocus') {
17336 block.autofocus = element.var;
17337 }
17338 }
17339 get_init(block, value) {
17340 this.last = this.should_cache && block.get_unique_name(`${this.parent.var.name}_${this.name.replace(/[^a-zA-Z_$]/g, '_')}_value`);
17341 if (this.should_cache)
17342 block.add_variable(this.last);
17343 return this.should_cache ? x `${this.last} = ${value}` : value;
17344 }
17345 get_dom_update_conditions(block, dependency_condition) {
17346 const { property_name, should_cache, last } = this;
17347 const element = this.parent;
17348 const value = this.get_value(block);
17349 let condition = dependency_condition;
17350 if (should_cache) {
17351 condition = this.is_src
17352 ? x `${condition} && (${element.var}.src !== (${last} = ${value}))`
17353 : x `${condition} && (${last} !== (${last} = ${value}))`;
17354 }
17355 if (this.is_input_value) {
17356 const type = element.node.get_static_attribute_value('type');
17357 if (type === null || type === '' || type === 'text' || type === 'email' || type === 'password') {
17358 condition = x `${condition} && ${element.var}.${property_name} !== ${should_cache ? last : value}`;
17359 }
17360 }
17361 if (block.has_outros) {
17362 condition = x `!#current || ${condition}`;
17363 }
17364 return condition;
17365 }
17366 get_dependencies() {
17367 const node_dependencies = this.node.get_dependencies();
17368 const dependencies = new Set(node_dependencies);
17369 node_dependencies.forEach((prop) => {
17370 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17371 if (indirect_dependencies) {
17372 indirect_dependencies.forEach(indirect_dependency => {
17373 dependencies.add(indirect_dependency);
17374 });
17375 }
17376 });
17377 return Array.from(dependencies);
17378 }
17379 get_metadata() {
17380 if (this.parent.node.namespace)
17381 return null;
17382 const metadata = attribute_lookup[this.name];
17383 if (metadata && metadata.applies_to && !metadata.applies_to.includes(this.parent.node.name))
17384 return null;
17385 return metadata;
17386 }
17387 get_value(block) {
17388 if (this.node.is_true) {
17389 if (this.metadata && boolean_attribute.has(this.metadata.property_name.toLowerCase())) {
17390 return x `true`;
17391 }
17392 return x `""`;
17393 }
17394 if (this.node.chunks.length === 0)
17395 return x `""`;
17396 // TODO some of this code is repeated in Tag.ts — would be good to
17397 // DRY it out if that's possible without introducing crazy indirection
17398 if (this.node.chunks.length === 1) {
17399 return this.node.chunks[0].type === 'Text'
17400 ? string_literal(this.node.chunks[0].data)
17401 : this.node.chunks[0].manipulate(block);
17402 }
17403 let value = this.node.name === 'class'
17404 ? this.get_class_name_text(block)
17405 : this.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17406 // '{foo} {bar}' — treat as string concatenation
17407 if (this.node.chunks[0].type !== 'Text') {
17408 value = x `"" + ${value}`;
17409 }
17410 return value;
17411 }
17412 get_class_name_text(block) {
17413 const scoped_css = this.node.chunks.some((chunk) => chunk.synthetic);
17414 const rendered = this.render_chunks(block);
17415 if (scoped_css && rendered.length === 2) {
17416 // we have a situation like class={possiblyUndefined}
17417 rendered[0] = x `@null_to_empty(${rendered[0]})`;
17418 }
17419 return rendered.reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17420 }
17421 render_chunks(block) {
17422 return this.node.chunks.map((chunk) => {
17423 if (chunk.type === 'Text') {
17424 return string_literal(chunk.data);
17425 }
17426 return chunk.manipulate(block);
17427 });
17428 }
17429 stringify() {
17430 if (this.node.is_true)
17431 return '';
17432 const value = this.node.chunks;
17433 if (value.length === 0)
17434 return '=""';
17435 return `="${value.map(chunk => {
17436 return chunk.type === 'Text'
17437 ? chunk.data.replace(/"/g, '\\"')
17438 : `\${${chunk.manipulate()}}`;
17439 }).join('')}"`;
17440 }
17441}
17442// source: https://html.spec.whatwg.org/multipage/indices.html
17443const attribute_lookup = {
17444 allowfullscreen: { property_name: 'allowFullscreen', applies_to: ['iframe'] },
17445 allowpaymentrequest: { property_name: 'allowPaymentRequest', applies_to: ['iframe'] },
17446 async: { applies_to: ['script'] },
17447 autofocus: { applies_to: ['button', 'input', 'keygen', 'select', 'textarea'] },
17448 autoplay: { applies_to: ['audio', 'video'] },
17449 checked: { applies_to: ['input'] },
17450 controls: { applies_to: ['audio', 'video'] },
17451 default: { applies_to: ['track'] },
17452 defer: { applies_to: ['script'] },
17453 disabled: {
17454 applies_to: [
17455 'button',
17456 'fieldset',
17457 'input',
17458 'keygen',
17459 'optgroup',
17460 'option',
17461 'select',
17462 'textarea'
17463 ]
17464 },
17465 formnovalidate: { property_name: 'formNoValidate', applies_to: ['button', 'input'] },
17466 hidden: {},
17467 indeterminate: { applies_to: ['input'] },
17468 ismap: { property_name: 'isMap', applies_to: ['img'] },
17469 loop: { applies_to: ['audio', 'bgsound', 'video'] },
17470 multiple: { applies_to: ['input', 'select'] },
17471 muted: { applies_to: ['audio', 'video'] },
17472 nomodule: { property_name: 'noModule', applies_to: ['script'] },
17473 novalidate: { property_name: 'noValidate', applies_to: ['form'] },
17474 open: { applies_to: ['details', 'dialog'] },
17475 playsinline: { property_name: 'playsInline', applies_to: ['video'] },
17476 readonly: { property_name: 'readOnly', applies_to: ['input', 'textarea'] },
17477 required: { applies_to: ['input', 'select', 'textarea'] },
17478 reversed: { applies_to: ['ol'] },
17479 selected: { applies_to: ['option'] },
17480 value: {
17481 applies_to: [
17482 'button',
17483 'option',
17484 'input',
17485 'li',
17486 'meter',
17487 'progress',
17488 'param',
17489 'select',
17490 'textarea'
17491 ]
17492 }
17493};
17494Object.keys(attribute_lookup).forEach(name => {
17495 const metadata = attribute_lookup[name];
17496 if (!metadata.property_name)
17497 metadata.property_name = name;
17498});
17499// source: https://html.spec.whatwg.org/multipage/indices.html
17500const boolean_attribute = new Set([
17501 'allowfullscreen',
17502 'allowpaymentrequest',
17503 'async',
17504 'autofocus',
17505 'autoplay',
17506 'checked',
17507 'controls',
17508 'default',
17509 'defer',
17510 'disabled',
17511 'formnovalidate',
17512 'hidden',
17513 'ismap',
17514 'itemscope',
17515 'loop',
17516 'multiple',
17517 'muted',
17518 'nomodule',
17519 'novalidate',
17520 'open',
17521 'playsinline',
17522 'readonly',
17523 'required',
17524 'reversed',
17525 'selected'
17526]);
17527function should_cache(attribute) {
17528 return attribute.is_src || attribute.node.should_cache();
17529}
17530function is_indirectly_bound_value(attribute) {
17531 const element = attribute.parent;
17532 return attribute.name === 'value' &&
17533 (element.node.name === 'option' || // TODO check it's actually bound
17534 (element.node.name === 'input' &&
17535 element.node.bindings.some((binding) => /checked|group/.test(binding.name))));
17536}
17537
17538class StyleAttributeWrapper extends AttributeWrapper {
17539 render(block) {
17540 const style_props = optimize_style(this.node.chunks);
17541 if (!style_props)
17542 return super.render(block);
17543 style_props.forEach((prop) => {
17544 let value;
17545 if (is_dynamic(prop.value)) {
17546 const prop_dependencies = new Set();
17547 value = prop.value
17548 .map(chunk => {
17549 if (chunk.type === 'Text') {
17550 return string_literal(chunk.data);
17551 }
17552 else {
17553 add_to_set(prop_dependencies, chunk.dynamic_dependencies());
17554 return chunk.manipulate(block);
17555 }
17556 })
17557 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17558 // TODO is this necessary? style.setProperty always treats value as string, no?
17559 // if (prop.value.length === 1 || prop.value[0].type !== 'Text') {
17560 // value = x`"" + ${value}`;
17561 // }
17562 if (prop_dependencies.size) {
17563 let condition = block.renderer.dirty(Array.from(prop_dependencies));
17564 if (block.has_outros) {
17565 condition = x `!#current || ${condition}`;
17566 }
17567 const update = b `
17568 if (${condition}) {
17569 @set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});
17570 }`;
17571 block.chunks.update.push(update);
17572 }
17573 }
17574 else {
17575 value = string_literal(prop.value[0].data);
17576 }
17577 block.chunks.hydrate.push(b `@set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});`);
17578 });
17579 }
17580}
17581function optimize_style(value) {
17582 const props = [];
17583 let chunks = value.slice();
17584 while (chunks.length) {
17585 const chunk = chunks[0];
17586 if (chunk.type !== 'Text')
17587 return null;
17588 const key_match = /^\s*([\w-]+):\s*/.exec(chunk.data);
17589 if (!key_match)
17590 return null;
17591 const key = key_match[1];
17592 const offset = key_match.index + key_match[0].length;
17593 const remaining_data = chunk.data.slice(offset);
17594 if (remaining_data) {
17595 chunks[0] = {
17596 start: chunk.start + offset,
17597 end: chunk.end,
17598 type: 'Text',
17599 data: remaining_data
17600 };
17601 }
17602 else {
17603 chunks.shift();
17604 }
17605 const result = get_style_value(chunks);
17606 props.push({ key, value: result.value, important: result.important });
17607 chunks = result.chunks;
17608 }
17609 return props;
17610}
17611function get_style_value(chunks) {
17612 const value = [];
17613 let in_url = false;
17614 let quote_mark = null;
17615 let escaped = false;
17616 let closed = false;
17617 while (chunks.length && !closed) {
17618 const chunk = chunks.shift();
17619 if (chunk.type === 'Text') {
17620 let c = 0;
17621 while (c < chunk.data.length) {
17622 const char = chunk.data[c];
17623 if (escaped) {
17624 escaped = false;
17625 }
17626 else if (char === '\\') {
17627 escaped = true;
17628 }
17629 else if (char === quote_mark) {
17630 quote_mark = null;
17631 }
17632 else if (char === '"' || char === "'") {
17633 quote_mark = char;
17634 }
17635 else if (char === ')' && in_url) {
17636 in_url = false;
17637 }
17638 else if (char === 'u' && chunk.data.slice(c, c + 4) === 'url(') {
17639 in_url = true;
17640 }
17641 else if (char === ';' && !in_url && !quote_mark) {
17642 closed = true;
17643 break;
17644 }
17645 c += 1;
17646 }
17647 if (c > 0) {
17648 value.push({
17649 type: 'Text',
17650 start: chunk.start,
17651 end: chunk.start + c,
17652 data: chunk.data.slice(0, c)
17653 });
17654 }
17655 while (/[;\s]/.test(chunk.data[c]))
17656 c += 1;
17657 const remaining_data = chunk.data.slice(c);
17658 if (remaining_data) {
17659 chunks.unshift({
17660 start: chunk.start + c,
17661 end: chunk.end,
17662 type: 'Text',
17663 data: remaining_data
17664 });
17665 break;
17666 }
17667 }
17668 else {
17669 value.push(chunk);
17670 }
17671 }
17672 let important = false;
17673 const last_chunk = value[value.length - 1];
17674 if (last_chunk && last_chunk.type === 'Text' && /\s*!important\s*$/.test(last_chunk.data)) {
17675 important = true;
17676 last_chunk.data = last_chunk.data.replace(/\s*!important\s*$/, '');
17677 if (!last_chunk.data)
17678 value.pop();
17679 }
17680 return {
17681 chunks,
17682 value,
17683 important
17684 };
17685}
17686function is_dynamic(value) {
17687 return value.length > 1 || value[0].type !== 'Text';
17688}
17689
17690class SpreadAttributeWrapper extends BaseAttributeWrapper {
17691}
17692
17693function replace_object(node, replacement) {
17694 if (node.type === 'Identifier')
17695 return replacement;
17696 const ancestor = node;
17697 let parent;
17698 while (node.type === 'MemberExpression') {
17699 parent = node;
17700 node = node.object;
17701 }
17702 parent.object = replacement;
17703 return ancestor;
17704}
17705
17706function flatten_reference(node) {
17707 const nodes = [];
17708 const parts = [];
17709 while (node.type === 'MemberExpression') {
17710 nodes.unshift(node.property);
17711 if (!node.computed) {
17712 parts.unshift(node.property.name);
17713 }
17714 else {
17715 const computed_property = to_string$1(node.property);
17716 if (computed_property) {
17717 parts.unshift(`[${computed_property}]`);
17718 }
17719 }
17720 node = node.object;
17721 }
17722 const name = node.type === 'Identifier'
17723 ? node.name
17724 : node.type === 'ThisExpression' ? 'this' : null;
17725 nodes.unshift(node);
17726 parts.unshift(name);
17727 return { name, nodes, parts };
17728}
17729function to_string$1(node) {
17730 switch (node.type) {
17731 case 'Literal':
17732 return String(node.value);
17733 case 'Identifier':
17734 return node.name;
17735 }
17736}
17737
17738function mark_each_block_bindings(parent, binding) {
17739 // we need to ensure that the each block creates a context including
17740 // the list and the index, if they're not otherwise referenced
17741 binding.expression.references.forEach(name => {
17742 const each_block = parent.node.scope.get_owner(name);
17743 if (each_block) {
17744 each_block.has_binding = true;
17745 }
17746 });
17747 if (binding.name === 'group') {
17748 const add_index_binding = (name) => {
17749 const each_block = parent.node.scope.get_owner(name);
17750 if (each_block.type === 'EachBlock') {
17751 each_block.has_index_binding = true;
17752 for (const dep of each_block.expression.contextual_dependencies) {
17753 add_index_binding(dep);
17754 }
17755 }
17756 };
17757 // for `<input bind:group={} >`, we make sure that all the each blocks creates context with `index`
17758 for (const name of binding.expression.contextual_dependencies) {
17759 add_index_binding(name);
17760 }
17761 }
17762}
17763
17764class BindingWrapper {
17765 constructor(block, node, parent) {
17766 this.node = node;
17767 this.parent = parent;
17768 const { dependencies } = this.node.expression;
17769 block.add_dependencies(dependencies);
17770 // TODO does this also apply to e.g. `<input type='checkbox' bind:group='foo'>`?
17771 handle_select_value_binding(this, dependencies);
17772 if (node.is_contextual) {
17773 mark_each_block_bindings(this.parent, this.node);
17774 }
17775 this.object = get_object(this.node.expression.node).name;
17776 // view to model
17777 this.handler = get_event_handler(this, parent.renderer, block, this.object, this.node.raw_expression);
17778 this.snippet = this.node.expression.manipulate(block);
17779 this.is_readonly = this.node.is_readonly;
17780 this.needs_lock = this.node.name === 'currentTime'; // TODO others?
17781 }
17782 get_dependencies() {
17783 const dependencies = new Set(this.node.expression.dependencies);
17784 this.node.expression.dependencies.forEach((prop) => {
17785 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17786 if (indirect_dependencies) {
17787 indirect_dependencies.forEach(indirect_dependency => {
17788 dependencies.add(indirect_dependency);
17789 });
17790 }
17791 });
17792 return dependencies;
17793 }
17794 is_readonly_media_attribute() {
17795 return this.node.is_readonly_media_attribute();
17796 }
17797 render(block, lock) {
17798 if (this.is_readonly)
17799 return;
17800 const { parent } = this;
17801 const update_conditions = this.needs_lock ? [x `!${lock}`] : [];
17802 const mount_conditions = [];
17803 const dependency_array = Array.from(this.get_dependencies());
17804 if (dependency_array.length > 0) {
17805 update_conditions.push(block.renderer.dirty(dependency_array));
17806 }
17807 if (parent.node.name === 'input') {
17808 const type = parent.node.get_static_attribute_value('type');
17809 if (type === null ||
17810 type === '' ||
17811 type === 'text' ||
17812 type === 'email' ||
17813 type === 'password') {
17814 update_conditions.push(x `${parent.var}.${this.node.name} !== ${this.snippet}`);
17815 }
17816 else if (type === 'number') {
17817 update_conditions.push(x `@to_number(${parent.var}.${this.node.name}) !== ${this.snippet}`);
17818 }
17819 }
17820 // model to view
17821 let update_dom = get_dom_updater(parent, this);
17822 let mount_dom = update_dom;
17823 // special cases
17824 switch (this.node.name) {
17825 case 'group':
17826 {
17827 const { binding_group, is_context, contexts, index, keypath } = get_binding_group(parent.renderer, this.node, block);
17828 block.renderer.add_to_context('$$binding_groups');
17829 if (is_context && !block.binding_group_initialised.has(keypath)) {
17830 if (contexts.length > 1) {
17831 let binding_group = x `${block.renderer.reference('$$binding_groups')}[${index}]`;
17832 for (const name of contexts.slice(0, -1)) {
17833 binding_group = x `${binding_group}[${block.renderer.reference(name)}]`;
17834 block.chunks.init.push(b `${binding_group} = ${binding_group} || [];`);
17835 }
17836 }
17837 block.chunks.init.push(b `${binding_group(true)} = [];`);
17838 block.binding_group_initialised.add(keypath);
17839 }
17840 block.chunks.hydrate.push(b `${binding_group(true)}.push(${parent.var});`);
17841 block.chunks.destroy.push(b `${binding_group(true)}.splice(${binding_group(true)}.indexOf(${parent.var}), 1);`);
17842 break;
17843 }
17844 case 'textContent':
17845 update_conditions.push(x `${this.snippet} !== ${parent.var}.textContent`);
17846 mount_conditions.push(x `${this.snippet} !== void 0`);
17847 break;
17848 case 'innerHTML':
17849 update_conditions.push(x `${this.snippet} !== ${parent.var}.innerHTML`);
17850 mount_conditions.push(x `${this.snippet} !== void 0`);
17851 break;
17852 case 'currentTime':
17853 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17854 mount_dom = null;
17855 break;
17856 case 'playbackRate':
17857 case 'volume':
17858 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17859 mount_conditions.push(x `!@_isNaN(${this.snippet})`);
17860 break;
17861 case 'paused':
17862 {
17863 // this is necessary to prevent audio restarting by itself
17864 const last = block.get_unique_name(`${parent.var.name}_is_paused`);
17865 block.add_variable(last, x `true`);
17866 update_conditions.push(x `${last} !== (${last} = ${this.snippet})`);
17867 update_dom = b `${parent.var}[${last} ? "pause" : "play"]();`;
17868 mount_dom = null;
17869 break;
17870 }
17871 case 'value':
17872 if (parent.node.get_static_attribute_value('type') === 'file') {
17873 update_dom = null;
17874 mount_dom = null;
17875 }
17876 }
17877 if (update_dom) {
17878 if (update_conditions.length > 0) {
17879 const condition = update_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17880 block.chunks.update.push(b `
17881 if (${condition}) {
17882 ${update_dom}
17883 }
17884 `);
17885 }
17886 else {
17887 block.chunks.update.push(update_dom);
17888 }
17889 }
17890 if (mount_dom) {
17891 if (mount_conditions.length > 0) {
17892 const condition = mount_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17893 block.chunks.mount.push(b `
17894 if (${condition}) {
17895 ${mount_dom}
17896 }
17897 `);
17898 }
17899 else {
17900 block.chunks.mount.push(mount_dom);
17901 }
17902 }
17903 }
17904}
17905function get_dom_updater(element, binding) {
17906 const { node } = element;
17907 if (binding.is_readonly_media_attribute()) {
17908 return null;
17909 }
17910 if (binding.node.name === 'this') {
17911 return null;
17912 }
17913 if (node.name === 'select') {
17914 return node.get_static_attribute_value('multiple') === true ?
17915 b `@select_options(${element.var}, ${binding.snippet})` :
17916 b `@select_option(${element.var}, ${binding.snippet})`;
17917 }
17918 if (binding.node.name === 'group') {
17919 const type = node.get_static_attribute_value('type');
17920 const condition = type === 'checkbox'
17921 ? x `~${binding.snippet}.indexOf(${element.var}.__value)`
17922 : x `${element.var}.__value === ${binding.snippet}`;
17923 return b `${element.var}.checked = ${condition};`;
17924 }
17925 if (binding.node.name === 'value') {
17926 return b `@set_input_value(${element.var}, ${binding.snippet});`;
17927 }
17928 return b `${element.var}.${binding.node.name} = ${binding.snippet};`;
17929}
17930function get_binding_group(renderer, value, block) {
17931 const { parts } = flatten_reference(value.raw_expression);
17932 let keypath = parts.join('.');
17933 const contexts = [];
17934 const contextual_dependencies = new Set();
17935 const { template_scope } = value.expression;
17936 const add_contextual_dependency = (dep) => {
17937 contextual_dependencies.add(dep);
17938 const owner = template_scope.get_owner(dep);
17939 if (owner.type === 'EachBlock') {
17940 for (const dep of owner.expression.contextual_dependencies) {
17941 add_contextual_dependency(dep);
17942 }
17943 }
17944 };
17945 for (const dep of value.expression.contextual_dependencies) {
17946 add_contextual_dependency(dep);
17947 }
17948 for (const dep of contextual_dependencies) {
17949 const context = block.bindings.get(dep);
17950 let key;
17951 let name;
17952 if (context) {
17953 key = context.object.name;
17954 name = context.property.name;
17955 }
17956 else {
17957 key = dep;
17958 name = dep;
17959 }
17960 keypath = `${key}@${keypath}`;
17961 contexts.push(name);
17962 }
17963 if (!renderer.binding_groups.has(keypath)) {
17964 const index = renderer.binding_groups.size;
17965 contexts.forEach(context => {
17966 renderer.add_to_context(context, true);
17967 });
17968 renderer.binding_groups.set(keypath, {
17969 binding_group: (to_reference = false) => {
17970 let binding_group = '$$binding_groups';
17971 let _secondary_indexes = contexts;
17972 if (to_reference) {
17973 binding_group = block.renderer.reference(binding_group);
17974 _secondary_indexes = _secondary_indexes.map(name => block.renderer.reference(name));
17975 }
17976 if (_secondary_indexes.length > 0) {
17977 let obj = x `${binding_group}[${index}]`;
17978 _secondary_indexes.forEach(secondary_index => {
17979 obj = x `${obj}[${secondary_index}]`;
17980 });
17981 return obj;
17982 }
17983 else {
17984 return x `${binding_group}[${index}]`;
17985 }
17986 },
17987 is_context: contexts.length > 0,
17988 contexts,
17989 index,
17990 keypath
17991 });
17992 }
17993 return renderer.binding_groups.get(keypath);
17994}
17995function get_event_handler(binding, renderer, block, name, lhs) {
17996 const contextual_dependencies = new Set(binding.node.expression.contextual_dependencies);
17997 const context = block.bindings.get(name);
17998 let set_store;
17999 if (context) {
18000 const { object, property, store, snippet } = context;
18001 lhs = replace_object(lhs, snippet);
18002 contextual_dependencies.add(object.name);
18003 contextual_dependencies.add(property.name);
18004 contextual_dependencies.delete(name);
18005 if (store) {
18006 set_store = b `${store}.set(${`$${store}`});`;
18007 }
18008 }
18009 else {
18010 const object = get_object(lhs);
18011 if (object.name[0] === '$') {
18012 const store = object.name.slice(1);
18013 set_store = b `${store}.set(${object.name});`;
18014 }
18015 }
18016 const value = get_value_from_dom(renderer, binding.parent, binding, block, contextual_dependencies);
18017 const mutation = b `
18018 ${lhs} = ${value};
18019 ${set_store}
18020 `;
18021 return {
18022 uses_context: binding.node.is_contextual || binding.node.expression.uses_context,
18023 mutation,
18024 contextual_dependencies,
18025 lhs
18026 };
18027}
18028function get_value_from_dom(renderer, element, binding, block, contextual_dependencies) {
18029 const { node } = element;
18030 const { name } = binding.node;
18031 if (name === 'this') {
18032 return x `$$value`;
18033 }
18034 // <select bind:value='selected>
18035 if (node.name === 'select') {
18036 return node.get_static_attribute_value('multiple') === true ?
18037 x `@select_multiple_value(this)` :
18038 x `@select_value(this)`;
18039 }
18040 const type = node.get_static_attribute_value('type');
18041 // <input type='checkbox' bind:group='foo'>
18042 if (name === 'group') {
18043 if (type === 'checkbox') {
18044 const { binding_group, contexts } = get_binding_group(renderer, binding.node, block);
18045 add_to_set(contextual_dependencies, contexts);
18046 return x `@get_binding_group_value(${binding_group()}, this.__value, this.checked)`;
18047 }
18048 return x `this.__value`;
18049 }
18050 // <input type='range|number' bind:value>
18051 if (type === 'range' || type === 'number') {
18052 return x `@to_number(this.${name})`;
18053 }
18054 if ((name === 'buffered' || name === 'seekable' || name === 'played')) {
18055 return x `@time_ranges_to_array(this.${name})`;
18056 }
18057 // everything else
18058 return x `this.${name}`;
18059}
18060
18061const reserved_keywords = new Set(['$$props', '$$restProps', '$$slots']);
18062function is_reserved_keyword(name) {
18063 return reserved_keywords.has(name);
18064}
18065
18066function is_contextual(component, scope, name) {
18067 if (is_reserved_keyword(name))
18068 return true;
18069 // if it's a name below root scope, it's contextual
18070 if (!scope.is_top_level(name))
18071 return true;
18072 const variable = component.var_lookup.get(name);
18073 // hoistables, module declarations, and imports are non-contextual
18074 if (!variable || variable.hoistable)
18075 return false;
18076 // assume contextual
18077 return true;
18078}
18079
18080function add_actions(block, target, actions) {
18081 actions.forEach(action => add_action(block, target, action));
18082}
18083function add_action(block, target, action) {
18084 const { expression, template_scope } = action;
18085 let snippet;
18086 let dependencies;
18087 if (expression) {
18088 snippet = expression.manipulate(block);
18089 dependencies = expression.dynamic_dependencies();
18090 }
18091 const id = block.get_unique_name(`${action.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action`);
18092 block.add_variable(id);
18093 const [obj, ...properties] = action.name.split('.');
18094 const fn = is_contextual(action.component, template_scope, obj)
18095 ? block.renderer.reference(obj)
18096 : obj;
18097 if (properties.length) {
18098 const member_expression = properties.reduce((lhs, rhs) => x `${lhs}.${rhs}`, fn);
18099 block.event_listeners.push(x `@action_destroyer(${id} = ${member_expression}(${target}, ${snippet}))`);
18100 }
18101 else {
18102 block.event_listeners.push(x `@action_destroyer(${id} = ${fn}.call(null, ${target}, ${snippet}))`);
18103 }
18104 if (dependencies && dependencies.length > 0) {
18105 let condition = x `${id} && @is_function(${id}.update)`;
18106 if (dependencies.length > 0) {
18107 condition = x `${condition} && ${block.renderer.dirty(dependencies)}`;
18108 }
18109 block.chunks.update.push(b `if (${condition}) ${id}.update.call(null, ${snippet});`);
18110 }
18111}
18112
18113function compare_node(a, b) {
18114 if (a === b)
18115 return true;
18116 if (!a || !b)
18117 return false;
18118 if (a.type !== b.type)
18119 return false;
18120 switch (a.type) {
18121 case 'Identifier':
18122 return a.name === b.name;
18123 case 'MemberExpression':
18124 return (compare_node(a.object, b.object) &&
18125 compare_node(a.property, b.property) &&
18126 a.computed === b.computed);
18127 case 'Literal':
18128 return a.value === b.value;
18129 }
18130}
18131
18132function bind_this(component, block, binding, variable) {
18133 const fn = component.get_unique_name(`${variable.name}_binding`);
18134 block.renderer.add_to_context(fn.name);
18135 const callee = block.renderer.reference(fn.name);
18136 const { contextual_dependencies, mutation } = binding.handler;
18137 const dependencies = binding.get_dependencies();
18138 const body = b `
18139 ${mutation}
18140 ${Array.from(dependencies)
18141 .filter(dep => dep[0] !== '$')
18142 .filter(dep => !contextual_dependencies.has(dep))
18143 .map(dep => b `${block.renderer.invalidate(dep)};`)}
18144 `;
18145 if (contextual_dependencies.size) {
18146 const params = Array.from(contextual_dependencies).map(name => ({
18147 type: 'Identifier',
18148 name
18149 }));
18150 component.partly_hoisted.push(b `
18151 function ${fn}($$value, ${params}) {
18152 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
18153 ${body}
18154 });
18155 }
18156 `);
18157 const alias_map = new Map();
18158 const args = [];
18159 for (let id of params) {
18160 const value = block.renderer.reference(id.name);
18161 let found = false;
18162 if (block.variables.has(id.name)) {
18163 let alias = id.name;
18164 for (let i = 1; block.variables.has(alias) && !compare_node(block.variables.get(alias).init, value); alias = `${id.name}_${i++}`)
18165 ;
18166 alias_map.set(alias, id.name);
18167 id = { type: 'Identifier', name: alias };
18168 found = block.variables.has(alias);
18169 }
18170 args.push(id);
18171 if (!found) {
18172 block.add_variable(id, value);
18173 }
18174 }
18175 const assign = block.get_unique_name(`assign_${variable.name}`);
18176 const unassign = block.get_unique_name(`unassign_${variable.name}`);
18177 block.chunks.init.push(b `
18178 const ${assign} = () => ${callee}(${variable}, ${args});
18179 const ${unassign} = () => ${callee}(null, ${args});
18180 `);
18181 const condition = Array.from(args)
18182 .map(name => x `${name} !== ${block.renderer.reference(alias_map.get(name.name) || name.name)}`)
18183 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
18184 // we push unassign and unshift assign so that references are
18185 // nulled out before they're created, to avoid glitches
18186 // with shifting indices
18187 block.chunks.update.push(b `
18188 if (${condition}) {
18189 ${unassign}();
18190 ${args.map(a => b `${a} = ${block.renderer.reference(alias_map.get(a.name) || a.name)}`)};
18191 ${assign}();
18192 }`);
18193 block.chunks.destroy.push(b `${unassign}();`);
18194 return b `${assign}();`;
18195 }
18196 component.partly_hoisted.push(b `
18197 function ${fn}($$value) {
18198 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
18199 ${body}
18200 });
18201 }
18202 `);
18203 block.chunks.destroy.push(b `${callee}(null);`);
18204 return b `${callee}(${variable});`;
18205}
18206
18207class Node$1 {
18208 constructor(component, parent, _scope, info) {
18209 this.start = info.start;
18210 this.end = info.end;
18211 this.type = info.type;
18212 // this makes properties non-enumerable, which makes logging
18213 // bearable. might have a performance cost. TODO remove in prod?
18214 Object.defineProperties(this, {
18215 component: {
18216 value: component
18217 },
18218 parent: {
18219 value: parent
18220 }
18221 });
18222 }
18223 cannot_use_innerhtml() {
18224 if (this.can_use_innerhtml !== false) {
18225 this.can_use_innerhtml = false;
18226 if (this.parent)
18227 this.parent.cannot_use_innerhtml();
18228 }
18229 }
18230 find_nearest(selector) {
18231 if (selector.test(this.type))
18232 return this;
18233 if (this.parent)
18234 return this.parent.find_nearest(selector);
18235 }
18236 get_static_attribute_value(name) {
18237 const attribute = this.attributes && this.attributes.find((attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === name);
18238 if (!attribute)
18239 return null;
18240 if (attribute.is_true)
18241 return true;
18242 if (attribute.chunks.length === 0)
18243 return '';
18244 if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
18245 return attribute.chunks[0].data;
18246 }
18247 return null;
18248 }
18249 has_ancestor(type) {
18250 return this.parent ?
18251 this.parent.type === type || this.parent.has_ancestor(type) :
18252 false;
18253 }
18254}
18255
18256function create_scopes(expression) {
18257 return analyze(expression);
18258}
18259
18260function is_dynamic$1(variable) {
18261 if (variable) {
18262 if (variable.mutated || variable.reassigned)
18263 return true; // dynamic internal state
18264 if (!variable.module && variable.writable && variable.export_name)
18265 return true; // writable props
18266 if (is_reserved_keyword(variable.name))
18267 return true;
18268 }
18269 return false;
18270}
18271
18272function nodes_match(a, b) {
18273 if (!!a !== !!b)
18274 return false;
18275 if (Array.isArray(a) !== Array.isArray(b))
18276 return false;
18277 if (a && typeof a === 'object') {
18278 if (Array.isArray(a)) {
18279 if (a.length !== b.length)
18280 return false;
18281 return a.every((child, i) => nodes_match(child, b[i]));
18282 }
18283 const a_keys = Object.keys(a).sort();
18284 const b_keys = Object.keys(b).sort();
18285 if (a_keys.length !== b_keys.length)
18286 return false;
18287 let i = a_keys.length;
18288 while (i--) {
18289 const key = a_keys[i];
18290 if (b_keys[i] !== key)
18291 return false;
18292 if (key === 'start' || key === 'end')
18293 continue;
18294 if (!nodes_match(a[key], b[key])) {
18295 return false;
18296 }
18297 }
18298 return true;
18299 }
18300 return a === b;
18301}
18302
18303function invalidate(renderer, scope, node, names, main_execution_context = false) {
18304 const { component } = renderer;
18305 const [head, ...tail] = Array.from(names)
18306 .filter(name => {
18307 const owner = scope.find_owner(name);
18308 return !owner || owner === component.instance_scope;
18309 })
18310 .map(name => component.var_lookup.get(name))
18311 .filter(variable => {
18312 return variable && (!variable.hoistable &&
18313 !variable.global &&
18314 !variable.module &&
18315 (variable.referenced ||
18316 variable.subscribable ||
18317 variable.is_reactive_dependency ||
18318 variable.export_name ||
18319 variable.name[0] === '$'));
18320 });
18321 function get_invalidated(variable, node) {
18322 if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') {
18323 return node;
18324 }
18325 return renderer_invalidate(renderer, variable.name, undefined, main_execution_context);
18326 }
18327 if (!head) {
18328 return node;
18329 }
18330 component.has_reactive_assignments = true;
18331 if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) {
18332 return get_invalidated(head, node);
18333 }
18334 const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
18335 const extra_args = tail.map(variable => get_invalidated(variable)).filter(Boolean);
18336 if (is_store_value) {
18337 return x `@set_store_value(${head.name.slice(1)}, ${node}, ${head.name}, ${extra_args})`;
18338 }
18339 let invalidate;
18340 if (!main_execution_context) {
18341 const pass_value = (extra_args.length > 0 ||
18342 (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
18343 (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier')));
18344 if (pass_value) {
18345 extra_args.unshift({
18346 type: 'Identifier',
18347 name: head.name
18348 });
18349 }
18350 invalidate = x `$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`;
18351 }
18352 else {
18353 // skip `$$invalidate` if it is in the main execution context
18354 invalidate = extra_args.length ? [node, ...extra_args] : node;
18355 }
18356 if (head.subscribable && head.reassigned) {
18357 const subscribe = `$$subscribe_${head.name}`;
18358 invalidate = x `${subscribe}(${invalidate})`;
18359 }
18360 return invalidate;
18361}
18362function renderer_invalidate(renderer, name, value, main_execution_context = false) {
18363 const variable = renderer.component.var_lookup.get(name);
18364 if (variable && (variable.subscribable && (variable.reassigned || variable.export_name))) {
18365 if (main_execution_context) {
18366 return x `${`$$subscribe_${name}`}(${value || name})`;
18367 }
18368 else {
18369 const member = renderer.context_lookup.get(name);
18370 return x `${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
18371 }
18372 }
18373 if (name[0] === '$' && name[1] !== '$') {
18374 return x `${name.slice(1)}.set(${value || name})`;
18375 }
18376 if (variable && (variable.module || (!variable.referenced &&
18377 !variable.is_reactive_dependency &&
18378 !variable.export_name &&
18379 !name.startsWith('$$')))) {
18380 return value || name;
18381 }
18382 if (value) {
18383 if (main_execution_context) {
18384 return x `${value}`;
18385 }
18386 else {
18387 const member = renderer.context_lookup.get(name);
18388 return x `$$invalidate(${member.index}, ${value})`;
18389 }
18390 }
18391 if (main_execution_context)
18392 return;
18393 // if this is a reactive declaration, invalidate dependencies recursively
18394 const deps = new Set([name]);
18395 deps.forEach(name => {
18396 const reactive_declarations = renderer.component.reactive_declarations.filter(x => x.assignees.has(name));
18397 reactive_declarations.forEach(declaration => {
18398 declaration.dependencies.forEach(name => {
18399 deps.add(name);
18400 });
18401 });
18402 });
18403 // TODO ideally globals etc wouldn't be here in the first place
18404 const filtered = Array.from(deps).filter(n => renderer.context_lookup.has(n));
18405 if (!filtered.length)
18406 return null;
18407 return filtered
18408 .map(n => x `$$invalidate(${renderer.context_lookup.get(n).index}, ${n})`)
18409 .reduce((lhs, rhs) => x `${lhs}, ${rhs}`);
18410}
18411
18412class Expression {
18413 constructor(component, owner, template_scope, info, lazy) {
18414 this.type = 'Expression';
18415 this.references = new Set();
18416 this.dependencies = new Set();
18417 this.contextual_dependencies = new Set();
18418 this.declarations = [];
18419 this.uses_context = false;
18420 // TODO revert to direct property access in prod?
18421 Object.defineProperties(this, {
18422 component: {
18423 value: component
18424 }
18425 });
18426 this.node = info;
18427 this.template_scope = template_scope;
18428 this.owner = owner;
18429 const { dependencies, contextual_dependencies, references } = this;
18430 let { map, scope } = create_scopes(info);
18431 this.scope = scope;
18432 this.scope_map = map;
18433 const expression = this;
18434 let function_expression;
18435 // discover dependencies, but don't change the code yet
18436 walk(info, {
18437 enter(node, parent, key) {
18438 // don't manipulate shorthand props twice
18439 if (key === 'value' && parent.shorthand)
18440 return;
18441 // don't manipulate `import.meta`, `new.target`
18442 if (node.type === 'MetaProperty')
18443 return this.skip();
18444 if (map.has(node)) {
18445 scope = map.get(node);
18446 }
18447 if (!function_expression && /FunctionExpression/.test(node.type)) {
18448 function_expression = node;
18449 }
18450 if (isReference(node, parent)) {
18451 const { name, nodes } = flatten_reference(node);
18452 references.add(name);
18453 if (scope.has(name))
18454 return;
18455 if (name[0] === '$') {
18456 const store_name = name.slice(1);
18457 if (template_scope.names.has(store_name) || scope.has(store_name)) {
18458 component.error(node, {
18459 code: 'contextual-store',
18460 message: 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
18461 });
18462 }
18463 }
18464 if (template_scope.is_let(name)) {
18465 if (!function_expression) { // TODO should this be `!lazy` ?
18466 contextual_dependencies.add(name);
18467 dependencies.add(name);
18468 }
18469 }
18470 else if (template_scope.names.has(name)) {
18471 expression.uses_context = true;
18472 contextual_dependencies.add(name);
18473 const owner = template_scope.get_owner(name);
18474 const is_index = owner.type === 'EachBlock' && owner.key && name === owner.index;
18475 if (!lazy || is_index) {
18476 template_scope.dependencies_for_name.get(name).forEach(name => dependencies.add(name));
18477 }
18478 }
18479 else {
18480 if (!lazy) {
18481 dependencies.add(name);
18482 }
18483 component.add_reference(name);
18484 component.warn_if_undefined(name, nodes[0], template_scope);
18485 }
18486 this.skip();
18487 }
18488 // track any assignments from template expressions as mutable
18489 let names;
18490 let deep = false;
18491 if (function_expression) {
18492 if (node.type === 'AssignmentExpression') {
18493 deep = node.left.type === 'MemberExpression';
18494 names = extract_names(deep ? get_object(node.left) : node.left);
18495 }
18496 else if (node.type === 'UpdateExpression') {
18497 names = extract_names(get_object(node.argument));
18498 }
18499 }
18500 if (names) {
18501 names.forEach(name => {
18502 if (template_scope.names.has(name)) {
18503 template_scope.dependencies_for_name.get(name).forEach(name => {
18504 const variable = component.var_lookup.get(name);
18505 if (variable)
18506 variable[deep ? 'mutated' : 'reassigned'] = true;
18507 });
18508 const each_block = template_scope.get_owner(name);
18509 each_block.has_binding = true;
18510 }
18511 else {
18512 component.add_reference(name);
18513 const variable = component.var_lookup.get(name);
18514 if (variable)
18515 variable[deep ? 'mutated' : 'reassigned'] = true;
18516 }
18517 });
18518 }
18519 },
18520 leave(node) {
18521 if (map.has(node)) {
18522 scope = scope.parent;
18523 }
18524 if (node === function_expression) {
18525 function_expression = null;
18526 }
18527 }
18528 });
18529 }
18530 dynamic_dependencies() {
18531 return Array.from(this.dependencies).filter(name => {
18532 if (this.template_scope.is_let(name))
18533 return true;
18534 if (is_reserved_keyword(name))
18535 return true;
18536 const variable = this.component.var_lookup.get(name);
18537 return is_dynamic$1(variable);
18538 });
18539 }
18540 // TODO move this into a render-dom wrapper?
18541 manipulate(block) {
18542 // TODO ideally we wouldn't end up calling this method
18543 // multiple times
18544 if (this.manipulated)
18545 return this.manipulated;
18546 const { component, declarations, scope_map: map, template_scope, owner } = this;
18547 let scope = this.scope;
18548 let function_expression;
18549 let dependencies;
18550 let contextual_dependencies;
18551 const node = walk(this.node, {
18552 enter(node, parent) {
18553 if (node.type === 'Property' && node.shorthand) {
18554 node.value = JSON.parse(JSON.stringify(node.value));
18555 node.shorthand = false;
18556 }
18557 if (map.has(node)) {
18558 scope = map.get(node);
18559 }
18560 if (node.type === 'Identifier' && isReference(node, parent)) {
18561 const { name } = flatten_reference(node);
18562 if (scope.has(name))
18563 return;
18564 if (function_expression) {
18565 if (template_scope.names.has(name)) {
18566 contextual_dependencies.add(name);
18567 template_scope.dependencies_for_name.get(name).forEach(dependency => {
18568 dependencies.add(dependency);
18569 });
18570 }
18571 else {
18572 dependencies.add(name);
18573 component.add_reference(name); // TODO is this redundant/misplaced?
18574 }
18575 }
18576 else if (is_contextual(component, template_scope, name)) {
18577 const reference = block.renderer.reference(node);
18578 this.replace(reference);
18579 }
18580 this.skip();
18581 }
18582 if (!function_expression) {
18583 if (node.type === 'AssignmentExpression') ;
18584 if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
18585 function_expression = node;
18586 dependencies = new Set();
18587 contextual_dependencies = new Set();
18588 }
18589 }
18590 },
18591 leave(node, parent) {
18592 if (map.has(node))
18593 scope = scope.parent;
18594 if (node === function_expression) {
18595 const id = component.get_unique_name(sanitize(get_function_name(node, owner)));
18596 const declaration = b `const ${id} = ${node}`;
18597 if (dependencies.size === 0 && contextual_dependencies.size === 0) {
18598 // we can hoist this out of the component completely
18599 component.fully_hoisted.push(declaration);
18600 this.replace(id);
18601 component.add_var({
18602 name: id.name,
18603 internal: true,
18604 hoistable: true,
18605 referenced: true
18606 });
18607 }
18608 else if (contextual_dependencies.size === 0) {
18609 // function can be hoisted inside the component init
18610 component.partly_hoisted.push(declaration);
18611 block.renderer.add_to_context(id.name);
18612 this.replace(block.renderer.reference(id));
18613 }
18614 else {
18615 // we need a combo block/init recipe
18616 const deps = Array.from(contextual_dependencies);
18617 const function_expression = node;
18618 const has_args = function_expression.params.length > 0;
18619 function_expression.params = [
18620 ...deps.map(name => ({ type: 'Identifier', name })),
18621 ...function_expression.params
18622 ];
18623 const context_args = deps.map(name => block.renderer.reference(name));
18624 component.partly_hoisted.push(declaration);
18625 block.renderer.add_to_context(id.name);
18626 const callee = block.renderer.reference(id);
18627 this.replace(id);
18628 const func_declaration = has_args
18629 ? b `function ${id}(...args) {
18630 return ${callee}(${context_args}, ...args);
18631 }`
18632 : b `function ${id}() {
18633 return ${callee}(${context_args});
18634 }`;
18635 if (owner.type === 'Attribute' && owner.parent.name === 'slot') {
18636 const dep_scopes = new Set(deps.map(name => template_scope.get_owner(name)));
18637 // find the nearest scopes
18638 let node = owner.parent;
18639 while (node && !dep_scopes.has(node)) {
18640 node = node.parent;
18641 }
18642 const func_expression = func_declaration[0];
18643 if (node.type === 'InlineComponent') {
18644 // <Comp let:data />
18645 this.replace(func_expression);
18646 }
18647 else {
18648 // {#each}, {#await}
18649 const func_id = component.get_unique_name(id.name + '_func');
18650 block.renderer.add_to_context(func_id.name, true);
18651 // rename #ctx -> child_ctx;
18652 walk(func_expression, {
18653 enter(node) {
18654 if (node.type === 'Identifier' && node.name === '#ctx') {
18655 node.name = 'child_ctx';
18656 }
18657 }
18658 });
18659 // add to get_xxx_context
18660 // child_ctx[x] = function () { ... }
18661 template_scope.get_owner(deps[0]).contexts.push({
18662 key: func_id,
18663 modifier: () => func_expression
18664 });
18665 this.replace(block.renderer.reference(func_id));
18666 }
18667 }
18668 else {
18669 declarations.push(func_declaration);
18670 }
18671 }
18672 function_expression = null;
18673 dependencies = null;
18674 contextual_dependencies = null;
18675 if (parent && parent.type === 'Property') {
18676 parent.method = false;
18677 }
18678 }
18679 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
18680 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
18681 const object_name = get_object(assignee).name;
18682 if (scope.has(object_name))
18683 return;
18684 // normally (`a = 1`, `b.c = 2`), there'll be a single name
18685 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
18686 // may be more, in which case we need to tack the extra ones
18687 // onto the initial function call
18688 const names = new Set(extract_names(assignee));
18689 const traced = new Set();
18690 names.forEach(name => {
18691 const dependencies = template_scope.dependencies_for_name.get(name);
18692 if (dependencies) {
18693 dependencies.forEach(name => traced.add(name));
18694 }
18695 else {
18696 traced.add(name);
18697 }
18698 });
18699 const context = block.bindings.get(object_name);
18700 if (context) {
18701 // for `{#each array as item}`
18702 // replace `item = 1` to `each_array[each_index] = 1`, this allow us to mutate the array
18703 // rather than mutating the local `item` variable
18704 const { snippet, object, property } = context;
18705 const replaced = replace_object(assignee, snippet);
18706 if (node.type === 'AssignmentExpression') {
18707 node.left = replaced;
18708 }
18709 else {
18710 node.argument = replaced;
18711 }
18712 contextual_dependencies.add(object.name);
18713 contextual_dependencies.add(property.name);
18714 }
18715 this.replace(invalidate(block.renderer, scope, node, traced));
18716 }
18717 }
18718 });
18719 if (declarations.length > 0) {
18720 block.maintain_context = true;
18721 declarations.forEach(declaration => {
18722 block.chunks.init.push(declaration);
18723 });
18724 }
18725 return (this.manipulated = node);
18726 }
18727}
18728function get_function_name(_node, parent) {
18729 if (parent.type === 'EventHandler') {
18730 return `${parent.name}_handler`;
18731 }
18732 if (parent.type === 'Action') {
18733 return `${parent.name}_function`;
18734 }
18735 return 'func';
18736}
18737
18738class Action extends Node$1 {
18739 constructor(component, parent, scope, info) {
18740 super(component, parent, scope, info);
18741 const object = info.name.split('.')[0];
18742 component.warn_if_undefined(object, info, scope);
18743 this.name = info.name;
18744 component.add_reference(object);
18745 this.expression = info.expression
18746 ? new Expression(component, this, scope, info.expression)
18747 : null;
18748 this.template_scope = scope;
18749 this.uses_context = this.expression && this.expression.uses_context;
18750 }
18751}
18752
18753class Tag extends Wrapper {
18754 constructor(renderer, block, parent, node) {
18755 super(renderer, block, parent, node);
18756 this.cannot_use_innerhtml();
18757 if (!this.is_dependencies_static()) {
18758 this.not_static_content();
18759 }
18760 block.add_dependencies(node.expression.dependencies);
18761 }
18762 is_dependencies_static() {
18763 return this.node.expression.contextual_dependencies.size === 0 && this.node.expression.dynamic_dependencies().length === 0;
18764 }
18765 rename_this_method(block, update) {
18766 const dependencies = this.node.expression.dynamic_dependencies();
18767 let snippet = this.node.expression.manipulate(block);
18768 const value = this.node.should_cache && block.get_unique_name(`${this.var.name}_value`);
18769 const content = this.node.should_cache ? value : snippet;
18770 snippet = x `${snippet} + ""`;
18771 if (this.node.should_cache)
18772 block.add_variable(value, snippet); // TODO may need to coerce snippet to string
18773 if (dependencies.length > 0) {
18774 let condition = block.renderer.dirty(dependencies);
18775 if (block.has_outros) {
18776 condition = x `!#current || ${condition}`;
18777 }
18778 const update_cached_value = x `${value} !== (${value} = ${snippet})`;
18779 if (this.node.should_cache) {
18780 condition = x `${condition} && ${update_cached_value}`;
18781 }
18782 block.chunks.update.push(b `if (${condition}) ${update(content)}`);
18783 }
18784 return { init: content };
18785 }
18786}
18787
18788class MustacheTagWrapper extends Tag {
18789 constructor(renderer, block, parent, node) {
18790 super(renderer, block, parent, node);
18791 this.var = { type: 'Identifier', name: 't' };
18792 }
18793 render(block, parent_node, parent_nodes) {
18794 const { init } = this.rename_this_method(block, value => x `@set_data(${this.var}, ${value})`);
18795 block.add_element(this.var, x `@text(${init})`, parent_nodes && x `@claim_text(${parent_nodes}, ${init})`, parent_node);
18796 }
18797}
18798
18799class RawMustacheTagWrapper extends Tag {
18800 constructor(renderer, block, parent, node) {
18801 super(renderer, block, parent, node);
18802 this.var = { type: 'Identifier', name: 'raw' };
18803 this.cannot_use_innerhtml();
18804 this.not_static_content();
18805 }
18806 render(block, parent_node, _parent_nodes) {
18807 const in_head = is_head(parent_node);
18808 const can_use_innerhtml = !in_head && parent_node && !this.prev && !this.next;
18809 if (can_use_innerhtml) {
18810 const insert = content => b `${parent_node}.innerHTML = ${content};`[0];
18811 const { init } = this.rename_this_method(block, content => insert(content));
18812 block.chunks.mount.push(insert(init));
18813 }
18814 else {
18815 const needs_anchor = in_head || (this.next ? !this.next.is_dom_node() : (!this.parent || !this.parent.is_dom_node()));
18816 const html_tag = block.get_unique_name('html_tag');
18817 const html_anchor = needs_anchor && block.get_unique_name('html_anchor');
18818 block.add_variable(html_tag);
18819 const { init } = this.rename_this_method(block, content => x `${html_tag}.p(${content})`);
18820 const update_anchor = needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
18821 block.chunks.hydrate.push(b `${html_tag} = new @HtmlTag(${update_anchor});`);
18822 block.chunks.mount.push(b `${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`);
18823 if (needs_anchor) {
18824 block.add_element(html_anchor, x `@empty()`, x `@empty()`, parent_node);
18825 }
18826 if (!parent_node || in_head) {
18827 block.chunks.destroy.push(b `if (detaching) ${html_tag}.d();`);
18828 }
18829 }
18830 }
18831}
18832
18833function get_slot_definition(block, scope, lets) {
18834 if (lets.length === 0)
18835 return { block, scope };
18836 const context_input = {
18837 type: 'ObjectPattern',
18838 properties: lets.map(l => ({
18839 type: 'Property',
18840 kind: 'init',
18841 key: l.name,
18842 value: l.value || l.name
18843 }))
18844 };
18845 const properties = [];
18846 const value_map = new Map();
18847 lets.forEach(l => {
18848 let value;
18849 if (l.names.length > 1) {
18850 // more than one, probably destructuring
18851 const unique_name = block.get_unique_name(l.names.join('_')).name;
18852 value_map.set(l.value, unique_name);
18853 value = { type: 'Identifier', name: unique_name };
18854 }
18855 else {
18856 value = l.value || l.name;
18857 }
18858 properties.push({
18859 type: 'Property',
18860 kind: 'init',
18861 key: l.name,
18862 value
18863 });
18864 });
18865 const changes_input = {
18866 type: 'ObjectPattern',
18867 properties
18868 };
18869 const names = new Set();
18870 const names_lookup = new Map();
18871 lets.forEach(l => {
18872 l.names.forEach(name => {
18873 names.add(name);
18874 if (value_map.has(l.value)) {
18875 names_lookup.set(name, value_map.get(l.value));
18876 }
18877 });
18878 });
18879 const context = {
18880 type: 'ObjectExpression',
18881 properties: Array.from(names).map(name => p `${block.renderer.context_lookup.get(name).index}: ${name}`)
18882 };
18883 const { context_lookup } = block.renderer;
18884 // i am well aware that this code is gross
18885 // TODO: context-overflow make it less gross
18886 const changes = {
18887 type: 'ParenthesizedExpression',
18888 get expression() {
18889 if (block.renderer.context_overflow) {
18890 const grouped = [];
18891 Array.from(names).forEach(name => {
18892 const i = context_lookup.get(name).index.value;
18893 const g = Math.floor(i / 31);
18894 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
18895 if (!grouped[g])
18896 grouped[g] = [];
18897 grouped[g].push({ name: lookup_name, n: i % 31 });
18898 });
18899 const elements = [];
18900 for (let g = 0; g < grouped.length; g += 1) {
18901 elements[g] = grouped[g]
18902 ? grouped[g]
18903 .map(({ name, n }) => x `${name} ? ${1 << n} : 0`)
18904 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`)
18905 : x `0`;
18906 }
18907 return {
18908 type: 'ArrayExpression',
18909 elements
18910 };
18911 }
18912 return Array.from(names)
18913 .map(name => {
18914 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
18915 const i = context_lookup.get(name).index.value;
18916 return x `${lookup_name} ? ${1 << i} : 0`;
18917 })
18918 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
18919 }
18920 };
18921 return {
18922 block,
18923 scope,
18924 get_context: x `${context_input} => ${context}`,
18925 get_changes: x `${changes_input} => ${changes}`
18926 };
18927}
18928
18929function create_slot_block(attribute, element, block) {
18930 const owner = find_slot_owner(element.parent);
18931 if (owner && owner.node.type === 'InlineComponent') {
18932 const name = attribute.get_static_value();
18933 if (!owner.slots.has(name)) {
18934 const child_block = block.child({
18935 comment: create_debugging_comment(element.node, element.renderer.component),
18936 name: element.renderer.component.get_unique_name(`create_${sanitize(name)}_slot`),
18937 type: 'slot'
18938 });
18939 const { scope, lets } = element.node;
18940 const seen = new Set(lets.map(l => l.name.name));
18941 owner.node.lets.forEach(l => {
18942 if (!seen.has(l.name.name))
18943 lets.push(l);
18944 });
18945 owner.slots.set(name, get_slot_definition(child_block, scope, lets));
18946 element.renderer.blocks.push(child_block);
18947 }
18948 element.slot_block = owner.slots.get(name).block;
18949 return element.slot_block;
18950 }
18951 return block;
18952}
18953function find_slot_owner(owner) {
18954 while (owner) {
18955 if (owner.node.type === 'InlineComponent') {
18956 break;
18957 }
18958 if (owner.node.type === 'Element' && /-/.test(owner.node.name)) {
18959 break;
18960 }
18961 owner = owner.parent;
18962 }
18963 return owner;
18964}
18965
18966const events = [
18967 {
18968 event_names: ['input'],
18969 filter: (node, _name) => node.name === 'textarea' ||
18970 node.name === 'input' && !/radio|checkbox|range|file/.test(node.get_static_attribute_value('type'))
18971 },
18972 {
18973 event_names: ['input'],
18974 filter: (node, name) => (name === 'textContent' || name === 'innerHTML') &&
18975 node.attributes.some(attribute => attribute.name === 'contenteditable')
18976 },
18977 {
18978 event_names: ['change'],
18979 filter: (node, _name) => node.name === 'select' ||
18980 node.name === 'input' && /radio|checkbox|file/.test(node.get_static_attribute_value('type'))
18981 },
18982 {
18983 event_names: ['change', 'input'],
18984 filter: (node, _name) => node.name === 'input' && node.get_static_attribute_value('type') === 'range'
18985 },
18986 {
18987 event_names: ['elementresize'],
18988 filter: (_node, name) => dimensions.test(name)
18989 },
18990 // media events
18991 {
18992 event_names: ['timeupdate'],
18993 filter: (node, name) => node.is_media_node() &&
18994 (name === 'currentTime' || name === 'played' || name === 'ended')
18995 },
18996 {
18997 event_names: ['durationchange'],
18998 filter: (node, name) => node.is_media_node() &&
18999 name === 'duration'
19000 },
19001 {
19002 event_names: ['play', 'pause'],
19003 filter: (node, name) => node.is_media_node() &&
19004 name === 'paused'
19005 },
19006 {
19007 event_names: ['progress'],
19008 filter: (node, name) => node.is_media_node() &&
19009 name === 'buffered'
19010 },
19011 {
19012 event_names: ['loadedmetadata'],
19013 filter: (node, name) => node.is_media_node() &&
19014 (name === 'buffered' || name === 'seekable')
19015 },
19016 {
19017 event_names: ['volumechange'],
19018 filter: (node, name) => node.is_media_node() &&
19019 (name === 'volume' || name === 'muted')
19020 },
19021 {
19022 event_names: ['ratechange'],
19023 filter: (node, name) => node.is_media_node() &&
19024 name === 'playbackRate'
19025 },
19026 {
19027 event_names: ['seeking', 'seeked'],
19028 filter: (node, name) => node.is_media_node() &&
19029 (name === 'seeking')
19030 },
19031 {
19032 event_names: ['ended'],
19033 filter: (node, name) => node.is_media_node() &&
19034 name === 'ended'
19035 },
19036 {
19037 event_names: ['resize'],
19038 filter: (node, name) => node.is_media_node() &&
19039 (name === 'videoHeight' || name === 'videoWidth')
19040 },
19041 // details event
19042 {
19043 event_names: ['toggle'],
19044 filter: (node, _name) => node.name === 'details'
19045 }
19046];
19047class ElementWrapper extends Wrapper {
19048 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19049 super(renderer, block, parent, node);
19050 this.var = {
19051 type: 'Identifier',
19052 name: node.name.replace(/[^a-zA-Z0-9_$]/g, '_')
19053 };
19054 this.void = is_void(node.name);
19055 this.class_dependencies = [];
19056 if (this.node.children.length) {
19057 this.node.lets.forEach(l => {
19058 extract_names(l.value || l.name).forEach(name => {
19059 renderer.add_to_context(name, true);
19060 });
19061 });
19062 }
19063 this.attributes = this.node.attributes.map(attribute => {
19064 if (attribute.name === 'slot') {
19065 block = create_slot_block(attribute, this, block);
19066 }
19067 if (attribute.name === 'style') {
19068 return new StyleAttributeWrapper(this, block, attribute);
19069 }
19070 if (attribute.type === 'Spread') {
19071 return new SpreadAttributeWrapper(this, block, attribute);
19072 }
19073 return new AttributeWrapper(this, block, attribute);
19074 });
19075 // ordinarily, there'll only be one... but we need to handle
19076 // the rare case where an element can have multiple bindings,
19077 // e.g. <audio bind:paused bind:currentTime>
19078 this.bindings = this.node.bindings.map(binding => new BindingWrapper(block, binding, this));
19079 this.event_handlers = this.node.handlers.map(event_handler => new EventHandlerWrapper(event_handler, this));
19080 if (node.intro || node.outro) {
19081 if (node.intro)
19082 block.add_intro(node.intro.is_local);
19083 if (node.outro)
19084 block.add_outro(node.outro.is_local);
19085 }
19086 if (node.animation) {
19087 block.add_animation();
19088 }
19089 // add directive and handler dependencies
19090 [node.animation, node.outro, ...node.actions, ...node.classes].forEach(directive => {
19091 if (directive && directive.expression) {
19092 block.add_dependencies(directive.expression.dependencies);
19093 }
19094 });
19095 node.handlers.forEach(handler => {
19096 if (handler.expression) {
19097 block.add_dependencies(handler.expression.dependencies);
19098 }
19099 });
19100 if (this.parent) {
19101 if (node.actions.length > 0 ||
19102 node.animation ||
19103 node.bindings.length > 0 ||
19104 node.classes.length > 0 ||
19105 node.intro || node.outro ||
19106 node.handlers.length > 0 ||
19107 this.node.name === 'option' ||
19108 renderer.options.dev) {
19109 this.parent.cannot_use_innerhtml(); // need to use add_location
19110 this.parent.not_static_content();
19111 }
19112 }
19113 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
19114 if (this.slot_block) {
19115 block.parent.add_dependencies(block.dependencies);
19116 // appalling hack
19117 const index = block.parent.wrappers.indexOf(this);
19118 block.parent.wrappers.splice(index, 1);
19119 block.wrappers.push(this);
19120 }
19121 }
19122 render(block, parent_node, parent_nodes) {
19123 const { renderer } = this;
19124 if (this.node.name === 'noscript')
19125 return;
19126 if (this.slot_block) {
19127 block = this.slot_block;
19128 }
19129 const node = this.var;
19130 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
19131 const children = x `@children(${this.node.name === 'template' ? x `${node}.content` : node})`;
19132 block.add_variable(node);
19133 const render_statement = this.get_render_statement(block);
19134 block.chunks.create.push(b `${node} = ${render_statement};`);
19135 if (renderer.options.hydratable) {
19136 if (parent_nodes) {
19137 block.chunks.claim.push(b `
19138 ${node} = ${this.get_claim_statement(parent_nodes)};
19139 `);
19140 if (!this.void && this.node.children.length > 0) {
19141 block.chunks.claim.push(b `
19142 var ${nodes} = ${children};
19143 `);
19144 }
19145 }
19146 else {
19147 block.chunks.claim.push(b `${node} = ${render_statement};`);
19148 }
19149 }
19150 if (parent_node) {
19151 block.chunks.mount.push(b `@append(${parent_node}, ${node});`);
19152 if (is_head(parent_node)) {
19153 block.chunks.destroy.push(b `@detach(${node});`);
19154 }
19155 }
19156 else {
19157 block.chunks.mount.push(b `@insert(#target, ${node}, #anchor);`);
19158 // TODO we eventually need to consider what happens to elements
19159 // that belong to the same outgroup as an outroing element...
19160 block.chunks.destroy.push(b `if (detaching) @detach(${node});`);
19161 }
19162 // insert static children with textContent or innerHTML
19163 const can_use_textcontent = this.can_use_textcontent();
19164 if (!this.node.namespace && (this.can_use_innerhtml || can_use_textcontent) && this.fragment.nodes.length > 0) {
19165 if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
19166 block.chunks.create.push(b `${node}.textContent = ${string_literal(this.fragment.nodes[0].data)};`);
19167 }
19168 else {
19169 const state = {
19170 quasi: {
19171 type: 'TemplateElement',
19172 value: { raw: '' }
19173 }
19174 };
19175 const literal = {
19176 type: 'TemplateLiteral',
19177 expressions: [],
19178 quasis: []
19179 };
19180 const can_use_raw_text = !this.can_use_innerhtml && can_use_textcontent;
19181 to_html(this.fragment.nodes, block, literal, state, can_use_raw_text);
19182 literal.quasis.push(state.quasi);
19183 block.chunks.create.push(b `${node}.${this.can_use_innerhtml ? 'innerHTML' : 'textContent'} = ${literal};`);
19184 }
19185 }
19186 else {
19187 this.fragment.nodes.forEach((child) => {
19188 child.render(block, this.node.name === 'template' ? x `${node}.content` : node, nodes);
19189 });
19190 }
19191 const event_handler_or_binding_uses_context = (this.bindings.some(binding => binding.handler.uses_context) ||
19192 this.node.handlers.some(handler => handler.uses_context) ||
19193 this.node.actions.some(action => action.uses_context));
19194 if (event_handler_or_binding_uses_context) {
19195 block.maintain_context = true;
19196 }
19197 this.add_attributes(block);
19198 this.add_directives_in_order(block);
19199 this.add_transitions(block);
19200 this.add_animation(block);
19201 this.add_classes(block);
19202 this.add_manual_style_scoping(block);
19203 if (nodes && this.renderer.options.hydratable && !this.void) {
19204 block.chunks.claim.push(b `${this.node.children.length > 0 ? nodes : children}.forEach(@detach);`);
19205 }
19206 if (renderer.options.dev) {
19207 const loc = renderer.locate(this.node.start);
19208 block.chunks.hydrate.push(b `@add_location(${this.var}, ${renderer.file_var}, ${loc.line - 1}, ${loc.column}, ${this.node.start});`);
19209 }
19210 }
19211 can_use_textcontent() {
19212 return this.is_static_content && this.fragment.nodes.every(node => node.node.type === 'Text' || node.node.type === 'MustacheTag');
19213 }
19214 get_render_statement(block) {
19215 const { name, namespace } = this.node;
19216 if (namespace === namespaces.svg) {
19217 return x `@svg_element("${name}")`;
19218 }
19219 if (namespace) {
19220 return x `@_document.createElementNS("${namespace}", "${name}")`;
19221 }
19222 const is = this.attributes.find(attr => attr.node.name === 'is');
19223 if (is) {
19224 return x `@element_is("${name}", ${is.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`)})`;
19225 }
19226 return x `@element("${name}")`;
19227 }
19228 get_claim_statement(nodes) {
19229 const attributes = this.node.attributes
19230 .filter((attr) => attr.type === 'Attribute')
19231 .map((attr) => p `${attr.name}: true`);
19232 const name = this.node.namespace
19233 ? this.node.name
19234 : this.node.name.toUpperCase();
19235 const svg = this.node.namespace === namespaces.svg ? 1 : null;
19236 return x `@claim_element(${nodes}, "${name}", { ${attributes} }, ${svg})`;
19237 }
19238 add_directives_in_order(block) {
19239 const binding_groups = events
19240 .map(event => ({
19241 events: event.event_names,
19242 bindings: this.bindings
19243 .filter(binding => binding.node.name !== 'this')
19244 .filter(binding => event.filter(this.node, binding.node.name))
19245 }))
19246 .filter(group => group.bindings.length);
19247 const this_binding = this.bindings.find(b => b.node.name === 'this');
19248 function getOrder(item) {
19249 if (item instanceof EventHandlerWrapper) {
19250 return item.node.start;
19251 }
19252 else if (item instanceof BindingWrapper) {
19253 return item.node.start;
19254 }
19255 else if (item instanceof Action) {
19256 return item.start;
19257 }
19258 else {
19259 return item.bindings[0].node.start;
19260 }
19261 }
19262 [
19263 ...binding_groups,
19264 ...this.event_handlers,
19265 this_binding,
19266 ...this.node.actions
19267 ]
19268 .filter(Boolean)
19269 .sort((a, b) => getOrder(a) - getOrder(b))
19270 .forEach(item => {
19271 if (item instanceof EventHandlerWrapper) {
19272 add_event_handler(block, this.var, item);
19273 }
19274 else if (item instanceof BindingWrapper) {
19275 this.add_this_binding(block, item);
19276 }
19277 else if (item instanceof Action) {
19278 add_action(block, this.var, item);
19279 }
19280 else {
19281 this.add_bindings(block, item);
19282 }
19283 });
19284 }
19285 add_bindings(block, binding_group) {
19286 const { renderer } = this;
19287 if (binding_group.bindings.length === 0)
19288 return;
19289 renderer.component.has_reactive_assignments = true;
19290 const lock = binding_group.bindings.some(binding => binding.needs_lock) ?
19291 block.get_unique_name(`${this.var.name}_updating`) :
19292 null;
19293 if (lock)
19294 block.add_variable(lock, x `false`);
19295 const handler = renderer.component.get_unique_name(`${this.var.name}_${binding_group.events.join('_')}_handler`);
19296 renderer.add_to_context(handler.name);
19297 // TODO figure out how to handle locks
19298 const needs_lock = binding_group.bindings.some(binding => binding.needs_lock);
19299 const dependencies = new Set();
19300 const contextual_dependencies = new Set();
19301 binding_group.bindings.forEach(binding => {
19302 // TODO this is a mess
19303 add_to_set(dependencies, binding.get_dependencies());
19304 add_to_set(contextual_dependencies, binding.handler.contextual_dependencies);
19305 binding.render(block, lock);
19306 });
19307 // media bindings — awkward special case. The native timeupdate events
19308 // fire too infrequently, so we need to take matters into our
19309 // own hands
19310 let animation_frame;
19311 if (binding_group.events[0] === 'timeupdate') {
19312 animation_frame = block.get_unique_name(`${this.var.name}_animationframe`);
19313 block.add_variable(animation_frame);
19314 }
19315 const has_local_function = contextual_dependencies.size > 0 || needs_lock || animation_frame;
19316 let callee = renderer.reference(handler);
19317 // TODO dry this out — similar code for event handlers and component bindings
19318 if (has_local_function) {
19319 const args = Array.from(contextual_dependencies).map(name => renderer.reference(name));
19320 // need to create a block-local function that calls an instance-level function
19321 if (animation_frame) {
19322 block.chunks.init.push(b `
19323 function ${handler}() {
19324 @_cancelAnimationFrame(${animation_frame});
19325 if (!${this.var}.paused) {
19326 ${animation_frame} = @raf(${handler});
19327 ${needs_lock && b `${lock} = true;`}
19328 }
19329 ${callee}.call(${this.var}, ${args});
19330 }
19331 `);
19332 }
19333 else {
19334 block.chunks.init.push(b `
19335 function ${handler}() {
19336 ${needs_lock && b `${lock} = true;`}
19337 ${callee}.call(${this.var}, ${args});
19338 }
19339 `);
19340 }
19341 callee = handler;
19342 }
19343 const params = Array.from(contextual_dependencies).map(name => ({
19344 type: 'Identifier',
19345 name
19346 }));
19347 this.renderer.component.partly_hoisted.push(b `
19348 function ${handler}(${params}) {
19349 ${binding_group.bindings.map(b => b.handler.mutation)}
19350 ${Array.from(dependencies)
19351 .filter(dep => dep[0] !== '$')
19352 .filter(dep => !contextual_dependencies.has(dep))
19353 .map(dep => b `${this.renderer.invalidate(dep)};`)}
19354 }
19355 `);
19356 binding_group.events.forEach(name => {
19357 if (name === 'elementresize') {
19358 // special case
19359 const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`);
19360 block.add_variable(resize_listener);
19361 block.chunks.mount.push(b `${resize_listener} = @add_resize_listener(${this.var}, ${callee}.bind(${this.var}));`);
19362 block.chunks.destroy.push(b `${resize_listener}();`);
19363 }
19364 else {
19365 block.event_listeners.push(x `@listen(${this.var}, "${name}", ${callee})`);
19366 }
19367 });
19368 const some_initial_state_is_undefined = binding_group.bindings
19369 .map(binding => x `${binding.snippet} === void 0`)
19370 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
19371 const should_initialise = (this.node.name === 'select' ||
19372 binding_group.bindings.find(binding => {
19373 return (binding.node.name === 'indeterminate' ||
19374 binding.node.name === 'textContent' ||
19375 binding.node.name === 'innerHTML' ||
19376 binding.is_readonly_media_attribute());
19377 }));
19378 if (should_initialise) {
19379 const callback = has_local_function ? handler : x `() => ${callee}.call(${this.var})`;
19380 block.chunks.hydrate.push(b `if (${some_initial_state_is_undefined}) @add_render_callback(${callback});`);
19381 }
19382 if (binding_group.events[0] === 'elementresize') {
19383 block.chunks.hydrate.push(b `@add_render_callback(() => ${callee}.call(${this.var}));`);
19384 }
19385 if (lock) {
19386 block.chunks.update.push(b `${lock} = false;`);
19387 }
19388 }
19389 add_this_binding(block, this_binding) {
19390 const { renderer } = this;
19391 renderer.component.has_reactive_assignments = true;
19392 const binding_callback = bind_this(renderer.component, block, this_binding, this.var);
19393 block.chunks.mount.push(binding_callback);
19394 }
19395 add_attributes(block) {
19396 // Get all the class dependencies first
19397 this.attributes.forEach((attribute) => {
19398 if (attribute.node.name === 'class') {
19399 const dependencies = attribute.node.get_dependencies();
19400 this.class_dependencies.push(...dependencies);
19401 }
19402 });
19403 if (this.node.attributes.some(attr => attr.is_spread)) {
19404 this.add_spread_attributes(block);
19405 return;
19406 }
19407 this.attributes.forEach((attribute) => {
19408 attribute.render(block);
19409 });
19410 }
19411 add_spread_attributes(block) {
19412 const levels = block.get_unique_name(`${this.var.name}_levels`);
19413 const data = block.get_unique_name(`${this.var.name}_data`);
19414 const initial_props = [];
19415 const updates = [];
19416 this.attributes
19417 .forEach(attr => {
19418 const dependencies = attr.node.get_dependencies();
19419 const condition = dependencies.length > 0
19420 ? block.renderer.dirty(dependencies)
19421 : null;
19422 if (attr instanceof SpreadAttributeWrapper) {
19423 const snippet = attr.node.expression.manipulate(block);
19424 initial_props.push(snippet);
19425 updates.push(condition ? x `${condition} && ${snippet}` : snippet);
19426 }
19427 else {
19428 const name = attr.property_name || attr.name;
19429 initial_props.push(x `{ ${name}: ${attr.get_init(block, attr.get_value(block))} }`);
19430 const snippet = x `{ ${name}: ${attr.should_cache ? attr.last : attr.get_value(block)} }`;
19431 updates.push(condition ? x `${attr.get_dom_update_conditions(block, condition)} && ${snippet}` : snippet);
19432 }
19433 });
19434 block.chunks.init.push(b `
19435 let ${levels} = [${initial_props}];
19436
19437 let ${data} = {};
19438 for (let #i = 0; #i < ${levels}.length; #i += 1) {
19439 ${data} = @assign(${data}, ${levels}[#i]);
19440 }
19441 `);
19442 const fn = this.node.namespace === namespaces.svg ? x `@set_svg_attributes` : x `@set_attributes`;
19443 block.chunks.hydrate.push(b `${fn}(${this.var}, ${data});`);
19444 block.chunks.update.push(b `
19445 ${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
19446 ${updates}
19447 ]));
19448 `);
19449 // handle edge cases for elements
19450 if (this.node.name === 'select') {
19451 const dependencies = new Set();
19452 for (const attr of this.attributes) {
19453 for (const dep of attr.node.dependencies) {
19454 dependencies.add(dep);
19455 }
19456 }
19457 block.chunks.mount.push(b `
19458 if (${data}.multiple) @select_options(${this.var}, ${data}.value);
19459 `);
19460 block.chunks.update.push(b `
19461 if (${block.renderer.dirty(Array.from(dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value);
19462 `);
19463 }
19464 else if (this.node.name === 'input' && this.attributes.find(attr => attr.node.name === 'value')) {
19465 const type = this.node.get_static_attribute_value('type');
19466 if (type === null || type === '' || type === 'text' || type === 'email' || type === 'password') {
19467 block.chunks.mount.push(b `
19468 ${this.var}.value = ${data}.value;
19469 `);
19470 block.chunks.update.push(b `
19471 if ('value' in ${data}) {
19472 ${this.var}.value = ${data}.value;
19473 }
19474 `);
19475 }
19476 }
19477 }
19478 add_transitions(block) {
19479 const { intro, outro } = this.node;
19480 if (!intro && !outro)
19481 return;
19482 if (intro === outro) {
19483 // bidirectional transition
19484 const name = block.get_unique_name(`${this.var.name}_transition`);
19485 const snippet = intro.expression
19486 ? intro.expression.manipulate(block)
19487 : x `{}`;
19488 block.add_variable(name);
19489 const fn = this.renderer.reference(intro.name);
19490 const intro_block = b `
19491 @add_render_callback(() => {
19492 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, true);
19493 ${name}.run(1);
19494 });
19495 `;
19496 const outro_block = b `
19497 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, false);
19498 ${name}.run(0);
19499 `;
19500 if (intro.is_local) {
19501 block.chunks.intro.push(b `
19502 if (#local) {
19503 ${intro_block}
19504 }
19505 `);
19506 block.chunks.outro.push(b `
19507 if (#local) {
19508 ${outro_block}
19509 }
19510 `);
19511 }
19512 else {
19513 block.chunks.intro.push(intro_block);
19514 block.chunks.outro.push(outro_block);
19515 }
19516 block.chunks.destroy.push(b `if (detaching && ${name}) ${name}.end();`);
19517 }
19518 else {
19519 const intro_name = intro && block.get_unique_name(`${this.var.name}_intro`);
19520 const outro_name = outro && block.get_unique_name(`${this.var.name}_outro`);
19521 if (intro) {
19522 block.add_variable(intro_name);
19523 const snippet = intro.expression
19524 ? intro.expression.manipulate(block)
19525 : x `{}`;
19526 const fn = this.renderer.reference(intro.name);
19527 let intro_block;
19528 if (outro) {
19529 intro_block = b `
19530 @add_render_callback(() => {
19531 if (${outro_name}) ${outro_name}.end(1);
19532 if (!${intro_name}) ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
19533 ${intro_name}.start();
19534 });
19535 `;
19536 block.chunks.outro.push(b `if (${intro_name}) ${intro_name}.invalidate();`);
19537 }
19538 else {
19539 intro_block = b `
19540 if (!${intro_name}) {
19541 @add_render_callback(() => {
19542 ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
19543 ${intro_name}.start();
19544 });
19545 }
19546 `;
19547 }
19548 if (intro.is_local) {
19549 intro_block = b `
19550 if (#local) {
19551 ${intro_block}
19552 }
19553 `;
19554 }
19555 block.chunks.intro.push(intro_block);
19556 }
19557 if (outro) {
19558 block.add_variable(outro_name);
19559 const snippet = outro.expression
19560 ? outro.expression.manipulate(block)
19561 : x `{}`;
19562 const fn = this.renderer.reference(outro.name);
19563 if (!intro) {
19564 block.chunks.intro.push(b `
19565 if (${outro_name}) ${outro_name}.end(1);
19566 `);
19567 }
19568 // TODO hide elements that have outro'd (unless they belong to a still-outroing
19569 // group) prior to their removal from the DOM
19570 let outro_block = b `
19571 ${outro_name} = @create_out_transition(${this.var}, ${fn}, ${snippet});
19572 `;
19573 if (outro.is_local) {
19574 outro_block = b `
19575 if (#local) {
19576 ${outro_block}
19577 }
19578 `;
19579 }
19580 block.chunks.outro.push(outro_block);
19581 block.chunks.destroy.push(b `if (detaching && ${outro_name}) ${outro_name}.end();`);
19582 }
19583 }
19584 if ((intro && intro.expression && intro.expression.dependencies.size) || (outro && outro.expression && outro.expression.dependencies.size)) {
19585 block.maintain_context = true;
19586 }
19587 }
19588 add_animation(block) {
19589 if (!this.node.animation)
19590 return;
19591 const { outro } = this.node;
19592 const rect = block.get_unique_name('rect');
19593 const stop_animation = block.get_unique_name('stop_animation');
19594 block.add_variable(rect);
19595 block.add_variable(stop_animation, x `@noop`);
19596 block.chunks.measure.push(b `
19597 ${rect} = ${this.var}.getBoundingClientRect();
19598 `);
19599 block.chunks.fix.push(b `
19600 @fix_position(${this.var});
19601 ${stop_animation}();
19602 ${outro && b `@add_transform(${this.var}, ${rect});`}
19603 `);
19604 let params;
19605 if (this.node.animation.expression) {
19606 params = this.node.animation.expression.manipulate(block);
19607 if (this.node.animation.expression.dynamic_dependencies().length) {
19608 // if `params` is dynamic, calculate params ahead of time in the `.r()` method
19609 const params_var = block.get_unique_name('params');
19610 block.add_variable(params_var);
19611 block.chunks.measure.push(b `${params_var} = ${params};`);
19612 params = params_var;
19613 }
19614 }
19615 else {
19616 params = x `{}`;
19617 }
19618 const name = this.renderer.reference(this.node.animation.name);
19619 block.chunks.animate.push(b `
19620 ${stop_animation}();
19621 ${stop_animation} = @create_animation(${this.var}, ${rect}, ${name}, ${params});
19622 `);
19623 }
19624 add_classes(block) {
19625 const has_spread = this.node.attributes.some(attr => attr.is_spread);
19626 this.node.classes.forEach(class_directive => {
19627 const { expression, name } = class_directive;
19628 let snippet;
19629 let dependencies;
19630 if (expression) {
19631 snippet = expression.manipulate(block);
19632 dependencies = expression.dependencies;
19633 }
19634 else {
19635 snippet = name;
19636 dependencies = new Set([name]);
19637 }
19638 const updater = b `@toggle_class(${this.var}, "${name}", ${snippet});`;
19639 block.chunks.hydrate.push(updater);
19640 if (has_spread) {
19641 block.chunks.update.push(updater);
19642 }
19643 else if ((dependencies && dependencies.size > 0) || this.class_dependencies.length) {
19644 const all_dependencies = this.class_dependencies.concat(...dependencies);
19645 const condition = block.renderer.dirty(all_dependencies);
19646 block.chunks.update.push(b `
19647 if (${condition}) {
19648 ${updater}
19649 }`);
19650 }
19651 });
19652 }
19653 add_manual_style_scoping(block) {
19654 if (this.node.needs_manual_style_scoping) {
19655 const updater = b `@toggle_class(${this.var}, "${this.node.component.stylesheet.id}", true);`;
19656 block.chunks.hydrate.push(updater);
19657 block.chunks.update.push(updater);
19658 }
19659 }
19660}
19661function to_html(wrappers, block, literal, state, can_use_raw_text) {
19662 wrappers.forEach(wrapper => {
19663 if (wrapper instanceof TextWrapper) {
19664 if (wrapper.use_space())
19665 state.quasi.value.raw += ' ';
19666 const parent = wrapper.node.parent;
19667 const raw = parent && (parent.name === 'script' ||
19668 parent.name === 'style' ||
19669 can_use_raw_text);
19670 state.quasi.value.raw += (raw ? wrapper.data : escape_html(wrapper.data))
19671 .replace(/\\/g, '\\\\')
19672 .replace(/`/g, '\\`')
19673 .replace(/\$/g, '\\$');
19674 }
19675 else if (wrapper instanceof MustacheTagWrapper || wrapper instanceof RawMustacheTagWrapper) {
19676 literal.quasis.push(state.quasi);
19677 literal.expressions.push(wrapper.node.expression.manipulate(block));
19678 state.quasi = {
19679 type: 'TemplateElement',
19680 value: { raw: '' }
19681 };
19682 }
19683 else if (wrapper.node.name === 'noscript') ;
19684 else {
19685 // element
19686 state.quasi.value.raw += `<${wrapper.node.name}`;
19687 wrapper.attributes.forEach((attr) => {
19688 state.quasi.value.raw += ` ${fix_attribute_casing(attr.node.name)}="`;
19689 attr.node.chunks.forEach(chunk => {
19690 if (chunk.type === 'Text') {
19691 state.quasi.value.raw += escape_html(chunk.data);
19692 }
19693 else {
19694 literal.quasis.push(state.quasi);
19695 literal.expressions.push(chunk.manipulate(block));
19696 state.quasi = {
19697 type: 'TemplateElement',
19698 value: { raw: '' }
19699 };
19700 }
19701 });
19702 state.quasi.value.raw += '"';
19703 });
19704 if (!wrapper.void) {
19705 state.quasi.value.raw += '>';
19706 to_html(wrapper.fragment.nodes, block, literal, state);
19707 state.quasi.value.raw += `</${wrapper.node.name}>`;
19708 }
19709 else {
19710 state.quasi.value.raw += '/>';
19711 }
19712 }
19713 });
19714}
19715
19716class HeadWrapper extends Wrapper {
19717 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19718 super(renderer, block, parent, node);
19719 this.can_use_innerhtml = false;
19720 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
19721 }
19722 render(block, _parent_node, _parent_nodes) {
19723 let nodes;
19724 if (this.renderer.options.hydratable && this.fragment.nodes.length) {
19725 nodes = block.get_unique_name('head_nodes');
19726 block.chunks.claim.push(b `const ${nodes} = @query_selector_all('[data-svelte="${this.node.id}"]', @_document.head);`);
19727 }
19728 this.fragment.render(block, x `@_document.head`, nodes);
19729 if (nodes && this.renderer.options.hydratable) {
19730 block.chunks.claim.push(b `${nodes}.forEach(@detach);`);
19731 }
19732 }
19733}
19734
19735function is_else_if(node) {
19736 return (node && node.children.length === 1 && node.children[0].type === 'IfBlock');
19737}
19738class IfBlockBranch extends Wrapper {
19739 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19740 super(renderer, block, parent, node);
19741 this.var = null;
19742 const { expression } = node;
19743 const is_else = !expression;
19744 if (expression) {
19745 this.dependencies = expression.dynamic_dependencies();
19746 // TODO is this the right rule? or should any non-reference count?
19747 // const should_cache = !is_reference(expression.node, null) && dependencies.length > 0;
19748 let should_cache = false;
19749 walk(expression.node, {
19750 enter(node) {
19751 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
19752 should_cache = true;
19753 }
19754 }
19755 });
19756 if (should_cache) {
19757 this.condition = block.get_unique_name('show_if');
19758 this.snippet = expression.manipulate(block);
19759 }
19760 else {
19761 this.condition = expression.manipulate(block);
19762 }
19763 }
19764 this.block = block.child({
19765 comment: create_debugging_comment(node, parent.renderer.component),
19766 name: parent.renderer.component.get_unique_name(is_else ? 'create_else_block' : 'create_if_block'),
19767 type: node.expression ? 'if' : 'else'
19768 });
19769 this.fragment = new FragmentWrapper(renderer, this.block, node.children, parent, strip_whitespace, next_sibling);
19770 this.is_dynamic = this.block.dependencies.size > 0;
19771 }
19772}
19773class IfBlockWrapper extends Wrapper {
19774 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19775 super(renderer, block, parent, node);
19776 this.needs_update = false;
19777 this.var = { type: 'Identifier', name: 'if_block' };
19778 this.cannot_use_innerhtml();
19779 this.not_static_content();
19780 this.branches = [];
19781 const blocks = [];
19782 let is_dynamic = false;
19783 let has_intros = false;
19784 let has_outros = false;
19785 const create_branches = (node) => {
19786 const branch = new IfBlockBranch(renderer, block, this, node, strip_whitespace, next_sibling);
19787 this.branches.push(branch);
19788 blocks.push(branch.block);
19789 block.add_dependencies(node.expression.dependencies);
19790 if (branch.block.dependencies.size > 0) {
19791 // the condition, or its contents, is dynamic
19792 is_dynamic = true;
19793 block.add_dependencies(branch.block.dependencies);
19794 }
19795 if (branch.dependencies && branch.dependencies.length > 0) {
19796 // the condition itself is dynamic
19797 this.needs_update = true;
19798 }
19799 if (branch.block.has_intros)
19800 has_intros = true;
19801 if (branch.block.has_outros)
19802 has_outros = true;
19803 if (is_else_if(node.else)) {
19804 create_branches(node.else.children[0]);
19805 }
19806 else if (node.else) {
19807 const branch = new IfBlockBranch(renderer, block, this, node.else, strip_whitespace, next_sibling);
19808 this.branches.push(branch);
19809 blocks.push(branch.block);
19810 if (branch.block.dependencies.size > 0) {
19811 is_dynamic = true;
19812 block.add_dependencies(branch.block.dependencies);
19813 }
19814 if (branch.block.has_intros)
19815 has_intros = true;
19816 if (branch.block.has_outros)
19817 has_outros = true;
19818 }
19819 };
19820 create_branches(this.node);
19821 blocks.forEach(block => {
19822 block.has_update_method = is_dynamic;
19823 block.has_intro_method = has_intros;
19824 block.has_outro_method = has_outros;
19825 });
19826 renderer.blocks.push(...blocks);
19827 }
19828 render(block, parent_node, parent_nodes) {
19829 const name = this.var;
19830 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
19831 const anchor = needs_anchor
19832 ? block.get_unique_name(`${this.var.name}_anchor`)
19833 : (this.next && this.next.var) || 'null';
19834 const has_else = !(this.branches[this.branches.length - 1].condition);
19835 const if_exists_condition = has_else ? null : name;
19836 const dynamic = this.branches[0].block.has_update_method; // can use [0] as proxy for all, since they necessarily have the same value
19837 const has_intros = this.branches[0].block.has_intro_method;
19838 const has_outros = this.branches[0].block.has_outro_method;
19839 const has_transitions = has_intros || has_outros;
19840 const vars = { name, anchor, if_exists_condition, has_else, has_transitions };
19841 const detaching = parent_node && !is_head(parent_node) ? null : 'detaching';
19842 if (this.node.else) {
19843 this.branches.forEach(branch => {
19844 if (branch.snippet)
19845 block.add_variable(branch.condition);
19846 });
19847 if (has_outros) {
19848 this.render_compound_with_outros(block, parent_node, parent_nodes, dynamic, vars, detaching);
19849 block.chunks.outro.push(b `@transition_out(${name});`);
19850 }
19851 else {
19852 this.render_compound(block, parent_node, parent_nodes, dynamic, vars, detaching);
19853 }
19854 }
19855 else {
19856 this.render_simple(block, parent_node, parent_nodes, dynamic, vars, detaching);
19857 if (has_outros) {
19858 block.chunks.outro.push(b `@transition_out(${name});`);
19859 }
19860 }
19861 if (if_exists_condition) {
19862 block.chunks.create.push(b `if (${if_exists_condition}) ${name}.c();`);
19863 }
19864 else {
19865 block.chunks.create.push(b `${name}.c();`);
19866 }
19867 if (parent_nodes && this.renderer.options.hydratable) {
19868 if (if_exists_condition) {
19869 block.chunks.claim.push(b `if (${if_exists_condition}) ${name}.l(${parent_nodes});`);
19870 }
19871 else {
19872 block.chunks.claim.push(b `${name}.l(${parent_nodes});`);
19873 }
19874 }
19875 if (has_intros || has_outros) {
19876 block.chunks.intro.push(b `@transition_in(${name});`);
19877 }
19878 if (needs_anchor) {
19879 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
19880 }
19881 this.branches.forEach(branch => {
19882 branch.fragment.render(branch.block, null, x `#nodes`);
19883 });
19884 }
19885 render_compound(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, if_exists_condition, has_transitions }, detaching) {
19886 const select_block_type = this.renderer.component.get_unique_name('select_block_type');
19887 const current_block_type = block.get_unique_name('current_block_type');
19888 const get_block = has_else
19889 ? x `${current_block_type}(#ctx)`
19890 : x `${current_block_type} && ${current_block_type}(#ctx)`;
19891 if (this.needs_update) {
19892 block.chunks.init.push(b `
19893 function ${select_block_type}(#ctx, #dirty) {
19894 ${this.branches.map(({ dependencies, condition, snippet, block }) => condition
19895 ? b `
19896 ${snippet && (dependencies.length > 0
19897 ? b `if (${condition} == null || ${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
19898 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
19899 if (${condition}) return ${block.name};`
19900 : b `return ${block.name};`)}
19901 }
19902 `);
19903 }
19904 else {
19905 block.chunks.init.push(b `
19906 function ${select_block_type}(#ctx, #dirty) {
19907 ${this.branches.map(({ condition, snippet, block }) => condition
19908 ? b `if (${snippet || condition}) return ${block.name};`
19909 : b `return ${block.name};`)}
19910 }
19911 `);
19912 }
19913 block.chunks.init.push(b `
19914 let ${current_block_type} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
19915 let ${name} = ${get_block};
19916 `);
19917 const initial_mount_node = parent_node || '#target';
19918 const anchor_node = parent_node ? 'null' : '#anchor';
19919 if (if_exists_condition) {
19920 block.chunks.mount.push(b `if (${if_exists_condition}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
19921 }
19922 else {
19923 block.chunks.mount.push(b `${name}.m(${initial_mount_node}, ${anchor_node});`);
19924 }
19925 if (this.needs_update) {
19926 const update_mount_node = this.get_update_mount_node(anchor);
19927 const change_block = b `
19928 ${if_exists_condition ? b `if (${if_exists_condition}) ${name}.d(1)` : b `${name}.d(1)`};
19929 ${name} = ${get_block};
19930 if (${name}) {
19931 ${name}.c();
19932 ${has_transitions && b `@transition_in(${name}, 1);`}
19933 ${name}.m(${update_mount_node}, ${anchor});
19934 }
19935 `;
19936 if (dynamic) {
19937 block.chunks.update.push(b `
19938 if (${current_block_type} === (${current_block_type} = ${select_block_type}(#ctx, #dirty)) && ${name}) {
19939 ${name}.p(#ctx, #dirty);
19940 } else {
19941 ${change_block}
19942 }
19943 `);
19944 }
19945 else {
19946 block.chunks.update.push(b `
19947 if (${current_block_type} !== (${current_block_type} = ${select_block_type}(#ctx, #dirty))) {
19948 ${change_block}
19949 }
19950 `);
19951 }
19952 }
19953 else if (dynamic) {
19954 if (if_exists_condition) {
19955 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
19956 }
19957 else {
19958 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
19959 }
19960 }
19961 if (if_exists_condition) {
19962 block.chunks.destroy.push(b `
19963 if (${if_exists_condition}) {
19964 ${name}.d(${detaching});
19965 }
19966 `);
19967 }
19968 else {
19969 block.chunks.destroy.push(b `
19970 ${name}.d(${detaching});
19971 `);
19972 }
19973 }
19974 // if any of the siblings have outros, we need to keep references to the blocks
19975 // (TODO does this only apply to bidi transitions?)
19976 render_compound_with_outros(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, has_transitions, if_exists_condition }, detaching) {
19977 const select_block_type = this.renderer.component.get_unique_name('select_block_type');
19978 const current_block_type_index = block.get_unique_name('current_block_type_index');
19979 const previous_block_index = block.get_unique_name('previous_block_index');
19980 const if_block_creators = block.get_unique_name('if_block_creators');
19981 const if_blocks = block.get_unique_name('if_blocks');
19982 const if_current_block_type_index = has_else
19983 ? nodes => nodes
19984 : nodes => b `if (~${current_block_type_index}) { ${nodes} }`;
19985 block.add_variable(current_block_type_index);
19986 block.add_variable(name);
19987 block.chunks.init.push(b `
19988 const ${if_block_creators} = [
19989 ${this.branches.map(branch => branch.block.name)}
19990 ];
19991
19992 const ${if_blocks} = [];
19993
19994 ${this.needs_update
19995 ? b `
19996 function ${select_block_type}(#ctx, #dirty) {
19997 ${this.branches.map(({ dependencies, condition, snippet }, i) => condition
19998 ? b `
19999 ${snippet && (dependencies.length > 0
20000 ? b `if (${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
20001 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
20002 if (${condition}) return ${i};`
20003 : b `return ${i};`)}
20004 ${!has_else && b `return -1;`}
20005 }
20006 `
20007 : b `
20008 function ${select_block_type}(#ctx, #dirty) {
20009 ${this.branches.map(({ condition, snippet }, i) => condition
20010 ? b `if (${snippet || condition}) return ${i};`
20011 : b `return ${i};`)}
20012 ${!has_else && b `return -1;`}
20013 }
20014 `}
20015 `);
20016 if (has_else) {
20017 block.chunks.init.push(b `
20018 ${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
20019 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
20020 `);
20021 }
20022 else {
20023 block.chunks.init.push(b `
20024 if (~(${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}))) {
20025 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
20026 }
20027 `);
20028 }
20029 const initial_mount_node = parent_node || '#target';
20030 const anchor_node = parent_node ? 'null' : '#anchor';
20031 block.chunks.mount.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].m(${initial_mount_node}, ${anchor_node});`));
20032 if (this.needs_update) {
20033 const update_mount_node = this.get_update_mount_node(anchor);
20034 const destroy_old_block = b `
20035 @group_outros();
20036 @transition_out(${if_blocks}[${previous_block_index}], 1, 1, () => {
20037 ${if_blocks}[${previous_block_index}] = null;
20038 });
20039 @check_outros();
20040 `;
20041 const create_new_block = b `
20042 ${name} = ${if_blocks}[${current_block_type_index}];
20043 if (!${name}) {
20044 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
20045 ${name}.c();
20046 } else {
20047 ${dynamic && b `${name}.p(#ctx, #dirty);`}
20048 }
20049 ${has_transitions && b `@transition_in(${name}, 1);`}
20050 ${name}.m(${update_mount_node}, ${anchor});
20051 `;
20052 const change_block = has_else
20053 ? b `
20054 ${destroy_old_block}
20055
20056 ${create_new_block}
20057 `
20058 : b `
20059 if (${name}) {
20060 ${destroy_old_block}
20061 }
20062
20063 if (~${current_block_type_index}) {
20064 ${create_new_block}
20065 } else {
20066 ${name} = null;
20067 }
20068 `;
20069 block.chunks.update.push(b `
20070 let ${previous_block_index} = ${current_block_type_index};
20071 ${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
20072 `);
20073 if (dynamic) {
20074 block.chunks.update.push(b `
20075 if (${current_block_type_index} === ${previous_block_index}) {
20076 ${if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].p(#ctx, #dirty);`)}
20077 } else {
20078 ${change_block}
20079 }
20080 `);
20081 }
20082 else {
20083 block.chunks.update.push(b `
20084 if (${current_block_type_index} !== ${previous_block_index}) {
20085 ${change_block}
20086 }
20087 `);
20088 }
20089 }
20090 else if (dynamic) {
20091 if (if_exists_condition) {
20092 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
20093 }
20094 else {
20095 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
20096 }
20097 }
20098 block.chunks.destroy.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].d(${detaching});`));
20099 }
20100 render_simple(block, parent_node, _parent_nodes, dynamic, { name, anchor, if_exists_condition, has_transitions }, detaching) {
20101 const branch = this.branches[0];
20102 if (branch.snippet)
20103 block.add_variable(branch.condition, branch.snippet);
20104 block.chunks.init.push(b `
20105 let ${name} = ${branch.condition} && ${branch.block.name}(#ctx);
20106 `);
20107 const initial_mount_node = parent_node || '#target';
20108 const anchor_node = parent_node ? 'null' : '#anchor';
20109 block.chunks.mount.push(b `if (${name}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
20110 if (branch.dependencies.length > 0) {
20111 const update_mount_node = this.get_update_mount_node(anchor);
20112 const enter = b `
20113 if (${name}) {
20114 ${dynamic && b `${name}.p(#ctx, #dirty);`}
20115 ${has_transitions &&
20116 b `if (${block.renderer.dirty(branch.dependencies)}) {
20117 @transition_in(${name}, 1);
20118 }`}
20119 } else {
20120 ${name} = ${branch.block.name}(#ctx);
20121 ${name}.c();
20122 ${has_transitions && b `@transition_in(${name}, 1);`}
20123 ${name}.m(${update_mount_node}, ${anchor});
20124 }
20125 `;
20126 if (branch.snippet) {
20127 block.chunks.update.push(b `if (${block.renderer.dirty(branch.dependencies)}) ${branch.condition} = ${branch.snippet}`);
20128 }
20129 // no `p()` here — we don't want to update outroing nodes,
20130 // as that will typically result in glitching
20131 if (branch.block.has_outro_method) {
20132 block.chunks.update.push(b `
20133 if (${branch.condition}) {
20134 ${enter}
20135 } else if (${name}) {
20136 @group_outros();
20137 @transition_out(${name}, 1, 1, () => {
20138 ${name} = null;
20139 });
20140 @check_outros();
20141 }
20142 `);
20143 }
20144 else {
20145 block.chunks.update.push(b `
20146 if (${branch.condition}) {
20147 ${enter}
20148 } else if (${name}) {
20149 ${name}.d(1);
20150 ${name} = null;
20151 }
20152 `);
20153 }
20154 }
20155 else if (dynamic) {
20156 block.chunks.update.push(b `
20157 if (${branch.condition}) ${name}.p(#ctx, #dirty);
20158 `);
20159 }
20160 if (if_exists_condition) {
20161 block.chunks.destroy.push(b `
20162 if (${if_exists_condition}) ${name}.d(${detaching});
20163 `);
20164 }
20165 else {
20166 block.chunks.destroy.push(b `
20167 ${name}.d(${detaching});
20168 `);
20169 }
20170 }
20171 get_initial_dirty_bit() {
20172 const _this = this;
20173 // TODO: context-overflow make it less gross
20174 const val = x `-1`;
20175 return {
20176 get type() {
20177 return _this.renderer.context_overflow ? 'ArrayExpression' : 'UnaryExpression';
20178 },
20179 // as [-1]
20180 elements: [val],
20181 // as -1
20182 operator: val.operator,
20183 prefix: val.prefix,
20184 argument: val.argument
20185 };
20186 }
20187}
20188
20189class KeyBlockWrapper extends Wrapper {
20190 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20191 super(renderer, block, parent, node);
20192 this.var = { type: 'Identifier', name: 'key_block' };
20193 this.cannot_use_innerhtml();
20194 this.not_static_content();
20195 this.dependencies = node.expression.dynamic_dependencies();
20196 if (this.dependencies.length) {
20197 block = block.child({
20198 comment: create_debugging_comment(node, renderer.component),
20199 name: renderer.component.get_unique_name('create_key_block'),
20200 type: 'key'
20201 });
20202 renderer.blocks.push(block);
20203 }
20204 this.block = block;
20205 this.fragment = new FragmentWrapper(renderer, this.block, node.children, this, strip_whitespace, next_sibling);
20206 }
20207 render(block, parent_node, parent_nodes) {
20208 if (this.dependencies.length === 0) {
20209 this.render_static_key(block, parent_node, parent_nodes);
20210 }
20211 else {
20212 this.render_dynamic_key(block, parent_node, parent_nodes);
20213 }
20214 }
20215 render_static_key(_block, parent_node, parent_nodes) {
20216 this.fragment.render(this.block, parent_node, parent_nodes);
20217 }
20218 render_dynamic_key(block, parent_node, parent_nodes) {
20219 this.fragment.render(this.block, null, x `#nodes`);
20220 const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
20221 const dynamic = this.block.has_update_method;
20222 const previous_key = block.get_unique_name('previous_key');
20223 const snippet = this.node.expression.manipulate(block);
20224 block.add_variable(previous_key, snippet);
20225 const not_equal = this.renderer.component.component_options.immutable ? x `@not_equal` : x `@safe_not_equal`;
20226 const condition = x `${this.renderer.dirty(this.dependencies)} && ${not_equal}(${previous_key}, ${previous_key} = ${snippet})`;
20227 block.chunks.init.push(b `
20228 let ${this.var} = ${this.block.name}(#ctx);
20229 `);
20230 block.chunks.create.push(b `${this.var}.c();`);
20231 if (this.renderer.options.hydratable) {
20232 block.chunks.claim.push(b `${this.var}.l(${parent_nodes});`);
20233 }
20234 block.chunks.mount.push(b `${this.var}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});`);
20235 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
20236 const body = b `
20237 ${has_transitions
20238 ? b `
20239 @group_outros();
20240 @transition_out(${this.var}, 1, 1, @noop);
20241 @check_outros();
20242 `
20243 : b `${this.var}.d(1);`}
20244 ${this.var} = ${this.block.name}(#ctx);
20245 ${this.var}.c();
20246 ${has_transitions && b `@transition_in(${this.var})`}
20247 ${this.var}.m(${this.get_update_mount_node(anchor)}, ${anchor});
20248 `;
20249 if (dynamic) {
20250 block.chunks.update.push(b `
20251 if (${condition}) {
20252 ${body}
20253 } else {
20254 ${this.var}.p(#ctx, #dirty);
20255 }
20256 `);
20257 }
20258 else {
20259 block.chunks.update.push(b `
20260 if (${condition}) {
20261 ${body}
20262 }
20263 `);
20264 }
20265 if (has_transitions) {
20266 block.chunks.intro.push(b `@transition_in(${this.var})`);
20267 block.chunks.outro.push(b `@transition_out(${this.var})`);
20268 }
20269 block.chunks.destroy.push(b `${this.var}.d(detaching)`);
20270 }
20271}
20272
20273function string_to_member_expression(name) {
20274 const parts = name.split('.');
20275 let node = {
20276 type: 'Identifier',
20277 name: parts[0]
20278 };
20279 for (let i = 1; i < parts.length; i++) {
20280 node = {
20281 type: 'MemberExpression',
20282 object: node,
20283 property: { type: 'Identifier', name: parts[i] }
20284 };
20285 }
20286 return node;
20287}
20288
20289class InlineComponentWrapper extends Wrapper {
20290 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20291 super(renderer, block, parent, node);
20292 this.slots = new Map();
20293 this.cannot_use_innerhtml();
20294 this.not_static_content();
20295 if (this.node.expression) {
20296 block.add_dependencies(this.node.expression.dependencies);
20297 }
20298 this.node.attributes.forEach(attr => {
20299 block.add_dependencies(attr.dependencies);
20300 });
20301 this.node.bindings.forEach(binding => {
20302 if (binding.is_contextual) {
20303 mark_each_block_bindings(this, binding);
20304 }
20305 block.add_dependencies(binding.expression.dependencies);
20306 });
20307 this.node.handlers.forEach(handler => {
20308 if (handler.expression) {
20309 block.add_dependencies(handler.expression.dependencies);
20310 }
20311 });
20312 this.var = {
20313 type: 'Identifier',
20314 name: (this.node.name === 'svelte:self' ? renderer.component.name.name :
20315 this.node.name === 'svelte:component' ? 'switch_instance' :
20316 sanitize(this.node.name)).toLowerCase()
20317 };
20318 if (this.node.children.length) {
20319 this.node.lets.forEach(l => {
20320 extract_names(l.value || l.name).forEach(name => {
20321 renderer.add_to_context(name, true);
20322 });
20323 });
20324 const default_slot = block.child({
20325 comment: create_debugging_comment(node, renderer.component),
20326 name: renderer.component.get_unique_name('create_default_slot'),
20327 type: 'slot'
20328 });
20329 this.renderer.blocks.push(default_slot);
20330 this.slots.set('default', get_slot_definition(default_slot, this.node.scope, this.node.lets));
20331 this.fragment = new FragmentWrapper(renderer, default_slot, node.children, this, strip_whitespace, next_sibling);
20332 const dependencies = new Set();
20333 // TODO is this filtering necessary? (I *think* so)
20334 default_slot.dependencies.forEach(name => {
20335 if (!this.node.scope.is_let(name)) {
20336 dependencies.add(name);
20337 }
20338 });
20339 block.add_dependencies(dependencies);
20340 }
20341 block.add_outro();
20342 }
20343 warn_if_reactive() {
20344 const { name } = this.node;
20345 const variable = this.renderer.component.var_lookup.get(name);
20346 if (!variable) {
20347 return;
20348 }
20349 if (variable.reassigned || variable.export_name || variable.is_reactive_dependency) {
20350 this.renderer.component.warn(this.node, {
20351 code: 'reactive-component',
20352 message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`
20353 });
20354 }
20355 }
20356 render(block, parent_node, parent_nodes) {
20357 this.warn_if_reactive();
20358 const { renderer } = this;
20359 const { component } = renderer;
20360 const name = this.var;
20361 block.add_variable(name);
20362 const component_opts = x `{}`;
20363 const statements = [];
20364 const updates = [];
20365 if (this.fragment) {
20366 this.renderer.add_to_context('$$scope', true);
20367 const default_slot = this.slots.get('default');
20368 this.fragment.nodes.forEach((child) => {
20369 child.render(default_slot.block, null, x `#nodes`);
20370 });
20371 }
20372 let props;
20373 const name_changes = block.get_unique_name(`${name.name}_changes`);
20374 const uses_spread = !!this.node.attributes.find(a => a.is_spread);
20375 // removing empty slot
20376 for (const slot of this.slots.keys()) {
20377 if (!this.slots.get(slot).block.has_content()) {
20378 this.renderer.remove_block(this.slots.get(slot).block);
20379 this.slots.delete(slot);
20380 }
20381 }
20382 const initial_props = this.slots.size > 0
20383 ? [
20384 p `$$slots: {
20385 ${Array.from(this.slots).map(([name, slot]) => {
20386 return p `${name}: [${slot.block.name}, ${slot.get_context || null}, ${slot.get_changes || null}]`;
20387 })}
20388 }`,
20389 p `$$scope: {
20390 ctx: #ctx
20391 }`
20392 ]
20393 : [];
20394 const attribute_object = uses_spread
20395 ? x `{ ${initial_props} }`
20396 : x `{
20397 ${this.node.attributes.map(attr => p `${attr.name}: ${attr.get_value(block)}`)},
20398 ${initial_props}
20399 }`;
20400 if (this.node.attributes.length || this.node.bindings.length || initial_props.length) {
20401 if (!uses_spread && this.node.bindings.length === 0) {
20402 component_opts.properties.push(p `props: ${attribute_object}`);
20403 }
20404 else {
20405 props = block.get_unique_name(`${name.name}_props`);
20406 component_opts.properties.push(p `props: ${props}`);
20407 }
20408 }
20409 if (component.compile_options.dev) {
20410 // TODO this is a terrible hack, but without it the component
20411 // will complain that options.target is missing. This would
20412 // work better if components had separate public and private
20413 // APIs
20414 component_opts.properties.push(p `$$inline: true`);
20415 }
20416 const fragment_dependencies = new Set(this.fragment ? ['$$scope'] : []);
20417 this.slots.forEach(slot => {
20418 slot.block.dependencies.forEach(name => {
20419 const is_let = slot.scope.is_let(name);
20420 const variable = renderer.component.var_lookup.get(name);
20421 if (is_let || is_dynamic$1(variable))
20422 fragment_dependencies.add(name);
20423 });
20424 });
20425 const dynamic_attributes = this.node.attributes.filter(a => a.get_dependencies().length > 0);
20426 if (!uses_spread && (dynamic_attributes.length > 0 || this.node.bindings.length > 0 || fragment_dependencies.size > 0)) {
20427 updates.push(b `const ${name_changes} = {};`);
20428 }
20429 if (this.node.attributes.length) {
20430 if (uses_spread) {
20431 const levels = block.get_unique_name(`${this.var.name}_spread_levels`);
20432 const initial_props = [];
20433 const changes = [];
20434 const all_dependencies = new Set();
20435 this.node.attributes.forEach(attr => {
20436 add_to_set(all_dependencies, attr.dependencies);
20437 });
20438 this.node.attributes.forEach((attr, i) => {
20439 const { name, dependencies } = attr;
20440 const condition = dependencies.size > 0 && (dependencies.size !== all_dependencies.size)
20441 ? renderer.dirty(Array.from(dependencies))
20442 : null;
20443 const unchanged = dependencies.size === 0;
20444 let change_object;
20445 if (attr.is_spread) {
20446 const value = attr.expression.manipulate(block);
20447 initial_props.push(value);
20448 let value_object = value;
20449 if (attr.expression.node.type !== 'ObjectExpression') {
20450 value_object = x `@get_spread_object(${value})`;
20451 }
20452 change_object = value_object;
20453 }
20454 else {
20455 const obj = x `{ ${name}: ${attr.get_value(block)} }`;
20456 initial_props.push(obj);
20457 change_object = obj;
20458 }
20459 changes.push(unchanged
20460 ? x `${levels}[${i}]`
20461 : condition
20462 ? x `${condition} && ${change_object}`
20463 : change_object);
20464 });
20465 block.chunks.init.push(b `
20466 const ${levels} = [
20467 ${initial_props}
20468 ];
20469 `);
20470 statements.push(b `
20471 for (let #i = 0; #i < ${levels}.length; #i += 1) {
20472 ${props} = @assign(${props}, ${levels}[#i]);
20473 }
20474 `);
20475 if (all_dependencies.size) {
20476 const condition = renderer.dirty(Array.from(all_dependencies));
20477 updates.push(b `
20478 const ${name_changes} = ${condition} ? @get_spread_update(${levels}, [
20479 ${changes}
20480 ]) : {}
20481 `);
20482 }
20483 else {
20484 updates.push(b `
20485 const ${name_changes} = {};
20486 `);
20487 }
20488 }
20489 else {
20490 dynamic_attributes.forEach((attribute) => {
20491 const dependencies = attribute.get_dependencies();
20492 if (dependencies.length > 0) {
20493 const condition = renderer.dirty(dependencies);
20494 updates.push(b `
20495 if (${condition}) ${name_changes}.${attribute.name} = ${attribute.get_value(block)};
20496 `);
20497 }
20498 });
20499 }
20500 }
20501 if (fragment_dependencies.size > 0) {
20502 updates.push(b `
20503 if (${renderer.dirty(Array.from(fragment_dependencies))}) {
20504 ${name_changes}.$$scope = { dirty: #dirty, ctx: #ctx };
20505 }`);
20506 }
20507 const munged_bindings = this.node.bindings.map(binding => {
20508 component.has_reactive_assignments = true;
20509 if (binding.name === 'this') {
20510 return bind_this(component, block, new BindingWrapper(block, binding, this), this.var);
20511 }
20512 const id = component.get_unique_name(`${this.var.name}_${binding.name}_binding`);
20513 renderer.add_to_context(id.name);
20514 const callee = renderer.reference(id);
20515 const updating = block.get_unique_name(`updating_${binding.name}`);
20516 block.add_variable(updating);
20517 const snippet = binding.expression.manipulate(block);
20518 statements.push(b `
20519 if (${snippet} !== void 0) {
20520 ${props}.${binding.name} = ${snippet};
20521 }`);
20522 updates.push(b `
20523 if (!${updating} && ${renderer.dirty(Array.from(binding.expression.dependencies))}) {
20524 ${updating} = true;
20525 ${name_changes}.${binding.name} = ${snippet};
20526 @add_flush_callback(() => ${updating} = false);
20527 }
20528 `);
20529 const contextual_dependencies = Array.from(binding.expression.contextual_dependencies);
20530 const dependencies = Array.from(binding.expression.dependencies);
20531 let lhs = binding.raw_expression;
20532 if (binding.is_contextual && binding.expression.node.type === 'Identifier') {
20533 // bind:x={y} — we can't just do `y = x`, we need to
20534 // to `array[index] = x;
20535 const { name } = binding.expression.node;
20536 const { object, property, snippet } = block.bindings.get(name);
20537 lhs = snippet;
20538 contextual_dependencies.push(object.name, property.name);
20539 }
20540 const params = [x `#value`];
20541 if (contextual_dependencies.length > 0) {
20542 const args = [];
20543 contextual_dependencies.forEach(name => {
20544 params.push({
20545 type: 'Identifier',
20546 name
20547 });
20548 renderer.add_to_context(name, true);
20549 args.push(renderer.reference(name));
20550 });
20551 block.chunks.init.push(b `
20552 function ${id}(#value) {
20553 ${callee}.call(null, #value, ${args});
20554 }
20555 `);
20556 block.maintain_context = true; // TODO put this somewhere more logical
20557 }
20558 else {
20559 block.chunks.init.push(b `
20560 function ${id}(#value) {
20561 ${callee}.call(null, #value);
20562 }
20563 `);
20564 }
20565 const body = b `
20566 function ${id}(${params}) {
20567 ${lhs} = #value;
20568 ${renderer.invalidate(dependencies[0])};
20569 }
20570 `;
20571 component.partly_hoisted.push(body);
20572 return b `@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
20573 });
20574 const munged_handlers = this.node.handlers.map(handler => {
20575 const event_handler = new EventHandlerWrapper(handler, this);
20576 let snippet = event_handler.get_snippet(block);
20577 if (handler.modifiers.has('once'))
20578 snippet = x `@once(${snippet})`;
20579 return b `${name}.$on("${handler.name}", ${snippet});`;
20580 });
20581 if (this.node.name === 'svelte:component') {
20582 const switch_value = block.get_unique_name('switch_value');
20583 const switch_props = block.get_unique_name('switch_props');
20584 const snippet = this.node.expression.manipulate(block);
20585 block.chunks.init.push(b `
20586 var ${switch_value} = ${snippet};
20587
20588 function ${switch_props}(#ctx) {
20589 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
20590 ${props && b `let ${props} = ${attribute_object};`}`}
20591 ${statements}
20592 return ${component_opts};
20593 }
20594
20595 if (${switch_value}) {
20596 ${name} = new ${switch_value}(${switch_props}(#ctx));
20597
20598 ${munged_bindings}
20599 ${munged_handlers}
20600 }
20601 `);
20602 block.chunks.create.push(b `if (${name}) @create_component(${name}.$$.fragment);`);
20603 if (parent_nodes && this.renderer.options.hydratable) {
20604 block.chunks.claim.push(b `if (${name}) @claim_component(${name}.$$.fragment, ${parent_nodes});`);
20605 }
20606 block.chunks.mount.push(b `
20607 if (${name}) {
20608 @mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20609 }
20610 `);
20611 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
20612 const update_mount_node = this.get_update_mount_node(anchor);
20613 if (updates.length) {
20614 block.chunks.update.push(b `
20615 ${updates}
20616 `);
20617 }
20618 block.chunks.update.push(b `
20619 if (${switch_value} !== (${switch_value} = ${snippet})) {
20620 if (${name}) {
20621 @group_outros();
20622 const old_component = ${name};
20623 @transition_out(old_component.$$.fragment, 1, 0, () => {
20624 @destroy_component(old_component, 1);
20625 });
20626 @check_outros();
20627 }
20628
20629 if (${switch_value}) {
20630 ${name} = new ${switch_value}(${switch_props}(#ctx));
20631
20632 ${munged_bindings}
20633 ${munged_handlers}
20634
20635 @create_component(${name}.$$.fragment);
20636 @transition_in(${name}.$$.fragment, 1);
20637 @mount_component(${name}, ${update_mount_node}, ${anchor});
20638 } else {
20639 ${name} = null;
20640 }
20641 } else if (${switch_value}) {
20642 ${updates.length > 0 && b `${name}.$set(${name_changes});`}
20643 }
20644 `);
20645 block.chunks.intro.push(b `
20646 if (${name}) @transition_in(${name}.$$.fragment, #local);
20647 `);
20648 block.chunks.outro.push(b `if (${name}) @transition_out(${name}.$$.fragment, #local);`);
20649 block.chunks.destroy.push(b `if (${name}) @destroy_component(${name}, ${parent_node ? null : 'detaching'});`);
20650 }
20651 else {
20652 const expression = this.node.name === 'svelte:self'
20653 ? component.name
20654 : this.renderer.reference(string_to_member_expression(this.node.name));
20655 block.chunks.init.push(b `
20656 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
20657 ${props && b `let ${props} = ${attribute_object};`}`}
20658 ${statements}
20659 ${name} = new ${expression}(${component_opts});
20660
20661 ${munged_bindings}
20662 ${munged_handlers}
20663 `);
20664 block.chunks.create.push(b `@create_component(${name}.$$.fragment);`);
20665 if (parent_nodes && this.renderer.options.hydratable) {
20666 block.chunks.claim.push(b `@claim_component(${name}.$$.fragment, ${parent_nodes});`);
20667 }
20668 block.chunks.mount.push(b `@mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});`);
20669 block.chunks.intro.push(b `
20670 @transition_in(${name}.$$.fragment, #local);
20671 `);
20672 if (updates.length) {
20673 block.chunks.update.push(b `
20674 ${updates}
20675 ${name}.$set(${name_changes});
20676 `);
20677 }
20678 block.chunks.destroy.push(b `
20679 @destroy_component(${name}, ${parent_node ? null : 'detaching'});
20680 `);
20681 block.chunks.outro.push(b `@transition_out(${name}.$$.fragment, #local);`);
20682 }
20683 }
20684}
20685
20686function get_slot_data(values, block = null) {
20687 return {
20688 type: 'ObjectExpression',
20689 properties: Array.from(values.values())
20690 .filter(attribute => attribute.name !== 'name')
20691 .map(attribute => {
20692 if (attribute.is_spread) {
20693 const argument = get_spread_value(block, attribute);
20694 return {
20695 type: 'SpreadElement',
20696 argument
20697 };
20698 }
20699 const value = get_value(block, attribute);
20700 return p `${attribute.name}: ${value}`;
20701 })
20702 };
20703}
20704function get_value(block, attribute) {
20705 if (attribute.is_true)
20706 return x `true`;
20707 if (attribute.chunks.length === 0)
20708 return x `""`;
20709 let value = attribute.chunks
20710 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : (block ? chunk.manipulate(block) : chunk.node))
20711 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20712 if (attribute.chunks.length > 1 && attribute.chunks[0].type !== 'Text') {
20713 value = x `"" + ${value}`;
20714 }
20715 return value;
20716}
20717function get_spread_value(block, attribute) {
20718 return block ? attribute.expression.manipulate(block) : attribute.expression.node;
20719}
20720
20721class SlotWrapper extends Wrapper {
20722 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20723 super(renderer, block, parent, node);
20724 this.fallback = null;
20725 this.var = { type: 'Identifier', name: 'slot' };
20726 this.dependencies = new Set(['$$scope']);
20727 this.cannot_use_innerhtml();
20728 this.not_static_content();
20729 if (this.node.children.length) {
20730 this.fallback = block.child({
20731 comment: create_debugging_comment(this.node.children[0], this.renderer.component),
20732 name: this.renderer.component.get_unique_name('fallback_block'),
20733 type: 'fallback'
20734 });
20735 renderer.blocks.push(this.fallback);
20736 }
20737 if (this.node.values.has('slot')) {
20738 block = create_slot_block(this.node.values.get('slot'), this, block);
20739 }
20740 this.fragment = new FragmentWrapper(renderer, this.fallback, node.children, this, strip_whitespace, next_sibling);
20741 this.node.values.forEach(attribute => {
20742 add_to_set(this.dependencies, attribute.dependencies);
20743 });
20744 block.add_dependencies(this.dependencies);
20745 // we have to do this, just in case
20746 block.add_intro();
20747 block.add_outro();
20748 }
20749 render(block, parent_node, parent_nodes) {
20750 const { renderer } = this;
20751 const { slot_name } = this.node;
20752 if (this.slot_block) {
20753 block = this.slot_block;
20754 }
20755 let get_slot_changes_fn;
20756 let get_slot_spread_changes_fn;
20757 let get_slot_context_fn;
20758 if (this.node.values.size > 0) {
20759 get_slot_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_changes`);
20760 get_slot_context_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_context`);
20761 const changes = x `{}`;
20762 const spread_dynamic_dependencies = new Set();
20763 this.node.values.forEach(attribute => {
20764 if (attribute.type === 'Spread') {
20765 add_to_set(spread_dynamic_dependencies, Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name)));
20766 }
20767 else {
20768 const dynamic_dependencies = Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name));
20769 if (dynamic_dependencies.length > 0) {
20770 changes.properties.push(p `${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`);
20771 }
20772 }
20773 });
20774 renderer.blocks.push(b `
20775 const ${get_slot_changes_fn} = #dirty => ${changes};
20776 const ${get_slot_context_fn} = #ctx => ${get_slot_data(this.node.values, block)};
20777 `);
20778 if (spread_dynamic_dependencies.size) {
20779 get_slot_spread_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_spread_changes`);
20780 renderer.blocks.push(b `
20781 const ${get_slot_spread_changes_fn} = #dirty => ${renderer.dirty(Array.from(spread_dynamic_dependencies))} > 0 ? -1 : 0;
20782 `);
20783 }
20784 }
20785 else {
20786 get_slot_changes_fn = 'null';
20787 get_slot_context_fn = 'null';
20788 }
20789 let has_fallback = !!this.fallback;
20790 if (this.fallback) {
20791 this.fragment.render(this.fallback, null, x `#nodes`);
20792 has_fallback = this.fallback.has_content();
20793 if (!has_fallback) {
20794 renderer.remove_block(this.fallback);
20795 }
20796 }
20797 const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`);
20798 const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
20799 const slot_or_fallback = has_fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot;
20800 block.chunks.init.push(b `
20801 const ${slot_definition} = ${renderer.reference('#slots')}.${slot_name};
20802 const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn});
20803 ${has_fallback ? b `const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
20804 `);
20805 block.chunks.create.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.c();`);
20806 if (renderer.options.hydratable) {
20807 block.chunks.claim.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});`);
20808 }
20809 block.chunks.mount.push(b `
20810 if (${slot_or_fallback}) {
20811 ${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20812 }
20813 `);
20814 block.chunks.intro.push(b `@transition_in(${slot_or_fallback}, #local);`);
20815 block.chunks.outro.push(b `@transition_out(${slot_or_fallback}, #local);`);
20816 const dynamic_dependencies = Array.from(this.dependencies).filter((name) => this.is_dependency_dynamic(name));
20817 const fallback_dynamic_dependencies = has_fallback
20818 ? Array.from(this.fallback.dependencies).filter((name) => this.is_dependency_dynamic(name))
20819 : [];
20820 const slot_update = get_slot_spread_changes_fn ? b `
20821 if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
20822 @update_slot_spread(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_spread_changes_fn}, ${get_slot_context_fn});
20823 }
20824 ` : b `
20825 if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
20826 @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn});
20827 }
20828 `;
20829 const fallback_update = has_fallback && fallback_dynamic_dependencies.length > 0 && b `
20830 if (${slot_or_fallback} && ${slot_or_fallback}.p && ${renderer.dirty(fallback_dynamic_dependencies)}) {
20831 ${slot_or_fallback}.p(#ctx, #dirty);
20832 }
20833 `;
20834 if (fallback_update) {
20835 block.chunks.update.push(b `
20836 if (${slot}) {
20837 ${slot_update}
20838 } else {
20839 ${fallback_update}
20840 }
20841 `);
20842 }
20843 else {
20844 block.chunks.update.push(b `
20845 if (${slot}) {
20846 ${slot_update}
20847 }
20848 `);
20849 }
20850 block.chunks.destroy.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`);
20851 }
20852 is_dependency_dynamic(name) {
20853 if (name === '$$scope')
20854 return true;
20855 if (this.node.scope.is_let(name))
20856 return true;
20857 if (is_reserved_keyword(name))
20858 return true;
20859 const variable = this.renderer.component.var_lookup.get(name);
20860 return is_dynamic$1(variable);
20861 }
20862}
20863
20864class TitleWrapper extends Wrapper {
20865 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
20866 super(renderer, block, parent, node);
20867 }
20868 render(block, _parent_node, _parent_nodes) {
20869 const is_dynamic = !!this.node.children.find(node => node.type !== 'Text');
20870 if (is_dynamic) {
20871 let value;
20872 const all_dependencies = new Set();
20873 // TODO some of this code is repeated in Tag.ts — would be good to
20874 // DRY it out if that's possible without introducing crazy indirection
20875 if (this.node.children.length === 1) {
20876 // single {tag} — may be a non-string
20877 // @ts-ignore todo: check this
20878 const { expression } = this.node.children[0];
20879 value = expression.manipulate(block);
20880 add_to_set(all_dependencies, expression.dependencies);
20881 }
20882 else {
20883 // '{foo} {bar}' — treat as string concatenation
20884 value = this.node.children
20885 .map(chunk => {
20886 if (chunk.type === 'Text')
20887 return string_literal(chunk.data);
20888 chunk.expression.dependencies.forEach(d => {
20889 all_dependencies.add(d);
20890 });
20891 return chunk.expression.manipulate(block);
20892 })
20893 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20894 if (this.node.children[0].type !== 'Text') {
20895 value = x `"" + ${value}`;
20896 }
20897 }
20898 const last = this.node.should_cache && block.get_unique_name('title_value');
20899 if (this.node.should_cache)
20900 block.add_variable(last);
20901 const init = this.node.should_cache ? x `${last} = ${value}` : value;
20902 block.chunks.init.push(b `@_document.title = ${init};`);
20903 const updater = b `@_document.title = ${this.node.should_cache ? last : value};`;
20904 if (all_dependencies.size) {
20905 const dependencies = Array.from(all_dependencies);
20906 let condition = block.renderer.dirty(dependencies);
20907 if (block.has_outros) {
20908 condition = x `!#current || ${condition}`;
20909 }
20910 if (this.node.should_cache) {
20911 condition = x `${condition} && (${last} !== (${last} = ${value}))`;
20912 }
20913 block.chunks.update.push(b `
20914 if (${condition}) {
20915 ${updater}
20916 }`);
20917 }
20918 }
20919 else {
20920 const value = this.node.children.length > 0
20921 ? string_literal(this.node.children[0].data)
20922 : x `""`;
20923 block.chunks.hydrate.push(b `@_document.title = ${value};`);
20924 }
20925 }
20926}
20927
20928const associated_events = {
20929 innerWidth: 'resize',
20930 innerHeight: 'resize',
20931 outerWidth: 'resize',
20932 outerHeight: 'resize',
20933 scrollX: 'scroll',
20934 scrollY: 'scroll'
20935};
20936const properties = {
20937 scrollX: 'pageXOffset',
20938 scrollY: 'pageYOffset'
20939};
20940const readonly = new Set([
20941 'innerWidth',
20942 'innerHeight',
20943 'outerWidth',
20944 'outerHeight',
20945 'online'
20946]);
20947class WindowWrapper extends Wrapper {
20948 constructor(renderer, block, parent, node) {
20949 super(renderer, block, parent, node);
20950 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
20951 }
20952 render(block, _parent_node, _parent_nodes) {
20953 const { renderer } = this;
20954 const { component } = renderer;
20955 const events = {};
20956 const bindings = {};
20957 add_actions(block, '@_window', this.node.actions);
20958 add_event_handlers(block, '@_window', this.handlers);
20959 this.node.bindings.forEach(binding => {
20960 // TODO: what if it's a MemberExpression?
20961 const binding_name = binding.expression.node.name;
20962 // in dev mode, throw if read-only values are written to
20963 if (readonly.has(binding.name)) {
20964 renderer.readonly.add(binding_name);
20965 }
20966 bindings[binding.name] = binding_name;
20967 // bind:online is a special case, we need to listen for two separate events
20968 if (binding.name === 'online')
20969 return;
20970 const associated_event = associated_events[binding.name];
20971 const property = properties[binding.name] || binding.name;
20972 if (!events[associated_event])
20973 events[associated_event] = [];
20974 events[associated_event].push({
20975 name: binding_name,
20976 value: property
20977 });
20978 });
20979 const scrolling = block.get_unique_name('scrolling');
20980 const clear_scrolling = block.get_unique_name('clear_scrolling');
20981 const scrolling_timeout = block.get_unique_name('scrolling_timeout');
20982 Object.keys(events).forEach(event => {
20983 const id = block.get_unique_name(`onwindow${event}`);
20984 const props = events[event];
20985 renderer.add_to_context(id.name);
20986 const fn = renderer.reference(id.name);
20987 if (event === 'scroll') {
20988 // TODO other bidirectional bindings...
20989 block.add_variable(scrolling, x `false`);
20990 block.add_variable(clear_scrolling, x `() => { ${scrolling} = false }`);
20991 block.add_variable(scrolling_timeout);
20992 const condition = bindings.scrollX && bindings.scrollY
20993 ? x `"${bindings.scrollX}" in this._state || "${bindings.scrollY}" in this._state`
20994 : x `"${bindings.scrollX || bindings.scrollY}" in this._state`;
20995 const scrollX = bindings.scrollX && x `this._state.${bindings.scrollX}`;
20996 const scrollY = bindings.scrollY && x `this._state.${bindings.scrollY}`;
20997 renderer.meta_bindings.push(b `
20998 if (${condition}) {
20999 @_scrollTo(${scrollX || '@_window.pageXOffset'}, ${scrollY || '@_window.pageYOffset'});
21000 }
21001 ${scrollX && `${scrollX} = @_window.pageXOffset;`}
21002 ${scrollY && `${scrollY} = @_window.pageYOffset;`}
21003 `);
21004 block.event_listeners.push(x `
21005 @listen(@_window, "${event}", () => {
21006 ${scrolling} = true;
21007 @_clearTimeout(${scrolling_timeout});
21008 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
21009 ${fn}();
21010 })
21011 `);
21012 }
21013 else {
21014 props.forEach(prop => {
21015 renderer.meta_bindings.push(b `this._state.${prop.name} = @_window.${prop.value};`);
21016 });
21017 block.event_listeners.push(x `
21018 @listen(@_window, "${event}", ${fn})
21019 `);
21020 }
21021 component.partly_hoisted.push(b `
21022 function ${id}() {
21023 ${props.map(prop => renderer.invalidate(prop.name, x `${prop.name} = @_window.${prop.value}`))}
21024 }
21025 `);
21026 block.chunks.init.push(b `
21027 @add_render_callback(${fn});
21028 `);
21029 component.has_reactive_assignments = true;
21030 });
21031 // special case... might need to abstract this out if we add more special cases
21032 if (bindings.scrollX || bindings.scrollY) {
21033 const condition = renderer.dirty([bindings.scrollX, bindings.scrollY].filter(Boolean));
21034 const scrollX = bindings.scrollX ? renderer.reference(bindings.scrollX) : x `@_window.pageXOffset`;
21035 const scrollY = bindings.scrollY ? renderer.reference(bindings.scrollY) : x `@_window.pageYOffset`;
21036 block.chunks.update.push(b `
21037 if (${condition} && !${scrolling}) {
21038 ${scrolling} = true;
21039 @_clearTimeout(${scrolling_timeout});
21040 @_scrollTo(${scrollX}, ${scrollY});
21041 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
21042 }
21043 `);
21044 }
21045 // another special case. (I'm starting to think these are all special cases.)
21046 if (bindings.online) {
21047 const id = block.get_unique_name('onlinestatuschanged');
21048 const name = bindings.online;
21049 renderer.add_to_context(id.name);
21050 const reference = renderer.reference(id.name);
21051 component.partly_hoisted.push(b `
21052 function ${id}() {
21053 ${renderer.invalidate(name, x `${name} = @_navigator.onLine`)}
21054 }
21055 `);
21056 block.chunks.init.push(b `
21057 @add_render_callback(${reference});
21058 `);
21059 block.event_listeners.push(x `@listen(@_window, "online", ${reference})`, x `@listen(@_window, "offline", ${reference})`);
21060 component.has_reactive_assignments = true;
21061 }
21062 }
21063}
21064
21065function link(next, prev) {
21066 prev.next = next;
21067 if (next)
21068 next.prev = prev;
21069}
21070
21071const wrappers = {
21072 AwaitBlock: AwaitBlockWrapper,
21073 Body: BodyWrapper,
21074 Comment: null,
21075 DebugTag: DebugTagWrapper,
21076 EachBlock: EachBlockWrapper,
21077 Element: ElementWrapper,
21078 Head: HeadWrapper,
21079 IfBlock: IfBlockWrapper,
21080 InlineComponent: InlineComponentWrapper,
21081 KeyBlock: KeyBlockWrapper,
21082 MustacheTag: MustacheTagWrapper,
21083 Options: null,
21084 RawMustacheTag: RawMustacheTagWrapper,
21085 Slot: SlotWrapper,
21086 Text: TextWrapper,
21087 Title: TitleWrapper,
21088 Window: WindowWrapper
21089};
21090function trimmable_at(child, next_sibling) {
21091 // Whitespace is trimmable if one of the following is true:
21092 // The child and its sibling share a common nearest each block (not at an each block boundary)
21093 // The next sibling's previous node is an each block
21094 return (next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/)) || next_sibling.node.prev.type === 'EachBlock';
21095}
21096class FragmentWrapper {
21097 constructor(renderer, block, nodes, parent, strip_whitespace, next_sibling) {
21098 this.nodes = [];
21099 let last_child;
21100 let window_wrapper;
21101 let i = nodes.length;
21102 while (i--) {
21103 const child = nodes[i];
21104 if (!child.type) {
21105 throw new Error('missing type');
21106 }
21107 if (!(child.type in wrappers)) {
21108 throw new Error(`TODO implement ${child.type}`);
21109 }
21110 // special case — this is an easy way to remove whitespace surrounding
21111 // <svelte:window/>. lil hacky but it works
21112 if (child.type === 'Window') {
21113 window_wrapper = new WindowWrapper(renderer, block, parent, child);
21114 continue;
21115 }
21116 if (child.type === 'Text') {
21117 let { data } = child;
21118 // We want to remove trailing whitespace inside an element/component/block,
21119 // *unless* there is no whitespace between this node and its next sibling
21120 if (this.nodes.length === 0) {
21121 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'));
21122 if (should_trim) {
21123 data = trim_end(data);
21124 if (!data)
21125 continue;
21126 }
21127 }
21128 // glue text nodes (which could e.g. be separated by comments) together
21129 if (last_child && last_child.node.type === 'Text') {
21130 last_child.data = data + last_child.data;
21131 continue;
21132 }
21133 const wrapper = new TextWrapper(renderer, block, parent, child, data);
21134 if (wrapper.skip)
21135 continue;
21136 this.nodes.unshift(wrapper);
21137 link(last_child, last_child = wrapper);
21138 }
21139 else {
21140 const Wrapper = wrappers[child.type];
21141 if (!Wrapper)
21142 continue;
21143 const wrapper = new Wrapper(renderer, block, parent, child, strip_whitespace, last_child || next_sibling);
21144 this.nodes.unshift(wrapper);
21145 link(last_child, last_child = wrapper);
21146 }
21147 }
21148 if (strip_whitespace) {
21149 const first = this.nodes[0];
21150 if (first && first.node.type === 'Text') {
21151 first.data = trim_start(first.data);
21152 if (!first.data) {
21153 first.var = null;
21154 this.nodes.shift();
21155 if (this.nodes[0]) {
21156 this.nodes[0].prev = null;
21157 }
21158 }
21159 }
21160 }
21161 if (window_wrapper) {
21162 this.nodes.unshift(window_wrapper);
21163 link(last_child, window_wrapper);
21164 }
21165 }
21166 render(block, parent_node, parent_nodes) {
21167 for (let i = 0; i < this.nodes.length; i += 1) {
21168 this.nodes[i].render(block, parent_node, parent_nodes);
21169 }
21170 }
21171}
21172
21173class Renderer {
21174 constructor(component, options) {
21175 this.context = [];
21176 this.initial_context = [];
21177 this.context_lookup = new Map();
21178 this.blocks = [];
21179 this.readonly = new Set();
21180 this.meta_bindings = []; // initial values for e.g. window.innerWidth, if there's a <svelte:window> meta tag
21181 this.binding_groups = new Map();
21182 this.component = component;
21183 this.options = options;
21184 this.locate = component.locate; // TODO messy
21185 this.file_var = options.dev && this.component.get_unique_name('file');
21186 component.vars.filter(v => !v.hoistable || (v.export_name && !v.module)).forEach(v => this.add_to_context(v.name));
21187 // ensure store values are included in context
21188 component.vars.filter(v => v.subscribable).forEach(v => this.add_to_context(`$${v.name}`));
21189 reserved_keywords.forEach(keyword => {
21190 if (component.var_lookup.has(keyword)) {
21191 this.add_to_context(keyword);
21192 }
21193 });
21194 if (component.slots.size > 0) {
21195 this.add_to_context('$$scope');
21196 this.add_to_context('#slots');
21197 }
21198 if (this.binding_groups.size > 0) {
21199 this.add_to_context('$$binding_groups');
21200 }
21201 // main block
21202 this.block = new Block$1({
21203 renderer: this,
21204 name: null,
21205 type: 'component',
21206 key: null,
21207 bindings: new Map(),
21208 dependencies: new Set()
21209 });
21210 this.block.has_update_method = true;
21211 this.fragment = new FragmentWrapper(this, this.block, component.fragment.children, null, true, null);
21212 // TODO messy
21213 this.blocks.forEach(block => {
21214 if (block instanceof Block$1) {
21215 block.assign_variable_names();
21216 }
21217 });
21218 this.block.assign_variable_names();
21219 this.fragment.render(this.block, null, x `#nodes`);
21220 this.context_overflow = this.context.length > 31;
21221 this.context.forEach(member => {
21222 const { variable } = member;
21223 if (variable) {
21224 member.priority += 2;
21225 if (variable.mutated || variable.reassigned)
21226 member.priority += 4;
21227 // these determine whether variable is included in initial context
21228 // array, so must have the highest priority
21229 if (variable.is_reactive_dependency && (variable.mutated || variable.reassigned))
21230 member.priority += 16;
21231 if (variable.export_name)
21232 member.priority += 32;
21233 if (variable.referenced)
21234 member.priority += 64;
21235 }
21236 else if (member.is_non_contextual) {
21237 // determine whether variable is included in initial context
21238 // array, so must have the highest priority
21239 member.priority += 8;
21240 }
21241 if (!member.is_contextual) {
21242 member.priority += 1;
21243 }
21244 });
21245 this.context.sort((a, b) => (b.priority - a.priority) || (a.index.value - b.index.value));
21246 this.context.forEach((member, i) => member.index.value = i);
21247 let i = this.context.length;
21248 while (i--) {
21249 const member = this.context[i];
21250 if (member.variable) {
21251 if (member.variable.referenced || member.variable.export_name || (member.variable.is_reactive_dependency && (member.variable.mutated || member.variable.reassigned)))
21252 break;
21253 }
21254 else if (member.is_non_contextual) {
21255 break;
21256 }
21257 }
21258 this.initial_context = this.context.slice(0, i + 1);
21259 }
21260 add_to_context(name, contextual = false) {
21261 if (!this.context_lookup.has(name)) {
21262 const member = {
21263 name,
21264 index: { type: 'Literal', value: this.context.length },
21265 is_contextual: false,
21266 is_non_contextual: false,
21267 variable: null,
21268 priority: 0
21269 };
21270 this.context_lookup.set(name, member);
21271 this.context.push(member);
21272 }
21273 const member = this.context_lookup.get(name);
21274 if (contextual) {
21275 member.is_contextual = true;
21276 }
21277 else {
21278 member.is_non_contextual = true;
21279 member.variable = this.component.var_lookup.get(name);
21280 }
21281 return member;
21282 }
21283 invalidate(name, value, main_execution_context = false) {
21284 return renderer_invalidate(this, name, value, main_execution_context);
21285 }
21286 dirty(names, is_reactive_declaration = false) {
21287 const renderer = this;
21288 const dirty = (is_reactive_declaration
21289 ? x `$$self.$$.dirty`
21290 : x `#dirty`);
21291 const get_bitmask = () => {
21292 const bitmask = [];
21293 names.forEach((name) => {
21294 const member = renderer.context_lookup.get(name);
21295 if (!member)
21296 return;
21297 if (member.index.value === -1) {
21298 throw new Error('unset index');
21299 }
21300 const value = member.index.value;
21301 const i = (value / 31) | 0;
21302 const n = 1 << (value % 31);
21303 if (!bitmask[i])
21304 bitmask[i] = { n: 0, names: [] };
21305 bitmask[i].n |= n;
21306 bitmask[i].names.push(name);
21307 });
21308 return bitmask;
21309 };
21310 // TODO: context-overflow make it less gross
21311 return {
21312 // Using a ParenthesizedExpression allows us to create
21313 // the expression lazily. TODO would be better if
21314 // context was determined before rendering, so that
21315 // this indirection was unnecessary
21316 type: 'ParenthesizedExpression',
21317 get expression() {
21318 const bitmask = get_bitmask();
21319 if (!bitmask.length) {
21320 return x `${dirty} & /*${names.join(', ')}*/ 0`;
21321 }
21322 if (renderer.context_overflow) {
21323 return bitmask
21324 .map((b, i) => ({ b, i }))
21325 .filter(({ b }) => b)
21326 .map(({ b, i }) => x `${dirty}[${i}] & /*${b.names.join(', ')}*/ ${b.n}`)
21327 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
21328 }
21329 return x `${dirty} & /*${names.join(', ')}*/ ${bitmask[0].n}`;
21330 }
21331 };
21332 }
21333 reference(node) {
21334 if (typeof node === 'string') {
21335 node = { type: 'Identifier', name: node };
21336 }
21337 const { name, nodes } = flatten_reference(node);
21338 const member = this.context_lookup.get(name);
21339 // TODO is this correct?
21340 if (this.component.var_lookup.get(name)) {
21341 this.component.add_reference(name);
21342 }
21343 if (member !== undefined) {
21344 const replacement = x `/*${member.name}*/ #ctx[${member.index}]`;
21345 if (nodes[0].loc)
21346 replacement.object.loc = nodes[0].loc;
21347 nodes[0] = replacement;
21348 return nodes.reduce((lhs, rhs) => x `${lhs}.${rhs}`);
21349 }
21350 return node;
21351 }
21352 remove_block(block) {
21353 this.blocks.splice(this.blocks.indexOf(block), 1);
21354 }
21355}
21356
21357var charToInteger$1 = {};
21358var chars$1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
21359for (var i$2 = 0; i$2 < chars$1.length; i$2++) {
21360 charToInteger$1[chars$1.charCodeAt(i$2)] = i$2;
21361}
21362function decode$1(mappings) {
21363 var decoded = [];
21364 var line = [];
21365 var segment = [
21366 0,
21367 0,
21368 0,
21369 0,
21370 0,
21371 ];
21372 var j = 0;
21373 for (var i = 0, shift = 0, value = 0; i < mappings.length; i++) {
21374 var c = mappings.charCodeAt(i);
21375 if (c === 44) { // ","
21376 segmentify$1(line, segment, j);
21377 j = 0;
21378 }
21379 else if (c === 59) { // ";"
21380 segmentify$1(line, segment, j);
21381 j = 0;
21382 decoded.push(line);
21383 line = [];
21384 segment[0] = 0;
21385 }
21386 else {
21387 var integer = charToInteger$1[c];
21388 if (integer === undefined) {
21389 throw new Error('Invalid character (' + String.fromCharCode(c) + ')');
21390 }
21391 var hasContinuationBit = integer & 32;
21392 integer &= 31;
21393 value += integer << shift;
21394 if (hasContinuationBit) {
21395 shift += 5;
21396 }
21397 else {
21398 var shouldNegate = value & 1;
21399 value >>>= 1;
21400 if (shouldNegate) {
21401 value = value === 0 ? -0x80000000 : -value;
21402 }
21403 segment[j] += value;
21404 j++;
21405 value = shift = 0; // reset
21406 }
21407 }
21408 }
21409 segmentify$1(line, segment, j);
21410 decoded.push(line);
21411 return decoded;
21412}
21413function segmentify$1(line, segment, j) {
21414 // This looks ugly, but we're creating specialized arrays with a specific
21415 // length. This is much faster than creating a new array (which v8 expands to
21416 // a capacity of 17 after pushing the first item), or slicing out a subarray
21417 // (which is slow). Length 4 is assumed to be the most frequent, followed by
21418 // length 5 (since not everything will have an associated name), followed by
21419 // length 1 (it's probably rare for a source substring to not have an
21420 // associated segment data).
21421 if (j === 4)
21422 line.push([segment[0], segment[1], segment[2], segment[3]]);
21423 else if (j === 5)
21424 line.push([segment[0], segment[1], segment[2], segment[3], segment[4]]);
21425 else if (j === 1)
21426 line.push([segment[0]]);
21427}
21428function encode$1(decoded) {
21429 var sourceFileIndex = 0; // second field
21430 var sourceCodeLine = 0; // third field
21431 var sourceCodeColumn = 0; // fourth field
21432 var nameIndex = 0; // fifth field
21433 var mappings = '';
21434 for (var i = 0; i < decoded.length; i++) {
21435 var line = decoded[i];
21436 if (i > 0)
21437 mappings += ';';
21438 if (line.length === 0)
21439 continue;
21440 var generatedCodeColumn = 0; // first field
21441 var lineMappings = [];
21442 for (var _i = 0, line_1 = line; _i < line_1.length; _i++) {
21443 var segment = line_1[_i];
21444 var segmentMappings = encodeInteger$1(segment[0] - generatedCodeColumn);
21445 generatedCodeColumn = segment[0];
21446 if (segment.length > 1) {
21447 segmentMappings +=
21448 encodeInteger$1(segment[1] - sourceFileIndex) +
21449 encodeInteger$1(segment[2] - sourceCodeLine) +
21450 encodeInteger$1(segment[3] - sourceCodeColumn);
21451 sourceFileIndex = segment[1];
21452 sourceCodeLine = segment[2];
21453 sourceCodeColumn = segment[3];
21454 }
21455 if (segment.length === 5) {
21456 segmentMappings += encodeInteger$1(segment[4] - nameIndex);
21457 nameIndex = segment[4];
21458 }
21459 lineMappings.push(segmentMappings);
21460 }
21461 mappings += lineMappings.join(',');
21462 }
21463 return mappings;
21464}
21465function encodeInteger$1(num) {
21466 var result = '';
21467 num = num < 0 ? (-num << 1) | 1 : num << 1;
21468 do {
21469 var clamped = num & 31;
21470 num >>>= 5;
21471 if (num > 0) {
21472 clamped |= 32;
21473 }
21474 result += chars$1[clamped];
21475 } while (num > 0);
21476 return result;
21477}
21478
21479/**
21480 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21481 *
21482 * Licensed under the Apache License, Version 2.0 (the "License");
21483 * you may not use this file except in compliance with the License.
21484 * You may obtain a copy of the License at
21485 *
21486 * http://www.apache.org/licenses/LICENSE-2.0
21487 *
21488 * Unless required by applicable law or agreed to in writing, software
21489 * distributed under the License is distributed on an "AS IS" BASIS,
21490 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21491 * See the License for the specific language governing permissions and
21492 * limitations under the License.
21493 */
21494/**
21495 * Creates a brand new (prototype-less) object with the enumerable-own
21496 * properties of `target`. Any enumerable-own properties from `source` which
21497 * are not present on `target` will be copied as well.
21498 */
21499function defaults(target, source) {
21500 return Object.assign(Object.create(null), source, target);
21501}
21502
21503/**
21504 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21505 *
21506 * Licensed under the Apache License, Version 2.0 (the "License");
21507 * you may not use this file except in compliance with the License.
21508 * You may obtain a copy of the License at
21509 *
21510 * http://www.apache.org/licenses/LICENSE-2.0
21511 *
21512 * Unless required by applicable law or agreed to in writing, software
21513 * distributed under the License is distributed on an "AS IS" BASIS,
21514 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21515 * See the License for the specific language governing permissions and
21516 * limitations under the License.
21517 */
21518/**
21519 * Decodes an input sourcemap into a `DecodedSourceMap` sourcemap object.
21520 *
21521 * Valid input maps include a `DecodedSourceMap`, a `RawSourceMap`, or JSON
21522 * representations of either type.
21523 */
21524function decodeSourceMap(map) {
21525 if (typeof map === 'string') {
21526 map = JSON.parse(map);
21527 }
21528 let { mappings } = map;
21529 if (typeof mappings === 'string') {
21530 mappings = decode$1(mappings);
21531 }
21532 else {
21533 // Clone the Line so that we can sort it. We don't want to mutate an array
21534 // that we don't own directly.
21535 mappings = mappings.map(cloneSegmentLine);
21536 }
21537 // Sort each Line's segments. There's no guarantee that segments are sorted for us,
21538 // and even Chrome's implementation sorts:
21539 // https://cs.chromium.org/chromium/src/third_party/devtools-frontend/src/front_end/sdk/SourceMap.js?l=507-508&rcl=109232bcf479c8f4ef8ead3cf56c49eb25f8c2f0
21540 mappings.forEach(sortSegments);
21541 return defaults({ mappings }, map);
21542}
21543function cloneSegmentLine(segments) {
21544 return segments.slice();
21545}
21546function sortSegments(segments) {
21547 segments.sort(segmentComparator);
21548}
21549function segmentComparator(a, b) {
21550 return a[0] - b[0];
21551}
21552
21553/**
21554 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21555 *
21556 * Licensed under the Apache License, Version 2.0 (the "License");
21557 * you may not use this file except in compliance with the License.
21558 * You may obtain a copy of the License at
21559 *
21560 * http://www.apache.org/licenses/LICENSE-2.0
21561 *
21562 * Unless required by applicable law or agreed to in writing, software
21563 * distributed under the License is distributed on an "AS IS" BASIS,
21564 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21565 * See the License for the specific language governing permissions and
21566 * limitations under the License.
21567 */
21568/**
21569 * A "leaf" node in the sourcemap tree, representing an original, unmodified
21570 * source file. Recursive segment tracing ends at the `OriginalSource`.
21571 */
21572class OriginalSource {
21573 constructor(filename, content) {
21574 this.filename = filename;
21575 this.content = content;
21576 }
21577 /**
21578 * Tracing a `SourceMapSegment` ends when we get to an `OriginalSource`,
21579 * meaning this line/column location originated from this source file.
21580 */
21581 traceSegment(line, column, name) {
21582 return { column, line, name, source: this };
21583 }
21584}
21585
21586/* istanbul ignore next */
21587const Url$1 = (typeof URL !== 'undefined' ? URL : require('url').URL);
21588// Matches "..", which must be preceeded by "/" or the start of the string, and
21589// must be followed by a "/". We do not eat the following "/", so that the next
21590// iteration can match on it.
21591const parentRegex = /(^|\/)\.\.(?=\/|$)/g;
21592function isAbsoluteUrl(url) {
21593 try {
21594 return !!new Url$1(url);
21595 }
21596 catch (e) {
21597 return false;
21598 }
21599}
21600/**
21601 * Creates a directory name that is guaranteed to not be in `str`.
21602 */
21603function uniqInStr(str) {
21604 let uniq = String(Math.random()).slice(2);
21605 while (str.indexOf(uniq) > -1) {
21606 /* istanbul ignore next */
21607 uniq += uniq;
21608 }
21609 return uniq;
21610}
21611/**
21612 * Removes the filename from the path (everything trailing the last "/"). This
21613 * is only safe to call on a path, never call with an absolute or protocol
21614 * relative URL.
21615 */
21616function stripPathFilename(path) {
21617 path = normalizePath(path);
21618 const index = path.lastIndexOf('/');
21619 return path.slice(0, index + 1);
21620}
21621/**
21622 * Normalizes a protocol-relative URL, but keeps it protocol relative by
21623 * stripping out the protocl before returning it.
21624 */
21625function normalizeProtocolRelative(input, absoluteBase) {
21626 const { href, protocol } = new Url$1(input, absoluteBase);
21627 return href.slice(protocol.length);
21628}
21629/**
21630 * Normalizes a simple path (one that has no ".."s, or is absolute so ".."s can
21631 * be normalized absolutely).
21632 */
21633function normalizeSimplePath(input) {
21634 const { href } = new Url$1(input, 'https://foo.com/');
21635 return href.slice('https://foo.com/'.length);
21636}
21637/**
21638 * Normalizes a path, ensuring that excess ".."s are preserved for relative
21639 * paths in the output.
21640 *
21641 * If the input is absolute, this will return an absolutey normalized path, but
21642 * it will not have a leading "/".
21643 *
21644 * If the input has a leading "..", the output will have a leading "..".
21645 *
21646 * If the input has a leading ".", the output will not have a leading "."
21647 * unless there are too many ".."s, in which case there will be a leading "..".
21648 */
21649function normalizePath(input) {
21650 // If there are no ".."s, we can treat this as if it were an absolute path.
21651 // The return won't be an absolute path, so it's easy.
21652 if (!parentRegex.test(input))
21653 return normalizeSimplePath(input);
21654 // We already found one "..". Let's see how many there are.
21655 let total = 1;
21656 while (parentRegex.test(input))
21657 total++;
21658 // If there are ".."s, we need to prefix the the path with the same number of
21659 // unique directories. This is to ensure that we "remember" how many parent
21660 // directories we are accessing. Eg, "../../.." must keep 3, and "foo/../.."
21661 // must keep 1.
21662 const uniqDirectory = `z${uniqInStr(input)}/`;
21663 // uniqDirectory is just a "z", followed by numbers, followed by a "/". So
21664 // generating a runtime regex from it is safe. We'll use this search regex to
21665 // strip out our uniq directory names and insert any needed ".."s.
21666 const search = new RegExp(`^(?:${uniqDirectory})*`);
21667 // Now we can resolve the total path. If there are excess ".."s, they will
21668 // eliminate one or more of the unique directories we prefix with.
21669 const relative = normalizeSimplePath(uniqDirectory.repeat(total) + input);
21670 // We can now count the number of unique directories that were eliminated. If
21671 // there were 3, and 1 was eliminated, we know we only need to add 1 "..". If
21672 // 2 were eliminated, we need to insert 2 ".."s. If all 3 were eliminated,
21673 // then we need 3, etc. This replace is guranteed to match (it may match 0 or
21674 // more times), and we can count the total match to see how many were eliminated.
21675 return relative.replace(search, (all) => {
21676 const leftover = all.length / uniqDirectory.length;
21677 return '../'.repeat(total - leftover);
21678 });
21679}
21680/**
21681 * Attempts to resolve `input` URL relative to `base`.
21682 */
21683function resolve(input, base) {
21684 if (!base)
21685 base = '';
21686 // Absolute URLs are very easy to resolve right.
21687 if (isAbsoluteUrl(input))
21688 return new Url$1(input).href;
21689 if (base) {
21690 // Absolute URLs are easy...
21691 if (isAbsoluteUrl(base))
21692 return new Url$1(input, base).href;
21693 // If base is protocol relative, we'll resolve with it but keep the result
21694 // protocol relative.
21695 if (base.startsWith('//'))
21696 return normalizeProtocolRelative(input, `https:${base}`);
21697 }
21698 // Normalize input, but keep it protocol relative. We know base doesn't supply
21699 // a protocol, because that would have been handled above.
21700 if (input.startsWith('//'))
21701 return normalizeProtocolRelative(input, 'https://foo.com/');
21702 // We now know that base (if there is one) and input are paths. We've handled
21703 // both absolute and protocol-relative variations above.
21704 // Absolute paths don't need any special handling, because they cannot have
21705 // extra "." or ".."s. That'll all be stripped away. Input takes priority here,
21706 // because if input is an absolute path, base path won't affect it in any way.
21707 if (input.startsWith('/'))
21708 return '/' + normalizeSimplePath(input);
21709 // Since input and base are paths, we need to join them to do any further
21710 // processing. Paths are joined at the directory level, so we need to remove
21711 // the base's filename before joining. We also know that input does not have a
21712 // leading slash, and that the stripped base will have a trailing slash if
21713 // there are any directories (or it'll be empty).
21714 const joined = stripPathFilename(base) + input;
21715 // If base is an absolute path, then input will be relative to it.
21716 if (base.startsWith('/'))
21717 return '/' + normalizeSimplePath(joined);
21718 // We now know both base (if there is one) and input are relative paths.
21719 const relative = normalizePath(joined);
21720 // If base started with a leading ".", or there is no base and input started
21721 // with a ".", then we need to ensure that the relative path starts with a
21722 // ".". We don't know if relative starts with a "..", though, so check before
21723 // prepending.
21724 if ((base || input).startsWith('.') && !relative.startsWith('.')) {
21725 return './' + relative;
21726 }
21727 return relative;
21728}
21729
21730/**
21731 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21732 *
21733 * Licensed under the Apache License, Version 2.0 (the "License");
21734 * you may not use this file except in compliance with the License.
21735 * You may obtain a copy of the License at
21736 *
21737 * http://www.apache.org/licenses/LICENSE-2.0
21738 *
21739 * Unless required by applicable law or agreed to in writing, software
21740 * distributed under the License is distributed on an "AS IS" BASIS,
21741 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21742 * See the License for the specific language governing permissions and
21743 * limitations under the License.
21744 */
21745function resolve$1(input, base) {
21746 // The base is always treated as a directory, if it's not empty.
21747 // https://github.com/mozilla/source-map/blob/8cb3ee57/lib/util.js#L327
21748 // https://github.com/chromium/chromium/blob/da4adbb3/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js#L400-L401
21749 if (base && !base.endsWith('/'))
21750 base += '/';
21751 return resolve(input, base);
21752}
21753
21754/**
21755 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21756 *
21757 * Licensed under the Apache License, Version 2.0 (the "License");
21758 * you may not use this file except in compliance with the License.
21759 * You may obtain a copy of the License at
21760 *
21761 * http://www.apache.org/licenses/LICENSE-2.0
21762 *
21763 * Unless required by applicable law or agreed to in writing, software
21764 * distributed under the License is distributed on an "AS IS" BASIS,
21765 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21766 * See the License for the specific language governing permissions and
21767 * limitations under the License.
21768 */
21769/**
21770 * A binary search implementation that returns the index if a match is found,
21771 * or the negated index of where the `needle` should be inserted.
21772 *
21773 * The `comparator` callback receives both the `item` under comparison and the
21774 * needle we are searching for. It must return `0` if the `item` is a match,
21775 * any negative number if `item` is too small (and we must search after it), or
21776 * any positive number if the `item` is too large (and we must search before
21777 * it).
21778 *
21779 * If no match is found, a negated index of where to insert the `needle` is
21780 * returned. This negated index is guaranteed to be less than 0. To insert an
21781 * item, negate it (again) and splice:
21782 *
21783 * ```js
21784 * const array = [1, 3];
21785 * const needle = 2;
21786 * const index = binarySearch(array, needle, (item, needle) => item - needle);
21787 *
21788 * assert.equal(index, -2);
21789 * assert.equal(~index, 1);
21790 * array.splice(~index, 0, needle);
21791 * assert.deepEqual(array, [1, 2, 3]);
21792 * ```
21793 */
21794function binarySearch(haystack, needle, comparator) {
21795 let low = 0;
21796 let high = haystack.length - 1;
21797 while (low <= high) {
21798 const mid = low + ((high - low) >> 1);
21799 const cmp = comparator(haystack[mid], needle);
21800 if (cmp === 0) {
21801 return mid;
21802 }
21803 if (cmp < 0) {
21804 low = mid + 1;
21805 }
21806 else {
21807 high = mid - 1;
21808 }
21809 }
21810 return ~low;
21811}
21812
21813/**
21814 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21815 *
21816 * Licensed under the Apache License, Version 2.0 (the "License");
21817 * you may not use this file except in compliance with the License.
21818 * You may obtain a copy of the License at
21819 *
21820 * http://www.apache.org/licenses/LICENSE-2.0
21821 *
21822 * Unless required by applicable law or agreed to in writing, software
21823 * distributed under the License is distributed on an "AS IS" BASIS,
21824 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21825 * See the License for the specific language governing permissions and
21826 * limitations under the License.
21827 */
21828/**
21829 * FastStringArray acts like a `Set` (allowing only one occurrence of a string
21830 * `key`), but provides the index of the `key` in the backing array.
21831 *
21832 * This is designed to allow synchronizing a second array with the contents of
21833 * the backing array, like how `sourcesContent[i]` is the source content
21834 * associated with `source[i]`, and there are never duplicates.
21835 */
21836class FastStringArray {
21837 constructor() {
21838 this.indexes = Object.create(null);
21839 this.array = [];
21840 }
21841 /**
21842 * Puts `key` into the backing array, if it is not already present. Returns
21843 * the index of the `key` in the backing array.
21844 */
21845 put(key) {
21846 const { array, indexes } = this;
21847 // The key may or may not be present. If it is present, it's a number.
21848 let index = indexes[key];
21849 // If it's not yet present, we need to insert it and track the index in the
21850 // indexes.
21851 if (index === undefined) {
21852 index = indexes[key] = array.length;
21853 array.push(key);
21854 }
21855 return index;
21856 }
21857}
21858
21859/**
21860 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21861 *
21862 * Licensed under the Apache License, Version 2.0 (the "License");
21863 * you may not use this file except in compliance with the License.
21864 * You may obtain a copy of the License at
21865 *
21866 * http://www.apache.org/licenses/LICENSE-2.0
21867 *
21868 * Unless required by applicable law or agreed to in writing, software
21869 * distributed under the License is distributed on an "AS IS" BASIS,
21870 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21871 * See the License for the specific language governing permissions and
21872 * limitations under the License.
21873 */
21874/**
21875 * SourceMapTree represents a single sourcemap, with the ability to trace
21876 * mappings into its child nodes (which may themselves be SourceMapTrees).
21877 */
21878class SourceMapTree {
21879 constructor(map, sources) {
21880 this.map = map;
21881 this.sources = sources;
21882 }
21883 /**
21884 * traceMappings is only called on the root level SourceMapTree, and begins
21885 * the process of resolving each mapping in terms of the original source
21886 * files.
21887 */
21888 traceMappings() {
21889 const mappings = [];
21890 const names = new FastStringArray();
21891 const sources = new FastStringArray();
21892 const sourcesContent = [];
21893 const { mappings: rootMappings, names: rootNames } = this.map;
21894 for (let i = 0; i < rootMappings.length; i++) {
21895 const segments = rootMappings[i];
21896 const tracedSegments = [];
21897 for (let j = 0; j < segments.length; j++) {
21898 const segment = segments[j];
21899 // 1-length segments only move the current generated column, there's no
21900 // source information to gather from it.
21901 if (segment.length === 1)
21902 continue;
21903 const source = this.sources[segment[1]];
21904 const traced = source.traceSegment(segment[2], segment[3], segment.length === 5 ? rootNames[segment[4]] : '');
21905 if (!traced)
21906 continue;
21907 // So we traced a segment down into its original source file. Now push a
21908 // new segment pointing to this location.
21909 const { column, line, name } = traced;
21910 const { content, filename } = traced.source;
21911 // Store the source location, and ensure we keep sourcesContent up to
21912 // date with the sources array.
21913 const sourceIndex = sources.put(filename);
21914 sourcesContent[sourceIndex] = content;
21915 // This looks like unnecessary duplication, but it noticeably increases
21916 // performance. If we were to push the nameIndex onto length-4 array, v8
21917 // would internally allocate 22 slots! That's 68 wasted bytes! Array
21918 // literals have the same capacity as their length, saving memory.
21919 if (name) {
21920 tracedSegments.push([segment[0], sourceIndex, line, column, names.put(name)]);
21921 }
21922 else {
21923 tracedSegments.push([segment[0], sourceIndex, line, column]);
21924 }
21925 }
21926 mappings.push(tracedSegments);
21927 }
21928 // TODO: Make all sources relative to the sourceRoot.
21929 return defaults({
21930 mappings,
21931 names: names.array,
21932 sources: sources.array,
21933 sourcesContent,
21934 }, this.map);
21935 }
21936 /**
21937 * traceSegment is only called on children SourceMapTrees. It recurses down
21938 * into its own child SourceMapTrees, until we find the original source map.
21939 */
21940 traceSegment(line, column, name) {
21941 const { mappings, names } = this.map;
21942 // It's common for parent sourcemaps to have pointers to lines that have no
21943 // mapping (like a "//# sourceMappingURL=") at the end of the child file.
21944 if (line >= mappings.length)
21945 return null;
21946 const segments = mappings[line];
21947 if (segments.length === 0)
21948 return null;
21949 let index = binarySearch(segments, column, segmentComparator$1);
21950 if (index === -1)
21951 return null; // we come before any mapped segment
21952 // If we can't find a segment that lines up to this column, we use the
21953 // segment before.
21954 if (index < 0) {
21955 index = ~index - 1;
21956 }
21957 const segment = segments[index];
21958 // 1-length segments only move the current generated column, there's no
21959 // source information to gather from it.
21960 if (segment.length === 1)
21961 return null;
21962 const source = this.sources[segment[1]];
21963 // So now we can recurse down, until we hit the original source file.
21964 return source.traceSegment(segment[2], segment[3],
21965 // A child map's recorded name for this segment takes precedence over the
21966 // parent's mapped name. Imagine a mangler changing the name over, etc.
21967 segment.length === 5 ? names[segment[4]] : name);
21968 }
21969}
21970function segmentComparator$1(segment, column) {
21971 return segment[0] - column;
21972}
21973
21974/**
21975 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21976 *
21977 * Licensed under the Apache License, Version 2.0 (the "License");
21978 * you may not use this file except in compliance with the License.
21979 * You may obtain a copy of the License at
21980 *
21981 * http://www.apache.org/licenses/LICENSE-2.0
21982 *
21983 * Unless required by applicable law or agreed to in writing, software
21984 * distributed under the License is distributed on an "AS IS" BASIS,
21985 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21986 * See the License for the specific language governing permissions and
21987 * limitations under the License.
21988 */
21989/**
21990 * Removes the filename from a path.
21991 */
21992function stripFilename(path) {
21993 if (!path)
21994 return '';
21995 const index = path.lastIndexOf('/');
21996 return path.slice(0, index + 1);
21997}
21998
21999/**
22000 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
22001 *
22002 * Licensed under the Apache License, Version 2.0 (the "License");
22003 * you may not use this file except in compliance with the License.
22004 * You may obtain a copy of the License at
22005 *
22006 * http://www.apache.org/licenses/LICENSE-2.0
22007 *
22008 * Unless required by applicable law or agreed to in writing, software
22009 * distributed under the License is distributed on an "AS IS" BASIS,
22010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22011 * See the License for the specific language governing permissions and
22012 * limitations under the License.
22013 */
22014function asArray(value) {
22015 if (Array.isArray(value))
22016 return value;
22017 return [value];
22018}
22019/**
22020 * Recursively builds a tree structure out of sourcemap files, with each node
22021 * being either an `OriginalSource` "leaf" or a `SourceMapTree` composed of
22022 * `OriginalSource`s and `SourceMapTree`s.
22023 *
22024 * Every sourcemap is composed of a collection of source files and mappings
22025 * into locations of those source files. When we generate a `SourceMapTree` for
22026 * the sourcemap, we attempt to load each source file's own sourcemap. If it
22027 * does not have an associated sourcemap, it is considered an original,
22028 * unmodified source file.
22029 */
22030function buildSourceMapTree(input, loader, relativeRoot) {
22031 const maps = asArray(input).map(decodeSourceMap);
22032 const map = maps.pop();
22033 for (let i = 0; i < maps.length; i++) {
22034 if (maps[i].sources.length !== 1) {
22035 throw new Error(`Transformation map ${i} must have exactly one source file.\n` +
22036 'Did you specify these with the most recent transformation maps first?');
22037 }
22038 }
22039 const { sourceRoot, sources, sourcesContent } = map;
22040 const children = sources.map((sourceFile, i) => {
22041 // Each source file is loaded relative to the sourcemap's own sourceRoot,
22042 // which is itself relative to the sourcemap's parent.
22043 const uri = resolve$1(sourceFile || '', resolve$1(sourceRoot || '', stripFilename(relativeRoot)));
22044 // Use the provided loader callback to retrieve the file's sourcemap.
22045 // TODO: We should eventually support async loading of sourcemap files.
22046 const sourceMap = loader(uri);
22047 // If there is no sourcemap, then it is an unmodified source file.
22048 if (!sourceMap) {
22049 // The source file's actual contents must be included in the sourcemap
22050 // (done when generating the sourcemap) for it to be included as a
22051 // sourceContent in the output sourcemap.
22052 const sourceContent = sourcesContent ? sourcesContent[i] : null;
22053 return new OriginalSource(uri, sourceContent);
22054 }
22055 // Else, it's a real sourcemap, and we need to recurse into it to load its
22056 // source files.
22057 return buildSourceMapTree(decodeSourceMap(sourceMap), loader, uri);
22058 });
22059 let tree = new SourceMapTree(map, children);
22060 for (let i = maps.length - 1; i >= 0; i--) {
22061 tree = new SourceMapTree(maps[i], [tree]);
22062 }
22063 return tree;
22064}
22065
22066/**
22067 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
22068 *
22069 * Licensed under the Apache License, Version 2.0 (the "License");
22070 * you may not use this file except in compliance with the License.
22071 * You may obtain a copy of the License at
22072 *
22073 * http://www.apache.org/licenses/LICENSE-2.0
22074 *
22075 * Unless required by applicable law or agreed to in writing, software
22076 * distributed under the License is distributed on an "AS IS" BASIS,
22077 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22078 * See the License for the specific language governing permissions and
22079 * limitations under the License.
22080 */
22081/**
22082 * A SourceMap v3 compatible sourcemap, which only includes fields that were
22083 * provided to it.
22084 */
22085class SourceMap {
22086 constructor(map, excludeContent) {
22087 this.version = 3; // SourceMap spec says this should be first.
22088 if ('file' in map)
22089 this.file = map.file;
22090 this.mappings = encode$1(map.mappings);
22091 this.names = map.names;
22092 // TODO: We first need to make all source URIs relative to the sourceRoot
22093 // before we can support a sourceRoot.
22094 // if ('sourceRoot' in map) this.sourceRoot = map.sourceRoot;
22095 this.sources = map.sources;
22096 if (!excludeContent && 'sourcesContent' in map)
22097 this.sourcesContent = map.sourcesContent;
22098 }
22099 toString() {
22100 return JSON.stringify(this);
22101 }
22102}
22103
22104/**
22105 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
22106 *
22107 * Licensed under the Apache License, Version 2.0 (the "License");
22108 * you may not use this file except in compliance with the License.
22109 * You may obtain a copy of the License at
22110 *
22111 * http://www.apache.org/licenses/LICENSE-2.0
22112 *
22113 * Unless required by applicable law or agreed to in writing, software
22114 * distributed under the License is distributed on an "AS IS" BASIS,
22115 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22116 * See the License for the specific language governing permissions and
22117 * limitations under the License.
22118 */
22119/**
22120 * Traces through all the mappings in the root sourcemap, through the sources
22121 * (and their sourcemaps), all the way back to the original source location.
22122 *
22123 * `loader` will be called every time we encounter a source file. If it returns
22124 * a sourcemap, we will recurse into that sourcemap to continue the trace. If
22125 * it returns a falsey value, that source file is treated as an original,
22126 * unmodified source file.
22127 *
22128 * Pass `excludeContent` content to exclude any self-containing source file
22129 * content from the output sourcemap.
22130 */
22131function remapping(input, loader, excludeContent) {
22132 const graph = buildSourceMapTree(input, loader);
22133 return new SourceMap(graph.traceMappings(), !!excludeContent);
22134}
22135
22136function last_line_length(s) {
22137 return s.length - s.lastIndexOf('\n') - 1;
22138}
22139// mutate map in-place
22140function sourcemap_add_offset(map, offset, source_index) {
22141 if (map.mappings.length == 0)
22142 return;
22143 for (let line = 0; line < map.mappings.length; line++) {
22144 const segment_list = map.mappings[line];
22145 for (let segment = 0; segment < segment_list.length; segment++) {
22146 const seg = segment_list[segment];
22147 // shift only segments that belong to component source file
22148 if (seg[1] === source_index) { // also ensures that seg.length >= 4
22149 // shift column if it points at the first line
22150 if (seg[2] === 0) {
22151 seg[3] += offset.column;
22152 }
22153 // shift line
22154 seg[2] += offset.line;
22155 }
22156 }
22157 }
22158}
22159function merge_tables(this_table, other_table) {
22160 const new_table = this_table.slice();
22161 const idx_map = [];
22162 other_table = other_table || [];
22163 let val_changed = false;
22164 for (const [other_idx, other_val] of other_table.entries()) {
22165 const this_idx = this_table.indexOf(other_val);
22166 if (this_idx >= 0) {
22167 idx_map[other_idx] = this_idx;
22168 }
22169 else {
22170 const new_idx = new_table.length;
22171 new_table[new_idx] = other_val;
22172 idx_map[other_idx] = new_idx;
22173 val_changed = true;
22174 }
22175 }
22176 let idx_changed = val_changed;
22177 if (val_changed) {
22178 if (idx_map.find((val, idx) => val != idx) === undefined) {
22179 // idx_map is identity map [0, 1, 2, 3, 4, ....]
22180 idx_changed = false;
22181 }
22182 }
22183 return [new_table, idx_map, val_changed, idx_changed];
22184}
22185function pushArray(_this, other) {
22186 // We use push to mutate in place for memory and perf reasons
22187 // We use the for loop instead of _this.push(...other) to avoid the JS engine's function argument limit (65,535 in JavascriptCore)
22188 for (let i = 0; i < other.length; i++) {
22189 _this.push(other[i]);
22190 }
22191}
22192class StringWithSourcemap {
22193 constructor(string = '', map = null) {
22194 this.string = string;
22195 if (map) {
22196 this.map = map;
22197 }
22198 else {
22199 this.map = {
22200 version: 3,
22201 mappings: [],
22202 sources: [],
22203 names: []
22204 };
22205 }
22206 }
22207 /**
22208 * concat in-place (mutable), return this (chainable)
22209 * will also mutate the `other` object
22210 */
22211 concat(other) {
22212 // noop: if one is empty, return the other
22213 if (other.string == '')
22214 return this;
22215 if (this.string == '') {
22216 this.string = other.string;
22217 this.map = other.map;
22218 return this;
22219 }
22220 // compute last line length before mutating
22221 const column_offset = last_line_length(this.string);
22222 this.string += other.string;
22223 const m1 = this.map;
22224 const m2 = other.map;
22225 if (m2.mappings.length == 0)
22226 return this;
22227 // combine sources and names
22228 const [sources, new_source_idx, sources_changed, sources_idx_changed] = merge_tables(m1.sources, m2.sources);
22229 const [names, new_name_idx, names_changed, names_idx_changed] = merge_tables(m1.names, m2.names);
22230 if (sources_changed)
22231 m1.sources = sources;
22232 if (names_changed)
22233 m1.names = names;
22234 // unswitched loops are faster
22235 if (sources_idx_changed && names_idx_changed) {
22236 for (let line = 0; line < m2.mappings.length; line++) {
22237 const segment_list = m2.mappings[line];
22238 for (let segment = 0; segment < segment_list.length; segment++) {
22239 const seg = segment_list[segment];
22240 if (seg[1] >= 0)
22241 seg[1] = new_source_idx[seg[1]];
22242 if (seg[4] >= 0)
22243 seg[4] = new_name_idx[seg[4]];
22244 }
22245 }
22246 }
22247 else if (sources_idx_changed) {
22248 for (let line = 0; line < m2.mappings.length; line++) {
22249 const segment_list = m2.mappings[line];
22250 for (let segment = 0; segment < segment_list.length; segment++) {
22251 const seg = segment_list[segment];
22252 if (seg[1] >= 0)
22253 seg[1] = new_source_idx[seg[1]];
22254 }
22255 }
22256 }
22257 else if (names_idx_changed) {
22258 for (let line = 0; line < m2.mappings.length; line++) {
22259 const segment_list = m2.mappings[line];
22260 for (let segment = 0; segment < segment_list.length; segment++) {
22261 const seg = segment_list[segment];
22262 if (seg[4] >= 0)
22263 seg[4] = new_name_idx[seg[4]];
22264 }
22265 }
22266 }
22267 // combine the mappings
22268 // combine
22269 // 1. last line of first map
22270 // 2. first line of second map
22271 // columns of 2 must be shifted
22272 if (m2.mappings.length > 0 && column_offset > 0) {
22273 const first_line = m2.mappings[0];
22274 for (let i = 0; i < first_line.length; i++) {
22275 first_line[i][0] += column_offset;
22276 }
22277 }
22278 // combine last line + first line
22279 pushArray(m1.mappings[m1.mappings.length - 1], m2.mappings.shift());
22280 // append other lines
22281 pushArray(m1.mappings, m2.mappings);
22282 return this;
22283 }
22284 static from_processed(string, map) {
22285 const line_count = string.split('\n').length;
22286 if (map) {
22287 // ensure that count of source map mappings lines
22288 // is equal to count of generated code lines
22289 // (some tools may produce less)
22290 const missing_lines = line_count - map.mappings.length;
22291 for (let i = 0; i < missing_lines; i++) {
22292 map.mappings.push([]);
22293 }
22294 return new StringWithSourcemap(string, map);
22295 }
22296 if (string == '')
22297 return new StringWithSourcemap();
22298 map = { version: 3, names: [], sources: [], mappings: [] };
22299 // add empty SourceMapSegment[] for every line
22300 for (let i = 0; i < line_count; i++)
22301 map.mappings.push([]);
22302 return new StringWithSourcemap(string, map);
22303 }
22304 static from_source(source_file, source, offset) {
22305 if (!offset)
22306 offset = { line: 0, column: 0 };
22307 const map = { version: 3, names: [], sources: [source_file], mappings: [] };
22308 if (source == '')
22309 return new StringWithSourcemap(source, map);
22310 // we create a high resolution identity map here,
22311 // we know that it will eventually be merged with svelte's map,
22312 // at which stage the resolution will decrease.
22313 const line_list = source.split('\n');
22314 for (let line = 0; line < line_list.length; line++) {
22315 map.mappings.push([]);
22316 const token_list = line_list[line].split(/([^\d\w\s]|\s+)/g);
22317 for (let token = 0, column = 0; token < token_list.length; token++) {
22318 if (token_list[token] == '')
22319 continue;
22320 map.mappings[line].push([column, 0, offset.line + line, column]);
22321 column += token_list[token].length;
22322 }
22323 }
22324 // shift columns in first line
22325 const segment_list = map.mappings[0];
22326 for (let segment = 0; segment < segment_list.length; segment++) {
22327 segment_list[segment][3] += offset.column;
22328 }
22329 return new StringWithSourcemap(source, map);
22330 }
22331}
22332function combine_sourcemaps(filename, sourcemap_list) {
22333 if (sourcemap_list.length == 0)
22334 return null;
22335 let map_idx = 1;
22336 const map = sourcemap_list.slice(0, -1)
22337 .find(m => m.sources.length !== 1) === undefined
22338 ? remapping(// use array interface
22339 // only the oldest sourcemap can have multiple sources
22340 sourcemap_list, () => null, true // skip optional field `sourcesContent`
22341 )
22342 : remapping(// use loader interface
22343 sourcemap_list[0], // last map
22344 function loader(sourcefile) {
22345 if (sourcefile === filename && sourcemap_list[map_idx]) {
22346 return sourcemap_list[map_idx++]; // idx 1, 2, ...
22347 // bundle file = branch node
22348 }
22349 else {
22350 return null; // source file = leaf node
22351 }
22352 }, true);
22353 if (!map.file)
22354 delete map.file; // skip optional field `file`
22355 return map;
22356}
22357// browser vs node.js
22358const b64enc = typeof btoa == 'function' ? btoa : b => Buffer.from(b).toString('base64');
22359function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_map_input) {
22360 if (!svelte_map || !preprocessor_map_input)
22361 return svelte_map;
22362 const preprocessor_map = typeof preprocessor_map_input === 'string' ? JSON.parse(preprocessor_map_input) : preprocessor_map_input;
22363 const result_map = combine_sourcemaps(filename, [
22364 svelte_map,
22365 preprocessor_map
22366 ]);
22367 // Svelte expects a SourceMap which includes toUrl and toString. Instead of wrapping our output in a class,
22368 // we just tack on the extra properties.
22369 Object.defineProperties(result_map, {
22370 toString: {
22371 enumerable: false,
22372 value: function toString() {
22373 return JSON.stringify(this);
22374 }
22375 },
22376 toUrl: {
22377 enumerable: false,
22378 value: function toUrl() {
22379 return 'data:application/json;charset=utf-8;base64,' + b64enc(this.toString());
22380 }
22381 }
22382 });
22383 return result_map;
22384}
22385
22386function dom(component, options) {
22387 const { name } = component;
22388 const renderer = new Renderer(component, options);
22389 const { block } = renderer;
22390 block.has_outro_method = true;
22391 // prevent fragment being created twice (#1063)
22392 if (options.customElement)
22393 block.chunks.create.push(b `this.c = @noop;`);
22394 const body = [];
22395 if (renderer.file_var) {
22396 const file = component.file ? x `"${component.file}"` : x `undefined`;
22397 body.push(b `const ${renderer.file_var} = ${file};`);
22398 }
22399 const css = component.stylesheet.render(options.filename, !options.customElement);
22400 css.map = apply_preprocessor_sourcemap(options.filename, css.map, options.sourcemap);
22401 const styles = component.stylesheet.has_styles && options.dev
22402 ? `${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */`
22403 : css.code;
22404 const add_css = component.get_unique_name('add_css');
22405 const should_add_css = (!options.customElement &&
22406 !!styles &&
22407 options.css !== false);
22408 if (should_add_css) {
22409 body.push(b `
22410 function ${add_css}() {
22411 var style = @element("style");
22412 style.id = "${component.stylesheet.id}-style";
22413 style.textContent = "${styles}";
22414 @append(@_document.head, style);
22415 }
22416 `);
22417 }
22418 // fix order
22419 // TODO the deconflicted names of blocks are reversed... should set them here
22420 const blocks = renderer.blocks.slice().reverse();
22421 body.push(...blocks.map(block => {
22422 // TODO this is a horrible mess — renderer.blocks
22423 // contains a mixture of Blocks and Nodes
22424 if (block.render)
22425 return block.render();
22426 return block;
22427 }));
22428 if (options.dev && !options.hydratable) {
22429 block.chunks.claim.push(b `throw new @_Error("options.hydrate only works if the component was compiled with the \`hydratable: true\` option");`);
22430 }
22431 const uses_slots = component.var_lookup.has('$$slots');
22432 let compute_slots;
22433 if (uses_slots) {
22434 compute_slots = b `
22435 const $$slots = @compute_slots(#slots);
22436 `;
22437 }
22438 const uses_props = component.var_lookup.has('$$props');
22439 const uses_rest = component.var_lookup.has('$$restProps');
22440 const $$props = uses_props || uses_rest ? '$$new_props' : '$$props';
22441 const props = component.vars.filter(variable => !variable.module && variable.export_name);
22442 const writable_props = props.filter(variable => variable.writable);
22443 const omit_props_names = component.get_unique_name('omit_props_names');
22444 const compute_rest = x `@compute_rest_props($$props, ${omit_props_names.name})`;
22445 const rest = uses_rest ? b `
22446 const ${omit_props_names.name} = [${props.map(prop => `"${prop.export_name}"`).join(',')}];
22447 let $$restProps = ${compute_rest};
22448 ` : null;
22449 const set = (uses_props || uses_rest || writable_props.length > 0 || component.slots.size > 0)
22450 ? x `
22451 ${$$props} => {
22452 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`)}
22453 ${uses_rest && !uses_props && x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`}
22454 ${uses_rest && renderer.invalidate('$$restProps', x `$$restProps = ${compute_rest}`)}
22455 ${writable_props.map(prop => b `if ('${prop.export_name}' in ${$$props}) ${renderer.invalidate(prop.name, x `${prop.name} = ${$$props}.${prop.export_name}`)};`)}
22456 ${component.slots.size > 0 &&
22457 b `if ('$$scope' in ${$$props}) ${renderer.invalidate('$$scope', x `$$scope = ${$$props}.$$scope`)};`}
22458 }
22459 `
22460 : null;
22461 const accessors = [];
22462 const not_equal = component.component_options.immutable ? x `@not_equal` : x `@safe_not_equal`;
22463 let dev_props_check;
22464 let inject_state;
22465 let capture_state;
22466 let props_inject;
22467 props.forEach(prop => {
22468 const variable = component.var_lookup.get(prop.name);
22469 if (!variable.writable || component.component_options.accessors) {
22470 accessors.push({
22471 type: 'MethodDefinition',
22472 kind: 'get',
22473 key: { type: 'Identifier', name: prop.export_name },
22474 value: x `function() {
22475 return ${prop.hoistable ? prop.name : x `this.$$.ctx[${renderer.context_lookup.get(prop.name).index}]`}
22476 }`
22477 });
22478 }
22479 else if (component.compile_options.dev) {
22480 accessors.push({
22481 type: 'MethodDefinition',
22482 kind: 'get',
22483 key: { type: 'Identifier', name: prop.export_name },
22484 value: x `function() {
22485 throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
22486 }`
22487 });
22488 }
22489 if (component.component_options.accessors) {
22490 if (variable.writable && !renderer.readonly.has(prop.name)) {
22491 accessors.push({
22492 type: 'MethodDefinition',
22493 kind: 'set',
22494 key: { type: 'Identifier', name: prop.export_name },
22495 value: x `function(${prop.name}) {
22496 this.$set({ ${prop.export_name}: ${prop.name} });
22497 @flush();
22498 }`
22499 });
22500 }
22501 else if (component.compile_options.dev) {
22502 accessors.push({
22503 type: 'MethodDefinition',
22504 kind: 'set',
22505 key: { type: 'Identifier', name: prop.export_name },
22506 value: x `function(value) {
22507 throw new @_Error("<${component.tag}>: Cannot set read-only property '${prop.export_name}'");
22508 }`
22509 });
22510 }
22511 }
22512 else if (component.compile_options.dev) {
22513 accessors.push({
22514 type: 'MethodDefinition',
22515 kind: 'set',
22516 key: { type: 'Identifier', name: prop.export_name },
22517 value: x `function(value) {
22518 throw new @_Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
22519 }`
22520 });
22521 }
22522 });
22523 if (component.compile_options.dev) {
22524 // checking that expected ones were passed
22525 const expected = props.filter(prop => prop.writable && !prop.initialised);
22526 if (expected.length) {
22527 dev_props_check = b `
22528 const { ctx: #ctx } = this.$$;
22529 const props = ${options.customElement ? x `this.attributes` : x `options.props || {}`};
22530 ${expected.map(prop => b `
22531 if (${renderer.reference(prop.name)} === undefined && !('${prop.export_name}' in props)) {
22532 @_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'");
22533 }`)}
22534 `;
22535 }
22536 const capturable_vars = component.vars.filter(v => !v.internal && !v.global && !v.name.startsWith('$$'));
22537 if (capturable_vars.length > 0) {
22538 capture_state = x `() => ({ ${capturable_vars.map(prop => p `${prop.name}`)} })`;
22539 }
22540 const injectable_vars = capturable_vars.filter(v => !v.module && v.writable && v.name[0] !== '$');
22541 if (uses_props || injectable_vars.length > 0) {
22542 inject_state = x `
22543 ${$$props} => {
22544 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), $$new_props)`)}
22545 ${injectable_vars.map(v => b `if ('${v.name}' in $$props) ${renderer.invalidate(v.name, x `${v.name} = ${$$props}.${v.name}`)};`)}
22546 }
22547 `;
22548 props_inject = b `
22549 if ($$props && "$$inject" in $$props) {
22550 $$self.$inject_state($$props.$$inject);
22551 }
22552 `;
22553 }
22554 }
22555 // instrument assignments
22556 if (component.ast.instance) {
22557 let scope = component.instance_scope;
22558 const map = component.instance_scope_map;
22559 let execution_context = null;
22560 walk(component.ast.instance.content, {
22561 enter(node) {
22562 if (map.has(node)) {
22563 scope = map.get(node);
22564 if (!execution_context && !scope.block) {
22565 execution_context = node;
22566 }
22567 }
22568 else if (!execution_context && node.type === 'LabeledStatement' && node.label.name === '$') {
22569 execution_context = node;
22570 }
22571 },
22572 leave(node) {
22573 if (map.has(node)) {
22574 scope = scope.parent;
22575 }
22576 if (execution_context === node) {
22577 execution_context = null;
22578 }
22579 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
22580 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
22581 // normally (`a = 1`, `b.c = 2`), there'll be a single name
22582 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
22583 // may be more, in which case we need to tack the extra ones
22584 // onto the initial function call
22585 const names = new Set(extract_names(assignee));
22586 this.replace(invalidate(renderer, scope, node, names, execution_context === null));
22587 }
22588 }
22589 });
22590 component.rewrite_props(({ name, reassigned, export_name }) => {
22591 const value = `$${name}`;
22592 const i = renderer.context_lookup.get(`$${name}`).index;
22593 const insert = (reassigned || export_name)
22594 ? b `${`$$subscribe_${name}`}()`
22595 : b `@component_subscribe($$self, ${name}, #value => $$invalidate(${i}, ${value} = #value))`;
22596 if (component.compile_options.dev) {
22597 return b `@validate_store(${name}, '${name}'); ${insert}`;
22598 }
22599 return insert;
22600 });
22601 }
22602 const args = [x `$$self`];
22603 const has_invalidate = props.length > 0 ||
22604 component.has_reactive_assignments ||
22605 component.slots.size > 0 ||
22606 capture_state ||
22607 inject_state;
22608 if (has_invalidate) {
22609 args.push(x `$$props`, x `$$invalidate`);
22610 }
22611 else if (component.compile_options.dev) {
22612 // $$props arg is still needed for unknown prop check
22613 args.push(x `$$props`);
22614 }
22615 const has_create_fragment = component.compile_options.dev || block.has_content();
22616 if (has_create_fragment) {
22617 body.push(b `
22618 function create_fragment(#ctx) {
22619 ${block.get_contents()}
22620 }
22621 `);
22622 }
22623 body.push(b `
22624 ${component.extract_javascript(component.ast.module)}
22625
22626 ${component.fully_hoisted}
22627 `);
22628 const filtered_props = props.filter(prop => {
22629 const variable = component.var_lookup.get(prop.name);
22630 if (variable.hoistable)
22631 return false;
22632 return prop.name[0] !== '$';
22633 });
22634 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
22635 const instance_javascript = component.extract_javascript(component.ast.instance);
22636 const has_definition = (component.compile_options.dev ||
22637 (instance_javascript && instance_javascript.length > 0) ||
22638 filtered_props.length > 0 ||
22639 uses_props ||
22640 component.partly_hoisted.length > 0 ||
22641 renderer.initial_context.length > 0 ||
22642 component.reactive_declarations.length > 0 ||
22643 capture_state ||
22644 inject_state);
22645 const definition = has_definition
22646 ? component.alias('instance')
22647 : { type: 'Literal', value: null };
22648 const reactive_store_subscriptions = reactive_stores
22649 .filter(store => {
22650 const variable = component.var_lookup.get(store.name.slice(1));
22651 return !variable || variable.hoistable;
22652 })
22653 .map(({ name }) => b `
22654 ${component.compile_options.dev && b `@validate_store(${name.slice(1)}, '${name.slice(1)}');`}
22655 @component_subscribe($$self, ${name.slice(1)}, $$value => $$invalidate(${renderer.context_lookup.get(name).index}, ${name} = $$value));
22656 `);
22657 const resubscribable_reactive_store_unsubscribers = reactive_stores
22658 .filter(store => {
22659 const variable = component.var_lookup.get(store.name.slice(1));
22660 return variable && (variable.reassigned || variable.export_name);
22661 })
22662 .map(({ name }) => b `$$self.$$.on_destroy.push(() => ${`$$unsubscribe_${name.slice(1)}`}());`);
22663 if (has_definition) {
22664 const reactive_declarations = [];
22665 const fixed_reactive_declarations = []; // not really 'reactive' but whatever
22666 component.reactive_declarations.forEach(d => {
22667 const dependencies = Array.from(d.dependencies);
22668 const uses_rest_or_props = !!dependencies.find(n => n === '$$props' || n === '$$restProps');
22669 const writable = dependencies.filter(n => {
22670 const variable = component.var_lookup.get(n);
22671 return variable && (variable.export_name || variable.mutated || variable.reassigned);
22672 });
22673 const condition = !uses_rest_or_props && writable.length > 0 && renderer.dirty(writable, true);
22674 let statement = d.node; // TODO remove label (use d.node.body) if it's not referenced
22675 if (condition)
22676 statement = b `if (${condition}) { ${statement} }`[0];
22677 if (condition || uses_rest_or_props) {
22678 reactive_declarations.push(statement);
22679 }
22680 else {
22681 fixed_reactive_declarations.push(statement);
22682 }
22683 });
22684 const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
22685 const variable = component.var_lookup.get(name);
22686 return variable.injected && variable.name[0] !== '$';
22687 });
22688 const reactive_store_declarations = reactive_stores.map(variable => {
22689 const $name = variable.name;
22690 const name = $name.slice(1);
22691 const store = component.var_lookup.get(name);
22692 if (store && (store.reassigned || store.export_name)) {
22693 const unsubscribe = `$$unsubscribe_${name}`;
22694 const subscribe = `$$subscribe_${name}`;
22695 const i = renderer.context_lookup.get($name).index;
22696 return b `let ${$name}, ${unsubscribe} = @noop, ${subscribe} = () => (${unsubscribe}(), ${unsubscribe} = @subscribe(${name}, $$value => $$invalidate(${i}, ${$name} = $$value)), ${name})`;
22697 }
22698 return b `let ${$name};`;
22699 });
22700 let unknown_props_check;
22701 if (component.compile_options.dev && !(uses_props || uses_rest)) {
22702 unknown_props_check = b `
22703 const writable_props = [${writable_props.map(prop => x `'${prop.export_name}'`)}];
22704 @_Object.keys($$props).forEach(key => {
22705 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$') @_console.warn(\`<${component.tag}> was created with unknown prop '\${key}'\`);
22706 });
22707 `;
22708 }
22709 const return_value = {
22710 type: 'ArrayExpression',
22711 elements: renderer.initial_context.map(member => ({
22712 type: 'Identifier',
22713 name: member.name
22714 }))
22715 };
22716 body.push(b `
22717 function ${definition}(${args}) {
22718 ${injected.map(name => b `let ${name};`)}
22719
22720 ${rest}
22721
22722 ${reactive_store_declarations}
22723
22724 ${reactive_store_subscriptions}
22725
22726 ${resubscribable_reactive_store_unsubscribers}
22727
22728 ${component.slots.size || component.compile_options.dev || uses_slots ? b `let { $$slots: #slots = {}, $$scope } = $$props;` : null}
22729 ${component.compile_options.dev && b `@validate_slots('${component.tag}', #slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
22730 ${compute_slots}
22731
22732 ${instance_javascript}
22733
22734 ${unknown_props_check}
22735
22736 ${renderer.binding_groups.size > 0 && b `const $$binding_groups = [${[...renderer.binding_groups.keys()].map(_ => x `[]`)}];`}
22737
22738 ${component.partly_hoisted}
22739
22740 ${set && b `$$self.$$set = ${set};`}
22741
22742 ${capture_state && b `$$self.$capture_state = ${capture_state};`}
22743
22744 ${inject_state && b `$$self.$inject_state = ${inject_state};`}
22745
22746 ${ /* before reactive declarations */props_inject}
22747
22748 ${reactive_declarations.length > 0 && b `
22749 $$self.$$.update = () => {
22750 ${reactive_declarations}
22751 };
22752 `}
22753
22754 ${fixed_reactive_declarations}
22755
22756 ${uses_props && b `$$props = @exclude_internal_props($$props);`}
22757
22758 return ${return_value};
22759 }
22760 `);
22761 }
22762 const prop_indexes = x `{
22763 ${props.filter(v => v.export_name && !v.module).map(v => p `${v.export_name}: ${renderer.context_lookup.get(v.name).index}`)}
22764 }`;
22765 let dirty;
22766 if (renderer.context_overflow) {
22767 dirty = x `[]`;
22768 for (let i = 0; i < renderer.context.length; i += 31) {
22769 dirty.elements.push(x `-1`);
22770 }
22771 }
22772 if (options.customElement) {
22773 let init_props = x `@attribute_to_object(this.attributes)`;
22774 if (uses_slots) {
22775 init_props = x `{ ...${init_props}, $$slots: @get_custom_elements_slots(this) }`;
22776 }
22777 const declaration = b `
22778 class ${name} extends @SvelteElement {
22779 constructor(options) {
22780 super();
22781
22782 ${css.code && b `this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
22783
22784 @init(this, { target: this.shadowRoot, props: ${init_props} }, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
22785
22786 ${dev_props_check}
22787
22788 if (options) {
22789 if (options.target) {
22790 @insert(options.target, this, options.anchor);
22791 }
22792
22793 ${(props.length > 0 || uses_props || uses_rest) && b `
22794 if (options.props) {
22795 this.$set(options.props);
22796 @flush();
22797 }`}
22798 }
22799 }
22800 }
22801 `[0];
22802 if (props.length > 0) {
22803 declaration.body.body.push({
22804 type: 'MethodDefinition',
22805 kind: 'get',
22806 static: true,
22807 computed: false,
22808 key: { type: 'Identifier', name: 'observedAttributes' },
22809 value: x `function() {
22810 return [${props.map(prop => x `"${prop.export_name}"`)}];
22811 }`
22812 });
22813 }
22814 declaration.body.body.push(...accessors);
22815 body.push(declaration);
22816 if (component.tag != null) {
22817 body.push(b `
22818 @_customElements.define("${component.tag}", ${name});
22819 `);
22820 }
22821 }
22822 else {
22823 const superclass = {
22824 type: 'Identifier',
22825 name: options.dev ? '@SvelteComponentDev' : '@SvelteComponent'
22826 };
22827 const declaration = b `
22828 class ${name} extends ${superclass} {
22829 constructor(options) {
22830 super(${options.dev && 'options'});
22831 ${should_add_css && b `if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
22832 @init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
22833 ${options.dev && b `@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`}
22834
22835 ${dev_props_check}
22836 }
22837 }
22838 `[0];
22839 declaration.body.body.push(...accessors);
22840 body.push(declaration);
22841 }
22842 return { js: flatten$1(body, []), css };
22843}
22844function flatten$1(nodes, target) {
22845 for (let i = 0; i < nodes.length; i += 1) {
22846 const node = nodes[i];
22847 if (Array.isArray(node)) {
22848 flatten$1(node, target);
22849 }
22850 else {
22851 target.push(node);
22852 }
22853 }
22854 return target;
22855}
22856
22857function AwaitBlock (node, renderer, options) {
22858 renderer.push();
22859 renderer.render(node.pending.children, options);
22860 const pending = renderer.pop();
22861 renderer.push();
22862 renderer.render(node.then.children, options);
22863 const then = renderer.pop();
22864 renderer.add_expression(x `
22865 function(__value) {
22866 if (@is_promise(__value)) return ${pending};
22867 return (function(${node.then_node ? node.then_node : ''}) { return ${then}; }(__value));
22868 }(${node.expression.node})
22869 `);
22870}
22871
22872function Comment$1 (_node, _renderer, _options) {
22873 // TODO preserve comments
22874 // if (options.preserveComments) {
22875 // renderer.append(`<!--${node.data}-->`);
22876 // }
22877}
22878
22879function DebugTag (node, renderer, options) {
22880 if (!options.dev)
22881 return;
22882 const filename = options.filename || null;
22883 const { line, column } = options.locate(node.start + 1);
22884 const obj = x `{
22885 ${node.expressions.map(e => p `${e.node.name}`)}
22886 }`;
22887 renderer.add_expression(x `@debug(${filename ? x `"${filename}"` : x `null`}, ${line - 1}, ${column}, ${obj})`);
22888}
22889
22890function EachBlock (node, renderer, options) {
22891 const args = [node.context_node];
22892 if (node.index)
22893 args.push({ type: 'Identifier', name: node.index });
22894 renderer.push();
22895 renderer.render(node.children, options);
22896 const result = renderer.pop();
22897 const consequent = x `@each(${node.expression.node}, (${args}) => ${result})`;
22898 if (node.else) {
22899 renderer.push();
22900 renderer.render(node.else.children, options);
22901 const alternate = renderer.pop();
22902 renderer.add_expression(x `${node.expression.node}.length ? ${consequent} : ${alternate}`);
22903 }
22904 else {
22905 renderer.add_expression(consequent);
22906 }
22907}
22908
22909function get_class_attribute_value(attribute) {
22910 // handle special case — `class={possiblyUndefined}` with scoped CSS
22911 if (attribute.chunks.length === 2 && attribute.chunks[1].synthetic) {
22912 const value = attribute.chunks[0].node;
22913 return x `@escape(@null_to_empty(${value})) + "${attribute.chunks[1].data}"`;
22914 }
22915 return get_attribute_value(attribute);
22916}
22917function get_attribute_value(attribute) {
22918 if (attribute.chunks.length === 0)
22919 return x `""`;
22920 return attribute.chunks
22921 .map((chunk) => {
22922 return chunk.type === 'Text'
22923 ? string_literal(chunk.data.replace(/"/g, '&quot;'))
22924 : x `@escape(${chunk.node})`;
22925 })
22926 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
22927}
22928
22929function get_slot_scope(lets) {
22930 if (lets.length === 0)
22931 return null;
22932 return {
22933 type: 'ObjectPattern',
22934 properties: lets.map(l => {
22935 return {
22936 type: 'Property',
22937 kind: 'init',
22938 method: false,
22939 shorthand: false,
22940 computed: false,
22941 key: l.name,
22942 value: l.value || l.name
22943 };
22944 })
22945 };
22946}
22947
22948// source: https://html.spec.whatwg.org/multipage/indices.html
22949const boolean_attributes = new Set([
22950 'allowfullscreen',
22951 'allowpaymentrequest',
22952 'async',
22953 'autofocus',
22954 'autoplay',
22955 'checked',
22956 'controls',
22957 'default',
22958 'defer',
22959 'disabled',
22960 'formnovalidate',
22961 'hidden',
22962 'ismap',
22963 'loop',
22964 'multiple',
22965 'muted',
22966 'nomodule',
22967 'novalidate',
22968 'open',
22969 'playsinline',
22970 'readonly',
22971 'required',
22972 'reversed',
22973 'selected'
22974]);
22975
22976// similar logic from `compile/render_dom/wrappers/Fragment`
22977// We want to remove trailing whitespace inside an element/component/block,
22978// *unless* there is no whitespace between this node and its next sibling
22979function remove_whitespace_children(children, next) {
22980 const nodes = [];
22981 let last_child;
22982 let i = children.length;
22983 while (i--) {
22984 const child = children[i];
22985 if (child.type === 'Text') {
22986 if (child.should_skip()) {
22987 continue;
22988 }
22989 let { data } = child;
22990 if (nodes.length === 0) {
22991 const should_trim = next
22992 ? next.type === 'Text' &&
22993 /^\s/.test(next.data) &&
22994 trimmable_at$1(child, next)
22995 : !child.has_ancestor('EachBlock');
22996 if (should_trim) {
22997 data = trim_end(data);
22998 if (!data)
22999 continue;
23000 }
23001 }
23002 // glue text nodes (which could e.g. be separated by comments) together
23003 if (last_child && last_child.type === 'Text') {
23004 last_child.data = data + last_child.data;
23005 continue;
23006 }
23007 nodes.unshift(child);
23008 link(last_child, last_child = child);
23009 }
23010 else {
23011 nodes.unshift(child);
23012 link(last_child, last_child = child);
23013 }
23014 }
23015 const first = nodes[0];
23016 if (first && first.type === 'Text') {
23017 first.data = trim_start(first.data);
23018 if (!first.data) {
23019 first.var = null;
23020 nodes.shift();
23021 if (nodes[0]) {
23022 nodes[0].prev = null;
23023 }
23024 }
23025 }
23026 return nodes;
23027}
23028function trimmable_at$1(child, next_sibling) {
23029 // Whitespace is trimmable if one of the following is true:
23030 // The child and its sibling share a common nearest each block (not at an each block boundary)
23031 // The next sibling's previous node is an each block
23032 return (next_sibling.find_nearest(/EachBlock/) ===
23033 child.find_nearest(/EachBlock/) || next_sibling.prev.type === 'EachBlock');
23034}
23035
23036function Element (node, renderer, options) {
23037 const children = remove_whitespace_children(node.children, node.next);
23038 // awkward special case
23039 let node_contents;
23040 const contenteditable = (node.name !== 'textarea' &&
23041 node.name !== 'input' &&
23042 node.attributes.some((attribute) => attribute.name === 'contenteditable'));
23043 const slot = node.get_static_attribute_value('slot');
23044 const nearest_inline_component = node.find_nearest(/InlineComponent/);
23045 if (slot && nearest_inline_component) {
23046 renderer.push();
23047 }
23048 renderer.add_string(`<${node.name}`);
23049 const class_expression_list = node.classes.map(class_directive => {
23050 const { expression, name } = class_directive;
23051 const snippet = expression ? expression.node : x `#ctx.${name}`; // TODO is this right?
23052 return x `${snippet} ? "${name}" : ""`;
23053 });
23054 if (node.needs_manual_style_scoping) {
23055 class_expression_list.push(x `"${node.component.stylesheet.id}"`);
23056 }
23057 const class_expression = class_expression_list.length > 0 &&
23058 class_expression_list.reduce((lhs, rhs) => x `${lhs} + ' ' + ${rhs}`);
23059 if (node.attributes.some(attr => attr.is_spread)) {
23060 // TODO dry this out
23061 const args = [];
23062 node.attributes.forEach(attribute => {
23063 if (attribute.is_spread) {
23064 args.push(attribute.expression.node);
23065 }
23066 else {
23067 const name = attribute.name.toLowerCase();
23068 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
23069 node_contents = get_attribute_value(attribute);
23070 }
23071 else if (attribute.is_true) {
23072 args.push(x `{ ${attribute.name}: true }`);
23073 }
23074 else if (boolean_attributes.has(name) &&
23075 attribute.chunks.length === 1 &&
23076 attribute.chunks[0].type !== 'Text') {
23077 // a boolean attribute with one non-Text chunk
23078 args.push(x `{ ${attribute.name}: ${attribute.chunks[0].node} || null }`);
23079 }
23080 else {
23081 args.push(x `{ ${attribute.name}: ${get_attribute_value(attribute)} }`);
23082 }
23083 }
23084 });
23085 renderer.add_expression(x `@spread([${args}], ${class_expression})`);
23086 }
23087 else {
23088 let add_class_attribute = !!class_expression;
23089 node.attributes.forEach(attribute => {
23090 const name = attribute.name.toLowerCase();
23091 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
23092 node_contents = get_attribute_value(attribute);
23093 }
23094 else if (attribute.is_true) {
23095 renderer.add_string(` ${attribute.name}`);
23096 }
23097 else if (boolean_attributes.has(name) &&
23098 attribute.chunks.length === 1 &&
23099 attribute.chunks[0].type !== 'Text') {
23100 // a boolean attribute with one non-Text chunk
23101 renderer.add_string(' ');
23102 renderer.add_expression(x `${attribute.chunks[0].node} ? "${attribute.name}" : ""`);
23103 }
23104 else if (name === 'class' && class_expression) {
23105 add_class_attribute = false;
23106 renderer.add_string(` ${attribute.name}="`);
23107 renderer.add_expression(x `[${get_class_attribute_value(attribute)}, ${class_expression}].join(' ').trim()`);
23108 renderer.add_string('"');
23109 }
23110 else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') {
23111 const snippet = attribute.chunks[0].node;
23112 renderer.add_expression(x `@add_attribute("${attribute.name}", ${snippet}, ${boolean_attributes.has(name) ? 1 : 0})`);
23113 }
23114 else {
23115 renderer.add_string(` ${attribute.name}="`);
23116 renderer.add_expression((name === 'class' ? get_class_attribute_value : get_attribute_value)(attribute));
23117 renderer.add_string('"');
23118 }
23119 });
23120 if (add_class_attribute) {
23121 renderer.add_expression(x `@add_classes([${class_expression}].join(' ').trim())`);
23122 }
23123 }
23124 node.bindings.forEach(binding => {
23125 const { name, expression } = binding;
23126 if (binding.is_readonly) {
23127 return;
23128 }
23129 if (name === 'group') ;
23130 else if (contenteditable && (name === 'textContent' || name === 'innerHTML')) {
23131 node_contents = expression.node;
23132 // TODO where was this used?
23133 // value = name === 'textContent' ? x`@escape($$value)` : x`$$value`;
23134 }
23135 else if (binding.name === 'value' && node.name === 'textarea') {
23136 const snippet = expression.node;
23137 node_contents = x `${snippet} || ""`;
23138 }
23139 else {
23140 const snippet = expression.node;
23141 renderer.add_expression(x `@add_attribute("${name}", ${snippet}, 1)`);
23142 }
23143 });
23144 if (options.hydratable && options.head_id) {
23145 renderer.add_string(` data-svelte="${options.head_id}"`);
23146 }
23147 renderer.add_string('>');
23148 if (node_contents !== undefined) {
23149 if (contenteditable) {
23150 renderer.push();
23151 renderer.render(children, options);
23152 const result = renderer.pop();
23153 renderer.add_expression(x `($$value => $$value === void 0 ? ${result} : $$value)(${node_contents})`);
23154 }
23155 else {
23156 renderer.add_expression(node_contents);
23157 }
23158 if (!is_void(node.name)) {
23159 renderer.add_string(`</${node.name}>`);
23160 }
23161 }
23162 else if (slot && nearest_inline_component) {
23163 renderer.render(children, options);
23164 if (!is_void(node.name)) {
23165 renderer.add_string(`</${node.name}>`);
23166 }
23167 const lets = node.lets;
23168 const seen = new Set(lets.map(l => l.name.name));
23169 nearest_inline_component.lets.forEach(l => {
23170 if (!seen.has(l.name.name))
23171 lets.push(l);
23172 });
23173 options.slot_scopes.set(slot, {
23174 input: get_slot_scope(node.lets),
23175 output: renderer.pop()
23176 });
23177 }
23178 else {
23179 renderer.render(children, options);
23180 if (!is_void(node.name)) {
23181 renderer.add_string(`</${node.name}>`);
23182 }
23183 }
23184}
23185
23186function Head (node, renderer, options) {
23187 const head_options = Object.assign(Object.assign({}, options), { head_id: node.id });
23188 renderer.push();
23189 renderer.render(node.children, head_options);
23190 const result = renderer.pop();
23191 renderer.add_expression(x `$$result.head += ${result}, ""`);
23192}
23193
23194function HtmlTag (node, renderer, _options) {
23195 renderer.add_expression(node.expression.node);
23196}
23197
23198function IfBlock (node, renderer, options) {
23199 const condition = node.expression.node;
23200 renderer.push();
23201 renderer.render(node.children, options);
23202 const consequent = renderer.pop();
23203 renderer.push();
23204 if (node.else)
23205 renderer.render(node.else.children, options);
23206 const alternate = renderer.pop();
23207 renderer.add_expression(x `${condition} ? ${consequent} : ${alternate}`);
23208}
23209
23210function get_prop_value(attribute) {
23211 if (attribute.is_true)
23212 return x `true`;
23213 if (attribute.chunks.length === 0)
23214 return x `''`;
23215 return attribute.chunks
23216 .map(chunk => {
23217 if (chunk.type === 'Text')
23218 return string_literal(chunk.data);
23219 return chunk.node;
23220 })
23221 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
23222}
23223function InlineComponent (node, renderer, options) {
23224 const binding_props = [];
23225 const binding_fns = [];
23226 node.bindings.forEach(binding => {
23227 renderer.has_bindings = true;
23228 // TODO this probably won't work for contextual bindings
23229 const snippet = binding.expression.node;
23230 binding_props.push(p `${binding.name}: ${snippet}`);
23231 binding_fns.push(p `${binding.name}: $$value => { ${snippet} = $$value; $$settled = false }`);
23232 });
23233 const uses_spread = node.attributes.find(attr => attr.is_spread);
23234 let props;
23235 if (uses_spread) {
23236 props = x `@_Object.assign(${node.attributes
23237 .map(attribute => {
23238 if (attribute.is_spread) {
23239 return attribute.expression.node;
23240 }
23241 else {
23242 return x `{ ${attribute.name}: ${get_prop_value(attribute)} }`;
23243 }
23244 })
23245 .concat(binding_props.map(p => x `{ ${p} }`))})`;
23246 }
23247 else {
23248 props = x `{
23249 ${node.attributes.map(attribute => p `${attribute.name}: ${get_prop_value(attribute)}`)},
23250 ${binding_props}
23251 }`;
23252 }
23253 const bindings = x `{
23254 ${binding_fns}
23255 }`;
23256 const expression = (node.name === 'svelte:self'
23257 ? renderer.name
23258 : node.name === 'svelte:component'
23259 ? x `(${node.expression.node}) || @missing_component`
23260 : node.name.split('.').reduce(((lhs, rhs) => x `${lhs}.${rhs}`)));
23261 const slot_fns = [];
23262 const children = remove_whitespace_children(node.children, node.next);
23263 if (children.length) {
23264 const slot_scopes = new Map();
23265 renderer.push();
23266 renderer.render(children, Object.assign({}, options, {
23267 slot_scopes
23268 }));
23269 slot_scopes.set('default', {
23270 input: get_slot_scope(node.lets),
23271 output: renderer.pop()
23272 });
23273 slot_scopes.forEach(({ input, output }, name) => {
23274 if (!is_empty_template_literal(output)) {
23275 slot_fns.push(p `${name}: (${input}) => ${output}`);
23276 }
23277 });
23278 }
23279 const slots = x `{
23280 ${slot_fns}
23281 }`;
23282 renderer.add_expression(x `@validate_component(${expression}, "${node.name}").$$render($$result, ${props}, ${bindings}, ${slots})`);
23283}
23284function is_empty_template_literal(template_literal) {
23285 return (template_literal.expressions.length === 0 &&
23286 template_literal.quasis.length === 1 &&
23287 template_literal.quasis[0].value.raw === '');
23288}
23289
23290function KeyBlock (node, renderer, options) {
23291 renderer.render(node.children, options);
23292}
23293
23294function Slot (node, renderer, options) {
23295 const slot_data = get_slot_data(node.values);
23296 const slot = node.get_static_attribute_value('slot');
23297 const nearest_inline_component = node.find_nearest(/InlineComponent/);
23298 if (slot && nearest_inline_component) {
23299 renderer.push();
23300 }
23301 renderer.push();
23302 renderer.render(node.children, options);
23303 const result = renderer.pop();
23304 renderer.add_expression(x `
23305 #slots.${node.slot_name}
23306 ? #slots.${node.slot_name}(${slot_data})
23307 : ${result}
23308 `);
23309 if (slot && nearest_inline_component) {
23310 const lets = node.lets;
23311 const seen = new Set(lets.map(l => l.name.name));
23312 nearest_inline_component.lets.forEach(l => {
23313 if (!seen.has(l.name.name))
23314 lets.push(l);
23315 });
23316 options.slot_scopes.set(slot, {
23317 input: get_slot_scope(node.lets),
23318 output: renderer.pop()
23319 });
23320 }
23321}
23322
23323function Tag$1 (node, renderer, _options) {
23324 const snippet = node.expression.node;
23325 renderer.add_expression(node.parent &&
23326 node.parent.type === 'Element' &&
23327 node.parent.name === 'style'
23328 ? snippet
23329 : x `@escape(${snippet})`);
23330}
23331
23332function Text (node, renderer, _options) {
23333 let text = node.data;
23334 if (!node.parent ||
23335 node.parent.type !== 'Element' ||
23336 (node.parent.name !== 'script' && node.parent.name !== 'style')) {
23337 // unless this Text node is inside a <script> or <style> element, escape &,<,>
23338 text = escape_html(text);
23339 }
23340 renderer.add_string(text);
23341}
23342
23343function Title (node, renderer, options) {
23344 renderer.push();
23345 renderer.add_string('<title>');
23346 renderer.render(node.children, options);
23347 renderer.add_string('</title>');
23348 const result = renderer.pop();
23349 renderer.add_expression(x `$$result.title = ${result}, ""`);
23350}
23351
23352function noop$1() { }
23353const handlers$1 = {
23354 AwaitBlock,
23355 Body: noop$1,
23356 Comment: Comment$1,
23357 DebugTag,
23358 EachBlock,
23359 Element,
23360 Head,
23361 IfBlock,
23362 InlineComponent,
23363 KeyBlock,
23364 MustacheTag: Tag$1,
23365 Options: noop$1,
23366 RawMustacheTag: HtmlTag,
23367 Slot,
23368 Text,
23369 Title,
23370 Window: noop$1
23371};
23372class Renderer$1 {
23373 constructor({ name }) {
23374 this.has_bindings = false;
23375 this.stack = [];
23376 this.targets = [];
23377 this.name = name;
23378 this.push();
23379 }
23380 add_string(str) {
23381 this.current.value += escape_template(str);
23382 }
23383 add_expression(node) {
23384 this.literal.quasis.push({
23385 type: 'TemplateElement',
23386 value: { raw: this.current.value, cooked: null },
23387 tail: false
23388 });
23389 this.literal.expressions.push(node);
23390 this.current.value = '';
23391 }
23392 push() {
23393 const current = this.current = { value: '' };
23394 const literal = this.literal = {
23395 type: 'TemplateLiteral',
23396 expressions: [],
23397 quasis: []
23398 };
23399 this.stack.push({ current, literal });
23400 }
23401 pop() {
23402 this.literal.quasis.push({
23403 type: 'TemplateElement',
23404 value: { raw: this.current.value, cooked: null },
23405 tail: true
23406 });
23407 const popped = this.stack.pop();
23408 const last = this.stack[this.stack.length - 1];
23409 if (last) {
23410 this.literal = last.literal;
23411 this.current = last.current;
23412 }
23413 return popped.literal;
23414 }
23415 render(nodes, options) {
23416 nodes.forEach(node => {
23417 const handler = handlers$1[node.type];
23418 if (!handler) {
23419 throw new Error(`No handler for '${node.type}' nodes`);
23420 }
23421 handler(node, this, options);
23422 });
23423 }
23424}
23425
23426function ssr(component, options) {
23427 const renderer = new Renderer$1({
23428 name: component.name
23429 });
23430 const { name } = component;
23431 // create $$render function
23432 renderer.render(trim(component.fragment.children), Object.assign({
23433 locate: component.locate
23434 }, options));
23435 // TODO put this inside the Renderer class
23436 const literal = renderer.pop();
23437 // TODO concatenate CSS maps
23438 const css = options.customElement ?
23439 { code: null, map: null } :
23440 component.stylesheet.render(options.filename, true);
23441 const uses_rest = component.var_lookup.has('$$restProps');
23442 const props = component.vars.filter(variable => !variable.module && variable.export_name);
23443 const rest = uses_rest ? b `let $$restProps = @compute_rest_props($$props, [${props.map(prop => `"${prop.export_name}"`).join(',')}]);` : null;
23444 const uses_slots = component.var_lookup.has('$$slots');
23445 const slots = uses_slots ? b `let $$slots = @compute_slots(#slots);` : null;
23446 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
23447 const reactive_store_subscriptions = reactive_stores
23448 .filter(store => {
23449 const variable = component.var_lookup.get(store.name.slice(1));
23450 return !variable || variable.hoistable;
23451 })
23452 .map(({ name }) => {
23453 const store_name = name.slice(1);
23454 return b `
23455 ${component.compile_options.dev && b `@validate_store(${store_name}, '${store_name}');`}
23456 ${`$$unsubscribe_${store_name}`} = @subscribe(${store_name}, #value => ${name} = #value)
23457 ${store_name}.subscribe($$value => ${name} = $$value);
23458 `;
23459 });
23460 const reactive_store_unsubscriptions = reactive_stores.map(({ name }) => b `${`$$unsubscribe_${name.slice(1)}`}()`);
23461 const reactive_store_declarations = reactive_stores
23462 .map(({ name }) => {
23463 const store_name = name.slice(1);
23464 const store = component.var_lookup.get(store_name);
23465 if (store && store.reassigned) {
23466 const unsubscribe = `$$unsubscribe_${store_name}`;
23467 const subscribe = `$$subscribe_${store_name}`;
23468 return b `let ${name}, ${unsubscribe} = @noop, ${subscribe} = () => (${unsubscribe}(), ${unsubscribe} = @subscribe(${store_name}, $$value => ${name} = $$value), ${store_name})`;
23469 }
23470 return b `let ${name}, ${`$$unsubscribe_${store_name}`};`;
23471 });
23472 // instrument get/set store value
23473 if (component.ast.instance) {
23474 let scope = component.instance_scope;
23475 const map = component.instance_scope_map;
23476 walk(component.ast.instance.content, {
23477 enter(node) {
23478 if (map.has(node)) {
23479 scope = map.get(node);
23480 }
23481 },
23482 leave(node) {
23483 if (map.has(node)) {
23484 scope = scope.parent;
23485 }
23486 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
23487 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
23488 const names = new Set(extract_names(assignee));
23489 const to_invalidate = new Set();
23490 for (const name of names) {
23491 const variable = component.var_lookup.get(name);
23492 if (variable &&
23493 !variable.hoistable &&
23494 !variable.global &&
23495 !variable.module &&
23496 (variable.subscribable || variable.name[0] === '$')) {
23497 to_invalidate.add(variable.name);
23498 }
23499 }
23500 if (to_invalidate.size) {
23501 this.replace(invalidate({ component }, scope, node, to_invalidate, true));
23502 }
23503 }
23504 }
23505 });
23506 }
23507 component.rewrite_props(({ name, reassigned }) => {
23508 const value = `$${name}`;
23509 let insert = reassigned
23510 ? b `${`$$subscribe_${name}`}()`
23511 : b `${`$$unsubscribe_${name}`} = @subscribe(${name}, #value => $${value} = #value)`;
23512 if (component.compile_options.dev) {
23513 insert = b `@validate_store(${name}, '${name}'); ${insert}`;
23514 }
23515 return insert;
23516 });
23517 const instance_javascript = component.extract_javascript(component.ast.instance);
23518 // TODO only do this for props with a default value
23519 const parent_bindings = instance_javascript
23520 ? component.vars
23521 .filter(variable => !variable.module && variable.export_name)
23522 .map(prop => {
23523 return b `if ($$props.${prop.export_name} === void 0 && $$bindings.${prop.export_name} && ${prop.name} !== void 0) $$bindings.${prop.export_name}(${prop.name});`;
23524 })
23525 : [];
23526 const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
23527 const variable = component.var_lookup.get(name);
23528 return variable.injected;
23529 });
23530 const reactive_declarations = component.reactive_declarations.map(d => {
23531 const body = d.node.body;
23532 let statement = b `${body}`;
23533 if (!d.declaration) { // TODO do not add label if it's not referenced
23534 statement = b `$: { ${statement} }`;
23535 }
23536 return statement;
23537 });
23538 const main = renderer.has_bindings
23539 ? b `
23540 let $$settled;
23541 let $$rendered;
23542
23543 do {
23544 $$settled = true;
23545
23546 ${reactive_declarations}
23547
23548 $$rendered = ${literal};
23549 } while (!$$settled);
23550
23551 ${reactive_store_unsubscriptions}
23552
23553 return $$rendered;
23554 `
23555 : b `
23556 ${reactive_declarations}
23557
23558 ${reactive_store_unsubscriptions}
23559
23560 return ${literal};`;
23561 const blocks = [
23562 ...injected.map(name => b `let ${name};`),
23563 rest,
23564 slots,
23565 ...reactive_store_declarations,
23566 ...reactive_store_subscriptions,
23567 instance_javascript,
23568 ...parent_bindings,
23569 css.code && b `$$result.css.add(#css);`,
23570 main
23571 ].filter(Boolean);
23572 const js = b `
23573 ${css.code ? b `
23574 const #css = {
23575 code: "${css.code}",
23576 map: ${css.map ? string_literal(css.map.toString()) : 'null'}
23577 };` : null}
23578
23579 ${component.extract_javascript(component.ast.module)}
23580
23581 ${component.fully_hoisted}
23582
23583 const ${name} = @create_ssr_component(($$result, $$props, $$bindings, #slots) => {
23584 ${blocks}
23585 });
23586 `;
23587 return { js, css };
23588}
23589function trim(nodes) {
23590 let start = 0;
23591 for (; start < nodes.length; start += 1) {
23592 const node = nodes[start];
23593 if (node.type !== 'Text')
23594 break;
23595 node.data = node.data.replace(/^\s+/, '');
23596 if (node.data)
23597 break;
23598 }
23599 let end = nodes.length;
23600 for (; end > start; end -= 1) {
23601 const node = nodes[end - 1];
23602 if (node.type !== 'Text')
23603 break;
23604 node.data = node.data.replace(/\s+$/, '');
23605 if (node.data)
23606 break;
23607 }
23608 return nodes.slice(start, end);
23609}
23610
23611const wrappers$1 = { esm, cjs };
23612function create_module(program, format, name, banner, sveltePath = 'svelte', helpers, globals, imports, module_exports) {
23613 const internal_path = `${sveltePath}/internal`;
23614 helpers.sort((a, b) => (a.name < b.name) ? -1 : 1);
23615 globals.sort((a, b) => (a.name < b.name) ? -1 : 1);
23616 if (format === 'esm') {
23617 return esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
23618 }
23619 if (format === 'cjs')
23620 return cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
23621 throw new Error(`options.format is invalid (must be ${list$1(Object.keys(wrappers$1))})`);
23622}
23623function edit_source(source, sveltePath) {
23624 return source === 'svelte' || source.startsWith('svelte/')
23625 ? source.replace('svelte', sveltePath)
23626 : source;
23627}
23628function get_internal_globals(globals, helpers) {
23629 return globals.length > 0 && {
23630 type: 'VariableDeclaration',
23631 kind: 'const',
23632 declarations: [{
23633 type: 'VariableDeclarator',
23634 id: {
23635 type: 'ObjectPattern',
23636 properties: globals.map(g => ({
23637 type: 'Property',
23638 method: false,
23639 shorthand: false,
23640 computed: false,
23641 key: { type: 'Identifier', name: g.name },
23642 value: g.alias,
23643 kind: 'init'
23644 }))
23645 },
23646 init: helpers.find(({ name }) => name === 'globals').alias
23647 }]
23648 };
23649}
23650function esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
23651 const import_declaration = {
23652 type: 'ImportDeclaration',
23653 specifiers: helpers.map(h => ({
23654 type: 'ImportSpecifier',
23655 local: h.alias,
23656 imported: { type: 'Identifier', name: h.name }
23657 })),
23658 source: { type: 'Literal', value: internal_path }
23659 };
23660 const internal_globals = get_internal_globals(globals, helpers);
23661 // edit user imports
23662 imports.forEach(node => {
23663 node.source.value = edit_source(node.source.value, sveltePath);
23664 });
23665 const exports = module_exports.length > 0 && {
23666 type: 'ExportNamedDeclaration',
23667 specifiers: module_exports.map(x => ({
23668 type: 'Specifier',
23669 local: { type: 'Identifier', name: x.name },
23670 exported: { type: 'Identifier', name: x.as }
23671 }))
23672 };
23673 program.body = b `
23674 /* ${banner} */
23675
23676 ${import_declaration}
23677 ${internal_globals}
23678 ${imports}
23679
23680 ${program.body}
23681
23682 export default ${name};
23683 ${exports}
23684 `;
23685}
23686function cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
23687 const internal_requires = {
23688 type: 'VariableDeclaration',
23689 kind: 'const',
23690 declarations: [{
23691 type: 'VariableDeclarator',
23692 id: {
23693 type: 'ObjectPattern',
23694 properties: helpers.map(h => ({
23695 type: 'Property',
23696 method: false,
23697 shorthand: false,
23698 computed: false,
23699 key: { type: 'Identifier', name: h.name },
23700 value: h.alias,
23701 kind: 'init'
23702 }))
23703 },
23704 init: x `require("${internal_path}")`
23705 }]
23706 };
23707 const internal_globals = get_internal_globals(globals, helpers);
23708 const user_requires = imports.map(node => {
23709 const init = x `require("${edit_source(node.source.value, sveltePath)}")`;
23710 if (node.specifiers.length === 0) {
23711 return b `${init};`;
23712 }
23713 return {
23714 type: 'VariableDeclaration',
23715 kind: 'const',
23716 declarations: [{
23717 type: 'VariableDeclarator',
23718 id: node.specifiers[0].type === 'ImportNamespaceSpecifier'
23719 ? { type: 'Identifier', name: node.specifiers[0].local.name }
23720 : {
23721 type: 'ObjectPattern',
23722 properties: node.specifiers.map(s => ({
23723 type: 'Property',
23724 method: false,
23725 shorthand: false,
23726 computed: false,
23727 key: s.type === 'ImportSpecifier' ? s.imported : { type: 'Identifier', name: 'default' },
23728 value: s.local,
23729 kind: 'init'
23730 }))
23731 },
23732 init
23733 }]
23734 };
23735 });
23736 const exports = module_exports.map(x => b `exports.${{ type: 'Identifier', name: x.as }} = ${{ type: 'Identifier', name: x.name }};`);
23737 program.body = b `
23738 /* ${banner} */
23739
23740 "use strict";
23741 ${internal_requires}
23742 ${internal_globals}
23743 ${user_requires}
23744
23745 ${program.body}
23746
23747 exports.default = ${name};
23748 ${exports}
23749 `;
23750}
23751
23752var Chunk = function Chunk(start, end, content) {
23753 this.start = start;
23754 this.end = end;
23755 this.original = content;
23756
23757 this.intro = '';
23758 this.outro = '';
23759
23760 this.content = content;
23761 this.storeName = false;
23762 this.edited = false;
23763
23764 // we make these non-enumerable, for sanity while debugging
23765 Object.defineProperties(this, {
23766 previous: { writable: true, value: null },
23767 next: { writable: true, value: null }
23768 });
23769};
23770
23771Chunk.prototype.appendLeft = function appendLeft (content) {
23772 this.outro += content;
23773};
23774
23775Chunk.prototype.appendRight = function appendRight (content) {
23776 this.intro = this.intro + content;
23777};
23778
23779Chunk.prototype.clone = function clone () {
23780 var chunk = new Chunk(this.start, this.end, this.original);
23781
23782 chunk.intro = this.intro;
23783 chunk.outro = this.outro;
23784 chunk.content = this.content;
23785 chunk.storeName = this.storeName;
23786 chunk.edited = this.edited;
23787
23788 return chunk;
23789};
23790
23791Chunk.prototype.contains = function contains (index) {
23792 return this.start < index && index < this.end;
23793};
23794
23795Chunk.prototype.eachNext = function eachNext (fn) {
23796 var chunk = this;
23797 while (chunk) {
23798 fn(chunk);
23799 chunk = chunk.next;
23800 }
23801};
23802
23803Chunk.prototype.eachPrevious = function eachPrevious (fn) {
23804 var chunk = this;
23805 while (chunk) {
23806 fn(chunk);
23807 chunk = chunk.previous;
23808 }
23809};
23810
23811Chunk.prototype.edit = function edit (content, storeName, contentOnly) {
23812 this.content = content;
23813 if (!contentOnly) {
23814 this.intro = '';
23815 this.outro = '';
23816 }
23817 this.storeName = storeName;
23818
23819 this.edited = true;
23820
23821 return this;
23822};
23823
23824Chunk.prototype.prependLeft = function prependLeft (content) {
23825 this.outro = content + this.outro;
23826};
23827
23828Chunk.prototype.prependRight = function prependRight (content) {
23829 this.intro = content + this.intro;
23830};
23831
23832Chunk.prototype.split = function split (index) {
23833 var sliceIndex = index - this.start;
23834
23835 var originalBefore = this.original.slice(0, sliceIndex);
23836 var originalAfter = this.original.slice(sliceIndex);
23837
23838 this.original = originalBefore;
23839
23840 var newChunk = new Chunk(index, this.end, originalAfter);
23841 newChunk.outro = this.outro;
23842 this.outro = '';
23843
23844 this.end = index;
23845
23846 if (this.edited) {
23847 // TODO is this block necessary?...
23848 newChunk.edit('', false);
23849 this.content = '';
23850 } else {
23851 this.content = originalBefore;
23852 }
23853
23854 newChunk.next = this.next;
23855 if (newChunk.next) { newChunk.next.previous = newChunk; }
23856 newChunk.previous = this;
23857 this.next = newChunk;
23858
23859 return newChunk;
23860};
23861
23862Chunk.prototype.toString = function toString () {
23863 return this.intro + this.content + this.outro;
23864};
23865
23866Chunk.prototype.trimEnd = function trimEnd (rx) {
23867 this.outro = this.outro.replace(rx, '');
23868 if (this.outro.length) { return true; }
23869
23870 var trimmed = this.content.replace(rx, '');
23871
23872 if (trimmed.length) {
23873 if (trimmed !== this.content) {
23874 this.split(this.start + trimmed.length).edit('', undefined, true);
23875 }
23876 return true;
23877
23878 } else {
23879 this.edit('', undefined, true);
23880
23881 this.intro = this.intro.replace(rx, '');
23882 if (this.intro.length) { return true; }
23883 }
23884};
23885
23886Chunk.prototype.trimStart = function trimStart (rx) {
23887 this.intro = this.intro.replace(rx, '');
23888 if (this.intro.length) { return true; }
23889
23890 var trimmed = this.content.replace(rx, '');
23891
23892 if (trimmed.length) {
23893 if (trimmed !== this.content) {
23894 this.split(this.end - trimmed.length);
23895 this.edit('', undefined, true);
23896 }
23897 return true;
23898
23899 } else {
23900 this.edit('', undefined, true);
23901
23902 this.outro = this.outro.replace(rx, '');
23903 if (this.outro.length) { return true; }
23904 }
23905};
23906
23907var btoa$2 = function () {
23908 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
23909};
23910if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
23911 btoa$2 = function (str) { return window.btoa(unescape(encodeURIComponent(str))); };
23912} else if (typeof Buffer === 'function') {
23913 btoa$2 = function (str) { return Buffer.from(str, 'utf-8').toString('base64'); };
23914}
23915
23916var SourceMap$1 = function SourceMap(properties) {
23917 this.version = 3;
23918 this.file = properties.file;
23919 this.sources = properties.sources;
23920 this.sourcesContent = properties.sourcesContent;
23921 this.names = properties.names;
23922 this.mappings = encode(properties.mappings);
23923};
23924
23925SourceMap$1.prototype.toString = function toString () {
23926 return JSON.stringify(this);
23927};
23928
23929SourceMap$1.prototype.toUrl = function toUrl () {
23930 return 'data:application/json;charset=utf-8;base64,' + btoa$2(this.toString());
23931};
23932
23933function guessIndent(code) {
23934 var lines = code.split('\n');
23935
23936 var tabbed = lines.filter(function (line) { return /^\t+/.test(line); });
23937 var spaced = lines.filter(function (line) { return /^ {2,}/.test(line); });
23938
23939 if (tabbed.length === 0 && spaced.length === 0) {
23940 return null;
23941 }
23942
23943 // More lines tabbed than spaced? Assume tabs, and
23944 // default to tabs in the case of a tie (or nothing
23945 // to go on)
23946 if (tabbed.length >= spaced.length) {
23947 return '\t';
23948 }
23949
23950 // Otherwise, we need to guess the multiple
23951 var min = spaced.reduce(function (previous, current) {
23952 var numSpaces = /^ +/.exec(current)[0].length;
23953 return Math.min(numSpaces, previous);
23954 }, Infinity);
23955
23956 return new Array(min + 1).join(' ');
23957}
23958
23959function getRelativePath(from, to) {
23960 var fromParts = from.split(/[/\\]/);
23961 var toParts = to.split(/[/\\]/);
23962
23963 fromParts.pop(); // get dirname
23964
23965 while (fromParts[0] === toParts[0]) {
23966 fromParts.shift();
23967 toParts.shift();
23968 }
23969
23970 if (fromParts.length) {
23971 var i = fromParts.length;
23972 while (i--) { fromParts[i] = '..'; }
23973 }
23974
23975 return fromParts.concat(toParts).join('/');
23976}
23977
23978var toString$1 = Object.prototype.toString;
23979
23980function isObject(thing) {
23981 return toString$1.call(thing) === '[object Object]';
23982}
23983
23984function getLocator$1(source) {
23985 var originalLines = source.split('\n');
23986 var lineOffsets = [];
23987
23988 for (var i = 0, pos = 0; i < originalLines.length; i++) {
23989 lineOffsets.push(pos);
23990 pos += originalLines[i].length + 1;
23991 }
23992
23993 return function locate(index) {
23994 var i = 0;
23995 var j = lineOffsets.length;
23996 while (i < j) {
23997 var m = (i + j) >> 1;
23998 if (index < lineOffsets[m]) {
23999 j = m;
24000 } else {
24001 i = m + 1;
24002 }
24003 }
24004 var line = i - 1;
24005 var column = index - lineOffsets[line];
24006 return { line: line, column: column };
24007 };
24008}
24009
24010var Mappings = function Mappings(hires) {
24011 this.hires = hires;
24012 this.generatedCodeLine = 0;
24013 this.generatedCodeColumn = 0;
24014 this.raw = [];
24015 this.rawSegments = this.raw[this.generatedCodeLine] = [];
24016 this.pending = null;
24017};
24018
24019Mappings.prototype.addEdit = function addEdit (sourceIndex, content, loc, nameIndex) {
24020 if (content.length) {
24021 var segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
24022 if (nameIndex >= 0) {
24023 segment.push(nameIndex);
24024 }
24025 this.rawSegments.push(segment);
24026 } else if (this.pending) {
24027 this.rawSegments.push(this.pending);
24028 }
24029
24030 this.advance(content);
24031 this.pending = null;
24032};
24033
24034Mappings.prototype.addUneditedChunk = function addUneditedChunk (sourceIndex, chunk, original, loc, sourcemapLocations) {
24035 var originalCharIndex = chunk.start;
24036 var first = true;
24037
24038 while (originalCharIndex < chunk.end) {
24039 if (this.hires || first || sourcemapLocations[originalCharIndex]) {
24040 this.rawSegments.push([this.generatedCodeColumn, sourceIndex, loc.line, loc.column]);
24041 }
24042
24043 if (original[originalCharIndex] === '\n') {
24044 loc.line += 1;
24045 loc.column = 0;
24046 this.generatedCodeLine += 1;
24047 this.raw[this.generatedCodeLine] = this.rawSegments = [];
24048 this.generatedCodeColumn = 0;
24049 } else {
24050 loc.column += 1;
24051 this.generatedCodeColumn += 1;
24052 }
24053
24054 originalCharIndex += 1;
24055 first = false;
24056 }
24057
24058 this.pending = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
24059};
24060
24061Mappings.prototype.advance = function advance (str) {
24062 if (!str) { return; }
24063
24064 var lines = str.split('\n');
24065
24066 if (lines.length > 1) {
24067 for (var i = 0; i < lines.length - 1; i++) {
24068 this.generatedCodeLine++;
24069 this.raw[this.generatedCodeLine] = this.rawSegments = [];
24070 }
24071 this.generatedCodeColumn = 0;
24072 }
24073
24074 this.generatedCodeColumn += lines[lines.length - 1].length;
24075};
24076
24077var n = '\n';
24078
24079var warned = {
24080 insertLeft: false,
24081 insertRight: false,
24082 storeName: false
24083};
24084
24085var MagicString = function MagicString(string, options) {
24086 if ( options === void 0 ) options = {};
24087
24088 var chunk = new Chunk(0, string.length, string);
24089
24090 Object.defineProperties(this, {
24091 original: { writable: true, value: string },
24092 outro: { writable: true, value: '' },
24093 intro: { writable: true, value: '' },
24094 firstChunk: { writable: true, value: chunk },
24095 lastChunk: { writable: true, value: chunk },
24096 lastSearchedChunk: { writable: true, value: chunk },
24097 byStart: { writable: true, value: {} },
24098 byEnd: { writable: true, value: {} },
24099 filename: { writable: true, value: options.filename },
24100 indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
24101 sourcemapLocations: { writable: true, value: {} },
24102 storedNames: { writable: true, value: {} },
24103 indentStr: { writable: true, value: guessIndent(string) }
24104 });
24105
24106 this.byStart[0] = chunk;
24107 this.byEnd[string.length] = chunk;
24108};
24109
24110MagicString.prototype.addSourcemapLocation = function addSourcemapLocation (char) {
24111 this.sourcemapLocations[char] = true;
24112};
24113
24114MagicString.prototype.append = function append (content) {
24115 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
24116
24117 this.outro += content;
24118 return this;
24119};
24120
24121MagicString.prototype.appendLeft = function appendLeft (index, content) {
24122 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
24123
24124 this._split(index);
24125
24126 var chunk = this.byEnd[index];
24127
24128 if (chunk) {
24129 chunk.appendLeft(content);
24130 } else {
24131 this.intro += content;
24132 }
24133 return this;
24134};
24135
24136MagicString.prototype.appendRight = function appendRight (index, content) {
24137 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
24138
24139 this._split(index);
24140
24141 var chunk = this.byStart[index];
24142
24143 if (chunk) {
24144 chunk.appendRight(content);
24145 } else {
24146 this.outro += content;
24147 }
24148 return this;
24149};
24150
24151MagicString.prototype.clone = function clone () {
24152 var cloned = new MagicString(this.original, { filename: this.filename });
24153
24154 var originalChunk = this.firstChunk;
24155 var clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());
24156
24157 while (originalChunk) {
24158 cloned.byStart[clonedChunk.start] = clonedChunk;
24159 cloned.byEnd[clonedChunk.end] = clonedChunk;
24160
24161 var nextOriginalChunk = originalChunk.next;
24162 var nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
24163
24164 if (nextClonedChunk) {
24165 clonedChunk.next = nextClonedChunk;
24166 nextClonedChunk.previous = clonedChunk;
24167
24168 clonedChunk = nextClonedChunk;
24169 }
24170
24171 originalChunk = nextOriginalChunk;
24172 }
24173
24174 cloned.lastChunk = clonedChunk;
24175
24176 if (this.indentExclusionRanges) {
24177 cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
24178 }
24179
24180 Object.keys(this.sourcemapLocations).forEach(function (loc) {
24181 cloned.sourcemapLocations[loc] = true;
24182 });
24183
24184 return cloned;
24185};
24186
24187MagicString.prototype.generateDecodedMap = function generateDecodedMap (options) {
24188 var this$1 = this;
24189
24190 options = options || {};
24191
24192 var sourceIndex = 0;
24193 var names = Object.keys(this.storedNames);
24194 var mappings = new Mappings(options.hires);
24195
24196 var locate = getLocator$1(this.original);
24197
24198 if (this.intro) {
24199 mappings.advance(this.intro);
24200 }
24201
24202 this.firstChunk.eachNext(function (chunk) {
24203 var loc = locate(chunk.start);
24204
24205 if (chunk.intro.length) { mappings.advance(chunk.intro); }
24206
24207 if (chunk.edited) {
24208 mappings.addEdit(
24209 sourceIndex,
24210 chunk.content,
24211 loc,
24212 chunk.storeName ? names.indexOf(chunk.original) : -1
24213 );
24214 } else {
24215 mappings.addUneditedChunk(sourceIndex, chunk, this$1.original, loc, this$1.sourcemapLocations);
24216 }
24217
24218 if (chunk.outro.length) { mappings.advance(chunk.outro); }
24219 });
24220
24221 return {
24222 file: options.file ? options.file.split(/[/\\]/).pop() : null,
24223 sources: [options.source ? getRelativePath(options.file || '', options.source) : null],
24224 sourcesContent: options.includeContent ? [this.original] : [null],
24225 names: names,
24226 mappings: mappings.raw
24227 };
24228};
24229
24230MagicString.prototype.generateMap = function generateMap (options) {
24231 return new SourceMap$1(this.generateDecodedMap(options));
24232};
24233
24234MagicString.prototype.getIndentString = function getIndentString () {
24235 return this.indentStr === null ? '\t' : this.indentStr;
24236};
24237
24238MagicString.prototype.indent = function indent (indentStr, options) {
24239 var pattern = /^[^\r\n]/gm;
24240
24241 if (isObject(indentStr)) {
24242 options = indentStr;
24243 indentStr = undefined;
24244 }
24245
24246 indentStr = indentStr !== undefined ? indentStr : this.indentStr || '\t';
24247
24248 if (indentStr === '') { return this; } // noop
24249
24250 options = options || {};
24251
24252 // Process exclusion ranges
24253 var isExcluded = {};
24254
24255 if (options.exclude) {
24256 var exclusions =
24257 typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;
24258 exclusions.forEach(function (exclusion) {
24259 for (var i = exclusion[0]; i < exclusion[1]; i += 1) {
24260 isExcluded[i] = true;
24261 }
24262 });
24263 }
24264
24265 var shouldIndentNextCharacter = options.indentStart !== false;
24266 var replacer = function (match) {
24267 if (shouldIndentNextCharacter) { return ("" + indentStr + match); }
24268 shouldIndentNextCharacter = true;
24269 return match;
24270 };
24271
24272 this.intro = this.intro.replace(pattern, replacer);
24273
24274 var charIndex = 0;
24275 var chunk = this.firstChunk;
24276
24277 while (chunk) {
24278 var end = chunk.end;
24279
24280 if (chunk.edited) {
24281 if (!isExcluded[charIndex]) {
24282 chunk.content = chunk.content.replace(pattern, replacer);
24283
24284 if (chunk.content.length) {
24285 shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';
24286 }
24287 }
24288 } else {
24289 charIndex = chunk.start;
24290
24291 while (charIndex < end) {
24292 if (!isExcluded[charIndex]) {
24293 var char = this.original[charIndex];
24294
24295 if (char === '\n') {
24296 shouldIndentNextCharacter = true;
24297 } else if (char !== '\r' && shouldIndentNextCharacter) {
24298 shouldIndentNextCharacter = false;
24299
24300 if (charIndex === chunk.start) {
24301 chunk.prependRight(indentStr);
24302 } else {
24303 this._splitChunk(chunk, charIndex);
24304 chunk = chunk.next;
24305 chunk.prependRight(indentStr);
24306 }
24307 }
24308 }
24309
24310 charIndex += 1;
24311 }
24312 }
24313
24314 charIndex = chunk.end;
24315 chunk = chunk.next;
24316 }
24317
24318 this.outro = this.outro.replace(pattern, replacer);
24319
24320 return this;
24321};
24322
24323MagicString.prototype.insert = function insert () {
24324 throw new Error('magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)');
24325};
24326
24327MagicString.prototype.insertLeft = function insertLeft (index, content) {
24328 if (!warned.insertLeft) {
24329 console.warn('magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead'); // eslint-disable-line no-console
24330 warned.insertLeft = true;
24331 }
24332
24333 return this.appendLeft(index, content);
24334};
24335
24336MagicString.prototype.insertRight = function insertRight (index, content) {
24337 if (!warned.insertRight) {
24338 console.warn('magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead'); // eslint-disable-line no-console
24339 warned.insertRight = true;
24340 }
24341
24342 return this.prependRight(index, content);
24343};
24344
24345MagicString.prototype.move = function move (start, end, index) {
24346 if (index >= start && index <= end) { throw new Error('Cannot move a selection inside itself'); }
24347
24348 this._split(start);
24349 this._split(end);
24350 this._split(index);
24351
24352 var first = this.byStart[start];
24353 var last = this.byEnd[end];
24354
24355 var oldLeft = first.previous;
24356 var oldRight = last.next;
24357
24358 var newRight = this.byStart[index];
24359 if (!newRight && last === this.lastChunk) { return this; }
24360 var newLeft = newRight ? newRight.previous : this.lastChunk;
24361
24362 if (oldLeft) { oldLeft.next = oldRight; }
24363 if (oldRight) { oldRight.previous = oldLeft; }
24364
24365 if (newLeft) { newLeft.next = first; }
24366 if (newRight) { newRight.previous = last; }
24367
24368 if (!first.previous) { this.firstChunk = last.next; }
24369 if (!last.next) {
24370 this.lastChunk = first.previous;
24371 this.lastChunk.next = null;
24372 }
24373
24374 first.previous = newLeft;
24375 last.next = newRight || null;
24376
24377 if (!newLeft) { this.firstChunk = first; }
24378 if (!newRight) { this.lastChunk = last; }
24379 return this;
24380};
24381
24382MagicString.prototype.overwrite = function overwrite (start, end, content, options) {
24383 if (typeof content !== 'string') { throw new TypeError('replacement content must be a string'); }
24384
24385 while (start < 0) { start += this.original.length; }
24386 while (end < 0) { end += this.original.length; }
24387
24388 if (end > this.original.length) { throw new Error('end is out of bounds'); }
24389 if (start === end)
24390 { throw new Error('Cannot overwrite a zero-length range – use appendLeft or prependRight instead'); }
24391
24392 this._split(start);
24393 this._split(end);
24394
24395 if (options === true) {
24396 if (!warned.storeName) {
24397 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
24398 warned.storeName = true;
24399 }
24400
24401 options = { storeName: true };
24402 }
24403 var storeName = options !== undefined ? options.storeName : false;
24404 var contentOnly = options !== undefined ? options.contentOnly : false;
24405
24406 if (storeName) {
24407 var original = this.original.slice(start, end);
24408 this.storedNames[original] = true;
24409 }
24410
24411 var first = this.byStart[start];
24412 var last = this.byEnd[end];
24413
24414 if (first) {
24415 if (end > first.end && first.next !== this.byStart[first.end]) {
24416 throw new Error('Cannot overwrite across a split point');
24417 }
24418
24419 first.edit(content, storeName, contentOnly);
24420
24421 if (first !== last) {
24422 var chunk = first.next;
24423 while (chunk !== last) {
24424 chunk.edit('', false);
24425 chunk = chunk.next;
24426 }
24427
24428 chunk.edit('', false);
24429 }
24430 } else {
24431 // must be inserting at the end
24432 var newChunk = new Chunk(start, end, '').edit(content, storeName);
24433
24434 // TODO last chunk in the array may not be the last chunk, if it's moved...
24435 last.next = newChunk;
24436 newChunk.previous = last;
24437 }
24438 return this;
24439};
24440
24441MagicString.prototype.prepend = function prepend (content) {
24442 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
24443
24444 this.intro = content + this.intro;
24445 return this;
24446};
24447
24448MagicString.prototype.prependLeft = function prependLeft (index, content) {
24449 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
24450
24451 this._split(index);
24452
24453 var chunk = this.byEnd[index];
24454
24455 if (chunk) {
24456 chunk.prependLeft(content);
24457 } else {
24458 this.intro = content + this.intro;
24459 }
24460 return this;
24461};
24462
24463MagicString.prototype.prependRight = function prependRight (index, content) {
24464 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
24465
24466 this._split(index);
24467
24468 var chunk = this.byStart[index];
24469
24470 if (chunk) {
24471 chunk.prependRight(content);
24472 } else {
24473 this.outro = content + this.outro;
24474 }
24475 return this;
24476};
24477
24478MagicString.prototype.remove = function remove (start, end) {
24479 while (start < 0) { start += this.original.length; }
24480 while (end < 0) { end += this.original.length; }
24481
24482 if (start === end) { return this; }
24483
24484 if (start < 0 || end > this.original.length) { throw new Error('Character is out of bounds'); }
24485 if (start > end) { throw new Error('end must be greater than start'); }
24486
24487 this._split(start);
24488 this._split(end);
24489
24490 var chunk = this.byStart[start];
24491
24492 while (chunk) {
24493 chunk.intro = '';
24494 chunk.outro = '';
24495 chunk.edit('');
24496
24497 chunk = end > chunk.end ? this.byStart[chunk.end] : null;
24498 }
24499 return this;
24500};
24501
24502MagicString.prototype.lastChar = function lastChar () {
24503 if (this.outro.length)
24504 { return this.outro[this.outro.length - 1]; }
24505 var chunk = this.lastChunk;
24506 do {
24507 if (chunk.outro.length)
24508 { return chunk.outro[chunk.outro.length - 1]; }
24509 if (chunk.content.length)
24510 { return chunk.content[chunk.content.length - 1]; }
24511 if (chunk.intro.length)
24512 { return chunk.intro[chunk.intro.length - 1]; }
24513 } while (chunk = chunk.previous);
24514 if (this.intro.length)
24515 { return this.intro[this.intro.length - 1]; }
24516 return '';
24517};
24518
24519MagicString.prototype.lastLine = function lastLine () {
24520 var lineIndex = this.outro.lastIndexOf(n);
24521 if (lineIndex !== -1)
24522 { return this.outro.substr(lineIndex + 1); }
24523 var lineStr = this.outro;
24524 var chunk = this.lastChunk;
24525 do {
24526 if (chunk.outro.length > 0) {
24527 lineIndex = chunk.outro.lastIndexOf(n);
24528 if (lineIndex !== -1)
24529 { return chunk.outro.substr(lineIndex + 1) + lineStr; }
24530 lineStr = chunk.outro + lineStr;
24531 }
24532
24533 if (chunk.content.length > 0) {
24534 lineIndex = chunk.content.lastIndexOf(n);
24535 if (lineIndex !== -1)
24536 { return chunk.content.substr(lineIndex + 1) + lineStr; }
24537 lineStr = chunk.content + lineStr;
24538 }
24539
24540 if (chunk.intro.length > 0) {
24541 lineIndex = chunk.intro.lastIndexOf(n);
24542 if (lineIndex !== -1)
24543 { return chunk.intro.substr(lineIndex + 1) + lineStr; }
24544 lineStr = chunk.intro + lineStr;
24545 }
24546 } while (chunk = chunk.previous);
24547 lineIndex = this.intro.lastIndexOf(n);
24548 if (lineIndex !== -1)
24549 { return this.intro.substr(lineIndex + 1) + lineStr; }
24550 return this.intro + lineStr;
24551};
24552
24553MagicString.prototype.slice = function slice (start, end) {
24554 if ( start === void 0 ) start = 0;
24555 if ( end === void 0 ) end = this.original.length;
24556
24557 while (start < 0) { start += this.original.length; }
24558 while (end < 0) { end += this.original.length; }
24559
24560 var result = '';
24561
24562 // find start chunk
24563 var chunk = this.firstChunk;
24564 while (chunk && (chunk.start > start || chunk.end <= start)) {
24565 // found end chunk before start
24566 if (chunk.start < end && chunk.end >= end) {
24567 return result;
24568 }
24569
24570 chunk = chunk.next;
24571 }
24572
24573 if (chunk && chunk.edited && chunk.start !== start)
24574 { throw new Error(("Cannot use replaced character " + start + " as slice start anchor.")); }
24575
24576 var startChunk = chunk;
24577 while (chunk) {
24578 if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
24579 result += chunk.intro;
24580 }
24581
24582 var containsEnd = chunk.start < end && chunk.end >= end;
24583 if (containsEnd && chunk.edited && chunk.end !== end)
24584 { throw new Error(("Cannot use replaced character " + end + " as slice end anchor.")); }
24585
24586 var sliceStart = startChunk === chunk ? start - chunk.start : 0;
24587 var sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
24588
24589 result += chunk.content.slice(sliceStart, sliceEnd);
24590
24591 if (chunk.outro && (!containsEnd || chunk.end === end)) {
24592 result += chunk.outro;
24593 }
24594
24595 if (containsEnd) {
24596 break;
24597 }
24598
24599 chunk = chunk.next;
24600 }
24601
24602 return result;
24603};
24604
24605// TODO deprecate this? not really very useful
24606MagicString.prototype.snip = function snip (start, end) {
24607 var clone = this.clone();
24608 clone.remove(0, start);
24609 clone.remove(end, clone.original.length);
24610
24611 return clone;
24612};
24613
24614MagicString.prototype._split = function _split (index) {
24615 if (this.byStart[index] || this.byEnd[index]) { return; }
24616
24617 var chunk = this.lastSearchedChunk;
24618 var searchForward = index > chunk.end;
24619
24620 while (chunk) {
24621 if (chunk.contains(index)) { return this._splitChunk(chunk, index); }
24622
24623 chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
24624 }
24625};
24626
24627MagicString.prototype._splitChunk = function _splitChunk (chunk, index) {
24628 if (chunk.edited && chunk.content.length) {
24629 // zero-length edited chunks are a special case (overlapping replacements)
24630 var loc = getLocator$1(this.original)(index);
24631 throw new Error(
24632 ("Cannot split a chunk that has already been edited (" + (loc.line) + ":" + (loc.column) + " – \"" + (chunk.original) + "\")")
24633 );
24634 }
24635
24636 var newChunk = chunk.split(index);
24637
24638 this.byEnd[index] = chunk;
24639 this.byStart[index] = newChunk;
24640 this.byEnd[newChunk.end] = newChunk;
24641
24642 if (chunk === this.lastChunk) { this.lastChunk = newChunk; }
24643
24644 this.lastSearchedChunk = chunk;
24645 return true;
24646};
24647
24648MagicString.prototype.toString = function toString () {
24649 var str = this.intro;
24650
24651 var chunk = this.firstChunk;
24652 while (chunk) {
24653 str += chunk.toString();
24654 chunk = chunk.next;
24655 }
24656
24657 return str + this.outro;
24658};
24659
24660MagicString.prototype.isEmpty = function isEmpty () {
24661 var chunk = this.firstChunk;
24662 do {
24663 if (chunk.intro.length && chunk.intro.trim() ||
24664 chunk.content.length && chunk.content.trim() ||
24665 chunk.outro.length && chunk.outro.trim())
24666 { return false; }
24667 } while (chunk = chunk.next);
24668 return true;
24669};
24670
24671MagicString.prototype.length = function length () {
24672 var chunk = this.firstChunk;
24673 var length = 0;
24674 do {
24675 length += chunk.intro.length + chunk.content.length + chunk.outro.length;
24676 } while (chunk = chunk.next);
24677 return length;
24678};
24679
24680MagicString.prototype.trimLines = function trimLines () {
24681 return this.trim('[\\r\\n]');
24682};
24683
24684MagicString.prototype.trim = function trim (charType) {
24685 return this.trimStart(charType).trimEnd(charType);
24686};
24687
24688MagicString.prototype.trimEndAborted = function trimEndAborted (charType) {
24689 var rx = new RegExp((charType || '\\s') + '+$');
24690
24691 this.outro = this.outro.replace(rx, '');
24692 if (this.outro.length) { return true; }
24693
24694 var chunk = this.lastChunk;
24695
24696 do {
24697 var end = chunk.end;
24698 var aborted = chunk.trimEnd(rx);
24699
24700 // if chunk was trimmed, we have a new lastChunk
24701 if (chunk.end !== end) {
24702 if (this.lastChunk === chunk) {
24703 this.lastChunk = chunk.next;
24704 }
24705
24706 this.byEnd[chunk.end] = chunk;
24707 this.byStart[chunk.next.start] = chunk.next;
24708 this.byEnd[chunk.next.end] = chunk.next;
24709 }
24710
24711 if (aborted) { return true; }
24712 chunk = chunk.previous;
24713 } while (chunk);
24714
24715 return false;
24716};
24717
24718MagicString.prototype.trimEnd = function trimEnd (charType) {
24719 this.trimEndAborted(charType);
24720 return this;
24721};
24722MagicString.prototype.trimStartAborted = function trimStartAborted (charType) {
24723 var rx = new RegExp('^' + (charType || '\\s') + '+');
24724
24725 this.intro = this.intro.replace(rx, '');
24726 if (this.intro.length) { return true; }
24727
24728 var chunk = this.firstChunk;
24729
24730 do {
24731 var end = chunk.end;
24732 var aborted = chunk.trimStart(rx);
24733
24734 if (chunk.end !== end) {
24735 // special case...
24736 if (chunk === this.lastChunk) { this.lastChunk = chunk.next; }
24737
24738 this.byEnd[chunk.end] = chunk;
24739 this.byStart[chunk.next.start] = chunk.next;
24740 this.byEnd[chunk.next.end] = chunk.next;
24741 }
24742
24743 if (aborted) { return true; }
24744 chunk = chunk.next;
24745 } while (chunk);
24746
24747 return false;
24748};
24749
24750MagicString.prototype.trimStart = function trimStart (charType) {
24751 this.trimStartAborted(charType);
24752 return this;
24753};
24754
24755const UNKNOWN = {};
24756function gather_possible_values(node, set) {
24757 if (node.type === 'Literal') {
24758 set.add(node.value);
24759 }
24760 else if (node.type === 'ConditionalExpression') {
24761 gather_possible_values(node.consequent, set);
24762 gather_possible_values(node.alternate, set);
24763 }
24764 else {
24765 set.add(UNKNOWN);
24766 }
24767}
24768
24769var BlockAppliesToNode;
24770(function (BlockAppliesToNode) {
24771 BlockAppliesToNode[BlockAppliesToNode["NotPossible"] = 0] = "NotPossible";
24772 BlockAppliesToNode[BlockAppliesToNode["Possible"] = 1] = "Possible";
24773 BlockAppliesToNode[BlockAppliesToNode["UnknownSelectorType"] = 2] = "UnknownSelectorType";
24774})(BlockAppliesToNode || (BlockAppliesToNode = {}));
24775var NodeExist;
24776(function (NodeExist) {
24777 NodeExist[NodeExist["Probably"] = 1] = "Probably";
24778 NodeExist[NodeExist["Definitely"] = 2] = "Definitely";
24779})(NodeExist || (NodeExist = {}));
24780const whitelist_attribute_selector = new Map([
24781 ['details', new Set(['open'])]
24782]);
24783class Selector$1 {
24784 constructor(node, stylesheet) {
24785 this.node = node;
24786 this.stylesheet = stylesheet;
24787 this.blocks = group_selectors(node);
24788 // take trailing :global(...) selectors out of consideration
24789 let i = this.blocks.length;
24790 while (i > 0) {
24791 if (!this.blocks[i - 1].global)
24792 break;
24793 i -= 1;
24794 }
24795 this.local_blocks = this.blocks.slice(0, i);
24796 this.used = this.local_blocks.length === 0;
24797 }
24798 apply(node) {
24799 const to_encapsulate = [];
24800 apply_selector(this.local_blocks.slice(), node, to_encapsulate);
24801 if (to_encapsulate.length > 0) {
24802 to_encapsulate.forEach(({ node, block }) => {
24803 this.stylesheet.nodes_with_css_class.add(node);
24804 block.should_encapsulate = true;
24805 });
24806 this.used = true;
24807 }
24808 }
24809 minify(code) {
24810 let c = null;
24811 this.blocks.forEach((block, i) => {
24812 if (i > 0) {
24813 if (block.start - c > 1) {
24814 code.overwrite(c, block.start, block.combinator.name || ' ');
24815 }
24816 }
24817 c = block.end;
24818 });
24819 }
24820 transform(code, attr, max_amount_class_specificity_increased) {
24821 const amount_class_specificity_to_increase = max_amount_class_specificity_increased - this.blocks.filter(block => block.should_encapsulate).length;
24822 function encapsulate_block(block, attr) {
24823 let i = block.selectors.length;
24824 while (i--) {
24825 const selector = block.selectors[i];
24826 if (selector.type === 'PseudoElementSelector' || selector.type === 'PseudoClassSelector') {
24827 if (selector.name !== 'root') {
24828 if (i === 0)
24829 code.prependRight(selector.start, attr);
24830 }
24831 continue;
24832 }
24833 if (selector.type === 'TypeSelector' && selector.name === '*') {
24834 code.overwrite(selector.start, selector.end, attr);
24835 }
24836 else {
24837 code.appendLeft(selector.end, attr);
24838 }
24839 break;
24840 }
24841 }
24842 this.blocks.forEach((block, index) => {
24843 if (block.global) {
24844 const selector = block.selectors[0];
24845 const first = selector.children[0];
24846 const last = selector.children[selector.children.length - 1];
24847 code.remove(selector.start, first.start).remove(last.end, selector.end);
24848 }
24849 if (block.should_encapsulate)
24850 encapsulate_block(block, index === this.blocks.length - 1 ? attr.repeat(amount_class_specificity_to_increase + 1) : attr);
24851 });
24852 }
24853 validate(component) {
24854 this.blocks.forEach((block) => {
24855 let i = block.selectors.length;
24856 while (i-- > 1) {
24857 const selector = block.selectors[i];
24858 if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
24859 component.error(selector, {
24860 code: 'css-invalid-global',
24861 message: ':global(...) must be the first element in a compound selector'
24862 });
24863 }
24864 }
24865 });
24866 let start = 0;
24867 let end = this.blocks.length;
24868 for (; start < end; start += 1) {
24869 if (!this.blocks[start].global)
24870 break;
24871 }
24872 for (; end > start; end -= 1) {
24873 if (!this.blocks[end - 1].global)
24874 break;
24875 }
24876 for (let i = start; i < end; i += 1) {
24877 if (this.blocks[i].global) {
24878 component.error(this.blocks[i].selectors[0], {
24879 code: 'css-invalid-global',
24880 message: ':global(...) can be at the start or end of a selector sequence, but not in the middle'
24881 });
24882 }
24883 }
24884 }
24885 get_amount_class_specificity_increased() {
24886 let count = 0;
24887 for (const block of this.blocks) {
24888 if (block.should_encapsulate) {
24889 count++;
24890 }
24891 }
24892 return count;
24893 }
24894}
24895function apply_selector(blocks, node, to_encapsulate) {
24896 const block = blocks.pop();
24897 if (!block)
24898 return false;
24899 if (!node) {
24900 return block.global && blocks.every(block => block.global);
24901 }
24902 switch (block_might_apply_to_node(block, node)) {
24903 case BlockAppliesToNode.NotPossible:
24904 return false;
24905 case BlockAppliesToNode.UnknownSelectorType:
24906 // bail. TODO figure out what these could be
24907 to_encapsulate.push({ node, block });
24908 return true;
24909 }
24910 if (block.combinator) {
24911 if (block.combinator.type === 'WhiteSpace') {
24912 for (const ancestor_block of blocks) {
24913 if (ancestor_block.global) {
24914 continue;
24915 }
24916 let parent = node;
24917 while (parent = get_element_parent(parent)) {
24918 if (block_might_apply_to_node(ancestor_block, parent) !== BlockAppliesToNode.NotPossible) {
24919 to_encapsulate.push({ node: parent, block: ancestor_block });
24920 }
24921 }
24922 if (to_encapsulate.length) {
24923 to_encapsulate.push({ node, block });
24924 return true;
24925 }
24926 }
24927 if (blocks.every(block => block.global)) {
24928 to_encapsulate.push({ node, block });
24929 return true;
24930 }
24931 return false;
24932 }
24933 else if (block.combinator.name === '>') {
24934 if (apply_selector(blocks, get_element_parent(node), to_encapsulate)) {
24935 to_encapsulate.push({ node, block });
24936 return true;
24937 }
24938 return false;
24939 }
24940 else if (block.combinator.name === '+' || block.combinator.name === '~') {
24941 const siblings = get_possible_element_siblings(node, block.combinator.name === '+');
24942 let has_match = false;
24943 for (const possible_sibling of siblings.keys()) {
24944 if (apply_selector(blocks.slice(), possible_sibling, to_encapsulate)) {
24945 to_encapsulate.push({ node, block });
24946 has_match = true;
24947 }
24948 }
24949 return has_match;
24950 }
24951 // TODO other combinators
24952 to_encapsulate.push({ node, block });
24953 return true;
24954 }
24955 to_encapsulate.push({ node, block });
24956 return true;
24957}
24958function block_might_apply_to_node(block, node) {
24959 let i = block.selectors.length;
24960 while (i--) {
24961 const selector = block.selectors[i];
24962 const name = typeof selector.name === 'string' && selector.name.replace(/\\(.)/g, '$1');
24963 if (selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector') {
24964 continue;
24965 }
24966 if (selector.type === 'PseudoClassSelector' && name === 'global') {
24967 // TODO shouldn't see this here... maybe we should enforce that :global(...)
24968 // cannot be sandwiched between non-global selectors?
24969 return BlockAppliesToNode.NotPossible;
24970 }
24971 if (selector.type === 'ClassSelector') {
24972 if (!attribute_matches(node, 'class', name, '~=', false) && !node.classes.some(c => c.name === name))
24973 return BlockAppliesToNode.NotPossible;
24974 }
24975 else if (selector.type === 'IdSelector') {
24976 if (!attribute_matches(node, 'id', name, '=', false))
24977 return BlockAppliesToNode.NotPossible;
24978 }
24979 else if (selector.type === 'AttributeSelector') {
24980 if (!(whitelist_attribute_selector.has(node.name.toLowerCase()) && whitelist_attribute_selector.get(node.name.toLowerCase()).has(selector.name.name.toLowerCase())) &&
24981 !attribute_matches(node, selector.name.name, selector.value && unquote(selector.value), selector.matcher, selector.flags)) {
24982 return BlockAppliesToNode.NotPossible;
24983 }
24984 }
24985 else if (selector.type === 'TypeSelector') {
24986 if (node.name.toLowerCase() !== name.toLowerCase() && name !== '*')
24987 return BlockAppliesToNode.NotPossible;
24988 }
24989 else {
24990 return BlockAppliesToNode.UnknownSelectorType;
24991 }
24992 }
24993 return BlockAppliesToNode.Possible;
24994}
24995function test_attribute(operator, expected_value, case_insensitive, value) {
24996 if (case_insensitive) {
24997 expected_value = expected_value.toLowerCase();
24998 value = value.toLowerCase();
24999 }
25000 switch (operator) {
25001 case '=': return value === expected_value;
25002 case '~=': return value.split(/\s/).includes(expected_value);
25003 case '|=': return `${value}-`.startsWith(`${expected_value}-`);
25004 case '^=': return value.startsWith(expected_value);
25005 case '$=': return value.endsWith(expected_value);
25006 case '*=': return value.includes(expected_value);
25007 default: throw new Error("this shouldn't happen");
25008 }
25009}
25010function attribute_matches(node, name, expected_value, operator, case_insensitive) {
25011 const spread = node.attributes.find(attr => attr.type === 'Spread');
25012 if (spread)
25013 return true;
25014 if (node.bindings.some((binding) => binding.name === name))
25015 return true;
25016 const attr = node.attributes.find((attr) => attr.name === name);
25017 if (!attr)
25018 return false;
25019 if (attr.is_true)
25020 return operator === null;
25021 if (!expected_value)
25022 return true;
25023 if (attr.chunks.length === 1) {
25024 const value = attr.chunks[0];
25025 if (!value)
25026 return false;
25027 if (value.type === 'Text')
25028 return test_attribute(operator, expected_value, case_insensitive, value.data);
25029 }
25030 const possible_values = new Set();
25031 let prev_values = [];
25032 for (const chunk of attr.chunks) {
25033 const current_possible_values = new Set();
25034 if (chunk.type === 'Text') {
25035 current_possible_values.add(chunk.data);
25036 }
25037 else {
25038 gather_possible_values(chunk.node, current_possible_values);
25039 }
25040 // impossible to find out all combinations
25041 if (current_possible_values.has(UNKNOWN))
25042 return true;
25043 if (prev_values.length > 0) {
25044 const start_with_space = [];
25045 const remaining = [];
25046 current_possible_values.forEach((current_possible_value) => {
25047 if (/^\s/.test(current_possible_value)) {
25048 start_with_space.push(current_possible_value);
25049 }
25050 else {
25051 remaining.push(current_possible_value);
25052 }
25053 });
25054 if (remaining.length > 0) {
25055 if (start_with_space.length > 0) {
25056 prev_values.forEach(prev_value => possible_values.add(prev_value));
25057 }
25058 const combined = [];
25059 prev_values.forEach((prev_value) => {
25060 remaining.forEach((value) => {
25061 combined.push(prev_value + value);
25062 });
25063 });
25064 prev_values = combined;
25065 start_with_space.forEach((value) => {
25066 if (/\s$/.test(value)) {
25067 possible_values.add(value);
25068 }
25069 else {
25070 prev_values.push(value);
25071 }
25072 });
25073 continue;
25074 }
25075 else {
25076 prev_values.forEach(prev_value => possible_values.add(prev_value));
25077 prev_values = [];
25078 }
25079 }
25080 current_possible_values.forEach((current_possible_value) => {
25081 if (/\s$/.test(current_possible_value)) {
25082 possible_values.add(current_possible_value);
25083 }
25084 else {
25085 prev_values.push(current_possible_value);
25086 }
25087 });
25088 if (prev_values.length < current_possible_values.size) {
25089 prev_values.push(' ');
25090 }
25091 if (prev_values.length > 20) {
25092 // might grow exponentially, bail out
25093 return true;
25094 }
25095 }
25096 prev_values.forEach(prev_value => possible_values.add(prev_value));
25097 if (possible_values.has(UNKNOWN))
25098 return true;
25099 for (const value of possible_values) {
25100 if (test_attribute(operator, expected_value, case_insensitive, value))
25101 return true;
25102 }
25103 return false;
25104}
25105function unquote(value) {
25106 if (value.type === 'Identifier')
25107 return value.name;
25108 const str = value.value;
25109 if (str[0] === str[str.length - 1] && str[0] === "'" || str[0] === '"') {
25110 return str.slice(1, str.length - 1);
25111 }
25112 return str;
25113}
25114function get_element_parent(node) {
25115 let parent = node;
25116 while ((parent = parent.parent) && parent.type !== 'Element')
25117 ;
25118 return parent;
25119}
25120function get_possible_element_siblings(node, adjacent_only) {
25121 const result = new Map();
25122 let prev = node;
25123 while (prev = prev.prev) {
25124 if (prev.type === 'Element') {
25125 if (!prev.attributes.find(attr => attr.type === 'Attribute' && attr.name.toLowerCase() === 'slot')) {
25126 result.set(prev, NodeExist.Definitely);
25127 }
25128 if (adjacent_only) {
25129 break;
25130 }
25131 }
25132 else if (prev.type === 'EachBlock' || prev.type === 'IfBlock' || prev.type === 'AwaitBlock') {
25133 const possible_last_child = get_possible_last_child(prev, adjacent_only);
25134 add_to_map(possible_last_child, result);
25135 if (adjacent_only && has_definite_elements(possible_last_child)) {
25136 return result;
25137 }
25138 }
25139 }
25140 if (!prev || !adjacent_only) {
25141 let parent = node;
25142 let skip_each_for_last_child = node.type === 'ElseBlock';
25143 while ((parent = parent.parent) && (parent.type === 'EachBlock' || parent.type === 'IfBlock' || parent.type === 'ElseBlock' || parent.type === 'AwaitBlock')) {
25144 const possible_siblings = get_possible_element_siblings(parent, adjacent_only);
25145 add_to_map(possible_siblings, result);
25146 if (parent.type === 'EachBlock') {
25147 // first child of each block can select the last child of each block as previous sibling
25148 if (skip_each_for_last_child) {
25149 skip_each_for_last_child = false;
25150 }
25151 else {
25152 add_to_map(get_possible_last_child(parent, adjacent_only), result);
25153 }
25154 }
25155 else if (parent.type === 'ElseBlock') {
25156 skip_each_for_last_child = true;
25157 parent = parent.parent;
25158 }
25159 if (adjacent_only && has_definite_elements(possible_siblings)) {
25160 break;
25161 }
25162 }
25163 }
25164 return result;
25165}
25166function get_possible_last_child(block, adjacent_only) {
25167 const result = new Map();
25168 if (block.type === 'EachBlock') {
25169 const each_result = loop_child(block.children, adjacent_only);
25170 const else_result = block.else ? loop_child(block.else.children, adjacent_only) : new Map();
25171 const not_exhaustive = !has_definite_elements(else_result);
25172 if (not_exhaustive) {
25173 mark_as_probably(each_result);
25174 mark_as_probably(else_result);
25175 }
25176 add_to_map(each_result, result);
25177 add_to_map(else_result, result);
25178 }
25179 else if (block.type === 'IfBlock') {
25180 const if_result = loop_child(block.children, adjacent_only);
25181 const else_result = block.else ? loop_child(block.else.children, adjacent_only) : new Map();
25182 const not_exhaustive = !has_definite_elements(if_result) || !has_definite_elements(else_result);
25183 if (not_exhaustive) {
25184 mark_as_probably(if_result);
25185 mark_as_probably(else_result);
25186 }
25187 add_to_map(if_result, result);
25188 add_to_map(else_result, result);
25189 }
25190 else if (block.type === 'AwaitBlock') {
25191 const pending_result = block.pending ? loop_child(block.pending.children, adjacent_only) : new Map();
25192 const then_result = block.then ? loop_child(block.then.children, adjacent_only) : new Map();
25193 const catch_result = block.catch ? loop_child(block.catch.children, adjacent_only) : new Map();
25194 const not_exhaustive = !has_definite_elements(pending_result) || !has_definite_elements(then_result) || !has_definite_elements(catch_result);
25195 if (not_exhaustive) {
25196 mark_as_probably(pending_result);
25197 mark_as_probably(then_result);
25198 mark_as_probably(catch_result);
25199 }
25200 add_to_map(pending_result, result);
25201 add_to_map(then_result, result);
25202 add_to_map(catch_result, result);
25203 }
25204 return result;
25205}
25206function has_definite_elements(result) {
25207 if (result.size === 0)
25208 return false;
25209 for (const exist of result.values()) {
25210 if (exist === NodeExist.Definitely) {
25211 return true;
25212 }
25213 }
25214 return false;
25215}
25216function add_to_map(from, to) {
25217 from.forEach((exist, element) => {
25218 to.set(element, higher_existance(exist, to.get(element)));
25219 });
25220}
25221function higher_existance(exist1, exist2) {
25222 if (exist1 === undefined || exist2 === undefined)
25223 return exist1 || exist2;
25224 return exist1 > exist2 ? exist1 : exist2;
25225}
25226function mark_as_probably(result) {
25227 for (const key of result.keys()) {
25228 result.set(key, NodeExist.Probably);
25229 }
25230}
25231function loop_child(children, adjacent_only) {
25232 const result = new Map();
25233 for (let i = children.length - 1; i >= 0; i--) {
25234 const child = children[i];
25235 if (child.type === 'Element') {
25236 result.set(child, NodeExist.Definitely);
25237 if (adjacent_only) {
25238 break;
25239 }
25240 }
25241 else if (child.type === 'EachBlock' || child.type === 'IfBlock' || child.type === 'AwaitBlock') {
25242 const child_result = get_possible_last_child(child, adjacent_only);
25243 add_to_map(child_result, result);
25244 if (adjacent_only && has_definite_elements(child_result)) {
25245 break;
25246 }
25247 }
25248 }
25249 return result;
25250}
25251class Block$2 {
25252 constructor(combinator) {
25253 this.combinator = combinator;
25254 this.global = false;
25255 this.selectors = [];
25256 this.start = null;
25257 this.end = null;
25258 this.should_encapsulate = false;
25259 }
25260 add(selector) {
25261 if (this.selectors.length === 0) {
25262 this.start = selector.start;
25263 this.global = selector.type === 'PseudoClassSelector' && selector.name === 'global';
25264 }
25265 this.selectors.push(selector);
25266 this.end = selector.end;
25267 }
25268}
25269function group_selectors(selector) {
25270 let block = new Block$2(null);
25271 const blocks = [block];
25272 selector.children.forEach((child) => {
25273 if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
25274 block = new Block$2(child);
25275 blocks.push(block);
25276 }
25277 else {
25278 block.add(child);
25279 }
25280 });
25281 return blocks;
25282}
25283
25284// https://github.com/darkskyapp/string-hash/blob/master/index.js
25285function hash(str) {
25286 str = str.replace(/\r/g, '');
25287 let hash = 5381;
25288 let i = str.length;
25289 while (i--)
25290 hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
25291 return (hash >>> 0).toString(36);
25292}
25293
25294function remove_css_prefix(name) {
25295 return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, '');
25296}
25297const is_keyframes_node = (node) => remove_css_prefix(node.name) === 'keyframes';
25298const at_rule_has_declaration = ({ block }) => block &&
25299 block.children &&
25300 block.children.find((node) => node.type === 'Declaration');
25301function minify_declarations(code, start, declarations) {
25302 let c = start;
25303 declarations.forEach((declaration, i) => {
25304 const separator = i > 0 ? ';' : '';
25305 if ((declaration.node.start - c) > separator.length) {
25306 code.overwrite(c, declaration.node.start, separator);
25307 }
25308 declaration.minify(code);
25309 c = declaration.node.end;
25310 });
25311 return c;
25312}
25313class Rule$1 {
25314 constructor(node, stylesheet, parent) {
25315 this.node = node;
25316 this.parent = parent;
25317 this.selectors = node.selector.children.map((node) => new Selector$1(node, stylesheet));
25318 this.declarations = node.block.children.map((node) => new Declaration$1(node));
25319 }
25320 apply(node) {
25321 this.selectors.forEach(selector => selector.apply(node)); // TODO move the logic in here?
25322 }
25323 is_used(dev) {
25324 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
25325 return true;
25326 if (this.declarations.length === 0)
25327 return dev;
25328 return this.selectors.some(s => s.used);
25329 }
25330 minify(code, _dev) {
25331 let c = this.node.start;
25332 let started = false;
25333 this.selectors.forEach((selector) => {
25334 if (selector.used) {
25335 const separator = started ? ',' : '';
25336 if ((selector.node.start - c) > separator.length) {
25337 code.overwrite(c, selector.node.start, separator);
25338 }
25339 selector.minify(code);
25340 c = selector.node.end;
25341 started = true;
25342 }
25343 });
25344 code.remove(c, this.node.block.start);
25345 c = this.node.block.start + 1;
25346 c = minify_declarations(code, c, this.declarations);
25347 code.remove(c, this.node.block.end - 1);
25348 }
25349 transform(code, id, keyframes, max_amount_class_specificity_increased) {
25350 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
25351 return true;
25352 const attr = `.${id}`;
25353 this.selectors.forEach(selector => selector.transform(code, attr, max_amount_class_specificity_increased));
25354 this.declarations.forEach(declaration => declaration.transform(code, keyframes));
25355 }
25356 validate(component) {
25357 this.selectors.forEach(selector => {
25358 selector.validate(component);
25359 });
25360 }
25361 warn_on_unused_selector(handler) {
25362 this.selectors.forEach(selector => {
25363 if (!selector.used)
25364 handler(selector);
25365 });
25366 }
25367 get_max_amount_class_specificity_increased() {
25368 return Math.max(...this.selectors.map(selector => selector.get_amount_class_specificity_increased()));
25369 }
25370}
25371class Declaration$1 {
25372 constructor(node) {
25373 this.node = node;
25374 }
25375 transform(code, keyframes) {
25376 const property = this.node.property && remove_css_prefix(this.node.property.toLowerCase());
25377 if (property === 'animation' || property === 'animation-name') {
25378 this.node.value.children.forEach((block) => {
25379 if (block.type === 'Identifier') {
25380 const name = block.name;
25381 if (keyframes.has(name)) {
25382 code.overwrite(block.start, block.end, keyframes.get(name));
25383 }
25384 }
25385 });
25386 }
25387 }
25388 minify(code) {
25389 if (!this.node.property)
25390 return; // @apply, and possibly other weird cases?
25391 const c = this.node.start + this.node.property.length;
25392 const first = this.node.value.children
25393 ? this.node.value.children[0]
25394 : this.node.value;
25395 let start = first.start;
25396 while (/\s/.test(code.original[start]))
25397 start += 1;
25398 if (start - c > 1) {
25399 code.overwrite(c, start, ':');
25400 }
25401 }
25402}
25403class Atrule$1 {
25404 constructor(node) {
25405 this.node = node;
25406 this.children = [];
25407 this.declarations = [];
25408 }
25409 apply(node) {
25410 if (this.node.name === 'media' || this.node.name === 'supports') {
25411 this.children.forEach(child => {
25412 child.apply(node);
25413 });
25414 }
25415 else if (is_keyframes_node(this.node)) {
25416 this.children.forEach((rule) => {
25417 rule.selectors.forEach(selector => {
25418 selector.used = true;
25419 });
25420 });
25421 }
25422 }
25423 is_used(_dev) {
25424 return true; // TODO
25425 }
25426 minify(code, dev) {
25427 if (this.node.name === 'media') {
25428 const expression_char = code.original[this.node.expression.start];
25429 let c = this.node.start + (expression_char === '(' ? 6 : 7);
25430 if (this.node.expression.start > c)
25431 code.remove(c, this.node.expression.start);
25432 this.node.expression.children.forEach((query) => {
25433 // TODO minify queries
25434 c = query.end;
25435 });
25436 code.remove(c, this.node.block.start);
25437 }
25438 else if (this.node.name === 'supports') {
25439 let c = this.node.start + 9;
25440 if (this.node.expression.start - c > 1)
25441 code.overwrite(c, this.node.expression.start, ' ');
25442 this.node.expression.children.forEach((query) => {
25443 // TODO minify queries
25444 c = query.end;
25445 });
25446 code.remove(c, this.node.block.start);
25447 }
25448 else {
25449 let c = this.node.start + this.node.name.length + 1;
25450 if (this.node.expression) {
25451 if (this.node.expression.start - c > 1)
25452 code.overwrite(c, this.node.expression.start, ' ');
25453 c = this.node.expression.end;
25454 }
25455 if (this.node.block && this.node.block.start - c > 0) {
25456 code.remove(c, this.node.block.start);
25457 }
25458 }
25459 // TODO other atrules
25460 if (this.node.block) {
25461 let c = this.node.block.start + 1;
25462 if (this.declarations.length) {
25463 c = minify_declarations(code, c, this.declarations);
25464 // if the atrule has children, leave the last declaration semicolon alone
25465 if (this.children.length)
25466 c++;
25467 }
25468 this.children.forEach(child => {
25469 if (child.is_used(dev)) {
25470 code.remove(c, child.node.start);
25471 child.minify(code, dev);
25472 c = child.node.end;
25473 }
25474 });
25475 code.remove(c, this.node.block.end - 1);
25476 }
25477 }
25478 transform(code, id, keyframes, max_amount_class_specificity_increased) {
25479 if (is_keyframes_node(this.node)) {
25480 this.node.expression.children.forEach(({ type, name, start, end }) => {
25481 if (type === 'Identifier') {
25482 if (name.startsWith('-global-')) {
25483 code.remove(start, start + 8);
25484 this.children.forEach((rule) => {
25485 rule.selectors.forEach(selector => {
25486 selector.used = true;
25487 });
25488 });
25489 }
25490 else {
25491 code.overwrite(start, end, keyframes.get(name));
25492 }
25493 }
25494 });
25495 }
25496 this.children.forEach(child => {
25497 child.transform(code, id, keyframes, max_amount_class_specificity_increased);
25498 });
25499 }
25500 validate(component) {
25501 this.children.forEach(child => {
25502 child.validate(component);
25503 });
25504 }
25505 warn_on_unused_selector(handler) {
25506 if (this.node.name !== 'media')
25507 return;
25508 this.children.forEach(child => {
25509 child.warn_on_unused_selector(handler);
25510 });
25511 }
25512 get_max_amount_class_specificity_increased() {
25513 return Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
25514 }
25515}
25516class Stylesheet {
25517 constructor(source, ast, filename, dev) {
25518 this.children = [];
25519 this.keyframes = new Map();
25520 this.nodes_with_css_class = new Set();
25521 this.source = source;
25522 this.ast = ast;
25523 this.filename = filename;
25524 this.dev = dev;
25525 if (ast.css && ast.css.children.length) {
25526 this.id = `svelte-${hash(ast.css.content.styles)}`;
25527 this.has_styles = true;
25528 const stack = [];
25529 let depth = 0;
25530 let current_atrule = null;
25531 walk(ast.css, {
25532 enter: (node) => {
25533 if (node.type === 'Atrule') {
25534 const atrule = new Atrule$1(node);
25535 stack.push(atrule);
25536 if (current_atrule) {
25537 current_atrule.children.push(atrule);
25538 }
25539 else if (depth <= 1) {
25540 this.children.push(atrule);
25541 }
25542 if (is_keyframes_node(node)) {
25543 node.expression.children.forEach((expression) => {
25544 if (expression.type === 'Identifier' && !expression.name.startsWith('-global-')) {
25545 this.keyframes.set(expression.name, `${this.id}-${expression.name}`);
25546 }
25547 });
25548 }
25549 else if (at_rule_has_declaration(node)) {
25550 const at_rule_declarations = node.block.children
25551 .filter(node => node.type === 'Declaration')
25552 .map(node => new Declaration$1(node));
25553 atrule.declarations.push(...at_rule_declarations);
25554 }
25555 current_atrule = atrule;
25556 }
25557 if (node.type === 'Rule') {
25558 const rule = new Rule$1(node, this, current_atrule);
25559 if (current_atrule) {
25560 current_atrule.children.push(rule);
25561 }
25562 else if (depth <= 1) {
25563 this.children.push(rule);
25564 }
25565 }
25566 depth += 1;
25567 },
25568 leave: (node) => {
25569 if (node.type === 'Atrule') {
25570 stack.pop();
25571 current_atrule = stack[stack.length - 1];
25572 }
25573 depth -= 1;
25574 }
25575 });
25576 }
25577 else {
25578 this.has_styles = false;
25579 }
25580 }
25581 apply(node) {
25582 if (!this.has_styles)
25583 return;
25584 for (let i = 0; i < this.children.length; i += 1) {
25585 const child = this.children[i];
25586 child.apply(node);
25587 }
25588 }
25589 reify() {
25590 this.nodes_with_css_class.forEach((node) => {
25591 node.add_css_class();
25592 });
25593 }
25594 render(file, should_transform_selectors) {
25595 if (!this.has_styles) {
25596 return { code: null, map: null };
25597 }
25598 const code = new MagicString(this.source);
25599 walk(this.ast.css, {
25600 enter: (node) => {
25601 code.addSourcemapLocation(node.start);
25602 code.addSourcemapLocation(node.end);
25603 }
25604 });
25605 if (should_transform_selectors) {
25606 const max = Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
25607 this.children.forEach((child) => {
25608 child.transform(code, this.id, this.keyframes, max);
25609 });
25610 }
25611 let c = 0;
25612 this.children.forEach(child => {
25613 if (child.is_used(this.dev)) {
25614 code.remove(c, child.node.start);
25615 child.minify(code, this.dev);
25616 c = child.node.end;
25617 }
25618 });
25619 code.remove(c, this.source.length);
25620 return {
25621 code: code.toString(),
25622 map: code.generateMap({
25623 includeContent: true,
25624 source: this.filename,
25625 file
25626 })
25627 };
25628 }
25629 validate(component) {
25630 this.children.forEach(child => {
25631 child.validate(component);
25632 });
25633 }
25634 warn_on_unused_selectors(component) {
25635 this.children.forEach(child => {
25636 child.warn_on_unused_selector((selector) => {
25637 component.warn(selector.node, {
25638 code: 'css-unused-selector',
25639 message: `Unused CSS selector "${this.source.slice(selector.node.start, selector.node.end)}"`
25640 });
25641 });
25642 });
25643 }
25644}
25645
25646const test = typeof process !== 'undefined' && process.env.TEST;
25647
25648class AbstractBlock extends Node$1 {
25649 constructor(component, parent, scope, info) {
25650 super(component, parent, scope, info);
25651 }
25652 warn_if_empty_block() {
25653 if (!this.children || this.children.length > 1)
25654 return;
25655 const child = this.children[0];
25656 if (!child || (child.type === 'Text' && !/[^ \r\n\f\v\t]/.test(child.data))) {
25657 this.component.warn(this, {
25658 code: 'empty-block',
25659 message: 'Empty block'
25660 });
25661 }
25662 }
25663}
25664
25665class PendingBlock extends AbstractBlock {
25666 constructor(component, parent, scope, info) {
25667 super(component, parent, scope, info);
25668 this.children = map_children(component, parent, scope, info.children);
25669 if (!info.skip) {
25670 this.warn_if_empty_block();
25671 }
25672 }
25673}
25674
25675class ThenBlock extends AbstractBlock {
25676 constructor(component, parent, scope, info) {
25677 super(component, parent, scope, info);
25678 this.scope = scope.child();
25679 if (parent.then_node) {
25680 parent.then_contexts.forEach(context => {
25681 this.scope.add(context.key.name, parent.expression.dependencies, this);
25682 });
25683 }
25684 this.children = map_children(component, parent, this.scope, info.children);
25685 if (!info.skip) {
25686 this.warn_if_empty_block();
25687 }
25688 }
25689}
25690
25691class CatchBlock extends AbstractBlock {
25692 constructor(component, parent, scope, info) {
25693 super(component, parent, scope, info);
25694 this.scope = scope.child();
25695 if (parent.catch_node) {
25696 parent.catch_contexts.forEach(context => {
25697 this.scope.add(context.key.name, parent.expression.dependencies, this);
25698 });
25699 }
25700 this.children = map_children(component, parent, this.scope, info.children);
25701 if (!info.skip) {
25702 this.warn_if_empty_block();
25703 }
25704 }
25705}
25706
25707function unpack_destructuring(contexts, node, modifier) {
25708 if (!node)
25709 return;
25710 if (node.type === 'Identifier') {
25711 contexts.push({
25712 key: node,
25713 modifier
25714 });
25715 }
25716 else if (node.type === 'RestElement') {
25717 contexts.push({
25718 key: node.argument,
25719 modifier
25720 });
25721 }
25722 else if (node.type === 'ArrayPattern') {
25723 node.elements.forEach((element, i) => {
25724 if (element && element.type === 'RestElement') {
25725 unpack_destructuring(contexts, element, node => x `${modifier(node)}.slice(${i})`);
25726 }
25727 else if (element && element.type === 'AssignmentPattern') {
25728 unpack_destructuring(contexts, element.left, node => x `${modifier(node)}[${i}] !== undefined ? ${modifier(node)}[${i}] : ${element.right}`);
25729 }
25730 else {
25731 unpack_destructuring(contexts, element, node => x `${modifier(node)}[${i}]`);
25732 }
25733 });
25734 }
25735 else if (node.type === 'ObjectPattern') {
25736 const used_properties = [];
25737 node.properties.forEach((property) => {
25738 if (property.type === 'RestElement') {
25739 unpack_destructuring(contexts, property.argument, node => x `@object_without_properties(${modifier(node)}, [${used_properties}])`);
25740 }
25741 else {
25742 const key = property.key;
25743 const value = property.value;
25744 used_properties.push(x `"${key.name}"`);
25745 if (value.type === 'AssignmentPattern') {
25746 unpack_destructuring(contexts, value.left, node => x `${modifier(node)}.${key.name} !== undefined ? ${modifier(node)}.${key.name} : ${value.right}`);
25747 }
25748 else {
25749 unpack_destructuring(contexts, value, node => x `${modifier(node)}.${key.name}`);
25750 }
25751 }
25752 });
25753 }
25754}
25755
25756class AwaitBlock$1 extends Node$1 {
25757 constructor(component, parent, scope, info) {
25758 super(component, parent, scope, info);
25759 this.expression = new Expression(component, this, scope, info.expression);
25760 this.then_node = info.value;
25761 this.catch_node = info.error;
25762 if (this.then_node) {
25763 this.then_contexts = [];
25764 unpack_destructuring(this.then_contexts, info.value, node => node);
25765 }
25766 if (this.catch_node) {
25767 this.catch_contexts = [];
25768 unpack_destructuring(this.catch_contexts, info.error, node => node);
25769 }
25770 this.pending = new PendingBlock(component, this, scope, info.pending);
25771 this.then = new ThenBlock(component, this, scope, info.then);
25772 this.catch = new CatchBlock(component, this, scope, info.catch);
25773 }
25774}
25775
25776class EventHandler extends Node$1 {
25777 constructor(component, parent, template_scope, info) {
25778 super(component, parent, template_scope, info);
25779 this.uses_context = false;
25780 this.can_make_passive = false;
25781 this.name = info.name;
25782 this.modifiers = new Set(info.modifiers);
25783 if (info.expression) {
25784 this.expression = new Expression(component, this, template_scope, info.expression);
25785 this.uses_context = this.expression.uses_context;
25786 if (/FunctionExpression/.test(info.expression.type) && info.expression.params.length === 0) {
25787 // TODO make this detection more accurate — if `event.preventDefault` isn't called, and
25788 // `event` is passed to another function, we can make it passive
25789 this.can_make_passive = true;
25790 }
25791 else if (info.expression.type === 'Identifier') {
25792 let node = component.node_for_declaration.get(info.expression.name);
25793 if (node) {
25794 if (node.type === 'VariableDeclaration') {
25795 // for `const handleClick = () => {...}`, we want the [arrow] function expression node
25796 const declarator = node.declarations.find(d => d.id.name === info.expression.name);
25797 node = declarator && declarator.init;
25798 }
25799 if (node && (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') && node.params.length === 0) {
25800 this.can_make_passive = true;
25801 }
25802 }
25803 }
25804 }
25805 else {
25806 this.handler_name = component.get_unique_name(`${sanitize(this.name)}_handler`);
25807 }
25808 }
25809 get reassigned() {
25810 if (!this.expression) {
25811 return false;
25812 }
25813 const node = this.expression.node;
25814 if (/FunctionExpression/.test(node.type)) {
25815 return false;
25816 }
25817 return this.expression.dynamic_dependencies().length > 0;
25818 }
25819}
25820
25821class Body extends Node$1 {
25822 constructor(component, parent, scope, info) {
25823 super(component, parent, scope, info);
25824 this.handlers = [];
25825 info.attributes.forEach((node) => {
25826 if (node.type === 'EventHandler') {
25827 this.handlers.push(new EventHandler(component, this, scope, node));
25828 }
25829 });
25830 }
25831}
25832
25833const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m;
25834class Comment$2 extends Node$1 {
25835 constructor(component, parent, scope, info) {
25836 super(component, parent, scope, info);
25837 this.data = info.data;
25838 const match = pattern.exec(this.data);
25839 this.ignores = match ? match[1].split(/[^\S]/).map(x => x.trim()).filter(Boolean) : [];
25840 }
25841}
25842
25843class ElseBlock extends AbstractBlock {
25844 constructor(component, parent, scope, info) {
25845 super(component, parent, scope, info);
25846 this.children = map_children(component, this, scope, info.children);
25847 this.warn_if_empty_block();
25848 }
25849}
25850
25851class EachBlock$1 extends AbstractBlock {
25852 constructor(component, parent, scope, info) {
25853 super(component, parent, scope, info);
25854 this.has_binding = false;
25855 this.has_index_binding = false;
25856 this.expression = new Expression(component, this, scope, info.expression);
25857 this.context = info.context.name || 'each'; // TODO this is used to facilitate binding; currently fails with destructuring
25858 this.context_node = info.context;
25859 this.index = info.index;
25860 this.scope = scope.child();
25861 this.contexts = [];
25862 unpack_destructuring(this.contexts, info.context, node => node);
25863 this.contexts.forEach(context => {
25864 this.scope.add(context.key.name, this.expression.dependencies, this);
25865 });
25866 if (this.index) {
25867 // index can only change if this is a keyed each block
25868 const dependencies = info.key ? this.expression.dependencies : new Set([]);
25869 this.scope.add(this.index, dependencies, this);
25870 }
25871 this.key = info.key
25872 ? new Expression(component, this, this.scope, info.key)
25873 : null;
25874 this.has_animation = false;
25875 this.children = map_children(component, this, this.scope, info.children);
25876 if (this.has_animation) {
25877 if (this.children.length !== 1) {
25878 const child = this.children.find(child => !!child.animation);
25879 component.error(child.animation, {
25880 code: 'invalid-animation',
25881 message: 'An element that uses the animate directive must be the sole child of a keyed each block'
25882 });
25883 }
25884 }
25885 this.warn_if_empty_block();
25886 this.else = info.else
25887 ? new ElseBlock(component, this, this.scope, info.else)
25888 : null;
25889 }
25890}
25891
25892class Attribute extends Node$1 {
25893 constructor(component, parent, scope, info) {
25894 super(component, parent, scope, info);
25895 this.scope = scope;
25896 if (info.type === 'Spread') {
25897 this.name = null;
25898 this.is_spread = true;
25899 this.is_true = false;
25900 this.expression = new Expression(component, this, scope, info.expression);
25901 this.dependencies = this.expression.dependencies;
25902 this.chunks = null;
25903 this.is_static = false;
25904 }
25905 else {
25906 this.name = info.name;
25907 this.is_true = info.value === true;
25908 this.is_static = true;
25909 this.dependencies = new Set();
25910 this.chunks = this.is_true
25911 ? []
25912 : info.value.map(node => {
25913 if (node.type === 'Text')
25914 return node;
25915 this.is_static = false;
25916 const expression = new Expression(component, this, scope, node.expression);
25917 add_to_set(this.dependencies, expression.dependencies);
25918 return expression;
25919 });
25920 }
25921 }
25922 get_dependencies() {
25923 if (this.is_spread)
25924 return this.expression.dynamic_dependencies();
25925 const dependencies = new Set();
25926 this.chunks.forEach(chunk => {
25927 if (chunk.type === 'Expression') {
25928 add_to_set(dependencies, chunk.dynamic_dependencies());
25929 }
25930 });
25931 return Array.from(dependencies);
25932 }
25933 get_value(block) {
25934 if (this.is_true)
25935 return x `true`;
25936 if (this.chunks.length === 0)
25937 return x `""`;
25938 if (this.chunks.length === 1) {
25939 return this.chunks[0].type === 'Text'
25940 ? string_literal(this.chunks[0].data)
25941 : this.chunks[0].manipulate(block);
25942 }
25943 let expression = this.chunks
25944 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : chunk.manipulate(block))
25945 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
25946 if (this.chunks[0].type !== 'Text') {
25947 expression = x `"" + ${expression}`;
25948 }
25949 return expression;
25950 }
25951 get_static_value() {
25952 if (this.is_spread || this.dependencies.size > 0)
25953 return null;
25954 return this.is_true
25955 ? true
25956 : this.chunks[0]
25957 // method should be called only when `is_static = true`
25958 ? this.chunks[0].data
25959 : '';
25960 }
25961 should_cache() {
25962 return this.is_static
25963 ? false
25964 : this.chunks.length === 1
25965 // @ts-ignore todo: probably error
25966 ? this.chunks[0].node.type !== 'Identifier' || this.scope.names.has(this.chunks[0].node.name)
25967 : true;
25968 }
25969}
25970
25971// TODO this should live in a specific binding
25972const read_only_media_attributes = new Set([
25973 'duration',
25974 'buffered',
25975 'seekable',
25976 'played',
25977 'seeking',
25978 'ended',
25979 'videoHeight',
25980 'videoWidth'
25981]);
25982class Binding extends Node$1 {
25983 constructor(component, parent, scope, info) {
25984 super(component, parent, scope, info);
25985 if (info.expression.type !== 'Identifier' && info.expression.type !== 'MemberExpression') {
25986 component.error(info, {
25987 code: 'invalid-directive-value',
25988 message: 'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
25989 });
25990 }
25991 this.name = info.name;
25992 this.expression = new Expression(component, this, scope, info.expression);
25993 this.raw_expression = JSON.parse(JSON.stringify(info.expression));
25994 const { name } = get_object(this.expression.node);
25995 this.is_contextual = Array.from(this.expression.references).some(name => scope.names.has(name));
25996 // make sure we track this as a mutable ref
25997 if (scope.is_let(name)) {
25998 component.error(this, {
25999 code: 'invalid-binding',
26000 message: 'Cannot bind to a variable declared with the let: directive'
26001 });
26002 }
26003 else if (scope.names.has(name)) {
26004 if (scope.is_await(name)) {
26005 component.error(this, {
26006 code: 'invalid-binding',
26007 message: 'Cannot bind to a variable declared with {#await ... then} or {:catch} blocks'
26008 });
26009 }
26010 scope.dependencies_for_name.get(name).forEach(name => {
26011 const variable = component.var_lookup.get(name);
26012 if (variable) {
26013 variable.mutated = true;
26014 }
26015 });
26016 }
26017 else {
26018 const variable = component.var_lookup.get(name);
26019 if (!variable || variable.global) {
26020 component.error(this.expression.node, {
26021 code: 'binding-undeclared',
26022 message: `${name} is not declared`
26023 });
26024 }
26025 variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
26026 if (info.expression.type === 'Identifier' && !variable.writable) {
26027 component.error(this.expression.node, {
26028 code: 'invalid-binding',
26029 message: 'Cannot bind to a variable which is not writable'
26030 });
26031 }
26032 }
26033 const type = parent.get_static_attribute_value('type');
26034 this.is_readonly =
26035 dimensions.test(this.name) ||
26036 (isElement(parent) &&
26037 ((parent.is_media_node() && read_only_media_attributes.has(this.name)) ||
26038 (parent.name === 'input' && type === 'file')) /* TODO others? */);
26039 }
26040 is_readonly_media_attribute() {
26041 return read_only_media_attributes.has(this.name);
26042 }
26043}
26044function isElement(node) {
26045 return !!node.is_media_node;
26046}
26047
26048class Transition extends Node$1 {
26049 constructor(component, parent, scope, info) {
26050 super(component, parent, scope, info);
26051 component.warn_if_undefined(info.name, info, scope);
26052 this.name = info.name;
26053 component.add_reference(info.name.split('.')[0]);
26054 this.directive = info.intro && info.outro ? 'transition' : info.intro ? 'in' : 'out';
26055 this.is_local = info.modifiers.includes('local');
26056 if ((info.intro && parent.intro) || (info.outro && parent.outro)) {
26057 const parent_transition = (parent.intro || parent.outro);
26058 const message = this.directive === parent_transition.directive
26059 ? `An element can only have one '${this.directive}' directive`
26060 : `An element cannot have both ${describe(parent_transition)} directive and ${describe(this)} directive`;
26061 component.error(info, {
26062 code: 'duplicate-transition',
26063 message
26064 });
26065 }
26066 this.expression = info.expression
26067 ? new Expression(component, this, scope, info.expression)
26068 : null;
26069 }
26070}
26071function describe(transition) {
26072 return transition.directive === 'transition'
26073 ? "a 'transition'"
26074 : `an '${transition.directive}'`;
26075}
26076
26077class Animation extends Node$1 {
26078 constructor(component, parent, scope, info) {
26079 super(component, parent, scope, info);
26080 component.warn_if_undefined(info.name, info, scope);
26081 this.name = info.name;
26082 component.add_reference(info.name.split('.')[0]);
26083 if (parent.animation) {
26084 component.error(this, {
26085 code: 'duplicate-animation',
26086 message: "An element can only have one 'animate' directive"
26087 });
26088 }
26089 const block = parent.parent;
26090 if (!block || block.type !== 'EachBlock' || !block.key) {
26091 // TODO can we relax the 'immediate child' rule?
26092 component.error(this, {
26093 code: 'invalid-animation',
26094 message: 'An element that uses the animate directive must be the immediate child of a keyed each block'
26095 });
26096 }
26097 block.has_animation = true;
26098 this.expression = info.expression
26099 ? new Expression(component, this, scope, info.expression, true)
26100 : null;
26101 }
26102}
26103
26104class Class extends Node$1 {
26105 constructor(component, parent, scope, info) {
26106 super(component, parent, scope, info);
26107 this.name = info.name;
26108 this.expression = info.expression
26109 ? new Expression(component, this, scope, info.expression)
26110 : null;
26111 }
26112}
26113
26114// Whitespace inside one of these elements will not result in
26115// a whitespace node being created in any circumstances. (This
26116// list is almost certainly very incomplete)
26117const elements_without_text = new Set([
26118 'audio',
26119 'datalist',
26120 'dl',
26121 'optgroup',
26122 'select',
26123 'video'
26124]);
26125class Text$1 extends Node$1 {
26126 constructor(component, parent, scope, info) {
26127 super(component, parent, scope, info);
26128 this.data = info.data;
26129 this.synthetic = info.synthetic || false;
26130 }
26131 should_skip() {
26132 if (/\S/.test(this.data))
26133 return false;
26134 const parent_element = this.find_nearest(/(?:Element|InlineComponent|Head)/);
26135 if (!parent_element)
26136 return false;
26137 if (parent_element.type === 'Head')
26138 return true;
26139 if (parent_element.type === 'InlineComponent')
26140 return parent_element.children.length === 1 && this === parent_element.children[0];
26141 // svg namespace exclusions
26142 if (/svg$/.test(parent_element.namespace)) {
26143 if (this.prev && this.prev.type === 'Element' && this.prev.name === 'tspan')
26144 return false;
26145 }
26146 return parent_element.namespace || elements_without_text.has(parent_element.name);
26147 }
26148}
26149
26150const applicable = new Set(['Identifier', 'ObjectExpression', 'ArrayExpression', 'Property']);
26151class Let extends Node$1 {
26152 constructor(component, parent, scope, info) {
26153 super(component, parent, scope, info);
26154 this.names = [];
26155 this.name = { type: 'Identifier', name: info.name };
26156 const { names } = this;
26157 if (info.expression) {
26158 this.value = info.expression;
26159 walk(info.expression, {
26160 enter(node) {
26161 if (!applicable.has(node.type)) {
26162 component.error(node, {
26163 code: 'invalid-let',
26164 message: 'let directive value must be an identifier or an object/array pattern'
26165 });
26166 }
26167 if (node.type === 'Identifier') {
26168 names.push(node.name);
26169 }
26170 // slightly unfortunate hack
26171 if (node.type === 'ArrayExpression') {
26172 node.type = 'ArrayPattern';
26173 }
26174 if (node.type === 'ObjectExpression') {
26175 node.type = 'ObjectPattern';
26176 }
26177 }
26178 });
26179 }
26180 else {
26181 names.push(this.name.name);
26182 }
26183 }
26184}
26185
26186const 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)$/;
26187const 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(' ');
26188const aria_attribute_set = new Set(aria_attributes);
26189const 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 graphics-document graphics-object graphics-symbol 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(' ');
26190const aria_role_set = new Set(aria_roles);
26191const a11y_required_attributes = {
26192 a: ['href'],
26193 area: ['alt', 'aria-label', 'aria-labelledby'],
26194 // html-has-lang
26195 html: ['lang'],
26196 // iframe-has-title
26197 iframe: ['title'],
26198 img: ['alt'],
26199 object: ['title', 'aria-label', 'aria-labelledby']
26200};
26201const a11y_distracting_elements = new Set([
26202 'blink',
26203 'marquee'
26204]);
26205const a11y_required_content = new Set([
26206 // anchor-has-content
26207 'a',
26208 // heading-has-content
26209 'h1',
26210 'h2',
26211 'h3',
26212 'h4',
26213 'h5',
26214 'h6'
26215]);
26216const a11y_no_onchange = new Set([
26217 'select',
26218 'option'
26219]);
26220const a11y_labelable = new Set([
26221 'button',
26222 'input',
26223 'keygen',
26224 'meter',
26225 'output',
26226 'progress',
26227 'select',
26228 'textarea'
26229]);
26230const invisible_elements = new Set(['meta', 'html', 'script', 'style']);
26231const valid_modifiers = new Set([
26232 'preventDefault',
26233 'stopPropagation',
26234 'capture',
26235 'once',
26236 'passive',
26237 'nonpassive',
26238 'self'
26239]);
26240const passive_events = new Set([
26241 'wheel',
26242 'touchstart',
26243 'touchmove',
26244 'touchend',
26245 'touchcancel'
26246]);
26247const react_attributes = new Map([
26248 ['className', 'class'],
26249 ['htmlFor', 'for']
26250]);
26251function get_namespace(parent, element, explicit_namespace) {
26252 const parent_element = parent.find_nearest(/^Element/);
26253 if (!parent_element) {
26254 return explicit_namespace || (svg$1.test(element.name)
26255 ? namespaces.svg
26256 : null);
26257 }
26258 if (svg$1.test(element.name.toLowerCase()))
26259 return namespaces.svg;
26260 if (parent_element.name.toLowerCase() === 'foreignobject')
26261 return null;
26262 return parent_element.namespace;
26263}
26264class Element$1 extends Node$1 {
26265 constructor(component, parent, scope, info) {
26266 super(component, parent, scope, info);
26267 this.attributes = [];
26268 this.actions = [];
26269 this.bindings = [];
26270 this.classes = [];
26271 this.handlers = [];
26272 this.lets = [];
26273 this.intro = null;
26274 this.outro = null;
26275 this.animation = null;
26276 this.name = info.name;
26277 this.namespace = get_namespace(parent, this, component.namespace);
26278 if (this.name === 'textarea') {
26279 if (info.children.length > 0) {
26280 const value_attribute = info.attributes.find(node => node.name === 'value');
26281 if (value_attribute) {
26282 component.error(value_attribute, {
26283 code: 'textarea-duplicate-value',
26284 message: 'A <textarea> can have either a value attribute or (equivalently) child content, but not both'
26285 });
26286 }
26287 // this is an egregious hack, but it's the easiest way to get <textarea>
26288 // children treated the same way as a value attribute
26289 info.attributes.push({
26290 type: 'Attribute',
26291 name: 'value',
26292 value: info.children
26293 });
26294 info.children = [];
26295 }
26296 }
26297 if (this.name === 'option') {
26298 // Special case — treat these the same way:
26299 // <option>{foo}</option>
26300 // <option value={foo}>{foo}</option>
26301 const value_attribute = info.attributes.find(attribute => attribute.name === 'value');
26302 if (!value_attribute) {
26303 info.attributes.push({
26304 type: 'Attribute',
26305 name: 'value',
26306 value: info.children,
26307 synthetic: true
26308 });
26309 }
26310 }
26311 const has_let = info.attributes.some(node => node.type === 'Let');
26312 if (has_let) {
26313 scope = scope.child();
26314 }
26315 // Binding relies on Attribute, defer its evaluation
26316 const order = ['Binding']; // everything else is -1
26317 info.attributes.sort((a, b) => order.indexOf(a.type) - order.indexOf(b.type));
26318 info.attributes.forEach(node => {
26319 switch (node.type) {
26320 case 'Action':
26321 this.actions.push(new Action(component, this, scope, node));
26322 break;
26323 case 'Attribute':
26324 case 'Spread':
26325 // special case
26326 if (node.name === 'xmlns')
26327 this.namespace = node.value[0].data;
26328 this.attributes.push(new Attribute(component, this, scope, node));
26329 break;
26330 case 'Binding':
26331 this.bindings.push(new Binding(component, this, scope, node));
26332 break;
26333 case 'Class':
26334 this.classes.push(new Class(component, this, scope, node));
26335 break;
26336 case 'EventHandler':
26337 this.handlers.push(new EventHandler(component, this, scope, node));
26338 break;
26339 case 'Let': {
26340 const l = new Let(component, this, scope, node);
26341 this.lets.push(l);
26342 const dependencies = new Set([l.name.name]);
26343 l.names.forEach(name => {
26344 scope.add(name, dependencies, this);
26345 });
26346 break;
26347 }
26348 case 'Transition':
26349 {
26350 const transition = new Transition(component, this, scope, node);
26351 if (node.intro)
26352 this.intro = transition;
26353 if (node.outro)
26354 this.outro = transition;
26355 break;
26356 }
26357 case 'Animation':
26358 this.animation = new Animation(component, this, scope, node);
26359 break;
26360 default:
26361 throw new Error(`Not implemented: ${node.type}`);
26362 }
26363 });
26364 this.scope = scope;
26365 this.children = map_children(component, this, this.scope, info.children);
26366 this.validate();
26367 component.apply_stylesheet(this);
26368 }
26369 validate() {
26370 if (this.component.var_lookup.has(this.name) && this.component.var_lookup.get(this.name).imported) {
26371 this.component.warn(this, {
26372 code: 'component-name-lowercase',
26373 message: `<${this.name}> will be treated as an HTML element unless it begins with a capital letter`
26374 });
26375 }
26376 if (a11y_distracting_elements.has(this.name)) {
26377 // no-distracting-elements
26378 this.component.warn(this, {
26379 code: 'a11y-distracting-elements',
26380 message: `A11y: Avoid <${this.name}> elements`
26381 });
26382 }
26383 if (this.name === 'figcaption') {
26384 let { parent } = this;
26385 let is_figure_parent = false;
26386 while (parent) {
26387 if (parent.name === 'figure') {
26388 is_figure_parent = true;
26389 break;
26390 }
26391 if (parent.type === 'Element') {
26392 break;
26393 }
26394 parent = parent.parent;
26395 }
26396 if (!is_figure_parent) {
26397 this.component.warn(this, {
26398 code: 'a11y-structure',
26399 message: 'A11y: <figcaption> must be an immediate child of <figure>'
26400 });
26401 }
26402 }
26403 if (this.name === 'figure') {
26404 const children = this.children.filter(node => {
26405 if (node.type === 'Comment')
26406 return false;
26407 if (node.type === 'Text')
26408 return /\S/.test(node.data);
26409 return true;
26410 });
26411 const index = children.findIndex(child => child.name === 'figcaption');
26412 if (index !== -1 && (index !== 0 && index !== children.length - 1)) {
26413 this.component.warn(children[index], {
26414 code: 'a11y-structure',
26415 message: 'A11y: <figcaption> must be first or last child of <figure>'
26416 });
26417 }
26418 }
26419 this.validate_attributes();
26420 this.validate_special_cases();
26421 this.validate_bindings();
26422 this.validate_content();
26423 this.validate_event_handlers();
26424 }
26425 validate_attributes() {
26426 const { component, parent } = this;
26427 const attribute_map = new Map();
26428 this.attributes.forEach(attribute => {
26429 if (attribute.is_spread)
26430 return;
26431 const name = attribute.name.toLowerCase();
26432 // aria-props
26433 if (name.startsWith('aria-')) {
26434 if (invisible_elements.has(this.name)) {
26435 // aria-unsupported-elements
26436 component.warn(attribute, {
26437 code: 'a11y-aria-attributes',
26438 message: `A11y: <${this.name}> should not have aria-* attributes`
26439 });
26440 }
26441 const type = name.slice(5);
26442 if (!aria_attribute_set.has(type)) {
26443 const match = fuzzymatch(type, aria_attributes);
26444 let message = `A11y: Unknown aria attribute 'aria-${type}'`;
26445 if (match)
26446 message += ` (did you mean '${match}'?)`;
26447 component.warn(attribute, {
26448 code: 'a11y-unknown-aria-attribute',
26449 message
26450 });
26451 }
26452 if (name === 'aria-hidden' && /^h[1-6]$/.test(this.name)) {
26453 component.warn(attribute, {
26454 code: 'a11y-hidden',
26455 message: `A11y: <${this.name}> element should not be hidden`
26456 });
26457 }
26458 }
26459 // aria-role
26460 if (name === 'role') {
26461 if (invisible_elements.has(this.name)) {
26462 // aria-unsupported-elements
26463 component.warn(attribute, {
26464 code: 'a11y-misplaced-role',
26465 message: `A11y: <${this.name}> should not have role attribute`
26466 });
26467 }
26468 const value = attribute.get_static_value();
26469 // @ts-ignore
26470 if (value && !aria_role_set.has(value)) {
26471 // @ts-ignore
26472 const match = fuzzymatch(value, aria_roles);
26473 let message = `A11y: Unknown role '${value}'`;
26474 if (match)
26475 message += ` (did you mean '${match}'?)`;
26476 component.warn(attribute, {
26477 code: 'a11y-unknown-role',
26478 message
26479 });
26480 }
26481 }
26482 // no-access-key
26483 if (name === 'accesskey') {
26484 component.warn(attribute, {
26485 code: 'a11y-accesskey',
26486 message: 'A11y: Avoid using accesskey'
26487 });
26488 }
26489 // no-autofocus
26490 if (name === 'autofocus') {
26491 component.warn(attribute, {
26492 code: 'a11y-autofocus',
26493 message: 'A11y: Avoid using autofocus'
26494 });
26495 }
26496 // scope
26497 if (name === 'scope' && this.name !== 'th') {
26498 component.warn(attribute, {
26499 code: 'a11y-misplaced-scope',
26500 message: 'A11y: The scope attribute should only be used with <th> elements'
26501 });
26502 }
26503 // tabindex-no-positive
26504 if (name === 'tabindex') {
26505 const value = attribute.get_static_value();
26506 // @ts-ignore todo is tabindex=true correct case?
26507 if (!isNaN(value) && +value > 0) {
26508 component.warn(attribute, {
26509 code: 'a11y-positive-tabindex',
26510 message: 'A11y: avoid tabindex values above zero'
26511 });
26512 }
26513 }
26514 if (/(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/.test(name)) {
26515 component.error(attribute, {
26516 code: 'illegal-attribute',
26517 message: `'${name}' is not a valid attribute name`
26518 });
26519 }
26520 if (name === 'slot') {
26521 if (!attribute.is_static) {
26522 component.error(attribute, {
26523 code: 'invalid-slot-attribute',
26524 message: 'slot attribute cannot have a dynamic value'
26525 });
26526 }
26527 if (component.slot_outlets.has(name)) {
26528 component.error(attribute, {
26529 code: 'duplicate-slot-attribute',
26530 message: `Duplicate '${name}' slot`
26531 });
26532 component.slot_outlets.add(name);
26533 }
26534 if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
26535 component.error(attribute, {
26536 code: 'invalid-slotted-content',
26537 message: 'Element with a slot=\'...\' attribute must be a child of a component or a descendant of a custom element'
26538 });
26539 }
26540 }
26541 if (name === 'is') {
26542 component.warn(attribute, {
26543 code: 'avoid-is',
26544 message: 'The \'is\' attribute is not supported cross-browser and should be avoided'
26545 });
26546 }
26547 if (react_attributes.has(attribute.name)) {
26548 component.warn(attribute, {
26549 code: 'invalid-html-attribute',
26550 message: `'${attribute.name}' is not a valid HTML attribute. Did you mean '${react_attributes.get(attribute.name)}'?`
26551 });
26552 }
26553 attribute_map.set(attribute.name, attribute);
26554 });
26555 }
26556 validate_special_cases() {
26557 const { component, attributes, handlers } = this;
26558 const attribute_map = new Map();
26559 const handlers_map = new Map();
26560 attributes.forEach(attribute => (attribute_map.set(attribute.name, attribute)));
26561 handlers.forEach(handler => (handlers_map.set(handler.name, handler)));
26562 if (this.name === 'a') {
26563 const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
26564 const id_attribute = attribute_map.get('id');
26565 const name_attribute = attribute_map.get('name');
26566 if (href_attribute) {
26567 const href_value = href_attribute.get_static_value();
26568 if (href_value === '' || href_value === '#' || /^\W*javascript:/i.test(href_value)) {
26569 component.warn(href_attribute, {
26570 code: 'a11y-invalid-attribute',
26571 message: `A11y: '${href_value}' is not a valid ${href_attribute.name} attribute`
26572 });
26573 }
26574 }
26575 else {
26576 const id_attribute_valid = id_attribute && id_attribute.get_static_value() !== '';
26577 const name_attribute_valid = name_attribute && name_attribute.get_static_value() !== '';
26578 if (!id_attribute_valid && !name_attribute_valid) {
26579 component.warn(this, {
26580 code: 'a11y-missing-attribute',
26581 message: 'A11y: <a> element should have an href attribute'
26582 });
26583 }
26584 }
26585 }
26586 else {
26587 const required_attributes = a11y_required_attributes[this.name];
26588 if (required_attributes) {
26589 const has_attribute = required_attributes.some(name => attribute_map.has(name));
26590 if (!has_attribute) {
26591 should_have_attribute(this, required_attributes);
26592 }
26593 }
26594 }
26595 if (this.name === 'input') {
26596 const type = attribute_map.get('type');
26597 if (type && type.get_static_value() === 'image') {
26598 const required_attributes = ['alt', 'aria-label', 'aria-labelledby'];
26599 const has_attribute = required_attributes.some(name => attribute_map.has(name));
26600 if (!has_attribute) {
26601 should_have_attribute(this, required_attributes, 'input type="image"');
26602 }
26603 }
26604 }
26605 if (this.name === 'img') {
26606 const alt_attribute = attribute_map.get('alt');
26607 const aria_hidden_attribute = attribute_map.get('aria-hidden');
26608 const aria_hidden_exist = aria_hidden_attribute && aria_hidden_attribute.get_static_value();
26609 if (alt_attribute && !aria_hidden_exist) {
26610 const alt_value = alt_attribute.get_static_value();
26611 if (/\b(image|picture|photo)\b/i.test(alt_value)) {
26612 component.warn(this, {
26613 code: 'a11y-img-redundant-alt',
26614 message: 'A11y: Screenreaders already announce <img> elements as an image.'
26615 });
26616 }
26617 }
26618 }
26619 if (this.name === 'label') {
26620 const has_input_child = this.children.some(i => (i instanceof Element$1 && a11y_labelable.has(i.name)));
26621 if (!attribute_map.has('for') && !has_input_child) {
26622 component.warn(this, {
26623 code: 'a11y-label-has-associated-control',
26624 message: 'A11y: A form label must be associated with a control.'
26625 });
26626 }
26627 }
26628 if (this.is_media_node()) {
26629 if (attribute_map.has('muted')) {
26630 return;
26631 }
26632 let has_caption;
26633 const track = this.children.find((i) => i.name === 'track');
26634 if (track) {
26635 has_caption = track.attributes.find(a => a.name === 'kind' && a.get_static_value() === 'captions');
26636 }
26637 if (!has_caption) {
26638 component.warn(this, {
26639 code: 'a11y-media-has-caption',
26640 message: 'A11y: Media elements must have a <track kind="captions">'
26641 });
26642 }
26643 }
26644 if (a11y_no_onchange.has(this.name)) {
26645 if (handlers_map.has('change') && !handlers_map.has('blur')) {
26646 component.warn(this, {
26647 code: 'a11y-no-onchange',
26648 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.'
26649 });
26650 }
26651 }
26652 }
26653 validate_bindings() {
26654 const { component } = this;
26655 const check_type_attribute = () => {
26656 const attribute = this.attributes.find((attribute) => attribute.name === 'type');
26657 if (!attribute)
26658 return null;
26659 if (!attribute.is_static) {
26660 component.error(attribute, {
26661 code: 'invalid-type',
26662 message: '\'type\' attribute cannot be dynamic if input uses two-way binding'
26663 });
26664 }
26665 const value = attribute.get_static_value();
26666 if (value === true) {
26667 component.error(attribute, {
26668 code: 'missing-type',
26669 message: '\'type\' attribute must be specified'
26670 });
26671 }
26672 return value;
26673 };
26674 this.bindings.forEach(binding => {
26675 const { name } = binding;
26676 if (name === 'value') {
26677 if (this.name !== 'input' &&
26678 this.name !== 'textarea' &&
26679 this.name !== 'select') {
26680 component.error(binding, {
26681 code: 'invalid-binding',
26682 message: `'value' is not a valid binding on <${this.name}> elements`
26683 });
26684 }
26685 if (this.name === 'select') {
26686 const attribute = this.attributes.find((attribute) => attribute.name === 'multiple');
26687 if (attribute && !attribute.is_static) {
26688 component.error(attribute, {
26689 code: 'dynamic-multiple-attribute',
26690 message: '\'multiple\' attribute cannot be dynamic if select uses two-way binding'
26691 });
26692 }
26693 }
26694 else {
26695 check_type_attribute();
26696 }
26697 }
26698 else if (name === 'checked' || name === 'indeterminate') {
26699 if (this.name !== 'input') {
26700 component.error(binding, {
26701 code: 'invalid-binding',
26702 message: `'${name}' is not a valid binding on <${this.name}> elements`
26703 });
26704 }
26705 const type = check_type_attribute();
26706 if (type !== 'checkbox') {
26707 let message = `'${name}' binding can only be used with <input type="checkbox">`;
26708 if (type === 'radio')
26709 message += ' — for <input type="radio">, use \'group\' binding';
26710 component.error(binding, { code: 'invalid-binding', message });
26711 }
26712 }
26713 else if (name === 'group') {
26714 if (this.name !== 'input') {
26715 component.error(binding, {
26716 code: 'invalid-binding',
26717 message: `'group' is not a valid binding on <${this.name}> elements`
26718 });
26719 }
26720 const type = check_type_attribute();
26721 if (type !== 'checkbox' && type !== 'radio') {
26722 component.error(binding, {
26723 code: 'invalid-binding',
26724 message: '\'group\' binding can only be used with <input type="checkbox"> or <input type="radio">'
26725 });
26726 }
26727 }
26728 else if (name === 'files') {
26729 if (this.name !== 'input') {
26730 component.error(binding, {
26731 code: 'invalid-binding',
26732 message: `'files' is not a valid binding on <${this.name}> elements`
26733 });
26734 }
26735 const type = check_type_attribute();
26736 if (type !== 'file') {
26737 component.error(binding, {
26738 code: 'invalid-binding',
26739 message: '\'files\' binding can only be used with <input type="file">'
26740 });
26741 }
26742 }
26743 else if (name === 'open') {
26744 if (this.name !== 'details') {
26745 component.error(binding, {
26746 code: 'invalid-binding',
26747 message: `'${name}' binding can only be used with <details>`
26748 });
26749 }
26750 }
26751 else if (name === 'currentTime' ||
26752 name === 'duration' ||
26753 name === 'paused' ||
26754 name === 'buffered' ||
26755 name === 'seekable' ||
26756 name === 'played' ||
26757 name === 'volume' ||
26758 name === 'muted' ||
26759 name === 'playbackRate' ||
26760 name === 'seeking' ||
26761 name === 'ended') {
26762 if (this.name !== 'audio' && this.name !== 'video') {
26763 component.error(binding, {
26764 code: 'invalid-binding',
26765 message: `'${name}' binding can only be used with <audio> or <video>`
26766 });
26767 }
26768 }
26769 else if (name === 'videoHeight' ||
26770 name === 'videoWidth') {
26771 if (this.name !== 'video') {
26772 component.error(binding, {
26773 code: 'invalid-binding',
26774 message: `'${name}' binding can only be used with <video>`
26775 });
26776 }
26777 }
26778 else if (dimensions.test(name)) {
26779 if (this.name === 'svg' && (name === 'offsetWidth' || name === 'offsetHeight')) {
26780 component.error(binding, {
26781 code: 'invalid-binding',
26782 message: `'${binding.name}' is not a valid binding on <svg>. Use '${name.replace('offset', 'client')}' instead`
26783 });
26784 }
26785 else if (svg$1.test(this.name)) {
26786 component.error(binding, {
26787 code: 'invalid-binding',
26788 message: `'${binding.name}' is not a valid binding on SVG elements`
26789 });
26790 }
26791 else if (is_void(this.name)) {
26792 component.error(binding, {
26793 code: 'invalid-binding',
26794 message: `'${binding.name}' is not a valid binding on void elements like <${this.name}>. Use a wrapper element instead`
26795 });
26796 }
26797 }
26798 else if (name === 'textContent' ||
26799 name === 'innerHTML') {
26800 const contenteditable = this.attributes.find((attribute) => attribute.name === 'contenteditable');
26801 if (!contenteditable) {
26802 component.error(binding, {
26803 code: 'missing-contenteditable-attribute',
26804 message: '\'contenteditable\' attribute is required for textContent and innerHTML two-way bindings'
26805 });
26806 }
26807 else if (contenteditable && !contenteditable.is_static) {
26808 component.error(contenteditable, {
26809 code: 'dynamic-contenteditable-attribute',
26810 message: '\'contenteditable\' attribute cannot be dynamic if element uses two-way binding'
26811 });
26812 }
26813 }
26814 else if (name !== 'this') {
26815 component.error(binding, {
26816 code: 'invalid-binding',
26817 message: `'${binding.name}' is not a valid binding`
26818 });
26819 }
26820 });
26821 }
26822 validate_content() {
26823 if (!a11y_required_content.has(this.name))
26824 return;
26825 if (this.bindings
26826 .some((binding) => ['textContent', 'innerHTML'].includes(binding.name)))
26827 return;
26828 if (this.children.length === 0) {
26829 this.component.warn(this, {
26830 code: 'a11y-missing-content',
26831 message: `A11y: <${this.name}> element should have child content`
26832 });
26833 }
26834 }
26835 validate_event_handlers() {
26836 const { component } = this;
26837 this.handlers.forEach(handler => {
26838 if (handler.modifiers.has('passive') && handler.modifiers.has('preventDefault')) {
26839 component.error(handler, {
26840 code: 'invalid-event-modifier',
26841 message: 'The \'passive\' and \'preventDefault\' modifiers cannot be used together'
26842 });
26843 }
26844 if (handler.modifiers.has('passive') && handler.modifiers.has('nonpassive')) {
26845 component.error(handler, {
26846 code: 'invalid-event-modifier',
26847 message: 'The \'passive\' and \'nonpassive\' modifiers cannot be used together'
26848 });
26849 }
26850 handler.modifiers.forEach(modifier => {
26851 if (!valid_modifiers.has(modifier)) {
26852 component.error(handler, {
26853 code: 'invalid-event-modifier',
26854 message: `Valid event modifiers are ${list$1(Array.from(valid_modifiers))}`
26855 });
26856 }
26857 if (modifier === 'passive') {
26858 if (passive_events.has(handler.name)) {
26859 if (handler.can_make_passive) {
26860 component.warn(handler, {
26861 code: 'redundant-event-modifier',
26862 message: 'Touch event handlers that don\'t use the \'event\' object are passive by default'
26863 });
26864 }
26865 }
26866 else {
26867 component.warn(handler, {
26868 code: 'redundant-event-modifier',
26869 message: 'The passive modifier only works with wheel and touch events'
26870 });
26871 }
26872 }
26873 if (component.compile_options.legacy && (modifier === 'once' || modifier === 'passive')) {
26874 // TODO this could be supported, but it would need a few changes to
26875 // how event listeners work
26876 component.error(handler, {
26877 code: 'invalid-event-modifier',
26878 message: `The '${modifier}' modifier cannot be used in legacy mode`
26879 });
26880 }
26881 });
26882 if (passive_events.has(handler.name) && handler.can_make_passive && !handler.modifiers.has('preventDefault') && !handler.modifiers.has('nonpassive')) {
26883 // touch/wheel events should be passive by default
26884 handler.modifiers.add('passive');
26885 }
26886 });
26887 }
26888 is_media_node() {
26889 return this.name === 'audio' || this.name === 'video';
26890 }
26891 add_css_class() {
26892 if (this.attributes.some(attr => attr.is_spread)) {
26893 this.needs_manual_style_scoping = true;
26894 return;
26895 }
26896 const { id } = this.component.stylesheet;
26897 const class_attribute = this.attributes.find(a => a.name === 'class');
26898 if (class_attribute && !class_attribute.is_true) {
26899 if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') {
26900 class_attribute.chunks[0].data += ` ${id}`;
26901 }
26902 else {
26903 class_attribute.chunks.push(new Text$1(this.component, this, this.scope, {
26904 type: 'Text',
26905 data: ` ${id}`,
26906 synthetic: true
26907 }));
26908 }
26909 }
26910 else {
26911 this.attributes.push(new Attribute(this.component, this, this.scope, {
26912 type: 'Attribute',
26913 name: 'class',
26914 value: [{ type: 'Text', data: id, synthetic: true }]
26915 }));
26916 }
26917 }
26918}
26919function should_have_attribute(node, attributes, name = node.name) {
26920 const article = /^[aeiou]/.test(attributes[0]) ? 'an' : 'a';
26921 const sequence = attributes.length > 1 ?
26922 attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}` :
26923 attributes[0];
26924 node.component.warn(node, {
26925 code: 'a11y-missing-attribute',
26926 message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
26927 });
26928}
26929function within_custom_element(parent) {
26930 while (parent) {
26931 if (parent.type === 'InlineComponent')
26932 return false;
26933 if (parent.type === 'Element' && /-/.test(parent.name))
26934 return true;
26935 parent = parent.parent;
26936 }
26937 return false;
26938}
26939
26940class Head$1 extends Node$1 {
26941 constructor(component, parent, scope, info) {
26942 super(component, parent, scope, info);
26943 if (info.attributes.length) {
26944 component.error(info.attributes[0], {
26945 code: 'invalid-attribute',
26946 message: '<svelte:head> should not have any attributes or directives'
26947 });
26948 }
26949 this.children = map_children(component, parent, scope, info.children.filter(child => {
26950 return (child.type !== 'Text' || /\S/.test(child.data));
26951 }));
26952 if (this.children.length > 0) {
26953 this.id = `svelte-${hash(this.component.source.slice(this.start, this.end))}`;
26954 }
26955 }
26956}
26957
26958class IfBlock$1 extends AbstractBlock {
26959 constructor(component, parent, scope, info) {
26960 super(component, parent, scope, info);
26961 this.expression = new Expression(component, this, scope, info.expression);
26962 this.children = map_children(component, this, scope, info.children);
26963 this.else = info.else
26964 ? new ElseBlock(component, this, scope, info.else)
26965 : null;
26966 this.warn_if_empty_block();
26967 }
26968}
26969
26970class InlineComponent$1 extends Node$1 {
26971 constructor(component, parent, scope, info) {
26972 super(component, parent, scope, info);
26973 this.attributes = [];
26974 this.bindings = [];
26975 this.handlers = [];
26976 this.lets = [];
26977 if (info.name !== 'svelte:component' && info.name !== 'svelte:self') {
26978 const name = info.name.split('.')[0]; // accommodate namespaces
26979 component.warn_if_undefined(name, info, scope);
26980 component.add_reference(name);
26981 }
26982 this.name = info.name;
26983 this.expression = this.name === 'svelte:component'
26984 ? new Expression(component, this, scope, info.expression)
26985 : null;
26986 info.attributes.forEach(node => {
26987 /* eslint-disable no-fallthrough */
26988 switch (node.type) {
26989 case 'Action':
26990 component.error(node, {
26991 code: 'invalid-action',
26992 message: 'Actions can only be applied to DOM elements, not components'
26993 });
26994 case 'Attribute':
26995 if (node.name === 'slot') {
26996 component.error(node, {
26997 code: 'invalid-prop',
26998 message: "'slot' is reserved for future use in named slots"
26999 });
27000 }
27001 // fallthrough
27002 case 'Spread':
27003 this.attributes.push(new Attribute(component, this, scope, node));
27004 break;
27005 case 'Binding':
27006 this.bindings.push(new Binding(component, this, scope, node));
27007 break;
27008 case 'Class':
27009 component.error(node, {
27010 code: 'invalid-class',
27011 message: 'Classes can only be applied to DOM elements, not components'
27012 });
27013 case 'EventHandler':
27014 this.handlers.push(new EventHandler(component, this, scope, node));
27015 break;
27016 case 'Let':
27017 this.lets.push(new Let(component, this, scope, node));
27018 break;
27019 case 'Transition':
27020 component.error(node, {
27021 code: 'invalid-transition',
27022 message: 'Transitions can only be applied to DOM elements, not components'
27023 });
27024 default:
27025 throw new Error(`Not implemented: ${node.type}`);
27026 }
27027 /* eslint-enable no-fallthrough */
27028 });
27029 if (this.lets.length > 0) {
27030 this.scope = scope.child();
27031 this.lets.forEach(l => {
27032 const dependencies = new Set([l.name.name]);
27033 l.names.forEach(name => {
27034 this.scope.add(name, dependencies, this);
27035 });
27036 });
27037 }
27038 else {
27039 this.scope = scope;
27040 }
27041 this.handlers.forEach(handler => {
27042 handler.modifiers.forEach(modifier => {
27043 if (modifier !== 'once') {
27044 component.error(handler, {
27045 code: 'invalid-event-modifier',
27046 message: "Event modifiers other than 'once' can only be used on DOM elements"
27047 });
27048 }
27049 });
27050 });
27051 this.children = map_children(component, this, this.scope, info.children);
27052 }
27053}
27054
27055class KeyBlock$1 extends AbstractBlock {
27056 constructor(component, parent, scope, info) {
27057 super(component, parent, scope, info);
27058 this.expression = new Expression(component, this, scope, info.expression);
27059 this.children = map_children(component, this, scope, info.children);
27060 this.warn_if_empty_block();
27061 }
27062}
27063
27064class Tag$2 extends Node$1 {
27065 constructor(component, parent, scope, info) {
27066 super(component, parent, scope, info);
27067 this.expression = new Expression(component, this, scope, info.expression);
27068 this.should_cache = (info.expression.type !== 'Identifier' ||
27069 (this.expression.dependencies.size && scope.names.has(info.expression.name)));
27070 }
27071}
27072
27073class MustacheTag extends Tag$2 {
27074}
27075
27076class Options extends Node$1 {
27077}
27078
27079class RawMustacheTag extends Tag$2 {
27080}
27081
27082class DebugTag$1 extends Node$1 {
27083 constructor(component, parent, scope, info) {
27084 super(component, parent, scope, info);
27085 this.expressions = info.identifiers.map((node) => {
27086 return new Expression(component, parent, scope, node);
27087 });
27088 }
27089}
27090
27091class Slot$1 extends Element$1 {
27092 constructor(component, parent, scope, info) {
27093 super(component, parent, scope, info);
27094 this.values = new Map();
27095 info.attributes.forEach(attr => {
27096 if (attr.type !== 'Attribute' && attr.type !== 'Spread') {
27097 component.error(attr, {
27098 code: 'invalid-slot-directive',
27099 message: '<slot> cannot have directives'
27100 });
27101 }
27102 if (attr.name === 'name') {
27103 if (attr.value.length !== 1 || attr.value[0].type !== 'Text') {
27104 component.error(attr, {
27105 code: 'dynamic-slot-name',
27106 message: '<slot> name cannot be dynamic'
27107 });
27108 }
27109 this.slot_name = attr.value[0].data;
27110 if (this.slot_name === 'default') {
27111 component.error(attr, {
27112 code: 'invalid-slot-name',
27113 message: 'default is a reserved word — it cannot be used as a slot name'
27114 });
27115 }
27116 }
27117 this.values.set(attr.name, new Attribute(component, this, scope, attr));
27118 });
27119 if (!this.slot_name)
27120 this.slot_name = 'default';
27121 if (this.slot_name === 'default') {
27122 // if this is the default slot, add our dependencies to any
27123 // other slots (which inherit our slot values) that were
27124 // previously encountered
27125 component.slots.forEach((slot) => {
27126 this.values.forEach((attribute, name) => {
27127 if (!slot.values.has(name)) {
27128 slot.values.set(name, attribute);
27129 }
27130 });
27131 });
27132 }
27133 else if (component.slots.has('default')) {
27134 // otherwise, go the other way — inherit values from
27135 // a previously encountered default slot
27136 const default_slot = component.slots.get('default');
27137 default_slot.values.forEach((attribute, name) => {
27138 if (!this.values.has(name)) {
27139 this.values.set(name, attribute);
27140 }
27141 });
27142 }
27143 component.slots.set(this.slot_name, this);
27144 }
27145}
27146
27147class Title$1 extends Node$1 {
27148 constructor(component, parent, scope, info) {
27149 super(component, parent, scope, info);
27150 this.children = map_children(component, parent, scope, info.children);
27151 if (info.attributes.length > 0) {
27152 component.error(info.attributes[0], {
27153 code: 'illegal-attribute',
27154 message: '<title> cannot have attributes'
27155 });
27156 }
27157 info.children.forEach(child => {
27158 if (child.type !== 'Text' && child.type !== 'MustacheTag') {
27159 component.error(child, {
27160 code: 'illegal-structure',
27161 message: '<title> can only contain text and {tags}'
27162 });
27163 }
27164 });
27165 this.should_cache = info.children.length === 1
27166 ? (info.children[0].type !== 'Identifier' ||
27167 scope.names.has(info.children[0].name))
27168 : true;
27169 }
27170}
27171
27172const valid_bindings = [
27173 'innerWidth',
27174 'innerHeight',
27175 'outerWidth',
27176 'outerHeight',
27177 'scrollX',
27178 'scrollY',
27179 'online'
27180];
27181class Window extends Node$1 {
27182 constructor(component, parent, scope, info) {
27183 super(component, parent, scope, info);
27184 this.handlers = [];
27185 this.bindings = [];
27186 this.actions = [];
27187 info.attributes.forEach(node => {
27188 if (node.type === 'EventHandler') {
27189 this.handlers.push(new EventHandler(component, this, scope, node));
27190 }
27191 else if (node.type === 'Binding') {
27192 if (node.expression.type !== 'Identifier') {
27193 const { parts } = flatten_reference(node.expression);
27194 // TODO is this constraint necessary?
27195 component.error(node.expression, {
27196 code: 'invalid-binding',
27197 message: `Bindings on <svelte:window> must be to top-level properties, e.g. '${parts[parts.length - 1]}' rather than '${parts.join('.')}'`
27198 });
27199 }
27200 if (!~valid_bindings.indexOf(node.name)) {
27201 const match = (node.name === 'width' ? 'innerWidth' :
27202 node.name === 'height' ? 'innerHeight' :
27203 fuzzymatch(node.name, valid_bindings));
27204 const message = `'${node.name}' is not a valid binding on <svelte:window>`;
27205 if (match) {
27206 component.error(node, {
27207 code: 'invalid-binding',
27208 message: `${message} (did you mean '${match}'?)`
27209 });
27210 }
27211 else {
27212 component.error(node, {
27213 code: 'invalid-binding',
27214 message: `${message} — valid bindings are ${list$1(valid_bindings)}`
27215 });
27216 }
27217 }
27218 this.bindings.push(new Binding(component, this, scope, node));
27219 }
27220 else if (node.type === 'Action') {
27221 this.actions.push(new Action(component, this, scope, node));
27222 }
27223 });
27224 }
27225}
27226
27227function get_constructor(type) {
27228 switch (type) {
27229 case 'AwaitBlock': return AwaitBlock$1;
27230 case 'Body': return Body;
27231 case 'Comment': return Comment$2;
27232 case 'EachBlock': return EachBlock$1;
27233 case 'Element': return Element$1;
27234 case 'Head': return Head$1;
27235 case 'IfBlock': return IfBlock$1;
27236 case 'InlineComponent': return InlineComponent$1;
27237 case 'KeyBlock': return KeyBlock$1;
27238 case 'MustacheTag': return MustacheTag;
27239 case 'Options': return Options;
27240 case 'RawMustacheTag': return RawMustacheTag;
27241 case 'DebugTag': return DebugTag$1;
27242 case 'Slot': return Slot$1;
27243 case 'Text': return Text$1;
27244 case 'Title': return Title$1;
27245 case 'Window': return Window;
27246 default: throw new Error(`Not implemented: ${type}`);
27247 }
27248}
27249function map_children(component, parent, scope, children) {
27250 let last = null;
27251 let ignores = [];
27252 return children.map(child => {
27253 const constructor = get_constructor(child.type);
27254 const use_ignores = child.type !== 'Text' && child.type !== 'Comment' && ignores.length;
27255 if (use_ignores)
27256 component.push_ignores(ignores);
27257 const node = new constructor(component, parent, scope, child);
27258 if (use_ignores)
27259 component.pop_ignores(), ignores = [];
27260 if (node.type === 'Comment' && node.ignores.length) {
27261 ignores.push(...node.ignores);
27262 }
27263 if (last)
27264 last.next = node;
27265 node.prev = last;
27266 last = node;
27267 return node;
27268 });
27269}
27270
27271class TemplateScope {
27272 constructor(parent) {
27273 this.owners = new Map();
27274 this.parent = parent;
27275 this.names = new Set(parent ? parent.names : []);
27276 this.dependencies_for_name = new Map(parent ? parent.dependencies_for_name : []);
27277 }
27278 add(name, dependencies, owner) {
27279 this.names.add(name);
27280 this.dependencies_for_name.set(name, dependencies);
27281 this.owners.set(name, owner);
27282 return this;
27283 }
27284 child() {
27285 const child = new TemplateScope(this);
27286 return child;
27287 }
27288 is_top_level(name) {
27289 return !this.parent || !this.names.has(name) && this.parent.is_top_level(name);
27290 }
27291 get_owner(name) {
27292 return this.owners.get(name) || (this.parent && this.parent.get_owner(name));
27293 }
27294 is_let(name) {
27295 const owner = this.get_owner(name);
27296 return owner && (owner.type === 'Element' || owner.type === 'InlineComponent');
27297 }
27298 is_await(name) {
27299 const owner = this.get_owner(name);
27300 return owner && (owner.type === 'ThenBlock' || owner.type === 'CatchBlock');
27301 }
27302}
27303
27304class Fragment extends Node$1 {
27305 constructor(component, info) {
27306 const scope = new TemplateScope();
27307 super(component, null, scope, info);
27308 this.scope = scope;
27309 this.children = map_children(component, this, scope, info.children);
27310 }
27311}
27312
27313// This file is automatically generated
27314var internal_exports = new Set(["HtmlTag", "SvelteComponent", "SvelteComponentDev", "SvelteComponentTyped", "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", "hasContext", "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", "update_slot_spread", "validate_component", "validate_each_argument", "validate_each_keys", "validate_slots", "validate_store", "xlink_attr"]);
27315
27316function is_used_as_reference(node, parent) {
27317 if (!isReference(node, parent)) {
27318 return false;
27319 }
27320 if (!parent) {
27321 return true;
27322 }
27323 /* eslint-disable no-fallthrough */
27324 switch (parent.type) {
27325 // disregard the `foo` in `const foo = bar`
27326 case 'VariableDeclarator':
27327 return node !== parent.id;
27328 // disregard the `foo`, `bar` in `function foo(bar){}`
27329 case 'FunctionDeclaration':
27330 // disregard the `foo` in `import { foo } from 'foo'`
27331 case 'ImportSpecifier':
27332 // disregard the `foo` in `import foo from 'foo'`
27333 case 'ImportDefaultSpecifier':
27334 // disregard the `foo` in `import * as foo from 'foo'`
27335 case 'ImportNamespaceSpecifier':
27336 // disregard the `foo` in `export { foo }`
27337 case 'ExportSpecifier':
27338 return false;
27339 default:
27340 return true;
27341 }
27342}
27343
27344function check_graph_for_cycles(edges) {
27345 const graph = edges.reduce((g, edge) => {
27346 const [u, v] = edge;
27347 if (!g.has(u))
27348 g.set(u, []);
27349 if (!g.has(v))
27350 g.set(v, []);
27351 g.get(u).push(v);
27352 return g;
27353 }, new Map());
27354 const visited = new Set();
27355 const on_stack = new Set();
27356 const cycles = [];
27357 function visit(v) {
27358 visited.add(v);
27359 on_stack.add(v);
27360 graph.get(v).forEach(w => {
27361 if (!visited.has(w)) {
27362 visit(w);
27363 }
27364 else if (on_stack.has(w)) {
27365 cycles.push([...on_stack, w]);
27366 }
27367 });
27368 on_stack.delete(v);
27369 }
27370 graph.forEach((_, v) => {
27371 if (!visited.has(v)) {
27372 visit(v);
27373 }
27374 });
27375 return cycles[0];
27376}
27377
27378class Component {
27379 constructor(ast, source, name, compile_options, stats, warnings) {
27380 this.ignore_stack = [];
27381 this.vars = [];
27382 this.var_lookup = new Map();
27383 this.imports = [];
27384 this.hoistable_nodes = new Set();
27385 this.node_for_declaration = new Map();
27386 this.partly_hoisted = [];
27387 this.fully_hoisted = [];
27388 this.reactive_declarations = [];
27389 this.reactive_declaration_nodes = new Set();
27390 this.has_reactive_assignments = false;
27391 this.injected_reactive_declaration_vars = new Set();
27392 this.helpers = new Map();
27393 this.globals = new Map();
27394 this.indirect_dependencies = new Map();
27395 this.elements = [];
27396 this.aliases = new Map();
27397 this.used_names = new Set();
27398 this.globally_used_names = new Set();
27399 this.slots = new Map();
27400 this.slot_outlets = new Set();
27401 this.name = { type: 'Identifier', name };
27402 this.stats = stats;
27403 this.warnings = warnings;
27404 this.ast = ast;
27405 this.source = source;
27406 this.compile_options = compile_options;
27407 // the instance JS gets mutated, so we park
27408 // a copy here for later. TODO this feels gross
27409 this.original_ast = {
27410 html: ast.html,
27411 css: ast.css,
27412 instance: ast.instance && JSON.parse(JSON.stringify(ast.instance)),
27413 module: ast.module
27414 };
27415 this.file =
27416 compile_options.filename &&
27417 (typeof process !== 'undefined'
27418 ? compile_options.filename
27419 .replace(process.cwd(), '')
27420 .replace(/^[/\\]/, '')
27421 : compile_options.filename);
27422 this.locate = getLocator(this.source, { offsetLine: 1 });
27423 // styles
27424 this.stylesheet = new Stylesheet(source, ast, compile_options.filename, compile_options.dev);
27425 this.stylesheet.validate(this);
27426 this.component_options = process_component_options(this, this.ast.html.children);
27427 this.namespace =
27428 namespaces[this.component_options.namespace] ||
27429 this.component_options.namespace;
27430 if (compile_options.customElement) {
27431 if (this.component_options.tag === undefined &&
27432 compile_options.tag === undefined) {
27433 const svelteOptions = ast.html.children.find(child => child.name === 'svelte:options') || { start: 0, end: 0 };
27434 this.warn(svelteOptions, {
27435 code: 'custom-element-no-tag',
27436 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}/>'
27437 });
27438 }
27439 this.tag = this.component_options.tag || compile_options.tag;
27440 }
27441 else {
27442 this.tag = this.name.name;
27443 }
27444 this.walk_module_js();
27445 this.walk_instance_js_pre_template();
27446 this.fragment = new Fragment(this, ast.html);
27447 this.name = this.get_unique_name(name);
27448 this.walk_instance_js_post_template();
27449 this.elements.forEach(element => this.stylesheet.apply(element));
27450 if (!compile_options.customElement)
27451 this.stylesheet.reify();
27452 this.stylesheet.warn_on_unused_selectors(this);
27453 }
27454 add_var(variable) {
27455 this.vars.push(variable);
27456 this.var_lookup.set(variable.name, variable);
27457 }
27458 add_reference(name) {
27459 const variable = this.var_lookup.get(name);
27460 if (variable) {
27461 variable.referenced = true;
27462 }
27463 else if (is_reserved_keyword(name)) {
27464 this.add_var({
27465 name,
27466 injected: true,
27467 referenced: true
27468 });
27469 }
27470 else if (name[0] === '$') {
27471 this.add_var({
27472 name,
27473 injected: true,
27474 referenced: true,
27475 mutated: true,
27476 writable: true
27477 });
27478 const subscribable_name = name.slice(1);
27479 const variable = this.var_lookup.get(subscribable_name);
27480 if (variable) {
27481 variable.referenced = true;
27482 variable.subscribable = true;
27483 }
27484 }
27485 else {
27486 this.used_names.add(name);
27487 }
27488 }
27489 alias(name) {
27490 if (!this.aliases.has(name)) {
27491 this.aliases.set(name, this.get_unique_name(name));
27492 }
27493 return this.aliases.get(name);
27494 }
27495 apply_stylesheet(element) {
27496 this.elements.push(element);
27497 }
27498 global(name) {
27499 const alias = this.alias(name);
27500 this.globals.set(name, alias);
27501 return alias;
27502 }
27503 generate(result) {
27504 let js = null;
27505 let css = null;
27506 if (result) {
27507 const { compile_options, name } = this;
27508 const { format = 'esm' } = compile_options;
27509 const banner = `${this.file ? `${this.file} ` : ''}generated by Svelte v${'3.31.2'}`;
27510 const program = { type: 'Program', body: result.js };
27511 walk(program, {
27512 enter: (node, parent, key) => {
27513 if (node.type === 'Identifier') {
27514 if (node.name[0] === '@') {
27515 if (node.name[1] === '_') {
27516 const alias = this.global(node.name.slice(2));
27517 node.name = alias.name;
27518 }
27519 else {
27520 let name = node.name.slice(1);
27521 if (compile_options.dev) {
27522 if (internal_exports.has(`${name}_dev`)) {
27523 name += '_dev';
27524 }
27525 else if (internal_exports.has(`${name}Dev`)) {
27526 name += 'Dev';
27527 }
27528 }
27529 const alias = this.alias(name);
27530 this.helpers.set(name, alias);
27531 node.name = alias.name;
27532 }
27533 }
27534 else if (node.name[0] !== '#' && !is_valid(node.name)) {
27535 // this hack allows x`foo.${bar}` where bar could be invalid
27536 const literal = { type: 'Literal', value: node.name };
27537 if (parent.type === 'Property' && key === 'key') {
27538 parent.key = literal;
27539 }
27540 else if (parent.type === 'MemberExpression' && key === 'property') {
27541 parent.property = literal;
27542 parent.computed = true;
27543 }
27544 }
27545 }
27546 }
27547 });
27548 const referenced_globals = Array.from(this.globals, ([name, alias]) => name !== alias.name && { name, alias }).filter(Boolean);
27549 if (referenced_globals.length) {
27550 this.helpers.set('globals', this.alias('globals'));
27551 }
27552 const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({
27553 name,
27554 alias
27555 }));
27556 create_module(program, format, name, banner, compile_options.sveltePath, imported_helpers, referenced_globals, this.imports, this.vars
27557 .filter(variable => variable.module && variable.export_name)
27558 .map(variable => ({
27559 name: variable.name,
27560 as: variable.export_name
27561 })));
27562 css = compile_options.customElement
27563 ? { code: null, map: null }
27564 : result.css;
27565 js = print(program, {
27566 sourceMapSource: compile_options.filename
27567 });
27568 js.map.sources = [
27569 compile_options.filename ? get_relative_path(compile_options.outputFilename || '', compile_options.filename) : null
27570 ];
27571 js.map.sourcesContent = [
27572 this.source
27573 ];
27574 js.map = apply_preprocessor_sourcemap(this.file, js.map, compile_options.sourcemap);
27575 }
27576 return {
27577 js,
27578 css,
27579 ast: this.original_ast,
27580 warnings: this.warnings,
27581 vars: this.vars
27582 .filter(v => !v.global && !v.internal)
27583 .map(v => ({
27584 name: v.name,
27585 export_name: v.export_name || null,
27586 injected: v.injected || false,
27587 module: v.module || false,
27588 mutated: v.mutated || false,
27589 reassigned: v.reassigned || false,
27590 referenced: v.referenced || false,
27591 writable: v.writable || false,
27592 referenced_from_script: v.referenced_from_script || false
27593 })),
27594 stats: this.stats.render()
27595 };
27596 }
27597 get_unique_name(name, scope) {
27598 if (test)
27599 name = `${name}$`;
27600 let alias = name;
27601 for (let i = 1; reserved.has(alias) ||
27602 this.var_lookup.has(alias) ||
27603 this.used_names.has(alias) ||
27604 this.globally_used_names.has(alias) ||
27605 (scope && scope.has(alias)); alias = `${name}_${i++}`)
27606 ;
27607 this.used_names.add(alias);
27608 return { type: 'Identifier', name: alias };
27609 }
27610 get_unique_name_maker() {
27611 const local_used_names = new Set();
27612 function add(name) {
27613 local_used_names.add(name);
27614 }
27615 reserved.forEach(add);
27616 internal_exports.forEach(add);
27617 this.var_lookup.forEach((_value, key) => add(key));
27618 return (name) => {
27619 if (test)
27620 name = `${name}$`;
27621 let alias = name;
27622 for (let i = 1; this.used_names.has(alias) || local_used_names.has(alias); alias = `${name}_${i++}`)
27623 ;
27624 local_used_names.add(alias);
27625 this.globally_used_names.add(alias);
27626 return {
27627 type: 'Identifier',
27628 name: alias
27629 };
27630 };
27631 }
27632 error(pos, e) {
27633 error$1(e.message, {
27634 name: 'ValidationError',
27635 code: e.code,
27636 source: this.source,
27637 start: pos.start,
27638 end: pos.end,
27639 filename: this.compile_options.filename
27640 });
27641 }
27642 warn(pos, warning) {
27643 if (this.ignores && this.ignores.has(warning.code)) {
27644 return;
27645 }
27646 const start = this.locate(pos.start);
27647 const end = this.locate(pos.end);
27648 const frame = get_code_frame(this.source, start.line - 1, start.column);
27649 this.warnings.push({
27650 code: warning.code,
27651 message: warning.message,
27652 frame,
27653 start,
27654 end,
27655 pos: pos.start,
27656 filename: this.compile_options.filename,
27657 toString: () => `${warning.message} (${start.line}:${start.column})\n${frame}`
27658 });
27659 }
27660 extract_imports(node) {
27661 this.imports.push(node);
27662 }
27663 extract_exports(node) {
27664 if (node.type === 'ExportDefaultDeclaration') {
27665 this.error(node, {
27666 code: 'default-export',
27667 message: 'A component cannot have a default export'
27668 });
27669 }
27670 if (node.type === 'ExportNamedDeclaration') {
27671 if (node.source) {
27672 this.error(node, {
27673 code: 'not-implemented',
27674 message: 'A component currently cannot have an export ... from'
27675 });
27676 }
27677 if (node.declaration) {
27678 if (node.declaration.type === 'VariableDeclaration') {
27679 node.declaration.declarations.forEach(declarator => {
27680 extract_names(declarator.id).forEach(name => {
27681 const variable = this.var_lookup.get(name);
27682 variable.export_name = name;
27683 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
27684 this.warn(declarator, {
27685 code: 'unused-export-let',
27686 message: `${this.name.name} has unused export property '${name}'. If it is for external reference only, please consider using \`export const ${name}\``
27687 });
27688 }
27689 });
27690 });
27691 }
27692 else {
27693 const { name } = node.declaration.id;
27694 const variable = this.var_lookup.get(name);
27695 variable.export_name = name;
27696 }
27697 return node.declaration;
27698 }
27699 else {
27700 node.specifiers.forEach(specifier => {
27701 const variable = this.var_lookup.get(specifier.local.name);
27702 if (variable) {
27703 variable.export_name = specifier.exported.name;
27704 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
27705 this.warn(specifier, {
27706 code: 'unused-export-let',
27707 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}\``
27708 });
27709 }
27710 }
27711 });
27712 return null;
27713 }
27714 }
27715 }
27716 extract_javascript(script) {
27717 if (!script)
27718 return null;
27719 return script.content.body.filter(node => {
27720 if (!node)
27721 return false;
27722 if (this.hoistable_nodes.has(node))
27723 return false;
27724 if (this.reactive_declaration_nodes.has(node))
27725 return false;
27726 if (node.type === 'ImportDeclaration')
27727 return false;
27728 if (node.type === 'ExportDeclaration' && node.specifiers.length > 0)
27729 return false;
27730 return true;
27731 });
27732 }
27733 walk_module_js() {
27734 const component = this;
27735 const script = this.ast.module;
27736 if (!script)
27737 return;
27738 walk(script.content, {
27739 enter(node) {
27740 if (node.type === 'LabeledStatement' && node.label.name === '$') {
27741 component.warn(node, {
27742 code: 'module-script-reactive-declaration',
27743 message: '$: has no effect in a module script'
27744 });
27745 }
27746 }
27747 });
27748 const { scope, globals } = create_scopes(script.content);
27749 this.module_scope = scope;
27750 scope.declarations.forEach((node, name) => {
27751 if (name[0] === '$') {
27752 this.error(node, {
27753 code: 'illegal-declaration',
27754 message: 'The $ prefix is reserved, and cannot be used for variable and import names'
27755 });
27756 }
27757 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
27758 this.add_var({
27759 name,
27760 module: true,
27761 hoistable: true,
27762 writable
27763 });
27764 });
27765 globals.forEach((node, name) => {
27766 if (name[0] === '$') {
27767 this.error(node, {
27768 code: 'illegal-subscription',
27769 message: 'Cannot reference store value inside <script context="module">'
27770 });
27771 }
27772 else {
27773 this.add_var({
27774 name,
27775 global: true,
27776 hoistable: true
27777 });
27778 }
27779 });
27780 const { body } = script.content;
27781 let i = body.length;
27782 while (--i >= 0) {
27783 const node = body[i];
27784 if (node.type === 'ImportDeclaration') {
27785 this.extract_imports(node);
27786 body.splice(i, 1);
27787 }
27788 if (/^Export/.test(node.type)) {
27789 const replacement = this.extract_exports(node);
27790 if (replacement) {
27791 body[i] = replacement;
27792 }
27793 else {
27794 body.splice(i, 1);
27795 }
27796 }
27797 }
27798 }
27799 walk_instance_js_pre_template() {
27800 const script = this.ast.instance;
27801 if (!script)
27802 return;
27803 // inject vars for reactive declarations
27804 script.content.body.forEach(node => {
27805 if (node.type !== 'LabeledStatement')
27806 return;
27807 if (node.body.type !== 'ExpressionStatement')
27808 return;
27809 const { expression } = node.body;
27810 if (expression.type !== 'AssignmentExpression')
27811 return;
27812 if (expression.left.type === 'MemberExpression')
27813 return;
27814 extract_names(expression.left).forEach(name => {
27815 if (!this.var_lookup.has(name) && name[0] !== '$') {
27816 this.injected_reactive_declaration_vars.add(name);
27817 }
27818 });
27819 });
27820 const { scope: instance_scope, map, globals } = create_scopes(script.content);
27821 this.instance_scope = instance_scope;
27822 this.instance_scope_map = map;
27823 instance_scope.declarations.forEach((node, name) => {
27824 if (name[0] === '$') {
27825 this.error(node, {
27826 code: 'illegal-declaration',
27827 message: 'The $ prefix is reserved, and cannot be used for variable and import names'
27828 });
27829 }
27830 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
27831 const imported = node.type.startsWith('Import');
27832 this.add_var({
27833 name,
27834 initialised: instance_scope.initialised_declarations.has(name),
27835 writable,
27836 imported
27837 });
27838 this.node_for_declaration.set(name, node);
27839 });
27840 globals.forEach((node, name) => {
27841 if (this.var_lookup.has(name))
27842 return;
27843 if (this.injected_reactive_declaration_vars.has(name)) {
27844 this.add_var({
27845 name,
27846 injected: true,
27847 writable: true,
27848 reassigned: true,
27849 initialised: true
27850 });
27851 }
27852 else if (is_reserved_keyword(name)) {
27853 this.add_var({
27854 name,
27855 injected: true
27856 });
27857 }
27858 else if (name[0] === '$') {
27859 if (name === '$' || name[1] === '$') {
27860 this.error(node, {
27861 code: 'illegal-global',
27862 message: `${name} is an illegal variable name`
27863 });
27864 }
27865 this.add_var({
27866 name,
27867 injected: true,
27868 mutated: true,
27869 writable: true
27870 });
27871 this.add_reference(name.slice(1));
27872 const variable = this.var_lookup.get(name.slice(1));
27873 if (variable) {
27874 variable.subscribable = true;
27875 variable.referenced_from_script = true;
27876 }
27877 }
27878 else {
27879 this.add_var({
27880 name,
27881 global: true,
27882 hoistable: true
27883 });
27884 }
27885 });
27886 this.track_references_and_mutations();
27887 }
27888 walk_instance_js_post_template() {
27889 const script = this.ast.instance;
27890 if (!script)
27891 return;
27892 this.post_template_walk();
27893 this.hoist_instance_declarations();
27894 this.extract_reactive_declarations();
27895 }
27896 post_template_walk() {
27897 const script = this.ast.instance;
27898 if (!script)
27899 return;
27900 const component = this;
27901 const { content } = script;
27902 const { instance_scope, instance_scope_map: map } = this;
27903 let scope = instance_scope;
27904 const to_remove = [];
27905 const remove = (parent, prop, index) => {
27906 to_remove.unshift([parent, prop, index]);
27907 };
27908 let scope_updated = false;
27909 let generator_count = 0;
27910 walk(content, {
27911 enter(node, parent, prop, index) {
27912 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
27913 generator_count++;
27914 }
27915 if (map.has(node)) {
27916 scope = map.get(node);
27917 }
27918 if (node.type === 'ImportDeclaration') {
27919 component.extract_imports(node);
27920 // TODO: to use actual remove
27921 remove(parent, prop, index);
27922 return this.skip();
27923 }
27924 if (/^Export/.test(node.type)) {
27925 const replacement = component.extract_exports(node);
27926 if (replacement) {
27927 this.replace(replacement);
27928 }
27929 else {
27930 // TODO: to use actual remove
27931 remove(parent, prop, index);
27932 }
27933 return this.skip();
27934 }
27935 component.warn_on_undefined_store_value_references(node, parent, scope);
27936 },
27937 leave(node) {
27938 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
27939 generator_count--;
27940 }
27941 // do it on leave, to prevent infinite loop
27942 if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0 && generator_count <= 0) {
27943 const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout);
27944 if (to_replace_for_loop_protect) {
27945 this.replace(to_replace_for_loop_protect);
27946 scope_updated = true;
27947 }
27948 }
27949 if (map.has(node)) {
27950 scope = scope.parent;
27951 }
27952 }
27953 });
27954 for (const [parent, prop, index] of to_remove) {
27955 if (parent) {
27956 if (index !== null) {
27957 parent[prop].splice(index, 1);
27958 }
27959 else {
27960 delete parent[prop];
27961 }
27962 }
27963 }
27964 if (scope_updated) {
27965 const { scope, map } = create_scopes(script.content);
27966 this.instance_scope = scope;
27967 this.instance_scope_map = map;
27968 }
27969 }
27970 track_references_and_mutations() {
27971 const script = this.ast.instance;
27972 if (!script)
27973 return;
27974 const component = this;
27975 const { content } = script;
27976 const { instance_scope, module_scope, instance_scope_map: map } = this;
27977 let scope = instance_scope;
27978 walk(content, {
27979 enter(node, parent) {
27980 if (map.has(node)) {
27981 scope = map.get(node);
27982 }
27983 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
27984 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
27985 const names = extract_names(assignee);
27986 const deep = assignee.type === 'MemberExpression';
27987 names.forEach(name => {
27988 const scope_owner = scope.find_owner(name);
27989 if (scope_owner !== null
27990 ? scope_owner === instance_scope
27991 : module_scope && module_scope.has(name)) {
27992 const variable = component.var_lookup.get(name);
27993 variable[deep ? 'mutated' : 'reassigned'] = true;
27994 }
27995 });
27996 }
27997 if (is_used_as_reference(node, parent)) {
27998 const object = get_object(node);
27999 if (scope.find_owner(object.name) === instance_scope) {
28000 const variable = component.var_lookup.get(object.name);
28001 variable.referenced_from_script = true;
28002 }
28003 }
28004 },
28005 leave(node) {
28006 if (map.has(node)) {
28007 scope = scope.parent;
28008 }
28009 }
28010 });
28011 }
28012 warn_on_undefined_store_value_references(node, parent, scope) {
28013 if (node.type === 'LabeledStatement' &&
28014 node.label.name === '$' &&
28015 parent.type !== 'Program') {
28016 this.warn(node, {
28017 code: 'non-top-level-reactive-declaration',
28018 message: '$: has no effect outside of the top-level'
28019 });
28020 }
28021 if (isReference(node, parent)) {
28022 const object = get_object(node);
28023 const { name } = object;
28024 if (name[0] === '$') {
28025 if (!scope.has(name)) {
28026 this.warn_if_undefined(name, object, null);
28027 }
28028 if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
28029 this.error(node, {
28030 code: 'contextual-store',
28031 message: 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
28032 });
28033 }
28034 }
28035 }
28036 }
28037 loop_protect(node, scope, timeout) {
28038 if (node.type === 'WhileStatement' ||
28039 node.type === 'ForStatement' ||
28040 node.type === 'DoWhileStatement') {
28041 const guard = this.get_unique_name('guard', scope);
28042 this.used_names.add(guard.name);
28043 const before = b `const ${guard} = @loop_guard(${timeout})`;
28044 const inside = b `${guard}();`;
28045 // wrap expression statement with BlockStatement
28046 if (node.body.type !== 'BlockStatement') {
28047 node.body = {
28048 type: 'BlockStatement',
28049 body: [node.body]
28050 };
28051 }
28052 node.body.body.push(inside[0]);
28053 return {
28054 type: 'BlockStatement',
28055 body: [
28056 before[0],
28057 node
28058 ]
28059 };
28060 }
28061 return null;
28062 }
28063 rewrite_props(get_insert) {
28064 if (!this.ast.instance)
28065 return;
28066 const component = this;
28067 const { instance_scope, instance_scope_map: map } = this;
28068 let scope = instance_scope;
28069 walk(this.ast.instance.content, {
28070 enter(node, parent, key, index) {
28071 if (/Function/.test(node.type)) {
28072 return this.skip();
28073 }
28074 if (map.has(node)) {
28075 scope = map.get(node);
28076 }
28077 if (node.type === 'VariableDeclaration') {
28078 if (node.kind === 'var' || scope === instance_scope) {
28079 node.declarations.forEach(declarator => {
28080 if (declarator.id.type !== 'Identifier') {
28081 const inserts = [];
28082 extract_names(declarator.id).forEach(name => {
28083 const variable = component.var_lookup.get(name);
28084 if (variable.export_name) {
28085 // TODO is this still true post-#3539?
28086 component.error(declarator, {
28087 code: 'destructured-prop',
28088 message: 'Cannot declare props in destructured declaration'
28089 });
28090 }
28091 if (variable.subscribable) {
28092 inserts.push(get_insert(variable));
28093 }
28094 });
28095 if (inserts.length) {
28096 parent[key].splice(index + 1, 0, ...inserts);
28097 }
28098 return;
28099 }
28100 const { name } = declarator.id;
28101 const variable = component.var_lookup.get(name);
28102 if (variable.export_name && variable.writable) {
28103 declarator.id = {
28104 type: 'ObjectPattern',
28105 properties: [{
28106 type: 'Property',
28107 method: false,
28108 shorthand: false,
28109 computed: false,
28110 kind: 'init',
28111 key: { type: 'Identifier', name: variable.export_name },
28112 value: declarator.init
28113 ? {
28114 type: 'AssignmentPattern',
28115 left: declarator.id,
28116 right: declarator.init
28117 }
28118 : declarator.id
28119 }]
28120 };
28121 declarator.init = x `$$props`;
28122 }
28123 if (variable.subscribable && declarator.init) {
28124 const insert = get_insert(variable);
28125 parent[key].splice(index + 1, 0, ...insert);
28126 }
28127 });
28128 }
28129 }
28130 },
28131 leave(node, parent, _key, index) {
28132 if (map.has(node)) {
28133 scope = scope.parent;
28134 }
28135 if (node.type === 'ExportNamedDeclaration' && node.declaration) {
28136 parent.body[index] = node.declaration;
28137 }
28138 }
28139 });
28140 }
28141 hoist_instance_declarations() {
28142 // we can safely hoist variable declarations that are
28143 // initialised to literals, and functions that don't
28144 // reference instance variables other than other
28145 // hoistable functions. TODO others?
28146 const { hoistable_nodes, var_lookup, injected_reactive_declaration_vars, imports } = this;
28147 const top_level_function_declarations = new Map();
28148 const { body } = this.ast.instance.content;
28149 for (let i = 0; i < body.length; i += 1) {
28150 const node = body[i];
28151 if (node.type === 'VariableDeclaration') {
28152 const all_hoistable = node.declarations.every(d => {
28153 if (!d.init)
28154 return false;
28155 if (d.init.type !== 'Literal')
28156 return false;
28157 // everything except const values can be changed by e.g. svelte devtools
28158 // which means we can't hoist it
28159 if (node.kind !== 'const' && this.compile_options.dev)
28160 return false;
28161 const { name } = d.id;
28162 const v = this.var_lookup.get(name);
28163 if (v.reassigned)
28164 return false;
28165 if (v.export_name)
28166 return false;
28167 if (this.var_lookup.get(name).reassigned)
28168 return false;
28169 if (this.vars.find(variable => variable.name === name && variable.module)) {
28170 return false;
28171 }
28172 return true;
28173 });
28174 if (all_hoistable) {
28175 node.declarations.forEach(d => {
28176 const variable = this.var_lookup.get(d.id.name);
28177 variable.hoistable = true;
28178 });
28179 hoistable_nodes.add(node);
28180 body.splice(i--, 1);
28181 this.fully_hoisted.push(node);
28182 }
28183 }
28184 if (node.type === 'ExportNamedDeclaration' &&
28185 node.declaration &&
28186 node.declaration.type === 'FunctionDeclaration') {
28187 top_level_function_declarations.set(node.declaration.id.name, node);
28188 }
28189 if (node.type === 'FunctionDeclaration') {
28190 top_level_function_declarations.set(node.id.name, node);
28191 }
28192 }
28193 const checked = new Set();
28194 const walking = new Set();
28195 const is_hoistable = fn_declaration => {
28196 if (fn_declaration.type === 'ExportNamedDeclaration') {
28197 fn_declaration = fn_declaration.declaration;
28198 }
28199 const instance_scope = this.instance_scope;
28200 let scope = this.instance_scope;
28201 const map = this.instance_scope_map;
28202 let hoistable = true;
28203 // handle cycles
28204 walking.add(fn_declaration);
28205 walk(fn_declaration, {
28206 enter(node, parent) {
28207 if (!hoistable)
28208 return this.skip();
28209 if (map.has(node)) {
28210 scope = map.get(node);
28211 }
28212 if (isReference(node, parent)) {
28213 const { name } = flatten_reference(node);
28214 const owner = scope.find_owner(name);
28215 if (injected_reactive_declaration_vars.has(name)) {
28216 hoistable = false;
28217 }
28218 else if (name[0] === '$' && !owner) {
28219 hoistable = false;
28220 }
28221 else if (owner === instance_scope) {
28222 const variable = var_lookup.get(name);
28223 if (variable.reassigned || variable.mutated)
28224 hoistable = false;
28225 if (name === fn_declaration.id.name)
28226 return;
28227 if (variable.hoistable)
28228 return;
28229 if (top_level_function_declarations.has(name)) {
28230 const other_declaration = top_level_function_declarations.get(name);
28231 if (walking.has(other_declaration)) {
28232 hoistable = false;
28233 }
28234 else if (other_declaration.type === 'ExportNamedDeclaration' &&
28235 walking.has(other_declaration.declaration)) {
28236 hoistable = false;
28237 }
28238 else if (!is_hoistable(other_declaration)) {
28239 hoistable = false;
28240 }
28241 }
28242 else {
28243 hoistable = false;
28244 }
28245 }
28246 this.skip();
28247 }
28248 },
28249 leave(node) {
28250 if (map.has(node)) {
28251 scope = scope.parent;
28252 }
28253 }
28254 });
28255 checked.add(fn_declaration);
28256 walking.delete(fn_declaration);
28257 return hoistable;
28258 };
28259 for (const [name, node] of top_level_function_declarations) {
28260 if (is_hoistable(node)) {
28261 const variable = this.var_lookup.get(name);
28262 variable.hoistable = true;
28263 hoistable_nodes.add(node);
28264 const i = body.indexOf(node);
28265 body.splice(i, 1);
28266 this.fully_hoisted.push(node);
28267 }
28268 }
28269 for (const { specifiers } of imports) {
28270 for (const specifier of specifiers) {
28271 const variable = var_lookup.get(specifier.local.name);
28272 if (!variable.mutated || variable.subscribable) {
28273 variable.hoistable = true;
28274 }
28275 }
28276 }
28277 }
28278 extract_reactive_declarations() {
28279 const component = this;
28280 const unsorted_reactive_declarations = [];
28281 this.ast.instance.content.body.forEach(node => {
28282 if (node.type === 'LabeledStatement' && node.label.name === '$') {
28283 this.reactive_declaration_nodes.add(node);
28284 const assignees = new Set();
28285 const assignee_nodes = new Set();
28286 const dependencies = new Set();
28287 let scope = this.instance_scope;
28288 const map = this.instance_scope_map;
28289 walk(node.body, {
28290 enter(node, parent) {
28291 if (map.has(node)) {
28292 scope = map.get(node);
28293 }
28294 if (node.type === 'AssignmentExpression') {
28295 const left = get_object(node.left);
28296 extract_identifiers(left).forEach(node => {
28297 assignee_nodes.add(node);
28298 assignees.add(node.name);
28299 });
28300 if (node.operator !== '=') {
28301 dependencies.add(left.name);
28302 }
28303 }
28304 else if (node.type === 'UpdateExpression') {
28305 const identifier = get_object(node.argument);
28306 assignees.add(identifier.name);
28307 }
28308 else if (isReference(node, parent)) {
28309 const identifier = get_object(node);
28310 if (!assignee_nodes.has(identifier)) {
28311 const { name } = identifier;
28312 const owner = scope.find_owner(name);
28313 const variable = component.var_lookup.get(name);
28314 if (variable)
28315 variable.is_reactive_dependency = true;
28316 const is_writable_or_mutated = variable && (variable.writable || variable.mutated);
28317 if ((!owner || owner === component.instance_scope) &&
28318 (name[0] === '$' || is_writable_or_mutated)) {
28319 dependencies.add(name);
28320 }
28321 }
28322 this.skip();
28323 }
28324 },
28325 leave(node) {
28326 if (map.has(node)) {
28327 scope = scope.parent;
28328 }
28329 }
28330 });
28331 const { expression } = node.body;
28332 const declaration = expression && expression.left;
28333 unsorted_reactive_declarations.push({
28334 assignees,
28335 dependencies,
28336 node,
28337 declaration
28338 });
28339 }
28340 });
28341 const lookup = new Map();
28342 unsorted_reactive_declarations.forEach(declaration => {
28343 declaration.assignees.forEach(name => {
28344 if (!lookup.has(name)) {
28345 lookup.set(name, []);
28346 }
28347 // TODO warn or error if a name is assigned to in
28348 // multiple reactive declarations?
28349 lookup.get(name).push(declaration);
28350 });
28351 });
28352 const cycle = check_graph_for_cycles(unsorted_reactive_declarations.reduce((acc, declaration) => {
28353 declaration.assignees.forEach(v => {
28354 declaration.dependencies.forEach(w => {
28355 if (!declaration.assignees.has(w)) {
28356 acc.push([v, w]);
28357 }
28358 });
28359 });
28360 return acc;
28361 }, []));
28362 if (cycle && cycle.length) {
28363 const declarationList = lookup.get(cycle[0]);
28364 const declaration = declarationList[0];
28365 this.error(declaration.node, {
28366 code: 'cyclical-reactive-declaration',
28367 message: `Cyclical dependency detected: ${cycle.join(' → ')}`
28368 });
28369 }
28370 const add_declaration = declaration => {
28371 if (this.reactive_declarations.includes(declaration))
28372 return;
28373 declaration.dependencies.forEach(name => {
28374 if (declaration.assignees.has(name))
28375 return;
28376 const earlier_declarations = lookup.get(name);
28377 if (earlier_declarations) {
28378 earlier_declarations.forEach(add_declaration);
28379 }
28380 });
28381 this.reactive_declarations.push(declaration);
28382 };
28383 unsorted_reactive_declarations.forEach(add_declaration);
28384 }
28385 warn_if_undefined(name, node, template_scope) {
28386 if (name[0] === '$') {
28387 if (name === '$' || name[1] === '$' && !is_reserved_keyword(name)) {
28388 this.error(node, {
28389 code: 'illegal-global',
28390 message: `${name} is an illegal variable name`
28391 });
28392 }
28393 this.has_reactive_assignments = true; // TODO does this belong here?
28394 if (is_reserved_keyword(name))
28395 return;
28396 name = name.slice(1);
28397 }
28398 if (this.var_lookup.has(name) && !this.var_lookup.get(name).global)
28399 return;
28400 if (template_scope && template_scope.names.has(name))
28401 return;
28402 if (globals.has(name) && node.type !== 'InlineComponent')
28403 return;
28404 let message = `'${name}' is not defined`;
28405 if (!this.ast.instance) {
28406 message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;
28407 }
28408 this.warn(node, {
28409 code: 'missing-declaration',
28410 message
28411 });
28412 }
28413 push_ignores(ignores) {
28414 this.ignores = new Set(this.ignores || []);
28415 add_to_set(this.ignores, ignores);
28416 this.ignore_stack.push(this.ignores);
28417 }
28418 pop_ignores() {
28419 this.ignore_stack.pop();
28420 this.ignores = this.ignore_stack[this.ignore_stack.length - 1];
28421 }
28422}
28423function process_component_options(component, nodes) {
28424 const component_options = {
28425 immutable: component.compile_options.immutable || false,
28426 accessors: 'accessors' in component.compile_options
28427 ? component.compile_options.accessors
28428 : !!component.compile_options.customElement,
28429 preserveWhitespace: !!component.compile_options.preserveWhitespace
28430 };
28431 const node = nodes.find(node => node.name === 'svelte:options');
28432 function get_value(attribute, code, message) {
28433 const { value } = attribute;
28434 const chunk = value[0];
28435 if (!chunk)
28436 return true;
28437 if (value.length > 1) {
28438 component.error(attribute, { code, message });
28439 }
28440 if (chunk.type === 'Text')
28441 return chunk.data;
28442 if (chunk.expression.type !== 'Literal') {
28443 component.error(attribute, { code, message });
28444 }
28445 return chunk.expression.value;
28446 }
28447 if (node) {
28448 node.attributes.forEach(attribute => {
28449 if (attribute.type === 'Attribute') {
28450 const { name } = attribute;
28451 switch (name) {
28452 case 'tag': {
28453 const code = 'invalid-tag-attribute';
28454 const message = "'tag' must be a string literal";
28455 const tag = get_value(attribute, code, message);
28456 if (typeof tag !== 'string' && tag !== null) {
28457 component.error(attribute, { code, message });
28458 }
28459 if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
28460 component.error(attribute, {
28461 code: 'invalid-tag-property',
28462 message: "tag name must be two or more words joined by the '-' character"
28463 });
28464 }
28465 if (tag && !component.compile_options.customElement) {
28466 component.warn(attribute, {
28467 code: 'missing-custom-element-compile-options',
28468 message: "The 'tag' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?"
28469 });
28470 }
28471 component_options.tag = tag;
28472 break;
28473 }
28474 case 'namespace': {
28475 const code = 'invalid-namespace-attribute';
28476 const message = "The 'namespace' attribute must be a string literal representing a valid namespace";
28477 const ns = get_value(attribute, code, message);
28478 if (typeof ns !== 'string') {
28479 component.error(attribute, { code, message });
28480 }
28481 if (valid_namespaces.indexOf(ns) === -1) {
28482 const match = fuzzymatch(ns, valid_namespaces);
28483 if (match) {
28484 component.error(attribute, {
28485 code: 'invalid-namespace-property',
28486 message: `Invalid namespace '${ns}' (did you mean '${match}'?)`
28487 });
28488 }
28489 else {
28490 component.error(attribute, {
28491 code: 'invalid-namespace-property',
28492 message: `Invalid namespace '${ns}'`
28493 });
28494 }
28495 }
28496 component_options.namespace = ns;
28497 break;
28498 }
28499 case 'accessors':
28500 case 'immutable':
28501 case 'preserveWhitespace': {
28502 const code = `invalid-${name}-value`;
28503 const message = `${name} attribute must be true or false`;
28504 const value = get_value(attribute, code, message);
28505 if (typeof value !== 'boolean') {
28506 component.error(attribute, { code, message });
28507 }
28508 component_options[name] = value;
28509 break;
28510 }
28511 default:
28512 component.error(attribute, {
28513 code: 'invalid-options-attribute',
28514 message: '<svelte:options> unknown attribute'
28515 });
28516 }
28517 }
28518 else {
28519 component.error(attribute, {
28520 code: 'invalid-options-attribute',
28521 message: "<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes"
28522 });
28523 }
28524 });
28525 }
28526 return component_options;
28527}
28528function get_relative_path(from, to) {
28529 const from_parts = from.split(/[/\\]/);
28530 const to_parts = to.split(/[/\\]/);
28531 from_parts.pop(); // get dirname
28532 while (from_parts[0] === to_parts[0]) {
28533 from_parts.shift();
28534 to_parts.shift();
28535 }
28536 if (from_parts.length) {
28537 let i = from_parts.length;
28538 while (i--)
28539 from_parts[i] = '..';
28540 }
28541 return from_parts.concat(to_parts).join('/');
28542}
28543
28544function get_name_from_filename(filename) {
28545 if (!filename)
28546 return null;
28547 const parts = filename.split(/[/\\]/).map(encodeURI);
28548 if (parts.length > 1) {
28549 const index_match = parts[parts.length - 1].match(/^index(\.\w+)/);
28550 if (index_match) {
28551 parts.pop();
28552 parts[parts.length - 1] += index_match[1];
28553 }
28554 }
28555 const base = parts.pop()
28556 .replace(/%/g, 'u')
28557 .replace(/\.[^.]+$/, '')
28558 .replace(/[^a-zA-Z_$0-9]+/g, '_')
28559 .replace(/^_/, '')
28560 .replace(/_$/, '')
28561 .replace(/^(\d)/, '_$1');
28562 if (!base) {
28563 throw new Error(`Could not derive component name from file ${filename}`);
28564 }
28565 return base[0].toUpperCase() + base.slice(1);
28566}
28567
28568const valid_options = [
28569 'format',
28570 'name',
28571 'filename',
28572 'sourcemap',
28573 'generate',
28574 'outputFilename',
28575 'cssOutputFilename',
28576 'sveltePath',
28577 'dev',
28578 'accessors',
28579 'immutable',
28580 'hydratable',
28581 'legacy',
28582 'customElement',
28583 'tag',
28584 'css',
28585 'loopGuardTimeout',
28586 'preserveComments',
28587 'preserveWhitespace'
28588];
28589function validate_options(options, warnings) {
28590 const { name, filename, loopGuardTimeout, dev } = options;
28591 Object.keys(options).forEach(key => {
28592 if (!valid_options.includes(key)) {
28593 const match = fuzzymatch(key, valid_options);
28594 let message = `Unrecognized option '${key}'`;
28595 if (match)
28596 message += ` (did you mean '${match}'?)`;
28597 throw new Error(message);
28598 }
28599 });
28600 if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) {
28601 throw new Error(`options.name must be a valid identifier (got '${name}')`);
28602 }
28603 if (name && /^[a-z]/.test(name)) {
28604 const message = 'options.name should be capitalised';
28605 warnings.push({
28606 code: 'options-lowercase-name',
28607 message,
28608 filename,
28609 toString: () => message
28610 });
28611 }
28612 if (loopGuardTimeout && !dev) {
28613 const message = 'options.loopGuardTimeout is for options.dev = true only';
28614 warnings.push({
28615 code: 'options-loop-guard-timeout',
28616 message,
28617 filename,
28618 toString: () => message
28619 });
28620 }
28621}
28622function compile(source, options = {}) {
28623 options = Object.assign({ generate: 'dom', dev: false }, options);
28624 const stats = new Stats();
28625 const warnings = [];
28626 validate_options(options, warnings);
28627 stats.start('parse');
28628 const ast = parse$3(source, options);
28629 stats.stop('parse');
28630 stats.start('create component');
28631 const component = new Component(ast, source, options.name || get_name_from_filename(options.filename) || 'Component', options, stats, warnings);
28632 stats.stop('create component');
28633 const result = options.generate === false
28634 ? null
28635 : options.generate === 'ssr'
28636 ? ssr(component, options)
28637 : dom(component, options);
28638 return component.generate(result);
28639}
28640
28641function parse_attributes(str) {
28642 const attrs = {};
28643 str.split(/\s+/).filter(Boolean).forEach(attr => {
28644 const p = attr.indexOf('=');
28645 if (p === -1) {
28646 attrs[attr] = true;
28647 }
28648 else {
28649 attrs[attr.slice(0, p)] = '\'"'.includes(attr[p + 1]) ?
28650 attr.slice(p + 2, -1) :
28651 attr.slice(p + 1);
28652 }
28653 });
28654 return attrs;
28655}
28656function get_file_basename(filename) {
28657 return filename.split(/[/\\]/).pop();
28658}
28659async function replace_async(file_basename, source, get_location, re, func) {
28660 const replacements = [];
28661 source.replace(re, (...args) => {
28662 replacements.push(func(...args).then(res => ({
28663 offset: args[args.length - 2],
28664 length: args[0].length,
28665 replacement: res
28666 })));
28667 return '';
28668 });
28669 const out = new StringWithSourcemap();
28670 let last_end = 0;
28671 for (const { offset, length, replacement } of await Promise.all(replacements)) {
28672 // content = unchanged source characters before the replaced segment
28673 const content = StringWithSourcemap.from_source(file_basename, source.slice(last_end, offset), get_location(last_end));
28674 out.concat(content).concat(replacement);
28675 last_end = offset + length;
28676 }
28677 // final_content = unchanged source characters after last replaced segment
28678 const final_content = StringWithSourcemap.from_source(file_basename, source.slice(last_end), get_location(last_end));
28679 return out.concat(final_content);
28680}
28681/**
28682 * Import decoded sourcemap from mozilla/source-map/SourceMapGenerator
28683 * Forked from source-map/lib/source-map-generator.js
28684 * from methods _serializeMappings and toJSON.
28685 * We cannot use source-map.d.ts types, because we access hidden properties.
28686 */
28687function decoded_sourcemap_from_generator(generator) {
28688 let previous_generated_line = 1;
28689 const converted_mappings = [[]];
28690 let result_line;
28691 let result_segment;
28692 let mapping;
28693 const source_idx = generator._sources.toArray()
28694 .reduce((acc, val, idx) => (acc[val] = idx, acc), {});
28695 const name_idx = generator._names.toArray()
28696 .reduce((acc, val, idx) => (acc[val] = idx, acc), {});
28697 const mappings = generator._mappings.toArray();
28698 result_line = converted_mappings[0];
28699 for (let i = 0, len = mappings.length; i < len; i++) {
28700 mapping = mappings[i];
28701 if (mapping.generatedLine > previous_generated_line) {
28702 while (mapping.generatedLine > previous_generated_line) {
28703 converted_mappings.push([]);
28704 previous_generated_line++;
28705 }
28706 result_line = converted_mappings[mapping.generatedLine - 1]; // line is one-based
28707 }
28708 else if (i > 0) {
28709 const previous_mapping = mappings[i - 1];
28710 if (
28711 // sorted by selectivity
28712 mapping.generatedColumn === previous_mapping.generatedColumn &&
28713 mapping.originalColumn === previous_mapping.originalColumn &&
28714 mapping.name === previous_mapping.name &&
28715 mapping.generatedLine === previous_mapping.generatedLine &&
28716 mapping.originalLine === previous_mapping.originalLine &&
28717 mapping.source === previous_mapping.source) {
28718 continue;
28719 }
28720 }
28721 result_line.push([mapping.generatedColumn]);
28722 result_segment = result_line[result_line.length - 1];
28723 if (mapping.source != null) {
28724 result_segment.push(...[
28725 source_idx[mapping.source],
28726 mapping.originalLine - 1,
28727 mapping.originalColumn
28728 ]);
28729 if (mapping.name != null) {
28730 result_segment.push(name_idx[mapping.name]);
28731 }
28732 }
28733 }
28734 const map = {
28735 version: generator._version,
28736 sources: generator._sources.toArray(),
28737 names: generator._names.toArray(),
28738 mappings: converted_mappings
28739 };
28740 if (generator._file != null) {
28741 map.file = generator._file;
28742 }
28743 // not needed: map.sourcesContent and map.sourceRoot
28744 return map;
28745}
28746/**
28747 * Convert a preprocessor output and its leading prefix and trailing suffix into StringWithSourceMap
28748 */
28749function get_replacement(file_basename, offset, get_location, original, processed, prefix, suffix) {
28750 // Convert the unchanged prefix and suffix to StringWithSourcemap
28751 const prefix_with_map = StringWithSourcemap.from_source(file_basename, prefix, get_location(offset));
28752 const suffix_with_map = StringWithSourcemap.from_source(file_basename, suffix, get_location(offset + prefix.length + original.length));
28753 // Convert the preprocessed code and its sourcemap to a StringWithSourcemap
28754 let decoded_map;
28755 if (processed.map) {
28756 decoded_map = typeof processed.map === 'string' ? JSON.parse(processed.map) : processed.map;
28757 if (typeof (decoded_map.mappings) === 'string') {
28758 decoded_map.mappings = decode(decoded_map.mappings);
28759 }
28760 if (decoded_map._mappings && decoded_map.constructor.name === 'SourceMapGenerator') {
28761 // import decoded sourcemap from mozilla/source-map/SourceMapGenerator
28762 decoded_map = decoded_sourcemap_from_generator(decoded_map);
28763 }
28764 // offset only segments pointing at original component source
28765 const source_index = decoded_map.sources.indexOf(file_basename);
28766 if (source_index !== -1) {
28767 sourcemap_add_offset(decoded_map, get_location(offset + prefix.length), source_index);
28768 }
28769 }
28770 const processed_with_map = StringWithSourcemap.from_processed(processed.code, decoded_map);
28771 // Surround the processed code with the prefix and suffix, retaining valid sourcemappings
28772 return prefix_with_map.concat(processed_with_map).concat(suffix_with_map);
28773}
28774async function preprocess(source, preprocessor, options) {
28775 // @ts-ignore todo: doublecheck
28776 const filename = (options && options.filename) || preprocessor.filename; // legacy
28777 const dependencies = [];
28778 // preprocess source must be relative to itself or equal null
28779 const file_basename = filename == null ? null : get_file_basename(filename);
28780 const preprocessors = preprocessor
28781 ? Array.isArray(preprocessor) ? preprocessor : [preprocessor]
28782 : [];
28783 const markup = preprocessors.map(p => p.markup).filter(Boolean);
28784 const script = preprocessors.map(p => p.script).filter(Boolean);
28785 const style = preprocessors.map(p => p.style).filter(Boolean);
28786 // sourcemap_list is sorted in reverse order from last map (index 0) to first map (index -1)
28787 // so we use sourcemap_list.unshift() to add new maps
28788 // https://github.com/ampproject/remapping#multiple-transformations-of-a-file
28789 const sourcemap_list = [];
28790 // TODO keep track: what preprocessor generated what sourcemap? to make debugging easier = detect low-resolution sourcemaps in fn combine_mappings
28791 for (const fn of markup) {
28792 // run markup preprocessor
28793 const processed = await fn({
28794 content: source,
28795 filename
28796 });
28797 if (!processed)
28798 continue;
28799 if (processed.dependencies)
28800 dependencies.push(...processed.dependencies);
28801 source = processed.code;
28802 if (processed.map) {
28803 sourcemap_list.unshift(typeof (processed.map) === 'string'
28804 ? JSON.parse(processed.map)
28805 : processed.map);
28806 }
28807 }
28808 async function preprocess_tag_content(tag_name, preprocessor) {
28809 const get_location = getLocator(source);
28810 const tag_regex = tag_name === 'style'
28811 ? /<!--[^]*?-->|<style(\s[^]*?)?(?:>([^]*?)<\/style>|\/>)/gi
28812 : /<!--[^]*?-->|<script(\s[^]*?)?(?:>([^]*?)<\/script>|\/>)/gi;
28813 const res = await replace_async(file_basename, source, get_location, tag_regex, async (match, attributes = '', content = '', offset) => {
28814 const no_change = () => StringWithSourcemap.from_source(file_basename, match, get_location(offset));
28815 if (!attributes && !content) {
28816 return no_change();
28817 }
28818 attributes = attributes || '';
28819 content = content || '';
28820 // run script preprocessor
28821 const processed = await preprocessor({
28822 content,
28823 attributes: parse_attributes(attributes),
28824 filename
28825 });
28826 if (processed && processed.dependencies) {
28827 dependencies.push(...processed.dependencies);
28828 }
28829 if (!processed || !processed.map && processed.code === content) {
28830 return no_change();
28831 }
28832 return get_replacement(file_basename, offset, get_location, content, processed, `<${tag_name}${attributes}>`, `</${tag_name}>`);
28833 });
28834 source = res.string;
28835 sourcemap_list.unshift(res.map);
28836 }
28837 for (const fn of script) {
28838 await preprocess_tag_content('script', fn);
28839 }
28840 for (const fn of style) {
28841 await preprocess_tag_content('style', fn);
28842 }
28843 // Combine all the source maps for each preprocessor function into one
28844 const map = combine_sourcemaps(file_basename, sourcemap_list);
28845 return {
28846 // TODO return separated output, in future version where svelte.compile supports it:
28847 // style: { code: styleCode, map: styleMap },
28848 // script { code: scriptCode, map: scriptMap },
28849 // markup { code: markupCode, map: markupMap },
28850 code: source,
28851 dependencies: [...new Set(dependencies)],
28852 map: map,
28853 toString() {
28854 return source;
28855 }
28856 };
28857}
28858
28859const VERSION = '3.31.2';
28860
28861export { VERSION, compile, parse$3 as parse, preprocess, walk };
28862//# sourceMappingURL=compiler.mjs.map