UNPKG

919 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3 typeof define === 'function' && define.amd ? define(['exports'], factory) :
4 (global = global || self, factory(global.svelte = {}));
5}(this, (function (exports) { 'use strict';
6
7 function assign(tar, src) {
8 // @ts-ignore
9 for (const k in src)
10 tar[k] = src[k];
11 return tar;
12 }
13
14 const now = (typeof process !== 'undefined' && process.hrtime)
15 ? () => {
16 const t = process.hrtime();
17 return t[0] * 1e3 + t[1] / 1e6;
18 }
19 : () => self.performance.now();
20 function collapse_timings(timings) {
21 const result = {};
22 timings.forEach(timing => {
23 result[timing.label] = Object.assign({
24 total: timing.end - timing.start
25 }, timing.children && collapse_timings(timing.children));
26 });
27 return result;
28 }
29 class Stats {
30 constructor() {
31 this.start_time = now();
32 this.stack = [];
33 this.current_children = this.timings = [];
34 }
35 start(label) {
36 const timing = {
37 label,
38 start: now(),
39 end: null,
40 children: []
41 };
42 this.current_children.push(timing);
43 this.stack.push(timing);
44 this.current_timing = timing;
45 this.current_children = timing.children;
46 }
47 stop(label) {
48 if (label !== this.current_timing.label) {
49 throw new Error(`Mismatched timing labels (expected ${this.current_timing.label}, got ${label})`);
50 }
51 this.current_timing.end = now();
52 this.stack.pop();
53 this.current_timing = this.stack[this.stack.length - 1];
54 this.current_children = this.current_timing ? this.current_timing.children : this.timings;
55 }
56 render() {
57 const timings = Object.assign({
58 total: now() - this.start_time
59 }, collapse_timings(this.timings));
60 return {
61 timings
62 };
63 }
64 }
65
66 // Reserved word lists for various dialects of the language
67
68 var reservedWords = {
69 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",
70 5: "class enum extends super const export import",
71 6: "enum",
72 strict: "implements interface let package private protected public static yield",
73 strictBind: "eval arguments"
74 };
75
76 // And the keywords
77
78 var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
79
80 var keywords = {
81 5: ecma5AndLessKeywords,
82 "5module": ecma5AndLessKeywords + " export import",
83 6: ecma5AndLessKeywords + " const class extends export import super"
84 };
85
86 var keywordRelationalOperator = /^in(stanceof)?$/;
87
88 // ## Character categories
89
90 // Big ugly regular expressions that match characters in the
91 // whitespace, identifier, and identifier-start categories. These
92 // are only applied when a character is found to actually have a
93 // code point above 128.
94 // Generated by `bin/generate-identifier-regex.js`.
95 var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\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";
96 var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\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";
97
98 var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
99 var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
100
101 nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
102
103 // These are a run-length and offset encoded representation of the
104 // >0xffff code points that are a valid part of identifiers. The
105 // offset starts at 0x10000, and each pair of numbers represents an
106 // offset to the next range, and then a size of the range. They were
107 // generated by bin/generate-identifier-regex.js
108
109 // eslint-disable-next-line comma-spacing
110 var 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];
111
112 // eslint-disable-next-line comma-spacing
113 var 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];
114
115 // This has a complexity linear to the value of the code. The
116 // assumption is that looking up astral identifier characters is
117 // rare.
118 function isInAstralSet(code, set) {
119 var pos = 0x10000;
120 for (var i = 0; i < set.length; i += 2) {
121 pos += set[i];
122 if (pos > code) { return false }
123 pos += set[i + 1];
124 if (pos >= code) { return true }
125 }
126 }
127
128 // Test whether a given character code starts an identifier.
129
130 function isIdentifierStart(code, astral) {
131 if (code < 65) { return code === 36 }
132 if (code < 91) { return true }
133 if (code < 97) { return code === 95 }
134 if (code < 123) { return true }
135 if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) }
136 if (astral === false) { return false }
137 return isInAstralSet(code, astralIdentifierStartCodes)
138 }
139
140 // Test whether a given character is part of an identifier.
141
142 function isIdentifierChar(code, astral) {
143 if (code < 48) { return code === 36 }
144 if (code < 58) { return true }
145 if (code < 65) { return false }
146 if (code < 91) { return true }
147 if (code < 97) { return code === 95 }
148 if (code < 123) { return true }
149 if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) }
150 if (astral === false) { return false }
151 return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
152 }
153
154 // ## Token types
155
156 // The assignment of fine-grained, information-carrying type objects
157 // allows the tokenizer to store the information it has about a
158 // token in a way that is very cheap for the parser to look up.
159
160 // All token type variables start with an underscore, to make them
161 // easy to recognize.
162
163 // The `beforeExpr` property is used to disambiguate between regular
164 // expressions and divisions. It is set on all token types that can
165 // be followed by an expression (thus, a slash after them would be a
166 // regular expression).
167 //
168 // The `startsExpr` property is used to check if the token ends a
169 // `yield` expression. It is set on all token types that either can
170 // directly start an expression (like a quotation mark) or can
171 // continue an expression (like the body of a string).
172 //
173 // `isLoop` marks a keyword as starting a loop, which is important
174 // to know when parsing a label, in order to allow or disallow
175 // continue jumps to that label.
176
177 var TokenType = function TokenType(label, conf) {
178 if ( conf === void 0 ) conf = {};
179
180 this.label = label;
181 this.keyword = conf.keyword;
182 this.beforeExpr = !!conf.beforeExpr;
183 this.startsExpr = !!conf.startsExpr;
184 this.isLoop = !!conf.isLoop;
185 this.isAssign = !!conf.isAssign;
186 this.prefix = !!conf.prefix;
187 this.postfix = !!conf.postfix;
188 this.binop = conf.binop || null;
189 this.updateContext = null;
190 };
191
192 function binop(name, prec) {
193 return new TokenType(name, {beforeExpr: true, binop: prec})
194 }
195 var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true};
196
197 // Map keyword names to token types.
198
199 var keywords$1 = {};
200
201 // Succinct definitions of keyword token types
202 function kw(name, options) {
203 if ( options === void 0 ) options = {};
204
205 options.keyword = name;
206 return keywords$1[name] = new TokenType(name, options)
207 }
208
209 var types = {
210 num: new TokenType("num", startsExpr),
211 regexp: new TokenType("regexp", startsExpr),
212 string: new TokenType("string", startsExpr),
213 name: new TokenType("name", startsExpr),
214 eof: new TokenType("eof"),
215
216 // Punctuation token types.
217 bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
218 bracketR: new TokenType("]"),
219 braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
220 braceR: new TokenType("}"),
221 parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
222 parenR: new TokenType(")"),
223 comma: new TokenType(",", beforeExpr),
224 semi: new TokenType(";", beforeExpr),
225 colon: new TokenType(":", beforeExpr),
226 dot: new TokenType("."),
227 question: new TokenType("?", beforeExpr),
228 questionDot: new TokenType("?."),
229 arrow: new TokenType("=>", beforeExpr),
230 template: new TokenType("template"),
231 invalidTemplate: new TokenType("invalidTemplate"),
232 ellipsis: new TokenType("...", beforeExpr),
233 backQuote: new TokenType("`", startsExpr),
234 dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
235
236 // Operators. These carry several kinds of properties to help the
237 // parser use them properly (the presence of these properties is
238 // what categorizes them as operators).
239 //
240 // `binop`, when present, specifies that this operator is a binary
241 // operator, and will refer to its precedence.
242 //
243 // `prefix` and `postfix` mark the operator as a prefix or postfix
244 // unary operator.
245 //
246 // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
247 // binary operators with a very low precedence, that should result
248 // in AssignmentExpression nodes.
249
250 eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
251 assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
252 incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
253 prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
254 logicalOR: binop("||", 1),
255 logicalAND: binop("&&", 2),
256 bitwiseOR: binop("|", 3),
257 bitwiseXOR: binop("^", 4),
258 bitwiseAND: binop("&", 5),
259 equality: binop("==/!=/===/!==", 6),
260 relational: binop("</>/<=/>=", 7),
261 bitShift: binop("<</>>/>>>", 8),
262 plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
263 modulo: binop("%", 10),
264 star: binop("*", 10),
265 slash: binop("/", 10),
266 starstar: new TokenType("**", {beforeExpr: true}),
267 coalesce: binop("??", 1),
268
269 // Keyword token types.
270 _break: kw("break"),
271 _case: kw("case", beforeExpr),
272 _catch: kw("catch"),
273 _continue: kw("continue"),
274 _debugger: kw("debugger"),
275 _default: kw("default", beforeExpr),
276 _do: kw("do", {isLoop: true, beforeExpr: true}),
277 _else: kw("else", beforeExpr),
278 _finally: kw("finally"),
279 _for: kw("for", {isLoop: true}),
280 _function: kw("function", startsExpr),
281 _if: kw("if"),
282 _return: kw("return", beforeExpr),
283 _switch: kw("switch"),
284 _throw: kw("throw", beforeExpr),
285 _try: kw("try"),
286 _var: kw("var"),
287 _const: kw("const"),
288 _while: kw("while", {isLoop: true}),
289 _with: kw("with"),
290 _new: kw("new", {beforeExpr: true, startsExpr: true}),
291 _this: kw("this", startsExpr),
292 _super: kw("super", startsExpr),
293 _class: kw("class", startsExpr),
294 _extends: kw("extends", beforeExpr),
295 _export: kw("export"),
296 _import: kw("import", startsExpr),
297 _null: kw("null", startsExpr),
298 _true: kw("true", startsExpr),
299 _false: kw("false", startsExpr),
300 _in: kw("in", {beforeExpr: true, binop: 7}),
301 _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
302 _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
303 _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
304 _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
305 };
306
307 // Matches a whole line break (where CRLF is considered a single
308 // line break). Used to count lines.
309
310 var lineBreak = /\r\n?|\n|\u2028|\u2029/;
311 var lineBreakG = new RegExp(lineBreak.source, "g");
312
313 function isNewLine(code, ecma2019String) {
314 return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029))
315 }
316
317 var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
318
319 var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
320
321 var ref = Object.prototype;
322 var hasOwnProperty = ref.hasOwnProperty;
323 var toString = ref.toString;
324
325 // Checks if an object has a property.
326
327 function has(obj, propName) {
328 return hasOwnProperty.call(obj, propName)
329 }
330
331 var isArray = Array.isArray || (function (obj) { return (
332 toString.call(obj) === "[object Array]"
333 ); });
334
335 function wordsRegexp(words) {
336 return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
337 }
338
339 // These are used when `options.locations` is on, for the
340 // `startLoc` and `endLoc` properties.
341
342 var Position = function Position(line, col) {
343 this.line = line;
344 this.column = col;
345 };
346
347 Position.prototype.offset = function offset (n) {
348 return new Position(this.line, this.column + n)
349 };
350
351 var SourceLocation = function SourceLocation(p, start, end) {
352 this.start = start;
353 this.end = end;
354 if (p.sourceFile !== null) { this.source = p.sourceFile; }
355 };
356
357 // The `getLineInfo` function is mostly useful when the
358 // `locations` option is off (for performance reasons) and you
359 // want to find the line/column position for a given character
360 // offset. `input` should be the code string that the offset refers
361 // into.
362
363 function getLineInfo(input, offset) {
364 for (var line = 1, cur = 0;;) {
365 lineBreakG.lastIndex = cur;
366 var match = lineBreakG.exec(input);
367 if (match && match.index < offset) {
368 ++line;
369 cur = match.index + match[0].length;
370 } else {
371 return new Position(line, offset - cur)
372 }
373 }
374 }
375
376 // A second optional argument can be given to further configure
377 // the parser process. These options are recognized:
378
379 var defaultOptions = {
380 // `ecmaVersion` indicates the ECMAScript version to parse. Must be
381 // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10
382 // (2019). This influences support for strict mode, the set of
383 // reserved words, and support for new syntax features. The default
384 // is 10.
385 ecmaVersion: 10,
386 // `sourceType` indicates the mode the code should be parsed in.
387 // Can be either `"script"` or `"module"`. This influences global
388 // strict mode and parsing of `import` and `export` declarations.
389 sourceType: "script",
390 // `onInsertedSemicolon` can be a callback that will be called
391 // when a semicolon is automatically inserted. It will be passed
392 // the position of the comma as an offset, and if `locations` is
393 // enabled, it is given the location as a `{line, column}` object
394 // as second argument.
395 onInsertedSemicolon: null,
396 // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
397 // trailing commas.
398 onTrailingComma: null,
399 // By default, reserved words are only enforced if ecmaVersion >= 5.
400 // Set `allowReserved` to a boolean value to explicitly turn this on
401 // an off. When this option has the value "never", reserved words
402 // and keywords can also not be used as property names.
403 allowReserved: null,
404 // When enabled, a return at the top level is not considered an
405 // error.
406 allowReturnOutsideFunction: false,
407 // When enabled, import/export statements are not constrained to
408 // appearing at the top of the program.
409 allowImportExportEverywhere: false,
410 // When enabled, await identifiers are allowed to appear at the top-level scope,
411 // but they are still not allowed in non-async functions.
412 allowAwaitOutsideFunction: false,
413 // When enabled, hashbang directive in the beginning of file
414 // is allowed and treated as a line comment.
415 allowHashBang: false,
416 // When `locations` is on, `loc` properties holding objects with
417 // `start` and `end` properties in `{line, column}` form (with
418 // line being 1-based and column 0-based) will be attached to the
419 // nodes.
420 locations: false,
421 // A function can be passed as `onToken` option, which will
422 // cause Acorn to call that function with object in the same
423 // format as tokens returned from `tokenizer().getToken()`. Note
424 // that you are not allowed to call the parser from the
425 // callback—that will corrupt its internal state.
426 onToken: null,
427 // A function can be passed as `onComment` option, which will
428 // cause Acorn to call that function with `(block, text, start,
429 // end)` parameters whenever a comment is skipped. `block` is a
430 // boolean indicating whether this is a block (`/* */`) comment,
431 // `text` is the content of the comment, and `start` and `end` are
432 // character offsets that denote the start and end of the comment.
433 // When the `locations` option is on, two more parameters are
434 // passed, the full `{line, column}` locations of the start and
435 // end of the comments. Note that you are not allowed to call the
436 // parser from the callback—that will corrupt its internal state.
437 onComment: null,
438 // Nodes have their start and end characters offsets recorded in
439 // `start` and `end` properties (directly on the node, rather than
440 // the `loc` object, which holds line/column data. To also add a
441 // [semi-standardized][range] `range` property holding a `[start,
442 // end]` array with the same numbers, set the `ranges` option to
443 // `true`.
444 //
445 // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
446 ranges: false,
447 // It is possible to parse multiple files into a single AST by
448 // passing the tree produced by parsing the first file as
449 // `program` option in subsequent parses. This will add the
450 // toplevel forms of the parsed file to the `Program` (top) node
451 // of an existing parse tree.
452 program: null,
453 // When `locations` is on, you can pass this to record the source
454 // file in every node's `loc` object.
455 sourceFile: null,
456 // This value, if given, is stored in every node, whether
457 // `locations` is on or off.
458 directSourceFile: null,
459 // When enabled, parenthesized expressions are represented by
460 // (non-standard) ParenthesizedExpression nodes
461 preserveParens: false
462 };
463
464 // Interpret and default an options object
465
466 function getOptions(opts) {
467 var options = {};
468
469 for (var opt in defaultOptions)
470 { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; }
471
472 if (options.ecmaVersion >= 2015)
473 { options.ecmaVersion -= 2009; }
474
475 if (options.allowReserved == null)
476 { options.allowReserved = options.ecmaVersion < 5; }
477
478 if (isArray(options.onToken)) {
479 var tokens = options.onToken;
480 options.onToken = function (token) { return tokens.push(token); };
481 }
482 if (isArray(options.onComment))
483 { options.onComment = pushComment(options, options.onComment); }
484
485 return options
486 }
487
488 function pushComment(options, array) {
489 return function(block, text, start, end, startLoc, endLoc) {
490 var comment = {
491 type: block ? "Block" : "Line",
492 value: text,
493 start: start,
494 end: end
495 };
496 if (options.locations)
497 { comment.loc = new SourceLocation(this, startLoc, endLoc); }
498 if (options.ranges)
499 { comment.range = [start, end]; }
500 array.push(comment);
501 }
502 }
503
504 // Each scope gets a bitset that may contain these flags
505 var
506 SCOPE_TOP = 1,
507 SCOPE_FUNCTION = 2,
508 SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION,
509 SCOPE_ASYNC = 4,
510 SCOPE_GENERATOR = 8,
511 SCOPE_ARROW = 16,
512 SCOPE_SIMPLE_CATCH = 32,
513 SCOPE_SUPER = 64,
514 SCOPE_DIRECT_SUPER = 128;
515
516 function functionFlags(async, generator) {
517 return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0)
518 }
519
520 // Used in checkLVal and declareName to determine the type of a binding
521 var
522 BIND_NONE = 0, // Not a binding
523 BIND_VAR = 1, // Var-style binding
524 BIND_LEXICAL = 2, // Let- or const-style binding
525 BIND_FUNCTION = 3, // Function declaration
526 BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding
527 BIND_OUTSIDE = 5; // Special case for function names as bound inside the function
528
529 var Parser = function Parser(options, input, startPos) {
530 this.options = options = getOptions(options);
531 this.sourceFile = options.sourceFile;
532 this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]);
533 var reserved = "";
534 if (options.allowReserved !== true) {
535 for (var v = options.ecmaVersion;; v--)
536 { if (reserved = reservedWords[v]) { break } }
537 if (options.sourceType === "module") { reserved += " await"; }
538 }
539 this.reservedWords = wordsRegexp(reserved);
540 var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
541 this.reservedWordsStrict = wordsRegexp(reservedStrict);
542 this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind);
543 this.input = String(input);
544
545 // Used to signal to callers of `readWord1` whether the word
546 // contained any escape sequences. This is needed because words with
547 // escape sequences must not be interpreted as keywords.
548 this.containsEsc = false;
549
550 // Set up token state
551
552 // The current position of the tokenizer in the input.
553 if (startPos) {
554 this.pos = startPos;
555 this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
556 this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
557 } else {
558 this.pos = this.lineStart = 0;
559 this.curLine = 1;
560 }
561
562 // Properties of the current token:
563 // Its type
564 this.type = types.eof;
565 // For tokens that include more information than their type, the value
566 this.value = null;
567 // Its start and end offset
568 this.start = this.end = this.pos;
569 // And, if locations are used, the {line, column} object
570 // corresponding to those offsets
571 this.startLoc = this.endLoc = this.curPosition();
572
573 // Position information for the previous token
574 this.lastTokEndLoc = this.lastTokStartLoc = null;
575 this.lastTokStart = this.lastTokEnd = this.pos;
576
577 // The context stack is used to superficially track syntactic
578 // context to predict whether a regular expression is allowed in a
579 // given position.
580 this.context = this.initialContext();
581 this.exprAllowed = true;
582
583 // Figure out if it's a module code.
584 this.inModule = options.sourceType === "module";
585 this.strict = this.inModule || this.strictDirective(this.pos);
586
587 // Used to signify the start of a potential arrow function
588 this.potentialArrowAt = -1;
589
590 // Positions to delayed-check that yield/await does not exist in default parameters.
591 this.yieldPos = this.awaitPos = this.awaitIdentPos = 0;
592 // Labels in scope.
593 this.labels = [];
594 // Thus-far undefined exports.
595 this.undefinedExports = {};
596
597 // If enabled, skip leading hashbang line.
598 if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
599 { this.skipLineComment(2); }
600
601 // Scope tracking for duplicate variable names (see scope.js)
602 this.scopeStack = [];
603 this.enterScope(SCOPE_TOP);
604
605 // For RegExp validation
606 this.regexpState = null;
607 };
608
609 var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true } };
610
611 Parser.prototype.parse = function parse () {
612 var node = this.options.program || this.startNode();
613 this.nextToken();
614 return this.parseTopLevel(node)
615 };
616
617 prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 };
618 prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 };
619 prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 };
620 prototypeAccessors.allowSuper.get = function () { return (this.currentThisScope().flags & SCOPE_SUPER) > 0 };
621 prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 };
622 prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) };
623
624 // Switch to a getter for 7.0.0.
625 Parser.prototype.inNonArrowFunction = function inNonArrowFunction () { return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0 };
626
627 Parser.extend = function extend () {
628 var plugins = [], len = arguments.length;
629 while ( len-- ) plugins[ len ] = arguments[ len ];
630
631 var cls = this;
632 for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
633 return cls
634 };
635
636 Parser.parse = function parse (input, options) {
637 return new this(options, input).parse()
638 };
639
640 Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) {
641 var parser = new this(options, input, pos);
642 parser.nextToken();
643 return parser.parseExpression()
644 };
645
646 Parser.tokenizer = function tokenizer (input, options) {
647 return new this(options, input)
648 };
649
650 Object.defineProperties( Parser.prototype, prototypeAccessors );
651
652 var pp = Parser.prototype;
653
654 // ## Parser utilities
655
656 var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)")/;
657 pp.strictDirective = function(start) {
658 for (;;) {
659 // Try to find string literal.
660 skipWhiteSpace.lastIndex = start;
661 start += skipWhiteSpace.exec(this.input)[0].length;
662 var match = literal.exec(this.input.slice(start));
663 if (!match) { return false }
664 if ((match[1] || match[2]) === "use strict") {
665 skipWhiteSpace.lastIndex = start + match[0].length;
666 var spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length;
667 var next = this.input.charAt(end);
668 return next === ";" || next === "}" ||
669 (lineBreak.test(spaceAfter[0]) &&
670 !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "="))
671 }
672 start += match[0].length;
673
674 // Skip semicolon, if any.
675 skipWhiteSpace.lastIndex = start;
676 start += skipWhiteSpace.exec(this.input)[0].length;
677 if (this.input[start] === ";")
678 { start++; }
679 }
680 };
681
682 // Predicate that tests whether the next token is of the given
683 // type, and if yes, consumes it as a side effect.
684
685 pp.eat = function(type) {
686 if (this.type === type) {
687 this.next();
688 return true
689 } else {
690 return false
691 }
692 };
693
694 // Tests whether parsed token is a contextual keyword.
695
696 pp.isContextual = function(name) {
697 return this.type === types.name && this.value === name && !this.containsEsc
698 };
699
700 // Consumes contextual keyword if possible.
701
702 pp.eatContextual = function(name) {
703 if (!this.isContextual(name)) { return false }
704 this.next();
705 return true
706 };
707
708 // Asserts that following token is given contextual keyword.
709
710 pp.expectContextual = function(name) {
711 if (!this.eatContextual(name)) { this.unexpected(); }
712 };
713
714 // Test whether a semicolon can be inserted at the current position.
715
716 pp.canInsertSemicolon = function() {
717 return this.type === types.eof ||
718 this.type === types.braceR ||
719 lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
720 };
721
722 pp.insertSemicolon = function() {
723 if (this.canInsertSemicolon()) {
724 if (this.options.onInsertedSemicolon)
725 { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
726 return true
727 }
728 };
729
730 // Consume a semicolon, or, failing that, see if we are allowed to
731 // pretend that there is a semicolon at this position.
732
733 pp.semicolon = function() {
734 if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); }
735 };
736
737 pp.afterTrailingComma = function(tokType, notNext) {
738 if (this.type === tokType) {
739 if (this.options.onTrailingComma)
740 { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
741 if (!notNext)
742 { this.next(); }
743 return true
744 }
745 };
746
747 // Expect a token of a given type. If found, consume it, otherwise,
748 // raise an unexpected token error.
749
750 pp.expect = function(type) {
751 this.eat(type) || this.unexpected();
752 };
753
754 // Raise an unexpected token error.
755
756 pp.unexpected = function(pos) {
757 this.raise(pos != null ? pos : this.start, "Unexpected token");
758 };
759
760 function DestructuringErrors() {
761 this.shorthandAssign =
762 this.trailingComma =
763 this.parenthesizedAssign =
764 this.parenthesizedBind =
765 this.doubleProto =
766 -1;
767 }
768
769 pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {
770 if (!refDestructuringErrors) { return }
771 if (refDestructuringErrors.trailingComma > -1)
772 { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
773 var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
774 if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); }
775 };
776
777 pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
778 if (!refDestructuringErrors) { return false }
779 var shorthandAssign = refDestructuringErrors.shorthandAssign;
780 var doubleProto = refDestructuringErrors.doubleProto;
781 if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 }
782 if (shorthandAssign >= 0)
783 { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); }
784 if (doubleProto >= 0)
785 { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); }
786 };
787
788 pp.checkYieldAwaitInDefaultParams = function() {
789 if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
790 { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
791 if (this.awaitPos)
792 { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
793 };
794
795 pp.isSimpleAssignTarget = function(expr) {
796 if (expr.type === "ParenthesizedExpression")
797 { return this.isSimpleAssignTarget(expr.expression) }
798 return expr.type === "Identifier" || expr.type === "MemberExpression"
799 };
800
801 var pp$1 = Parser.prototype;
802
803 // ### Statement parsing
804
805 // Parse a program. Initializes the parser, reads any number of
806 // statements, and wraps them in a Program node. Optionally takes a
807 // `program` argument. If present, the statements will be appended
808 // to its body instead of creating a new node.
809
810 pp$1.parseTopLevel = function(node) {
811 var exports = {};
812 if (!node.body) { node.body = []; }
813 while (this.type !== types.eof) {
814 var stmt = this.parseStatement(null, true, exports);
815 node.body.push(stmt);
816 }
817 if (this.inModule)
818 { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1)
819 {
820 var name = list[i];
821
822 this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined"));
823 } }
824 this.adaptDirectivePrologue(node.body);
825 this.next();
826 node.sourceType = this.options.sourceType;
827 return this.finishNode(node, "Program")
828 };
829
830 var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};
831
832 pp$1.isLet = function(context) {
833 if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false }
834 skipWhiteSpace.lastIndex = this.pos;
835 var skip = skipWhiteSpace.exec(this.input);
836 var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
837 // For ambiguous cases, determine if a LexicalDeclaration (or only a
838 // Statement) is allowed here. If context is not empty then only a Statement
839 // is allowed. However, `let [` is an explicit negative lookahead for
840 // ExpressionStatement, so special-case it first.
841 if (nextCh === 91) { return true } // '['
842 if (context) { return false }
843
844 if (nextCh === 123) { return true } // '{'
845 if (isIdentifierStart(nextCh, true)) {
846 var pos = next + 1;
847 while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; }
848 var ident = this.input.slice(next, pos);
849 if (!keywordRelationalOperator.test(ident)) { return true }
850 }
851 return false
852 };
853
854 // check 'async [no LineTerminator here] function'
855 // - 'async /*foo*/ function' is OK.
856 // - 'async /*\n*/ function' is invalid.
857 pp$1.isAsyncFunction = function() {
858 if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
859 { return false }
860
861 skipWhiteSpace.lastIndex = this.pos;
862 var skip = skipWhiteSpace.exec(this.input);
863 var next = this.pos + skip[0].length;
864 return !lineBreak.test(this.input.slice(this.pos, next)) &&
865 this.input.slice(next, next + 8) === "function" &&
866 (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))
867 };
868
869 // Parse a single statement.
870 //
871 // If expecting a statement and finding a slash operator, parse a
872 // regular expression literal. This is to handle cases like
873 // `if (foo) /blah/.exec(foo)`, where looking at the previous token
874 // does not help.
875
876 pp$1.parseStatement = function(context, topLevel, exports) {
877 var starttype = this.type, node = this.startNode(), kind;
878
879 if (this.isLet(context)) {
880 starttype = types._var;
881 kind = "let";
882 }
883
884 // Most types of statements are recognized by the keyword they
885 // start with. Many are trivial to parse, some require a bit of
886 // complexity.
887
888 switch (starttype) {
889 case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
890 case types._debugger: return this.parseDebuggerStatement(node)
891 case types._do: return this.parseDoStatement(node)
892 case types._for: return this.parseForStatement(node)
893 case types._function:
894 // Function as sole body of either an if statement or a labeled statement
895 // works, but not when it is part of a labeled statement that is the sole
896 // body of an if statement.
897 if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); }
898 return this.parseFunctionStatement(node, false, !context)
899 case types._class:
900 if (context) { this.unexpected(); }
901 return this.parseClass(node, true)
902 case types._if: return this.parseIfStatement(node)
903 case types._return: return this.parseReturnStatement(node)
904 case types._switch: return this.parseSwitchStatement(node)
905 case types._throw: return this.parseThrowStatement(node)
906 case types._try: return this.parseTryStatement(node)
907 case types._const: case types._var:
908 kind = kind || this.value;
909 if (context && kind !== "var") { this.unexpected(); }
910 return this.parseVarStatement(node, kind)
911 case types._while: return this.parseWhileStatement(node)
912 case types._with: return this.parseWithStatement(node)
913 case types.braceL: return this.parseBlock(true, node)
914 case types.semi: return this.parseEmptyStatement(node)
915 case types._export:
916 case types._import:
917 if (this.options.ecmaVersion > 10 && starttype === types._import) {
918 skipWhiteSpace.lastIndex = this.pos;
919 var skip = skipWhiteSpace.exec(this.input);
920 var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
921 if (nextCh === 40 || nextCh === 46) // '(' or '.'
922 { return this.parseExpressionStatement(node, this.parseExpression()) }
923 }
924
925 if (!this.options.allowImportExportEverywhere) {
926 if (!topLevel)
927 { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
928 if (!this.inModule)
929 { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
930 }
931 return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports)
932
933 // If the statement does not start with a statement keyword or a
934 // brace, it's an ExpressionStatement or LabeledStatement. We
935 // simply start parsing an expression, and afterwards, if the
936 // next token is a colon and the expression was a simple
937 // Identifier node, we switch to interpreting it as a label.
938 default:
939 if (this.isAsyncFunction()) {
940 if (context) { this.unexpected(); }
941 this.next();
942 return this.parseFunctionStatement(node, true, !context)
943 }
944
945 var maybeName = this.value, expr = this.parseExpression();
946 if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon))
947 { return this.parseLabeledStatement(node, maybeName, expr, context) }
948 else { return this.parseExpressionStatement(node, expr) }
949 }
950 };
951
952 pp$1.parseBreakContinueStatement = function(node, keyword) {
953 var isBreak = keyword === "break";
954 this.next();
955 if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; }
956 else if (this.type !== types.name) { this.unexpected(); }
957 else {
958 node.label = this.parseIdent();
959 this.semicolon();
960 }
961
962 // Verify that there is an actual destination to break or
963 // continue to.
964 var i = 0;
965 for (; i < this.labels.length; ++i) {
966 var lab = this.labels[i];
967 if (node.label == null || lab.name === node.label.name) {
968 if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
969 if (node.label && isBreak) { break }
970 }
971 }
972 if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
973 return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
974 };
975
976 pp$1.parseDebuggerStatement = function(node) {
977 this.next();
978 this.semicolon();
979 return this.finishNode(node, "DebuggerStatement")
980 };
981
982 pp$1.parseDoStatement = function(node) {
983 this.next();
984 this.labels.push(loopLabel);
985 node.body = this.parseStatement("do");
986 this.labels.pop();
987 this.expect(types._while);
988 node.test = this.parseParenExpression();
989 if (this.options.ecmaVersion >= 6)
990 { this.eat(types.semi); }
991 else
992 { this.semicolon(); }
993 return this.finishNode(node, "DoWhileStatement")
994 };
995
996 // Disambiguating between a `for` and a `for`/`in` or `for`/`of`
997 // loop is non-trivial. Basically, we have to parse the init `var`
998 // statement or expression, disallowing the `in` operator (see
999 // the second parameter to `parseExpression`), and then check
1000 // whether the next token is `in` or `of`. When there is no init
1001 // part (semicolon immediately after the opening parenthesis), it
1002 // is a regular `for` loop.
1003
1004 pp$1.parseForStatement = function(node) {
1005 this.next();
1006 var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1;
1007 this.labels.push(loopLabel);
1008 this.enterScope(0);
1009 this.expect(types.parenL);
1010 if (this.type === types.semi) {
1011 if (awaitAt > -1) { this.unexpected(awaitAt); }
1012 return this.parseFor(node, null)
1013 }
1014 var isLet = this.isLet();
1015 if (this.type === types._var || this.type === types._const || isLet) {
1016 var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
1017 this.next();
1018 this.parseVar(init$1, true, kind);
1019 this.finishNode(init$1, "VariableDeclaration");
1020 if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1) {
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 return this.parseForIn(node, init$1)
1027 }
1028 if (awaitAt > -1) { this.unexpected(awaitAt); }
1029 return this.parseFor(node, init$1)
1030 }
1031 var refDestructuringErrors = new DestructuringErrors;
1032 var init = this.parseExpression(true, refDestructuringErrors);
1033 if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
1034 if (this.options.ecmaVersion >= 9) {
1035 if (this.type === types._in) {
1036 if (awaitAt > -1) { this.unexpected(awaitAt); }
1037 } else { node.await = awaitAt > -1; }
1038 }
1039 this.toAssignable(init, false, refDestructuringErrors);
1040 this.checkLVal(init);
1041 return this.parseForIn(node, init)
1042 } else {
1043 this.checkExpressionErrors(refDestructuringErrors, true);
1044 }
1045 if (awaitAt > -1) { this.unexpected(awaitAt); }
1046 return this.parseFor(node, init)
1047 };
1048
1049 pp$1.parseFunctionStatement = function(node, isAsync, declarationPosition) {
1050 this.next();
1051 return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync)
1052 };
1053
1054 pp$1.parseIfStatement = function(node) {
1055 this.next();
1056 node.test = this.parseParenExpression();
1057 // allow function declarations in branches, but only in non-strict mode
1058 node.consequent = this.parseStatement("if");
1059 node.alternate = this.eat(types._else) ? this.parseStatement("if") : null;
1060 return this.finishNode(node, "IfStatement")
1061 };
1062
1063 pp$1.parseReturnStatement = function(node) {
1064 if (!this.inFunction && !this.options.allowReturnOutsideFunction)
1065 { this.raise(this.start, "'return' outside of function"); }
1066 this.next();
1067
1068 // In `return` (and `break`/`continue`), the keywords with
1069 // optional arguments, we eagerly look for a semicolon or the
1070 // possibility to insert one.
1071
1072 if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; }
1073 else { node.argument = this.parseExpression(); this.semicolon(); }
1074 return this.finishNode(node, "ReturnStatement")
1075 };
1076
1077 pp$1.parseSwitchStatement = function(node) {
1078 this.next();
1079 node.discriminant = this.parseParenExpression();
1080 node.cases = [];
1081 this.expect(types.braceL);
1082 this.labels.push(switchLabel);
1083 this.enterScope(0);
1084
1085 // Statements under must be grouped (by label) in SwitchCase
1086 // nodes. `cur` is used to keep the node that we are currently
1087 // adding statements to.
1088
1089 var cur;
1090 for (var sawDefault = false; this.type !== types.braceR;) {
1091 if (this.type === types._case || this.type === types._default) {
1092 var isCase = this.type === types._case;
1093 if (cur) { this.finishNode(cur, "SwitchCase"); }
1094 node.cases.push(cur = this.startNode());
1095 cur.consequent = [];
1096 this.next();
1097 if (isCase) {
1098 cur.test = this.parseExpression();
1099 } else {
1100 if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); }
1101 sawDefault = true;
1102 cur.test = null;
1103 }
1104 this.expect(types.colon);
1105 } else {
1106 if (!cur) { this.unexpected(); }
1107 cur.consequent.push(this.parseStatement(null));
1108 }
1109 }
1110 this.exitScope();
1111 if (cur) { this.finishNode(cur, "SwitchCase"); }
1112 this.next(); // Closing brace
1113 this.labels.pop();
1114 return this.finishNode(node, "SwitchStatement")
1115 };
1116
1117 pp$1.parseThrowStatement = function(node) {
1118 this.next();
1119 if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
1120 { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
1121 node.argument = this.parseExpression();
1122 this.semicolon();
1123 return this.finishNode(node, "ThrowStatement")
1124 };
1125
1126 // Reused empty array added for node fields that are always empty.
1127
1128 var empty = [];
1129
1130 pp$1.parseTryStatement = function(node) {
1131 this.next();
1132 node.block = this.parseBlock();
1133 node.handler = null;
1134 if (this.type === types._catch) {
1135 var clause = this.startNode();
1136 this.next();
1137 if (this.eat(types.parenL)) {
1138 clause.param = this.parseBindingAtom();
1139 var simple = clause.param.type === "Identifier";
1140 this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0);
1141 this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL);
1142 this.expect(types.parenR);
1143 } else {
1144 if (this.options.ecmaVersion < 10) { this.unexpected(); }
1145 clause.param = null;
1146 this.enterScope(0);
1147 }
1148 clause.body = this.parseBlock(false);
1149 this.exitScope();
1150 node.handler = this.finishNode(clause, "CatchClause");
1151 }
1152 node.finalizer = this.eat(types._finally) ? this.parseBlock() : null;
1153 if (!node.handler && !node.finalizer)
1154 { this.raise(node.start, "Missing catch or finally clause"); }
1155 return this.finishNode(node, "TryStatement")
1156 };
1157
1158 pp$1.parseVarStatement = function(node, kind) {
1159 this.next();
1160 this.parseVar(node, false, kind);
1161 this.semicolon();
1162 return this.finishNode(node, "VariableDeclaration")
1163 };
1164
1165 pp$1.parseWhileStatement = function(node) {
1166 this.next();
1167 node.test = this.parseParenExpression();
1168 this.labels.push(loopLabel);
1169 node.body = this.parseStatement("while");
1170 this.labels.pop();
1171 return this.finishNode(node, "WhileStatement")
1172 };
1173
1174 pp$1.parseWithStatement = function(node) {
1175 if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
1176 this.next();
1177 node.object = this.parseParenExpression();
1178 node.body = this.parseStatement("with");
1179 return this.finishNode(node, "WithStatement")
1180 };
1181
1182 pp$1.parseEmptyStatement = function(node) {
1183 this.next();
1184 return this.finishNode(node, "EmptyStatement")
1185 };
1186
1187 pp$1.parseLabeledStatement = function(node, maybeName, expr, context) {
1188 for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1)
1189 {
1190 var label = list[i$1];
1191
1192 if (label.name === maybeName)
1193 { this.raise(expr.start, "Label '" + maybeName + "' is already declared");
1194 } }
1195 var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null;
1196 for (var i = this.labels.length - 1; i >= 0; i--) {
1197 var label$1 = this.labels[i];
1198 if (label$1.statementStart === node.start) {
1199 // Update information about previous labels on this node
1200 label$1.statementStart = this.start;
1201 label$1.kind = kind;
1202 } else { break }
1203 }
1204 this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
1205 node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label");
1206 this.labels.pop();
1207 node.label = expr;
1208 return this.finishNode(node, "LabeledStatement")
1209 };
1210
1211 pp$1.parseExpressionStatement = function(node, expr) {
1212 node.expression = expr;
1213 this.semicolon();
1214 return this.finishNode(node, "ExpressionStatement")
1215 };
1216
1217 // Parse a semicolon-enclosed block of statements, handling `"use
1218 // strict"` declarations when `allowStrict` is true (used for
1219 // function bodies).
1220
1221 pp$1.parseBlock = function(createNewLexicalScope, node, exitStrict) {
1222 if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;
1223 if ( node === void 0 ) node = this.startNode();
1224
1225 node.body = [];
1226 this.expect(types.braceL);
1227 if (createNewLexicalScope) { this.enterScope(0); }
1228 while (this.type !== types.braceR) {
1229 var stmt = this.parseStatement(null);
1230 node.body.push(stmt);
1231 }
1232 if (exitStrict) { this.strict = false; }
1233 this.next();
1234 if (createNewLexicalScope) { this.exitScope(); }
1235 return this.finishNode(node, "BlockStatement")
1236 };
1237
1238 // Parse a regular `for` loop. The disambiguation code in
1239 // `parseStatement` will already have parsed the init statement or
1240 // expression.
1241
1242 pp$1.parseFor = function(node, init) {
1243 node.init = init;
1244 this.expect(types.semi);
1245 node.test = this.type === types.semi ? null : this.parseExpression();
1246 this.expect(types.semi);
1247 node.update = this.type === types.parenR ? null : this.parseExpression();
1248 this.expect(types.parenR);
1249 node.body = this.parseStatement("for");
1250 this.exitScope();
1251 this.labels.pop();
1252 return this.finishNode(node, "ForStatement")
1253 };
1254
1255 // Parse a `for`/`in` and `for`/`of` loop, which are almost
1256 // same from parser's perspective.
1257
1258 pp$1.parseForIn = function(node, init) {
1259 var isForIn = this.type === types._in;
1260 this.next();
1261
1262 if (
1263 init.type === "VariableDeclaration" &&
1264 init.declarations[0].init != null &&
1265 (
1266 !isForIn ||
1267 this.options.ecmaVersion < 8 ||
1268 this.strict ||
1269 init.kind !== "var" ||
1270 init.declarations[0].id.type !== "Identifier"
1271 )
1272 ) {
1273 this.raise(
1274 init.start,
1275 ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer")
1276 );
1277 } else if (init.type === "AssignmentPattern") {
1278 this.raise(init.start, "Invalid left-hand side in for-loop");
1279 }
1280 node.left = init;
1281 node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign();
1282 this.expect(types.parenR);
1283 node.body = this.parseStatement("for");
1284 this.exitScope();
1285 this.labels.pop();
1286 return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement")
1287 };
1288
1289 // Parse a list of variable declarations.
1290
1291 pp$1.parseVar = function(node, isFor, kind) {
1292 node.declarations = [];
1293 node.kind = kind;
1294 for (;;) {
1295 var decl = this.startNode();
1296 this.parseVarId(decl, kind);
1297 if (this.eat(types.eq)) {
1298 decl.init = this.parseMaybeAssign(isFor);
1299 } else if (kind === "const" && !(this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
1300 this.unexpected();
1301 } else if (decl.id.type !== "Identifier" && !(isFor && (this.type === types._in || this.isContextual("of")))) {
1302 this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value");
1303 } else {
1304 decl.init = null;
1305 }
1306 node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
1307 if (!this.eat(types.comma)) { break }
1308 }
1309 return node
1310 };
1311
1312 pp$1.parseVarId = function(decl, kind) {
1313 decl.id = this.parseBindingAtom();
1314 this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false);
1315 };
1316
1317 var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4;
1318
1319 // Parse a function declaration or literal (depending on the
1320 // `statement & FUNC_STATEMENT`).
1321
1322 // Remove `allowExpressionBody` for 7.0.0, as it is only called with false
1323 pp$1.parseFunction = function(node, statement, allowExpressionBody, isAsync) {
1324 this.initFunction(node);
1325 if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) {
1326 if (this.type === types.star && (statement & FUNC_HANGING_STATEMENT))
1327 { this.unexpected(); }
1328 node.generator = this.eat(types.star);
1329 }
1330 if (this.options.ecmaVersion >= 8)
1331 { node.async = !!isAsync; }
1332
1333 if (statement & FUNC_STATEMENT) {
1334 node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name ? null : this.parseIdent();
1335 if (node.id && !(statement & FUNC_HANGING_STATEMENT))
1336 // If it is a regular function declaration in sloppy mode, then it is
1337 // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
1338 // mode depends on properties of the current scope (see
1339 // treatFunctionsAsVar).
1340 { this.checkLVal(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); }
1341 }
1342
1343 var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
1344 this.yieldPos = 0;
1345 this.awaitPos = 0;
1346 this.awaitIdentPos = 0;
1347 this.enterScope(functionFlags(node.async, node.generator));
1348
1349 if (!(statement & FUNC_STATEMENT))
1350 { node.id = this.type === types.name ? this.parseIdent() : null; }
1351
1352 this.parseFunctionParams(node);
1353 this.parseFunctionBody(node, allowExpressionBody, false);
1354
1355 this.yieldPos = oldYieldPos;
1356 this.awaitPos = oldAwaitPos;
1357 this.awaitIdentPos = oldAwaitIdentPos;
1358 return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression")
1359 };
1360
1361 pp$1.parseFunctionParams = function(node) {
1362 this.expect(types.parenL);
1363 node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
1364 this.checkYieldAwaitInDefaultParams();
1365 };
1366
1367 // Parse a class declaration or literal (depending on the
1368 // `isStatement` parameter).
1369
1370 pp$1.parseClass = function(node, isStatement) {
1371 this.next();
1372
1373 // ecma-262 14.6 Class Definitions
1374 // A class definition is always strict mode code.
1375 var oldStrict = this.strict;
1376 this.strict = true;
1377
1378 this.parseClassId(node, isStatement);
1379 this.parseClassSuper(node);
1380 var classBody = this.startNode();
1381 var hadConstructor = false;
1382 classBody.body = [];
1383 this.expect(types.braceL);
1384 while (this.type !== types.braceR) {
1385 var element = this.parseClassElement(node.superClass !== null);
1386 if (element) {
1387 classBody.body.push(element);
1388 if (element.type === "MethodDefinition" && element.kind === "constructor") {
1389 if (hadConstructor) { this.raise(element.start, "Duplicate constructor in the same class"); }
1390 hadConstructor = true;
1391 }
1392 }
1393 }
1394 this.strict = oldStrict;
1395 this.next();
1396 node.body = this.finishNode(classBody, "ClassBody");
1397 return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
1398 };
1399
1400 pp$1.parseClassElement = function(constructorAllowsSuper) {
1401 var this$1 = this;
1402
1403 if (this.eat(types.semi)) { return null }
1404
1405 var method = this.startNode();
1406 var tryContextual = function (k, noLineBreak) {
1407 if ( noLineBreak === void 0 ) noLineBreak = false;
1408
1409 var start = this$1.start, startLoc = this$1.startLoc;
1410 if (!this$1.eatContextual(k)) { return false }
1411 if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true }
1412 if (method.key) { this$1.unexpected(); }
1413 method.computed = false;
1414 method.key = this$1.startNodeAt(start, startLoc);
1415 method.key.name = k;
1416 this$1.finishNode(method.key, "Identifier");
1417 return false
1418 };
1419
1420 method.kind = "method";
1421 method.static = tryContextual("static");
1422 var isGenerator = this.eat(types.star);
1423 var isAsync = false;
1424 if (!isGenerator) {
1425 if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) {
1426 isAsync = true;
1427 isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
1428 } else if (tryContextual("get")) {
1429 method.kind = "get";
1430 } else if (tryContextual("set")) {
1431 method.kind = "set";
1432 }
1433 }
1434 if (!method.key) { this.parsePropertyName(method); }
1435 var key = method.key;
1436 var allowsDirectSuper = false;
1437 if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" ||
1438 key.type === "Literal" && key.value === "constructor")) {
1439 if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); }
1440 if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); }
1441 if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); }
1442 method.kind = "constructor";
1443 allowsDirectSuper = constructorAllowsSuper;
1444 } else if (method.static && key.type === "Identifier" && key.name === "prototype") {
1445 this.raise(key.start, "Classes may not have a static property named prototype");
1446 }
1447 this.parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper);
1448 if (method.kind === "get" && method.value.params.length !== 0)
1449 { this.raiseRecoverable(method.value.start, "getter should have no params"); }
1450 if (method.kind === "set" && method.value.params.length !== 1)
1451 { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); }
1452 if (method.kind === "set" && method.value.params[0].type === "RestElement")
1453 { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); }
1454 return method
1455 };
1456
1457 pp$1.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) {
1458 method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper);
1459 return this.finishNode(method, "MethodDefinition")
1460 };
1461
1462 pp$1.parseClassId = function(node, isStatement) {
1463 if (this.type === types.name) {
1464 node.id = this.parseIdent();
1465 if (isStatement)
1466 { this.checkLVal(node.id, BIND_LEXICAL, false); }
1467 } else {
1468 if (isStatement === true)
1469 { this.unexpected(); }
1470 node.id = null;
1471 }
1472 };
1473
1474 pp$1.parseClassSuper = function(node) {
1475 node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null;
1476 };
1477
1478 // Parses module export declaration.
1479
1480 pp$1.parseExport = function(node, exports) {
1481 this.next();
1482 // export * from '...'
1483 if (this.eat(types.star)) {
1484 if (this.options.ecmaVersion >= 11) {
1485 if (this.eatContextual("as")) {
1486 node.exported = this.parseIdent(true);
1487 this.checkExport(exports, node.exported.name, this.lastTokStart);
1488 } else {
1489 node.exported = null;
1490 }
1491 }
1492 this.expectContextual("from");
1493 if (this.type !== types.string) { this.unexpected(); }
1494 node.source = this.parseExprAtom();
1495 this.semicolon();
1496 return this.finishNode(node, "ExportAllDeclaration")
1497 }
1498 if (this.eat(types._default)) { // export default ...
1499 this.checkExport(exports, "default", this.lastTokStart);
1500 var isAsync;
1501 if (this.type === types._function || (isAsync = this.isAsyncFunction())) {
1502 var fNode = this.startNode();
1503 this.next();
1504 if (isAsync) { this.next(); }
1505 node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync);
1506 } else if (this.type === types._class) {
1507 var cNode = this.startNode();
1508 node.declaration = this.parseClass(cNode, "nullableID");
1509 } else {
1510 node.declaration = this.parseMaybeAssign();
1511 this.semicolon();
1512 }
1513 return this.finishNode(node, "ExportDefaultDeclaration")
1514 }
1515 // export var|const|let|function|class ...
1516 if (this.shouldParseExportStatement()) {
1517 node.declaration = this.parseStatement(null);
1518 if (node.declaration.type === "VariableDeclaration")
1519 { this.checkVariableExport(exports, node.declaration.declarations); }
1520 else
1521 { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); }
1522 node.specifiers = [];
1523 node.source = null;
1524 } else { // export { x, y as z } [from '...']
1525 node.declaration = null;
1526 node.specifiers = this.parseExportSpecifiers(exports);
1527 if (this.eatContextual("from")) {
1528 if (this.type !== types.string) { this.unexpected(); }
1529 node.source = this.parseExprAtom();
1530 } else {
1531 for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
1532 // check for keywords used as local names
1533 var spec = list[i];
1534
1535 this.checkUnreserved(spec.local);
1536 // check if export is defined
1537 this.checkLocalExport(spec.local);
1538 }
1539
1540 node.source = null;
1541 }
1542 this.semicolon();
1543 }
1544 return this.finishNode(node, "ExportNamedDeclaration")
1545 };
1546
1547 pp$1.checkExport = function(exports, name, pos) {
1548 if (!exports) { return }
1549 if (has(exports, name))
1550 { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
1551 exports[name] = true;
1552 };
1553
1554 pp$1.checkPatternExport = function(exports, pat) {
1555 var type = pat.type;
1556 if (type === "Identifier")
1557 { this.checkExport(exports, pat.name, pat.start); }
1558 else if (type === "ObjectPattern")
1559 { for (var i = 0, list = pat.properties; i < list.length; i += 1)
1560 {
1561 var prop = list[i];
1562
1563 this.checkPatternExport(exports, prop);
1564 } }
1565 else if (type === "ArrayPattern")
1566 { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
1567 var elt = list$1[i$1];
1568
1569 if (elt) { this.checkPatternExport(exports, elt); }
1570 } }
1571 else if (type === "Property")
1572 { this.checkPatternExport(exports, pat.value); }
1573 else if (type === "AssignmentPattern")
1574 { this.checkPatternExport(exports, pat.left); }
1575 else if (type === "RestElement")
1576 { this.checkPatternExport(exports, pat.argument); }
1577 else if (type === "ParenthesizedExpression")
1578 { this.checkPatternExport(exports, pat.expression); }
1579 };
1580
1581 pp$1.checkVariableExport = function(exports, decls) {
1582 if (!exports) { return }
1583 for (var i = 0, list = decls; i < list.length; i += 1)
1584 {
1585 var decl = list[i];
1586
1587 this.checkPatternExport(exports, decl.id);
1588 }
1589 };
1590
1591 pp$1.shouldParseExportStatement = function() {
1592 return this.type.keyword === "var" ||
1593 this.type.keyword === "const" ||
1594 this.type.keyword === "class" ||
1595 this.type.keyword === "function" ||
1596 this.isLet() ||
1597 this.isAsyncFunction()
1598 };
1599
1600 // Parses a comma-separated list of module exports.
1601
1602 pp$1.parseExportSpecifiers = function(exports) {
1603 var nodes = [], first = true;
1604 // export { x, y as z } [from '...']
1605 this.expect(types.braceL);
1606 while (!this.eat(types.braceR)) {
1607 if (!first) {
1608 this.expect(types.comma);
1609 if (this.afterTrailingComma(types.braceR)) { break }
1610 } else { first = false; }
1611
1612 var node = this.startNode();
1613 node.local = this.parseIdent(true);
1614 node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local;
1615 this.checkExport(exports, node.exported.name, node.exported.start);
1616 nodes.push(this.finishNode(node, "ExportSpecifier"));
1617 }
1618 return nodes
1619 };
1620
1621 // Parses import declaration.
1622
1623 pp$1.parseImport = function(node) {
1624 this.next();
1625 // import '...'
1626 if (this.type === types.string) {
1627 node.specifiers = empty;
1628 node.source = this.parseExprAtom();
1629 } else {
1630 node.specifiers = this.parseImportSpecifiers();
1631 this.expectContextual("from");
1632 node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
1633 }
1634 this.semicolon();
1635 return this.finishNode(node, "ImportDeclaration")
1636 };
1637
1638 // Parses a comma-separated list of module imports.
1639
1640 pp$1.parseImportSpecifiers = function() {
1641 var nodes = [], first = true;
1642 if (this.type === types.name) {
1643 // import defaultObj, { x, y as z } from '...'
1644 var node = this.startNode();
1645 node.local = this.parseIdent();
1646 this.checkLVal(node.local, BIND_LEXICAL);
1647 nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
1648 if (!this.eat(types.comma)) { return nodes }
1649 }
1650 if (this.type === types.star) {
1651 var node$1 = this.startNode();
1652 this.next();
1653 this.expectContextual("as");
1654 node$1.local = this.parseIdent();
1655 this.checkLVal(node$1.local, BIND_LEXICAL);
1656 nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
1657 return nodes
1658 }
1659 this.expect(types.braceL);
1660 while (!this.eat(types.braceR)) {
1661 if (!first) {
1662 this.expect(types.comma);
1663 if (this.afterTrailingComma(types.braceR)) { break }
1664 } else { first = false; }
1665
1666 var node$2 = this.startNode();
1667 node$2.imported = this.parseIdent(true);
1668 if (this.eatContextual("as")) {
1669 node$2.local = this.parseIdent();
1670 } else {
1671 this.checkUnreserved(node$2.imported);
1672 node$2.local = node$2.imported;
1673 }
1674 this.checkLVal(node$2.local, BIND_LEXICAL);
1675 nodes.push(this.finishNode(node$2, "ImportSpecifier"));
1676 }
1677 return nodes
1678 };
1679
1680 // Set `ExpressionStatement#directive` property for directive prologues.
1681 pp$1.adaptDirectivePrologue = function(statements) {
1682 for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
1683 statements[i].directive = statements[i].expression.raw.slice(1, -1);
1684 }
1685 };
1686 pp$1.isDirectiveCandidate = function(statement) {
1687 return (
1688 statement.type === "ExpressionStatement" &&
1689 statement.expression.type === "Literal" &&
1690 typeof statement.expression.value === "string" &&
1691 // Reject parenthesized strings.
1692 (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
1693 )
1694 };
1695
1696 var pp$2 = Parser.prototype;
1697
1698 // Convert existing expression atom to assignable pattern
1699 // if possible.
1700
1701 pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) {
1702 if (this.options.ecmaVersion >= 6 && node) {
1703 switch (node.type) {
1704 case "Identifier":
1705 if (this.inAsync && node.name === "await")
1706 { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); }
1707 break
1708
1709 case "ObjectPattern":
1710 case "ArrayPattern":
1711 case "RestElement":
1712 break
1713
1714 case "ObjectExpression":
1715 node.type = "ObjectPattern";
1716 if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1717 for (var i = 0, list = node.properties; i < list.length; i += 1) {
1718 var prop = list[i];
1719
1720 this.toAssignable(prop, isBinding);
1721 // Early error:
1722 // AssignmentRestProperty[Yield, Await] :
1723 // `...` DestructuringAssignmentTarget[Yield, Await]
1724 //
1725 // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
1726 if (
1727 prop.type === "RestElement" &&
1728 (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")
1729 ) {
1730 this.raise(prop.argument.start, "Unexpected token");
1731 }
1732 }
1733 break
1734
1735 case "Property":
1736 // AssignmentProperty has type === "Property"
1737 if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); }
1738 this.toAssignable(node.value, isBinding);
1739 break
1740
1741 case "ArrayExpression":
1742 node.type = "ArrayPattern";
1743 if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1744 this.toAssignableList(node.elements, isBinding);
1745 break
1746
1747 case "SpreadElement":
1748 node.type = "RestElement";
1749 this.toAssignable(node.argument, isBinding);
1750 if (node.argument.type === "AssignmentPattern")
1751 { this.raise(node.argument.start, "Rest elements cannot have a default value"); }
1752 break
1753
1754 case "AssignmentExpression":
1755 if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); }
1756 node.type = "AssignmentPattern";
1757 delete node.operator;
1758 this.toAssignable(node.left, isBinding);
1759 // falls through to AssignmentPattern
1760
1761 case "AssignmentPattern":
1762 break
1763
1764 case "ParenthesizedExpression":
1765 this.toAssignable(node.expression, isBinding, refDestructuringErrors);
1766 break
1767
1768 case "ChainExpression":
1769 this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side");
1770 break
1771
1772 case "MemberExpression":
1773 if (!isBinding) { break }
1774
1775 default:
1776 this.raise(node.start, "Assigning to rvalue");
1777 }
1778 } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1779 return node
1780 };
1781
1782 // Convert list of expression atoms to binding list.
1783
1784 pp$2.toAssignableList = function(exprList, isBinding) {
1785 var end = exprList.length;
1786 for (var i = 0; i < end; i++) {
1787 var elt = exprList[i];
1788 if (elt) { this.toAssignable(elt, isBinding); }
1789 }
1790 if (end) {
1791 var last = exprList[end - 1];
1792 if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
1793 { this.unexpected(last.argument.start); }
1794 }
1795 return exprList
1796 };
1797
1798 // Parses spread element.
1799
1800 pp$2.parseSpread = function(refDestructuringErrors) {
1801 var node = this.startNode();
1802 this.next();
1803 node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
1804 return this.finishNode(node, "SpreadElement")
1805 };
1806
1807 pp$2.parseRestBinding = function() {
1808 var node = this.startNode();
1809 this.next();
1810
1811 // RestElement inside of a function parameter must be an identifier
1812 if (this.options.ecmaVersion === 6 && this.type !== types.name)
1813 { this.unexpected(); }
1814
1815 node.argument = this.parseBindingAtom();
1816
1817 return this.finishNode(node, "RestElement")
1818 };
1819
1820 // Parses lvalue (assignable) atom.
1821
1822 pp$2.parseBindingAtom = function() {
1823 if (this.options.ecmaVersion >= 6) {
1824 switch (this.type) {
1825 case types.bracketL:
1826 var node = this.startNode();
1827 this.next();
1828 node.elements = this.parseBindingList(types.bracketR, true, true);
1829 return this.finishNode(node, "ArrayPattern")
1830
1831 case types.braceL:
1832 return this.parseObj(true)
1833 }
1834 }
1835 return this.parseIdent()
1836 };
1837
1838 pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
1839 var elts = [], first = true;
1840 while (!this.eat(close)) {
1841 if (first) { first = false; }
1842 else { this.expect(types.comma); }
1843 if (allowEmpty && this.type === types.comma) {
1844 elts.push(null);
1845 } else if (allowTrailingComma && this.afterTrailingComma(close)) {
1846 break
1847 } else if (this.type === types.ellipsis) {
1848 var rest = this.parseRestBinding();
1849 this.parseBindingListItem(rest);
1850 elts.push(rest);
1851 if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); }
1852 this.expect(close);
1853 break
1854 } else {
1855 var elem = this.parseMaybeDefault(this.start, this.startLoc);
1856 this.parseBindingListItem(elem);
1857 elts.push(elem);
1858 }
1859 }
1860 return elts
1861 };
1862
1863 pp$2.parseBindingListItem = function(param) {
1864 return param
1865 };
1866
1867 // Parses assignment pattern around given atom if possible.
1868
1869 pp$2.parseMaybeDefault = function(startPos, startLoc, left) {
1870 left = left || this.parseBindingAtom();
1871 if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left }
1872 var node = this.startNodeAt(startPos, startLoc);
1873 node.left = left;
1874 node.right = this.parseMaybeAssign();
1875 return this.finishNode(node, "AssignmentPattern")
1876 };
1877
1878 // Verify that a node is an lval — something that can be assigned
1879 // to.
1880 // bindingType can be either:
1881 // 'var' indicating that the lval creates a 'var' binding
1882 // 'let' indicating that the lval creates a lexical ('let' or 'const') binding
1883 // 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references
1884
1885 pp$2.checkLVal = function(expr, bindingType, checkClashes) {
1886 if ( bindingType === void 0 ) bindingType = BIND_NONE;
1887
1888 switch (expr.type) {
1889 case "Identifier":
1890 if (bindingType === BIND_LEXICAL && expr.name === "let")
1891 { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); }
1892 if (this.strict && this.reservedWordsStrictBind.test(expr.name))
1893 { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
1894 if (checkClashes) {
1895 if (has(checkClashes, expr.name))
1896 { this.raiseRecoverable(expr.start, "Argument name clash"); }
1897 checkClashes[expr.name] = true;
1898 }
1899 if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); }
1900 break
1901
1902 case "ChainExpression":
1903 this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side");
1904 break
1905
1906 case "MemberExpression":
1907 if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); }
1908 break
1909
1910 case "ObjectPattern":
1911 for (var i = 0, list = expr.properties; i < list.length; i += 1)
1912 {
1913 var prop = list[i];
1914
1915 this.checkLVal(prop, bindingType, checkClashes);
1916 }
1917 break
1918
1919 case "Property":
1920 // AssignmentProperty has type === "Property"
1921 this.checkLVal(expr.value, bindingType, checkClashes);
1922 break
1923
1924 case "ArrayPattern":
1925 for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
1926 var elem = list$1[i$1];
1927
1928 if (elem) { this.checkLVal(elem, bindingType, checkClashes); }
1929 }
1930 break
1931
1932 case "AssignmentPattern":
1933 this.checkLVal(expr.left, bindingType, checkClashes);
1934 break
1935
1936 case "RestElement":
1937 this.checkLVal(expr.argument, bindingType, checkClashes);
1938 break
1939
1940 case "ParenthesizedExpression":
1941 this.checkLVal(expr.expression, bindingType, checkClashes);
1942 break
1943
1944 default:
1945 this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue");
1946 }
1947 };
1948
1949 // A recursive descent parser operates by defining functions for all
1950
1951 var pp$3 = Parser.prototype;
1952
1953 // Check if property name clashes with already added.
1954 // Object/class getters and setters are not allowed to clash —
1955 // either with each other or with an init property — and in
1956 // strict mode, init properties are also not allowed to be repeated.
1957
1958 pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) {
1959 if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
1960 { return }
1961 if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
1962 { return }
1963 var key = prop.key;
1964 var name;
1965 switch (key.type) {
1966 case "Identifier": name = key.name; break
1967 case "Literal": name = String(key.value); break
1968 default: return
1969 }
1970 var kind = prop.kind;
1971 if (this.options.ecmaVersion >= 6) {
1972 if (name === "__proto__" && kind === "init") {
1973 if (propHash.proto) {
1974 if (refDestructuringErrors) {
1975 if (refDestructuringErrors.doubleProto < 0)
1976 { refDestructuringErrors.doubleProto = key.start; }
1977 // Backwards-compat kludge. Can be removed in version 6.0
1978 } else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); }
1979 }
1980 propHash.proto = true;
1981 }
1982 return
1983 }
1984 name = "$" + name;
1985 var other = propHash[name];
1986 if (other) {
1987 var redefinition;
1988 if (kind === "init") {
1989 redefinition = this.strict && other.init || other.get || other.set;
1990 } else {
1991 redefinition = other.init || other[kind];
1992 }
1993 if (redefinition)
1994 { this.raiseRecoverable(key.start, "Redefinition of property"); }
1995 } else {
1996 other = propHash[name] = {
1997 init: false,
1998 get: false,
1999 set: false
2000 };
2001 }
2002 other[kind] = true;
2003 };
2004
2005 // ### Expression parsing
2006
2007 // These nest, from the most general expression type at the top to
2008 // 'atomic', nondivisible expression types at the bottom. Most of
2009 // the functions will simply let the function(s) below them parse,
2010 // and, *if* the syntactic construct they handle is present, wrap
2011 // the AST node that the inner parser gave them in another node.
2012
2013 // Parse a full expression. The optional arguments are used to
2014 // forbid the `in` operator (in for loops initalization expressions)
2015 // and provide reference for storing '=' operator inside shorthand
2016 // property assignment in contexts where both object expression
2017 // and object pattern might appear (so it's possible to raise
2018 // delayed syntax error at correct position).
2019
2020 pp$3.parseExpression = function(noIn, refDestructuringErrors) {
2021 var startPos = this.start, startLoc = this.startLoc;
2022 var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
2023 if (this.type === types.comma) {
2024 var node = this.startNodeAt(startPos, startLoc);
2025 node.expressions = [expr];
2026 while (this.eat(types.comma)) { node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); }
2027 return this.finishNode(node, "SequenceExpression")
2028 }
2029 return expr
2030 };
2031
2032 // Parse an assignment expression. This includes applications of
2033 // operators like `+=`.
2034
2035 pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
2036 if (this.isContextual("yield")) {
2037 if (this.inGenerator) { return this.parseYield(noIn) }
2038 // The tokenizer will assume an expression is allowed after
2039 // `yield`, but this isn't that kind of yield
2040 else { this.exprAllowed = false; }
2041 }
2042
2043 var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1;
2044 if (refDestructuringErrors) {
2045 oldParenAssign = refDestructuringErrors.parenthesizedAssign;
2046 oldTrailingComma = refDestructuringErrors.trailingComma;
2047 refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
2048 } else {
2049 refDestructuringErrors = new DestructuringErrors;
2050 ownDestructuringErrors = true;
2051 }
2052
2053 var startPos = this.start, startLoc = this.startLoc;
2054 if (this.type === types.parenL || this.type === types.name)
2055 { this.potentialArrowAt = this.start; }
2056 var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
2057 if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
2058 if (this.type.isAssign) {
2059 var node = this.startNodeAt(startPos, startLoc);
2060 node.operator = this.value;
2061 node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left;
2062 if (!ownDestructuringErrors) {
2063 refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
2064 }
2065 if (refDestructuringErrors.shorthandAssign >= node.left.start)
2066 { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly
2067 this.checkLVal(left);
2068 this.next();
2069 node.right = this.parseMaybeAssign(noIn);
2070 return this.finishNode(node, "AssignmentExpression")
2071 } else {
2072 if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
2073 }
2074 if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
2075 if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
2076 return left
2077 };
2078
2079 // Parse a ternary conditional (`?:`) operator.
2080
2081 pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) {
2082 var startPos = this.start, startLoc = this.startLoc;
2083 var expr = this.parseExprOps(noIn, refDestructuringErrors);
2084 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2085 if (this.eat(types.question)) {
2086 var node = this.startNodeAt(startPos, startLoc);
2087 node.test = expr;
2088 node.consequent = this.parseMaybeAssign();
2089 this.expect(types.colon);
2090 node.alternate = this.parseMaybeAssign(noIn);
2091 return this.finishNode(node, "ConditionalExpression")
2092 }
2093 return expr
2094 };
2095
2096 // Start the precedence parser.
2097
2098 pp$3.parseExprOps = function(noIn, refDestructuringErrors) {
2099 var startPos = this.start, startLoc = this.startLoc;
2100 var expr = this.parseMaybeUnary(refDestructuringErrors, false);
2101 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2102 return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn)
2103 };
2104
2105 // Parse binary operators with the operator precedence parsing
2106 // algorithm. `left` is the left-hand side of the operator.
2107 // `minPrec` provides context that allows the function to stop and
2108 // defer further parser to one of its callers when it encounters an
2109 // operator that has a lower precedence than the set it is parsing.
2110
2111 pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
2112 var prec = this.type.binop;
2113 if (prec != null && (!noIn || this.type !== types._in)) {
2114 if (prec > minPrec) {
2115 var logical = this.type === types.logicalOR || this.type === types.logicalAND;
2116 var coalesce = this.type === types.coalesce;
2117 if (coalesce) {
2118 // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions.
2119 // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error.
2120 prec = types.logicalAND.binop;
2121 }
2122 var op = this.value;
2123 this.next();
2124 var startPos = this.start, startLoc = this.startLoc;
2125 var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
2126 var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce);
2127 if ((logical && this.type === types.coalesce) || (coalesce && (this.type === types.logicalOR || this.type === types.logicalAND))) {
2128 this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses");
2129 }
2130 return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
2131 }
2132 }
2133 return left
2134 };
2135
2136 pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) {
2137 var node = this.startNodeAt(startPos, startLoc);
2138 node.left = left;
2139 node.operator = op;
2140 node.right = right;
2141 return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
2142 };
2143
2144 // Parse unary operators, both prefix and postfix.
2145
2146 pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
2147 var startPos = this.start, startLoc = this.startLoc, expr;
2148 if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) {
2149 expr = this.parseAwait();
2150 sawUnary = true;
2151 } else if (this.type.prefix) {
2152 var node = this.startNode(), update = this.type === types.incDec;
2153 node.operator = this.value;
2154 node.prefix = true;
2155 this.next();
2156 node.argument = this.parseMaybeUnary(null, true);
2157 this.checkExpressionErrors(refDestructuringErrors, true);
2158 if (update) { this.checkLVal(node.argument); }
2159 else if (this.strict && node.operator === "delete" &&
2160 node.argument.type === "Identifier")
2161 { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
2162 else { sawUnary = true; }
2163 expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
2164 } else {
2165 expr = this.parseExprSubscripts(refDestructuringErrors);
2166 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2167 while (this.type.postfix && !this.canInsertSemicolon()) {
2168 var node$1 = this.startNodeAt(startPos, startLoc);
2169 node$1.operator = this.value;
2170 node$1.prefix = false;
2171 node$1.argument = expr;
2172 this.checkLVal(expr);
2173 this.next();
2174 expr = this.finishNode(node$1, "UpdateExpression");
2175 }
2176 }
2177
2178 if (!sawUnary && this.eat(types.starstar))
2179 { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) }
2180 else
2181 { return expr }
2182 };
2183
2184 // Parse call, dot, and `[]`-subscript expressions.
2185
2186 pp$3.parseExprSubscripts = function(refDestructuringErrors) {
2187 var startPos = this.start, startLoc = this.startLoc;
2188 var expr = this.parseExprAtom(refDestructuringErrors);
2189 if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")")
2190 { return expr }
2191 var result = this.parseSubscripts(expr, startPos, startLoc);
2192 if (refDestructuringErrors && result.type === "MemberExpression") {
2193 if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
2194 if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
2195 }
2196 return result
2197 };
2198
2199 pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) {
2200 var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
2201 this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 &&
2202 this.potentialArrowAt === base.start;
2203 var optionalChained = false;
2204
2205 while (true) {
2206 var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained);
2207
2208 if (element.optional) { optionalChained = true; }
2209 if (element === base || element.type === "ArrowFunctionExpression") {
2210 if (optionalChained) {
2211 var chainNode = this.startNodeAt(startPos, startLoc);
2212 chainNode.expression = element;
2213 element = this.finishNode(chainNode, "ChainExpression");
2214 }
2215 return element
2216 }
2217
2218 base = element;
2219 }
2220 };
2221
2222 pp$3.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained) {
2223 var optionalSupported = this.options.ecmaVersion >= 11;
2224 var optional = optionalSupported && this.eat(types.questionDot);
2225 if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); }
2226
2227 var computed = this.eat(types.bracketL);
2228 if (computed || (optional && this.type !== types.parenL && this.type !== types.backQuote) || this.eat(types.dot)) {
2229 var node = this.startNodeAt(startPos, startLoc);
2230 node.object = base;
2231 node.property = computed ? this.parseExpression() : this.parseIdent(this.options.allowReserved !== "never");
2232 node.computed = !!computed;
2233 if (computed) { this.expect(types.bracketR); }
2234 if (optionalSupported) {
2235 node.optional = optional;
2236 }
2237 base = this.finishNode(node, "MemberExpression");
2238 } else if (!noCalls && this.eat(types.parenL)) {
2239 var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2240 this.yieldPos = 0;
2241 this.awaitPos = 0;
2242 this.awaitIdentPos = 0;
2243 var exprList = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors);
2244 if (maybeAsyncArrow && !optional && !this.canInsertSemicolon() && this.eat(types.arrow)) {
2245 this.checkPatternErrors(refDestructuringErrors, false);
2246 this.checkYieldAwaitInDefaultParams();
2247 if (this.awaitIdentPos > 0)
2248 { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); }
2249 this.yieldPos = oldYieldPos;
2250 this.awaitPos = oldAwaitPos;
2251 this.awaitIdentPos = oldAwaitIdentPos;
2252 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true)
2253 }
2254 this.checkExpressionErrors(refDestructuringErrors, true);
2255 this.yieldPos = oldYieldPos || this.yieldPos;
2256 this.awaitPos = oldAwaitPos || this.awaitPos;
2257 this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos;
2258 var node$1 = this.startNodeAt(startPos, startLoc);
2259 node$1.callee = base;
2260 node$1.arguments = exprList;
2261 if (optionalSupported) {
2262 node$1.optional = optional;
2263 }
2264 base = this.finishNode(node$1, "CallExpression");
2265 } else if (this.type === types.backQuote) {
2266 if (optional || optionalChained) {
2267 this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions");
2268 }
2269 var node$2 = this.startNodeAt(startPos, startLoc);
2270 node$2.tag = base;
2271 node$2.quasi = this.parseTemplate({isTagged: true});
2272 base = this.finishNode(node$2, "TaggedTemplateExpression");
2273 }
2274 return base
2275 };
2276
2277 // Parse an atomic expression — either a single token that is an
2278 // expression, an expression started by a keyword like `function` or
2279 // `new`, or an expression wrapped in punctuation like `()`, `[]`,
2280 // or `{}`.
2281
2282 pp$3.parseExprAtom = function(refDestructuringErrors) {
2283 // If a division operator appears in an expression position, the
2284 // tokenizer got confused, and we force it to read a regexp instead.
2285 if (this.type === types.slash) { this.readRegexp(); }
2286
2287 var node, canBeArrow = this.potentialArrowAt === this.start;
2288 switch (this.type) {
2289 case types._super:
2290 if (!this.allowSuper)
2291 { this.raise(this.start, "'super' keyword outside a method"); }
2292 node = this.startNode();
2293 this.next();
2294 if (this.type === types.parenL && !this.allowDirectSuper)
2295 { this.raise(node.start, "super() call outside constructor of a subclass"); }
2296 // The `super` keyword can appear at below:
2297 // SuperProperty:
2298 // super [ Expression ]
2299 // super . IdentifierName
2300 // SuperCall:
2301 // super ( Arguments )
2302 if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
2303 { this.unexpected(); }
2304 return this.finishNode(node, "Super")
2305
2306 case types._this:
2307 node = this.startNode();
2308 this.next();
2309 return this.finishNode(node, "ThisExpression")
2310
2311 case types.name:
2312 var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
2313 var id = this.parseIdent(false);
2314 if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function))
2315 { return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) }
2316 if (canBeArrow && !this.canInsertSemicolon()) {
2317 if (this.eat(types.arrow))
2318 { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) }
2319 if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) {
2320 id = this.parseIdent(false);
2321 if (this.canInsertSemicolon() || !this.eat(types.arrow))
2322 { this.unexpected(); }
2323 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
2324 }
2325 }
2326 return id
2327
2328 case types.regexp:
2329 var value = this.value;
2330 node = this.parseLiteral(value.value);
2331 node.regex = {pattern: value.pattern, flags: value.flags};
2332 return node
2333
2334 case types.num: case types.string:
2335 return this.parseLiteral(this.value)
2336
2337 case types._null: case types._true: case types._false:
2338 node = this.startNode();
2339 node.value = this.type === types._null ? null : this.type === types._true;
2340 node.raw = this.type.keyword;
2341 this.next();
2342 return this.finishNode(node, "Literal")
2343
2344 case types.parenL:
2345 var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow);
2346 if (refDestructuringErrors) {
2347 if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
2348 { refDestructuringErrors.parenthesizedAssign = start; }
2349 if (refDestructuringErrors.parenthesizedBind < 0)
2350 { refDestructuringErrors.parenthesizedBind = start; }
2351 }
2352 return expr
2353
2354 case types.bracketL:
2355 node = this.startNode();
2356 this.next();
2357 node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors);
2358 return this.finishNode(node, "ArrayExpression")
2359
2360 case types.braceL:
2361 return this.parseObj(false, refDestructuringErrors)
2362
2363 case types._function:
2364 node = this.startNode();
2365 this.next();
2366 return this.parseFunction(node, 0)
2367
2368 case types._class:
2369 return this.parseClass(this.startNode(), false)
2370
2371 case types._new:
2372 return this.parseNew()
2373
2374 case types.backQuote:
2375 return this.parseTemplate()
2376
2377 case types._import:
2378 if (this.options.ecmaVersion >= 11) {
2379 return this.parseExprImport()
2380 } else {
2381 return this.unexpected()
2382 }
2383
2384 default:
2385 this.unexpected();
2386 }
2387 };
2388
2389 pp$3.parseExprImport = function() {
2390 var node = this.startNode();
2391
2392 // Consume `import` as an identifier for `import.meta`.
2393 // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`.
2394 if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); }
2395 var meta = this.parseIdent(true);
2396
2397 switch (this.type) {
2398 case types.parenL:
2399 return this.parseDynamicImport(node)
2400 case types.dot:
2401 node.meta = meta;
2402 return this.parseImportMeta(node)
2403 default:
2404 this.unexpected();
2405 }
2406 };
2407
2408 pp$3.parseDynamicImport = function(node) {
2409 this.next(); // skip `(`
2410
2411 // Parse node.source.
2412 node.source = this.parseMaybeAssign();
2413
2414 // Verify ending.
2415 if (!this.eat(types.parenR)) {
2416 var errorPos = this.start;
2417 if (this.eat(types.comma) && this.eat(types.parenR)) {
2418 this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()");
2419 } else {
2420 this.unexpected(errorPos);
2421 }
2422 }
2423
2424 return this.finishNode(node, "ImportExpression")
2425 };
2426
2427 pp$3.parseImportMeta = function(node) {
2428 this.next(); // skip `.`
2429
2430 var containsEsc = this.containsEsc;
2431 node.property = this.parseIdent(true);
2432
2433 if (node.property.name !== "meta")
2434 { this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); }
2435 if (containsEsc)
2436 { this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); }
2437 if (this.options.sourceType !== "module")
2438 { this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); }
2439
2440 return this.finishNode(node, "MetaProperty")
2441 };
2442
2443 pp$3.parseLiteral = function(value) {
2444 var node = this.startNode();
2445 node.value = value;
2446 node.raw = this.input.slice(this.start, this.end);
2447 if (node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1); }
2448 this.next();
2449 return this.finishNode(node, "Literal")
2450 };
2451
2452 pp$3.parseParenExpression = function() {
2453 this.expect(types.parenL);
2454 var val = this.parseExpression();
2455 this.expect(types.parenR);
2456 return val
2457 };
2458
2459 pp$3.parseParenAndDistinguishExpression = function(canBeArrow) {
2460 var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
2461 if (this.options.ecmaVersion >= 6) {
2462 this.next();
2463
2464 var innerStartPos = this.start, innerStartLoc = this.startLoc;
2465 var exprList = [], first = true, lastIsComma = false;
2466 var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
2467 this.yieldPos = 0;
2468 this.awaitPos = 0;
2469 // Do not save awaitIdentPos to allow checking awaits nested in parameters
2470 while (this.type !== types.parenR) {
2471 first ? first = false : this.expect(types.comma);
2472 if (allowTrailingComma && this.afterTrailingComma(types.parenR, true)) {
2473 lastIsComma = true;
2474 break
2475 } else if (this.type === types.ellipsis) {
2476 spreadStart = this.start;
2477 exprList.push(this.parseParenItem(this.parseRestBinding()));
2478 if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); }
2479 break
2480 } else {
2481 exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem));
2482 }
2483 }
2484 var innerEndPos = this.start, innerEndLoc = this.startLoc;
2485 this.expect(types.parenR);
2486
2487 if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
2488 this.checkPatternErrors(refDestructuringErrors, false);
2489 this.checkYieldAwaitInDefaultParams();
2490 this.yieldPos = oldYieldPos;
2491 this.awaitPos = oldAwaitPos;
2492 return this.parseParenArrowList(startPos, startLoc, exprList)
2493 }
2494
2495 if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
2496 if (spreadStart) { this.unexpected(spreadStart); }
2497 this.checkExpressionErrors(refDestructuringErrors, true);
2498 this.yieldPos = oldYieldPos || this.yieldPos;
2499 this.awaitPos = oldAwaitPos || this.awaitPos;
2500
2501 if (exprList.length > 1) {
2502 val = this.startNodeAt(innerStartPos, innerStartLoc);
2503 val.expressions = exprList;
2504 this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
2505 } else {
2506 val = exprList[0];
2507 }
2508 } else {
2509 val = this.parseParenExpression();
2510 }
2511
2512 if (this.options.preserveParens) {
2513 var par = this.startNodeAt(startPos, startLoc);
2514 par.expression = val;
2515 return this.finishNode(par, "ParenthesizedExpression")
2516 } else {
2517 return val
2518 }
2519 };
2520
2521 pp$3.parseParenItem = function(item) {
2522 return item
2523 };
2524
2525 pp$3.parseParenArrowList = function(startPos, startLoc, exprList) {
2526 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)
2527 };
2528
2529 // New's precedence is slightly tricky. It must allow its argument to
2530 // be a `[]` or dot subscript expression, but not a call — at least,
2531 // not without wrapping it in parentheses. Thus, it uses the noCalls
2532 // argument to parseSubscripts to prevent it from consuming the
2533 // argument list.
2534
2535 var empty$1 = [];
2536
2537 pp$3.parseNew = function() {
2538 if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); }
2539 var node = this.startNode();
2540 var meta = this.parseIdent(true);
2541 if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) {
2542 node.meta = meta;
2543 var containsEsc = this.containsEsc;
2544 node.property = this.parseIdent(true);
2545 if (node.property.name !== "target")
2546 { this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); }
2547 if (containsEsc)
2548 { this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); }
2549 if (!this.inNonArrowFunction())
2550 { this.raiseRecoverable(node.start, "'new.target' can only be used in functions"); }
2551 return this.finishNode(node, "MetaProperty")
2552 }
2553 var startPos = this.start, startLoc = this.startLoc, isImport = this.type === types._import;
2554 node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
2555 if (isImport && node.callee.type === "ImportExpression") {
2556 this.raise(startPos, "Cannot use new with import()");
2557 }
2558 if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); }
2559 else { node.arguments = empty$1; }
2560 return this.finishNode(node, "NewExpression")
2561 };
2562
2563 // Parse template expression.
2564
2565 pp$3.parseTemplateElement = function(ref) {
2566 var isTagged = ref.isTagged;
2567
2568 var elem = this.startNode();
2569 if (this.type === types.invalidTemplate) {
2570 if (!isTagged) {
2571 this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
2572 }
2573 elem.value = {
2574 raw: this.value,
2575 cooked: null
2576 };
2577 } else {
2578 elem.value = {
2579 raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
2580 cooked: this.value
2581 };
2582 }
2583 this.next();
2584 elem.tail = this.type === types.backQuote;
2585 return this.finishNode(elem, "TemplateElement")
2586 };
2587
2588 pp$3.parseTemplate = function(ref) {
2589 if ( ref === void 0 ) ref = {};
2590 var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;
2591
2592 var node = this.startNode();
2593 this.next();
2594 node.expressions = [];
2595 var curElt = this.parseTemplateElement({isTagged: isTagged});
2596 node.quasis = [curElt];
2597 while (!curElt.tail) {
2598 if (this.type === types.eof) { this.raise(this.pos, "Unterminated template literal"); }
2599 this.expect(types.dollarBraceL);
2600 node.expressions.push(this.parseExpression());
2601 this.expect(types.braceR);
2602 node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged}));
2603 }
2604 this.next();
2605 return this.finishNode(node, "TemplateLiteral")
2606 };
2607
2608 pp$3.isAsyncProp = function(prop) {
2609 return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
2610 (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)) &&
2611 !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
2612 };
2613
2614 // Parse an object literal or binding pattern.
2615
2616 pp$3.parseObj = function(isPattern, refDestructuringErrors) {
2617 var node = this.startNode(), first = true, propHash = {};
2618 node.properties = [];
2619 this.next();
2620 while (!this.eat(types.braceR)) {
2621 if (!first) {
2622 this.expect(types.comma);
2623 if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types.braceR)) { break }
2624 } else { first = false; }
2625
2626 var prop = this.parseProperty(isPattern, refDestructuringErrors);
2627 if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); }
2628 node.properties.push(prop);
2629 }
2630 return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
2631 };
2632
2633 pp$3.parseProperty = function(isPattern, refDestructuringErrors) {
2634 var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
2635 if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) {
2636 if (isPattern) {
2637 prop.argument = this.parseIdent(false);
2638 if (this.type === types.comma) {
2639 this.raise(this.start, "Comma is not permitted after the rest element");
2640 }
2641 return this.finishNode(prop, "RestElement")
2642 }
2643 // To disallow parenthesized identifier via `this.toAssignable()`.
2644 if (this.type === types.parenL && refDestructuringErrors) {
2645 if (refDestructuringErrors.parenthesizedAssign < 0) {
2646 refDestructuringErrors.parenthesizedAssign = this.start;
2647 }
2648 if (refDestructuringErrors.parenthesizedBind < 0) {
2649 refDestructuringErrors.parenthesizedBind = this.start;
2650 }
2651 }
2652 // Parse argument.
2653 prop.argument = this.parseMaybeAssign(false, refDestructuringErrors);
2654 // To disallow trailing comma via `this.toAssignable()`.
2655 if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
2656 refDestructuringErrors.trailingComma = this.start;
2657 }
2658 // Finish
2659 return this.finishNode(prop, "SpreadElement")
2660 }
2661 if (this.options.ecmaVersion >= 6) {
2662 prop.method = false;
2663 prop.shorthand = false;
2664 if (isPattern || refDestructuringErrors) {
2665 startPos = this.start;
2666 startLoc = this.startLoc;
2667 }
2668 if (!isPattern)
2669 { isGenerator = this.eat(types.star); }
2670 }
2671 var containsEsc = this.containsEsc;
2672 this.parsePropertyName(prop);
2673 if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
2674 isAsync = true;
2675 isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
2676 this.parsePropertyName(prop, refDestructuringErrors);
2677 } else {
2678 isAsync = false;
2679 }
2680 this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
2681 return this.finishNode(prop, "Property")
2682 };
2683
2684 pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
2685 if ((isGenerator || isAsync) && this.type === types.colon)
2686 { this.unexpected(); }
2687
2688 if (this.eat(types.colon)) {
2689 prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
2690 prop.kind = "init";
2691 } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) {
2692 if (isPattern) { this.unexpected(); }
2693 prop.kind = "init";
2694 prop.method = true;
2695 prop.value = this.parseMethod(isGenerator, isAsync);
2696 } else if (!isPattern && !containsEsc &&
2697 this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
2698 (prop.key.name === "get" || prop.key.name === "set") &&
2699 (this.type !== types.comma && this.type !== types.braceR && this.type !== types.eq)) {
2700 if (isGenerator || isAsync) { this.unexpected(); }
2701 prop.kind = prop.key.name;
2702 this.parsePropertyName(prop);
2703 prop.value = this.parseMethod(false);
2704 var paramCount = prop.kind === "get" ? 0 : 1;
2705 if (prop.value.params.length !== paramCount) {
2706 var start = prop.value.start;
2707 if (prop.kind === "get")
2708 { this.raiseRecoverable(start, "getter should have no params"); }
2709 else
2710 { this.raiseRecoverable(start, "setter should have exactly one param"); }
2711 } else {
2712 if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
2713 { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
2714 }
2715 } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
2716 if (isGenerator || isAsync) { this.unexpected(); }
2717 this.checkUnreserved(prop.key);
2718 if (prop.key.name === "await" && !this.awaitIdentPos)
2719 { this.awaitIdentPos = startPos; }
2720 prop.kind = "init";
2721 if (isPattern) {
2722 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
2723 } else if (this.type === types.eq && refDestructuringErrors) {
2724 if (refDestructuringErrors.shorthandAssign < 0)
2725 { refDestructuringErrors.shorthandAssign = this.start; }
2726 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
2727 } else {
2728 prop.value = prop.key;
2729 }
2730 prop.shorthand = true;
2731 } else { this.unexpected(); }
2732 };
2733
2734 pp$3.parsePropertyName = function(prop) {
2735 if (this.options.ecmaVersion >= 6) {
2736 if (this.eat(types.bracketL)) {
2737 prop.computed = true;
2738 prop.key = this.parseMaybeAssign();
2739 this.expect(types.bracketR);
2740 return prop.key
2741 } else {
2742 prop.computed = false;
2743 }
2744 }
2745 return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never")
2746 };
2747
2748 // Initialize empty function node.
2749
2750 pp$3.initFunction = function(node) {
2751 node.id = null;
2752 if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; }
2753 if (this.options.ecmaVersion >= 8) { node.async = false; }
2754 };
2755
2756 // Parse object or class method.
2757
2758 pp$3.parseMethod = function(isGenerator, isAsync, allowDirectSuper) {
2759 var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2760
2761 this.initFunction(node);
2762 if (this.options.ecmaVersion >= 6)
2763 { node.generator = isGenerator; }
2764 if (this.options.ecmaVersion >= 8)
2765 { node.async = !!isAsync; }
2766
2767 this.yieldPos = 0;
2768 this.awaitPos = 0;
2769 this.awaitIdentPos = 0;
2770 this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0));
2771
2772 this.expect(types.parenL);
2773 node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
2774 this.checkYieldAwaitInDefaultParams();
2775 this.parseFunctionBody(node, false, true);
2776
2777 this.yieldPos = oldYieldPos;
2778 this.awaitPos = oldAwaitPos;
2779 this.awaitIdentPos = oldAwaitIdentPos;
2780 return this.finishNode(node, "FunctionExpression")
2781 };
2782
2783 // Parse arrow function expression with given parameters.
2784
2785 pp$3.parseArrowExpression = function(node, params, isAsync) {
2786 var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2787
2788 this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW);
2789 this.initFunction(node);
2790 if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; }
2791
2792 this.yieldPos = 0;
2793 this.awaitPos = 0;
2794 this.awaitIdentPos = 0;
2795
2796 node.params = this.toAssignableList(params, true);
2797 this.parseFunctionBody(node, true, false);
2798
2799 this.yieldPos = oldYieldPos;
2800 this.awaitPos = oldAwaitPos;
2801 this.awaitIdentPos = oldAwaitIdentPos;
2802 return this.finishNode(node, "ArrowFunctionExpression")
2803 };
2804
2805 // Parse function body and check parameters.
2806
2807 pp$3.parseFunctionBody = function(node, isArrowFunction, isMethod) {
2808 var isExpression = isArrowFunction && this.type !== types.braceL;
2809 var oldStrict = this.strict, useStrict = false;
2810
2811 if (isExpression) {
2812 node.body = this.parseMaybeAssign();
2813 node.expression = true;
2814 this.checkParams(node, false);
2815 } else {
2816 var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
2817 if (!oldStrict || nonSimple) {
2818 useStrict = this.strictDirective(this.end);
2819 // If this is a strict mode function, verify that argument names
2820 // are not repeated, and it does not try to bind the words `eval`
2821 // or `arguments`.
2822 if (useStrict && nonSimple)
2823 { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
2824 }
2825 // Start a new scope with regard to labels and the `inFunction`
2826 // flag (restore them to their old value afterwards).
2827 var oldLabels = this.labels;
2828 this.labels = [];
2829 if (useStrict) { this.strict = true; }
2830
2831 // Add the params to varDeclaredNames to ensure that an error is thrown
2832 // if a let/const declaration in the function clashes with one of the params.
2833 this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params));
2834 // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
2835 if (this.strict && node.id) { this.checkLVal(node.id, BIND_OUTSIDE); }
2836 node.body = this.parseBlock(false, undefined, useStrict && !oldStrict);
2837 node.expression = false;
2838 this.adaptDirectivePrologue(node.body.body);
2839 this.labels = oldLabels;
2840 }
2841 this.exitScope();
2842 };
2843
2844 pp$3.isSimpleParamList = function(params) {
2845 for (var i = 0, list = params; i < list.length; i += 1)
2846 {
2847 var param = list[i];
2848
2849 if (param.type !== "Identifier") { return false
2850 } }
2851 return true
2852 };
2853
2854 // Checks function params for various disallowed patterns such as using "eval"
2855 // or "arguments" and duplicate parameters.
2856
2857 pp$3.checkParams = function(node, allowDuplicates) {
2858 var nameHash = {};
2859 for (var i = 0, list = node.params; i < list.length; i += 1)
2860 {
2861 var param = list[i];
2862
2863 this.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash);
2864 }
2865 };
2866
2867 // Parses a comma-separated list of expressions, and returns them as
2868 // an array. `close` is the token type that ends the list, and
2869 // `allowEmpty` can be turned on to allow subsequent commas with
2870 // nothing in between them to be parsed as `null` (which is needed
2871 // for array literals).
2872
2873 pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
2874 var elts = [], first = true;
2875 while (!this.eat(close)) {
2876 if (!first) {
2877 this.expect(types.comma);
2878 if (allowTrailingComma && this.afterTrailingComma(close)) { break }
2879 } else { first = false; }
2880
2881 var elt = (void 0);
2882 if (allowEmpty && this.type === types.comma)
2883 { elt = null; }
2884 else if (this.type === types.ellipsis) {
2885 elt = this.parseSpread(refDestructuringErrors);
2886 if (refDestructuringErrors && this.type === types.comma && refDestructuringErrors.trailingComma < 0)
2887 { refDestructuringErrors.trailingComma = this.start; }
2888 } else {
2889 elt = this.parseMaybeAssign(false, refDestructuringErrors);
2890 }
2891 elts.push(elt);
2892 }
2893 return elts
2894 };
2895
2896 pp$3.checkUnreserved = function(ref) {
2897 var start = ref.start;
2898 var end = ref.end;
2899 var name = ref.name;
2900
2901 if (this.inGenerator && name === "yield")
2902 { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); }
2903 if (this.inAsync && name === "await")
2904 { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); }
2905 if (this.keywords.test(name))
2906 { this.raise(start, ("Unexpected keyword '" + name + "'")); }
2907 if (this.options.ecmaVersion < 6 &&
2908 this.input.slice(start, end).indexOf("\\") !== -1) { return }
2909 var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
2910 if (re.test(name)) {
2911 if (!this.inAsync && name === "await")
2912 { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); }
2913 this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved"));
2914 }
2915 };
2916
2917 // Parse the next token as an identifier. If `liberal` is true (used
2918 // when parsing properties), it will also convert keywords into
2919 // identifiers.
2920
2921 pp$3.parseIdent = function(liberal, isBinding) {
2922 var node = this.startNode();
2923 if (this.type === types.name) {
2924 node.name = this.value;
2925 } else if (this.type.keyword) {
2926 node.name = this.type.keyword;
2927
2928 // To fix https://github.com/acornjs/acorn/issues/575
2929 // `class` and `function` keywords push new context into this.context.
2930 // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
2931 // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
2932 if ((node.name === "class" || node.name === "function") &&
2933 (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
2934 this.context.pop();
2935 }
2936 } else {
2937 this.unexpected();
2938 }
2939 this.next(!!liberal);
2940 this.finishNode(node, "Identifier");
2941 if (!liberal) {
2942 this.checkUnreserved(node);
2943 if (node.name === "await" && !this.awaitIdentPos)
2944 { this.awaitIdentPos = node.start; }
2945 }
2946 return node
2947 };
2948
2949 // Parses yield expression inside generator.
2950
2951 pp$3.parseYield = function(noIn) {
2952 if (!this.yieldPos) { this.yieldPos = this.start; }
2953
2954 var node = this.startNode();
2955 this.next();
2956 if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) {
2957 node.delegate = false;
2958 node.argument = null;
2959 } else {
2960 node.delegate = this.eat(types.star);
2961 node.argument = this.parseMaybeAssign(noIn);
2962 }
2963 return this.finishNode(node, "YieldExpression")
2964 };
2965
2966 pp$3.parseAwait = function() {
2967 if (!this.awaitPos) { this.awaitPos = this.start; }
2968
2969 var node = this.startNode();
2970 this.next();
2971 node.argument = this.parseMaybeUnary(null, false);
2972 return this.finishNode(node, "AwaitExpression")
2973 };
2974
2975 var pp$4 = Parser.prototype;
2976
2977 // This function is used to raise exceptions on parse errors. It
2978 // takes an offset integer (into the current `input`) to indicate
2979 // the location of the error, attaches the position to the end
2980 // of the error message, and then raises a `SyntaxError` with that
2981 // message.
2982
2983 pp$4.raise = function(pos, message) {
2984 var loc = getLineInfo(this.input, pos);
2985 message += " (" + loc.line + ":" + loc.column + ")";
2986 var err = new SyntaxError(message);
2987 err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
2988 throw err
2989 };
2990
2991 pp$4.raiseRecoverable = pp$4.raise;
2992
2993 pp$4.curPosition = function() {
2994 if (this.options.locations) {
2995 return new Position(this.curLine, this.pos - this.lineStart)
2996 }
2997 };
2998
2999 var pp$5 = Parser.prototype;
3000
3001 var Scope = function Scope(flags) {
3002 this.flags = flags;
3003 // A list of var-declared names in the current lexical scope
3004 this.var = [];
3005 // A list of lexically-declared names in the current lexical scope
3006 this.lexical = [];
3007 // A list of lexically-declared FunctionDeclaration names in the current lexical scope
3008 this.functions = [];
3009 };
3010
3011 // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.
3012
3013 pp$5.enterScope = function(flags) {
3014 this.scopeStack.push(new Scope(flags));
3015 };
3016
3017 pp$5.exitScope = function() {
3018 this.scopeStack.pop();
3019 };
3020
3021 // The spec says:
3022 // > At the top level of a function, or script, function declarations are
3023 // > treated like var declarations rather than like lexical declarations.
3024 pp$5.treatFunctionsAsVarInScope = function(scope) {
3025 return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP)
3026 };
3027
3028 pp$5.declareName = function(name, bindingType, pos) {
3029 var redeclared = false;
3030 if (bindingType === BIND_LEXICAL) {
3031 var scope = this.currentScope();
3032 redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
3033 scope.lexical.push(name);
3034 if (this.inModule && (scope.flags & SCOPE_TOP))
3035 { delete this.undefinedExports[name]; }
3036 } else if (bindingType === BIND_SIMPLE_CATCH) {
3037 var scope$1 = this.currentScope();
3038 scope$1.lexical.push(name);
3039 } else if (bindingType === BIND_FUNCTION) {
3040 var scope$2 = this.currentScope();
3041 if (this.treatFunctionsAsVar)
3042 { redeclared = scope$2.lexical.indexOf(name) > -1; }
3043 else
3044 { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; }
3045 scope$2.functions.push(name);
3046 } else {
3047 for (var i = this.scopeStack.length - 1; i >= 0; --i) {
3048 var scope$3 = this.scopeStack[i];
3049 if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) ||
3050 !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) {
3051 redeclared = true;
3052 break
3053 }
3054 scope$3.var.push(name);
3055 if (this.inModule && (scope$3.flags & SCOPE_TOP))
3056 { delete this.undefinedExports[name]; }
3057 if (scope$3.flags & SCOPE_VAR) { break }
3058 }
3059 }
3060 if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); }
3061 };
3062
3063 pp$5.checkLocalExport = function(id) {
3064 // scope.functions must be empty as Module code is always strict.
3065 if (this.scopeStack[0].lexical.indexOf(id.name) === -1 &&
3066 this.scopeStack[0].var.indexOf(id.name) === -1) {
3067 this.undefinedExports[id.name] = id;
3068 }
3069 };
3070
3071 pp$5.currentScope = function() {
3072 return this.scopeStack[this.scopeStack.length - 1]
3073 };
3074
3075 pp$5.currentVarScope = function() {
3076 for (var i = this.scopeStack.length - 1;; i--) {
3077 var scope = this.scopeStack[i];
3078 if (scope.flags & SCOPE_VAR) { return scope }
3079 }
3080 };
3081
3082 // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
3083 pp$5.currentThisScope = function() {
3084 for (var i = this.scopeStack.length - 1;; i--) {
3085 var scope = this.scopeStack[i];
3086 if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) { return scope }
3087 }
3088 };
3089
3090 var Node = function Node(parser, pos, loc) {
3091 this.type = "";
3092 this.start = pos;
3093 this.end = 0;
3094 if (parser.options.locations)
3095 { this.loc = new SourceLocation(parser, loc); }
3096 if (parser.options.directSourceFile)
3097 { this.sourceFile = parser.options.directSourceFile; }
3098 if (parser.options.ranges)
3099 { this.range = [pos, 0]; }
3100 };
3101
3102 // Start an AST node, attaching a start offset.
3103
3104 var pp$6 = Parser.prototype;
3105
3106 pp$6.startNode = function() {
3107 return new Node(this, this.start, this.startLoc)
3108 };
3109
3110 pp$6.startNodeAt = function(pos, loc) {
3111 return new Node(this, pos, loc)
3112 };
3113
3114 // Finish an AST node, adding `type` and `end` properties.
3115
3116 function finishNodeAt(node, type, pos, loc) {
3117 node.type = type;
3118 node.end = pos;
3119 if (this.options.locations)
3120 { node.loc.end = loc; }
3121 if (this.options.ranges)
3122 { node.range[1] = pos; }
3123 return node
3124 }
3125
3126 pp$6.finishNode = function(node, type) {
3127 return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
3128 };
3129
3130 // Finish node at given position
3131
3132 pp$6.finishNodeAt = function(node, type, pos, loc) {
3133 return finishNodeAt.call(this, node, type, pos, loc)
3134 };
3135
3136 // The algorithm used to determine whether a regexp can appear at a
3137
3138 var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
3139 this.token = token;
3140 this.isExpr = !!isExpr;
3141 this.preserveSpace = !!preserveSpace;
3142 this.override = override;
3143 this.generator = !!generator;
3144 };
3145
3146 var types$1 = {
3147 b_stat: new TokContext("{", false),
3148 b_expr: new TokContext("{", true),
3149 b_tmpl: new TokContext("${", false),
3150 p_stat: new TokContext("(", false),
3151 p_expr: new TokContext("(", true),
3152 q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
3153 f_stat: new TokContext("function", false),
3154 f_expr: new TokContext("function", true),
3155 f_expr_gen: new TokContext("function", true, false, null, true),
3156 f_gen: new TokContext("function", false, false, null, true)
3157 };
3158
3159 var pp$7 = Parser.prototype;
3160
3161 pp$7.initialContext = function() {
3162 return [types$1.b_stat]
3163 };
3164
3165 pp$7.braceIsBlock = function(prevType) {
3166 var parent = this.curContext();
3167 if (parent === types$1.f_expr || parent === types$1.f_stat)
3168 { return true }
3169 if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr))
3170 { return !parent.isExpr }
3171
3172 // The check for `tt.name && exprAllowed` detects whether we are
3173 // after a `yield` or `of` construct. See the `updateContext` for
3174 // `tt.name`.
3175 if (prevType === types._return || prevType === types.name && this.exprAllowed)
3176 { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
3177 if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow)
3178 { return true }
3179 if (prevType === types.braceL)
3180 { return parent === types$1.b_stat }
3181 if (prevType === types._var || prevType === types._const || prevType === types.name)
3182 { return false }
3183 return !this.exprAllowed
3184 };
3185
3186 pp$7.inGeneratorContext = function() {
3187 for (var i = this.context.length - 1; i >= 1; i--) {
3188 var context = this.context[i];
3189 if (context.token === "function")
3190 { return context.generator }
3191 }
3192 return false
3193 };
3194
3195 pp$7.updateContext = function(prevType) {
3196 var update, type = this.type;
3197 if (type.keyword && prevType === types.dot)
3198 { this.exprAllowed = false; }
3199 else if (update = type.updateContext)
3200 { update.call(this, prevType); }
3201 else
3202 { this.exprAllowed = type.beforeExpr; }
3203 };
3204
3205 // Token-specific context update code
3206
3207 types.parenR.updateContext = types.braceR.updateContext = function() {
3208 if (this.context.length === 1) {
3209 this.exprAllowed = true;
3210 return
3211 }
3212 var out = this.context.pop();
3213 if (out === types$1.b_stat && this.curContext().token === "function") {
3214 out = this.context.pop();
3215 }
3216 this.exprAllowed = !out.isExpr;
3217 };
3218
3219 types.braceL.updateContext = function(prevType) {
3220 this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr);
3221 this.exprAllowed = true;
3222 };
3223
3224 types.dollarBraceL.updateContext = function() {
3225 this.context.push(types$1.b_tmpl);
3226 this.exprAllowed = true;
3227 };
3228
3229 types.parenL.updateContext = function(prevType) {
3230 var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while;
3231 this.context.push(statementParens ? types$1.p_stat : types$1.p_expr);
3232 this.exprAllowed = true;
3233 };
3234
3235 types.incDec.updateContext = function() {
3236 // tokExprAllowed stays unchanged
3237 };
3238
3239 types._function.updateContext = types._class.updateContext = function(prevType) {
3240 if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else &&
3241 !(prevType === types._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) &&
3242 !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat))
3243 { this.context.push(types$1.f_expr); }
3244 else
3245 { this.context.push(types$1.f_stat); }
3246 this.exprAllowed = false;
3247 };
3248
3249 types.backQuote.updateContext = function() {
3250 if (this.curContext() === types$1.q_tmpl)
3251 { this.context.pop(); }
3252 else
3253 { this.context.push(types$1.q_tmpl); }
3254 this.exprAllowed = false;
3255 };
3256
3257 types.star.updateContext = function(prevType) {
3258 if (prevType === types._function) {
3259 var index = this.context.length - 1;
3260 if (this.context[index] === types$1.f_expr)
3261 { this.context[index] = types$1.f_expr_gen; }
3262 else
3263 { this.context[index] = types$1.f_gen; }
3264 }
3265 this.exprAllowed = true;
3266 };
3267
3268 types.name.updateContext = function(prevType) {
3269 var allowed = false;
3270 if (this.options.ecmaVersion >= 6 && prevType !== types.dot) {
3271 if (this.value === "of" && !this.exprAllowed ||
3272 this.value === "yield" && this.inGeneratorContext())
3273 { allowed = true; }
3274 }
3275 this.exprAllowed = allowed;
3276 };
3277
3278 // This file contains Unicode properties extracted from the ECMAScript
3279 // specification. The lists are extracted like so:
3280 // $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText)
3281
3282 // #table-binary-unicode-properties
3283 var 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";
3284 var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic";
3285 var ecma11BinaryProperties = ecma10BinaryProperties;
3286 var unicodeBinaryProperties = {
3287 9: ecma9BinaryProperties,
3288 10: ecma10BinaryProperties,
3289 11: ecma11BinaryProperties
3290 };
3291
3292 // #table-unicode-general-category-values
3293 var 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";
3294
3295 // #table-unicode-script-values
3296 var 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";
3297 var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd";
3298 var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho";
3299 var unicodeScriptValues = {
3300 9: ecma9ScriptValues,
3301 10: ecma10ScriptValues,
3302 11: ecma11ScriptValues
3303 };
3304
3305 var data = {};
3306 function buildUnicodeData(ecmaVersion) {
3307 var d = data[ecmaVersion] = {
3308 binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues),
3309 nonBinary: {
3310 General_Category: wordsRegexp(unicodeGeneralCategoryValues),
3311 Script: wordsRegexp(unicodeScriptValues[ecmaVersion])
3312 }
3313 };
3314 d.nonBinary.Script_Extensions = d.nonBinary.Script;
3315
3316 d.nonBinary.gc = d.nonBinary.General_Category;
3317 d.nonBinary.sc = d.nonBinary.Script;
3318 d.nonBinary.scx = d.nonBinary.Script_Extensions;
3319 }
3320 buildUnicodeData(9);
3321 buildUnicodeData(10);
3322 buildUnicodeData(11);
3323
3324 var pp$8 = Parser.prototype;
3325
3326 var RegExpValidationState = function RegExpValidationState(parser) {
3327 this.parser = parser;
3328 this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "");
3329 this.unicodeProperties = data[parser.options.ecmaVersion >= 11 ? 11 : parser.options.ecmaVersion];
3330 this.source = "";
3331 this.flags = "";
3332 this.start = 0;
3333 this.switchU = false;
3334 this.switchN = false;
3335 this.pos = 0;
3336 this.lastIntValue = 0;
3337 this.lastStringValue = "";
3338 this.lastAssertionIsQuantifiable = false;
3339 this.numCapturingParens = 0;
3340 this.maxBackReference = 0;
3341 this.groupNames = [];
3342 this.backReferenceNames = [];
3343 };
3344
3345 RegExpValidationState.prototype.reset = function reset (start, pattern, flags) {
3346 var unicode = flags.indexOf("u") !== -1;
3347 this.start = start | 0;
3348 this.source = pattern + "";
3349 this.flags = flags;
3350 this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
3351 this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
3352 };
3353
3354 RegExpValidationState.prototype.raise = function raise (message) {
3355 this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message));
3356 };
3357
3358 // If u flag is given, this returns the code point at the index (it combines a surrogate pair).
3359 // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
3360 RegExpValidationState.prototype.at = function at (i, forceU) {
3361 if ( forceU === void 0 ) forceU = false;
3362
3363 var s = this.source;
3364 var l = s.length;
3365 if (i >= l) {
3366 return -1
3367 }
3368 var c = s.charCodeAt(i);
3369 if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
3370 return c
3371 }
3372 var next = s.charCodeAt(i + 1);
3373 return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c
3374 };
3375
3376 RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) {
3377 if ( forceU === void 0 ) forceU = false;
3378
3379 var s = this.source;
3380 var l = s.length;
3381 if (i >= l) {
3382 return l
3383 }
3384 var c = s.charCodeAt(i), next;
3385 if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l ||
3386 (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) {
3387 return i + 1
3388 }
3389 return i + 2
3390 };
3391
3392 RegExpValidationState.prototype.current = function current (forceU) {
3393 if ( forceU === void 0 ) forceU = false;
3394
3395 return this.at(this.pos, forceU)
3396 };
3397
3398 RegExpValidationState.prototype.lookahead = function lookahead (forceU) {
3399 if ( forceU === void 0 ) forceU = false;
3400
3401 return this.at(this.nextIndex(this.pos, forceU), forceU)
3402 };
3403
3404 RegExpValidationState.prototype.advance = function advance (forceU) {
3405 if ( forceU === void 0 ) forceU = false;
3406
3407 this.pos = this.nextIndex(this.pos, forceU);
3408 };
3409
3410 RegExpValidationState.prototype.eat = function eat (ch, forceU) {
3411 if ( forceU === void 0 ) forceU = false;
3412
3413 if (this.current(forceU) === ch) {
3414 this.advance(forceU);
3415 return true
3416 }
3417 return false
3418 };
3419
3420 function codePointToString(ch) {
3421 if (ch <= 0xFFFF) { return String.fromCharCode(ch) }
3422 ch -= 0x10000;
3423 return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00)
3424 }
3425
3426 /**
3427 * Validate the flags part of a given RegExpLiteral.
3428 *
3429 * @param {RegExpValidationState} state The state to validate RegExp.
3430 * @returns {void}
3431 */
3432 pp$8.validateRegExpFlags = function(state) {
3433 var validFlags = state.validFlags;
3434 var flags = state.flags;
3435
3436 for (var i = 0; i < flags.length; i++) {
3437 var flag = flags.charAt(i);
3438 if (validFlags.indexOf(flag) === -1) {
3439 this.raise(state.start, "Invalid regular expression flag");
3440 }
3441 if (flags.indexOf(flag, i + 1) > -1) {
3442 this.raise(state.start, "Duplicate regular expression flag");
3443 }
3444 }
3445 };
3446
3447 /**
3448 * Validate the pattern part of a given RegExpLiteral.
3449 *
3450 * @param {RegExpValidationState} state The state to validate RegExp.
3451 * @returns {void}
3452 */
3453 pp$8.validateRegExpPattern = function(state) {
3454 this.regexp_pattern(state);
3455
3456 // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
3457 // parsing contains a |GroupName|, reparse with the goal symbol
3458 // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
3459 // exception if _P_ did not conform to the grammar, if any elements of _P_
3460 // were not matched by the parse, or if any Early Error conditions exist.
3461 if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) {
3462 state.switchN = true;
3463 this.regexp_pattern(state);
3464 }
3465 };
3466
3467 // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
3468 pp$8.regexp_pattern = function(state) {
3469 state.pos = 0;
3470 state.lastIntValue = 0;
3471 state.lastStringValue = "";
3472 state.lastAssertionIsQuantifiable = false;
3473 state.numCapturingParens = 0;
3474 state.maxBackReference = 0;
3475 state.groupNames.length = 0;
3476 state.backReferenceNames.length = 0;
3477
3478 this.regexp_disjunction(state);
3479
3480 if (state.pos !== state.source.length) {
3481 // Make the same messages as V8.
3482 if (state.eat(0x29 /* ) */)) {
3483 state.raise("Unmatched ')'");
3484 }
3485 if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) {
3486 state.raise("Lone quantifier brackets");
3487 }
3488 }
3489 if (state.maxBackReference > state.numCapturingParens) {
3490 state.raise("Invalid escape");
3491 }
3492 for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) {
3493 var name = list[i];
3494
3495 if (state.groupNames.indexOf(name) === -1) {
3496 state.raise("Invalid named capture referenced");
3497 }
3498 }
3499 };
3500
3501 // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
3502 pp$8.regexp_disjunction = function(state) {
3503 this.regexp_alternative(state);
3504 while (state.eat(0x7C /* | */)) {
3505 this.regexp_alternative(state);
3506 }
3507
3508 // Make the same message as V8.
3509 if (this.regexp_eatQuantifier(state, true)) {
3510 state.raise("Nothing to repeat");
3511 }
3512 if (state.eat(0x7B /* { */)) {
3513 state.raise("Lone quantifier brackets");
3514 }
3515 };
3516
3517 // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
3518 pp$8.regexp_alternative = function(state) {
3519 while (state.pos < state.source.length && this.regexp_eatTerm(state))
3520 { }
3521 };
3522
3523 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
3524 pp$8.regexp_eatTerm = function(state) {
3525 if (this.regexp_eatAssertion(state)) {
3526 // Handle `QuantifiableAssertion Quantifier` alternative.
3527 // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
3528 // is a QuantifiableAssertion.
3529 if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
3530 // Make the same message as V8.
3531 if (state.switchU) {
3532 state.raise("Invalid quantifier");
3533 }
3534 }
3535 return true
3536 }
3537
3538 if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
3539 this.regexp_eatQuantifier(state);
3540 return true
3541 }
3542
3543 return false
3544 };
3545
3546 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
3547 pp$8.regexp_eatAssertion = function(state) {
3548 var start = state.pos;
3549 state.lastAssertionIsQuantifiable = false;
3550
3551 // ^, $
3552 if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) {
3553 return true
3554 }
3555
3556 // \b \B
3557 if (state.eat(0x5C /* \ */)) {
3558 if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) {
3559 return true
3560 }
3561 state.pos = start;
3562 }
3563
3564 // Lookahead / Lookbehind
3565 if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) {
3566 var lookbehind = false;
3567 if (this.options.ecmaVersion >= 9) {
3568 lookbehind = state.eat(0x3C /* < */);
3569 }
3570 if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) {
3571 this.regexp_disjunction(state);
3572 if (!state.eat(0x29 /* ) */)) {
3573 state.raise("Unterminated group");
3574 }
3575 state.lastAssertionIsQuantifiable = !lookbehind;
3576 return true
3577 }
3578 }
3579
3580 state.pos = start;
3581 return false
3582 };
3583
3584 // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
3585 pp$8.regexp_eatQuantifier = function(state, noError) {
3586 if ( noError === void 0 ) noError = false;
3587
3588 if (this.regexp_eatQuantifierPrefix(state, noError)) {
3589 state.eat(0x3F /* ? */);
3590 return true
3591 }
3592 return false
3593 };
3594
3595 // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
3596 pp$8.regexp_eatQuantifierPrefix = function(state, noError) {
3597 return (
3598 state.eat(0x2A /* * */) ||
3599 state.eat(0x2B /* + */) ||
3600 state.eat(0x3F /* ? */) ||
3601 this.regexp_eatBracedQuantifier(state, noError)
3602 )
3603 };
3604 pp$8.regexp_eatBracedQuantifier = function(state, noError) {
3605 var start = state.pos;
3606 if (state.eat(0x7B /* { */)) {
3607 var min = 0, max = -1;
3608 if (this.regexp_eatDecimalDigits(state)) {
3609 min = state.lastIntValue;
3610 if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) {
3611 max = state.lastIntValue;
3612 }
3613 if (state.eat(0x7D /* } */)) {
3614 // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
3615 if (max !== -1 && max < min && !noError) {
3616 state.raise("numbers out of order in {} quantifier");
3617 }
3618 return true
3619 }
3620 }
3621 if (state.switchU && !noError) {
3622 state.raise("Incomplete quantifier");
3623 }
3624 state.pos = start;
3625 }
3626 return false
3627 };
3628
3629 // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
3630 pp$8.regexp_eatAtom = function(state) {
3631 return (
3632 this.regexp_eatPatternCharacters(state) ||
3633 state.eat(0x2E /* . */) ||
3634 this.regexp_eatReverseSolidusAtomEscape(state) ||
3635 this.regexp_eatCharacterClass(state) ||
3636 this.regexp_eatUncapturingGroup(state) ||
3637 this.regexp_eatCapturingGroup(state)
3638 )
3639 };
3640 pp$8.regexp_eatReverseSolidusAtomEscape = function(state) {
3641 var start = state.pos;
3642 if (state.eat(0x5C /* \ */)) {
3643 if (this.regexp_eatAtomEscape(state)) {
3644 return true
3645 }
3646 state.pos = start;
3647 }
3648 return false
3649 };
3650 pp$8.regexp_eatUncapturingGroup = function(state) {
3651 var start = state.pos;
3652 if (state.eat(0x28 /* ( */)) {
3653 if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) {
3654 this.regexp_disjunction(state);
3655 if (state.eat(0x29 /* ) */)) {
3656 return true
3657 }
3658 state.raise("Unterminated group");
3659 }
3660 state.pos = start;
3661 }
3662 return false
3663 };
3664 pp$8.regexp_eatCapturingGroup = function(state) {
3665 if (state.eat(0x28 /* ( */)) {
3666 if (this.options.ecmaVersion >= 9) {
3667 this.regexp_groupSpecifier(state);
3668 } else if (state.current() === 0x3F /* ? */) {
3669 state.raise("Invalid group");
3670 }
3671 this.regexp_disjunction(state);
3672 if (state.eat(0x29 /* ) */)) {
3673 state.numCapturingParens += 1;
3674 return true
3675 }
3676 state.raise("Unterminated group");
3677 }
3678 return false
3679 };
3680
3681 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
3682 pp$8.regexp_eatExtendedAtom = function(state) {
3683 return (
3684 state.eat(0x2E /* . */) ||
3685 this.regexp_eatReverseSolidusAtomEscape(state) ||
3686 this.regexp_eatCharacterClass(state) ||
3687 this.regexp_eatUncapturingGroup(state) ||
3688 this.regexp_eatCapturingGroup(state) ||
3689 this.regexp_eatInvalidBracedQuantifier(state) ||
3690 this.regexp_eatExtendedPatternCharacter(state)
3691 )
3692 };
3693
3694 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
3695 pp$8.regexp_eatInvalidBracedQuantifier = function(state) {
3696 if (this.regexp_eatBracedQuantifier(state, true)) {
3697 state.raise("Nothing to repeat");
3698 }
3699 return false
3700 };
3701
3702 // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
3703 pp$8.regexp_eatSyntaxCharacter = function(state) {
3704 var ch = state.current();
3705 if (isSyntaxCharacter(ch)) {
3706 state.lastIntValue = ch;
3707 state.advance();
3708 return true
3709 }
3710 return false
3711 };
3712 function isSyntaxCharacter(ch) {
3713 return (
3714 ch === 0x24 /* $ */ ||
3715 ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ ||
3716 ch === 0x2E /* . */ ||
3717 ch === 0x3F /* ? */ ||
3718 ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ ||
3719 ch >= 0x7B /* { */ && ch <= 0x7D /* } */
3720 )
3721 }
3722
3723 // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
3724 // But eat eager.
3725 pp$8.regexp_eatPatternCharacters = function(state) {
3726 var start = state.pos;
3727 var ch = 0;
3728 while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
3729 state.advance();
3730 }
3731 return state.pos !== start
3732 };
3733
3734 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
3735 pp$8.regexp_eatExtendedPatternCharacter = function(state) {
3736 var ch = state.current();
3737 if (
3738 ch !== -1 &&
3739 ch !== 0x24 /* $ */ &&
3740 !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) &&
3741 ch !== 0x2E /* . */ &&
3742 ch !== 0x3F /* ? */ &&
3743 ch !== 0x5B /* [ */ &&
3744 ch !== 0x5E /* ^ */ &&
3745 ch !== 0x7C /* | */
3746 ) {
3747 state.advance();
3748 return true
3749 }
3750 return false
3751 };
3752
3753 // GroupSpecifier ::
3754 // [empty]
3755 // `?` GroupName
3756 pp$8.regexp_groupSpecifier = function(state) {
3757 if (state.eat(0x3F /* ? */)) {
3758 if (this.regexp_eatGroupName(state)) {
3759 if (state.groupNames.indexOf(state.lastStringValue) !== -1) {
3760 state.raise("Duplicate capture group name");
3761 }
3762 state.groupNames.push(state.lastStringValue);
3763 return
3764 }
3765 state.raise("Invalid group");
3766 }
3767 };
3768
3769 // GroupName ::
3770 // `<` RegExpIdentifierName `>`
3771 // Note: this updates `state.lastStringValue` property with the eaten name.
3772 pp$8.regexp_eatGroupName = function(state) {
3773 state.lastStringValue = "";
3774 if (state.eat(0x3C /* < */)) {
3775 if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) {
3776 return true
3777 }
3778 state.raise("Invalid capture group name");
3779 }
3780 return false
3781 };
3782
3783 // RegExpIdentifierName ::
3784 // RegExpIdentifierStart
3785 // RegExpIdentifierName RegExpIdentifierPart
3786 // Note: this updates `state.lastStringValue` property with the eaten name.
3787 pp$8.regexp_eatRegExpIdentifierName = function(state) {
3788 state.lastStringValue = "";
3789 if (this.regexp_eatRegExpIdentifierStart(state)) {
3790 state.lastStringValue += codePointToString(state.lastIntValue);
3791 while (this.regexp_eatRegExpIdentifierPart(state)) {
3792 state.lastStringValue += codePointToString(state.lastIntValue);
3793 }
3794 return true
3795 }
3796 return false
3797 };
3798
3799 // RegExpIdentifierStart ::
3800 // UnicodeIDStart
3801 // `$`
3802 // `_`
3803 // `\` RegExpUnicodeEscapeSequence[+U]
3804 pp$8.regexp_eatRegExpIdentifierStart = function(state) {
3805 var start = state.pos;
3806 var forceU = this.options.ecmaVersion >= 11;
3807 var ch = state.current(forceU);
3808 state.advance(forceU);
3809
3810 if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
3811 ch = state.lastIntValue;
3812 }
3813 if (isRegExpIdentifierStart(ch)) {
3814 state.lastIntValue = ch;
3815 return true
3816 }
3817
3818 state.pos = start;
3819 return false
3820 };
3821 function isRegExpIdentifierStart(ch) {
3822 return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */
3823 }
3824
3825 // RegExpIdentifierPart ::
3826 // UnicodeIDContinue
3827 // `$`
3828 // `_`
3829 // `\` RegExpUnicodeEscapeSequence[+U]
3830 // <ZWNJ>
3831 // <ZWJ>
3832 pp$8.regexp_eatRegExpIdentifierPart = function(state) {
3833 var start = state.pos;
3834 var forceU = this.options.ecmaVersion >= 11;
3835 var ch = state.current(forceU);
3836 state.advance(forceU);
3837
3838 if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
3839 ch = state.lastIntValue;
3840 }
3841 if (isRegExpIdentifierPart(ch)) {
3842 state.lastIntValue = ch;
3843 return true
3844 }
3845
3846 state.pos = start;
3847 return false
3848 };
3849 function isRegExpIdentifierPart(ch) {
3850 return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */
3851 }
3852
3853 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
3854 pp$8.regexp_eatAtomEscape = function(state) {
3855 if (
3856 this.regexp_eatBackReference(state) ||
3857 this.regexp_eatCharacterClassEscape(state) ||
3858 this.regexp_eatCharacterEscape(state) ||
3859 (state.switchN && this.regexp_eatKGroupName(state))
3860 ) {
3861 return true
3862 }
3863 if (state.switchU) {
3864 // Make the same message as V8.
3865 if (state.current() === 0x63 /* c */) {
3866 state.raise("Invalid unicode escape");
3867 }
3868 state.raise("Invalid escape");
3869 }
3870 return false
3871 };
3872 pp$8.regexp_eatBackReference = function(state) {
3873 var start = state.pos;
3874 if (this.regexp_eatDecimalEscape(state)) {
3875 var n = state.lastIntValue;
3876 if (state.switchU) {
3877 // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
3878 if (n > state.maxBackReference) {
3879 state.maxBackReference = n;
3880 }
3881 return true
3882 }
3883 if (n <= state.numCapturingParens) {
3884 return true
3885 }
3886 state.pos = start;
3887 }
3888 return false
3889 };
3890 pp$8.regexp_eatKGroupName = function(state) {
3891 if (state.eat(0x6B /* k */)) {
3892 if (this.regexp_eatGroupName(state)) {
3893 state.backReferenceNames.push(state.lastStringValue);
3894 return true
3895 }
3896 state.raise("Invalid named reference");
3897 }
3898 return false
3899 };
3900
3901 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
3902 pp$8.regexp_eatCharacterEscape = function(state) {
3903 return (
3904 this.regexp_eatControlEscape(state) ||
3905 this.regexp_eatCControlLetter(state) ||
3906 this.regexp_eatZero(state) ||
3907 this.regexp_eatHexEscapeSequence(state) ||
3908 this.regexp_eatRegExpUnicodeEscapeSequence(state, false) ||
3909 (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) ||
3910 this.regexp_eatIdentityEscape(state)
3911 )
3912 };
3913 pp$8.regexp_eatCControlLetter = function(state) {
3914 var start = state.pos;
3915 if (state.eat(0x63 /* c */)) {
3916 if (this.regexp_eatControlLetter(state)) {
3917 return true
3918 }
3919 state.pos = start;
3920 }
3921 return false
3922 };
3923 pp$8.regexp_eatZero = function(state) {
3924 if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) {
3925 state.lastIntValue = 0;
3926 state.advance();
3927 return true
3928 }
3929 return false
3930 };
3931
3932 // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
3933 pp$8.regexp_eatControlEscape = function(state) {
3934 var ch = state.current();
3935 if (ch === 0x74 /* t */) {
3936 state.lastIntValue = 0x09; /* \t */
3937 state.advance();
3938 return true
3939 }
3940 if (ch === 0x6E /* n */) {
3941 state.lastIntValue = 0x0A; /* \n */
3942 state.advance();
3943 return true
3944 }
3945 if (ch === 0x76 /* v */) {
3946 state.lastIntValue = 0x0B; /* \v */
3947 state.advance();
3948 return true
3949 }
3950 if (ch === 0x66 /* f */) {
3951 state.lastIntValue = 0x0C; /* \f */
3952 state.advance();
3953 return true
3954 }
3955 if (ch === 0x72 /* r */) {
3956 state.lastIntValue = 0x0D; /* \r */
3957 state.advance();
3958 return true
3959 }
3960 return false
3961 };
3962
3963 // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
3964 pp$8.regexp_eatControlLetter = function(state) {
3965 var ch = state.current();
3966 if (isControlLetter(ch)) {
3967 state.lastIntValue = ch % 0x20;
3968 state.advance();
3969 return true
3970 }
3971 return false
3972 };
3973 function isControlLetter(ch) {
3974 return (
3975 (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) ||
3976 (ch >= 0x61 /* a */ && ch <= 0x7A /* z */)
3977 )
3978 }
3979
3980 // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
3981 pp$8.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) {
3982 if ( forceU === void 0 ) forceU = false;
3983
3984 var start = state.pos;
3985 var switchU = forceU || state.switchU;
3986
3987 if (state.eat(0x75 /* u */)) {
3988 if (this.regexp_eatFixedHexDigits(state, 4)) {
3989 var lead = state.lastIntValue;
3990 if (switchU && lead >= 0xD800 && lead <= 0xDBFF) {
3991 var leadSurrogateEnd = state.pos;
3992 if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) {
3993 var trail = state.lastIntValue;
3994 if (trail >= 0xDC00 && trail <= 0xDFFF) {
3995 state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
3996 return true
3997 }
3998 }
3999 state.pos = leadSurrogateEnd;
4000 state.lastIntValue = lead;
4001 }
4002 return true
4003 }
4004 if (
4005 switchU &&
4006 state.eat(0x7B /* { */) &&
4007 this.regexp_eatHexDigits(state) &&
4008 state.eat(0x7D /* } */) &&
4009 isValidUnicode(state.lastIntValue)
4010 ) {
4011 return true
4012 }
4013 if (switchU) {
4014 state.raise("Invalid unicode escape");
4015 }
4016 state.pos = start;
4017 }
4018
4019 return false
4020 };
4021 function isValidUnicode(ch) {
4022 return ch >= 0 && ch <= 0x10FFFF
4023 }
4024
4025 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
4026 pp$8.regexp_eatIdentityEscape = function(state) {
4027 if (state.switchU) {
4028 if (this.regexp_eatSyntaxCharacter(state)) {
4029 return true
4030 }
4031 if (state.eat(0x2F /* / */)) {
4032 state.lastIntValue = 0x2F; /* / */
4033 return true
4034 }
4035 return false
4036 }
4037
4038 var ch = state.current();
4039 if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) {
4040 state.lastIntValue = ch;
4041 state.advance();
4042 return true
4043 }
4044
4045 return false
4046 };
4047
4048 // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
4049 pp$8.regexp_eatDecimalEscape = function(state) {
4050 state.lastIntValue = 0;
4051 var ch = state.current();
4052 if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) {
4053 do {
4054 state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
4055 state.advance();
4056 } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */)
4057 return true
4058 }
4059 return false
4060 };
4061
4062 // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
4063 pp$8.regexp_eatCharacterClassEscape = function(state) {
4064 var ch = state.current();
4065
4066 if (isCharacterClassEscape(ch)) {
4067 state.lastIntValue = -1;
4068 state.advance();
4069 return true
4070 }
4071
4072 if (
4073 state.switchU &&
4074 this.options.ecmaVersion >= 9 &&
4075 (ch === 0x50 /* P */ || ch === 0x70 /* p */)
4076 ) {
4077 state.lastIntValue = -1;
4078 state.advance();
4079 if (
4080 state.eat(0x7B /* { */) &&
4081 this.regexp_eatUnicodePropertyValueExpression(state) &&
4082 state.eat(0x7D /* } */)
4083 ) {
4084 return true
4085 }
4086 state.raise("Invalid property name");
4087 }
4088
4089 return false
4090 };
4091 function isCharacterClassEscape(ch) {
4092 return (
4093 ch === 0x64 /* d */ ||
4094 ch === 0x44 /* D */ ||
4095 ch === 0x73 /* s */ ||
4096 ch === 0x53 /* S */ ||
4097 ch === 0x77 /* w */ ||
4098 ch === 0x57 /* W */
4099 )
4100 }
4101
4102 // UnicodePropertyValueExpression ::
4103 // UnicodePropertyName `=` UnicodePropertyValue
4104 // LoneUnicodePropertyNameOrValue
4105 pp$8.regexp_eatUnicodePropertyValueExpression = function(state) {
4106 var start = state.pos;
4107
4108 // UnicodePropertyName `=` UnicodePropertyValue
4109 if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) {
4110 var name = state.lastStringValue;
4111 if (this.regexp_eatUnicodePropertyValue(state)) {
4112 var value = state.lastStringValue;
4113 this.regexp_validateUnicodePropertyNameAndValue(state, name, value);
4114 return true
4115 }
4116 }
4117 state.pos = start;
4118
4119 // LoneUnicodePropertyNameOrValue
4120 if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
4121 var nameOrValue = state.lastStringValue;
4122 this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue);
4123 return true
4124 }
4125 return false
4126 };
4127 pp$8.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
4128 if (!has(state.unicodeProperties.nonBinary, name))
4129 { state.raise("Invalid property name"); }
4130 if (!state.unicodeProperties.nonBinary[name].test(value))
4131 { state.raise("Invalid property value"); }
4132 };
4133 pp$8.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
4134 if (!state.unicodeProperties.binary.test(nameOrValue))
4135 { state.raise("Invalid property name"); }
4136 };
4137
4138 // UnicodePropertyName ::
4139 // UnicodePropertyNameCharacters
4140 pp$8.regexp_eatUnicodePropertyName = function(state) {
4141 var ch = 0;
4142 state.lastStringValue = "";
4143 while (isUnicodePropertyNameCharacter(ch = state.current())) {
4144 state.lastStringValue += codePointToString(ch);
4145 state.advance();
4146 }
4147 return state.lastStringValue !== ""
4148 };
4149 function isUnicodePropertyNameCharacter(ch) {
4150 return isControlLetter(ch) || ch === 0x5F /* _ */
4151 }
4152
4153 // UnicodePropertyValue ::
4154 // UnicodePropertyValueCharacters
4155 pp$8.regexp_eatUnicodePropertyValue = function(state) {
4156 var ch = 0;
4157 state.lastStringValue = "";
4158 while (isUnicodePropertyValueCharacter(ch = state.current())) {
4159 state.lastStringValue += codePointToString(ch);
4160 state.advance();
4161 }
4162 return state.lastStringValue !== ""
4163 };
4164 function isUnicodePropertyValueCharacter(ch) {
4165 return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch)
4166 }
4167
4168 // LoneUnicodePropertyNameOrValue ::
4169 // UnicodePropertyValueCharacters
4170 pp$8.regexp_eatLoneUnicodePropertyNameOrValue = function(state) {
4171 return this.regexp_eatUnicodePropertyValue(state)
4172 };
4173
4174 // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
4175 pp$8.regexp_eatCharacterClass = function(state) {
4176 if (state.eat(0x5B /* [ */)) {
4177 state.eat(0x5E /* ^ */);
4178 this.regexp_classRanges(state);
4179 if (state.eat(0x5D /* ] */)) {
4180 return true
4181 }
4182 // Unreachable since it threw "unterminated regular expression" error before.
4183 state.raise("Unterminated character class");
4184 }
4185 return false
4186 };
4187
4188 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
4189 // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
4190 // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
4191 pp$8.regexp_classRanges = function(state) {
4192 while (this.regexp_eatClassAtom(state)) {
4193 var left = state.lastIntValue;
4194 if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) {
4195 var right = state.lastIntValue;
4196 if (state.switchU && (left === -1 || right === -1)) {
4197 state.raise("Invalid character class");
4198 }
4199 if (left !== -1 && right !== -1 && left > right) {
4200 state.raise("Range out of order in character class");
4201 }
4202 }
4203 }
4204 };
4205
4206 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
4207 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
4208 pp$8.regexp_eatClassAtom = function(state) {
4209 var start = state.pos;
4210
4211 if (state.eat(0x5C /* \ */)) {
4212 if (this.regexp_eatClassEscape(state)) {
4213 return true
4214 }
4215 if (state.switchU) {
4216 // Make the same message as V8.
4217 var ch$1 = state.current();
4218 if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
4219 state.raise("Invalid class escape");
4220 }
4221 state.raise("Invalid escape");
4222 }
4223 state.pos = start;
4224 }
4225
4226 var ch = state.current();
4227 if (ch !== 0x5D /* ] */) {
4228 state.lastIntValue = ch;
4229 state.advance();
4230 return true
4231 }
4232
4233 return false
4234 };
4235
4236 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
4237 pp$8.regexp_eatClassEscape = function(state) {
4238 var start = state.pos;
4239
4240 if (state.eat(0x62 /* b */)) {
4241 state.lastIntValue = 0x08; /* <BS> */
4242 return true
4243 }
4244
4245 if (state.switchU && state.eat(0x2D /* - */)) {
4246 state.lastIntValue = 0x2D; /* - */
4247 return true
4248 }
4249
4250 if (!state.switchU && state.eat(0x63 /* c */)) {
4251 if (this.regexp_eatClassControlLetter(state)) {
4252 return true
4253 }
4254 state.pos = start;
4255 }
4256
4257 return (
4258 this.regexp_eatCharacterClassEscape(state) ||
4259 this.regexp_eatCharacterEscape(state)
4260 )
4261 };
4262
4263 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
4264 pp$8.regexp_eatClassControlLetter = function(state) {
4265 var ch = state.current();
4266 if (isDecimalDigit(ch) || ch === 0x5F /* _ */) {
4267 state.lastIntValue = ch % 0x20;
4268 state.advance();
4269 return true
4270 }
4271 return false
4272 };
4273
4274 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
4275 pp$8.regexp_eatHexEscapeSequence = function(state) {
4276 var start = state.pos;
4277 if (state.eat(0x78 /* x */)) {
4278 if (this.regexp_eatFixedHexDigits(state, 2)) {
4279 return true
4280 }
4281 if (state.switchU) {
4282 state.raise("Invalid escape");
4283 }
4284 state.pos = start;
4285 }
4286 return false
4287 };
4288
4289 // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
4290 pp$8.regexp_eatDecimalDigits = function(state) {
4291 var start = state.pos;
4292 var ch = 0;
4293 state.lastIntValue = 0;
4294 while (isDecimalDigit(ch = state.current())) {
4295 state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
4296 state.advance();
4297 }
4298 return state.pos !== start
4299 };
4300 function isDecimalDigit(ch) {
4301 return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */
4302 }
4303
4304 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
4305 pp$8.regexp_eatHexDigits = function(state) {
4306 var start = state.pos;
4307 var ch = 0;
4308 state.lastIntValue = 0;
4309 while (isHexDigit(ch = state.current())) {
4310 state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
4311 state.advance();
4312 }
4313 return state.pos !== start
4314 };
4315 function isHexDigit(ch) {
4316 return (
4317 (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) ||
4318 (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) ||
4319 (ch >= 0x61 /* a */ && ch <= 0x66 /* f */)
4320 )
4321 }
4322 function hexToInt(ch) {
4323 if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) {
4324 return 10 + (ch - 0x41 /* A */)
4325 }
4326 if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) {
4327 return 10 + (ch - 0x61 /* a */)
4328 }
4329 return ch - 0x30 /* 0 */
4330 }
4331
4332 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
4333 // Allows only 0-377(octal) i.e. 0-255(decimal).
4334 pp$8.regexp_eatLegacyOctalEscapeSequence = function(state) {
4335 if (this.regexp_eatOctalDigit(state)) {
4336 var n1 = state.lastIntValue;
4337 if (this.regexp_eatOctalDigit(state)) {
4338 var n2 = state.lastIntValue;
4339 if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
4340 state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
4341 } else {
4342 state.lastIntValue = n1 * 8 + n2;
4343 }
4344 } else {
4345 state.lastIntValue = n1;
4346 }
4347 return true
4348 }
4349 return false
4350 };
4351
4352 // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
4353 pp$8.regexp_eatOctalDigit = function(state) {
4354 var ch = state.current();
4355 if (isOctalDigit(ch)) {
4356 state.lastIntValue = ch - 0x30; /* 0 */
4357 state.advance();
4358 return true
4359 }
4360 state.lastIntValue = 0;
4361 return false
4362 };
4363 function isOctalDigit(ch) {
4364 return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */
4365 }
4366
4367 // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
4368 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
4369 // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
4370 pp$8.regexp_eatFixedHexDigits = function(state, length) {
4371 var start = state.pos;
4372 state.lastIntValue = 0;
4373 for (var i = 0; i < length; ++i) {
4374 var ch = state.current();
4375 if (!isHexDigit(ch)) {
4376 state.pos = start;
4377 return false
4378 }
4379 state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
4380 state.advance();
4381 }
4382 return true
4383 };
4384
4385 // Object type used to represent tokens. Note that normally, tokens
4386 // simply exist as properties on the parser object. This is only
4387 // used for the onToken callback and the external tokenizer.
4388
4389 var Token = function Token(p) {
4390 this.type = p.type;
4391 this.value = p.value;
4392 this.start = p.start;
4393 this.end = p.end;
4394 if (p.options.locations)
4395 { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
4396 if (p.options.ranges)
4397 { this.range = [p.start, p.end]; }
4398 };
4399
4400 // ## Tokenizer
4401
4402 var pp$9 = Parser.prototype;
4403
4404 // Move to the next token
4405
4406 pp$9.next = function(ignoreEscapeSequenceInKeyword) {
4407 if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc)
4408 { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); }
4409 if (this.options.onToken)
4410 { this.options.onToken(new Token(this)); }
4411
4412 this.lastTokEnd = this.end;
4413 this.lastTokStart = this.start;
4414 this.lastTokEndLoc = this.endLoc;
4415 this.lastTokStartLoc = this.startLoc;
4416 this.nextToken();
4417 };
4418
4419 pp$9.getToken = function() {
4420 this.next();
4421 return new Token(this)
4422 };
4423
4424 // If we're in an ES6 environment, make parsers iterable
4425 if (typeof Symbol !== "undefined")
4426 { pp$9[Symbol.iterator] = function() {
4427 var this$1 = this;
4428
4429 return {
4430 next: function () {
4431 var token = this$1.getToken();
4432 return {
4433 done: token.type === types.eof,
4434 value: token
4435 }
4436 }
4437 }
4438 }; }
4439
4440 // Toggle strict mode. Re-reads the next number or string to please
4441 // pedantic tests (`"use strict"; 010;` should fail).
4442
4443 pp$9.curContext = function() {
4444 return this.context[this.context.length - 1]
4445 };
4446
4447 // Read a single token, updating the parser object's token-related
4448 // properties.
4449
4450 pp$9.nextToken = function() {
4451 var curContext = this.curContext();
4452 if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }
4453
4454 this.start = this.pos;
4455 if (this.options.locations) { this.startLoc = this.curPosition(); }
4456 if (this.pos >= this.input.length) { return this.finishToken(types.eof) }
4457
4458 if (curContext.override) { return curContext.override(this) }
4459 else { this.readToken(this.fullCharCodeAtPos()); }
4460 };
4461
4462 pp$9.readToken = function(code) {
4463 // Identifier or keyword. '\uXXXX' sequences are allowed in
4464 // identifiers, so '\' also dispatches to that.
4465 if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
4466 { return this.readWord() }
4467
4468 return this.getTokenFromCode(code)
4469 };
4470
4471 pp$9.fullCharCodeAtPos = function() {
4472 var code = this.input.charCodeAt(this.pos);
4473 if (code <= 0xd7ff || code >= 0xe000) { return code }
4474 var next = this.input.charCodeAt(this.pos + 1);
4475 return (code << 10) + next - 0x35fdc00
4476 };
4477
4478 pp$9.skipBlockComment = function() {
4479 var startLoc = this.options.onComment && this.curPosition();
4480 var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
4481 if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
4482 this.pos = end + 2;
4483 if (this.options.locations) {
4484 lineBreakG.lastIndex = start;
4485 var match;
4486 while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
4487 ++this.curLine;
4488 this.lineStart = match.index + match[0].length;
4489 }
4490 }
4491 if (this.options.onComment)
4492 { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
4493 startLoc, this.curPosition()); }
4494 };
4495
4496 pp$9.skipLineComment = function(startSkip) {
4497 var start = this.pos;
4498 var startLoc = this.options.onComment && this.curPosition();
4499 var ch = this.input.charCodeAt(this.pos += startSkip);
4500 while (this.pos < this.input.length && !isNewLine(ch)) {
4501 ch = this.input.charCodeAt(++this.pos);
4502 }
4503 if (this.options.onComment)
4504 { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
4505 startLoc, this.curPosition()); }
4506 };
4507
4508 // Called at the start of the parse and after every token. Skips
4509 // whitespace and comments, and.
4510
4511 pp$9.skipSpace = function() {
4512 loop: while (this.pos < this.input.length) {
4513 var ch = this.input.charCodeAt(this.pos);
4514 switch (ch) {
4515 case 32: case 160: // ' '
4516 ++this.pos;
4517 break
4518 case 13:
4519 if (this.input.charCodeAt(this.pos + 1) === 10) {
4520 ++this.pos;
4521 }
4522 case 10: case 8232: case 8233:
4523 ++this.pos;
4524 if (this.options.locations) {
4525 ++this.curLine;
4526 this.lineStart = this.pos;
4527 }
4528 break
4529 case 47: // '/'
4530 switch (this.input.charCodeAt(this.pos + 1)) {
4531 case 42: // '*'
4532 this.skipBlockComment();
4533 break
4534 case 47:
4535 this.skipLineComment(2);
4536 break
4537 default:
4538 break loop
4539 }
4540 break
4541 default:
4542 if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
4543 ++this.pos;
4544 } else {
4545 break loop
4546 }
4547 }
4548 }
4549 };
4550
4551 // Called at the end of every token. Sets `end`, `val`, and
4552 // maintains `context` and `exprAllowed`, and skips the space after
4553 // the token, so that the next one's `start` will point at the
4554 // right position.
4555
4556 pp$9.finishToken = function(type, val) {
4557 this.end = this.pos;
4558 if (this.options.locations) { this.endLoc = this.curPosition(); }
4559 var prevType = this.type;
4560 this.type = type;
4561 this.value = val;
4562
4563 this.updateContext(prevType);
4564 };
4565
4566 // ### Token reading
4567
4568 // This is the function that is called to fetch the next token. It
4569 // is somewhat obscure, because it works in character codes rather
4570 // than characters, and because operator parsing has been inlined
4571 // into it.
4572 //
4573 // All in the name of speed.
4574 //
4575 pp$9.readToken_dot = function() {
4576 var next = this.input.charCodeAt(this.pos + 1);
4577 if (next >= 48 && next <= 57) { return this.readNumber(true) }
4578 var next2 = this.input.charCodeAt(this.pos + 2);
4579 if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
4580 this.pos += 3;
4581 return this.finishToken(types.ellipsis)
4582 } else {
4583 ++this.pos;
4584 return this.finishToken(types.dot)
4585 }
4586 };
4587
4588 pp$9.readToken_slash = function() { // '/'
4589 var next = this.input.charCodeAt(this.pos + 1);
4590 if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
4591 if (next === 61) { return this.finishOp(types.assign, 2) }
4592 return this.finishOp(types.slash, 1)
4593 };
4594
4595 pp$9.readToken_mult_modulo_exp = function(code) { // '%*'
4596 var next = this.input.charCodeAt(this.pos + 1);
4597 var size = 1;
4598 var tokentype = code === 42 ? types.star : types.modulo;
4599
4600 // exponentiation operator ** and **=
4601 if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
4602 ++size;
4603 tokentype = types.starstar;
4604 next = this.input.charCodeAt(this.pos + 2);
4605 }
4606
4607 if (next === 61) { return this.finishOp(types.assign, size + 1) }
4608 return this.finishOp(tokentype, size)
4609 };
4610
4611 pp$9.readToken_pipe_amp = function(code) { // '|&'
4612 var next = this.input.charCodeAt(this.pos + 1);
4613 if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) }
4614 if (next === 61) { return this.finishOp(types.assign, 2) }
4615 return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1)
4616 };
4617
4618 pp$9.readToken_caret = function() { // '^'
4619 var next = this.input.charCodeAt(this.pos + 1);
4620 if (next === 61) { return this.finishOp(types.assign, 2) }
4621 return this.finishOp(types.bitwiseXOR, 1)
4622 };
4623
4624 pp$9.readToken_plus_min = function(code) { // '+-'
4625 var next = this.input.charCodeAt(this.pos + 1);
4626 if (next === code) {
4627 if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 &&
4628 (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
4629 // A `-->` line comment
4630 this.skipLineComment(3);
4631 this.skipSpace();
4632 return this.nextToken()
4633 }
4634 return this.finishOp(types.incDec, 2)
4635 }
4636 if (next === 61) { return this.finishOp(types.assign, 2) }
4637 return this.finishOp(types.plusMin, 1)
4638 };
4639
4640 pp$9.readToken_lt_gt = function(code) { // '<>'
4641 var next = this.input.charCodeAt(this.pos + 1);
4642 var size = 1;
4643 if (next === code) {
4644 size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
4645 if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) }
4646 return this.finishOp(types.bitShift, size)
4647 }
4648 if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 &&
4649 this.input.charCodeAt(this.pos + 3) === 45) {
4650 // `<!--`, an XML-style comment that should be interpreted as a line comment
4651 this.skipLineComment(4);
4652 this.skipSpace();
4653 return this.nextToken()
4654 }
4655 if (next === 61) { size = 2; }
4656 return this.finishOp(types.relational, size)
4657 };
4658
4659 pp$9.readToken_eq_excl = function(code) { // '=!'
4660 var next = this.input.charCodeAt(this.pos + 1);
4661 if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
4662 if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
4663 this.pos += 2;
4664 return this.finishToken(types.arrow)
4665 }
4666 return this.finishOp(code === 61 ? types.eq : types.prefix, 1)
4667 };
4668
4669 pp$9.readToken_question = function() { // '?'
4670 if (this.options.ecmaVersion >= 11) {
4671 var next = this.input.charCodeAt(this.pos + 1);
4672 if (next === 46) {
4673 var next2 = this.input.charCodeAt(this.pos + 2);
4674 if (next2 < 48 || next2 > 57) { return this.finishOp(types.questionDot, 2) }
4675 }
4676 if (next === 63) { return this.finishOp(types.coalesce, 2) }
4677 }
4678 return this.finishOp(types.question, 1)
4679 };
4680
4681 pp$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
4757 pp$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
4763 pp$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
4805 pp$9.readInt = function(radix, len) {
4806 var start = this.pos, total = 0;
4807 for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
4808 var code = this.input.charCodeAt(this.pos), val = (void 0);
4809 if (code >= 97) { val = code - 97 + 10; } // a
4810 else if (code >= 65) { val = code - 65 + 10; } // A
4811 else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
4812 else { val = Infinity; }
4813 if (val >= radix) { break }
4814 ++this.pos;
4815 total = total * radix + val;
4816 }
4817 if (this.pos === start || len != null && this.pos - start !== len) { return null }
4818
4819 return total
4820 };
4821
4822 pp$9.readRadixNumber = function(radix) {
4823 var start = this.pos;
4824 this.pos += 2; // 0x
4825 var val = this.readInt(radix);
4826 if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
4827 if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
4828 val = typeof BigInt !== "undefined" ? BigInt(this.input.slice(start, this.pos)) : null;
4829 ++this.pos;
4830 } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4831 return this.finishToken(types.num, val)
4832 };
4833
4834 // Read an integer, octal integer, or floating-point number.
4835
4836 pp$9.readNumber = function(startsWithDot) {
4837 var start = this.pos;
4838 if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number"); }
4839 var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48;
4840 if (octal && this.strict) { this.raise(start, "Invalid number"); }
4841 var next = this.input.charCodeAt(this.pos);
4842 if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
4843 var str$1 = this.input.slice(start, this.pos);
4844 var val$1 = typeof BigInt !== "undefined" ? BigInt(str$1) : null;
4845 ++this.pos;
4846 if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4847 return this.finishToken(types.num, val$1)
4848 }
4849 if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; }
4850 if (next === 46 && !octal) { // '.'
4851 ++this.pos;
4852 this.readInt(10);
4853 next = this.input.charCodeAt(this.pos);
4854 }
4855 if ((next === 69 || next === 101) && !octal) { // 'eE'
4856 next = this.input.charCodeAt(++this.pos);
4857 if (next === 43 || next === 45) { ++this.pos; } // '+-'
4858 if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
4859 }
4860 if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4861
4862 var str = this.input.slice(start, this.pos);
4863 var val = octal ? parseInt(str, 8) : parseFloat(str);
4864 return this.finishToken(types.num, val)
4865 };
4866
4867 // Read a string value, interpreting backslash-escapes.
4868
4869 pp$9.readCodePoint = function() {
4870 var ch = this.input.charCodeAt(this.pos), code;
4871
4872 if (ch === 123) { // '{'
4873 if (this.options.ecmaVersion < 6) { this.unexpected(); }
4874 var codePos = ++this.pos;
4875 code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
4876 ++this.pos;
4877 if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
4878 } else {
4879 code = this.readHexChar(4);
4880 }
4881 return code
4882 };
4883
4884 function codePointToString$1(code) {
4885 // UTF-16 Decoding
4886 if (code <= 0xFFFF) { return String.fromCharCode(code) }
4887 code -= 0x10000;
4888 return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
4889 }
4890
4891 pp$9.readString = function(quote) {
4892 var out = "", chunkStart = ++this.pos;
4893 for (;;) {
4894 if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); }
4895 var ch = this.input.charCodeAt(this.pos);
4896 if (ch === quote) { break }
4897 if (ch === 92) { // '\'
4898 out += this.input.slice(chunkStart, this.pos);
4899 out += this.readEscapedChar(false);
4900 chunkStart = this.pos;
4901 } else {
4902 if (isNewLine(ch, this.options.ecmaVersion >= 10)) { this.raise(this.start, "Unterminated string constant"); }
4903 ++this.pos;
4904 }
4905 }
4906 out += this.input.slice(chunkStart, this.pos++);
4907 return this.finishToken(types.string, out)
4908 };
4909
4910 // Reads template string tokens.
4911
4912 var INVALID_TEMPLATE_ESCAPE_ERROR = {};
4913
4914 pp$9.tryReadTemplateToken = function() {
4915 this.inTemplateElement = true;
4916 try {
4917 this.readTmplToken();
4918 } catch (err) {
4919 if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
4920 this.readInvalidTemplateToken();
4921 } else {
4922 throw err
4923 }
4924 }
4925
4926 this.inTemplateElement = false;
4927 };
4928
4929 pp$9.invalidStringToken = function(position, message) {
4930 if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
4931 throw INVALID_TEMPLATE_ESCAPE_ERROR
4932 } else {
4933 this.raise(position, message);
4934 }
4935 };
4936
4937 pp$9.readTmplToken = function() {
4938 var out = "", chunkStart = this.pos;
4939 for (;;) {
4940 if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); }
4941 var ch = this.input.charCodeAt(this.pos);
4942 if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${'
4943 if (this.pos === this.start && (this.type === types.template || this.type === types.invalidTemplate)) {
4944 if (ch === 36) {
4945 this.pos += 2;
4946 return this.finishToken(types.dollarBraceL)
4947 } else {
4948 ++this.pos;
4949 return this.finishToken(types.backQuote)
4950 }
4951 }
4952 out += this.input.slice(chunkStart, this.pos);
4953 return this.finishToken(types.template, out)
4954 }
4955 if (ch === 92) { // '\'
4956 out += this.input.slice(chunkStart, this.pos);
4957 out += this.readEscapedChar(true);
4958 chunkStart = this.pos;
4959 } else if (isNewLine(ch)) {
4960 out += this.input.slice(chunkStart, this.pos);
4961 ++this.pos;
4962 switch (ch) {
4963 case 13:
4964 if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; }
4965 case 10:
4966 out += "\n";
4967 break
4968 default:
4969 out += String.fromCharCode(ch);
4970 break
4971 }
4972 if (this.options.locations) {
4973 ++this.curLine;
4974 this.lineStart = this.pos;
4975 }
4976 chunkStart = this.pos;
4977 } else {
4978 ++this.pos;
4979 }
4980 }
4981 };
4982
4983 // Reads a template token to search for the end, without validating any escape sequences
4984 pp$9.readInvalidTemplateToken = function() {
4985 for (; this.pos < this.input.length; this.pos++) {
4986 switch (this.input[this.pos]) {
4987 case "\\":
4988 ++this.pos;
4989 break
4990
4991 case "$":
4992 if (this.input[this.pos + 1] !== "{") {
4993 break
4994 }
4995 // falls through
4996
4997 case "`":
4998 return this.finishToken(types.invalidTemplate, this.input.slice(this.start, this.pos))
4999
5000 // no default
5001 }
5002 }
5003 this.raise(this.start, "Unterminated template");
5004 };
5005
5006 // Used to read escaped characters
5007
5008 pp$9.readEscapedChar = function(inTemplate) {
5009 var ch = this.input.charCodeAt(++this.pos);
5010 ++this.pos;
5011 switch (ch) {
5012 case 110: return "\n" // 'n' -> '\n'
5013 case 114: return "\r" // 'r' -> '\r'
5014 case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
5015 case 117: return codePointToString$1(this.readCodePoint()) // 'u'
5016 case 116: return "\t" // 't' -> '\t'
5017 case 98: return "\b" // 'b' -> '\b'
5018 case 118: return "\u000b" // 'v' -> '\u000b'
5019 case 102: return "\f" // 'f' -> '\f'
5020 case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
5021 case 10: // ' \n'
5022 if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
5023 return ""
5024 case 56:
5025 case 57:
5026 if (inTemplate) {
5027 var codePos = this.pos - 1;
5028
5029 this.invalidStringToken(
5030 codePos,
5031 "Invalid escape sequence in template string"
5032 );
5033
5034 return null
5035 }
5036 default:
5037 if (ch >= 48 && ch <= 55) {
5038 var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
5039 var octal = parseInt(octalStr, 8);
5040 if (octal > 255) {
5041 octalStr = octalStr.slice(0, -1);
5042 octal = parseInt(octalStr, 8);
5043 }
5044 this.pos += octalStr.length - 1;
5045 ch = this.input.charCodeAt(this.pos);
5046 if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
5047 this.invalidStringToken(
5048 this.pos - 1 - octalStr.length,
5049 inTemplate
5050 ? "Octal literal in template string"
5051 : "Octal literal in strict mode"
5052 );
5053 }
5054 return String.fromCharCode(octal)
5055 }
5056 if (isNewLine(ch)) {
5057 // Unicode new line characters after \ get removed from output in both
5058 // template literals and strings
5059 return ""
5060 }
5061 return String.fromCharCode(ch)
5062 }
5063 };
5064
5065 // Used to read character escape sequences ('\x', '\u', '\U').
5066
5067 pp$9.readHexChar = function(len) {
5068 var codePos = this.pos;
5069 var n = this.readInt(16, len);
5070 if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
5071 return n
5072 };
5073
5074 // Read an identifier, and return it as a string. Sets `this.containsEsc`
5075 // to whether the word contained a '\u' escape.
5076 //
5077 // Incrementally adds only escaped chars, adding other chunks as-is
5078 // as a micro-optimization.
5079
5080 pp$9.readWord1 = function() {
5081 this.containsEsc = false;
5082 var word = "", first = true, chunkStart = this.pos;
5083 var astral = this.options.ecmaVersion >= 6;
5084 while (this.pos < this.input.length) {
5085 var ch = this.fullCharCodeAtPos();
5086 if (isIdentifierChar(ch, astral)) {
5087 this.pos += ch <= 0xffff ? 1 : 2;
5088 } else if (ch === 92) { // "\"
5089 this.containsEsc = true;
5090 word += this.input.slice(chunkStart, this.pos);
5091 var escStart = this.pos;
5092 if (this.input.charCodeAt(++this.pos) !== 117) // "u"
5093 { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); }
5094 ++this.pos;
5095 var esc = this.readCodePoint();
5096 if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
5097 { this.invalidStringToken(escStart, "Invalid Unicode escape"); }
5098 word += codePointToString$1(esc);
5099 chunkStart = this.pos;
5100 } else {
5101 break
5102 }
5103 first = false;
5104 }
5105 return word + this.input.slice(chunkStart, this.pos)
5106 };
5107
5108 // Read an identifier or keyword token. Will check for reserved
5109 // words when necessary.
5110
5111 pp$9.readWord = function() {
5112 var word = this.readWord1();
5113 var type = types.name;
5114 if (this.keywords.test(word)) {
5115 type = keywords$1[word];
5116 }
5117 return this.finishToken(type, word)
5118 };
5119
5120 // Acorn is a tiny, fast JavaScript parser written in JavaScript.
5121
5122 var version = "7.3.1";
5123
5124 Parser.acorn = {
5125 Parser: Parser,
5126 version: version,
5127 defaultOptions: defaultOptions,
5128 Position: Position,
5129 SourceLocation: SourceLocation,
5130 getLineInfo: getLineInfo,
5131 Node: Node,
5132 TokenType: TokenType,
5133 tokTypes: types,
5134 keywordTypes: keywords$1,
5135 TokContext: TokContext,
5136 tokContexts: types$1,
5137 isIdentifierChar: isIdentifierChar,
5138 isIdentifierStart: isIdentifierStart,
5139 Token: Token,
5140 isNewLine: isNewLine,
5141 lineBreak: lineBreak,
5142 lineBreakG: lineBreakG,
5143 nonASCIIwhitespace: nonASCIIwhitespace
5144 };
5145
5146 // The main exported interface (under `self.acorn` when in the
5147 // browser) is a `parse` function that takes a code string and
5148 // returns an abstract syntax tree as specified by [Mozilla parser
5149 // API][api].
5150 //
5151 // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
5152
5153 function parse(input, options) {
5154 return Parser.parse(input, options)
5155 }
5156
5157 // This function tries to parse a single expression at a given
5158 // offset in a string. Useful for parsing mixed-language formats
5159 // that embed JavaScript expressions.
5160
5161 function parseExpressionAt(input, pos, options) {
5162 return Parser.parseExpressionAt(input, pos, options)
5163 }
5164
5165 function walk(ast, { enter, leave }) {
5166 return visit(ast, null, enter, leave);
5167 }
5168
5169 let should_skip = false;
5170 let should_remove = false;
5171 let replacement = null;
5172 const context = {
5173 skip: () => should_skip = true,
5174 remove: () => should_remove = true,
5175 replace: (node) => replacement = node
5176 };
5177
5178 function replace(parent, prop, index, node) {
5179 if (parent) {
5180 if (index !== null) {
5181 parent[prop][index] = node;
5182 } else {
5183 parent[prop] = node;
5184 }
5185 }
5186 }
5187
5188 function remove(parent, prop, index) {
5189 if (parent) {
5190 if (index !== null) {
5191 parent[prop].splice(index, 1);
5192 } else {
5193 delete parent[prop];
5194 }
5195 }
5196 }
5197
5198 function visit(
5199 node,
5200 parent,
5201 enter,
5202 leave,
5203 prop,
5204 index
5205 ) {
5206 if (node) {
5207 if (enter) {
5208 const _should_skip = should_skip;
5209 const _should_remove = should_remove;
5210 const _replacement = replacement;
5211 should_skip = false;
5212 should_remove = false;
5213 replacement = null;
5214
5215 enter.call(context, node, parent, prop, index);
5216
5217 if (replacement) {
5218 node = replacement;
5219 replace(parent, prop, index, node);
5220 }
5221
5222 if (should_remove) {
5223 remove(parent, prop, index);
5224 }
5225
5226 const skipped = should_skip;
5227 const removed = should_remove;
5228
5229 should_skip = _should_skip;
5230 should_remove = _should_remove;
5231 replacement = _replacement;
5232
5233 if (skipped) return node;
5234 if (removed) return null;
5235 }
5236
5237 for (const key in node) {
5238 const value = (node )[key];
5239
5240 if (typeof value !== 'object') {
5241 continue;
5242 }
5243
5244 else if (Array.isArray(value)) {
5245 for (let j = 0, k = 0; j < value.length; j += 1, k += 1) {
5246 if (value[j] !== null && typeof value[j].type === 'string') {
5247 if (!visit(value[j], node, enter, leave, key, k)) {
5248 // removed
5249 j--;
5250 }
5251 }
5252 }
5253 }
5254
5255 else if (value !== null && typeof value.type === 'string') {
5256 visit(value, node, enter, leave, key, null);
5257 }
5258 }
5259
5260 if (leave) {
5261 const _replacement = replacement;
5262 const _should_remove = should_remove;
5263 replacement = null;
5264 should_remove = false;
5265
5266 leave.call(context, node, parent, prop, index);
5267
5268 if (replacement) {
5269 node = replacement;
5270 replace(parent, prop, index, node);
5271 }
5272
5273 if (should_remove) {
5274 remove(parent, prop, index);
5275 }
5276
5277 const removed = should_remove;
5278
5279 replacement = _replacement;
5280 should_remove = _should_remove;
5281
5282 if (removed) return null;
5283 }
5284 }
5285
5286 return node;
5287 }
5288
5289 function isReference(node, parent) {
5290 if (node.type === 'MemberExpression') {
5291 return !node.computed && isReference(node.object, node);
5292 }
5293 if (node.type === 'Identifier') {
5294 if (!parent)
5295 return true;
5296 switch (parent.type) {
5297 // disregard `bar` in `foo.bar`
5298 case 'MemberExpression': return parent.computed || node === parent.object;
5299 // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
5300 case 'MethodDefinition': return parent.computed;
5301 // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
5302 case 'FieldDefinition': return parent.computed || node === parent.value;
5303 // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
5304 case 'Property': return parent.computed || node === parent.value;
5305 // disregard the `bar` in `export { foo as bar }` or
5306 // the foo in `import { foo as bar }`
5307 case 'ExportSpecifier':
5308 case 'ImportSpecifier': return node === parent.local;
5309 // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
5310 case 'LabeledStatement':
5311 case 'BreakStatement':
5312 case 'ContinueStatement': return false;
5313 default: return true;
5314 }
5315 }
5316 return false;
5317 }
5318
5319 function analyze(expression) {
5320 const map = new WeakMap();
5321
5322 let scope = new Scope$1(null, false);
5323
5324 walk(expression, {
5325 enter(node, parent) {
5326 if (node.type === 'ImportDeclaration') {
5327 node.specifiers.forEach((specifier) => {
5328 scope.declarations.set(specifier.local.name, specifier);
5329 });
5330 } else if (/(Function(Declaration|Expression)|ArrowFunctionExpression)/.test(node.type)) {
5331 if (node.type === 'FunctionDeclaration') {
5332 scope.declarations.set(node.id.name, node);
5333 map.set(node, scope = new Scope$1(scope, false));
5334 } else {
5335 map.set(node, scope = new Scope$1(scope, false));
5336 if (node.type === 'FunctionExpression' && node.id) scope.declarations.set(node.id.name, node);
5337 }
5338
5339 node.params.forEach((param) => {
5340 extract_names(param).forEach(name => {
5341 scope.declarations.set(name, node);
5342 });
5343 });
5344 } else if (/For(?:In|Of)?Statement/.test(node.type)) {
5345 map.set(node, scope = new Scope$1(scope, true));
5346 } else if (node.type === 'BlockStatement') {
5347 map.set(node, scope = new Scope$1(scope, true));
5348 } else if (/(Class|Variable)Declaration/.test(node.type)) {
5349 scope.add_declaration(node);
5350 } else if (node.type === 'CatchClause') {
5351 map.set(node, scope = new Scope$1(scope, true));
5352
5353 if (node.param) {
5354 extract_names(node.param).forEach(name => {
5355 scope.declarations.set(name, node.param);
5356 });
5357 }
5358 }
5359 },
5360
5361 leave(node) {
5362 if (map.has(node)) {
5363 scope = scope.parent;
5364 }
5365 }
5366 });
5367
5368 const globals = new Map();
5369
5370 walk(expression, {
5371 enter(node, parent) {
5372 if (map.has(node)) scope = map.get(node);
5373
5374 if (node.type === 'Identifier' && isReference(node, parent)) {
5375 const owner = scope.find_owner(node.name);
5376 if (!owner) globals.set(node.name, node);
5377
5378 add_reference(scope, node.name);
5379 }
5380 },
5381 leave(node) {
5382 if (map.has(node)) {
5383 scope = scope.parent;
5384 }
5385 }
5386 });
5387
5388 return { map, scope, globals };
5389 }
5390
5391 function add_reference(scope, name) {
5392 scope.references.add(name);
5393 if (scope.parent) add_reference(scope.parent, name);
5394 }
5395
5396 class Scope$1 {
5397
5398
5399 __init() {this.declarations = new Map();}
5400 __init2() {this.initialised_declarations = new Set();}
5401 __init3() {this.references = new Set();}
5402
5403 constructor(parent, block) {Scope$1.prototype.__init.call(this);Scope$1.prototype.__init2.call(this);Scope$1.prototype.__init3.call(this);
5404 this.parent = parent;
5405 this.block = block;
5406 }
5407
5408
5409 add_declaration(node) {
5410 if (node.type === 'VariableDeclaration') {
5411 if (node.kind === 'var' && this.block && this.parent) {
5412 this.parent.add_declaration(node);
5413 } else if (node.type === 'VariableDeclaration') {
5414 node.declarations.forEach((declarator) => {
5415 extract_names(declarator.id).forEach(name => {
5416 this.declarations.set(name, node);
5417 if (declarator.init) this.initialised_declarations.add(name);
5418 });
5419 });
5420 }
5421 } else {
5422 this.declarations.set(node.id.name, node);
5423 }
5424 }
5425
5426 find_owner(name) {
5427 if (this.declarations.has(name)) return this;
5428 return this.parent && this.parent.find_owner(name);
5429 }
5430
5431 has(name) {
5432 return (
5433 this.declarations.has(name) || (this.parent && this.parent.has(name))
5434 );
5435 }
5436 }
5437
5438 function extract_names(param) {
5439 return extract_identifiers(param).map(node => node.name);
5440 }
5441
5442 function extract_identifiers(param) {
5443 const nodes = [];
5444 extractors[param.type] && extractors[param.type](nodes, param);
5445 return nodes;
5446 }
5447
5448 const extractors = {
5449 Identifier(nodes, param) {
5450 nodes.push(param);
5451 },
5452
5453 MemberExpression(nodes, param) {
5454 let object = param;
5455 while (object.type === 'MemberExpression') object = object.object;
5456 nodes.push(object);
5457 },
5458
5459 ObjectPattern(nodes, param) {
5460 param.properties.forEach((prop) => {
5461 if (prop.type === 'RestElement') {
5462 nodes.push(prop.argument);
5463 } else {
5464 extractors[prop.value.type](nodes, prop.value);
5465 }
5466 });
5467 },
5468
5469 ArrayPattern(nodes, param) {
5470 param.elements.forEach((element) => {
5471 if (element) extractors[element.type](nodes, element);
5472 });
5473 },
5474
5475 RestElement(nodes, param) {
5476 extractors[param.argument.type](nodes, param.argument);
5477 },
5478
5479 AssignmentPattern(nodes, param) {
5480 extractors[param.left.type](nodes, param.left);
5481 }
5482 };
5483
5484 var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
5485 function encode(decoded) {
5486 var sourceFileIndex = 0; // second field
5487 var sourceCodeLine = 0; // third field
5488 var sourceCodeColumn = 0; // fourth field
5489 var nameIndex = 0; // fifth field
5490 var mappings = '';
5491 for (var i = 0; i < decoded.length; i++) {
5492 var line = decoded[i];
5493 if (i > 0)
5494 mappings += ';';
5495 if (line.length === 0)
5496 continue;
5497 var generatedCodeColumn = 0; // first field
5498 var lineMappings = [];
5499 for (var _i = 0, line_1 = line; _i < line_1.length; _i++) {
5500 var segment = line_1[_i];
5501 var segmentMappings = encodeInteger(segment[0] - generatedCodeColumn);
5502 generatedCodeColumn = segment[0];
5503 if (segment.length > 1) {
5504 segmentMappings +=
5505 encodeInteger(segment[1] - sourceFileIndex) +
5506 encodeInteger(segment[2] - sourceCodeLine) +
5507 encodeInteger(segment[3] - sourceCodeColumn);
5508 sourceFileIndex = segment[1];
5509 sourceCodeLine = segment[2];
5510 sourceCodeColumn = segment[3];
5511 }
5512 if (segment.length === 5) {
5513 segmentMappings += encodeInteger(segment[4] - nameIndex);
5514 nameIndex = segment[4];
5515 }
5516 lineMappings.push(segmentMappings);
5517 }
5518 mappings += lineMappings.join(',');
5519 }
5520 return mappings;
5521 }
5522 function encodeInteger(num) {
5523 var result = '';
5524 num = num < 0 ? (-num << 1) | 1 : num << 1;
5525 do {
5526 var clamped = num & 31;
5527 num >>>= 5;
5528 if (num > 0) {
5529 clamped |= 32;
5530 }
5531 result += chars[clamped];
5532 } while (num > 0);
5533 return result;
5534 }
5535
5536 // generate an ID that is, to all intents and purposes, unique
5537 const id = (Math.round(Math.random() * 1e20)).toString(36);
5538 const re = new RegExp(`_${id}_(?:(\\d+)|(AT)|(HASH))_(\\w+)?`, 'g');
5539
5540 const get_comment_handlers = (comments, raw) => ({
5541
5542 // pass to acorn options
5543 onComment: (block, value, start, end) => {
5544 if (block && /\n/.test(value)) {
5545 let a = start;
5546 while (a > 0 && raw[a - 1] !== '\n') a -= 1;
5547
5548 let b = a;
5549 while (/[ \t]/.test(raw[b])) b += 1;
5550
5551 const indentation = raw.slice(a, b);
5552 value = value.replace(new RegExp(`^${indentation}`, 'gm'), '');
5553 }
5554
5555 comments.push({ type: block ? 'Block' : 'Line', value, start, end });
5556 },
5557
5558 // pass to estree-walker options
5559 enter(node) {
5560 let comment;
5561
5562 while (comments[0] && comments[0].start < (node ).start) {
5563 comment = comments.shift();
5564
5565 comment.value = comment.value.replace(re, (match, id, at, hash, value) => {
5566 if (hash) return `#${value}`;
5567 if (at) return `@${value}`;
5568
5569 return match;
5570 });
5571
5572 const next = comments[0] || node;
5573 (comment ).has_trailing_newline = (
5574 comment.type === 'Line' ||
5575 /\n/.test(raw.slice(comment.end, (next ).start))
5576 );
5577
5578 (node.leadingComments || (node.leadingComments = [])).push(comment);
5579 }
5580 },
5581 leave(node) {
5582 if (comments[0]) {
5583 const slice = raw.slice((node ).end, comments[0].start);
5584
5585 if (/^[,) \t]*$/.test(slice)) {
5586 node.trailingComments = [comments.shift()];
5587 }
5588 }
5589 }
5590
5591 });
5592
5593 function handle(node, state) {
5594 const handler = handlers[node.type];
5595
5596 if (!handler) {
5597 throw new Error(`Not implemented ${node.type}`);
5598 }
5599
5600 const result = handler(node, state);
5601
5602 if (node.leadingComments) {
5603 result.unshift(c(node.leadingComments.map(comment => comment.type === 'Block'
5604 ? `/*${comment.value}*/${(comment ).has_trailing_newline ? `\n${state.indent}` : ` `}`
5605 : `//${comment.value}${(comment ).has_trailing_newline ? `\n${state.indent}` : ` `}`).join(``)));
5606 }
5607
5608 if (node.trailingComments) {
5609 state.comments.push(node.trailingComments[0]); // there is only ever one
5610 }
5611
5612 return result;
5613 }
5614
5615 function c(content, node) {
5616 return {
5617 content,
5618 loc: node && node.loc,
5619 has_newline: /\n/.test(content)
5620 };
5621 }
5622
5623 const OPERATOR_PRECEDENCE = {
5624 '||': 2,
5625 '&&': 3,
5626 '??': 4,
5627 '|': 5,
5628 '^': 6,
5629 '&': 7,
5630 '==': 8,
5631 '!=': 8,
5632 '===': 8,
5633 '!==': 8,
5634 '<': 9,
5635 '>': 9,
5636 '<=': 9,
5637 '>=': 9,
5638 in: 9,
5639 instanceof: 9,
5640 '<<': 10,
5641 '>>': 10,
5642 '>>>': 10,
5643 '+': 11,
5644 '-': 11,
5645 '*': 12,
5646 '%': 12,
5647 '/': 12,
5648 '**': 13,
5649 };
5650
5651 const EXPRESSIONS_PRECEDENCE = {
5652 ArrayExpression: 20,
5653 TaggedTemplateExpression: 20,
5654 ThisExpression: 20,
5655 Identifier: 20,
5656 Literal: 18,
5657 TemplateLiteral: 20,
5658 Super: 20,
5659 SequenceExpression: 20,
5660 MemberExpression: 19,
5661 CallExpression: 19,
5662 NewExpression: 19,
5663 AwaitExpression: 17,
5664 ClassExpression: 17,
5665 FunctionExpression: 17,
5666 ObjectExpression: 17,
5667 UpdateExpression: 16,
5668 UnaryExpression: 15,
5669 BinaryExpression: 14,
5670 LogicalExpression: 13,
5671 ConditionalExpression: 4,
5672 ArrowFunctionExpression: 3,
5673 AssignmentExpression: 3,
5674 YieldExpression: 2,
5675 RestElement: 1
5676 };
5677
5678 function needs_parens(node, parent, is_right) {
5679 const precedence = EXPRESSIONS_PRECEDENCE[node.type];
5680 const parent_precedence = EXPRESSIONS_PRECEDENCE[parent.type];
5681
5682 if (precedence !== parent_precedence) {
5683 // Different node types
5684 return (
5685 (!is_right &&
5686 precedence === 15 &&
5687 parent_precedence === 14 &&
5688 parent.operator === '**') ||
5689 precedence < parent_precedence
5690 );
5691 }
5692
5693 if (precedence !== 13 && precedence !== 14) {
5694 // Not a `LogicalExpression` or `BinaryExpression`
5695 return false;
5696 }
5697
5698 if ((node ).operator === '**' && parent.operator === '**') {
5699 // Exponentiation operator has right-to-left associativity
5700 return !is_right;
5701 }
5702
5703 if (is_right) {
5704 // Parenthesis are used if both operators have the same precedence
5705 return (
5706 OPERATOR_PRECEDENCE[(node ).operator] <=
5707 OPERATOR_PRECEDENCE[parent.operator]
5708 );
5709 }
5710
5711 return (
5712 OPERATOR_PRECEDENCE[(node ).operator] <
5713 OPERATOR_PRECEDENCE[parent.operator]
5714 );
5715 }
5716
5717 function has_call_expression(node) {
5718 while (node) {
5719 if (node.type[0] === 'CallExpression') {
5720 return true;
5721 } else if (node.type === 'MemberExpression') {
5722 node = node.object;
5723 } else {
5724 return false;
5725 }
5726 }
5727 }
5728
5729 const has_newline = (chunks) => {
5730 for (let i = 0; i < chunks.length; i += 1) {
5731 if (chunks[i].has_newline) return true;
5732 }
5733 return false;
5734 };
5735
5736 const get_length = (chunks) => {
5737 let total = 0;
5738 for (let i = 0; i < chunks.length; i += 1) {
5739 total += chunks[i].content.length;
5740 }
5741 return total;
5742 };
5743
5744 const sum = (a, b) => a + b;
5745
5746 const join = (nodes, separator) => {
5747 if (nodes.length === 0) return [];
5748 const joined = [...nodes[0]];
5749 for (let i = 1; i < nodes.length; i += 1) {
5750 joined.push(separator, ...nodes[i] );
5751 }
5752 return joined;
5753 };
5754
5755 const scoped = (fn) => {
5756 return (node, state) => {
5757 return fn(node, {
5758 ...state,
5759 scope: state.scope_map.get(node)
5760 });
5761 };
5762 };
5763
5764 const deconflict = (name, names) => {
5765 const original = name;
5766 let i = 1;
5767
5768 while (names.has(name)) {
5769 name = `${original}$${i++}`;
5770 }
5771
5772 return name;
5773 };
5774
5775 const handle_body = (nodes, state) => {
5776 const chunks = [];
5777
5778 const body = nodes.map(statement => {
5779 const chunks = handle(statement, {
5780 ...state,
5781 indent: state.indent
5782 });
5783
5784 let add_newline = false;
5785
5786 while (state.comments.length) {
5787 const comment = state.comments.shift();
5788 const prefix = add_newline ? `\n${state.indent}` : ` `;
5789
5790 chunks.push(c(comment.type === 'Block'
5791 ? `${prefix}/*${comment.value}*/`
5792 : `${prefix}//${comment.value}`));
5793
5794 add_newline = (comment.type === 'Line');
5795 }
5796
5797 return chunks;
5798 });
5799
5800 let needed_padding = false;
5801
5802 for (let i = 0; i < body.length; i += 1) {
5803 const needs_padding = has_newline(body[i]);
5804
5805 if (i > 0) {
5806 chunks.push(
5807 c(needs_padding || needed_padding ? `\n\n${state.indent}` : `\n${state.indent}`)
5808 );
5809 }
5810
5811 chunks.push(
5812 ...body[i]
5813 );
5814
5815 needed_padding = needs_padding;
5816 }
5817
5818 return chunks;
5819 };
5820
5821 const handle_var_declaration = (node, state) => {
5822 const chunks = [c(`${node.kind} `)];
5823
5824 const declarators = node.declarations.map(d => handle(d, {
5825 ...state,
5826 indent: state.indent + (node.declarations.length === 1 ? '' : '\t')
5827 }));
5828
5829 const multiple_lines = (
5830 declarators.some(has_newline) ||
5831 (declarators.map(get_length).reduce(sum, 0) + (state.indent.length + declarators.length - 1) * 2) > 80
5832 );
5833
5834 const separator = c(multiple_lines ? `,\n${state.indent}\t` : ', ');
5835
5836 if (multiple_lines) {
5837 chunks.push(...join(declarators, separator));
5838 } else {
5839 chunks.push(
5840 ...join(declarators, separator)
5841 );
5842 }
5843
5844 return chunks;
5845 };
5846
5847 const handlers = {
5848 Program(node, state) {
5849 return handle_body(node.body, state);
5850 },
5851
5852 BlockStatement: scoped((node, state) => {
5853 return [
5854 c(`{\n${state.indent}\t`),
5855 ...handle_body(node.body, { ...state, indent: state.indent + '\t' }),
5856 c(`\n${state.indent}}`)
5857 ];
5858 }),
5859
5860 EmptyStatement(node, state) {
5861 return [];
5862 },
5863
5864 ParenthesizedExpression(node, state) {
5865 return handle(node.expression, state);
5866 },
5867
5868 ExpressionStatement(node, state) {
5869 if (
5870 node.expression.type === 'AssignmentExpression' &&
5871 node.expression.left.type === 'ObjectPattern'
5872 ) {
5873 // is an AssignmentExpression to an ObjectPattern
5874 return [
5875 c('('),
5876 ...handle(node.expression, state),
5877 c(');')
5878 ];
5879 }
5880
5881 return [
5882 ...handle(node.expression, state),
5883 c(';')
5884 ];
5885 },
5886
5887 IfStatement(node, state) {
5888 const chunks = [
5889 c('if ('),
5890 ...handle(node.test, state),
5891 c(') '),
5892 ...handle(node.consequent, state)
5893 ];
5894
5895 if (node.alternate) {
5896 chunks.push(
5897 c(' else '),
5898 ...handle(node.alternate, state)
5899 );
5900 }
5901
5902 return chunks;
5903 },
5904
5905 LabeledStatement(node, state) {
5906 return [
5907 ...handle(node.label, state),
5908 c(': '),
5909 ...handle(node.body, state)
5910 ];
5911 },
5912
5913 BreakStatement(node, state) {
5914 return node.label
5915 ? [c('break '), ...handle(node.label, state), c(';')]
5916 : [c('break;')];
5917 },
5918
5919 ContinueStatement(node, state) {
5920 return node.label
5921 ? [c('continue '), ...handle(node.label, state), c(';')]
5922 : [c('continue;')];
5923 },
5924
5925 WithStatement(node, state) {
5926 return [
5927 c('with ('),
5928 ...handle(node.object, state),
5929 c(') '),
5930 ...handle(node.body, state)
5931 ];
5932 },
5933
5934 SwitchStatement(node, state) {
5935 const chunks = [
5936 c('switch ('),
5937 ...handle(node.discriminant, state),
5938 c(') {')
5939 ];
5940
5941 node.cases.forEach(block => {
5942 if (block.test) {
5943 chunks.push(
5944 c(`\n${state.indent}\tcase `),
5945 ...handle(block.test, { ...state, indent: `${state.indent}\t` }),
5946 c(':')
5947 );
5948 } else {
5949 chunks.push(c(`\n${state.indent}\tdefault:`));
5950 }
5951
5952 block.consequent.forEach(statement => {
5953 chunks.push(
5954 c(`\n${state.indent}\t\t`),
5955 ...handle(statement, { ...state, indent: `${state.indent}\t\t` })
5956 );
5957 });
5958 });
5959
5960 chunks.push(c(`\n${state.indent}}`));
5961
5962 return chunks;
5963 },
5964
5965 ReturnStatement(node, state) {
5966 if (node.argument) {
5967 return [
5968 c('return '),
5969 ...handle(node.argument, state),
5970 c(';')
5971 ];
5972 } else {
5973 return [c('return;')];
5974 }
5975 },
5976
5977 ThrowStatement(node, state) {
5978 return [
5979 c('throw '),
5980 ...handle(node.argument, state),
5981 c(';')
5982 ];
5983 },
5984
5985 TryStatement(node, state) {
5986 const chunks = [
5987 c('try '),
5988 ...handle(node.block, state)
5989 ];
5990
5991 if (node.handler) {
5992 if (node.handler.param) {
5993 chunks.push(
5994 c(' catch('),
5995 ...handle(node.handler.param, state),
5996 c(') ')
5997 );
5998 } else {
5999 chunks.push(c(' catch '));
6000 }
6001
6002 chunks.push(...handle(node.handler.body, state));
6003 }
6004
6005 if (node.finalizer) {
6006 chunks.push(c(' finally '), ...handle(node.finalizer, state));
6007 }
6008
6009 return chunks;
6010 },
6011
6012 WhileStatement(node, state) {
6013 return [
6014 c('while ('),
6015 ...handle(node.test, state),
6016 c(') '),
6017 ...handle(node.body, state)
6018 ];
6019 },
6020
6021 DoWhileStatement(node, state) {
6022 return [
6023 c('do '),
6024 ...handle(node.body, state),
6025 c(' while ('),
6026 ...handle(node.test, state),
6027 c(');')
6028 ];
6029 },
6030
6031 ForStatement: scoped((node, state) => {
6032 const chunks = [c('for (')];
6033
6034 if (node.init) {
6035 if ((node.init ).type === 'VariableDeclaration') {
6036 chunks.push(...handle_var_declaration(node.init , state));
6037 } else {
6038 chunks.push(...handle(node.init, state));
6039 }
6040 }
6041
6042 chunks.push(c('; '));
6043 if (node.test) chunks.push(...handle(node.test, state));
6044 chunks.push(c('; '));
6045 if (node.update) chunks.push(...handle(node.update, state));
6046
6047 chunks.push(
6048 c(') '),
6049 ...handle(node.body, state)
6050 );
6051
6052 return chunks;
6053 }),
6054
6055 ForInStatement: scoped((node, state) => {
6056 const chunks = [
6057 c(`for ${(node ).await ? 'await ' : ''}(`)
6058 ];
6059
6060 if ((node.left ).type === 'VariableDeclaration') {
6061 chunks.push(...handle_var_declaration(node.left , state));
6062 } else {
6063 chunks.push(...handle(node.left, state));
6064 }
6065
6066 chunks.push(
6067 c(node.type === 'ForInStatement' ? ` in ` : ` of `),
6068 ...handle(node.right, state),
6069 c(') '),
6070 ...handle(node.body, state)
6071 );
6072
6073 return chunks;
6074 }),
6075
6076 DebuggerStatement(node, state) {
6077 return [c('debugger', node), c(';')];
6078 },
6079
6080 FunctionDeclaration: scoped((node, state) => {
6081 const chunks = [];
6082
6083 if (node.async) chunks.push(c('async '));
6084 chunks.push(c(node.generator ? 'function* ' : 'function '));
6085 if (node.id) chunks.push(...handle(node.id, state));
6086 chunks.push(c('('));
6087
6088 const params = node.params.map(p => handle(p, {
6089 ...state,
6090 indent: state.indent + '\t'
6091 }));
6092
6093 const multiple_lines = (
6094 params.some(has_newline) ||
6095 (params.map(get_length).reduce(sum, 0) + (state.indent.length + params.length - 1) * 2) > 80
6096 );
6097
6098 const separator = c(multiple_lines ? `,\n${state.indent}` : ', ');
6099
6100 if (multiple_lines) {
6101 chunks.push(
6102 c(`\n${state.indent}\t`),
6103 ...join(params, separator),
6104 c(`\n${state.indent}`)
6105 );
6106 } else {
6107 chunks.push(
6108 ...join(params, separator)
6109 );
6110 }
6111
6112 chunks.push(
6113 c(') '),
6114 ...handle(node.body, state)
6115 );
6116
6117 return chunks;
6118 }),
6119
6120 VariableDeclaration(node, state) {
6121 return handle_var_declaration(node, state).concat(c(';'));
6122 },
6123
6124 VariableDeclarator(node, state) {
6125 if (node.init) {
6126 return [
6127 ...handle(node.id, state),
6128 c(' = '),
6129 ...handle(node.init, state)
6130 ];
6131 } else {
6132 return handle(node.id, state);
6133 }
6134 },
6135
6136 ClassDeclaration(node, state) {
6137 const chunks = [c('class ')];
6138
6139 if (node.id) chunks.push(...handle(node.id, state), c(' '));
6140
6141 if (node.superClass) {
6142 chunks.push(
6143 c('extends '),
6144 ...handle(node.superClass, state),
6145 c(' ')
6146 );
6147 }
6148
6149 chunks.push(...handle(node.body, state));
6150
6151 return chunks;
6152 },
6153
6154 ImportDeclaration(node, state) {
6155 const chunks = [c('import ')];
6156
6157 const { length } = node.specifiers;
6158 const source = handle(node.source, state);
6159
6160 if (length > 0) {
6161 let i = 0;
6162
6163 while (i < length) {
6164 if (i > 0) {
6165 chunks.push(c(', '));
6166 }
6167
6168 const specifier = node.specifiers[i];
6169
6170 if (specifier.type === 'ImportDefaultSpecifier') {
6171 chunks.push(c(specifier.local.name, specifier));
6172 i += 1;
6173 } else if (specifier.type === 'ImportNamespaceSpecifier') {
6174 chunks.push(c('* as ' + specifier.local.name, specifier));
6175 i += 1;
6176 } else {
6177 break;
6178 }
6179 }
6180
6181 if (i < length) {
6182 // we have named specifiers
6183 const specifiers = node.specifiers.slice(i).map((specifier) => {
6184 const name = handle(specifier.imported, state)[0];
6185 const as = handle(specifier.local, state)[0];
6186
6187 if (name.content === as.content) {
6188 return [as];
6189 }
6190
6191 return [name, c(' as '), as];
6192 });
6193
6194 const width = get_length(chunks) + specifiers.map(get_length).reduce(sum, 0) + (2 * specifiers.length) + 6 + get_length(source);
6195
6196 if (width > 80) {
6197 chunks.push(
6198 c(`{\n\t`),
6199 ...join(specifiers, c(',\n\t')),
6200 c('\n}')
6201 );
6202 } else {
6203 chunks.push(
6204 c(`{ `),
6205 ...join(specifiers, c(', ')),
6206 c(' }')
6207 );
6208 }
6209 }
6210
6211 chunks.push(c(' from '));
6212 }
6213
6214 chunks.push(
6215 ...source,
6216 c(';')
6217 );
6218
6219 return chunks;
6220 },
6221
6222 ImportExpression(node, state) {
6223 return [c('import('), ...handle(node.source, state), c(')')];
6224 },
6225
6226 ExportDefaultDeclaration(node, state) {
6227 const chunks = [
6228 c(`export default `),
6229 ...handle(node.declaration, state)
6230 ];
6231
6232 if (node.declaration.type !== 'FunctionDeclaration') {
6233 chunks.push(c(';'));
6234 }
6235
6236 return chunks;
6237 },
6238
6239 ExportNamedDeclaration(node, state) {
6240 const chunks = [c('export ')];
6241
6242 if (node.declaration) {
6243 chunks.push(...handle(node.declaration, state));
6244 } else {
6245 const specifiers = node.specifiers.map(specifier => {
6246 const name = handle(specifier.local, state)[0];
6247 const as = handle(specifier.exported, state)[0];
6248
6249 if (name.content === as.content) {
6250 return [name];
6251 }
6252
6253 return [name, c(' as '), as];
6254 });
6255
6256 const width = 7 + specifiers.map(get_length).reduce(sum, 0) + 2 * specifiers.length;
6257
6258 if (width > 80) {
6259 chunks.push(
6260 c('{\n\t'),
6261 ...join(specifiers, c(',\n\t')),
6262 c('\n}')
6263 );
6264 } else {
6265 chunks.push(
6266 c('{ '),
6267 ...join(specifiers, c(', ')),
6268 c(' }')
6269 );
6270 }
6271
6272 if (node.source) {
6273 chunks.push(
6274 c(' from '),
6275 ...handle(node.source, state)
6276 );
6277 }
6278 }
6279
6280 chunks.push(c(';'));
6281
6282 return chunks;
6283 },
6284
6285 ExportAllDeclaration(node, state) {
6286 return [
6287 c(`export * from `),
6288 ...handle(node.source, state),
6289 c(`;`)
6290 ];
6291 },
6292
6293 MethodDefinition(node, state) {
6294 const chunks = [];
6295
6296 if (node.static) {
6297 chunks.push(c('static '));
6298 }
6299
6300 if (node.kind === 'get' || node.kind === 'set') {
6301 // Getter or setter
6302 chunks.push(c(node.kind + ' '));
6303 }
6304
6305 if (node.value.async) {
6306 chunks.push(c('async '));
6307 }
6308
6309 if (node.value.generator) {
6310 chunks.push(c('*'));
6311 }
6312
6313 if (node.computed) {
6314 chunks.push(
6315 c('['),
6316 ...handle(node.key, state),
6317 c(']')
6318 );
6319 } else {
6320 chunks.push(...handle(node.key, state));
6321 }
6322
6323 chunks.push(c('('));
6324
6325 const { params } = node.value;
6326 for (let i = 0; i < params.length; i += 1) {
6327 chunks.push(...handle(params[i], state));
6328 if (i < params.length - 1) chunks.push(c(', '));
6329 }
6330
6331 chunks.push(
6332 c(') '),
6333 ...handle(node.value.body, state)
6334 );
6335
6336 return chunks;
6337 },
6338
6339 ArrowFunctionExpression: scoped((node, state) => {
6340 const chunks = [];
6341
6342 if (node.async) chunks.push(c('async '));
6343
6344 if (node.params.length === 1 && node.params[0].type === 'Identifier') {
6345 chunks.push(...handle(node.params[0], state));
6346 } else {
6347 const params = node.params.map(param => handle(param, {
6348 ...state,
6349 indent: state.indent + '\t'
6350 }));
6351
6352 chunks.push(
6353 c('('),
6354 ...join(params, c(', ')),
6355 c(')')
6356 );
6357 }
6358
6359 chunks.push(c(' => '));
6360
6361 if (node.body.type === 'ObjectExpression') {
6362 chunks.push(
6363 c('('),
6364 ...handle(node.body, state),
6365 c(')')
6366 );
6367 } else {
6368 chunks.push(...handle(node.body, state));
6369 }
6370
6371 return chunks;
6372 }),
6373
6374 ThisExpression(node, state) {
6375 return [c('this', node)];
6376 },
6377
6378 Super(node, state) {
6379 return [c('super', node)];
6380 },
6381
6382 RestElement(node, state) {
6383 return [c('...'), ...handle(node.argument, state)];
6384 },
6385
6386 YieldExpression(node, state) {
6387 if (node.argument) {
6388 return [c(node.delegate ? `yield* ` : `yield `), ...handle(node.argument, state)];
6389 }
6390
6391 return [c(node.delegate ? `yield*` : `yield`)];
6392 },
6393
6394 AwaitExpression(node, state) {
6395 if (node.argument) {
6396 const precedence = EXPRESSIONS_PRECEDENCE[node.argument.type];
6397
6398 if (precedence && (precedence < EXPRESSIONS_PRECEDENCE.AwaitExpression)) {
6399 return [c('await ('), ...handle(node.argument, state), c(')')];
6400 } else {
6401 return [c('await '), ...handle(node.argument, state)];
6402 }
6403 }
6404
6405 return [c('await')];
6406 },
6407
6408 TemplateLiteral(node, state) {
6409 const chunks = [c('`')];
6410
6411 const { quasis, expressions } = node;
6412
6413 for (let i = 0; i < expressions.length; i++) {
6414 chunks.push(
6415 c(quasis[i].value.raw),
6416 c('${'),
6417 ...handle(expressions[i], state),
6418 c('}')
6419 );
6420 }
6421
6422 chunks.push(
6423 c(quasis[quasis.length - 1].value.raw),
6424 c('`')
6425 );
6426
6427 return chunks;
6428 },
6429
6430 TaggedTemplateExpression(node, state) {
6431 return handle(node.tag, state).concat(handle(node.quasi, state));
6432 },
6433
6434 ArrayExpression(node, state) {
6435 const chunks = [c('[')];
6436
6437 const elements = [];
6438 let sparse_commas = [];
6439
6440 for (let i = 0; i < node.elements.length; i += 1) {
6441 // can't use map/forEach because of sparse arrays
6442 const element = node.elements[i];
6443 if (element) {
6444 elements.push([...sparse_commas, ...handle(element, {
6445 ...state,
6446 indent: state.indent + '\t'
6447 })]);
6448 sparse_commas = [];
6449 } else {
6450 sparse_commas.push(c(','));
6451 }
6452 }
6453
6454 const multiple_lines = (
6455 elements.some(has_newline) ||
6456 (elements.map(get_length).reduce(sum, 0) + (state.indent.length + elements.length - 1) * 2) > 80
6457 );
6458
6459 if (multiple_lines) {
6460 chunks.push(
6461 c(`\n${state.indent}\t`),
6462 ...join(elements, c(`,\n${state.indent}\t`)),
6463 c(`\n${state.indent}`),
6464 ...sparse_commas
6465 );
6466 } else {
6467 chunks.push(...join(elements, c(', ')), ...sparse_commas);
6468 }
6469
6470 chunks.push(c(']'));
6471
6472 return chunks;
6473 },
6474
6475 ObjectExpression(node, state) {
6476 if (node.properties.length === 0) {
6477 return [c('{}')];
6478 }
6479
6480 let has_inline_comment = false;
6481
6482 const chunks = [];
6483 const separator = c(', ');
6484
6485 node.properties.forEach((p, i) => {
6486 chunks.push(...handle(p, {
6487 ...state,
6488 indent: state.indent + '\t'
6489 }));
6490
6491 if (state.comments.length) {
6492 // TODO generalise this, so it works with ArrayExpressions and other things.
6493 // At present, stuff will just get appended to the closest statement/declaration
6494 chunks.push(c(', '));
6495
6496 while (state.comments.length) {
6497 const comment = state.comments.shift();
6498
6499 chunks.push(c(comment.type === 'Block'
6500 ? `/*${comment.value}*/\n${state.indent}\t`
6501 : `//${comment.value}\n${state.indent}\t`));
6502
6503 if (comment.type === 'Line') {
6504 has_inline_comment = true;
6505 }
6506 }
6507 } else {
6508 if (i < node.properties.length - 1) {
6509 chunks.push(separator);
6510 }
6511 }
6512 });
6513
6514 const multiple_lines = (
6515 has_inline_comment ||
6516 has_newline(chunks) ||
6517 get_length(chunks) > 40
6518 );
6519
6520 if (multiple_lines) {
6521 separator.content = `,\n${state.indent}\t`;
6522 }
6523
6524 return [
6525 c(multiple_lines ? `{\n${state.indent}\t` : `{ `),
6526 ...chunks,
6527 c(multiple_lines ? `\n${state.indent}}` : ` }`)
6528 ];
6529 },
6530
6531 Property(node, state) {
6532 const value = handle(node.value, state);
6533
6534 if (node.key === node.value) {
6535 return value;
6536 }
6537
6538 // special case
6539 if (
6540 !node.computed &&
6541 node.value.type === 'AssignmentPattern' &&
6542 node.value.left.type === 'Identifier' &&
6543 node.value.left.name === (node.key ).name
6544 ) {
6545 return value;
6546 }
6547
6548 if (node.value.type === 'Identifier' && (
6549 (node.key.type === 'Identifier' && node.key.name === value[0].content) ||
6550 (node.key.type === 'Literal' && node.key.value === value[0].content)
6551 )) {
6552 return value;
6553 }
6554
6555 const key = handle(node.key, state);
6556
6557 if (node.value.type === 'FunctionExpression' && !node.value.id) {
6558 state = {
6559 ...state,
6560 scope: state.scope_map.get(node.value)
6561 };
6562
6563 const chunks = node.kind !== 'init'
6564 ? [c(`${node.kind} `)]
6565 : [];
6566
6567 if (node.value.async) {
6568 chunks.push(c('async '));
6569 }
6570 if (node.value.generator) {
6571 chunks.push(c('*'));
6572 }
6573
6574 chunks.push(
6575 ...(node.computed ? [c('['), ...key, c(']')] : key),
6576 c('('),
6577 ...join((node.value ).params.map(param => handle(param, state)), c(', ')),
6578 c(') '),
6579 ...handle((node.value ).body, state)
6580 );
6581
6582 return chunks;
6583 }
6584
6585 if (node.computed) {
6586 return [
6587 c('['),
6588 ...key,
6589 c(']: '),
6590 ...value
6591 ];
6592 }
6593
6594 return [
6595 ...key,
6596 c(': '),
6597 ...value
6598 ];
6599 },
6600
6601 ObjectPattern(node, state) {
6602 const chunks = [c('{ ')];
6603
6604 for (let i = 0; i < node.properties.length; i += 1) {
6605 chunks.push(...handle(node.properties[i], state));
6606 if (i < node.properties.length - 1) chunks.push(c(', '));
6607 }
6608
6609 chunks.push(c(' }'));
6610
6611 return chunks;
6612 },
6613
6614 SequenceExpression(node, state) {
6615 const expressions = node.expressions.map(e => handle(e, state));
6616
6617 return [
6618 c('('),
6619 ...join(expressions, c(', ')),
6620 c(')')
6621 ];
6622 },
6623
6624 UnaryExpression(node, state) {
6625 const chunks = [c(node.operator)];
6626
6627 if (node.operator.length > 1) {
6628 chunks.push(c(' '));
6629 }
6630
6631 if (
6632 EXPRESSIONS_PRECEDENCE[node.argument.type] <
6633 EXPRESSIONS_PRECEDENCE.UnaryExpression
6634 ) {
6635 chunks.push(
6636 c('('),
6637 ...handle(node.argument, state),
6638 c(')')
6639 );
6640 } else {
6641 chunks.push(...handle(node.argument, state));
6642 }
6643
6644 return chunks;
6645 },
6646
6647 UpdateExpression(node, state) {
6648 return node.prefix
6649 ? [c(node.operator), ...handle(node.argument, state)]
6650 : [...handle(node.argument, state), c(node.operator)];
6651 },
6652
6653 AssignmentExpression(node, state) {
6654 return [
6655 ...handle(node.left, state),
6656 c(` ${node.operator || '='} `),
6657 ...handle(node.right, state)
6658 ];
6659 },
6660
6661 BinaryExpression(node, state) {
6662 const chunks = [];
6663
6664 // TODO
6665 // const is_in = node.operator === 'in';
6666 // if (is_in) {
6667 // // Avoids confusion in `for` loops initializers
6668 // chunks.push(c('('));
6669 // }
6670
6671 if (needs_parens(node.left, node, false)) {
6672 chunks.push(
6673 c('('),
6674 ...handle(node.left, state),
6675 c(')')
6676 );
6677 } else {
6678 chunks.push(...handle(node.left, state));
6679 }
6680
6681 chunks.push(c(` ${node.operator} `));
6682
6683 if (needs_parens(node.right, node, true)) {
6684 chunks.push(
6685 c('('),
6686 ...handle(node.right, state),
6687 c(')')
6688 );
6689 } else {
6690 chunks.push(...handle(node.right, state));
6691 }
6692
6693 return chunks;
6694 },
6695
6696 ConditionalExpression(node, state) {
6697 const chunks = [];
6698
6699 if (
6700 EXPRESSIONS_PRECEDENCE[node.test.type] >
6701 EXPRESSIONS_PRECEDENCE.ConditionalExpression
6702 ) {
6703 chunks.push(...handle(node.test, state));
6704 } else {
6705 chunks.push(
6706 c('('),
6707 ...handle(node.test, state),
6708 c(')')
6709 );
6710 }
6711
6712 const child_state = { ...state, indent: state.indent + '\t' };
6713
6714 const consequent = handle(node.consequent, child_state);
6715 const alternate = handle(node.alternate, child_state);
6716
6717 const multiple_lines = (
6718 has_newline(consequent) || has_newline(alternate) ||
6719 get_length(chunks) + get_length(consequent) + get_length(alternate) > 50
6720 );
6721
6722 if (multiple_lines) {
6723 chunks.push(
6724 c(`\n${state.indent}? `),
6725 ...consequent,
6726 c(`\n${state.indent}: `),
6727 ...alternate
6728 );
6729 } else {
6730 chunks.push(
6731 c(` ? `),
6732 ...consequent,
6733 c(` : `),
6734 ...alternate
6735 );
6736 }
6737
6738 return chunks;
6739 },
6740
6741 NewExpression(node, state) {
6742 const chunks = [c('new ')];
6743
6744 if (
6745 EXPRESSIONS_PRECEDENCE[node.callee.type] <
6746 EXPRESSIONS_PRECEDENCE.CallExpression || has_call_expression(node.callee)
6747 ) {
6748 chunks.push(
6749 c('('),
6750 ...handle(node.callee, state),
6751 c(')')
6752 );
6753 } else {
6754 chunks.push(...handle(node.callee, state));
6755 }
6756
6757 // TODO this is copied from CallExpression — DRY it out
6758 const args = node.arguments.map(arg => handle(arg, {
6759 ...state,
6760 indent: state.indent + '\t'
6761 }));
6762
6763 const separator = args.some(has_newline) // TODO or length exceeds 80
6764 ? c(',\n' + state.indent)
6765 : c(', ');
6766
6767 chunks.push(
6768 c('('),
6769 ...join(args, separator) ,
6770 c(')')
6771 );
6772
6773 return chunks;
6774 },
6775
6776 ChainExpression(node, state) {
6777 return handle(node.expression, state);
6778 },
6779
6780 CallExpression(node, state) {
6781 const chunks = [];
6782
6783 if (
6784 EXPRESSIONS_PRECEDENCE[node.callee.type] <
6785 EXPRESSIONS_PRECEDENCE.CallExpression
6786 ) {
6787 chunks.push(
6788 c('('),
6789 ...handle(node.callee, state),
6790 c(')')
6791 );
6792 } else {
6793 chunks.push(...handle(node.callee, state));
6794 }
6795
6796 if ((node ).optional) {
6797 chunks.push(c('?.'));
6798 }
6799
6800 const args = node.arguments.map(arg => handle(arg, state));
6801
6802 const multiple_lines = args.slice(0, -1).some(has_newline); // TODO or length exceeds 80
6803
6804 if (multiple_lines) {
6805 // need to handle args again. TODO find alternative approach?
6806 const args = node.arguments.map(arg => handle(arg, {
6807 ...state,
6808 indent: `${state.indent}\t`
6809 }));
6810
6811 chunks.push(
6812 c(`(\n${state.indent}\t`),
6813 ...join(args, c(`,\n${state.indent}\t`)),
6814 c(`\n${state.indent})`)
6815 );
6816 } else {
6817 chunks.push(
6818 c('('),
6819 ...join(args, c(', ')),
6820 c(')')
6821 );
6822 }
6823
6824 return chunks;
6825 },
6826
6827 MemberExpression(node, state) {
6828 const chunks = [];
6829
6830 if (EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression) {
6831 chunks.push(
6832 c('('),
6833 ...handle(node.object, state),
6834 c(')')
6835 );
6836 } else {
6837 chunks.push(...handle(node.object, state));
6838 }
6839
6840 if (node.computed) {
6841 if (node.optional) {
6842 chunks.push(c('?.'));
6843 }
6844 chunks.push(
6845 c('['),
6846 ...handle(node.property, state),
6847 c(']')
6848 );
6849 } else {
6850 chunks.push(
6851 c(node.optional ? '?.' : '.'),
6852 ...handle(node.property, state)
6853 );
6854 }
6855
6856 return chunks;
6857 },
6858
6859 MetaProperty(node, state) {
6860 return [...handle(node.meta, state), c('.'), ...handle(node.property, state)];
6861 },
6862
6863 Identifier(node, state) {
6864 let name = node.name;
6865
6866 if (name[0] === '@') {
6867 name = state.getName(name.slice(1));
6868 } else if (node.name[0] === '#') {
6869 const owner = state.scope.find_owner(node.name);
6870
6871 if (!owner) {
6872 throw new Error(`Could not find owner for node`);
6873 }
6874
6875 if (!state.deconflicted.has(owner)) {
6876 state.deconflicted.set(owner, new Map());
6877 }
6878
6879 const deconflict_map = state.deconflicted.get(owner);
6880
6881 if (!deconflict_map.has(node.name)) {
6882 deconflict_map.set(node.name, deconflict(node.name.slice(1), owner.references));
6883 }
6884
6885 name = deconflict_map.get(node.name);
6886 }
6887
6888 return [c(name, node)];
6889 },
6890
6891 Literal(node, state) {
6892 if (typeof node.value === 'string') {
6893 return [
6894 // TODO do we need to handle weird unicode characters somehow?
6895 // str.replace(/\\u(\d{4})/g, (m, n) => String.fromCharCode(+n))
6896 c(JSON.stringify(node.value).replace(re, (_m, _i, at, hash, name) => {
6897 if (at) return '@' + name;
6898 if (hash) return '#' + name;
6899 throw new Error(`this shouldn't happen`);
6900 }), node)
6901 ];
6902 }
6903
6904 const { regex } = node ; // TODO is this right?
6905 if (regex) {
6906 return [c(`/${regex.pattern}/${regex.flags}`, node)];
6907 }
6908
6909 return [c(String(node.value), node)];
6910 }
6911 };
6912
6913 handlers.ForOfStatement = handlers.ForInStatement;
6914 handlers.FunctionExpression = handlers.FunctionDeclaration;
6915 handlers.ClassExpression = handlers.ClassDeclaration;
6916 handlers.ClassBody = handlers.BlockStatement;
6917 handlers.SpreadElement = handlers.RestElement;
6918 handlers.ArrayPattern = handlers.ArrayExpression;
6919 handlers.LogicalExpression = handlers.BinaryExpression;
6920 handlers.AssignmentPattern = handlers.AssignmentExpression;
6921
6922 let btoa = () => {
6923 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
6924 };
6925 if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
6926 btoa = (str) => window.btoa(unescape(encodeURIComponent(str)));
6927 } else if (typeof Buffer === 'function') {
6928 btoa = (str) => Buffer.from(str, 'utf-8').toString('base64');
6929 }
6930
6931
6932
6933
6934
6935
6936
6937
6938 function print(node, opts = {}) {
6939 if (Array.isArray(node)) {
6940 return print({
6941 type: 'Program',
6942 body: node
6943 } , opts);
6944 }
6945
6946 const {
6947 getName = (x) => {
6948 throw new Error(`Unhandled sigil @${x}`);
6949 }
6950 } = opts;
6951
6952 let { map: scope_map, scope } = analyze(node);
6953 const deconflicted = new WeakMap();
6954
6955 const chunks = handle(node, {
6956 indent: '',
6957 getName,
6958 scope,
6959 scope_map,
6960 deconflicted,
6961 comments: []
6962 });
6963
6964
6965
6966 let code = '';
6967 let mappings = [];
6968 let current_line = [];
6969 let current_column = 0;
6970
6971 for (let i = 0; i < chunks.length; i += 1) {
6972 const chunk = chunks[i];
6973
6974 code += chunk.content;
6975
6976 if (chunk.loc) {
6977 current_line.push([
6978 current_column,
6979 0, // source index is always zero
6980 chunk.loc.start.line - 1,
6981 chunk.loc.start.column,
6982 ]);
6983 }
6984
6985 for (let i = 0; i < chunk.content.length; i += 1) {
6986 if (chunk.content[i] === '\n') {
6987 mappings.push(current_line);
6988 current_line = [];
6989 current_column = 0;
6990 } else {
6991 current_column += 1;
6992 }
6993 }
6994
6995 if (chunk.loc) {
6996 current_line.push([
6997 current_column,
6998 0, // source index is always zero
6999 chunk.loc.end.line - 1,
7000 chunk.loc.end.column,
7001 ]);
7002 }
7003 }
7004
7005 mappings.push(current_line);
7006
7007 const map = {
7008 version: 3,
7009 names: [] ,
7010 sources: [opts.sourceMapSource || null],
7011 sourcesContent: [opts.sourceMapContent || null],
7012 mappings: encode(mappings)
7013 };
7014
7015 Object.defineProperties(map, {
7016 toString: {
7017 enumerable: false,
7018 value: function toString() {
7019 return JSON.stringify(this);
7020 }
7021 },
7022 toUrl: {
7023 enumerable: false,
7024 value: function toUrl() {
7025 return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString());
7026 }
7027 }
7028 });
7029
7030 return {
7031 code,
7032 map
7033 };
7034 }
7035
7036 const sigils = {
7037 '@': 'AT',
7038 '#': 'HASH'
7039 };
7040
7041 const join$1 = (strings) => {
7042 let str = strings[0];
7043 for (let i = 1; i < strings.length; i += 1) {
7044 str += `_${id}_${i - 1}_${strings[i]}`;
7045 }
7046 return str.replace(/([@#])(\w+)/g, (_m, sigil, name) => `_${id}_${sigils[sigil]}_${name}`);
7047 };
7048
7049 const flatten_body = (array, target) => {
7050 for (let i = 0; i < array.length; i += 1) {
7051 const statement = array[i];
7052 if (Array.isArray(statement)) {
7053 flatten_body(statement, target);
7054 continue;
7055 }
7056
7057 if (statement.type === 'ExpressionStatement') {
7058 if (statement.expression === EMPTY) continue;
7059
7060 if (Array.isArray(statement.expression)) {
7061 // TODO this is hacktacular
7062 let node = statement.expression[0];
7063 while (Array.isArray(node)) node = node[0];
7064 if (node) node.leadingComments = statement.leadingComments;
7065
7066 flatten_body(statement.expression, target);
7067 continue;
7068 }
7069
7070 if (/(Expression|Literal)$/.test(statement.expression.type)) {
7071 target.push(statement);
7072 continue;
7073 }
7074
7075 if (statement.leadingComments) statement.expression.leadingComments = statement.leadingComments;
7076 if (statement.trailingComments) statement.expression.trailingComments = statement.trailingComments;
7077
7078 target.push(statement.expression);
7079 continue;
7080 }
7081
7082 target.push(statement);
7083 }
7084
7085 return target;
7086 };
7087
7088 const flatten_properties = (array, target) => {
7089 for (let i = 0; i < array.length; i += 1) {
7090 const property = array[i];
7091
7092 if (property.value === EMPTY) continue;
7093
7094 if (property.key === property.value && Array.isArray(property.key)) {
7095 flatten_properties(property.key, target);
7096 continue;
7097 }
7098
7099 target.push(property);
7100 }
7101
7102 return target;
7103 };
7104
7105 const flatten = (nodes, target) => {
7106 for (let i = 0; i < nodes.length; i += 1) {
7107 const node = nodes[i];
7108
7109 if (node === EMPTY) continue;
7110
7111 if (Array.isArray(node)) {
7112 flatten(node, target);
7113 continue;
7114 }
7115
7116 target.push(node);
7117 }
7118
7119 return target;
7120 };
7121
7122 const EMPTY = { type: 'Empty' };
7123
7124 const acorn_opts = (comments, raw) => {
7125 const { onComment } = get_comment_handlers(comments, raw);
7126 return {
7127 ecmaVersion: 2020,
7128 sourceType: 'module',
7129 allowAwaitOutsideFunction: true,
7130 allowImportExportEverywhere: true,
7131 allowReturnOutsideFunction: true,
7132 onComment
7133 } ;
7134 };
7135
7136 const inject = (raw, node, values, comments) => {
7137 comments.forEach(comment => {
7138 comment.value = comment.value.replace(re, (m, i) => +i in values ? values[+i] : m);
7139 });
7140
7141 const { enter, leave } = get_comment_handlers(comments, raw);
7142
7143 walk(node, {
7144 enter,
7145
7146 leave(node, parent, key, index) {
7147 if (node.type === 'Identifier') {
7148 re.lastIndex = 0;
7149 const match = re.exec(node.name);
7150
7151 if (match) {
7152 if (match[1]) {
7153 if (+match[1] in values) {
7154 let value = values[+match[1]];
7155
7156 if (typeof value === 'string') {
7157 value = { type: 'Identifier', name: value, leadingComments: node.leadingComments, trailingComments: node.trailingComments };
7158 } else if (typeof value === 'number') {
7159 value = { type: 'Literal', value, leadingComments: node.leadingComments, trailingComments: node.trailingComments };
7160 }
7161
7162 this.replace(value || EMPTY);
7163 }
7164 } else {
7165 node.name = `${match[2] ? `@` : `#`}${match[4]}`;
7166 }
7167 }
7168 }
7169
7170 if (node.type === 'Literal') {
7171 if (typeof node.value === 'string') {
7172 re.lastIndex = 0;
7173 node.value = node.value.replace(re, (m, i) => +i in values ? values[+i] : m);
7174 }
7175 }
7176
7177 if (node.type === 'TemplateElement') {
7178 re.lastIndex = 0;
7179 node.value.raw = (node.value.raw ).replace(re, (m, i) => +i in values ? values[+i] : m);
7180 }
7181
7182 if (node.type === 'Program' || node.type === 'BlockStatement') {
7183 node.body = flatten_body(node.body, []);
7184 }
7185
7186 if (node.type === 'ObjectExpression' || node.type === 'ObjectPattern') {
7187 node.properties = flatten_properties(node.properties, []);
7188 }
7189
7190 if (node.type === 'ArrayExpression' || node.type === 'ArrayPattern') {
7191 node.elements = flatten(node.elements, []);
7192 }
7193
7194 if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') {
7195 node.params = flatten(node.params, []);
7196 }
7197
7198 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
7199 node.arguments = flatten(node.arguments, []);
7200 }
7201
7202 if (node.type === 'ImportDeclaration' || node.type === 'ExportNamedDeclaration') {
7203 node.specifiers = flatten(node.specifiers, []);
7204 }
7205
7206 if (node.type === 'ForStatement') {
7207 node.init = node.init === EMPTY ? null : node.init;
7208 node.test = node.test === EMPTY ? null : node.test;
7209 node.update = node.update === EMPTY ? null : node.update;
7210 }
7211
7212 leave(node);
7213 }
7214 });
7215 };
7216
7217 function b(strings, ...values) {
7218 const str = join$1(strings);
7219 const comments = [];
7220
7221 try {
7222 const ast = parse(str, acorn_opts(comments, str));
7223
7224 inject(str, ast, values, comments);
7225
7226 return ast.body;
7227 } catch (err) {
7228 handle_error(str, err);
7229 }
7230 }
7231
7232 function x(strings, ...values) {
7233 const str = join$1(strings);
7234 const comments = [];
7235
7236 try {
7237 const expression = parseExpressionAt(str, 0, acorn_opts(comments, str)) ;
7238 const match = /\S+/.exec(str.slice((expression ).end));
7239 if (match) {
7240 throw new Error(`Unexpected token '${match[0]}'`);
7241 }
7242
7243 inject(str, expression, values, comments);
7244
7245 return expression;
7246 } catch (err) {
7247 handle_error(str, err);
7248 }
7249 }
7250
7251 function p(strings, ...values) {
7252 const str = `{${join$1(strings)}}`;
7253 const comments = [];
7254
7255 try {
7256 const expression = parseExpressionAt(str, 0, acorn_opts(comments, str)) ;
7257
7258 inject(str, expression, values, comments);
7259
7260 return expression.properties[0];
7261 } catch (err) {
7262 handle_error(str, err);
7263 }
7264 }
7265
7266 function handle_error(str, err) {
7267 // TODO location/code frame
7268
7269 re.lastIndex = 0;
7270
7271 str = str.replace(re, (m, i, at, hash, name) => {
7272 if (at) return `@${name}`;
7273 if (hash) return `#${name}`;
7274
7275 return '${...}';
7276 });
7277
7278 console.log(`failed to parse:\n${str}`);
7279 throw err;
7280 }
7281
7282 const parse$1 = (source, opts) => {
7283 const comments = [];
7284 const { onComment, enter, leave } = get_comment_handlers(comments, source);
7285 const ast = parse(source, { onComment, ...opts });
7286 walk(ast , { enter, leave });
7287 return ast;
7288 };
7289
7290 const parseExpressionAt$1 = (source, index, opts) => {
7291 const comments = [];
7292 const { onComment, enter, leave } = get_comment_handlers(comments, source);
7293 const ast = parseExpressionAt(source, index, { onComment, ...opts });
7294 walk(ast , { enter, leave });
7295 return ast;
7296 };
7297
7298 const parse$2 = (source) => parse$1(source, {
7299 sourceType: 'module',
7300 ecmaVersion: 11,
7301 locations: true
7302 });
7303 const parse_expression_at = (source, index) => parseExpressionAt$1(source, index, {
7304 ecmaVersion: 11,
7305 locations: true
7306 });
7307
7308 const whitespace = /[ \t\r\n]/;
7309 const dimensions = /^(?:offset|client)(?:Width|Height)$/;
7310
7311 function read_expression(parser) {
7312 try {
7313 const node = parse_expression_at(parser.template, parser.index);
7314 let num_parens = 0;
7315 for (let i = parser.index; i < node.start; i += 1) {
7316 if (parser.template[i] === '(')
7317 num_parens += 1;
7318 }
7319 let index = node.end;
7320 while (num_parens > 0) {
7321 const char = parser.template[index];
7322 if (char === ')') {
7323 num_parens -= 1;
7324 }
7325 else if (!whitespace.test(char)) {
7326 parser.error({
7327 code: 'unexpected-token',
7328 message: 'Expected )'
7329 }, index);
7330 }
7331 index += 1;
7332 }
7333 parser.index = index;
7334 return node;
7335 }
7336 catch (err) {
7337 parser.acorn_error(err);
7338 }
7339 }
7340
7341 const script_closing_tag = '</script>';
7342 function get_context(parser, attributes, start) {
7343 const context = attributes.find(attribute => attribute.name === 'context');
7344 if (!context)
7345 return 'default';
7346 if (context.value.length !== 1 || context.value[0].type !== 'Text') {
7347 parser.error({
7348 code: 'invalid-script',
7349 message: `context attribute must be static`
7350 }, start);
7351 }
7352 const value = context.value[0].data;
7353 if (value !== 'module') {
7354 parser.error({
7355 code: `invalid-script`,
7356 message: `If the context attribute is supplied, its value must be "module"`
7357 }, context.start);
7358 }
7359 return value;
7360 }
7361 function read_script(parser, start, attributes) {
7362 const script_start = parser.index;
7363 const script_end = parser.template.indexOf(script_closing_tag, script_start);
7364 if (script_end === -1)
7365 parser.error({
7366 code: `unclosed-script`,
7367 message: `<script> must have a closing tag`
7368 });
7369 const source = parser.template.slice(0, script_start).replace(/[^\n]/g, ' ') +
7370 parser.template.slice(script_start, script_end);
7371 parser.index = script_end + script_closing_tag.length;
7372 let ast;
7373 try {
7374 ast = parse$2(source);
7375 }
7376 catch (err) {
7377 parser.acorn_error(err);
7378 }
7379 // TODO is this necessary?
7380 ast.start = script_start;
7381 return {
7382 type: 'Script',
7383 start,
7384 end: parser.index,
7385 context: get_context(parser, attributes, start),
7386 content: ast,
7387 };
7388 }
7389
7390 var MAX_LINE_LENGTH = 100;
7391 var OFFSET_CORRECTION = 60;
7392 var TAB_REPLACEMENT = ' ';
7393
7394 function sourceFragment(error, extraLines) {
7395 function processLines(start, end) {
7396 return lines.slice(start, end).map(function(line, idx) {
7397 var num = String(start + idx + 1);
7398
7399 while (num.length < maxNumLength) {
7400 num = ' ' + num;
7401 }
7402
7403 return num + ' |' + line;
7404 }).join('\n');
7405 }
7406
7407 var lines = error.source.split(/\n|\r\n?|\f/);
7408 var line = error.line;
7409 var column = error.column;
7410 var startLine = Math.max(1, line - extraLines) - 1;
7411 var endLine = Math.min(line + extraLines, lines.length + 1);
7412 var maxNumLength = Math.max(4, String(endLine).length) + 1;
7413 var cutLeft = 0;
7414
7415 // correct column according to replaced tab before column
7416 column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;
7417
7418 if (column > MAX_LINE_LENGTH) {
7419 cutLeft = column - OFFSET_CORRECTION + 3;
7420 column = OFFSET_CORRECTION - 2;
7421 }
7422
7423 for (var i = startLine; i <= endLine; i++) {
7424 if (i >= 0 && i < lines.length) {
7425 lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT);
7426 lines[i] =
7427 (cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
7428 lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
7429 (lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
7430 }
7431 }
7432
7433 return [
7434 processLines(startLine, line),
7435 new Array(column + maxNumLength + 2).join('-') + '^',
7436 processLines(line, endLine)
7437 ].join('\n');
7438 }
7439
7440 var CssSyntaxError = function(message, source, offset, line, column) {
7441 // some VMs prevent setting line/column otherwise (iOS Safari 10 even throw an exception)
7442 var error = Object.create(SyntaxError.prototype);
7443
7444 error.name = 'CssSyntaxError';
7445 error.message = message;
7446 error.stack = (new Error().stack || '').replace(/^.+\n/, error.name + ': ' + error.message + '\n');
7447 error.source = source;
7448 error.offset = offset;
7449 error.line = line;
7450 error.column = column;
7451
7452 error.sourceFragment = function(extraLines) {
7453 return sourceFragment(error, isNaN(extraLines) ? 0 : extraLines);
7454 };
7455 Object.defineProperty(error, 'formattedMessage', {
7456 get: function() {
7457 return (
7458 'Parse error: ' + error.message + '\n' +
7459 sourceFragment(error, 2)
7460 );
7461 }
7462 });
7463
7464 // for backward capability
7465 error.parseError = {
7466 offset: offset,
7467 line: line,
7468 column: column
7469 };
7470
7471 return error;
7472 };
7473
7474 var error = CssSyntaxError;
7475
7476 // token types (note: value shouldn't intersect with used char codes)
7477 var WHITESPACE = 1;
7478 var IDENTIFIER = 2;
7479 var NUMBER = 3;
7480 var STRING = 4;
7481 var COMMENT = 5;
7482 var PUNCTUATOR = 6;
7483 var CDO = 7;
7484 var CDC = 8;
7485 var ATRULE = 14;
7486 var FUNCTION = 15;
7487 var URL = 16;
7488 var RAW = 17;
7489
7490 var TAB = 9;
7491 var N = 10;
7492 var F = 12;
7493 var R = 13;
7494 var SPACE = 32;
7495
7496 var TYPE = {
7497 WhiteSpace: WHITESPACE,
7498 Identifier: IDENTIFIER,
7499 Number: NUMBER,
7500 String: STRING,
7501 Comment: COMMENT,
7502 Punctuator: PUNCTUATOR,
7503 CDO: CDO,
7504 CDC: CDC,
7505 Atrule: ATRULE,
7506 Function: FUNCTION,
7507 Url: URL,
7508 Raw: RAW,
7509
7510 ExclamationMark: 33, // !
7511 QuotationMark: 34, // "
7512 NumberSign: 35, // #
7513 DollarSign: 36, // $
7514 PercentSign: 37, // %
7515 Ampersand: 38, // &
7516 Apostrophe: 39, // '
7517 LeftParenthesis: 40, // (
7518 RightParenthesis: 41, // )
7519 Asterisk: 42, // *
7520 PlusSign: 43, // +
7521 Comma: 44, // ,
7522 HyphenMinus: 45, // -
7523 FullStop: 46, // .
7524 Solidus: 47, // /
7525 Colon: 58, // :
7526 Semicolon: 59, // ;
7527 LessThanSign: 60, // <
7528 EqualsSign: 61, // =
7529 GreaterThanSign: 62, // >
7530 QuestionMark: 63, // ?
7531 CommercialAt: 64, // @
7532 LeftSquareBracket: 91, // [
7533 Backslash: 92, // \
7534 RightSquareBracket: 93, // ]
7535 CircumflexAccent: 94, // ^
7536 LowLine: 95, // _
7537 GraveAccent: 96, // `
7538 LeftCurlyBracket: 123, // {
7539 VerticalLine: 124, // |
7540 RightCurlyBracket: 125, // }
7541 Tilde: 126 // ~
7542 };
7543
7544 var NAME = Object.keys(TYPE).reduce(function(result, key) {
7545 result[TYPE[key]] = key;
7546 return result;
7547 }, {});
7548
7549 // https://drafts.csswg.org/css-syntax/#tokenizer-definitions
7550 // > non-ASCII code point
7551 // > A code point with a value equal to or greater than U+0080 <control>
7552 // > name-start code point
7553 // > A letter, a non-ASCII code point, or U+005F LOW LINE (_).
7554 // > name code point
7555 // > A name-start code point, a digit, or U+002D HYPHEN-MINUS (-)
7556 // That means only ASCII code points has a special meaning and we a maps for 0..127 codes only
7557 var SafeUint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
7558 var SYMBOL_TYPE = new SafeUint32Array(0x80);
7559 var PUNCTUATION = new SafeUint32Array(0x80);
7560 var STOP_URL_RAW = new SafeUint32Array(0x80);
7561
7562 for (var i = 0; i < SYMBOL_TYPE.length; i++) {
7563 SYMBOL_TYPE[i] = IDENTIFIER;
7564 }
7565
7566 // fill categories
7567 [
7568 TYPE.ExclamationMark, // !
7569 TYPE.QuotationMark, // "
7570 TYPE.NumberSign, // #
7571 TYPE.DollarSign, // $
7572 TYPE.PercentSign, // %
7573 TYPE.Ampersand, // &
7574 TYPE.Apostrophe, // '
7575 TYPE.LeftParenthesis, // (
7576 TYPE.RightParenthesis, // )
7577 TYPE.Asterisk, // *
7578 TYPE.PlusSign, // +
7579 TYPE.Comma, // ,
7580 TYPE.HyphenMinus, // -
7581 TYPE.FullStop, // .
7582 TYPE.Solidus, // /
7583 TYPE.Colon, // :
7584 TYPE.Semicolon, // ;
7585 TYPE.LessThanSign, // <
7586 TYPE.EqualsSign, // =
7587 TYPE.GreaterThanSign, // >
7588 TYPE.QuestionMark, // ?
7589 TYPE.CommercialAt, // @
7590 TYPE.LeftSquareBracket, // [
7591 // TYPE.Backslash, // \
7592 TYPE.RightSquareBracket, // ]
7593 TYPE.CircumflexAccent, // ^
7594 // TYPE.LowLine, // _
7595 TYPE.GraveAccent, // `
7596 TYPE.LeftCurlyBracket, // {
7597 TYPE.VerticalLine, // |
7598 TYPE.RightCurlyBracket, // }
7599 TYPE.Tilde // ~
7600 ].forEach(function(key) {
7601 SYMBOL_TYPE[Number(key)] = PUNCTUATOR;
7602 PUNCTUATION[Number(key)] = PUNCTUATOR;
7603 });
7604
7605 for (var i = 48; i <= 57; i++) {
7606 SYMBOL_TYPE[i] = NUMBER;
7607 }
7608
7609 SYMBOL_TYPE[SPACE] = WHITESPACE;
7610 SYMBOL_TYPE[TAB] = WHITESPACE;
7611 SYMBOL_TYPE[N] = WHITESPACE;
7612 SYMBOL_TYPE[R] = WHITESPACE;
7613 SYMBOL_TYPE[F] = WHITESPACE;
7614
7615 SYMBOL_TYPE[TYPE.Apostrophe] = STRING;
7616 SYMBOL_TYPE[TYPE.QuotationMark] = STRING;
7617
7618 STOP_URL_RAW[SPACE] = 1;
7619 STOP_URL_RAW[TAB] = 1;
7620 STOP_URL_RAW[N] = 1;
7621 STOP_URL_RAW[R] = 1;
7622 STOP_URL_RAW[F] = 1;
7623 STOP_URL_RAW[TYPE.Apostrophe] = 1;
7624 STOP_URL_RAW[TYPE.QuotationMark] = 1;
7625 STOP_URL_RAW[TYPE.LeftParenthesis] = 1;
7626 STOP_URL_RAW[TYPE.RightParenthesis] = 1;
7627
7628 // whitespace is punctuation ...
7629 PUNCTUATION[SPACE] = PUNCTUATOR;
7630 PUNCTUATION[TAB] = PUNCTUATOR;
7631 PUNCTUATION[N] = PUNCTUATOR;
7632 PUNCTUATION[R] = PUNCTUATOR;
7633 PUNCTUATION[F] = PUNCTUATOR;
7634 // ... hyper minus is not
7635 PUNCTUATION[TYPE.HyphenMinus] = 0;
7636
7637 var _const = {
7638 TYPE: TYPE,
7639 NAME: NAME,
7640
7641 SYMBOL_TYPE: SYMBOL_TYPE,
7642 PUNCTUATION: PUNCTUATION,
7643 STOP_URL_RAW: STOP_URL_RAW
7644 };
7645
7646 var PUNCTUATION$1 = _const.PUNCTUATION;
7647 var STOP_URL_RAW$1 = _const.STOP_URL_RAW;
7648 var TYPE$1 = _const.TYPE;
7649 var FULLSTOP = TYPE$1.FullStop;
7650 var PLUSSIGN = TYPE$1.PlusSign;
7651 var HYPHENMINUS = TYPE$1.HyphenMinus;
7652 var PUNCTUATOR$1 = TYPE$1.Punctuator;
7653 var TAB$1 = 9;
7654 var N$1 = 10;
7655 var F$1 = 12;
7656 var R$1 = 13;
7657 var SPACE$1 = 32;
7658 var BACK_SLASH = 92;
7659 var E = 101; // 'e'.charCodeAt(0)
7660
7661 function firstCharOffset(source) {
7662 // detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
7663 if (source.charCodeAt(0) === 0xFEFF || // UTF-16BE
7664 source.charCodeAt(0) === 0xFFFE) { // UTF-16LE
7665 return 1;
7666 }
7667
7668 return 0;
7669 }
7670
7671 function isHex(code) {
7672 return (code >= 48 && code <= 57) || // 0 .. 9
7673 (code >= 65 && code <= 70) || // A .. F
7674 (code >= 97 && code <= 102); // a .. f
7675 }
7676
7677 function isNumber(code) {
7678 return code >= 48 && code <= 57;
7679 }
7680
7681 function isNewline(source, offset, code) {
7682 if (code === N$1 || code === F$1 || code === R$1) {
7683 if (code === R$1 && offset + 1 < source.length && source.charCodeAt(offset + 1) === N$1) {
7684 return 2;
7685 }
7686
7687 return 1;
7688 }
7689
7690 return 0;
7691 }
7692
7693 function cmpChar(testStr, offset, referenceCode) {
7694 var code = testStr.charCodeAt(offset);
7695
7696 // code.toLowerCase()
7697 if (code >= 65 && code <= 90) {
7698 code = code | 32;
7699 }
7700
7701 return code === referenceCode;
7702 }
7703
7704 function cmpStr(testStr, start, end, referenceStr) {
7705 if (end - start !== referenceStr.length) {
7706 return false;
7707 }
7708
7709 if (start < 0 || end > testStr.length) {
7710 return false;
7711 }
7712
7713 for (var i = start; i < end; i++) {
7714 var testCode = testStr.charCodeAt(i);
7715 var refCode = referenceStr.charCodeAt(i - start);
7716
7717 // testStr[i].toLowerCase()
7718 if (testCode >= 65 && testCode <= 90) {
7719 testCode = testCode | 32;
7720 }
7721
7722 if (testCode !== refCode) {
7723 return false;
7724 }
7725 }
7726
7727 return true;
7728 }
7729
7730 function endsWith(testStr, referenceStr) {
7731 return cmpStr(testStr, testStr.length - referenceStr.length, testStr.length, referenceStr);
7732 }
7733
7734 function findLastNonSpaceLocation(scanner) {
7735 for (var i = scanner.source.length - 1; i >= 0; i--) {
7736 var code = scanner.source.charCodeAt(i);
7737
7738 if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
7739 break;
7740 }
7741 }
7742
7743 return scanner.getLocation(i + 1);
7744 }
7745
7746 function findWhiteSpaceEnd(source, offset) {
7747 for (; offset < source.length; offset++) {
7748 var code = source.charCodeAt(offset);
7749
7750 if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
7751 break;
7752 }
7753 }
7754
7755 return offset;
7756 }
7757
7758 function findCommentEnd(source, offset) {
7759 var commentEnd = source.indexOf('*/', offset);
7760
7761 if (commentEnd === -1) {
7762 return source.length;
7763 }
7764
7765 return commentEnd + 2;
7766 }
7767
7768 function findStringEnd(source, offset, quote) {
7769 for (; offset < source.length; offset++) {
7770 var code = source.charCodeAt(offset);
7771
7772 // TODO: bad string
7773 if (code === BACK_SLASH) {
7774 offset++;
7775 } else if (code === quote) {
7776 offset++;
7777 break;
7778 }
7779 }
7780
7781 return offset;
7782 }
7783
7784 function findDecimalNumberEnd(source, offset) {
7785 for (; offset < source.length; offset++) {
7786 var code = source.charCodeAt(offset);
7787
7788 if (code < 48 || code > 57) { // not a 0 .. 9
7789 break;
7790 }
7791 }
7792
7793 return offset;
7794 }
7795
7796 function findNumberEnd(source, offset, allowFraction) {
7797 var code;
7798
7799 offset = findDecimalNumberEnd(source, offset);
7800
7801 // fraction: .\d+
7802 if (allowFraction && offset + 1 < source.length && source.charCodeAt(offset) === FULLSTOP) {
7803 code = source.charCodeAt(offset + 1);
7804
7805 if (isNumber(code)) {
7806 offset = findDecimalNumberEnd(source, offset + 1);
7807 }
7808 }
7809
7810 // exponent: e[+-]\d+
7811 if (offset + 1 < source.length) {
7812 if ((source.charCodeAt(offset) | 32) === E) { // case insensitive check for `e`
7813 code = source.charCodeAt(offset + 1);
7814
7815 if (code === PLUSSIGN || code === HYPHENMINUS) {
7816 if (offset + 2 < source.length) {
7817 code = source.charCodeAt(offset + 2);
7818 }
7819 }
7820
7821 if (isNumber(code)) {
7822 offset = findDecimalNumberEnd(source, offset + 2);
7823 }
7824 }
7825 }
7826
7827 return offset;
7828 }
7829
7830 // skip escaped unicode sequence that can ends with space
7831 // [0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
7832 function findEscaseEnd(source, offset) {
7833 for (var i = 0; i < 7 && offset + i < source.length; i++) {
7834 var code = source.charCodeAt(offset + i);
7835
7836 if (i !== 6 && isHex(code)) {
7837 continue;
7838 }
7839
7840 if (i > 0) {
7841 offset += i - 1 + isNewline(source, offset + i, code);
7842 if (code === SPACE$1 || code === TAB$1) {
7843 offset++;
7844 }
7845 }
7846
7847 break;
7848 }
7849
7850 return offset;
7851 }
7852
7853 function findIdentifierEnd(source, offset) {
7854 for (; offset < source.length; offset++) {
7855 var code = source.charCodeAt(offset);
7856
7857 if (code === BACK_SLASH) {
7858 offset = findEscaseEnd(source, offset + 1);
7859 } else if (code < 0x80 && PUNCTUATION$1[code] === PUNCTUATOR$1) {
7860 break;
7861 }
7862 }
7863
7864 return offset;
7865 }
7866
7867 function findUrlRawEnd(source, offset) {
7868 for (; offset < source.length; offset++) {
7869 var code = source.charCodeAt(offset);
7870
7871 if (code === BACK_SLASH) {
7872 offset = findEscaseEnd(source, offset + 1);
7873 } else if (code < 0x80 && STOP_URL_RAW$1[code] === 1) {
7874 break;
7875 }
7876 }
7877
7878 return offset;
7879 }
7880
7881 var utils = {
7882 firstCharOffset: firstCharOffset,
7883
7884 isHex: isHex,
7885 isNumber: isNumber,
7886 isNewline: isNewline,
7887
7888 cmpChar: cmpChar,
7889 cmpStr: cmpStr,
7890 endsWith: endsWith,
7891
7892 findLastNonSpaceLocation: findLastNonSpaceLocation,
7893 findWhiteSpaceEnd: findWhiteSpaceEnd,
7894 findCommentEnd: findCommentEnd,
7895 findStringEnd: findStringEnd,
7896 findDecimalNumberEnd: findDecimalNumberEnd,
7897 findNumberEnd: findNumberEnd,
7898 findEscaseEnd: findEscaseEnd,
7899 findIdentifierEnd: findIdentifierEnd,
7900 findUrlRawEnd: findUrlRawEnd
7901 };
7902
7903 var TYPE$2 = _const.TYPE;
7904 var NAME$1 = _const.NAME;
7905 var SYMBOL_TYPE$1 = _const.SYMBOL_TYPE;
7906
7907
7908 var firstCharOffset$1 = utils.firstCharOffset;
7909 var cmpStr$1 = utils.cmpStr;
7910 var isNumber$1 = utils.isNumber;
7911 var findLastNonSpaceLocation$1 = utils.findLastNonSpaceLocation;
7912 var findWhiteSpaceEnd$1 = utils.findWhiteSpaceEnd;
7913 var findCommentEnd$1 = utils.findCommentEnd;
7914 var findStringEnd$1 = utils.findStringEnd;
7915 var findNumberEnd$1 = utils.findNumberEnd;
7916 var findIdentifierEnd$1 = utils.findIdentifierEnd;
7917 var findUrlRawEnd$1 = utils.findUrlRawEnd;
7918
7919 var NULL = 0;
7920 var WHITESPACE$1 = TYPE$2.WhiteSpace;
7921 var IDENTIFIER$1 = TYPE$2.Identifier;
7922 var NUMBER$1 = TYPE$2.Number;
7923 var STRING$1 = TYPE$2.String;
7924 var COMMENT$1 = TYPE$2.Comment;
7925 var PUNCTUATOR$2 = TYPE$2.Punctuator;
7926 var CDO$1 = TYPE$2.CDO;
7927 var CDC$1 = TYPE$2.CDC;
7928 var ATRULE$1 = TYPE$2.Atrule;
7929 var FUNCTION$1 = TYPE$2.Function;
7930 var URL$1 = TYPE$2.Url;
7931 var RAW$1 = TYPE$2.Raw;
7932
7933 var N$2 = 10;
7934 var F$2 = 12;
7935 var R$2 = 13;
7936 var STAR = TYPE$2.Asterisk;
7937 var SLASH = TYPE$2.Solidus;
7938 var FULLSTOP$1 = TYPE$2.FullStop;
7939 var PLUSSIGN$1 = TYPE$2.PlusSign;
7940 var HYPHENMINUS$1 = TYPE$2.HyphenMinus;
7941 var GREATERTHANSIGN = TYPE$2.GreaterThanSign;
7942 var LESSTHANSIGN = TYPE$2.LessThanSign;
7943 var EXCLAMATIONMARK = TYPE$2.ExclamationMark;
7944 var COMMERCIALAT = TYPE$2.CommercialAt;
7945 var QUOTATIONMARK = TYPE$2.QuotationMark;
7946 var APOSTROPHE = TYPE$2.Apostrophe;
7947 var LEFTPARENTHESIS = TYPE$2.LeftParenthesis;
7948 var RIGHTPARENTHESIS = TYPE$2.RightParenthesis;
7949 var LEFTCURLYBRACKET = TYPE$2.LeftCurlyBracket;
7950 var RIGHTCURLYBRACKET = TYPE$2.RightCurlyBracket;
7951 var LEFTSQUAREBRACKET = TYPE$2.LeftSquareBracket;
7952 var RIGHTSQUAREBRACKET = TYPE$2.RightSquareBracket;
7953
7954 var MIN_BUFFER_SIZE = 16 * 1024;
7955 var OFFSET_MASK = 0x00FFFFFF;
7956 var TYPE_SHIFT = 24;
7957 var SafeUint32Array$1 = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
7958
7959 function computeLinesAndColumns(tokenizer, source) {
7960 var sourceLength = source.length;
7961 var start = firstCharOffset$1(source);
7962 var lines = tokenizer.lines;
7963 var line = tokenizer.startLine;
7964 var columns = tokenizer.columns;
7965 var column = tokenizer.startColumn;
7966
7967 if (lines === null || lines.length < sourceLength + 1) {
7968 lines = new SafeUint32Array$1(Math.max(sourceLength + 1024, MIN_BUFFER_SIZE));
7969 columns = new SafeUint32Array$1(lines.length);
7970 }
7971
7972 for (var i = start; i < sourceLength; i++) {
7973 var code = source.charCodeAt(i);
7974
7975 lines[i] = line;
7976 columns[i] = column++;
7977
7978 if (code === N$2 || code === R$2 || code === F$2) {
7979 if (code === R$2 && i + 1 < sourceLength && source.charCodeAt(i + 1) === N$2) {
7980 i++;
7981 lines[i] = line;
7982 columns[i] = column;
7983 }
7984
7985 line++;
7986 column = 1;
7987 }
7988 }
7989
7990 lines[i] = line;
7991 columns[i] = column;
7992
7993 tokenizer.linesAnsColumnsComputed = true;
7994 tokenizer.lines = lines;
7995 tokenizer.columns = columns;
7996 }
7997
7998 function tokenLayout(tokenizer, source, startPos) {
7999 var sourceLength = source.length;
8000 var offsetAndType = tokenizer.offsetAndType;
8001 var balance = tokenizer.balance;
8002 var tokenCount = 0;
8003 var prevType = 0;
8004 var offset = startPos;
8005 var anchor = 0;
8006 var balanceCloseCode = 0;
8007 var balanceStart = 0;
8008 var balancePrev = 0;
8009
8010 if (offsetAndType === null || offsetAndType.length < sourceLength + 1) {
8011 offsetAndType = new SafeUint32Array$1(sourceLength + 1024);
8012 balance = new SafeUint32Array$1(sourceLength + 1024);
8013 }
8014
8015 while (offset < sourceLength) {
8016 var code = source.charCodeAt(offset);
8017 var type = code < 0x80 ? SYMBOL_TYPE$1[code] : IDENTIFIER$1;
8018
8019 balance[tokenCount] = sourceLength;
8020
8021 switch (type) {
8022 case WHITESPACE$1:
8023 offset = findWhiteSpaceEnd$1(source, offset + 1);
8024 break;
8025
8026 case PUNCTUATOR$2:
8027 switch (code) {
8028 case balanceCloseCode:
8029 balancePrev = balanceStart & OFFSET_MASK;
8030 balanceStart = balance[balancePrev];
8031 balanceCloseCode = balanceStart >> TYPE_SHIFT;
8032 balance[tokenCount] = balancePrev;
8033 balance[balancePrev++] = tokenCount;
8034 for (; balancePrev < tokenCount; balancePrev++) {
8035 if (balance[balancePrev] === sourceLength) {
8036 balance[balancePrev] = tokenCount;
8037 }
8038 }
8039 break;
8040
8041 case LEFTSQUAREBRACKET:
8042 balance[tokenCount] = balanceStart;
8043 balanceCloseCode = RIGHTSQUAREBRACKET;
8044 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8045 break;
8046
8047 case LEFTCURLYBRACKET:
8048 balance[tokenCount] = balanceStart;
8049 balanceCloseCode = RIGHTCURLYBRACKET;
8050 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8051 break;
8052
8053 case LEFTPARENTHESIS:
8054 balance[tokenCount] = balanceStart;
8055 balanceCloseCode = RIGHTPARENTHESIS;
8056 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8057 break;
8058 }
8059
8060 // /*
8061 if (code === STAR && prevType === SLASH) {
8062 type = COMMENT$1;
8063 offset = findCommentEnd$1(source, offset + 1);
8064 tokenCount--; // rewrite prev token
8065 break;
8066 }
8067
8068 // edge case for -.123 and +.123
8069 if (code === FULLSTOP$1 && (prevType === PLUSSIGN$1 || prevType === HYPHENMINUS$1)) {
8070 if (offset + 1 < sourceLength && isNumber$1(source.charCodeAt(offset + 1))) {
8071 type = NUMBER$1;
8072 offset = findNumberEnd$1(source, offset + 2, false);
8073 tokenCount--; // rewrite prev token
8074 break;
8075 }
8076 }
8077
8078 // <!--
8079 if (code === EXCLAMATIONMARK && prevType === LESSTHANSIGN) {
8080 if (offset + 2 < sourceLength &&
8081 source.charCodeAt(offset + 1) === HYPHENMINUS$1 &&
8082 source.charCodeAt(offset + 2) === HYPHENMINUS$1) {
8083 type = CDO$1;
8084 offset = offset + 3;
8085 tokenCount--; // rewrite prev token
8086 break;
8087 }
8088 }
8089
8090 // -->
8091 if (code === HYPHENMINUS$1 && prevType === HYPHENMINUS$1) {
8092 if (offset + 1 < sourceLength && source.charCodeAt(offset + 1) === GREATERTHANSIGN) {
8093 type = CDC$1;
8094 offset = offset + 2;
8095 tokenCount--; // rewrite prev token
8096 break;
8097 }
8098 }
8099
8100 // ident(
8101 if (code === LEFTPARENTHESIS && prevType === IDENTIFIER$1) {
8102 offset = offset + 1;
8103 tokenCount--; // rewrite prev token
8104 balance[tokenCount] = balance[tokenCount + 1];
8105 balanceStart--;
8106
8107 // 4 char length identifier and equal to `url(` (case insensitive)
8108 if (offset - anchor === 4 && cmpStr$1(source, anchor, offset, 'url(')) {
8109 // special case for url() because it can contain any symbols sequence with few exceptions
8110 anchor = findWhiteSpaceEnd$1(source, offset);
8111 code = source.charCodeAt(anchor);
8112 if (code !== LEFTPARENTHESIS &&
8113 code !== RIGHTPARENTHESIS &&
8114 code !== QUOTATIONMARK &&
8115 code !== APOSTROPHE) {
8116 // url(
8117 offsetAndType[tokenCount++] = (URL$1 << TYPE_SHIFT) | offset;
8118 balance[tokenCount] = sourceLength;
8119
8120 // ws*
8121 if (anchor !== offset) {
8122 offsetAndType[tokenCount++] = (WHITESPACE$1 << TYPE_SHIFT) | anchor;
8123 balance[tokenCount] = sourceLength;
8124 }
8125
8126 // raw
8127 type = RAW$1;
8128 offset = findUrlRawEnd$1(source, anchor);
8129 } else {
8130 type = URL$1;
8131 }
8132 } else {
8133 type = FUNCTION$1;
8134 }
8135 break;
8136 }
8137
8138 type = code;
8139 offset = offset + 1;
8140 break;
8141
8142 case NUMBER$1:
8143 offset = findNumberEnd$1(source, offset + 1, prevType !== FULLSTOP$1);
8144
8145 // merge number with a preceding dot, dash or plus
8146 if (prevType === FULLSTOP$1 ||
8147 prevType === HYPHENMINUS$1 ||
8148 prevType === PLUSSIGN$1) {
8149 tokenCount--; // rewrite prev token
8150 }
8151
8152 break;
8153
8154 case STRING$1:
8155 offset = findStringEnd$1(source, offset + 1, code);
8156 break;
8157
8158 default:
8159 anchor = offset;
8160 offset = findIdentifierEnd$1(source, offset);
8161
8162 // merge identifier with a preceding dash
8163 if (prevType === HYPHENMINUS$1) {
8164 // rewrite prev token
8165 tokenCount--;
8166 // restore prev prev token type
8167 // for case @-prefix-ident
8168 prevType = tokenCount === 0 ? 0 : offsetAndType[tokenCount - 1] >> TYPE_SHIFT;
8169 }
8170
8171 if (prevType === COMMERCIALAT) {
8172 // rewrite prev token and change type to <at-keyword-token>
8173 tokenCount--;
8174 type = ATRULE$1;
8175 }
8176 }
8177
8178 offsetAndType[tokenCount++] = (type << TYPE_SHIFT) | offset;
8179 prevType = type;
8180 }
8181
8182 // finalize arrays
8183 offsetAndType[tokenCount] = offset;
8184 balance[tokenCount] = sourceLength;
8185 while (balanceStart !== 0) {
8186 balancePrev = balanceStart & OFFSET_MASK;
8187 balanceStart = balance[balancePrev];
8188 balance[balancePrev] = sourceLength;
8189 }
8190
8191 tokenizer.offsetAndType = offsetAndType;
8192 tokenizer.tokenCount = tokenCount;
8193 tokenizer.balance = balance;
8194 }
8195
8196 //
8197 // tokenizer
8198 //
8199
8200 var Tokenizer = function(source, startOffset, startLine, startColumn) {
8201 this.offsetAndType = null;
8202 this.balance = null;
8203 this.lines = null;
8204 this.columns = null;
8205
8206 this.setSource(source, startOffset, startLine, startColumn);
8207 };
8208
8209 Tokenizer.prototype = {
8210 setSource: function(source, startOffset, startLine, startColumn) {
8211 var safeSource = String(source || '');
8212 var start = firstCharOffset$1(safeSource);
8213
8214 this.source = safeSource;
8215 this.firstCharOffset = start;
8216 this.startOffset = typeof startOffset === 'undefined' ? 0 : startOffset;
8217 this.startLine = typeof startLine === 'undefined' ? 1 : startLine;
8218 this.startColumn = typeof startColumn === 'undefined' ? 1 : startColumn;
8219 this.linesAnsColumnsComputed = false;
8220
8221 this.eof = false;
8222 this.currentToken = -1;
8223 this.tokenType = 0;
8224 this.tokenStart = start;
8225 this.tokenEnd = start;
8226
8227 tokenLayout(this, safeSource, start);
8228 this.next();
8229 },
8230
8231 lookupType: function(offset) {
8232 offset += this.currentToken;
8233
8234 if (offset < this.tokenCount) {
8235 return this.offsetAndType[offset] >> TYPE_SHIFT;
8236 }
8237
8238 return NULL;
8239 },
8240 lookupNonWSType: function(offset) {
8241 offset += this.currentToken;
8242
8243 for (var type; offset < this.tokenCount; offset++) {
8244 type = this.offsetAndType[offset] >> TYPE_SHIFT;
8245
8246 if (type !== WHITESPACE$1) {
8247 return type;
8248 }
8249 }
8250
8251 return NULL;
8252 },
8253 lookupValue: function(offset, referenceStr) {
8254 offset += this.currentToken;
8255
8256 if (offset < this.tokenCount) {
8257 return cmpStr$1(
8258 this.source,
8259 this.offsetAndType[offset - 1] & OFFSET_MASK,
8260 this.offsetAndType[offset] & OFFSET_MASK,
8261 referenceStr
8262 );
8263 }
8264
8265 return false;
8266 },
8267 getTokenStart: function(tokenNum) {
8268 if (tokenNum === this.currentToken) {
8269 return this.tokenStart;
8270 }
8271
8272 if (tokenNum > 0) {
8273 return tokenNum < this.tokenCount
8274 ? this.offsetAndType[tokenNum - 1] & OFFSET_MASK
8275 : this.offsetAndType[this.tokenCount] & OFFSET_MASK;
8276 }
8277
8278 return this.firstCharOffset;
8279 },
8280 getOffsetExcludeWS: function() {
8281 if (this.currentToken > 0) {
8282 if ((this.offsetAndType[this.currentToken - 1] >> TYPE_SHIFT) === WHITESPACE$1) {
8283 return this.currentToken > 1
8284 ? this.offsetAndType[this.currentToken - 2] & OFFSET_MASK
8285 : this.firstCharOffset;
8286 }
8287 }
8288 return this.tokenStart;
8289 },
8290 getRawLength: function(startToken, endTokenType1, endTokenType2, includeTokenType2) {
8291 var cursor = startToken;
8292 var balanceEnd;
8293
8294 loop:
8295 for (; cursor < this.tokenCount; cursor++) {
8296 balanceEnd = this.balance[cursor];
8297
8298 // belance end points to offset before start
8299 if (balanceEnd < startToken) {
8300 break loop;
8301 }
8302
8303 // check token is stop type
8304 switch (this.offsetAndType[cursor] >> TYPE_SHIFT) {
8305 case endTokenType1:
8306 break loop;
8307
8308 case endTokenType2:
8309 if (includeTokenType2) {
8310 cursor++;
8311 }
8312 break loop;
8313
8314 default:
8315 // fast forward to the end of balanced block
8316 if (this.balance[balanceEnd] === cursor) {
8317 cursor = balanceEnd;
8318 }
8319 }
8320
8321 }
8322
8323 return cursor - this.currentToken;
8324 },
8325
8326 getTokenValue: function() {
8327 return this.source.substring(this.tokenStart, this.tokenEnd);
8328 },
8329 substrToCursor: function(start) {
8330 return this.source.substring(start, this.tokenStart);
8331 },
8332
8333 skipWS: function() {
8334 for (var i = this.currentToken, skipTokenCount = 0; i < this.tokenCount; i++, skipTokenCount++) {
8335 if ((this.offsetAndType[i] >> TYPE_SHIFT) !== WHITESPACE$1) {
8336 break;
8337 }
8338 }
8339
8340 if (skipTokenCount > 0) {
8341 this.skip(skipTokenCount);
8342 }
8343 },
8344 skipSC: function() {
8345 while (this.tokenType === WHITESPACE$1 || this.tokenType === COMMENT$1) {
8346 this.next();
8347 }
8348 },
8349 skip: function(tokenCount) {
8350 var next = this.currentToken + tokenCount;
8351
8352 if (next < this.tokenCount) {
8353 this.currentToken = next;
8354 this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
8355 next = this.offsetAndType[next];
8356 this.tokenType = next >> TYPE_SHIFT;
8357 this.tokenEnd = next & OFFSET_MASK;
8358 } else {
8359 this.currentToken = this.tokenCount;
8360 this.next();
8361 }
8362 },
8363 next: function() {
8364 var next = this.currentToken + 1;
8365
8366 if (next < this.tokenCount) {
8367 this.currentToken = next;
8368 this.tokenStart = this.tokenEnd;
8369 next = this.offsetAndType[next];
8370 this.tokenType = next >> TYPE_SHIFT;
8371 this.tokenEnd = next & OFFSET_MASK;
8372 } else {
8373 this.currentToken = this.tokenCount;
8374 this.eof = true;
8375 this.tokenType = NULL;
8376 this.tokenStart = this.tokenEnd = this.source.length;
8377 }
8378 },
8379
8380 eat: function(tokenType) {
8381 if (this.tokenType !== tokenType) {
8382 var offset = this.tokenStart;
8383 var message = NAME$1[tokenType] + ' is expected';
8384
8385 // tweak message and offset
8386 if (tokenType === IDENTIFIER$1) {
8387 // when identifier is expected but there is a function or url
8388 if (this.tokenType === FUNCTION$1 || this.tokenType === URL$1) {
8389 offset = this.tokenEnd - 1;
8390 message += ' but function found';
8391 }
8392 } else {
8393 // when test type is part of another token show error for current position + 1
8394 // e.g. eat(HYPHENMINUS) will fail on "-foo", but pointing on "-" is odd
8395 if (this.source.charCodeAt(this.tokenStart) === tokenType) {
8396 offset = offset + 1;
8397 }
8398 }
8399
8400 this.error(message, offset);
8401 }
8402
8403 this.next();
8404 },
8405 eatNonWS: function(tokenType) {
8406 this.skipWS();
8407 this.eat(tokenType);
8408 },
8409
8410 consume: function(tokenType) {
8411 var value = this.getTokenValue();
8412
8413 this.eat(tokenType);
8414
8415 return value;
8416 },
8417 consumeFunctionName: function() {
8418 var name = this.source.substring(this.tokenStart, this.tokenEnd - 1);
8419
8420 this.eat(FUNCTION$1);
8421
8422 return name;
8423 },
8424 consumeNonWS: function(tokenType) {
8425 this.skipWS();
8426
8427 return this.consume(tokenType);
8428 },
8429
8430 expectIdentifier: function(name) {
8431 if (this.tokenType !== IDENTIFIER$1 || cmpStr$1(this.source, this.tokenStart, this.tokenEnd, name) === false) {
8432 this.error('Identifier `' + name + '` is expected');
8433 }
8434
8435 this.next();
8436 },
8437
8438 getLocation: function(offset, filename) {
8439 if (!this.linesAnsColumnsComputed) {
8440 computeLinesAndColumns(this, this.source);
8441 }
8442
8443 return {
8444 source: filename,
8445 offset: this.startOffset + offset,
8446 line: this.lines[offset],
8447 column: this.columns[offset]
8448 };
8449 },
8450
8451 getLocationRange: function(start, end, filename) {
8452 if (!this.linesAnsColumnsComputed) {
8453 computeLinesAndColumns(this, this.source);
8454 }
8455
8456 return {
8457 source: filename,
8458 start: {
8459 offset: this.startOffset + start,
8460 line: this.lines[start],
8461 column: this.columns[start]
8462 },
8463 end: {
8464 offset: this.startOffset + end,
8465 line: this.lines[end],
8466 column: this.columns[end]
8467 }
8468 };
8469 },
8470
8471 error: function(message, offset) {
8472 var location = typeof offset !== 'undefined' && offset < this.source.length
8473 ? this.getLocation(offset)
8474 : this.eof
8475 ? findLastNonSpaceLocation$1(this)
8476 : this.getLocation(this.tokenStart);
8477
8478 throw new error(
8479 message || 'Unexpected input',
8480 this.source,
8481 location.offset,
8482 location.line,
8483 location.column
8484 );
8485 },
8486
8487 dump: function() {
8488 var offset = 0;
8489
8490 return Array.prototype.slice.call(this.offsetAndType, 0, this.tokenCount).map(function(item, idx) {
8491 var start = offset;
8492 var end = item & OFFSET_MASK;
8493
8494 offset = end;
8495
8496 return {
8497 idx: idx,
8498 type: NAME$1[item >> TYPE_SHIFT],
8499 chunk: this.source.substring(start, end),
8500 balance: this.balance[idx]
8501 };
8502 }, this);
8503 }
8504 };
8505
8506 // extend with error class
8507 Tokenizer.CssSyntaxError = error;
8508
8509 // extend tokenizer with constants
8510 Object.keys(_const).forEach(function(key) {
8511 Tokenizer[key] = _const[key];
8512 });
8513
8514 // extend tokenizer with static methods from utils
8515 Object.keys(utils).forEach(function(key) {
8516 Tokenizer[key] = utils[key];
8517 });
8518
8519 // warm up tokenizer to elimitate code branches that never execute
8520 // fix soft deoptimizations (insufficient type feedback)
8521 new Tokenizer('\n\r\r\n\f<!---->//""\'\'/*\r\n\f*/1a;.\\31\t\+2{url(a);func();+1.2e3 -.4e-5 .6e+7}').getLocation();
8522
8523 var Tokenizer_1 = Tokenizer;
8524
8525 var tokenizer = Tokenizer_1;
8526
8527 //
8528 // item item item item
8529 // /------\ /------\ /------\ /------\
8530 // | data | | data | | data | | data |
8531 // null <--+-prev |<---+-prev |<---+-prev |<---+-prev |
8532 // | next-+--->| next-+--->| next-+--->| next-+--> null
8533 // \------/ \------/ \------/ \------/
8534 // ^ ^
8535 // | list |
8536 // | /------\ |
8537 // \--------------+-head | |
8538 // | tail-+--------------/
8539 // \------/
8540 //
8541
8542 function createItem(data) {
8543 return {
8544 prev: null,
8545 next: null,
8546 data: data
8547 };
8548 }
8549
8550 var cursors = null;
8551 var List = function() {
8552 this.cursor = null;
8553 this.head = null;
8554 this.tail = null;
8555 };
8556
8557 List.createItem = createItem;
8558 List.prototype.createItem = createItem;
8559
8560 List.prototype.getSize = function() {
8561 var size = 0;
8562 var cursor = this.head;
8563
8564 while (cursor) {
8565 size++;
8566 cursor = cursor.next;
8567 }
8568
8569 return size;
8570 };
8571
8572 List.prototype.fromArray = function(array) {
8573 var cursor = null;
8574
8575 this.head = null;
8576
8577 for (var i = 0; i < array.length; i++) {
8578 var item = createItem(array[i]);
8579
8580 if (cursor !== null) {
8581 cursor.next = item;
8582 } else {
8583 this.head = item;
8584 }
8585
8586 item.prev = cursor;
8587 cursor = item;
8588 }
8589
8590 this.tail = cursor;
8591
8592 return this;
8593 };
8594
8595 List.prototype.toArray = function() {
8596 var cursor = this.head;
8597 var result = [];
8598
8599 while (cursor) {
8600 result.push(cursor.data);
8601 cursor = cursor.next;
8602 }
8603
8604 return result;
8605 };
8606
8607 List.prototype.toJSON = List.prototype.toArray;
8608
8609 List.prototype.isEmpty = function() {
8610 return this.head === null;
8611 };
8612
8613 List.prototype.first = function() {
8614 return this.head && this.head.data;
8615 };
8616
8617 List.prototype.last = function() {
8618 return this.tail && this.tail.data;
8619 };
8620
8621 function allocateCursor(node, prev, next) {
8622 var cursor;
8623
8624 if (cursors !== null) {
8625 cursor = cursors;
8626 cursors = cursors.cursor;
8627 cursor.prev = prev;
8628 cursor.next = next;
8629 cursor.cursor = node.cursor;
8630 } else {
8631 cursor = {
8632 prev: prev,
8633 next: next,
8634 cursor: node.cursor
8635 };
8636 }
8637
8638 node.cursor = cursor;
8639
8640 return cursor;
8641 }
8642
8643 function releaseCursor(node) {
8644 var cursor = node.cursor;
8645
8646 node.cursor = cursor.cursor;
8647 cursor.prev = null;
8648 cursor.next = null;
8649 cursor.cursor = cursors;
8650 cursors = cursor;
8651 }
8652
8653 List.prototype.each = function(fn, context) {
8654 var item;
8655
8656 if (context === undefined) {
8657 context = this;
8658 }
8659
8660 // push cursor
8661 var cursor = allocateCursor(this, null, this.head);
8662
8663 while (cursor.next !== null) {
8664 item = cursor.next;
8665 cursor.next = item.next;
8666
8667 fn.call(context, item.data, item, this);
8668 }
8669
8670 // pop cursor
8671 releaseCursor(this);
8672 };
8673
8674 List.prototype.eachRight = function(fn, context) {
8675 var item;
8676
8677 if (context === undefined) {
8678 context = this;
8679 }
8680
8681 // push cursor
8682 var cursor = allocateCursor(this, this.tail, null);
8683
8684 while (cursor.prev !== null) {
8685 item = cursor.prev;
8686 cursor.prev = item.prev;
8687
8688 fn.call(context, item.data, item, this);
8689 }
8690
8691 // pop cursor
8692 releaseCursor(this);
8693 };
8694
8695 List.prototype.nextUntil = function(start, fn, context) {
8696 if (start === null) {
8697 return;
8698 }
8699
8700 var item;
8701
8702 if (context === undefined) {
8703 context = this;
8704 }
8705
8706 // push cursor
8707 var cursor = allocateCursor(this, null, start);
8708
8709 while (cursor.next !== null) {
8710 item = cursor.next;
8711 cursor.next = item.next;
8712
8713 if (fn.call(context, item.data, item, this)) {
8714 break;
8715 }
8716 }
8717
8718 // pop cursor
8719 releaseCursor(this);
8720 };
8721
8722 List.prototype.prevUntil = function(start, fn, context) {
8723 if (start === null) {
8724 return;
8725 }
8726
8727 var item;
8728
8729 if (context === undefined) {
8730 context = this;
8731 }
8732
8733 // push cursor
8734 var cursor = allocateCursor(this, start, null);
8735
8736 while (cursor.prev !== null) {
8737 item = cursor.prev;
8738 cursor.prev = item.prev;
8739
8740 if (fn.call(context, item.data, item, this)) {
8741 break;
8742 }
8743 }
8744
8745 // pop cursor
8746 releaseCursor(this);
8747 };
8748
8749 List.prototype.some = function(fn, context) {
8750 var cursor = this.head;
8751
8752 if (context === undefined) {
8753 context = this;
8754 }
8755
8756 while (cursor !== null) {
8757 if (fn.call(context, cursor.data, cursor, this)) {
8758 return true;
8759 }
8760
8761 cursor = cursor.next;
8762 }
8763
8764 return false;
8765 };
8766
8767 List.prototype.map = function(fn, context) {
8768 var result = [];
8769 var cursor = this.head;
8770
8771 if (context === undefined) {
8772 context = this;
8773 }
8774
8775 while (cursor !== null) {
8776 result.push(fn.call(context, cursor.data, cursor, this));
8777 cursor = cursor.next;
8778 }
8779
8780 return result;
8781 };
8782
8783 List.prototype.clear = function() {
8784 this.head = null;
8785 this.tail = null;
8786 };
8787
8788 List.prototype.copy = function() {
8789 var result = new List();
8790 var cursor = this.head;
8791
8792 while (cursor !== null) {
8793 result.insert(createItem(cursor.data));
8794 cursor = cursor.next;
8795 }
8796
8797 return result;
8798 };
8799
8800 List.prototype.updateCursors = function(prevOld, prevNew, nextOld, nextNew) {
8801 var cursor = this.cursor;
8802
8803 while (cursor !== null) {
8804 if (cursor.prev === prevOld) {
8805 cursor.prev = prevNew;
8806 }
8807
8808 if (cursor.next === nextOld) {
8809 cursor.next = nextNew;
8810 }
8811
8812 cursor = cursor.cursor;
8813 }
8814 };
8815
8816 List.prototype.prepend = function(item) {
8817 // head
8818 // ^
8819 // item
8820 this.updateCursors(null, item, this.head, item);
8821
8822 // insert to the beginning of the list
8823 if (this.head !== null) {
8824 // new item <- first item
8825 this.head.prev = item;
8826
8827 // new item -> first item
8828 item.next = this.head;
8829 } else {
8830 // if list has no head, then it also has no tail
8831 // in this case tail points to the new item
8832 this.tail = item;
8833 }
8834
8835 // head always points to new item
8836 this.head = item;
8837
8838 return this;
8839 };
8840
8841 List.prototype.prependData = function(data) {
8842 return this.prepend(createItem(data));
8843 };
8844
8845 List.prototype.append = function(item) {
8846 // tail
8847 // ^
8848 // item
8849 this.updateCursors(this.tail, item, null, item);
8850
8851 // insert to the ending of the list
8852 if (this.tail !== null) {
8853 // last item -> new item
8854 this.tail.next = item;
8855
8856 // last item <- new item
8857 item.prev = this.tail;
8858 } else {
8859 // if list has no tail, then it also has no head
8860 // in this case head points to new item
8861 this.head = item;
8862 }
8863
8864 // tail always points to new item
8865 this.tail = item;
8866
8867 return this;
8868 };
8869
8870 List.prototype.appendData = function(data) {
8871 return this.append(createItem(data));
8872 };
8873
8874 List.prototype.insert = function(item, before) {
8875 if (before !== undefined && before !== null) {
8876 // prev before
8877 // ^
8878 // item
8879 this.updateCursors(before.prev, item, before, item);
8880
8881 if (before.prev === null) {
8882 // insert to the beginning of list
8883 if (this.head !== before) {
8884 throw new Error('before doesn\'t belong to list');
8885 }
8886
8887 // since head points to before therefore list doesn't empty
8888 // no need to check tail
8889 this.head = item;
8890 before.prev = item;
8891 item.next = before;
8892
8893 this.updateCursors(null, item);
8894 } else {
8895
8896 // insert between two items
8897 before.prev.next = item;
8898 item.prev = before.prev;
8899
8900 before.prev = item;
8901 item.next = before;
8902 }
8903 } else {
8904 this.append(item);
8905 }
8906 };
8907
8908 List.prototype.insertData = function(data, before) {
8909 this.insert(createItem(data), before);
8910 };
8911
8912 List.prototype.remove = function(item) {
8913 // item
8914 // ^
8915 // prev next
8916 this.updateCursors(item, item.prev, item, item.next);
8917
8918 if (item.prev !== null) {
8919 item.prev.next = item.next;
8920 } else {
8921 if (this.head !== item) {
8922 throw new Error('item doesn\'t belong to list');
8923 }
8924
8925 this.head = item.next;
8926 }
8927
8928 if (item.next !== null) {
8929 item.next.prev = item.prev;
8930 } else {
8931 if (this.tail !== item) {
8932 throw new Error('item doesn\'t belong to list');
8933 }
8934
8935 this.tail = item.prev;
8936 }
8937
8938 item.prev = null;
8939 item.next = null;
8940
8941 return item;
8942 };
8943
8944 List.prototype.appendList = function(list) {
8945 // ignore empty lists
8946 if (list.head === null) {
8947 return;
8948 }
8949
8950 this.updateCursors(this.tail, list.tail, null, list.head);
8951
8952 // insert to end of the list
8953 if (this.tail !== null) {
8954 // if destination list has a tail, then it also has a head,
8955 // but head doesn't change
8956
8957 // dest tail -> source head
8958 this.tail.next = list.head;
8959
8960 // dest tail <- source head
8961 list.head.prev = this.tail;
8962 } else {
8963 // if list has no a tail, then it also has no a head
8964 // in this case points head to new item
8965 this.head = list.head;
8966 }
8967
8968 // tail always start point to new item
8969 this.tail = list.tail;
8970
8971 list.head = null;
8972 list.tail = null;
8973 };
8974
8975 List.prototype.insertList = function(list, before) {
8976 if (before !== undefined && before !== null) {
8977 // ignore empty lists
8978 if (list.head === null) {
8979 return;
8980 }
8981
8982 this.updateCursors(before.prev, list.tail, before, list.head);
8983
8984 // insert in the middle of dist list
8985 if (before.prev !== null) {
8986 // before.prev <-> list.head
8987 before.prev.next = list.head;
8988 list.head.prev = before.prev;
8989 } else {
8990 this.head = list.head;
8991 }
8992
8993 before.prev = list.tail;
8994 list.tail.next = before;
8995
8996 list.head = null;
8997 list.tail = null;
8998 } else {
8999 this.appendList(list);
9000 }
9001 };
9002
9003 List.prototype.replace = function(oldItem, newItemOrList) {
9004 if ('head' in newItemOrList) {
9005 this.insertList(newItemOrList, oldItem);
9006 } else {
9007 this.insert(newItemOrList, oldItem);
9008 }
9009 this.remove(oldItem);
9010 };
9011
9012 var list = List;
9013
9014 var TYPE$3 = tokenizer.TYPE;
9015 var WHITESPACE$2 = TYPE$3.WhiteSpace;
9016 var COMMENT$2 = TYPE$3.Comment;
9017
9018 var sequence = function readSequence(recognizer) {
9019 var children = new list();
9020 var child = null;
9021 var context = {
9022 recognizer: recognizer,
9023 space: null,
9024 ignoreWS: false,
9025 ignoreWSAfter: false
9026 };
9027
9028 this.scanner.skipSC();
9029
9030 while (!this.scanner.eof) {
9031 switch (this.scanner.tokenType) {
9032 case COMMENT$2:
9033 this.scanner.next();
9034 continue;
9035
9036 case WHITESPACE$2:
9037 if (context.ignoreWS) {
9038 this.scanner.next();
9039 } else {
9040 context.space = this.WhiteSpace();
9041 }
9042 continue;
9043 }
9044
9045 child = recognizer.getNode.call(this, context);
9046
9047 if (child === undefined) {
9048 break;
9049 }
9050
9051 if (context.space !== null) {
9052 children.appendData(context.space);
9053 context.space = null;
9054 }
9055
9056 children.appendData(child);
9057
9058 if (context.ignoreWSAfter) {
9059 context.ignoreWSAfter = false;
9060 context.ignoreWS = true;
9061 } else {
9062 context.ignoreWS = false;
9063 }
9064 }
9065
9066 return children;
9067 };
9068
9069 var noop = function() {};
9070
9071 function createParseContext(name) {
9072 return function() {
9073 return this[name]();
9074 };
9075 }
9076
9077 function processConfig(config) {
9078 var parserConfig = {
9079 context: {},
9080 scope: {},
9081 atrule: {},
9082 pseudo: {}
9083 };
9084
9085 if (config.parseContext) {
9086 for (var name in config.parseContext) {
9087 switch (typeof config.parseContext[name]) {
9088 case 'function':
9089 parserConfig.context[name] = config.parseContext[name];
9090 break;
9091
9092 case 'string':
9093 parserConfig.context[name] = createParseContext(config.parseContext[name]);
9094 break;
9095 }
9096 }
9097 }
9098
9099 if (config.scope) {
9100 for (var name in config.scope) {
9101 parserConfig.scope[name] = config.scope[name];
9102 }
9103 }
9104
9105 if (config.atrule) {
9106 for (var name in config.atrule) {
9107 var atrule = config.atrule[name];
9108
9109 if (atrule.parse) {
9110 parserConfig.atrule[name] = atrule.parse;
9111 }
9112 }
9113 }
9114
9115 if (config.pseudo) {
9116 for (var name in config.pseudo) {
9117 var pseudo = config.pseudo[name];
9118
9119 if (pseudo.parse) {
9120 parserConfig.pseudo[name] = pseudo.parse;
9121 }
9122 }
9123 }
9124
9125 if (config.node) {
9126 for (var name in config.node) {
9127 parserConfig[name] = config.node[name].parse;
9128 }
9129 }
9130
9131 return parserConfig;
9132 }
9133
9134 var create = function createParser(config) {
9135 var parser = {
9136 scanner: new tokenizer(),
9137 filename: '<unknown>',
9138 needPositions: false,
9139 tolerant: false,
9140 onParseError: noop,
9141 parseAtruleExpression: true,
9142 parseSelector: true,
9143 parseValue: true,
9144 parseCustomProperty: false,
9145
9146 readSequence: sequence,
9147
9148 tolerantParse: function(consumer, fallback) {
9149 if (this.tolerant) {
9150 var start = this.scanner.currentToken;
9151
9152 try {
9153 return consumer.call(this);
9154 } catch (e) {
9155 this.onParseError(e);
9156 return fallback.call(this, start);
9157 }
9158 } else {
9159 return consumer.call(this);
9160 }
9161 },
9162
9163 getLocation: function(start, end) {
9164 if (this.needPositions) {
9165 return this.scanner.getLocationRange(
9166 start,
9167 end,
9168 this.filename
9169 );
9170 }
9171
9172 return null;
9173 },
9174 getLocationFromList: function(list) {
9175 if (this.needPositions) {
9176 return this.scanner.getLocationRange(
9177 list.head !== null ? list.first().loc.start.offset - this.scanner.startOffset : this.scanner.tokenStart,
9178 list.head !== null ? list.last().loc.end.offset - this.scanner.startOffset : this.scanner.tokenStart,
9179 this.filename
9180 );
9181 }
9182
9183 return null;
9184 }
9185 };
9186
9187 config = processConfig(config || {});
9188 for (var key in config) {
9189 parser[key] = config[key];
9190 }
9191
9192 return function(source, options) {
9193 options = options || {};
9194
9195 var context = options.context || 'default';
9196 var ast;
9197
9198 parser.scanner.setSource(source, options.offset, options.line, options.column);
9199 parser.filename = options.filename || '<unknown>';
9200 parser.needPositions = Boolean(options.positions);
9201 parser.tolerant = Boolean(options.tolerant);
9202 parser.onParseError = typeof options.onParseError === 'function' ? options.onParseError : noop;
9203 parser.parseAtruleExpression = 'parseAtruleExpression' in options ? Boolean(options.parseAtruleExpression) : true;
9204 parser.parseSelector = 'parseSelector' in options ? Boolean(options.parseSelector) : true;
9205 parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
9206 parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;
9207
9208 if (!parser.context.hasOwnProperty(context)) {
9209 throw new Error('Unknown context `' + context + '`');
9210 }
9211
9212 ast = parser.context[context].call(parser, options);
9213
9214 if (!parser.scanner.eof) {
9215 parser.scanner.error();
9216 }
9217
9218 // console.log(JSON.stringify(ast, null, 4));
9219 return ast;
9220 };
9221 };
9222
9223 var cmpChar$1 = tokenizer.cmpChar;
9224 var TYPE$4 = tokenizer.TYPE;
9225
9226 var IDENTIFIER$2 = TYPE$4.Identifier;
9227 var STRING$2 = TYPE$4.String;
9228 var NUMBER$2 = TYPE$4.Number;
9229 var FUNCTION$2 = TYPE$4.Function;
9230 var URL$2 = TYPE$4.Url;
9231 var NUMBERSIGN = TYPE$4.NumberSign;
9232 var LEFTPARENTHESIS$1 = TYPE$4.LeftParenthesis;
9233 var LEFTSQUAREBRACKET$1 = TYPE$4.LeftSquareBracket;
9234 var PLUSSIGN$2 = TYPE$4.PlusSign;
9235 var HYPHENMINUS$2 = TYPE$4.HyphenMinus;
9236 var COMMA = TYPE$4.Comma;
9237 var SOLIDUS = TYPE$4.Solidus;
9238 var ASTERISK = TYPE$4.Asterisk;
9239 var PERCENTSIGN = TYPE$4.PercentSign;
9240 var BACKSLASH = TYPE$4.Backslash;
9241 var U = 117; // 'u'.charCodeAt(0)
9242
9243 var _default = function defaultRecognizer(context) {
9244 switch (this.scanner.tokenType) {
9245 case NUMBERSIGN:
9246 return this.HexColor();
9247
9248 case COMMA:
9249 context.space = null;
9250 context.ignoreWSAfter = true;
9251 return this.Operator();
9252
9253 case SOLIDUS:
9254 case ASTERISK:
9255 case PLUSSIGN$2:
9256 case HYPHENMINUS$2:
9257 return this.Operator();
9258
9259 case LEFTPARENTHESIS$1:
9260 return this.Parentheses(this.readSequence, context.recognizer);
9261
9262 case LEFTSQUAREBRACKET$1:
9263 return this.Brackets(this.readSequence, context.recognizer);
9264
9265 case STRING$2:
9266 return this.String();
9267
9268 case NUMBER$2:
9269 switch (this.scanner.lookupType(1)) {
9270 case PERCENTSIGN:
9271 return this.Percentage();
9272
9273 case IDENTIFIER$2:
9274 // edge case: number with folowing \0 and \9 hack shouldn't to be a Dimension
9275 if (cmpChar$1(this.scanner.source, this.scanner.tokenEnd, BACKSLASH)) {
9276 return this.Number();
9277 } else {
9278 return this.Dimension();
9279 }
9280
9281 default:
9282 return this.Number();
9283 }
9284
9285 case FUNCTION$2:
9286 return this.Function(this.readSequence, context.recognizer);
9287
9288 case URL$2:
9289 return this.Url();
9290
9291 case IDENTIFIER$2:
9292 // check for unicode range, it should start with u+ or U+
9293 if (cmpChar$1(this.scanner.source, this.scanner.tokenStart, U) &&
9294 cmpChar$1(this.scanner.source, this.scanner.tokenStart + 1, PLUSSIGN$2)) {
9295 return this.UnicodeRange();
9296 } else {
9297 return this.Identifier();
9298 }
9299 }
9300 };
9301
9302 var atruleExpression = {
9303 getNode: _default
9304 };
9305
9306 var TYPE$5 = tokenizer.TYPE;
9307
9308 var IDENTIFIER$3 = TYPE$5.Identifier;
9309 var NUMBER$3 = TYPE$5.Number;
9310 var NUMBERSIGN$1 = TYPE$5.NumberSign;
9311 var LEFTSQUAREBRACKET$2 = TYPE$5.LeftSquareBracket;
9312 var PLUSSIGN$3 = TYPE$5.PlusSign;
9313 var SOLIDUS$1 = TYPE$5.Solidus;
9314 var ASTERISK$1 = TYPE$5.Asterisk;
9315 var FULLSTOP$2 = TYPE$5.FullStop;
9316 var COLON = TYPE$5.Colon;
9317 var GREATERTHANSIGN$1 = TYPE$5.GreaterThanSign;
9318 var VERTICALLINE = TYPE$5.VerticalLine;
9319 var TILDE = TYPE$5.Tilde;
9320
9321 function getNode(context) {
9322 switch (this.scanner.tokenType) {
9323 case PLUSSIGN$3:
9324 case GREATERTHANSIGN$1:
9325 case TILDE:
9326 context.space = null;
9327 context.ignoreWSAfter = true;
9328 return this.Combinator();
9329
9330 case SOLIDUS$1: // /deep/
9331 return this.Combinator();
9332
9333 case FULLSTOP$2:
9334 return this.ClassSelector();
9335
9336 case LEFTSQUAREBRACKET$2:
9337 return this.AttributeSelector();
9338
9339 case NUMBERSIGN$1:
9340 return this.IdSelector();
9341
9342 case COLON:
9343 if (this.scanner.lookupType(1) === COLON) {
9344 return this.PseudoElementSelector();
9345 } else {
9346 return this.PseudoClassSelector();
9347 }
9348
9349 case IDENTIFIER$3:
9350 case ASTERISK$1:
9351 case VERTICALLINE:
9352 return this.TypeSelector();
9353
9354 case NUMBER$3:
9355 return this.Percentage();
9356 }
9357 }
9358 var selector = {
9359 getNode: getNode
9360 };
9361
9362 // https://drafts.csswg.org/css-images-4/#element-notation
9363 // https://developer.mozilla.org/en-US/docs/Web/CSS/element
9364 var element = function() {
9365 this.scanner.skipSC();
9366
9367 var id = this.IdSelector();
9368
9369 this.scanner.skipSC();
9370
9371 return new list().appendData(
9372 id
9373 );
9374 };
9375
9376 // legacy IE function
9377 // expression '(' raw ')'
9378 var expression = function() {
9379 return new list().appendData(
9380 this.Raw(this.scanner.currentToken, 0, 0, false, false)
9381 );
9382 };
9383
9384 var TYPE$6 = tokenizer.TYPE;
9385
9386 var IDENTIFIER$4 = TYPE$6.Identifier;
9387 var COMMA$1 = TYPE$6.Comma;
9388 var SEMICOLON = TYPE$6.Semicolon;
9389 var HYPHENMINUS$3 = TYPE$6.HyphenMinus;
9390 var EXCLAMATIONMARK$1 = TYPE$6.ExclamationMark;
9391
9392 // var '(' ident (',' <value>? )? ')'
9393 var _var = function() {
9394 var children = new list();
9395
9396 this.scanner.skipSC();
9397
9398 var identStart = this.scanner.tokenStart;
9399
9400 this.scanner.eat(HYPHENMINUS$3);
9401 if (this.scanner.source.charCodeAt(this.scanner.tokenStart) !== HYPHENMINUS$3) {
9402 this.scanner.error('HyphenMinus is expected');
9403 }
9404 this.scanner.eat(IDENTIFIER$4);
9405
9406 children.appendData({
9407 type: 'Identifier',
9408 loc: this.getLocation(identStart, this.scanner.tokenStart),
9409 name: this.scanner.substrToCursor(identStart)
9410 });
9411
9412 this.scanner.skipSC();
9413
9414 if (this.scanner.tokenType === COMMA$1) {
9415 children.appendData(this.Operator());
9416 children.appendData(this.parseCustomProperty
9417 ? this.Value(null)
9418 : this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$1, SEMICOLON, false, false)
9419 );
9420 }
9421
9422 return children;
9423 };
9424
9425 var value = {
9426 getNode: _default,
9427 '-moz-element': element,
9428 'element': element,
9429 'expression': expression,
9430 'var': _var
9431 };
9432
9433 var scope = {
9434 AtruleExpression: atruleExpression,
9435 Selector: selector,
9436 Value: value
9437 };
9438
9439 var fontFace = {
9440 parse: {
9441 expression: null,
9442 block: function() {
9443 return this.Block(this.Declaration);
9444 }
9445 }
9446 };
9447
9448 var TYPE$7 = tokenizer.TYPE;
9449
9450 var STRING$3 = TYPE$7.String;
9451 var IDENTIFIER$5 = TYPE$7.Identifier;
9452 var URL$3 = TYPE$7.Url;
9453 var LEFTPARENTHESIS$2 = TYPE$7.LeftParenthesis;
9454
9455 var _import = {
9456 parse: {
9457 expression: function() {
9458 var children = new list();
9459
9460 this.scanner.skipSC();
9461
9462 switch (this.scanner.tokenType) {
9463 case STRING$3:
9464 children.appendData(this.String());
9465 break;
9466
9467 case URL$3:
9468 children.appendData(this.Url());
9469 break;
9470
9471 default:
9472 this.scanner.error('String or url() is expected');
9473 }
9474
9475 if (this.scanner.lookupNonWSType(0) === IDENTIFIER$5 ||
9476 this.scanner.lookupNonWSType(0) === LEFTPARENTHESIS$2) {
9477 children.appendData(this.WhiteSpace());
9478 children.appendData(this.MediaQueryList());
9479 }
9480
9481 return children;
9482 },
9483 block: null
9484 }
9485 };
9486
9487 var media = {
9488 parse: {
9489 expression: function() {
9490 return new list().appendData(
9491 this.MediaQueryList()
9492 );
9493 },
9494 block: function() {
9495 return this.Block(this.Rule);
9496 }
9497 }
9498 };
9499
9500 var TYPE$8 = tokenizer.TYPE;
9501 var LEFTCURLYBRACKET$1 = TYPE$8.LeftCurlyBracket;
9502
9503 var page = {
9504 parse: {
9505 expression: function() {
9506 if (this.scanner.lookupNonWSType(0) === LEFTCURLYBRACKET$1) {
9507 return null;
9508 }
9509
9510 return new list().appendData(
9511 this.SelectorList()
9512 );
9513 },
9514 block: function() {
9515 return this.Block(this.Declaration);
9516 }
9517 }
9518 };
9519
9520 var TYPE$9 = tokenizer.TYPE;
9521
9522 var WHITESPACE$3 = TYPE$9.WhiteSpace;
9523 var COMMENT$3 = TYPE$9.Comment;
9524 var IDENTIFIER$6 = TYPE$9.Identifier;
9525 var FUNCTION$3 = TYPE$9.Function;
9526 var LEFTPARENTHESIS$3 = TYPE$9.LeftParenthesis;
9527 var HYPHENMINUS$4 = TYPE$9.HyphenMinus;
9528 var COLON$1 = TYPE$9.Colon;
9529
9530 function consumeRaw() {
9531 return new list().appendData(
9532 this.Raw(this.scanner.currentToken, 0, 0, false, false)
9533 );
9534 }
9535
9536 function parentheses() {
9537 var index = 0;
9538
9539 this.scanner.skipSC();
9540
9541 // TODO: make it simplier
9542 if (this.scanner.tokenType === IDENTIFIER$6) {
9543 index = 1;
9544 } else if (this.scanner.tokenType === HYPHENMINUS$4 &&
9545 this.scanner.lookupType(1) === IDENTIFIER$6) {
9546 index = 2;
9547 }
9548
9549 if (index !== 0 && this.scanner.lookupNonWSType(index) === COLON$1) {
9550 return new list().appendData(
9551 this.Declaration()
9552 );
9553 }
9554
9555 return readSequence.call(this);
9556 }
9557
9558 function readSequence() {
9559 var children = new list();
9560 var space = null;
9561 var child;
9562
9563 this.scanner.skipSC();
9564
9565 scan:
9566 while (!this.scanner.eof) {
9567 switch (this.scanner.tokenType) {
9568 case WHITESPACE$3:
9569 space = this.WhiteSpace();
9570 continue;
9571
9572 case COMMENT$3:
9573 this.scanner.next();
9574 continue;
9575
9576 case FUNCTION$3:
9577 child = this.Function(consumeRaw, this.scope.AtruleExpression);
9578 break;
9579
9580 case IDENTIFIER$6:
9581 child = this.Identifier();
9582 break;
9583
9584 case LEFTPARENTHESIS$3:
9585 child = this.Parentheses(parentheses, this.scope.AtruleExpression);
9586 break;
9587
9588 default:
9589 break scan;
9590 }
9591
9592 if (space !== null) {
9593 children.appendData(space);
9594 space = null;
9595 }
9596
9597 children.appendData(child);
9598 }
9599
9600 return children;
9601 }
9602
9603 var supports = {
9604 parse: {
9605 expression: function() {
9606 var children = readSequence.call(this);
9607
9608 if (children.isEmpty()) {
9609 this.scanner.error('Condition is expected');
9610 }
9611
9612 return children;
9613 },
9614 block: function() {
9615 return this.Block(this.Rule);
9616 }
9617 }
9618 };
9619
9620 var atrule = {
9621 'font-face': fontFace,
9622 'import': _import,
9623 'media': media,
9624 'page': page,
9625 'supports': supports
9626 };
9627
9628 var dir = {
9629 parse: function() {
9630 return new list().appendData(
9631 this.Identifier()
9632 );
9633 }
9634 };
9635
9636 var has$1 = {
9637 parse: function() {
9638 return new list().appendData(
9639 this.SelectorList()
9640 );
9641 }
9642 };
9643
9644 var lang = {
9645 parse: function() {
9646 return new list().appendData(
9647 this.Identifier()
9648 );
9649 }
9650 };
9651
9652 var selectorList = {
9653 parse: function selectorList() {
9654 return new list().appendData(
9655 this.SelectorList()
9656 );
9657 }
9658 };
9659
9660 var matches = selectorList;
9661
9662 var not = selectorList;
9663
9664 var ALLOW_OF_CLAUSE = true;
9665
9666 var nthWithOfClause = {
9667 parse: function() {
9668 return new list().appendData(
9669 this.Nth(ALLOW_OF_CLAUSE)
9670 );
9671 }
9672 };
9673
9674 var nthChild = nthWithOfClause;
9675
9676 var nthLastChild = nthWithOfClause;
9677
9678 var DISALLOW_OF_CLAUSE = false;
9679
9680 var nth = {
9681 parse: function nth() {
9682 return new list().appendData(
9683 this.Nth(DISALLOW_OF_CLAUSE)
9684 );
9685 }
9686 };
9687
9688 var nthLastOfType = nth;
9689
9690 var nthOfType = nth;
9691
9692 var slotted = {
9693 parse: function compoundSelector() {
9694 return new list().appendData(
9695 this.Selector()
9696 );
9697 }
9698 };
9699
9700 var pseudo = {
9701 'dir': dir,
9702 'has': has$1,
9703 'lang': lang,
9704 'matches': matches,
9705 'not': not,
9706 'nth-child': nthChild,
9707 'nth-last-child': nthLastChild,
9708 'nth-last-of-type': nthLastOfType,
9709 'nth-of-type': nthOfType,
9710 'slotted': slotted
9711 };
9712
9713 var cmpChar$2 = tokenizer.cmpChar;
9714 var isNumber$2 = tokenizer.isNumber;
9715 var TYPE$a = tokenizer.TYPE;
9716
9717 var IDENTIFIER$7 = TYPE$a.Identifier;
9718 var NUMBER$4 = TYPE$a.Number;
9719 var PLUSSIGN$4 = TYPE$a.PlusSign;
9720 var HYPHENMINUS$5 = TYPE$a.HyphenMinus;
9721 var N$3 = 110; // 'n'.charCodeAt(0)
9722 var DISALLOW_SIGN = true;
9723 var ALLOW_SIGN = false;
9724
9725 function checkTokenIsInteger(scanner, disallowSign) {
9726 var pos = scanner.tokenStart;
9727
9728 if (scanner.source.charCodeAt(pos) === PLUSSIGN$4 ||
9729 scanner.source.charCodeAt(pos) === HYPHENMINUS$5) {
9730 if (disallowSign) {
9731 scanner.error();
9732 }
9733 pos++;
9734 }
9735
9736 for (; pos < scanner.tokenEnd; pos++) {
9737 if (!isNumber$2(scanner.source.charCodeAt(pos))) {
9738 scanner.error('Unexpected input', pos);
9739 }
9740 }
9741 }
9742
9743 // An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
9744 var AnPlusB = {
9745 name: 'AnPlusB',
9746 structure: {
9747 a: [String, null],
9748 b: [String, null]
9749 },
9750 parse: function() {
9751 var start = this.scanner.tokenStart;
9752 var end = start;
9753 var prefix = '';
9754 var a = null;
9755 var b = null;
9756
9757 if (this.scanner.tokenType === NUMBER$4 ||
9758 this.scanner.tokenType === PLUSSIGN$4) {
9759 checkTokenIsInteger(this.scanner, ALLOW_SIGN);
9760 prefix = this.scanner.getTokenValue();
9761 this.scanner.next();
9762 end = this.scanner.tokenStart;
9763 }
9764
9765 if (this.scanner.tokenType === IDENTIFIER$7) {
9766 var bStart = this.scanner.tokenStart;
9767
9768 if (cmpChar$2(this.scanner.source, bStart, HYPHENMINUS$5)) {
9769 if (prefix === '') {
9770 prefix = '-';
9771 bStart++;
9772 } else {
9773 this.scanner.error('Unexpected hyphen minus');
9774 }
9775 }
9776
9777 if (!cmpChar$2(this.scanner.source, bStart, N$3)) {
9778 this.scanner.error();
9779 }
9780
9781 a = prefix === '' ? '1' :
9782 prefix === '+' ? '+1' :
9783 prefix === '-' ? '-1' :
9784 prefix;
9785
9786 var len = this.scanner.tokenEnd - bStart;
9787 if (len > 1) {
9788 // ..n-..
9789 if (this.scanner.source.charCodeAt(bStart + 1) !== HYPHENMINUS$5) {
9790 this.scanner.error('Unexpected input', bStart + 1);
9791 }
9792
9793 if (len > 2) {
9794 // ..n-{number}..
9795 this.scanner.tokenStart = bStart + 2;
9796 } else {
9797 // ..n- {number}
9798 this.scanner.next();
9799 this.scanner.skipSC();
9800 }
9801
9802 checkTokenIsInteger(this.scanner, DISALLOW_SIGN);
9803 b = '-' + this.scanner.getTokenValue();
9804 this.scanner.next();
9805 end = this.scanner.tokenStart;
9806 } else {
9807 prefix = '';
9808 this.scanner.next();
9809 end = this.scanner.tokenStart;
9810 this.scanner.skipSC();
9811
9812 if (this.scanner.tokenType === HYPHENMINUS$5 ||
9813 this.scanner.tokenType === PLUSSIGN$4) {
9814 prefix = this.scanner.getTokenValue();
9815 this.scanner.next();
9816 this.scanner.skipSC();
9817 }
9818
9819 if (this.scanner.tokenType === NUMBER$4) {
9820 checkTokenIsInteger(this.scanner, prefix !== '');
9821
9822 if (!isNumber$2(this.scanner.source.charCodeAt(this.scanner.tokenStart))) {
9823 prefix = this.scanner.source.charAt(this.scanner.tokenStart);
9824 this.scanner.tokenStart++;
9825 }
9826
9827 if (prefix === '') {
9828 // should be an operator before number
9829 this.scanner.error();
9830 } else if (prefix === '+') {
9831 // plus is using by default
9832 prefix = '';
9833 }
9834
9835 b = prefix + this.scanner.getTokenValue();
9836
9837 this.scanner.next();
9838 end = this.scanner.tokenStart;
9839 } else {
9840 if (prefix) {
9841 this.scanner.eat(NUMBER$4);
9842 }
9843 }
9844 }
9845 } else {
9846 if (prefix === '' || prefix === '+') { // no number
9847 this.scanner.error(
9848 'Number or identifier is expected',
9849 this.scanner.tokenStart + (
9850 this.scanner.tokenType === PLUSSIGN$4 ||
9851 this.scanner.tokenType === HYPHENMINUS$5
9852 )
9853 );
9854 }
9855
9856 b = prefix;
9857 }
9858
9859 return {
9860 type: 'AnPlusB',
9861 loc: this.getLocation(start, end),
9862 a: a,
9863 b: b
9864 };
9865 },
9866 generate: function(processChunk, node) {
9867 var a = node.a !== null && node.a !== undefined;
9868 var b = node.b !== null && node.b !== undefined;
9869
9870 if (a) {
9871 processChunk(
9872 node.a === '+1' ? '+n' :
9873 node.a === '1' ? 'n' :
9874 node.a === '-1' ? '-n' :
9875 node.a + 'n'
9876 );
9877
9878 if (b) {
9879 b = String(node.b);
9880 if (b.charAt(0) === '-' || b.charAt(0) === '+') {
9881 processChunk(b.charAt(0));
9882 processChunk(b.substr(1));
9883 } else {
9884 processChunk('+');
9885 processChunk(b);
9886 }
9887 }
9888 } else {
9889 processChunk(String(node.b));
9890 }
9891 }
9892 };
9893
9894 var TYPE$b = tokenizer.TYPE;
9895
9896 var ATRULE$2 = TYPE$b.Atrule;
9897 var SEMICOLON$1 = TYPE$b.Semicolon;
9898 var LEFTCURLYBRACKET$2 = TYPE$b.LeftCurlyBracket;
9899 var RIGHTCURLYBRACKET$1 = TYPE$b.RightCurlyBracket;
9900
9901 function isBlockAtrule() {
9902 for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) {
9903 if (type === RIGHTCURLYBRACKET$1) {
9904 return true;
9905 }
9906
9907 if (type === LEFTCURLYBRACKET$2 ||
9908 type === ATRULE$2) {
9909 return false;
9910 }
9911 }
9912
9913 this.scanner.skip(offset);
9914 this.scanner.eat(RIGHTCURLYBRACKET$1);
9915 }
9916
9917 var Atrule = {
9918 name: 'Atrule',
9919 structure: {
9920 name: String,
9921 expression: ['AtruleExpression', null],
9922 block: ['Block', null]
9923 },
9924 parse: function() {
9925 var start = this.scanner.tokenStart;
9926 var name;
9927 var nameLowerCase;
9928 var expression = null;
9929 var block = null;
9930
9931 this.scanner.eat(ATRULE$2);
9932
9933 name = this.scanner.substrToCursor(start + 1);
9934 nameLowerCase = name.toLowerCase();
9935 this.scanner.skipSC();
9936
9937 expression = this.AtruleExpression(name);
9938
9939 // turn empty AtruleExpression into null
9940 if (expression.children.head === null) {
9941 expression = null;
9942 }
9943
9944 this.scanner.skipSC();
9945
9946 if (this.atrule.hasOwnProperty(nameLowerCase)) {
9947 if (typeof this.atrule[nameLowerCase].block === 'function') {
9948 if (this.scanner.tokenType !== LEFTCURLYBRACKET$2) {
9949 // FIXME: make tolerant
9950 this.scanner.error('Curly bracket is expected');
9951 }
9952
9953 block = this.atrule[nameLowerCase].block.call(this);
9954 } else {
9955 if (!this.tolerant || !this.scanner.eof) {
9956 this.scanner.eat(SEMICOLON$1);
9957 }
9958 }
9959 } else {
9960 switch (this.scanner.tokenType) {
9961 case SEMICOLON$1:
9962 this.scanner.next();
9963 break;
9964
9965 case LEFTCURLYBRACKET$2:
9966 // TODO: should consume block content as Raw?
9967 block = this.Block(isBlockAtrule.call(this) ? this.Declaration : this.Rule);
9968 break;
9969
9970 default:
9971 if (!this.tolerant) {
9972 this.scanner.error('Semicolon or block is expected');
9973 }
9974 }
9975 }
9976
9977 return {
9978 type: 'Atrule',
9979 loc: this.getLocation(start, this.scanner.tokenStart),
9980 name: name,
9981 expression: expression,
9982 block: block
9983 };
9984 },
9985 generate: function(processChunk, node) {
9986 processChunk('@');
9987 processChunk(node.name);
9988
9989 if (node.expression !== null) {
9990 processChunk(' ');
9991 this.generate(processChunk, node.expression);
9992 }
9993
9994 if (node.block) {
9995 this.generate(processChunk, node.block);
9996 } else {
9997 processChunk(';');
9998 }
9999 },
10000 walkContext: 'atrule'
10001 };
10002
10003 var TYPE$c = tokenizer.TYPE;
10004 var SEMICOLON$2 = TYPE$c.Semicolon;
10005 var LEFTCURLYBRACKET$3 = TYPE$c.LeftCurlyBracket;
10006
10007 function consumeRaw$1(startToken) {
10008 return new list().appendData(
10009 this.Raw(startToken, SEMICOLON$2, LEFTCURLYBRACKET$3, false, true)
10010 );
10011 }
10012
10013 function consumeDefaultSequence() {
10014 return this.readSequence(this.scope.AtruleExpression);
10015 }
10016
10017 var AtruleExpression = {
10018 name: 'AtruleExpression',
10019 structure: {
10020 children: [[]]
10021 },
10022 parse: function(name) {
10023 var children = null;
10024 var startToken = this.scanner.currentToken;
10025
10026 if (name !== null) {
10027 name = name.toLowerCase();
10028 }
10029
10030 if (this.parseAtruleExpression) {
10031 // custom consumer
10032 if (this.atrule.hasOwnProperty(name)) {
10033 if (typeof this.atrule[name].expression === 'function') {
10034 children = this.tolerantParse(this.atrule[name].expression, consumeRaw$1);
10035 }
10036 } else {
10037 // default consumer
10038 this.scanner.skipSC();
10039 children = this.tolerantParse(consumeDefaultSequence, consumeRaw$1);
10040 }
10041
10042 if (this.tolerant) {
10043 if (this.scanner.eof || (this.scanner.tokenType !== SEMICOLON$2 && this.scanner.tokenType !== LEFTCURLYBRACKET$3)) {
10044 children = consumeRaw$1.call(this, startToken);
10045 }
10046 }
10047 } else {
10048 children = consumeRaw$1.call(this, startToken);
10049 }
10050
10051 if (children === null) {
10052 children = new list();
10053 }
10054
10055 return {
10056 type: 'AtruleExpression',
10057 loc: this.getLocationFromList(children),
10058 children: children
10059 };
10060 },
10061 generate: function(processChunk, node) {
10062 this.each(processChunk, node);
10063 },
10064 walkContext: 'atruleExpression'
10065 };
10066
10067 var TYPE$d = tokenizer.TYPE;
10068
10069 var IDENTIFIER$8 = TYPE$d.Identifier;
10070 var STRING$4 = TYPE$d.String;
10071 var DOLLARSIGN = TYPE$d.DollarSign;
10072 var ASTERISK$2 = TYPE$d.Asterisk;
10073 var COLON$2 = TYPE$d.Colon;
10074 var EQUALSSIGN = TYPE$d.EqualsSign;
10075 var LEFTSQUAREBRACKET$3 = TYPE$d.LeftSquareBracket;
10076 var RIGHTSQUAREBRACKET$1 = TYPE$d.RightSquareBracket;
10077 var CIRCUMFLEXACCENT = TYPE$d.CircumflexAccent;
10078 var VERTICALLINE$1 = TYPE$d.VerticalLine;
10079 var TILDE$1 = TYPE$d.Tilde;
10080
10081 function getAttributeName() {
10082 if (this.scanner.eof) {
10083 this.scanner.error('Unexpected end of input');
10084 }
10085
10086 var start = this.scanner.tokenStart;
10087 var expectIdentifier = false;
10088 var checkColon = true;
10089
10090 if (this.scanner.tokenType === ASTERISK$2) {
10091 expectIdentifier = true;
10092 checkColon = false;
10093 this.scanner.next();
10094 } else if (this.scanner.tokenType !== VERTICALLINE$1) {
10095 this.scanner.eat(IDENTIFIER$8);
10096 }
10097
10098 if (this.scanner.tokenType === VERTICALLINE$1) {
10099 if (this.scanner.lookupType(1) !== EQUALSSIGN) {
10100 this.scanner.next();
10101 this.scanner.eat(IDENTIFIER$8);
10102 } else if (expectIdentifier) {
10103 this.scanner.error('Identifier is expected', this.scanner.tokenEnd);
10104 }
10105 } else if (expectIdentifier) {
10106 this.scanner.error('Vertical line is expected');
10107 }
10108
10109 if (checkColon && this.scanner.tokenType === COLON$2) {
10110 this.scanner.next();
10111 this.scanner.eat(IDENTIFIER$8);
10112 }
10113
10114 return {
10115 type: 'Identifier',
10116 loc: this.getLocation(start, this.scanner.tokenStart),
10117 name: this.scanner.substrToCursor(start)
10118 };
10119 }
10120
10121 function getOperator() {
10122 var start = this.scanner.tokenStart;
10123 var tokenType = this.scanner.tokenType;
10124
10125 if (tokenType !== EQUALSSIGN && // =
10126 tokenType !== TILDE$1 && // ~=
10127 tokenType !== CIRCUMFLEXACCENT && // ^=
10128 tokenType !== DOLLARSIGN && // $=
10129 tokenType !== ASTERISK$2 && // *=
10130 tokenType !== VERTICALLINE$1 // |=
10131 ) {
10132 this.scanner.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
10133 }
10134
10135 if (tokenType === EQUALSSIGN) {
10136 this.scanner.next();
10137 } else {
10138 this.scanner.next();
10139 this.scanner.eat(EQUALSSIGN);
10140 }
10141
10142 return this.scanner.substrToCursor(start);
10143 }
10144
10145 // '[' S* attrib_name ']'
10146 // '[' S* attrib_name S* attrib_matcher S* [ IDENT | STRING ] S* attrib_flags? S* ']'
10147 var AttributeSelector = {
10148 name: 'AttributeSelector',
10149 structure: {
10150 name: 'Identifier',
10151 matcher: [String, null],
10152 value: ['String', 'Identifier', null],
10153 flags: [String, null]
10154 },
10155 parse: function() {
10156 var start = this.scanner.tokenStart;
10157 var name;
10158 var matcher = null;
10159 var value = null;
10160 var flags = null;
10161
10162 this.scanner.eat(LEFTSQUAREBRACKET$3);
10163 this.scanner.skipSC();
10164
10165 name = getAttributeName.call(this);
10166 this.scanner.skipSC();
10167
10168 if (this.scanner.tokenType !== RIGHTSQUAREBRACKET$1) {
10169 // avoid case `[name i]`
10170 if (this.scanner.tokenType !== IDENTIFIER$8) {
10171 matcher = getOperator.call(this);
10172
10173 this.scanner.skipSC();
10174
10175 value = this.scanner.tokenType === STRING$4
10176 ? this.String()
10177 : this.Identifier();
10178
10179 this.scanner.skipSC();
10180 }
10181
10182 // attribute flags
10183 if (this.scanner.tokenType === IDENTIFIER$8) {
10184 flags = this.scanner.getTokenValue();
10185 this.scanner.next();
10186
10187 this.scanner.skipSC();
10188 }
10189 }
10190
10191 this.scanner.eat(RIGHTSQUAREBRACKET$1);
10192
10193 return {
10194 type: 'AttributeSelector',
10195 loc: this.getLocation(start, this.scanner.tokenStart),
10196 name: name,
10197 matcher: matcher,
10198 value: value,
10199 flags: flags
10200 };
10201 },
10202 generate: function(processChunk, node) {
10203 var flagsPrefix = ' ';
10204
10205 processChunk('[');
10206 this.generate(processChunk, node.name);
10207
10208 if (node.matcher !== null) {
10209 processChunk(node.matcher);
10210
10211 if (node.value !== null) {
10212 this.generate(processChunk, node.value);
10213
10214 // space between string and flags is not required
10215 if (node.value.type === 'String') {
10216 flagsPrefix = '';
10217 }
10218 }
10219 }
10220
10221 if (node.flags !== null) {
10222 processChunk(flagsPrefix);
10223 processChunk(node.flags);
10224 }
10225
10226 processChunk(']');
10227 }
10228 };
10229
10230 var TYPE$e = tokenizer.TYPE;
10231
10232 var WHITESPACE$4 = TYPE$e.WhiteSpace;
10233 var COMMENT$4 = TYPE$e.Comment;
10234 var SEMICOLON$3 = TYPE$e.Semicolon;
10235 var ATRULE$3 = TYPE$e.Atrule;
10236 var LEFTCURLYBRACKET$4 = TYPE$e.LeftCurlyBracket;
10237 var RIGHTCURLYBRACKET$2 = TYPE$e.RightCurlyBracket;
10238
10239 function consumeRaw$2(startToken) {
10240 return this.Raw(startToken, 0, SEMICOLON$3, true, true);
10241 }
10242
10243 var Block = {
10244 name: 'Block',
10245 structure: {
10246 children: [['Atrule', 'Rule', 'Declaration']]
10247 },
10248 parse: function(defaultConsumer) {
10249 if (!defaultConsumer) {
10250 defaultConsumer = this.Declaration;
10251 }
10252
10253 var start = this.scanner.tokenStart;
10254 var children = new list();
10255
10256 this.scanner.eat(LEFTCURLYBRACKET$4);
10257
10258 scan:
10259 while (!this.scanner.eof) {
10260 switch (this.scanner.tokenType) {
10261 case RIGHTCURLYBRACKET$2:
10262 break scan;
10263
10264 case WHITESPACE$4:
10265 case COMMENT$4:
10266 case SEMICOLON$3:
10267 this.scanner.next();
10268 break;
10269
10270 case ATRULE$3:
10271 children.appendData(this.tolerantParse(this.Atrule, consumeRaw$2));
10272 break;
10273
10274 default:
10275 children.appendData(this.tolerantParse(defaultConsumer, consumeRaw$2));
10276 }
10277 }
10278
10279 if (!this.tolerant || !this.scanner.eof) {
10280 this.scanner.eat(RIGHTCURLYBRACKET$2);
10281 }
10282
10283 return {
10284 type: 'Block',
10285 loc: this.getLocation(start, this.scanner.tokenStart),
10286 children: children
10287 };
10288 },
10289 generate: function(processChunk, node) {
10290 processChunk('{');
10291 this.each(processChunk, node);
10292 processChunk('}');
10293 },
10294 walkContext: 'block'
10295 };
10296
10297 var TYPE$f = tokenizer.TYPE;
10298 var LEFTSQUAREBRACKET$4 = TYPE$f.LeftSquareBracket;
10299 var RIGHTSQUAREBRACKET$2 = TYPE$f.RightSquareBracket;
10300
10301 // currently only Grid Layout uses square brackets, but left it universal
10302 // https://drafts.csswg.org/css-grid/#track-sizing
10303 // [ ident* ]
10304 var Brackets = {
10305 name: 'Brackets',
10306 structure: {
10307 children: [[]]
10308 },
10309 parse: function(readSequence, recognizer) {
10310 var start = this.scanner.tokenStart;
10311 var children = null;
10312
10313 this.scanner.eat(LEFTSQUAREBRACKET$4);
10314 children = readSequence.call(this, recognizer);
10315 this.scanner.eat(RIGHTSQUAREBRACKET$2);
10316
10317 return {
10318 type: 'Brackets',
10319 loc: this.getLocation(start, this.scanner.tokenStart),
10320 children: children
10321 };
10322 },
10323 generate: function(processChunk, node) {
10324 processChunk('[');
10325 this.each(processChunk, node);
10326 processChunk(']');
10327 }
10328 };
10329
10330 var CDC$2 = tokenizer.TYPE.CDC;
10331
10332 var CDC_1 = {
10333 name: 'CDC',
10334 structure: [],
10335 parse: function() {
10336 var start = this.scanner.tokenStart;
10337
10338 this.scanner.eat(CDC$2); // -->
10339
10340 return {
10341 type: 'CDC',
10342 loc: this.getLocation(start, this.scanner.tokenStart)
10343 };
10344 },
10345 generate: function(processChunk) {
10346 processChunk('-->');
10347 }
10348 };
10349
10350 var CDO$2 = tokenizer.TYPE.CDO;
10351
10352 var CDO_1 = {
10353 name: 'CDO',
10354 structure: [],
10355 parse: function() {
10356 var start = this.scanner.tokenStart;
10357
10358 this.scanner.eat(CDO$2); // <!--
10359
10360 return {
10361 type: 'CDO',
10362 loc: this.getLocation(start, this.scanner.tokenStart)
10363 };
10364 },
10365 generate: function(processChunk) {
10366 processChunk('<!--');
10367 }
10368 };
10369
10370 var TYPE$g = tokenizer.TYPE;
10371 var IDENTIFIER$9 = TYPE$g.Identifier;
10372 var FULLSTOP$3 = TYPE$g.FullStop;
10373
10374 // '.' ident
10375 var ClassSelector = {
10376 name: 'ClassSelector',
10377 structure: {
10378 name: String
10379 },
10380 parse: function() {
10381 this.scanner.eat(FULLSTOP$3);
10382
10383 return {
10384 type: 'ClassSelector',
10385 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10386 name: this.scanner.consume(IDENTIFIER$9)
10387 };
10388 },
10389 generate: function(processChunk, node) {
10390 processChunk('.');
10391 processChunk(node.name);
10392 }
10393 };
10394
10395 var TYPE$h = tokenizer.TYPE;
10396
10397 var PLUSSIGN$5 = TYPE$h.PlusSign;
10398 var SOLIDUS$2 = TYPE$h.Solidus;
10399 var GREATERTHANSIGN$2 = TYPE$h.GreaterThanSign;
10400 var TILDE$2 = TYPE$h.Tilde;
10401
10402 // + | > | ~ | /deep/
10403 var Combinator = {
10404 name: 'Combinator',
10405 structure: {
10406 name: String
10407 },
10408 parse: function() {
10409 var start = this.scanner.tokenStart;
10410
10411 switch (this.scanner.tokenType) {
10412 case GREATERTHANSIGN$2:
10413 case PLUSSIGN$5:
10414 case TILDE$2:
10415 this.scanner.next();
10416 break;
10417
10418 case SOLIDUS$2:
10419 this.scanner.next();
10420 this.scanner.expectIdentifier('deep');
10421 this.scanner.eat(SOLIDUS$2);
10422 break;
10423
10424 default:
10425 this.scanner.error('Combinator is expected');
10426 }
10427
10428 return {
10429 type: 'Combinator',
10430 loc: this.getLocation(start, this.scanner.tokenStart),
10431 name: this.scanner.substrToCursor(start)
10432 };
10433 },
10434 generate: function(processChunk, node) {
10435 processChunk(node.name);
10436 }
10437 };
10438
10439 var TYPE$i = tokenizer.TYPE;
10440
10441 var ASTERISK$3 = TYPE$i.Asterisk;
10442 var SOLIDUS$3 = TYPE$i.Solidus;
10443
10444 // '/*' .* '*/'
10445 var Comment = {
10446 name: 'Comment',
10447 structure: {
10448 value: String
10449 },
10450 parse: function() {
10451 var start = this.scanner.tokenStart;
10452 var end = this.scanner.tokenEnd;
10453
10454 if ((end - start + 2) >= 2 &&
10455 this.scanner.source.charCodeAt(end - 2) === ASTERISK$3 &&
10456 this.scanner.source.charCodeAt(end - 1) === SOLIDUS$3) {
10457 end -= 2;
10458 }
10459
10460 this.scanner.next();
10461
10462 return {
10463 type: 'Comment',
10464 loc: this.getLocation(start, this.scanner.tokenStart),
10465 value: this.scanner.source.substring(start + 2, end)
10466 };
10467 },
10468 generate: function(processChunk, node) {
10469 processChunk('/*');
10470 processChunk(node.value);
10471 processChunk('*/');
10472 }
10473 };
10474
10475 var TYPE$j = tokenizer.TYPE;
10476
10477 var IDENTIFIER$a = TYPE$j.Identifier;
10478 var COLON$3 = TYPE$j.Colon;
10479 var EXCLAMATIONMARK$2 = TYPE$j.ExclamationMark;
10480 var SOLIDUS$4 = TYPE$j.Solidus;
10481 var ASTERISK$4 = TYPE$j.Asterisk;
10482 var DOLLARSIGN$1 = TYPE$j.DollarSign;
10483 var HYPHENMINUS$6 = TYPE$j.HyphenMinus;
10484 var SEMICOLON$4 = TYPE$j.Semicolon;
10485 var RIGHTCURLYBRACKET$3 = TYPE$j.RightCurlyBracket;
10486 var RIGHTPARENTHESIS$1 = TYPE$j.RightParenthesis;
10487 var PLUSSIGN$6 = TYPE$j.PlusSign;
10488 var NUMBERSIGN$2 = TYPE$j.NumberSign;
10489
10490 var Declaration = {
10491 name: 'Declaration',
10492 structure: {
10493 important: [Boolean, String],
10494 property: String,
10495 value: ['Value', 'Raw']
10496 },
10497 parse: function() {
10498 var start = this.scanner.tokenStart;
10499 var property = readProperty.call(this);
10500 var important = false;
10501 var value;
10502
10503 this.scanner.skipSC();
10504 this.scanner.eat(COLON$3);
10505
10506 if (isCustomProperty(property) ? this.parseCustomProperty : this.parseValue) {
10507 value = this.Value(property);
10508 } else {
10509 value = this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$2, SEMICOLON$4, false, false);
10510 }
10511
10512 if (this.scanner.tokenType === EXCLAMATIONMARK$2) {
10513 important = getImportant(this.scanner);
10514 this.scanner.skipSC();
10515 }
10516
10517 // TODO: include or not to include semicolon to range?
10518 // if (this.scanner.tokenType === SEMICOLON) {
10519 // this.scanner.next();
10520 // }
10521
10522 if (!this.scanner.eof &&
10523 this.scanner.tokenType !== SEMICOLON$4 &&
10524 this.scanner.tokenType !== RIGHTPARENTHESIS$1 &&
10525 this.scanner.tokenType !== RIGHTCURLYBRACKET$3) {
10526 this.scanner.error();
10527 }
10528
10529 return {
10530 type: 'Declaration',
10531 loc: this.getLocation(start, this.scanner.tokenStart),
10532 important: important,
10533 property: property,
10534 value: value
10535 };
10536 },
10537 generate: function(processChunk, node, item) {
10538 processChunk(node.property);
10539 processChunk(':');
10540 this.generate(processChunk, node.value);
10541
10542 if (node.important) {
10543 processChunk(node.important === true ? '!important' : '!' + node.important);
10544 }
10545
10546 if (item && item.next) {
10547 processChunk(';');
10548 }
10549 },
10550 walkContext: 'declaration'
10551 };
10552
10553 function isCustomProperty(name) {
10554 return name.length >= 2 &&
10555 name.charCodeAt(0) === HYPHENMINUS$6 &&
10556 name.charCodeAt(1) === HYPHENMINUS$6;
10557 }
10558
10559 function readProperty() {
10560 var start = this.scanner.tokenStart;
10561 var prefix = 0;
10562
10563 // hacks
10564 switch (this.scanner.tokenType) {
10565 case ASTERISK$4:
10566 case DOLLARSIGN$1:
10567 case PLUSSIGN$6:
10568 case NUMBERSIGN$2:
10569 prefix = 1;
10570 break;
10571
10572 // TODO: not sure we should support this hack
10573 case SOLIDUS$4:
10574 prefix = this.scanner.lookupType(1) === SOLIDUS$4 ? 2 : 1;
10575 break;
10576 }
10577
10578 if (this.scanner.lookupType(prefix) === HYPHENMINUS$6) {
10579 prefix++;
10580 }
10581
10582 if (prefix) {
10583 this.scanner.skip(prefix);
10584 }
10585
10586 this.scanner.eat(IDENTIFIER$a);
10587
10588 return this.scanner.substrToCursor(start);
10589 }
10590
10591 // ! ws* important
10592 function getImportant(scanner) {
10593 scanner.eat(EXCLAMATIONMARK$2);
10594 scanner.skipSC();
10595
10596 var important = scanner.consume(IDENTIFIER$a);
10597
10598 // store original value in case it differ from `important`
10599 // for better original source restoring and hacks like `!ie` support
10600 return important === 'important' ? true : important;
10601 }
10602
10603 var TYPE$k = tokenizer.TYPE;
10604
10605 var WHITESPACE$5 = TYPE$k.WhiteSpace;
10606 var COMMENT$5 = TYPE$k.Comment;
10607 var SEMICOLON$5 = TYPE$k.Semicolon;
10608
10609 function consumeRaw$3(startToken) {
10610 return this.Raw(startToken, 0, SEMICOLON$5, true, true);
10611 }
10612
10613 var DeclarationList = {
10614 name: 'DeclarationList',
10615 structure: {
10616 children: [['Declaration']]
10617 },
10618 parse: function() {
10619 var children = new list();
10620
10621
10622 while (!this.scanner.eof) {
10623 switch (this.scanner.tokenType) {
10624 case WHITESPACE$5:
10625 case COMMENT$5:
10626 case SEMICOLON$5:
10627 this.scanner.next();
10628 break;
10629
10630 default:
10631 children.appendData(this.tolerantParse(this.Declaration, consumeRaw$3));
10632 }
10633 }
10634
10635 return {
10636 type: 'DeclarationList',
10637 loc: this.getLocationFromList(children),
10638 children: children
10639 };
10640 },
10641 generate: function(processChunk, node) {
10642 this.each(processChunk, node);
10643 }
10644 };
10645
10646 var NUMBER$5 = tokenizer.TYPE.Number;
10647
10648 // special reader for units to avoid adjoined IE hacks (i.e. '1px\9')
10649 function readUnit(scanner) {
10650 var unit = scanner.getTokenValue();
10651 var backSlashPos = unit.indexOf('\\');
10652
10653 if (backSlashPos > 0) {
10654 // patch token offset
10655 scanner.tokenStart += backSlashPos;
10656
10657 // return part before backslash
10658 return unit.substring(0, backSlashPos);
10659 }
10660
10661 // no backslash in unit name
10662 scanner.next();
10663
10664 return unit;
10665 }
10666
10667 // number ident
10668 var Dimension = {
10669 name: 'Dimension',
10670 structure: {
10671 value: String,
10672 unit: String
10673 },
10674 parse: function() {
10675 var start = this.scanner.tokenStart;
10676 var value = this.scanner.consume(NUMBER$5);
10677 var unit = readUnit(this.scanner);
10678
10679 return {
10680 type: 'Dimension',
10681 loc: this.getLocation(start, this.scanner.tokenStart),
10682 value: value,
10683 unit: unit
10684 };
10685 },
10686 generate: function(processChunk, node) {
10687 processChunk(node.value);
10688 processChunk(node.unit);
10689 }
10690 };
10691
10692 var TYPE$l = tokenizer.TYPE;
10693 var RIGHTPARENTHESIS$2 = TYPE$l.RightParenthesis;
10694
10695 // <function-token> <sequence> ')'
10696 var _Function = {
10697 name: 'Function',
10698 structure: {
10699 name: String,
10700 children: [[]]
10701 },
10702 parse: function(readSequence, recognizer) {
10703 var start = this.scanner.tokenStart;
10704 var name = this.scanner.consumeFunctionName();
10705 var nameLowerCase = name.toLowerCase();
10706 var children;
10707
10708 children = recognizer.hasOwnProperty(nameLowerCase)
10709 ? recognizer[nameLowerCase].call(this, recognizer)
10710 : readSequence.call(this, recognizer);
10711
10712 this.scanner.eat(RIGHTPARENTHESIS$2);
10713
10714 return {
10715 type: 'Function',
10716 loc: this.getLocation(start, this.scanner.tokenStart),
10717 name: name,
10718 children: children
10719 };
10720 },
10721 generate: function(processChunk, node) {
10722 processChunk(node.name);
10723 processChunk('(');
10724 this.each(processChunk, node);
10725 processChunk(')');
10726 },
10727 walkContext: 'function'
10728 };
10729
10730 var isHex$1 = tokenizer.isHex;
10731 var TYPE$m = tokenizer.TYPE;
10732
10733 var IDENTIFIER$b = TYPE$m.Identifier;
10734 var NUMBER$6 = TYPE$m.Number;
10735 var NUMBERSIGN$3 = TYPE$m.NumberSign;
10736
10737 function consumeHexSequence(scanner, required) {
10738 if (!isHex$1(scanner.source.charCodeAt(scanner.tokenStart))) {
10739 if (required) {
10740 scanner.error('Unexpected input', scanner.tokenStart);
10741 } else {
10742 return;
10743 }
10744 }
10745
10746 for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
10747 var code = scanner.source.charCodeAt(pos);
10748
10749 // break on non-hex char
10750 if (!isHex$1(code)) {
10751 // break token, exclude symbol
10752 scanner.tokenStart = pos;
10753 return;
10754 }
10755 }
10756
10757 // token is full hex sequence, go to next token
10758 scanner.next();
10759 }
10760
10761 // # ident
10762 var HexColor = {
10763 name: 'HexColor',
10764 structure: {
10765 value: String
10766 },
10767 parse: function() {
10768 var start = this.scanner.tokenStart;
10769
10770 this.scanner.eat(NUMBERSIGN$3);
10771
10772
10773 switch (this.scanner.tokenType) {
10774 case NUMBER$6:
10775 consumeHexSequence(this.scanner, true);
10776
10777 // if token is identifier then number consists of hex only,
10778 // try to add identifier to result
10779 if (this.scanner.tokenType === IDENTIFIER$b) {
10780 consumeHexSequence(this.scanner, false);
10781 }
10782
10783 break;
10784
10785 case IDENTIFIER$b:
10786 consumeHexSequence(this.scanner, true);
10787 break;
10788
10789 default:
10790 this.scanner.error('Number or identifier is expected');
10791 }
10792
10793 return {
10794 type: 'HexColor',
10795 loc: this.getLocation(start, this.scanner.tokenStart),
10796 value: this.scanner.substrToCursor(start + 1) // skip #
10797 };
10798 },
10799 generate: function(processChunk, node) {
10800 processChunk('#');
10801 processChunk(node.value);
10802 }
10803 };
10804
10805 var TYPE$n = tokenizer.TYPE;
10806 var IDENTIFIER$c = TYPE$n.Identifier;
10807
10808 var Identifier = {
10809 name: 'Identifier',
10810 structure: {
10811 name: String
10812 },
10813 parse: function() {
10814 return {
10815 type: 'Identifier',
10816 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
10817 name: this.scanner.consume(IDENTIFIER$c)
10818 };
10819 },
10820 generate: function(processChunk, node) {
10821 processChunk(node.name);
10822 }
10823 };
10824
10825 var TYPE$o = tokenizer.TYPE;
10826 var IDENTIFIER$d = TYPE$o.Identifier;
10827 var NUMBERSIGN$4 = TYPE$o.NumberSign;
10828
10829 // '#' ident
10830 var IdSelector = {
10831 name: 'IdSelector',
10832 structure: {
10833 name: String
10834 },
10835 parse: function() {
10836 this.scanner.eat(NUMBERSIGN$4);
10837
10838 return {
10839 type: 'IdSelector',
10840 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10841 name: this.scanner.consume(IDENTIFIER$d)
10842 };
10843 },
10844 generate: function(processChunk, node) {
10845 processChunk('#');
10846 processChunk(node.name);
10847 }
10848 };
10849
10850 var TYPE$p = tokenizer.TYPE;
10851
10852 var IDENTIFIER$e = TYPE$p.Identifier;
10853 var NUMBER$7 = TYPE$p.Number;
10854 var LEFTPARENTHESIS$4 = TYPE$p.LeftParenthesis;
10855 var RIGHTPARENTHESIS$3 = TYPE$p.RightParenthesis;
10856 var COLON$4 = TYPE$p.Colon;
10857 var SOLIDUS$5 = TYPE$p.Solidus;
10858
10859 var MediaFeature = {
10860 name: 'MediaFeature',
10861 structure: {
10862 name: String,
10863 value: ['Identifier', 'Number', 'Dimension', 'Ratio', null]
10864 },
10865 parse: function() {
10866 var start = this.scanner.tokenStart;
10867 var name;
10868 var value = null;
10869
10870 this.scanner.eat(LEFTPARENTHESIS$4);
10871 this.scanner.skipSC();
10872
10873 name = this.scanner.consume(IDENTIFIER$e);
10874 this.scanner.skipSC();
10875
10876 if (this.scanner.tokenType !== RIGHTPARENTHESIS$3) {
10877 this.scanner.eat(COLON$4);
10878 this.scanner.skipSC();
10879
10880 switch (this.scanner.tokenType) {
10881 case NUMBER$7:
10882 if (this.scanner.lookupType(1) === IDENTIFIER$e) {
10883 value = this.Dimension();
10884 } else if (this.scanner.lookupNonWSType(1) === SOLIDUS$5) {
10885 value = this.Ratio();
10886 } else {
10887 value = this.Number();
10888 }
10889
10890 break;
10891
10892 case IDENTIFIER$e:
10893 value = this.Identifier();
10894
10895 break;
10896
10897 default:
10898 this.scanner.error('Number, dimension, ratio or identifier is expected');
10899 }
10900
10901 this.scanner.skipSC();
10902 }
10903
10904 this.scanner.eat(RIGHTPARENTHESIS$3);
10905
10906 return {
10907 type: 'MediaFeature',
10908 loc: this.getLocation(start, this.scanner.tokenStart),
10909 name: name,
10910 value: value
10911 };
10912 },
10913 generate: function(processChunk, node) {
10914 processChunk('(');
10915 processChunk(node.name);
10916 if (node.value !== null) {
10917 processChunk(':');
10918 this.generate(processChunk, node.value);
10919 }
10920 processChunk(')');
10921 }
10922 };
10923
10924 var TYPE$q = tokenizer.TYPE;
10925
10926 var WHITESPACE$6 = TYPE$q.WhiteSpace;
10927 var COMMENT$6 = TYPE$q.Comment;
10928 var IDENTIFIER$f = TYPE$q.Identifier;
10929 var LEFTPARENTHESIS$5 = TYPE$q.LeftParenthesis;
10930
10931 var MediaQuery = {
10932 name: 'MediaQuery',
10933 structure: {
10934 children: [['Identifier', 'MediaFeature', 'WhiteSpace']]
10935 },
10936 parse: function() {
10937 this.scanner.skipSC();
10938
10939 var children = new list();
10940 var child = null;
10941 var space = null;
10942
10943 scan:
10944 while (!this.scanner.eof) {
10945 switch (this.scanner.tokenType) {
10946 case COMMENT$6:
10947 this.scanner.next();
10948 continue;
10949
10950 case WHITESPACE$6:
10951 space = this.WhiteSpace();
10952 continue;
10953
10954 case IDENTIFIER$f:
10955 child = this.Identifier();
10956 break;
10957
10958 case LEFTPARENTHESIS$5:
10959 child = this.MediaFeature();
10960 break;
10961
10962 default:
10963 break scan;
10964 }
10965
10966 if (space !== null) {
10967 children.appendData(space);
10968 space = null;
10969 }
10970
10971 children.appendData(child);
10972 }
10973
10974 if (child === null) {
10975 this.scanner.error('Identifier or parenthesis is expected');
10976 }
10977
10978 return {
10979 type: 'MediaQuery',
10980 loc: this.getLocationFromList(children),
10981 children: children
10982 };
10983 },
10984 generate: function(processChunk, node) {
10985 this.each(processChunk, node);
10986 }
10987 };
10988
10989 var COMMA$2 = tokenizer.TYPE.Comma;
10990
10991 var MediaQueryList = {
10992 name: 'MediaQueryList',
10993 structure: {
10994 children: [['MediaQuery']]
10995 },
10996 parse: function(relative) {
10997 var children = new list();
10998
10999 this.scanner.skipSC();
11000
11001 while (!this.scanner.eof) {
11002 children.appendData(this.MediaQuery(relative));
11003
11004 if (this.scanner.tokenType !== COMMA$2) {
11005 break;
11006 }
11007
11008 this.scanner.next();
11009 }
11010
11011 return {
11012 type: 'MediaQueryList',
11013 loc: this.getLocationFromList(children),
11014 children: children
11015 };
11016 },
11017 generate: function(processChunk, node) {
11018 this.eachComma(processChunk, node);
11019 }
11020 };
11021
11022 // https://drafts.csswg.org/css-syntax-3/#the-anb-type
11023 var Nth = {
11024 name: 'Nth',
11025 structure: {
11026 nth: ['AnPlusB', 'Identifier'],
11027 selector: ['SelectorList', null]
11028 },
11029 parse: function(allowOfClause) {
11030 this.scanner.skipSC();
11031
11032 var start = this.scanner.tokenStart;
11033 var end = start;
11034 var selector = null;
11035 var query;
11036
11037 if (this.scanner.lookupValue(0, 'odd') || this.scanner.lookupValue(0, 'even')) {
11038 query = this.Identifier();
11039 } else {
11040 query = this.AnPlusB();
11041 }
11042
11043 this.scanner.skipSC();
11044
11045 if (allowOfClause && this.scanner.lookupValue(0, 'of')) {
11046 this.scanner.next();
11047
11048 selector = this.SelectorList();
11049
11050 if (this.needPositions) {
11051 end = selector.children.last().loc.end.offset;
11052 }
11053 } else {
11054 if (this.needPositions) {
11055 end = query.loc.end.offset;
11056 }
11057 }
11058
11059 return {
11060 type: 'Nth',
11061 loc: this.getLocation(start, end),
11062 nth: query,
11063 selector: selector
11064 };
11065 },
11066 generate: function(processChunk, node) {
11067 this.generate(processChunk, node.nth);
11068 if (node.selector !== null) {
11069 processChunk(' of ');
11070 this.generate(processChunk, node.selector);
11071 }
11072 }
11073 };
11074
11075 var NUMBER$8 = tokenizer.TYPE.Number;
11076
11077 var _Number = {
11078 name: 'Number',
11079 structure: {
11080 value: String
11081 },
11082 parse: function() {
11083 return {
11084 type: 'Number',
11085 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11086 value: this.scanner.consume(NUMBER$8)
11087 };
11088 },
11089 generate: function(processChunk, node) {
11090 processChunk(node.value);
11091 }
11092 };
11093
11094 // '/' | '*' | ',' | ':' | '+' | '-'
11095 var Operator = {
11096 name: 'Operator',
11097 structure: {
11098 value: String
11099 },
11100 parse: function() {
11101 var start = this.scanner.tokenStart;
11102
11103 this.scanner.next();
11104
11105 return {
11106 type: 'Operator',
11107 loc: this.getLocation(start, this.scanner.tokenStart),
11108 value: this.scanner.substrToCursor(start)
11109 };
11110 },
11111 generate: function(processChunk, node) {
11112 processChunk(node.value);
11113 }
11114 };
11115
11116 var TYPE$r = tokenizer.TYPE;
11117 var LEFTPARENTHESIS$6 = TYPE$r.LeftParenthesis;
11118 var RIGHTPARENTHESIS$4 = TYPE$r.RightParenthesis;
11119
11120 var Parentheses = {
11121 name: 'Parentheses',
11122 structure: {
11123 children: [[]]
11124 },
11125 parse: function(readSequence, recognizer) {
11126 var start = this.scanner.tokenStart;
11127 var children = null;
11128
11129 this.scanner.eat(LEFTPARENTHESIS$6);
11130 children = readSequence.call(this, recognizer);
11131 this.scanner.eat(RIGHTPARENTHESIS$4);
11132
11133 return {
11134 type: 'Parentheses',
11135 loc: this.getLocation(start, this.scanner.tokenStart),
11136 children: children
11137 };
11138 },
11139 generate: function(processChunk, node) {
11140 processChunk('(');
11141 this.each(processChunk, node);
11142 processChunk(')');
11143 }
11144 };
11145
11146 var TYPE$s = tokenizer.TYPE;
11147
11148 var NUMBER$9 = TYPE$s.Number;
11149 var PERCENTSIGN$1 = TYPE$s.PercentSign;
11150
11151 var Percentage = {
11152 name: 'Percentage',
11153 structure: {
11154 value: String
11155 },
11156 parse: function() {
11157 var start = this.scanner.tokenStart;
11158 var number = this.scanner.consume(NUMBER$9);
11159
11160 this.scanner.eat(PERCENTSIGN$1);
11161
11162 return {
11163 type: 'Percentage',
11164 loc: this.getLocation(start, this.scanner.tokenStart),
11165 value: number
11166 };
11167 },
11168 generate: function(processChunk, node) {
11169 processChunk(node.value);
11170 processChunk('%');
11171 }
11172 };
11173
11174 var TYPE$t = tokenizer.TYPE;
11175
11176 var IDENTIFIER$g = TYPE$t.Identifier;
11177 var FUNCTION$4 = TYPE$t.Function;
11178 var COLON$5 = TYPE$t.Colon;
11179 var RIGHTPARENTHESIS$5 = TYPE$t.RightParenthesis;
11180
11181 // : ident [ '(' .. ')' ]?
11182 var PseudoClassSelector = {
11183 name: 'PseudoClassSelector',
11184 structure: {
11185 name: String,
11186 children: [['Raw'], null]
11187 },
11188 parse: function() {
11189 var start = this.scanner.tokenStart;
11190 var children = null;
11191 var name;
11192 var nameLowerCase;
11193
11194 this.scanner.eat(COLON$5);
11195
11196 if (this.scanner.tokenType === FUNCTION$4) {
11197 name = this.scanner.consumeFunctionName();
11198 nameLowerCase = name.toLowerCase();
11199
11200 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11201 this.scanner.skipSC();
11202 children = this.pseudo[nameLowerCase].call(this);
11203 this.scanner.skipSC();
11204 } else {
11205 children = new list().appendData(
11206 this.Raw(this.scanner.currentToken, 0, 0, false, false)
11207 );
11208 }
11209
11210 this.scanner.eat(RIGHTPARENTHESIS$5);
11211 } else {
11212 name = this.scanner.consume(IDENTIFIER$g);
11213 }
11214
11215 return {
11216 type: 'PseudoClassSelector',
11217 loc: this.getLocation(start, this.scanner.tokenStart),
11218 name: name,
11219 children: children
11220 };
11221 },
11222 generate: function(processChunk, node) {
11223 processChunk(':');
11224 processChunk(node.name);
11225
11226 if (node.children !== null) {
11227 processChunk('(');
11228 this.each(processChunk, node);
11229 processChunk(')');
11230 }
11231 },
11232 walkContext: 'function'
11233 };
11234
11235 var TYPE$u = tokenizer.TYPE;
11236
11237 var IDENTIFIER$h = TYPE$u.Identifier;
11238 var FUNCTION$5 = TYPE$u.Function;
11239 var COLON$6 = TYPE$u.Colon;
11240 var RIGHTPARENTHESIS$6 = TYPE$u.RightParenthesis;
11241
11242 // :: ident [ '(' .. ')' ]?
11243 var PseudoElementSelector = {
11244 name: 'PseudoElementSelector',
11245 structure: {
11246 name: String,
11247 children: [['Raw'], null]
11248 },
11249 parse: function() {
11250 var start = this.scanner.tokenStart;
11251 var children = null;
11252 var name;
11253 var nameLowerCase;
11254
11255 this.scanner.eat(COLON$6);
11256 this.scanner.eat(COLON$6);
11257
11258 if (this.scanner.tokenType === FUNCTION$5) {
11259 name = this.scanner.consumeFunctionName();
11260 nameLowerCase = name.toLowerCase();
11261
11262 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11263 this.scanner.skipSC();
11264 children = this.pseudo[nameLowerCase].call(this);
11265 this.scanner.skipSC();
11266 } else {
11267 children = new list().appendData(
11268 this.Raw(this.scanner.currentToken, 0, 0, false, false)
11269 );
11270 }
11271
11272 this.scanner.eat(RIGHTPARENTHESIS$6);
11273 } else {
11274 name = this.scanner.consume(IDENTIFIER$h);
11275 }
11276
11277 return {
11278 type: 'PseudoElementSelector',
11279 loc: this.getLocation(start, this.scanner.tokenStart),
11280 name: name,
11281 children: children
11282 };
11283 },
11284 generate: function(processChunk, node) {
11285 processChunk('::');
11286 processChunk(node.name);
11287
11288 if (node.children !== null) {
11289 processChunk('(');
11290 this.each(processChunk, node);
11291 processChunk(')');
11292 }
11293 },
11294 walkContext: 'function'
11295 };
11296
11297 var isNumber$3 = tokenizer.isNumber;
11298 var TYPE$v = tokenizer.TYPE;
11299 var NUMBER$a = TYPE$v.Number;
11300 var SOLIDUS$6 = TYPE$v.Solidus;
11301 var FULLSTOP$4 = TYPE$v.FullStop;
11302
11303 // Terms of <ratio> should to be a positive number (not zero or negative)
11304 // (see https://drafts.csswg.org/mediaqueries-3/#values)
11305 // However, -o-min-device-pixel-ratio takes fractional values as a ratio's term
11306 // and this is using by various sites. Therefore we relax checking on parse
11307 // to test a term is unsigned number without exponent part.
11308 // Additional checks may to be applied on lexer validation.
11309 function consumeNumber(scanner) {
11310 var value = scanner.consumeNonWS(NUMBER$a);
11311
11312 for (var i = 0; i < value.length; i++) {
11313 var code = value.charCodeAt(i);
11314 if (!isNumber$3(code) && code !== FULLSTOP$4) {
11315 scanner.error('Unsigned number is expected', scanner.tokenStart - value.length + i);
11316 }
11317 }
11318
11319 if (Number(value) === 0) {
11320 scanner.error('Zero number is not allowed', scanner.tokenStart - value.length);
11321 }
11322
11323 return value;
11324 }
11325
11326 // <positive-integer> S* '/' S* <positive-integer>
11327 var Ratio = {
11328 name: 'Ratio',
11329 structure: {
11330 left: String,
11331 right: String
11332 },
11333 parse: function() {
11334 var start = this.scanner.tokenStart;
11335 var left = consumeNumber(this.scanner);
11336 var right;
11337
11338 this.scanner.eatNonWS(SOLIDUS$6);
11339 right = consumeNumber(this.scanner);
11340
11341 return {
11342 type: 'Ratio',
11343 loc: this.getLocation(start, this.scanner.tokenStart),
11344 left: left,
11345 right: right
11346 };
11347 },
11348 generate: function(processChunk, node) {
11349 processChunk(node.left);
11350 processChunk('/');
11351 processChunk(node.right);
11352 }
11353 };
11354
11355 var Raw = {
11356 name: 'Raw',
11357 structure: {
11358 value: String
11359 },
11360 parse: function(startToken, endTokenType1, endTokenType2, includeTokenType2, excludeWhiteSpace) {
11361 var startOffset = this.scanner.getTokenStart(startToken);
11362 var endOffset;
11363
11364 this.scanner.skip(
11365 this.scanner.getRawLength(
11366 startToken,
11367 endTokenType1,
11368 endTokenType2,
11369 includeTokenType2
11370 )
11371 );
11372
11373 if (excludeWhiteSpace && this.scanner.tokenStart > startOffset) {
11374 endOffset = this.scanner.getOffsetExcludeWS();
11375 } else {
11376 endOffset = this.scanner.tokenStart;
11377 }
11378
11379 return {
11380 type: 'Raw',
11381 loc: this.getLocation(startOffset, endOffset),
11382 value: this.scanner.source.substring(startOffset, endOffset)
11383 };
11384 },
11385 generate: function(processChunk, node) {
11386 processChunk(node.value);
11387 }
11388 };
11389
11390 var TYPE$w = tokenizer.TYPE;
11391
11392 var LEFTCURLYBRACKET$5 = TYPE$w.LeftCurlyBracket;
11393
11394 function consumeRaw$4(startToken) {
11395 return this.Raw(startToken, LEFTCURLYBRACKET$5, 0, false, true);
11396 }
11397
11398 var Rule = {
11399 name: 'Rule',
11400 structure: {
11401 selector: ['SelectorList', 'Raw'],
11402 block: ['Block']
11403 },
11404 parse: function() {
11405 var startToken = this.scanner.currentToken;
11406 var startOffset = this.scanner.tokenStart;
11407 var selector = this.parseSelector
11408 ? this.tolerantParse(this.SelectorList, consumeRaw$4)
11409 : consumeRaw$4.call(this, startToken);
11410 var block = this.Block(this.Declaration);
11411
11412 return {
11413 type: 'Rule',
11414 loc: this.getLocation(startOffset, this.scanner.tokenStart),
11415 selector: selector,
11416 block: block
11417 };
11418 },
11419 generate: function(processChunk, node) {
11420 this.generate(processChunk, node.selector);
11421 this.generate(processChunk, node.block);
11422 },
11423 walkContext: 'rule'
11424 };
11425
11426 var Selector = {
11427 name: 'Selector',
11428 structure: {
11429 children: [[
11430 'TypeSelector',
11431 'IdSelector',
11432 'ClassSelector',
11433 'AttributeSelector',
11434 'PseudoClassSelector',
11435 'PseudoElementSelector',
11436 'Combinator',
11437 'WhiteSpace'
11438 ]]
11439 },
11440 parse: function() {
11441 var children = this.readSequence(this.scope.Selector);
11442
11443 // nothing were consumed
11444 if (children.isEmpty()) {
11445 this.scanner.error('Selector is expected');
11446 }
11447
11448 return {
11449 type: 'Selector',
11450 loc: this.getLocationFromList(children),
11451 children: children
11452 };
11453 },
11454 generate: function(processChunk, node) {
11455 this.each(processChunk, node);
11456 }
11457 };
11458
11459 var TYPE$x = tokenizer.TYPE;
11460
11461 var COMMA$3 = TYPE$x.Comma;
11462 var LEFTCURLYBRACKET$6 = TYPE$x.LeftCurlyBracket;
11463
11464 var SelectorList = {
11465 name: 'SelectorList',
11466 structure: {
11467 children: [['Selector', 'Raw']]
11468 },
11469 parse: function() {
11470 var children = new list();
11471
11472 while (!this.scanner.eof) {
11473 children.appendData(this.parseSelector
11474 ? this.Selector()
11475 : this.Raw(this.scanner.currentToken, COMMA$3, LEFTCURLYBRACKET$6, false, false)
11476 );
11477
11478 if (this.scanner.tokenType === COMMA$3) {
11479 this.scanner.next();
11480 continue;
11481 }
11482
11483 break;
11484 }
11485
11486 return {
11487 type: 'SelectorList',
11488 loc: this.getLocationFromList(children),
11489 children: children
11490 };
11491 },
11492 generate: function(processChunk, node) {
11493 this.eachComma(processChunk, node);
11494 },
11495 walkContext: 'selector'
11496 };
11497
11498 var STRING$5 = tokenizer.TYPE.String;
11499
11500 var _String = {
11501 name: 'String',
11502 structure: {
11503 value: String
11504 },
11505 parse: function() {
11506 return {
11507 type: 'String',
11508 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11509 value: this.scanner.consume(STRING$5)
11510 };
11511 },
11512 generate: function(processChunk, node) {
11513 processChunk(node.value);
11514 }
11515 };
11516
11517 var TYPE$y = tokenizer.TYPE;
11518
11519 var WHITESPACE$7 = TYPE$y.WhiteSpace;
11520 var COMMENT$7 = TYPE$y.Comment;
11521 var EXCLAMATIONMARK$3 = TYPE$y.ExclamationMark;
11522 var ATRULE$4 = TYPE$y.Atrule;
11523 var CDO$3 = TYPE$y.CDO;
11524 var CDC$3 = TYPE$y.CDC;
11525
11526 function consumeRaw$5(startToken) {
11527 return this.Raw(startToken, 0, 0, false, false);
11528 }
11529
11530 var StyleSheet = {
11531 name: 'StyleSheet',
11532 structure: {
11533 children: [['Comment', 'Atrule', 'Rule', 'Raw']]
11534 },
11535 parse: function() {
11536 var start = this.scanner.tokenStart;
11537 var children = new list();
11538 var child;
11539
11540
11541 while (!this.scanner.eof) {
11542 switch (this.scanner.tokenType) {
11543 case WHITESPACE$7:
11544 this.scanner.next();
11545 continue;
11546
11547 case COMMENT$7:
11548 // ignore comments except exclamation comments (i.e. /*! .. */) on top level
11549 if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 2) !== EXCLAMATIONMARK$3) {
11550 this.scanner.next();
11551 continue;
11552 }
11553
11554 child = this.Comment();
11555 break;
11556
11557 case CDO$3: // <!--
11558 child = this.CDO();
11559 break;
11560
11561 case CDC$3: // -->
11562 child = this.CDC();
11563 break;
11564
11565 // CSS Syntax Module Level 3
11566 // §2.2 Error handling
11567 // At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule.
11568 case ATRULE$4:
11569 child = this.Atrule();
11570 break;
11571
11572 // Anything else starts a qualified rule ...
11573 default:
11574 child = this.tolerantParse(this.Rule, consumeRaw$5);
11575 }
11576
11577 children.appendData(child);
11578 }
11579
11580 return {
11581 type: 'StyleSheet',
11582 loc: this.getLocation(start, this.scanner.tokenStart),
11583 children: children
11584 };
11585 },
11586 generate: function(processChunk, node) {
11587 this.each(processChunk, node);
11588 },
11589 walkContext: 'stylesheet'
11590 };
11591
11592 var TYPE$z = tokenizer.TYPE;
11593
11594 var IDENTIFIER$i = TYPE$z.Identifier;
11595 var ASTERISK$5 = TYPE$z.Asterisk;
11596 var VERTICALLINE$2 = TYPE$z.VerticalLine;
11597
11598 function eatIdentifierOrAsterisk() {
11599 if (this.scanner.tokenType !== IDENTIFIER$i &&
11600 this.scanner.tokenType !== ASTERISK$5) {
11601 this.scanner.error('Identifier or asterisk is expected');
11602 }
11603
11604 this.scanner.next();
11605 }
11606
11607 // ident
11608 // ident|ident
11609 // ident|*
11610 // *
11611 // *|ident
11612 // *|*
11613 // |ident
11614 // |*
11615 var TypeSelector = {
11616 name: 'TypeSelector',
11617 structure: {
11618 name: String
11619 },
11620 parse: function() {
11621 var start = this.scanner.tokenStart;
11622
11623 if (this.scanner.tokenType === VERTICALLINE$2) {
11624 this.scanner.next();
11625 eatIdentifierOrAsterisk.call(this);
11626 } else {
11627 eatIdentifierOrAsterisk.call(this);
11628
11629 if (this.scanner.tokenType === VERTICALLINE$2) {
11630 this.scanner.next();
11631 eatIdentifierOrAsterisk.call(this);
11632 }
11633 }
11634
11635 return {
11636 type: 'TypeSelector',
11637 loc: this.getLocation(start, this.scanner.tokenStart),
11638 name: this.scanner.substrToCursor(start)
11639 };
11640 },
11641 generate: function(processChunk, node) {
11642 processChunk(node.name);
11643 }
11644 };
11645
11646 var isHex$2 = tokenizer.isHex;
11647 var TYPE$A = tokenizer.TYPE;
11648
11649 var IDENTIFIER$j = TYPE$A.Identifier;
11650 var NUMBER$b = TYPE$A.Number;
11651 var PLUSSIGN$7 = TYPE$A.PlusSign;
11652 var HYPHENMINUS$7 = TYPE$A.HyphenMinus;
11653 var FULLSTOP$5 = TYPE$A.FullStop;
11654 var QUESTIONMARK = TYPE$A.QuestionMark;
11655
11656 function scanUnicodeNumber(scanner) {
11657 for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
11658 var code = scanner.source.charCodeAt(pos);
11659
11660 // break on fullstop or hyperminus/plussign after exponent
11661 if (code === FULLSTOP$5 || code === PLUSSIGN$7) {
11662 // break token, exclude symbol
11663 scanner.tokenStart = pos;
11664 return false;
11665 }
11666 }
11667
11668 return true;
11669 }
11670
11671 // https://drafts.csswg.org/css-syntax-3/#urange
11672 function scanUnicodeRange(scanner) {
11673 var hexStart = scanner.tokenStart + 1; // skip +
11674 var hexLength = 0;
11675
11676 scan: {
11677 if (scanner.tokenType === NUMBER$b) {
11678 if (scanner.source.charCodeAt(scanner.tokenStart) !== FULLSTOP$5 && scanUnicodeNumber(scanner)) {
11679 scanner.next();
11680 } else if (scanner.source.charCodeAt(scanner.tokenStart) !== HYPHENMINUS$7) {
11681 break scan;
11682 }
11683 } else {
11684 scanner.next(); // PLUSSIGN
11685 }
11686
11687 if (scanner.tokenType === HYPHENMINUS$7) {
11688 scanner.next();
11689 }
11690
11691 if (scanner.tokenType === NUMBER$b) {
11692 scanner.next();
11693 }
11694
11695 if (scanner.tokenType === IDENTIFIER$j) {
11696 scanner.next();
11697 }
11698
11699 if (scanner.tokenStart === hexStart) {
11700 scanner.error('Unexpected input', hexStart);
11701 }
11702 }
11703
11704 // validate for U+x{1,6} or U+x{1,6}-x{1,6}
11705 // where x is [0-9a-fA-F]
11706 for (var i = hexStart, wasHyphenMinus = false; i < scanner.tokenStart; i++) {
11707 var code = scanner.source.charCodeAt(i);
11708
11709 if (isHex$2(code) === false && (code !== HYPHENMINUS$7 || wasHyphenMinus)) {
11710 scanner.error('Unexpected input', i);
11711 }
11712
11713 if (code === HYPHENMINUS$7) {
11714 // hex sequence shouldn't be an empty
11715 if (hexLength === 0) {
11716 scanner.error('Unexpected input', i);
11717 }
11718
11719 wasHyphenMinus = true;
11720 hexLength = 0;
11721 } else {
11722 hexLength++;
11723
11724 // too long hex sequence
11725 if (hexLength > 6) {
11726 scanner.error('Too long hex sequence', i);
11727 }
11728 }
11729
11730 }
11731
11732 // check we have a non-zero sequence
11733 if (hexLength === 0) {
11734 scanner.error('Unexpected input', i - 1);
11735 }
11736
11737 // U+abc???
11738 if (!wasHyphenMinus) {
11739 // consume as many U+003F QUESTION MARK (?) code points as possible
11740 for (; hexLength < 6 && !scanner.eof; scanner.next()) {
11741 if (scanner.tokenType !== QUESTIONMARK) {
11742 break;
11743 }
11744
11745 hexLength++;
11746 }
11747 }
11748 }
11749
11750 var UnicodeRange = {
11751 name: 'UnicodeRange',
11752 structure: {
11753 value: String
11754 },
11755 parse: function() {
11756 var start = this.scanner.tokenStart;
11757
11758 this.scanner.next(); // U or u
11759 scanUnicodeRange(this.scanner);
11760
11761 return {
11762 type: 'UnicodeRange',
11763 loc: this.getLocation(start, this.scanner.tokenStart),
11764 value: this.scanner.substrToCursor(start)
11765 };
11766 },
11767 generate: function(processChunk, node) {
11768 processChunk(node.value);
11769 }
11770 };
11771
11772 var TYPE$B = tokenizer.TYPE;
11773
11774 var STRING$6 = TYPE$B.String;
11775 var URL$4 = TYPE$B.Url;
11776 var RAW$2 = TYPE$B.Raw;
11777 var RIGHTPARENTHESIS$7 = TYPE$B.RightParenthesis;
11778
11779 // url '(' S* (string | raw) S* ')'
11780 var Url = {
11781 name: 'Url',
11782 structure: {
11783 value: ['String', 'Raw']
11784 },
11785 parse: function() {
11786 var start = this.scanner.tokenStart;
11787 var value;
11788
11789 this.scanner.eat(URL$4);
11790 this.scanner.skipSC();
11791
11792 switch (this.scanner.tokenType) {
11793 case STRING$6:
11794 value = this.String();
11795 break;
11796
11797 case RAW$2:
11798 value = this.Raw(this.scanner.currentToken, 0, RAW$2, true, false);
11799 break;
11800
11801 default:
11802 this.scanner.error('String or Raw is expected');
11803 }
11804
11805 this.scanner.skipSC();
11806 this.scanner.eat(RIGHTPARENTHESIS$7);
11807
11808 return {
11809 type: 'Url',
11810 loc: this.getLocation(start, this.scanner.tokenStart),
11811 value: value
11812 };
11813 },
11814 generate: function(processChunk, node) {
11815 processChunk('url');
11816 processChunk('(');
11817 this.generate(processChunk, node.value);
11818 processChunk(')');
11819 }
11820 };
11821
11822 var endsWith$1 = tokenizer.endsWith;
11823 var TYPE$C = tokenizer.TYPE;
11824
11825 var WHITESPACE$8 = TYPE$C.WhiteSpace;
11826 var COMMENT$8 = TYPE$C.Comment;
11827 var FUNCTION$6 = TYPE$C.Function;
11828 var COLON$7 = TYPE$C.Colon;
11829 var SEMICOLON$6 = TYPE$C.Semicolon;
11830 var EXCLAMATIONMARK$4 = TYPE$C.ExclamationMark;
11831
11832 // 'progid:' ws* 'DXImageTransform.Microsoft.' ident ws* '(' .* ')'
11833 function checkProgid(scanner) {
11834 var offset = 0;
11835
11836 for (var type; type = scanner.lookupType(offset); offset++) {
11837 if (type !== WHITESPACE$8 && type !== COMMENT$8) {
11838 break;
11839 }
11840 }
11841
11842 if (scanner.lookupValue(offset, 'alpha(') ||
11843 scanner.lookupValue(offset, 'chroma(') ||
11844 scanner.lookupValue(offset, 'dropshadow(')) {
11845 if (scanner.lookupType(offset) !== FUNCTION$6) {
11846 return false;
11847 }
11848 } else {
11849 if (scanner.lookupValue(offset, 'progid') === false ||
11850 scanner.lookupType(offset + 1) !== COLON$7) {
11851 return false;
11852 }
11853 }
11854
11855 return true;
11856 }
11857
11858 var Value = {
11859 name: 'Value',
11860 structure: {
11861 children: [[]]
11862 },
11863 parse: function(property) {
11864 // special parser for filter property since it can contains non-standart syntax for old IE
11865 if (property !== null && endsWith$1(property, 'filter') && checkProgid(this.scanner)) {
11866 this.scanner.skipSC();
11867 return this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$4, SEMICOLON$6, false, false);
11868 }
11869
11870 var start = this.scanner.tokenStart;
11871 var children = this.readSequence(this.scope.Value);
11872
11873 return {
11874 type: 'Value',
11875 loc: this.getLocation(start, this.scanner.tokenStart),
11876 children: children
11877 };
11878 },
11879 generate: function(processChunk, node) {
11880 this.each(processChunk, node);
11881 }
11882 };
11883
11884 var WHITESPACE$9 = tokenizer.TYPE.WhiteSpace;
11885 var SPACE$2 = Object.freeze({
11886 type: 'WhiteSpace',
11887 loc: null,
11888 value: ' '
11889 });
11890
11891 var WhiteSpace = {
11892 name: 'WhiteSpace',
11893 structure: {
11894 value: String
11895 },
11896 parse: function() {
11897 this.scanner.eat(WHITESPACE$9);
11898 return SPACE$2;
11899
11900 // return {
11901 // type: 'WhiteSpace',
11902 // loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11903 // value: this.scanner.consume(WHITESPACE)
11904 // };
11905 },
11906 generate: function(processChunk, node) {
11907 processChunk(node.value);
11908 }
11909 };
11910
11911 var node = {
11912 AnPlusB: AnPlusB,
11913 Atrule: Atrule,
11914 AtruleExpression: AtruleExpression,
11915 AttributeSelector: AttributeSelector,
11916 Block: Block,
11917 Brackets: Brackets,
11918 CDC: CDC_1,
11919 CDO: CDO_1,
11920 ClassSelector: ClassSelector,
11921 Combinator: Combinator,
11922 Comment: Comment,
11923 Declaration: Declaration,
11924 DeclarationList: DeclarationList,
11925 Dimension: Dimension,
11926 Function: _Function,
11927 HexColor: HexColor,
11928 Identifier: Identifier,
11929 IdSelector: IdSelector,
11930 MediaFeature: MediaFeature,
11931 MediaQuery: MediaQuery,
11932 MediaQueryList: MediaQueryList,
11933 Nth: Nth,
11934 Number: _Number,
11935 Operator: Operator,
11936 Parentheses: Parentheses,
11937 Percentage: Percentage,
11938 PseudoClassSelector: PseudoClassSelector,
11939 PseudoElementSelector: PseudoElementSelector,
11940 Ratio: Ratio,
11941 Raw: Raw,
11942 Rule: Rule,
11943 Selector: Selector,
11944 SelectorList: SelectorList,
11945 String: _String,
11946 StyleSheet: StyleSheet,
11947 TypeSelector: TypeSelector,
11948 UnicodeRange: UnicodeRange,
11949 Url: Url,
11950 Value: Value,
11951 WhiteSpace: WhiteSpace
11952 };
11953
11954 var parser = {
11955 parseContext: {
11956 default: 'StyleSheet',
11957 stylesheet: 'StyleSheet',
11958 atrule: 'Atrule',
11959 atruleExpression: function(options) {
11960 return this.AtruleExpression(options.atrule ? String(options.atrule) : null);
11961 },
11962 mediaQueryList: 'MediaQueryList',
11963 mediaQuery: 'MediaQuery',
11964 rule: 'Rule',
11965 selectorList: 'SelectorList',
11966 selector: 'Selector',
11967 block: function() {
11968 return this.Block(this.Declaration);
11969 },
11970 declarationList: 'DeclarationList',
11971 declaration: 'Declaration',
11972 value: function(options) {
11973 return this.Value(options.property ? String(options.property) : null);
11974 }
11975 },
11976 scope: scope,
11977 atrule: atrule,
11978 pseudo: pseudo,
11979 node: node
11980 };
11981
11982 var parser$1 = create(parser);
11983
11984 function read_style(parser, start, attributes) {
11985 const content_start = parser.index;
11986 const styles = parser.read_until(/<\/style>/);
11987 const content_end = parser.index;
11988 let ast;
11989 try {
11990 ast = parser$1(styles, {
11991 positions: true,
11992 offset: content_start,
11993 });
11994 }
11995 catch (err) {
11996 if (err.name === 'CssSyntaxError') {
11997 parser.error({
11998 code: `css-syntax-error`,
11999 message: err.message
12000 }, err.offset);
12001 }
12002 else {
12003 throw err;
12004 }
12005 }
12006 ast = JSON.parse(JSON.stringify(ast));
12007 // tidy up AST
12008 walk(ast, {
12009 enter: (node) => {
12010 // replace `ref:a` nodes
12011 if (node.type === 'Selector') {
12012 for (let i = 0; i < node.children.length; i += 1) {
12013 const a = node.children[i];
12014 const b = node.children[i + 1];
12015 if (is_ref_selector(a, b)) {
12016 parser.error({
12017 code: `invalid-ref-selector`,
12018 message: 'ref selectors are no longer supported'
12019 }, a.loc.start.offset);
12020 }
12021 }
12022 }
12023 if (node.type === 'Declaration' && node.value.type === 'Value' && node.value.children.length === 0) {
12024 parser.error({
12025 code: `invalid-declaration`,
12026 message: `Declaration cannot be empty`
12027 }, node.start);
12028 }
12029 if (node.type === 'PseudoClassSelector' && node.name === 'global' && node.children === null) {
12030 parser.error({
12031 code: `css-syntax-error`,
12032 message: `:global() must contain a selector`
12033 }, node.loc.start.offset);
12034 }
12035 if (node.loc) {
12036 node.start = node.loc.start.offset;
12037 node.end = node.loc.end.offset;
12038 delete node.loc;
12039 }
12040 }
12041 });
12042 parser.eat('</style>', true);
12043 const end = parser.index;
12044 return {
12045 type: 'Style',
12046 start,
12047 end,
12048 attributes,
12049 children: ast.children,
12050 content: {
12051 start: content_start,
12052 end: content_end,
12053 styles
12054 }
12055 };
12056 }
12057 function is_ref_selector(a, b) {
12058 if (!b)
12059 return false;
12060 return (a.type === 'TypeSelector' &&
12061 a.name === 'ref' &&
12062 b.type === 'PseudoClassSelector');
12063 }
12064
12065 // https://dev.w3.org/html5/html-author/charref
12066 var entities = {
12067 CounterClockwiseContourIntegral: 8755,
12068 ClockwiseContourIntegral: 8754,
12069 DoubleLongLeftRightArrow: 10234,
12070 DiacriticalDoubleAcute: 733,
12071 NotSquareSupersetEqual: 8931,
12072 CloseCurlyDoubleQuote: 8221,
12073 DoubleContourIntegral: 8751,
12074 FilledVerySmallSquare: 9642,
12075 NegativeVeryThinSpace: 8203,
12076 NotPrecedesSlantEqual: 8928,
12077 NotRightTriangleEqual: 8941,
12078 NotSucceedsSlantEqual: 8929,
12079 CapitalDifferentialD: 8517,
12080 DoubleLeftRightArrow: 8660,
12081 DoubleLongRightArrow: 10233,
12082 EmptyVerySmallSquare: 9643,
12083 NestedGreaterGreater: 8811,
12084 NotDoubleVerticalBar: 8742,
12085 NotLeftTriangleEqual: 8940,
12086 NotSquareSubsetEqual: 8930,
12087 OpenCurlyDoubleQuote: 8220,
12088 ReverseUpEquilibrium: 10607,
12089 DoubleLongLeftArrow: 10232,
12090 DownLeftRightVector: 10576,
12091 LeftArrowRightArrow: 8646,
12092 NegativeMediumSpace: 8203,
12093 RightArrowLeftArrow: 8644,
12094 SquareSupersetEqual: 8850,
12095 leftrightsquigarrow: 8621,
12096 DownRightTeeVector: 10591,
12097 DownRightVectorBar: 10583,
12098 LongLeftRightArrow: 10231,
12099 Longleftrightarrow: 10234,
12100 NegativeThickSpace: 8203,
12101 PrecedesSlantEqual: 8828,
12102 ReverseEquilibrium: 8651,
12103 RightDoubleBracket: 10215,
12104 RightDownTeeVector: 10589,
12105 RightDownVectorBar: 10581,
12106 RightTriangleEqual: 8885,
12107 SquareIntersection: 8851,
12108 SucceedsSlantEqual: 8829,
12109 blacktriangleright: 9656,
12110 longleftrightarrow: 10231,
12111 DoubleUpDownArrow: 8661,
12112 DoubleVerticalBar: 8741,
12113 DownLeftTeeVector: 10590,
12114 DownLeftVectorBar: 10582,
12115 FilledSmallSquare: 9724,
12116 GreaterSlantEqual: 10878,
12117 LeftDoubleBracket: 10214,
12118 LeftDownTeeVector: 10593,
12119 LeftDownVectorBar: 10585,
12120 LeftTriangleEqual: 8884,
12121 NegativeThinSpace: 8203,
12122 NotReverseElement: 8716,
12123 NotTildeFullEqual: 8775,
12124 RightAngleBracket: 10217,
12125 RightUpDownVector: 10575,
12126 SquareSubsetEqual: 8849,
12127 VerticalSeparator: 10072,
12128 blacktriangledown: 9662,
12129 blacktriangleleft: 9666,
12130 leftrightharpoons: 8651,
12131 rightleftharpoons: 8652,
12132 twoheadrightarrow: 8608,
12133 DiacriticalAcute: 180,
12134 DiacriticalGrave: 96,
12135 DiacriticalTilde: 732,
12136 DoubleRightArrow: 8658,
12137 DownArrowUpArrow: 8693,
12138 EmptySmallSquare: 9723,
12139 GreaterEqualLess: 8923,
12140 GreaterFullEqual: 8807,
12141 LeftAngleBracket: 10216,
12142 LeftUpDownVector: 10577,
12143 LessEqualGreater: 8922,
12144 NonBreakingSpace: 160,
12145 NotRightTriangle: 8939,
12146 NotSupersetEqual: 8841,
12147 RightTriangleBar: 10704,
12148 RightUpTeeVector: 10588,
12149 RightUpVectorBar: 10580,
12150 UnderParenthesis: 9181,
12151 UpArrowDownArrow: 8645,
12152 circlearrowright: 8635,
12153 downharpoonright: 8642,
12154 ntrianglerighteq: 8941,
12155 rightharpoondown: 8641,
12156 rightrightarrows: 8649,
12157 twoheadleftarrow: 8606,
12158 vartriangleright: 8883,
12159 CloseCurlyQuote: 8217,
12160 ContourIntegral: 8750,
12161 DoubleDownArrow: 8659,
12162 DoubleLeftArrow: 8656,
12163 DownRightVector: 8641,
12164 LeftRightVector: 10574,
12165 LeftTriangleBar: 10703,
12166 LeftUpTeeVector: 10592,
12167 LeftUpVectorBar: 10584,
12168 LowerRightArrow: 8600,
12169 NotGreaterEqual: 8817,
12170 NotGreaterTilde: 8821,
12171 NotLeftTriangle: 8938,
12172 OverParenthesis: 9180,
12173 RightDownVector: 8642,
12174 ShortRightArrow: 8594,
12175 UpperRightArrow: 8599,
12176 bigtriangledown: 9661,
12177 circlearrowleft: 8634,
12178 curvearrowright: 8631,
12179 downharpoonleft: 8643,
12180 leftharpoondown: 8637,
12181 leftrightarrows: 8646,
12182 nLeftrightarrow: 8654,
12183 nleftrightarrow: 8622,
12184 ntrianglelefteq: 8940,
12185 rightleftarrows: 8644,
12186 rightsquigarrow: 8605,
12187 rightthreetimes: 8908,
12188 straightepsilon: 1013,
12189 trianglerighteq: 8885,
12190 vartriangleleft: 8882,
12191 DiacriticalDot: 729,
12192 DoubleRightTee: 8872,
12193 DownLeftVector: 8637,
12194 GreaterGreater: 10914,
12195 HorizontalLine: 9472,
12196 InvisibleComma: 8291,
12197 InvisibleTimes: 8290,
12198 LeftDownVector: 8643,
12199 LeftRightArrow: 8596,
12200 Leftrightarrow: 8660,
12201 LessSlantEqual: 10877,
12202 LongRightArrow: 10230,
12203 Longrightarrow: 10233,
12204 LowerLeftArrow: 8601,
12205 NestedLessLess: 8810,
12206 NotGreaterLess: 8825,
12207 NotLessGreater: 8824,
12208 NotSubsetEqual: 8840,
12209 NotVerticalBar: 8740,
12210 OpenCurlyQuote: 8216,
12211 ReverseElement: 8715,
12212 RightTeeVector: 10587,
12213 RightVectorBar: 10579,
12214 ShortDownArrow: 8595,
12215 ShortLeftArrow: 8592,
12216 SquareSuperset: 8848,
12217 TildeFullEqual: 8773,
12218 UpperLeftArrow: 8598,
12219 ZeroWidthSpace: 8203,
12220 curvearrowleft: 8630,
12221 doublebarwedge: 8966,
12222 downdownarrows: 8650,
12223 hookrightarrow: 8618,
12224 leftleftarrows: 8647,
12225 leftrightarrow: 8596,
12226 leftthreetimes: 8907,
12227 longrightarrow: 10230,
12228 looparrowright: 8620,
12229 nshortparallel: 8742,
12230 ntriangleright: 8939,
12231 rightarrowtail: 8611,
12232 rightharpoonup: 8640,
12233 trianglelefteq: 8884,
12234 upharpoonright: 8638,
12235 ApplyFunction: 8289,
12236 DifferentialD: 8518,
12237 DoubleLeftTee: 10980,
12238 DoubleUpArrow: 8657,
12239 LeftTeeVector: 10586,
12240 LeftVectorBar: 10578,
12241 LessFullEqual: 8806,
12242 LongLeftArrow: 10229,
12243 Longleftarrow: 10232,
12244 NotTildeEqual: 8772,
12245 NotTildeTilde: 8777,
12246 Poincareplane: 8460,
12247 PrecedesEqual: 10927,
12248 PrecedesTilde: 8830,
12249 RightArrowBar: 8677,
12250 RightTeeArrow: 8614,
12251 RightTriangle: 8883,
12252 RightUpVector: 8638,
12253 SucceedsEqual: 10928,
12254 SucceedsTilde: 8831,
12255 SupersetEqual: 8839,
12256 UpEquilibrium: 10606,
12257 VerticalTilde: 8768,
12258 VeryThinSpace: 8202,
12259 bigtriangleup: 9651,
12260 blacktriangle: 9652,
12261 divideontimes: 8903,
12262 fallingdotseq: 8786,
12263 hookleftarrow: 8617,
12264 leftarrowtail: 8610,
12265 leftharpoonup: 8636,
12266 longleftarrow: 10229,
12267 looparrowleft: 8619,
12268 measuredangle: 8737,
12269 ntriangleleft: 8938,
12270 shortparallel: 8741,
12271 smallsetminus: 8726,
12272 triangleright: 9657,
12273 upharpoonleft: 8639,
12274 DownArrowBar: 10515,
12275 DownTeeArrow: 8615,
12276 ExponentialE: 8519,
12277 GreaterEqual: 8805,
12278 GreaterTilde: 8819,
12279 HilbertSpace: 8459,
12280 HumpDownHump: 8782,
12281 Intersection: 8898,
12282 LeftArrowBar: 8676,
12283 LeftTeeArrow: 8612,
12284 LeftTriangle: 8882,
12285 LeftUpVector: 8639,
12286 NotCongruent: 8802,
12287 NotLessEqual: 8816,
12288 NotLessTilde: 8820,
12289 Proportional: 8733,
12290 RightCeiling: 8969,
12291 RoundImplies: 10608,
12292 ShortUpArrow: 8593,
12293 SquareSubset: 8847,
12294 UnderBracket: 9141,
12295 VerticalLine: 124,
12296 blacklozenge: 10731,
12297 exponentiale: 8519,
12298 risingdotseq: 8787,
12299 triangledown: 9663,
12300 triangleleft: 9667,
12301 CircleMinus: 8854,
12302 CircleTimes: 8855,
12303 Equilibrium: 8652,
12304 GreaterLess: 8823,
12305 LeftCeiling: 8968,
12306 LessGreater: 8822,
12307 MediumSpace: 8287,
12308 NotPrecedes: 8832,
12309 NotSucceeds: 8833,
12310 OverBracket: 9140,
12311 RightVector: 8640,
12312 Rrightarrow: 8667,
12313 RuleDelayed: 10740,
12314 SmallCircle: 8728,
12315 SquareUnion: 8852,
12316 SubsetEqual: 8838,
12317 UpDownArrow: 8597,
12318 Updownarrow: 8661,
12319 VerticalBar: 8739,
12320 backepsilon: 1014,
12321 blacksquare: 9642,
12322 circledcirc: 8858,
12323 circleddash: 8861,
12324 curlyeqprec: 8926,
12325 curlyeqsucc: 8927,
12326 diamondsuit: 9830,
12327 eqslantless: 10901,
12328 expectation: 8496,
12329 nRightarrow: 8655,
12330 nrightarrow: 8603,
12331 preccurlyeq: 8828,
12332 precnapprox: 10937,
12333 quaternions: 8461,
12334 straightphi: 981,
12335 succcurlyeq: 8829,
12336 succnapprox: 10938,
12337 thickapprox: 8776,
12338 updownarrow: 8597,
12339 Bernoullis: 8492,
12340 CirclePlus: 8853,
12341 EqualTilde: 8770,
12342 Fouriertrf: 8497,
12343 ImaginaryI: 8520,
12344 Laplacetrf: 8466,
12345 LeftVector: 8636,
12346 Lleftarrow: 8666,
12347 NotElement: 8713,
12348 NotGreater: 8815,
12349 Proportion: 8759,
12350 RightArrow: 8594,
12351 RightFloor: 8971,
12352 Rightarrow: 8658,
12353 TildeEqual: 8771,
12354 TildeTilde: 8776,
12355 UnderBrace: 9183,
12356 UpArrowBar: 10514,
12357 UpTeeArrow: 8613,
12358 circledast: 8859,
12359 complement: 8705,
12360 curlywedge: 8911,
12361 eqslantgtr: 10902,
12362 gtreqqless: 10892,
12363 lessapprox: 10885,
12364 lesseqqgtr: 10891,
12365 lmoustache: 9136,
12366 longmapsto: 10236,
12367 mapstodown: 8615,
12368 mapstoleft: 8612,
12369 nLeftarrow: 8653,
12370 nleftarrow: 8602,
12371 precapprox: 10935,
12372 rightarrow: 8594,
12373 rmoustache: 9137,
12374 sqsubseteq: 8849,
12375 sqsupseteq: 8850,
12376 subsetneqq: 10955,
12377 succapprox: 10936,
12378 supsetneqq: 10956,
12379 upuparrows: 8648,
12380 varepsilon: 949,
12381 varnothing: 8709,
12382 Backslash: 8726,
12383 CenterDot: 183,
12384 CircleDot: 8857,
12385 Congruent: 8801,
12386 Coproduct: 8720,
12387 DoubleDot: 168,
12388 DownArrow: 8595,
12389 DownBreve: 785,
12390 Downarrow: 8659,
12391 HumpEqual: 8783,
12392 LeftArrow: 8592,
12393 LeftFloor: 8970,
12394 Leftarrow: 8656,
12395 LessTilde: 8818,
12396 Mellintrf: 8499,
12397 MinusPlus: 8723,
12398 NotCupCap: 8813,
12399 NotExists: 8708,
12400 OverBrace: 9182,
12401 PlusMinus: 177,
12402 Therefore: 8756,
12403 ThinSpace: 8201,
12404 TripleDot: 8411,
12405 UnionPlus: 8846,
12406 backprime: 8245,
12407 backsimeq: 8909,
12408 bigotimes: 10754,
12409 centerdot: 183,
12410 checkmark: 10003,
12411 complexes: 8450,
12412 dotsquare: 8865,
12413 downarrow: 8595,
12414 gtrapprox: 10886,
12415 gtreqless: 8923,
12416 heartsuit: 9829,
12417 leftarrow: 8592,
12418 lesseqgtr: 8922,
12419 nparallel: 8742,
12420 nshortmid: 8740,
12421 nsubseteq: 8840,
12422 nsupseteq: 8841,
12423 pitchfork: 8916,
12424 rationals: 8474,
12425 spadesuit: 9824,
12426 subseteqq: 10949,
12427 subsetneq: 8842,
12428 supseteqq: 10950,
12429 supsetneq: 8843,
12430 therefore: 8756,
12431 triangleq: 8796,
12432 varpropto: 8733,
12433 DDotrahd: 10513,
12434 DotEqual: 8784,
12435 Integral: 8747,
12436 LessLess: 10913,
12437 NotEqual: 8800,
12438 NotTilde: 8769,
12439 PartialD: 8706,
12440 Precedes: 8826,
12441 RightTee: 8866,
12442 Succeeds: 8827,
12443 SuchThat: 8715,
12444 Superset: 8835,
12445 Uarrocir: 10569,
12446 UnderBar: 818,
12447 andslope: 10840,
12448 angmsdaa: 10664,
12449 angmsdab: 10665,
12450 angmsdac: 10666,
12451 angmsdad: 10667,
12452 angmsdae: 10668,
12453 angmsdaf: 10669,
12454 angmsdag: 10670,
12455 angmsdah: 10671,
12456 angrtvbd: 10653,
12457 approxeq: 8778,
12458 awconint: 8755,
12459 backcong: 8780,
12460 barwedge: 8965,
12461 bbrktbrk: 9142,
12462 bigoplus: 10753,
12463 bigsqcup: 10758,
12464 biguplus: 10756,
12465 bigwedge: 8896,
12466 boxminus: 8863,
12467 boxtimes: 8864,
12468 capbrcup: 10825,
12469 circledR: 174,
12470 circledS: 9416,
12471 cirfnint: 10768,
12472 clubsuit: 9827,
12473 cupbrcap: 10824,
12474 curlyvee: 8910,
12475 cwconint: 8754,
12476 doteqdot: 8785,
12477 dotminus: 8760,
12478 drbkarow: 10512,
12479 dzigrarr: 10239,
12480 elinters: 9191,
12481 emptyset: 8709,
12482 eqvparsl: 10725,
12483 fpartint: 10765,
12484 geqslant: 10878,
12485 gesdotol: 10884,
12486 gnapprox: 10890,
12487 hksearow: 10533,
12488 hkswarow: 10534,
12489 imagline: 8464,
12490 imagpart: 8465,
12491 infintie: 10717,
12492 integers: 8484,
12493 intercal: 8890,
12494 intlarhk: 10775,
12495 laemptyv: 10676,
12496 ldrushar: 10571,
12497 leqslant: 10877,
12498 lesdotor: 10883,
12499 llcorner: 8990,
12500 lnapprox: 10889,
12501 lrcorner: 8991,
12502 lurdshar: 10570,
12503 mapstoup: 8613,
12504 multimap: 8888,
12505 naturals: 8469,
12506 otimesas: 10806,
12507 parallel: 8741,
12508 plusacir: 10787,
12509 pointint: 10773,
12510 precneqq: 10933,
12511 precnsim: 8936,
12512 profalar: 9006,
12513 profline: 8978,
12514 profsurf: 8979,
12515 raemptyv: 10675,
12516 realpart: 8476,
12517 rppolint: 10770,
12518 rtriltri: 10702,
12519 scpolint: 10771,
12520 setminus: 8726,
12521 shortmid: 8739,
12522 smeparsl: 10724,
12523 sqsubset: 8847,
12524 sqsupset: 8848,
12525 subseteq: 8838,
12526 succneqq: 10934,
12527 succnsim: 8937,
12528 supseteq: 8839,
12529 thetasym: 977,
12530 thicksim: 8764,
12531 timesbar: 10801,
12532 triangle: 9653,
12533 triminus: 10810,
12534 trpezium: 9186,
12535 ulcorner: 8988,
12536 urcorner: 8989,
12537 varkappa: 1008,
12538 varsigma: 962,
12539 vartheta: 977,
12540 Because: 8757,
12541 Cayleys: 8493,
12542 Cconint: 8752,
12543 Cedilla: 184,
12544 Diamond: 8900,
12545 DownTee: 8868,
12546 Element: 8712,
12547 Epsilon: 917,
12548 Implies: 8658,
12549 LeftTee: 8867,
12550 NewLine: 10,
12551 NoBreak: 8288,
12552 NotLess: 8814,
12553 Omicron: 927,
12554 OverBar: 175,
12555 Product: 8719,
12556 UpArrow: 8593,
12557 Uparrow: 8657,
12558 Upsilon: 933,
12559 alefsym: 8501,
12560 angrtvb: 8894,
12561 angzarr: 9084,
12562 asympeq: 8781,
12563 backsim: 8765,
12564 because: 8757,
12565 bemptyv: 10672,
12566 between: 8812,
12567 bigcirc: 9711,
12568 bigodot: 10752,
12569 bigstar: 9733,
12570 boxplus: 8862,
12571 ccupssm: 10832,
12572 cemptyv: 10674,
12573 cirscir: 10690,
12574 coloneq: 8788,
12575 congdot: 10861,
12576 cudarrl: 10552,
12577 cudarrr: 10549,
12578 cularrp: 10557,
12579 curarrm: 10556,
12580 dbkarow: 10511,
12581 ddagger: 8225,
12582 ddotseq: 10871,
12583 demptyv: 10673,
12584 diamond: 8900,
12585 digamma: 989,
12586 dotplus: 8724,
12587 dwangle: 10662,
12588 epsilon: 949,
12589 eqcolon: 8789,
12590 equivDD: 10872,
12591 gesdoto: 10882,
12592 gtquest: 10876,
12593 gtrless: 8823,
12594 harrcir: 10568,
12595 intprod: 10812,
12596 isindot: 8949,
12597 larrbfs: 10527,
12598 larrsim: 10611,
12599 lbrksld: 10639,
12600 lbrkslu: 10637,
12601 ldrdhar: 10599,
12602 lesdoto: 10881,
12603 lessdot: 8918,
12604 lessgtr: 8822,
12605 lesssim: 8818,
12606 lotimes: 10804,
12607 lozenge: 9674,
12608 ltquest: 10875,
12609 luruhar: 10598,
12610 maltese: 10016,
12611 minusdu: 10794,
12612 napprox: 8777,
12613 natural: 9838,
12614 nearrow: 8599,
12615 nexists: 8708,
12616 notinva: 8713,
12617 notinvb: 8951,
12618 notinvc: 8950,
12619 notniva: 8716,
12620 notnivb: 8958,
12621 notnivc: 8957,
12622 npolint: 10772,
12623 nsqsube: 8930,
12624 nsqsupe: 8931,
12625 nvinfin: 10718,
12626 nwarrow: 8598,
12627 olcross: 10683,
12628 omicron: 959,
12629 orderof: 8500,
12630 orslope: 10839,
12631 pertenk: 8241,
12632 planckh: 8462,
12633 pluscir: 10786,
12634 plussim: 10790,
12635 plustwo: 10791,
12636 precsim: 8830,
12637 quatint: 10774,
12638 questeq: 8799,
12639 rarrbfs: 10528,
12640 rarrsim: 10612,
12641 rbrksld: 10638,
12642 rbrkslu: 10640,
12643 rdldhar: 10601,
12644 realine: 8475,
12645 rotimes: 10805,
12646 ruluhar: 10600,
12647 searrow: 8600,
12648 simplus: 10788,
12649 simrarr: 10610,
12650 subedot: 10947,
12651 submult: 10945,
12652 subplus: 10943,
12653 subrarr: 10617,
12654 succsim: 8831,
12655 supdsub: 10968,
12656 supedot: 10948,
12657 suphsub: 10967,
12658 suplarr: 10619,
12659 supmult: 10946,
12660 supplus: 10944,
12661 swarrow: 8601,
12662 topfork: 10970,
12663 triplus: 10809,
12664 tritime: 10811,
12665 uparrow: 8593,
12666 upsilon: 965,
12667 uwangle: 10663,
12668 vzigzag: 10650,
12669 zigrarr: 8669,
12670 Aacute: 193,
12671 Abreve: 258,
12672 Agrave: 192,
12673 Assign: 8788,
12674 Atilde: 195,
12675 Barwed: 8966,
12676 Bumpeq: 8782,
12677 Cacute: 262,
12678 Ccaron: 268,
12679 Ccedil: 199,
12680 Colone: 10868,
12681 Conint: 8751,
12682 CupCap: 8781,
12683 Dagger: 8225,
12684 Dcaron: 270,
12685 DotDot: 8412,
12686 Dstrok: 272,
12687 Eacute: 201,
12688 Ecaron: 282,
12689 Egrave: 200,
12690 Exists: 8707,
12691 ForAll: 8704,
12692 Gammad: 988,
12693 Gbreve: 286,
12694 Gcedil: 290,
12695 HARDcy: 1066,
12696 Hstrok: 294,
12697 Iacute: 205,
12698 Igrave: 204,
12699 Itilde: 296,
12700 Jsercy: 1032,
12701 Kcedil: 310,
12702 Lacute: 313,
12703 Lambda: 923,
12704 Lcaron: 317,
12705 Lcedil: 315,
12706 Lmidot: 319,
12707 Lstrok: 321,
12708 Nacute: 323,
12709 Ncaron: 327,
12710 Ncedil: 325,
12711 Ntilde: 209,
12712 Oacute: 211,
12713 Odblac: 336,
12714 Ograve: 210,
12715 Oslash: 216,
12716 Otilde: 213,
12717 Otimes: 10807,
12718 Racute: 340,
12719 Rarrtl: 10518,
12720 Rcaron: 344,
12721 Rcedil: 342,
12722 SHCHcy: 1065,
12723 SOFTcy: 1068,
12724 Sacute: 346,
12725 Scaron: 352,
12726 Scedil: 350,
12727 Square: 9633,
12728 Subset: 8912,
12729 Supset: 8913,
12730 Tcaron: 356,
12731 Tcedil: 354,
12732 Tstrok: 358,
12733 Uacute: 218,
12734 Ubreve: 364,
12735 Udblac: 368,
12736 Ugrave: 217,
12737 Utilde: 360,
12738 Vdashl: 10982,
12739 Verbar: 8214,
12740 Vvdash: 8874,
12741 Yacute: 221,
12742 Zacute: 377,
12743 Zcaron: 381,
12744 aacute: 225,
12745 abreve: 259,
12746 agrave: 224,
12747 andand: 10837,
12748 angmsd: 8737,
12749 angsph: 8738,
12750 apacir: 10863,
12751 approx: 8776,
12752 atilde: 227,
12753 barvee: 8893,
12754 barwed: 8965,
12755 becaus: 8757,
12756 bernou: 8492,
12757 bigcap: 8898,
12758 bigcup: 8899,
12759 bigvee: 8897,
12760 bkarow: 10509,
12761 bottom: 8869,
12762 bowtie: 8904,
12763 boxbox: 10697,
12764 bprime: 8245,
12765 brvbar: 166,
12766 bullet: 8226,
12767 bumpeq: 8783,
12768 cacute: 263,
12769 capand: 10820,
12770 capcap: 10827,
12771 capcup: 10823,
12772 capdot: 10816,
12773 ccaron: 269,
12774 ccedil: 231,
12775 circeq: 8791,
12776 cirmid: 10991,
12777 colone: 8788,
12778 commat: 64,
12779 compfn: 8728,
12780 conint: 8750,
12781 coprod: 8720,
12782 copysr: 8471,
12783 cularr: 8630,
12784 cupcap: 10822,
12785 cupcup: 10826,
12786 cupdot: 8845,
12787 curarr: 8631,
12788 curren: 164,
12789 cylcty: 9005,
12790 dagger: 8224,
12791 daleth: 8504,
12792 dcaron: 271,
12793 dfisht: 10623,
12794 divide: 247,
12795 divonx: 8903,
12796 dlcorn: 8990,
12797 dlcrop: 8973,
12798 dollar: 36,
12799 drcorn: 8991,
12800 drcrop: 8972,
12801 dstrok: 273,
12802 eacute: 233,
12803 easter: 10862,
12804 ecaron: 283,
12805 ecolon: 8789,
12806 egrave: 232,
12807 egsdot: 10904,
12808 elsdot: 10903,
12809 emptyv: 8709,
12810 emsp13: 8196,
12811 emsp14: 8197,
12812 eparsl: 10723,
12813 eqcirc: 8790,
12814 equals: 61,
12815 equest: 8799,
12816 female: 9792,
12817 ffilig: 64259,
12818 ffllig: 64260,
12819 forall: 8704,
12820 frac12: 189,
12821 frac13: 8531,
12822 frac14: 188,
12823 frac15: 8533,
12824 frac16: 8537,
12825 frac18: 8539,
12826 frac23: 8532,
12827 frac25: 8534,
12828 frac34: 190,
12829 frac35: 8535,
12830 frac38: 8540,
12831 frac45: 8536,
12832 frac56: 8538,
12833 frac58: 8541,
12834 frac78: 8542,
12835 gacute: 501,
12836 gammad: 989,
12837 gbreve: 287,
12838 gesdot: 10880,
12839 gesles: 10900,
12840 gtlPar: 10645,
12841 gtrarr: 10616,
12842 gtrdot: 8919,
12843 gtrsim: 8819,
12844 hairsp: 8202,
12845 hamilt: 8459,
12846 hardcy: 1098,
12847 hearts: 9829,
12848 hellip: 8230,
12849 hercon: 8889,
12850 homtht: 8763,
12851 horbar: 8213,
12852 hslash: 8463,
12853 hstrok: 295,
12854 hybull: 8259,
12855 hyphen: 8208,
12856 iacute: 237,
12857 igrave: 236,
12858 iiiint: 10764,
12859 iinfin: 10716,
12860 incare: 8453,
12861 inodot: 305,
12862 intcal: 8890,
12863 iquest: 191,
12864 isinsv: 8947,
12865 itilde: 297,
12866 jsercy: 1112,
12867 kappav: 1008,
12868 kcedil: 311,
12869 kgreen: 312,
12870 lAtail: 10523,
12871 lacute: 314,
12872 lagran: 8466,
12873 lambda: 955,
12874 langle: 10216,
12875 larrfs: 10525,
12876 larrhk: 8617,
12877 larrlp: 8619,
12878 larrpl: 10553,
12879 larrtl: 8610,
12880 latail: 10521,
12881 lbrace: 123,
12882 lbrack: 91,
12883 lcaron: 318,
12884 lcedil: 316,
12885 ldquor: 8222,
12886 lesdot: 10879,
12887 lesges: 10899,
12888 lfisht: 10620,
12889 lfloor: 8970,
12890 lharul: 10602,
12891 llhard: 10603,
12892 lmidot: 320,
12893 lmoust: 9136,
12894 loplus: 10797,
12895 lowast: 8727,
12896 lowbar: 95,
12897 lparlt: 10643,
12898 lrhard: 10605,
12899 lsaquo: 8249,
12900 lsquor: 8218,
12901 lstrok: 322,
12902 lthree: 8907,
12903 ltimes: 8905,
12904 ltlarr: 10614,
12905 ltrPar: 10646,
12906 mapsto: 8614,
12907 marker: 9646,
12908 mcomma: 10793,
12909 midast: 42,
12910 midcir: 10992,
12911 middot: 183,
12912 minusb: 8863,
12913 minusd: 8760,
12914 mnplus: 8723,
12915 models: 8871,
12916 mstpos: 8766,
12917 nVDash: 8879,
12918 nVdash: 8878,
12919 nacute: 324,
12920 ncaron: 328,
12921 ncedil: 326,
12922 nearhk: 10532,
12923 nequiv: 8802,
12924 nesear: 10536,
12925 nexist: 8708,
12926 nltrie: 8940,
12927 nprcue: 8928,
12928 nrtrie: 8941,
12929 nsccue: 8929,
12930 nsimeq: 8772,
12931 ntilde: 241,
12932 numero: 8470,
12933 nvDash: 8877,
12934 nvHarr: 10500,
12935 nvdash: 8876,
12936 nvlArr: 10498,
12937 nvrArr: 10499,
12938 nwarhk: 10531,
12939 nwnear: 10535,
12940 oacute: 243,
12941 odblac: 337,
12942 odsold: 10684,
12943 ograve: 242,
12944 ominus: 8854,
12945 origof: 8886,
12946 oslash: 248,
12947 otilde: 245,
12948 otimes: 8855,
12949 parsim: 10995,
12950 percnt: 37,
12951 period: 46,
12952 permil: 8240,
12953 phmmat: 8499,
12954 planck: 8463,
12955 plankv: 8463,
12956 plusdo: 8724,
12957 plusdu: 10789,
12958 plusmn: 177,
12959 preceq: 10927,
12960 primes: 8473,
12961 prnsim: 8936,
12962 propto: 8733,
12963 prurel: 8880,
12964 puncsp: 8200,
12965 qprime: 8279,
12966 rAtail: 10524,
12967 racute: 341,
12968 rangle: 10217,
12969 rarrap: 10613,
12970 rarrfs: 10526,
12971 rarrhk: 8618,
12972 rarrlp: 8620,
12973 rarrpl: 10565,
12974 rarrtl: 8611,
12975 ratail: 10522,
12976 rbrace: 125,
12977 rbrack: 93,
12978 rcaron: 345,
12979 rcedil: 343,
12980 rdquor: 8221,
12981 rfisht: 10621,
12982 rfloor: 8971,
12983 rharul: 10604,
12984 rmoust: 9137,
12985 roplus: 10798,
12986 rpargt: 10644,
12987 rsaquo: 8250,
12988 rsquor: 8217,
12989 rthree: 8908,
12990 rtimes: 8906,
12991 sacute: 347,
12992 scaron: 353,
12993 scedil: 351,
12994 scnsim: 8937,
12995 searhk: 10533,
12996 seswar: 10537,
12997 sfrown: 8994,
12998 shchcy: 1097,
12999 sigmaf: 962,
13000 sigmav: 962,
13001 simdot: 10858,
13002 smashp: 10803,
13003 softcy: 1100,
13004 solbar: 9023,
13005 spades: 9824,
13006 sqsube: 8849,
13007 sqsupe: 8850,
13008 square: 9633,
13009 squarf: 9642,
13010 ssetmn: 8726,
13011 ssmile: 8995,
13012 sstarf: 8902,
13013 subdot: 10941,
13014 subset: 8834,
13015 subsim: 10951,
13016 subsub: 10965,
13017 subsup: 10963,
13018 succeq: 10928,
13019 supdot: 10942,
13020 supset: 8835,
13021 supsim: 10952,
13022 supsub: 10964,
13023 supsup: 10966,
13024 swarhk: 10534,
13025 swnwar: 10538,
13026 target: 8982,
13027 tcaron: 357,
13028 tcedil: 355,
13029 telrec: 8981,
13030 there4: 8756,
13031 thetav: 977,
13032 thinsp: 8201,
13033 thksim: 8764,
13034 timesb: 8864,
13035 timesd: 10800,
13036 topbot: 9014,
13037 topcir: 10993,
13038 tprime: 8244,
13039 tridot: 9708,
13040 tstrok: 359,
13041 uacute: 250,
13042 ubreve: 365,
13043 udblac: 369,
13044 ufisht: 10622,
13045 ugrave: 249,
13046 ulcorn: 8988,
13047 ulcrop: 8975,
13048 urcorn: 8989,
13049 urcrop: 8974,
13050 utilde: 361,
13051 vangrt: 10652,
13052 varphi: 966,
13053 varrho: 1009,
13054 veebar: 8891,
13055 vellip: 8942,
13056 verbar: 124,
13057 wedbar: 10847,
13058 wedgeq: 8793,
13059 weierp: 8472,
13060 wreath: 8768,
13061 xoplus: 10753,
13062 xotime: 10754,
13063 xsqcup: 10758,
13064 xuplus: 10756,
13065 xwedge: 8896,
13066 yacute: 253,
13067 zacute: 378,
13068 zcaron: 382,
13069 zeetrf: 8488,
13070 AElig: 198,
13071 Acirc: 194,
13072 Alpha: 913,
13073 Amacr: 256,
13074 Aogon: 260,
13075 Aring: 197,
13076 Breve: 728,
13077 Ccirc: 264,
13078 Colon: 8759,
13079 Cross: 10799,
13080 Dashv: 10980,
13081 Delta: 916,
13082 Ecirc: 202,
13083 Emacr: 274,
13084 Eogon: 280,
13085 Equal: 10869,
13086 Gamma: 915,
13087 Gcirc: 284,
13088 Hacek: 711,
13089 Hcirc: 292,
13090 IJlig: 306,
13091 Icirc: 206,
13092 Imacr: 298,
13093 Iogon: 302,
13094 Iukcy: 1030,
13095 Jcirc: 308,
13096 Jukcy: 1028,
13097 Kappa: 922,
13098 OElig: 338,
13099 Ocirc: 212,
13100 Omacr: 332,
13101 Omega: 937,
13102 Prime: 8243,
13103 RBarr: 10512,
13104 Scirc: 348,
13105 Sigma: 931,
13106 THORN: 222,
13107 TRADE: 8482,
13108 TSHcy: 1035,
13109 Theta: 920,
13110 Tilde: 8764,
13111 Ubrcy: 1038,
13112 Ucirc: 219,
13113 Umacr: 362,
13114 Union: 8899,
13115 Uogon: 370,
13116 UpTee: 8869,
13117 Uring: 366,
13118 VDash: 8875,
13119 Vdash: 8873,
13120 Wcirc: 372,
13121 Wedge: 8896,
13122 Ycirc: 374,
13123 acirc: 226,
13124 acute: 180,
13125 aelig: 230,
13126 aleph: 8501,
13127 alpha: 945,
13128 amacr: 257,
13129 amalg: 10815,
13130 angle: 8736,
13131 angrt: 8735,
13132 angst: 8491,
13133 aogon: 261,
13134 aring: 229,
13135 asymp: 8776,
13136 awint: 10769,
13137 bcong: 8780,
13138 bdquo: 8222,
13139 bepsi: 1014,
13140 blank: 9251,
13141 blk12: 9618,
13142 blk14: 9617,
13143 blk34: 9619,
13144 block: 9608,
13145 boxDL: 9559,
13146 boxDR: 9556,
13147 boxDl: 9558,
13148 boxDr: 9555,
13149 boxHD: 9574,
13150 boxHU: 9577,
13151 boxHd: 9572,
13152 boxHu: 9575,
13153 boxUL: 9565,
13154 boxUR: 9562,
13155 boxUl: 9564,
13156 boxUr: 9561,
13157 boxVH: 9580,
13158 boxVL: 9571,
13159 boxVR: 9568,
13160 boxVh: 9579,
13161 boxVl: 9570,
13162 boxVr: 9567,
13163 boxdL: 9557,
13164 boxdR: 9554,
13165 boxdl: 9488,
13166 boxdr: 9484,
13167 boxhD: 9573,
13168 boxhU: 9576,
13169 boxhd: 9516,
13170 boxhu: 9524,
13171 boxuL: 9563,
13172 boxuR: 9560,
13173 boxul: 9496,
13174 boxur: 9492,
13175 boxvH: 9578,
13176 boxvL: 9569,
13177 boxvR: 9566,
13178 boxvh: 9532,
13179 boxvl: 9508,
13180 boxvr: 9500,
13181 breve: 728,
13182 bsemi: 8271,
13183 bsime: 8909,
13184 bsolb: 10693,
13185 bumpE: 10926,
13186 bumpe: 8783,
13187 caret: 8257,
13188 caron: 711,
13189 ccaps: 10829,
13190 ccirc: 265,
13191 ccups: 10828,
13192 cedil: 184,
13193 check: 10003,
13194 clubs: 9827,
13195 colon: 58,
13196 comma: 44,
13197 crarr: 8629,
13198 cross: 10007,
13199 csube: 10961,
13200 csupe: 10962,
13201 ctdot: 8943,
13202 cuepr: 8926,
13203 cuesc: 8927,
13204 cupor: 10821,
13205 cuvee: 8910,
13206 cuwed: 8911,
13207 cwint: 8753,
13208 dashv: 8867,
13209 dblac: 733,
13210 ddarr: 8650,
13211 delta: 948,
13212 dharl: 8643,
13213 dharr: 8642,
13214 diams: 9830,
13215 disin: 8946,
13216 doteq: 8784,
13217 dtdot: 8945,
13218 dtrif: 9662,
13219 duarr: 8693,
13220 duhar: 10607,
13221 eDDot: 10871,
13222 ecirc: 234,
13223 efDot: 8786,
13224 emacr: 275,
13225 empty: 8709,
13226 eogon: 281,
13227 eplus: 10865,
13228 epsiv: 949,
13229 eqsim: 8770,
13230 equiv: 8801,
13231 erDot: 8787,
13232 erarr: 10609,
13233 esdot: 8784,
13234 exist: 8707,
13235 fflig: 64256,
13236 filig: 64257,
13237 fllig: 64258,
13238 fltns: 9649,
13239 forkv: 10969,
13240 frasl: 8260,
13241 frown: 8994,
13242 gamma: 947,
13243 gcirc: 285,
13244 gescc: 10921,
13245 gimel: 8503,
13246 gneqq: 8809,
13247 gnsim: 8935,
13248 grave: 96,
13249 gsime: 10894,
13250 gsiml: 10896,
13251 gtcir: 10874,
13252 gtdot: 8919,
13253 harrw: 8621,
13254 hcirc: 293,
13255 hoarr: 8703,
13256 icirc: 238,
13257 iexcl: 161,
13258 iiint: 8749,
13259 iiota: 8489,
13260 ijlig: 307,
13261 imacr: 299,
13262 image: 8465,
13263 imath: 305,
13264 imped: 437,
13265 infin: 8734,
13266 iogon: 303,
13267 iprod: 10812,
13268 isinE: 8953,
13269 isins: 8948,
13270 isinv: 8712,
13271 iukcy: 1110,
13272 jcirc: 309,
13273 jmath: 567,
13274 jukcy: 1108,
13275 kappa: 954,
13276 lAarr: 8666,
13277 lBarr: 10510,
13278 langd: 10641,
13279 laquo: 171,
13280 larrb: 8676,
13281 lbarr: 10508,
13282 lbbrk: 10098,
13283 lbrke: 10635,
13284 lceil: 8968,
13285 ldquo: 8220,
13286 lescc: 10920,
13287 lhard: 8637,
13288 lharu: 8636,
13289 lhblk: 9604,
13290 llarr: 8647,
13291 lltri: 9722,
13292 lneqq: 8808,
13293 lnsim: 8934,
13294 loang: 10220,
13295 loarr: 8701,
13296 lobrk: 10214,
13297 lopar: 10629,
13298 lrarr: 8646,
13299 lrhar: 8651,
13300 lrtri: 8895,
13301 lsime: 10893,
13302 lsimg: 10895,
13303 lsquo: 8216,
13304 ltcir: 10873,
13305 ltdot: 8918,
13306 ltrie: 8884,
13307 ltrif: 9666,
13308 mDDot: 8762,
13309 mdash: 8212,
13310 micro: 181,
13311 minus: 8722,
13312 mumap: 8888,
13313 nabla: 8711,
13314 napos: 329,
13315 natur: 9838,
13316 ncong: 8775,
13317 ndash: 8211,
13318 neArr: 8663,
13319 nearr: 8599,
13320 ngsim: 8821,
13321 nhArr: 8654,
13322 nharr: 8622,
13323 nhpar: 10994,
13324 nlArr: 8653,
13325 nlarr: 8602,
13326 nless: 8814,
13327 nlsim: 8820,
13328 nltri: 8938,
13329 notin: 8713,
13330 notni: 8716,
13331 nprec: 8832,
13332 nrArr: 8655,
13333 nrarr: 8603,
13334 nrtri: 8939,
13335 nsime: 8772,
13336 nsmid: 8740,
13337 nspar: 8742,
13338 nsube: 8840,
13339 nsucc: 8833,
13340 nsupe: 8841,
13341 numsp: 8199,
13342 nwArr: 8662,
13343 nwarr: 8598,
13344 ocirc: 244,
13345 odash: 8861,
13346 oelig: 339,
13347 ofcir: 10687,
13348 ohbar: 10677,
13349 olarr: 8634,
13350 olcir: 10686,
13351 oline: 8254,
13352 omacr: 333,
13353 omega: 969,
13354 operp: 10681,
13355 oplus: 8853,
13356 orarr: 8635,
13357 order: 8500,
13358 ovbar: 9021,
13359 parsl: 11005,
13360 phone: 9742,
13361 plusb: 8862,
13362 pluse: 10866,
13363 pound: 163,
13364 prcue: 8828,
13365 prime: 8242,
13366 prnap: 10937,
13367 prsim: 8830,
13368 quest: 63,
13369 rAarr: 8667,
13370 rBarr: 10511,
13371 radic: 8730,
13372 rangd: 10642,
13373 range: 10661,
13374 raquo: 187,
13375 rarrb: 8677,
13376 rarrc: 10547,
13377 rarrw: 8605,
13378 ratio: 8758,
13379 rbarr: 10509,
13380 rbbrk: 10099,
13381 rbrke: 10636,
13382 rceil: 8969,
13383 rdquo: 8221,
13384 reals: 8477,
13385 rhard: 8641,
13386 rharu: 8640,
13387 rlarr: 8644,
13388 rlhar: 8652,
13389 rnmid: 10990,
13390 roang: 10221,
13391 roarr: 8702,
13392 robrk: 10215,
13393 ropar: 10630,
13394 rrarr: 8649,
13395 rsquo: 8217,
13396 rtrie: 8885,
13397 rtrif: 9656,
13398 sbquo: 8218,
13399 sccue: 8829,
13400 scirc: 349,
13401 scnap: 10938,
13402 scsim: 8831,
13403 sdotb: 8865,
13404 sdote: 10854,
13405 seArr: 8664,
13406 searr: 8600,
13407 setmn: 8726,
13408 sharp: 9839,
13409 sigma: 963,
13410 simeq: 8771,
13411 simgE: 10912,
13412 simlE: 10911,
13413 simne: 8774,
13414 slarr: 8592,
13415 smile: 8995,
13416 sqcap: 8851,
13417 sqcup: 8852,
13418 sqsub: 8847,
13419 sqsup: 8848,
13420 srarr: 8594,
13421 starf: 9733,
13422 strns: 175,
13423 subnE: 10955,
13424 subne: 8842,
13425 supnE: 10956,
13426 supne: 8843,
13427 swArr: 8665,
13428 swarr: 8601,
13429 szlig: 223,
13430 theta: 952,
13431 thkap: 8776,
13432 thorn: 254,
13433 tilde: 732,
13434 times: 215,
13435 trade: 8482,
13436 trisb: 10701,
13437 tshcy: 1115,
13438 twixt: 8812,
13439 ubrcy: 1118,
13440 ucirc: 251,
13441 udarr: 8645,
13442 udhar: 10606,
13443 uharl: 8639,
13444 uharr: 8638,
13445 uhblk: 9600,
13446 ultri: 9720,
13447 umacr: 363,
13448 uogon: 371,
13449 uplus: 8846,
13450 upsih: 978,
13451 uring: 367,
13452 urtri: 9721,
13453 utdot: 8944,
13454 utrif: 9652,
13455 uuarr: 8648,
13456 vBarv: 10985,
13457 vDash: 8872,
13458 varpi: 982,
13459 vdash: 8866,
13460 veeeq: 8794,
13461 vltri: 8882,
13462 vprop: 8733,
13463 vrtri: 8883,
13464 wcirc: 373,
13465 wedge: 8743,
13466 xcirc: 9711,
13467 xdtri: 9661,
13468 xhArr: 10234,
13469 xharr: 10231,
13470 xlArr: 10232,
13471 xlarr: 10229,
13472 xodot: 10752,
13473 xrArr: 10233,
13474 xrarr: 10230,
13475 xutri: 9651,
13476 ycirc: 375,
13477 Aopf: 120120,
13478 Ascr: 119964,
13479 Auml: 196,
13480 Barv: 10983,
13481 Beta: 914,
13482 Bopf: 120121,
13483 Bscr: 8492,
13484 CHcy: 1063,
13485 COPY: 169,
13486 Cdot: 266,
13487 Copf: 8450,
13488 Cscr: 119966,
13489 DJcy: 1026,
13490 DScy: 1029,
13491 DZcy: 1039,
13492 Darr: 8609,
13493 Dopf: 120123,
13494 Dscr: 119967,
13495 Edot: 278,
13496 Eopf: 120124,
13497 Escr: 8496,
13498 Esim: 10867,
13499 Euml: 203,
13500 Fopf: 120125,
13501 Fscr: 8497,
13502 GJcy: 1027,
13503 Gdot: 288,
13504 Gopf: 120126,
13505 Gscr: 119970,
13506 Hopf: 8461,
13507 Hscr: 8459,
13508 IEcy: 1045,
13509 IOcy: 1025,
13510 Idot: 304,
13511 Iopf: 120128,
13512 Iota: 921,
13513 Iscr: 8464,
13514 Iuml: 207,
13515 Jopf: 120129,
13516 Jscr: 119973,
13517 KHcy: 1061,
13518 KJcy: 1036,
13519 Kopf: 120130,
13520 Kscr: 119974,
13521 LJcy: 1033,
13522 Lang: 10218,
13523 Larr: 8606,
13524 Lopf: 120131,
13525 Lscr: 8466,
13526 Mopf: 120132,
13527 Mscr: 8499,
13528 NJcy: 1034,
13529 Nopf: 8469,
13530 Nscr: 119977,
13531 Oopf: 120134,
13532 Oscr: 119978,
13533 Ouml: 214,
13534 Popf: 8473,
13535 Pscr: 119979,
13536 QUOT: 34,
13537 Qopf: 8474,
13538 Qscr: 119980,
13539 Rang: 10219,
13540 Rarr: 8608,
13541 Ropf: 8477,
13542 Rscr: 8475,
13543 SHcy: 1064,
13544 Sopf: 120138,
13545 Sqrt: 8730,
13546 Sscr: 119982,
13547 Star: 8902,
13548 TScy: 1062,
13549 Topf: 120139,
13550 Tscr: 119983,
13551 Uarr: 8607,
13552 Uopf: 120140,
13553 Upsi: 978,
13554 Uscr: 119984,
13555 Uuml: 220,
13556 Vbar: 10987,
13557 Vert: 8214,
13558 Vopf: 120141,
13559 Vscr: 119985,
13560 Wopf: 120142,
13561 Wscr: 119986,
13562 Xopf: 120143,
13563 Xscr: 119987,
13564 YAcy: 1071,
13565 YIcy: 1031,
13566 YUcy: 1070,
13567 Yopf: 120144,
13568 Yscr: 119988,
13569 Yuml: 376,
13570 ZHcy: 1046,
13571 Zdot: 379,
13572 Zeta: 918,
13573 Zopf: 8484,
13574 Zscr: 119989,
13575 andd: 10844,
13576 andv: 10842,
13577 ange: 10660,
13578 aopf: 120146,
13579 apid: 8779,
13580 apos: 39,
13581 ascr: 119990,
13582 auml: 228,
13583 bNot: 10989,
13584 bbrk: 9141,
13585 beta: 946,
13586 beth: 8502,
13587 bnot: 8976,
13588 bopf: 120147,
13589 boxH: 9552,
13590 boxV: 9553,
13591 boxh: 9472,
13592 boxv: 9474,
13593 bscr: 119991,
13594 bsim: 8765,
13595 bsol: 92,
13596 bull: 8226,
13597 bump: 8782,
13598 cdot: 267,
13599 cent: 162,
13600 chcy: 1095,
13601 cirE: 10691,
13602 circ: 710,
13603 cire: 8791,
13604 comp: 8705,
13605 cong: 8773,
13606 copf: 120148,
13607 copy: 169,
13608 cscr: 119992,
13609 csub: 10959,
13610 csup: 10960,
13611 dArr: 8659,
13612 dHar: 10597,
13613 darr: 8595,
13614 dash: 8208,
13615 diam: 8900,
13616 djcy: 1106,
13617 dopf: 120149,
13618 dscr: 119993,
13619 dscy: 1109,
13620 dsol: 10742,
13621 dtri: 9663,
13622 dzcy: 1119,
13623 eDot: 8785,
13624 ecir: 8790,
13625 edot: 279,
13626 emsp: 8195,
13627 ensp: 8194,
13628 eopf: 120150,
13629 epar: 8917,
13630 epsi: 1013,
13631 escr: 8495,
13632 esim: 8770,
13633 euml: 235,
13634 euro: 8364,
13635 excl: 33,
13636 flat: 9837,
13637 fnof: 402,
13638 fopf: 120151,
13639 fork: 8916,
13640 fscr: 119995,
13641 gdot: 289,
13642 geqq: 8807,
13643 gjcy: 1107,
13644 gnap: 10890,
13645 gneq: 10888,
13646 gopf: 120152,
13647 gscr: 8458,
13648 gsim: 8819,
13649 gtcc: 10919,
13650 hArr: 8660,
13651 half: 189,
13652 harr: 8596,
13653 hbar: 8463,
13654 hopf: 120153,
13655 hscr: 119997,
13656 iecy: 1077,
13657 imof: 8887,
13658 iocy: 1105,
13659 iopf: 120154,
13660 iota: 953,
13661 iscr: 119998,
13662 isin: 8712,
13663 iuml: 239,
13664 jopf: 120155,
13665 jscr: 119999,
13666 khcy: 1093,
13667 kjcy: 1116,
13668 kopf: 120156,
13669 kscr: 120000,
13670 lArr: 8656,
13671 lHar: 10594,
13672 lang: 10216,
13673 larr: 8592,
13674 late: 10925,
13675 lcub: 123,
13676 ldca: 10550,
13677 ldsh: 8626,
13678 leqq: 8806,
13679 ljcy: 1113,
13680 lnap: 10889,
13681 lneq: 10887,
13682 lopf: 120157,
13683 lozf: 10731,
13684 lpar: 40,
13685 lscr: 120001,
13686 lsim: 8818,
13687 lsqb: 91,
13688 ltcc: 10918,
13689 ltri: 9667,
13690 macr: 175,
13691 male: 9794,
13692 malt: 10016,
13693 mlcp: 10971,
13694 mldr: 8230,
13695 mopf: 120158,
13696 mscr: 120002,
13697 nbsp: 160,
13698 ncap: 10819,
13699 ncup: 10818,
13700 ngeq: 8817,
13701 ngtr: 8815,
13702 nisd: 8954,
13703 njcy: 1114,
13704 nldr: 8229,
13705 nleq: 8816,
13706 nmid: 8740,
13707 nopf: 120159,
13708 npar: 8742,
13709 nscr: 120003,
13710 nsim: 8769,
13711 nsub: 8836,
13712 nsup: 8837,
13713 ntgl: 8825,
13714 ntlg: 8824,
13715 oast: 8859,
13716 ocir: 8858,
13717 odiv: 10808,
13718 odot: 8857,
13719 ogon: 731,
13720 oint: 8750,
13721 omid: 10678,
13722 oopf: 120160,
13723 opar: 10679,
13724 ordf: 170,
13725 ordm: 186,
13726 oror: 10838,
13727 oscr: 8500,
13728 osol: 8856,
13729 ouml: 246,
13730 para: 182,
13731 part: 8706,
13732 perp: 8869,
13733 phiv: 966,
13734 plus: 43,
13735 popf: 120161,
13736 prap: 10935,
13737 prec: 8826,
13738 prnE: 10933,
13739 prod: 8719,
13740 prop: 8733,
13741 pscr: 120005,
13742 qint: 10764,
13743 qopf: 120162,
13744 qscr: 120006,
13745 quot: 34,
13746 rArr: 8658,
13747 rHar: 10596,
13748 race: 10714,
13749 rang: 10217,
13750 rarr: 8594,
13751 rcub: 125,
13752 rdca: 10551,
13753 rdsh: 8627,
13754 real: 8476,
13755 rect: 9645,
13756 rhov: 1009,
13757 ring: 730,
13758 ropf: 120163,
13759 rpar: 41,
13760 rscr: 120007,
13761 rsqb: 93,
13762 rtri: 9657,
13763 scap: 10936,
13764 scnE: 10934,
13765 sdot: 8901,
13766 sect: 167,
13767 semi: 59,
13768 sext: 10038,
13769 shcy: 1096,
13770 sime: 8771,
13771 simg: 10910,
13772 siml: 10909,
13773 smid: 8739,
13774 smte: 10924,
13775 solb: 10692,
13776 sopf: 120164,
13777 spar: 8741,
13778 squf: 9642,
13779 sscr: 120008,
13780 star: 9734,
13781 subE: 10949,
13782 sube: 8838,
13783 succ: 8827,
13784 sung: 9834,
13785 sup1: 185,
13786 sup2: 178,
13787 sup3: 179,
13788 supE: 10950,
13789 supe: 8839,
13790 tbrk: 9140,
13791 tdot: 8411,
13792 tint: 8749,
13793 toea: 10536,
13794 topf: 120165,
13795 tosa: 10537,
13796 trie: 8796,
13797 tscr: 120009,
13798 tscy: 1094,
13799 uArr: 8657,
13800 uHar: 10595,
13801 uarr: 8593,
13802 uopf: 120166,
13803 upsi: 965,
13804 uscr: 120010,
13805 utri: 9653,
13806 uuml: 252,
13807 vArr: 8661,
13808 vBar: 10984,
13809 varr: 8597,
13810 vert: 124,
13811 vopf: 120167,
13812 vscr: 120011,
13813 wopf: 120168,
13814 wscr: 120012,
13815 xcap: 8898,
13816 xcup: 8899,
13817 xmap: 10236,
13818 xnis: 8955,
13819 xopf: 120169,
13820 xscr: 120013,
13821 xvee: 8897,
13822 yacy: 1103,
13823 yicy: 1111,
13824 yopf: 120170,
13825 yscr: 120014,
13826 yucy: 1102,
13827 yuml: 255,
13828 zdot: 380,
13829 zeta: 950,
13830 zhcy: 1078,
13831 zopf: 120171,
13832 zscr: 120015,
13833 zwnj: 8204,
13834 AMP: 38,
13835 Acy: 1040,
13836 Afr: 120068,
13837 And: 10835,
13838 Bcy: 1041,
13839 Bfr: 120069,
13840 Cap: 8914,
13841 Cfr: 8493,
13842 Chi: 935,
13843 Cup: 8915,
13844 Dcy: 1044,
13845 Del: 8711,
13846 Dfr: 120071,
13847 Dot: 168,
13848 ENG: 330,
13849 ETH: 208,
13850 Ecy: 1069,
13851 Efr: 120072,
13852 Eta: 919,
13853 Fcy: 1060,
13854 Ffr: 120073,
13855 Gcy: 1043,
13856 Gfr: 120074,
13857 Hat: 94,
13858 Hfr: 8460,
13859 Icy: 1048,
13860 Ifr: 8465,
13861 Int: 8748,
13862 Jcy: 1049,
13863 Jfr: 120077,
13864 Kcy: 1050,
13865 Kfr: 120078,
13866 Lcy: 1051,
13867 Lfr: 120079,
13868 Lsh: 8624,
13869 Map: 10501,
13870 Mcy: 1052,
13871 Mfr: 120080,
13872 Ncy: 1053,
13873 Nfr: 120081,
13874 Not: 10988,
13875 Ocy: 1054,
13876 Ofr: 120082,
13877 Pcy: 1055,
13878 Pfr: 120083,
13879 Phi: 934,
13880 Psi: 936,
13881 Qfr: 120084,
13882 REG: 174,
13883 Rcy: 1056,
13884 Rfr: 8476,
13885 Rho: 929,
13886 Rsh: 8625,
13887 Scy: 1057,
13888 Sfr: 120086,
13889 Sub: 8912,
13890 Sum: 8721,
13891 Sup: 8913,
13892 Tab: 9,
13893 Tau: 932,
13894 Tcy: 1058,
13895 Tfr: 120087,
13896 Ucy: 1059,
13897 Ufr: 120088,
13898 Vcy: 1042,
13899 Vee: 8897,
13900 Vfr: 120089,
13901 Wfr: 120090,
13902 Xfr: 120091,
13903 Ycy: 1067,
13904 Yfr: 120092,
13905 Zcy: 1047,
13906 Zfr: 8488,
13907 acd: 8767,
13908 acy: 1072,
13909 afr: 120094,
13910 amp: 38,
13911 and: 8743,
13912 ang: 8736,
13913 apE: 10864,
13914 ape: 8778,
13915 ast: 42,
13916 bcy: 1073,
13917 bfr: 120095,
13918 bot: 8869,
13919 cap: 8745,
13920 cfr: 120096,
13921 chi: 967,
13922 cir: 9675,
13923 cup: 8746,
13924 dcy: 1076,
13925 deg: 176,
13926 dfr: 120097,
13927 die: 168,
13928 div: 247,
13929 dot: 729,
13930 ecy: 1101,
13931 efr: 120098,
13932 egs: 10902,
13933 ell: 8467,
13934 els: 10901,
13935 eng: 331,
13936 eta: 951,
13937 eth: 240,
13938 fcy: 1092,
13939 ffr: 120099,
13940 gEl: 10892,
13941 gap: 10886,
13942 gcy: 1075,
13943 gel: 8923,
13944 geq: 8805,
13945 ges: 10878,
13946 gfr: 120100,
13947 ggg: 8921,
13948 glE: 10898,
13949 gla: 10917,
13950 glj: 10916,
13951 gnE: 8809,
13952 gne: 10888,
13953 hfr: 120101,
13954 icy: 1080,
13955 iff: 8660,
13956 ifr: 120102,
13957 int: 8747,
13958 jcy: 1081,
13959 jfr: 120103,
13960 kcy: 1082,
13961 kfr: 120104,
13962 lEg: 10891,
13963 lap: 10885,
13964 lat: 10923,
13965 lcy: 1083,
13966 leg: 8922,
13967 leq: 8804,
13968 les: 10877,
13969 lfr: 120105,
13970 lgE: 10897,
13971 lnE: 8808,
13972 lne: 10887,
13973 loz: 9674,
13974 lrm: 8206,
13975 lsh: 8624,
13976 map: 8614,
13977 mcy: 1084,
13978 mfr: 120106,
13979 mho: 8487,
13980 mid: 8739,
13981 nap: 8777,
13982 ncy: 1085,
13983 nfr: 120107,
13984 nge: 8817,
13985 ngt: 8815,
13986 nis: 8956,
13987 niv: 8715,
13988 nle: 8816,
13989 nlt: 8814,
13990 not: 172,
13991 npr: 8832,
13992 nsc: 8833,
13993 num: 35,
13994 ocy: 1086,
13995 ofr: 120108,
13996 ogt: 10689,
13997 ohm: 8486,
13998 olt: 10688,
13999 ord: 10845,
14000 orv: 10843,
14001 par: 8741,
14002 pcy: 1087,
14003 pfr: 120109,
14004 phi: 966,
14005 piv: 982,
14006 prE: 10931,
14007 pre: 10927,
14008 psi: 968,
14009 qfr: 120110,
14010 rcy: 1088,
14011 reg: 174,
14012 rfr: 120111,
14013 rho: 961,
14014 rlm: 8207,
14015 rsh: 8625,
14016 scE: 10932,
14017 sce: 10928,
14018 scy: 1089,
14019 sfr: 120112,
14020 shy: 173,
14021 sim: 8764,
14022 smt: 10922,
14023 sol: 47,
14024 squ: 9633,
14025 sub: 8834,
14026 sum: 8721,
14027 sup: 8835,
14028 tau: 964,
14029 tcy: 1090,
14030 tfr: 120113,
14031 top: 8868,
14032 ucy: 1091,
14033 ufr: 120114,
14034 uml: 168,
14035 vcy: 1074,
14036 vee: 8744,
14037 vfr: 120115,
14038 wfr: 120116,
14039 xfr: 120117,
14040 ycy: 1099,
14041 yen: 165,
14042 yfr: 120118,
14043 zcy: 1079,
14044 zfr: 120119,
14045 zwj: 8205,
14046 DD: 8517,
14047 GT: 62,
14048 Gg: 8921,
14049 Gt: 8811,
14050 Im: 8465,
14051 LT: 60,
14052 Ll: 8920,
14053 Lt: 8810,
14054 Mu: 924,
14055 Nu: 925,
14056 Or: 10836,
14057 Pi: 928,
14058 Pr: 10939,
14059 Re: 8476,
14060 Sc: 10940,
14061 Xi: 926,
14062 ac: 8766,
14063 af: 8289,
14064 ap: 8776,
14065 dd: 8518,
14066 ee: 8519,
14067 eg: 10906,
14068 el: 10905,
14069 gE: 8807,
14070 ge: 8805,
14071 gg: 8811,
14072 gl: 8823,
14073 gt: 62,
14074 ic: 8291,
14075 ii: 8520,
14076 in: 8712,
14077 it: 8290,
14078 lE: 8806,
14079 le: 8804,
14080 lg: 8822,
14081 ll: 8810,
14082 lt: 60,
14083 mp: 8723,
14084 mu: 956,
14085 ne: 8800,
14086 ni: 8715,
14087 nu: 957,
14088 oS: 9416,
14089 or: 8744,
14090 pi: 960,
14091 pm: 177,
14092 pr: 8826,
14093 rx: 8478,
14094 sc: 8827,
14095 wp: 8472,
14096 wr: 8768,
14097 xi: 958,
14098 };
14099
14100 const windows_1252 = [
14101 8364,
14102 129,
14103 8218,
14104 402,
14105 8222,
14106 8230,
14107 8224,
14108 8225,
14109 710,
14110 8240,
14111 352,
14112 8249,
14113 338,
14114 141,
14115 381,
14116 143,
14117 144,
14118 8216,
14119 8217,
14120 8220,
14121 8221,
14122 8226,
14123 8211,
14124 8212,
14125 732,
14126 8482,
14127 353,
14128 8250,
14129 339,
14130 157,
14131 382,
14132 376,
14133 ];
14134 const entity_pattern = new RegExp(`&(#?(?:x[\\w\\d]+|\\d+|${Object.keys(entities).join('|')}))(?:;|\\b)`, 'g');
14135 function decode_character_references(html) {
14136 return html.replace(entity_pattern, (match, entity) => {
14137 let code;
14138 // Handle named entities
14139 if (entity[0] !== '#') {
14140 code = entities[entity];
14141 }
14142 else if (entity[1] === 'x') {
14143 code = parseInt(entity.substring(2), 16);
14144 }
14145 else {
14146 code = parseInt(entity.substring(1), 10);
14147 }
14148 if (!code) {
14149 return match;
14150 }
14151 return String.fromCodePoint(validate_code(code));
14152 });
14153 }
14154 const NUL = 0;
14155 // some code points are verboten. If we were inserting HTML, the browser would replace the illegal
14156 // code points with alternatives in some cases - since we're bypassing that mechanism, we need
14157 // to replace them ourselves
14158 //
14159 // Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
14160 function validate_code(code) {
14161 // line feed becomes generic whitespace
14162 if (code === 10) {
14163 return 32;
14164 }
14165 // ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
14166 if (code < 128) {
14167 return code;
14168 }
14169 // code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
14170 // to correct the mistake or we'll end up with missing € signs and so on
14171 if (code <= 159) {
14172 return windows_1252[code - 128];
14173 }
14174 // basic multilingual plane
14175 if (code < 55296) {
14176 return code;
14177 }
14178 // UTF-16 surrogate halves
14179 if (code <= 57343) {
14180 return NUL;
14181 }
14182 // rest of the basic multilingual plane
14183 if (code <= 65535) {
14184 return code;
14185 }
14186 // supplementary multilingual plane 0x10000 - 0x1ffff
14187 if (code >= 65536 && code <= 131071) {
14188 return code;
14189 }
14190 // supplementary ideographic plane 0x20000 - 0x2ffff
14191 if (code >= 131072 && code <= 196607) {
14192 return code;
14193 }
14194 return NUL;
14195 }
14196 // based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
14197 const disallowed_contents = new Map([
14198 ['li', new Set(['li'])],
14199 ['dt', new Set(['dt', 'dd'])],
14200 ['dd', new Set(['dt', 'dd'])],
14201 [
14202 'p',
14203 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(' ')),
14204 ],
14205 ['rt', new Set(['rt', 'rp'])],
14206 ['rp', new Set(['rt', 'rp'])],
14207 ['optgroup', new Set(['optgroup'])],
14208 ['option', new Set(['option', 'optgroup'])],
14209 ['thead', new Set(['tbody', 'tfoot'])],
14210 ['tbody', new Set(['tbody', 'tfoot'])],
14211 ['tfoot', new Set(['tbody'])],
14212 ['tr', new Set(['tr', 'tbody'])],
14213 ['td', new Set(['td', 'th', 'tr'])],
14214 ['th', new Set(['td', 'th', 'tr'])],
14215 ]);
14216 // can this be a child of the parent element, or does it implicitly
14217 // close it, like `<li>one<li>two`?
14218 function closing_tag_omitted(current, next) {
14219 if (disallowed_contents.has(current)) {
14220 if (!next || disallowed_contents.get(current).has(next)) {
14221 return true;
14222 }
14223 }
14224 return false;
14225 }
14226
14227 // Adapted from https://github.com/acornjs/acorn/blob/6584815dca7440e00de841d1dad152302fdd7ca5/src/tokenize.js
14228 // Reproduced under MIT License https://github.com/acornjs/acorn/blob/master/LICENSE
14229 function full_char_code_at(str, i) {
14230 const code = str.charCodeAt(i);
14231 if (code <= 0xd7ff || code >= 0xe000)
14232 return code;
14233 const next = str.charCodeAt(i + 1);
14234 return (code << 10) + next - 0x35fdc00;
14235 }
14236
14237 const globals = new Set([
14238 'alert',
14239 'Array',
14240 'Boolean',
14241 'clearInterval',
14242 'clearTimeout',
14243 'confirm',
14244 'console',
14245 'Date',
14246 'decodeURI',
14247 'decodeURIComponent',
14248 'document',
14249 'encodeURI',
14250 'encodeURIComponent',
14251 'Error',
14252 'EvalError',
14253 'Event',
14254 'fetch',
14255 'global',
14256 'globalThis',
14257 'history',
14258 'Infinity',
14259 'InternalError',
14260 'Intl',
14261 'isFinite',
14262 'isNaN',
14263 'JSON',
14264 'localStorage',
14265 'location',
14266 'Map',
14267 'Math',
14268 'NaN',
14269 'navigator',
14270 'Number',
14271 'Object',
14272 'parseFloat',
14273 'parseInt',
14274 'process',
14275 'Promise',
14276 'prompt',
14277 'RangeError',
14278 'ReferenceError',
14279 'RegExp',
14280 'sessionStorage',
14281 'Set',
14282 'setInterval',
14283 'setTimeout',
14284 'String',
14285 'SyntaxError',
14286 'TypeError',
14287 'undefined',
14288 'URIError',
14289 'URL',
14290 'window'
14291 ]);
14292 const reserved = new Set([
14293 'arguments',
14294 'await',
14295 'break',
14296 'case',
14297 'catch',
14298 'class',
14299 'const',
14300 'continue',
14301 'debugger',
14302 'default',
14303 'delete',
14304 'do',
14305 'else',
14306 'enum',
14307 'eval',
14308 'export',
14309 'extends',
14310 'false',
14311 'finally',
14312 'for',
14313 'function',
14314 'if',
14315 'implements',
14316 'import',
14317 'in',
14318 'instanceof',
14319 'interface',
14320 'let',
14321 'new',
14322 'null',
14323 'package',
14324 'private',
14325 'protected',
14326 'public',
14327 'return',
14328 'static',
14329 'super',
14330 'switch',
14331 'this',
14332 'throw',
14333 'true',
14334 'try',
14335 'typeof',
14336 'var',
14337 'void',
14338 'while',
14339 'with',
14340 'yield',
14341 ]);
14342 const void_element_names = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
14343 function is_void(name) {
14344 return void_element_names.test(name) || name.toLowerCase() === '!doctype';
14345 }
14346 function is_valid(str) {
14347 let i = 0;
14348 while (i < str.length) {
14349 const code = full_char_code_at(str, i);
14350 if (!(i === 0 ? isIdentifierStart : isIdentifierChar)(code, true))
14351 return false;
14352 i += code <= 0xffff ? 1 : 2;
14353 }
14354 return true;
14355 }
14356 function sanitize(name) {
14357 return name
14358 .replace(/[^a-zA-Z0-9_]+/g, '_')
14359 .replace(/^_/, '')
14360 .replace(/_$/, '')
14361 .replace(/^[0-9]/, '_$&');
14362 }
14363
14364 function fuzzymatch(name, names) {
14365 const set = new FuzzySet(names);
14366 const matches = set.get(name);
14367 return matches && matches[0] && matches[0][0] > 0.7 ? matches[0][1] : null;
14368 }
14369 // adapted from https://github.com/Glench/fuzzyset.js/blob/master/lib/fuzzyset.js
14370 // BSD Licensed
14371 const GRAM_SIZE_LOWER = 2;
14372 const GRAM_SIZE_UPPER = 3;
14373 // return an edit distance from 0 to 1
14374 function _distance(str1, str2) {
14375 if (str1 === null && str2 === null)
14376 throw 'Trying to compare two null values';
14377 if (str1 === null || str2 === null)
14378 return 0;
14379 str1 = String(str1);
14380 str2 = String(str2);
14381 const distance = levenshtein(str1, str2);
14382 if (str1.length > str2.length) {
14383 return 1 - distance / str1.length;
14384 }
14385 else {
14386 return 1 - distance / str2.length;
14387 }
14388 }
14389 // helper functions
14390 function levenshtein(str1, str2) {
14391 const current = [];
14392 let prev;
14393 let value;
14394 for (let i = 0; i <= str2.length; i++) {
14395 for (let j = 0; j <= str1.length; j++) {
14396 if (i && j) {
14397 if (str1.charAt(j - 1) === str2.charAt(i - 1)) {
14398 value = prev;
14399 }
14400 else {
14401 value = Math.min(current[j], current[j - 1], prev) + 1;
14402 }
14403 }
14404 else {
14405 value = i + j;
14406 }
14407 prev = current[j];
14408 current[j] = value;
14409 }
14410 }
14411 return current.pop();
14412 }
14413 const non_word_regex = /[^\w, ]+/;
14414 function iterate_grams(value, gram_size = 2) {
14415 const simplified = '-' + value.toLowerCase().replace(non_word_regex, '') + '-';
14416 const len_diff = gram_size - simplified.length;
14417 const results = [];
14418 if (len_diff > 0) {
14419 for (let i = 0; i < len_diff; ++i) {
14420 value += '-';
14421 }
14422 }
14423 for (let i = 0; i < simplified.length - gram_size + 1; ++i) {
14424 results.push(simplified.slice(i, i + gram_size));
14425 }
14426 return results;
14427 }
14428 function gram_counter(value, gram_size = 2) {
14429 // return an object where key=gram, value=number of occurrences
14430 const result = {};
14431 const grams = iterate_grams(value, gram_size);
14432 let i = 0;
14433 for (i; i < grams.length; ++i) {
14434 if (grams[i] in result) {
14435 result[grams[i]] += 1;
14436 }
14437 else {
14438 result[grams[i]] = 1;
14439 }
14440 }
14441 return result;
14442 }
14443 function sort_descending(a, b) {
14444 return b[0] - a[0];
14445 }
14446 class FuzzySet {
14447 constructor(arr) {
14448 this.exact_set = {};
14449 this.match_dict = {};
14450 this.items = {};
14451 // initialization
14452 for (let i = GRAM_SIZE_LOWER; i < GRAM_SIZE_UPPER + 1; ++i) {
14453 this.items[i] = [];
14454 }
14455 // add all the items to the set
14456 for (let i = 0; i < arr.length; ++i) {
14457 this.add(arr[i]);
14458 }
14459 }
14460 add(value) {
14461 const normalized_value = value.toLowerCase();
14462 if (normalized_value in this.exact_set) {
14463 return false;
14464 }
14465 let i = GRAM_SIZE_LOWER;
14466 for (i; i < GRAM_SIZE_UPPER + 1; ++i) {
14467 this._add(value, i);
14468 }
14469 }
14470 _add(value, gram_size) {
14471 const normalized_value = value.toLowerCase();
14472 const items = this.items[gram_size] || [];
14473 const index = items.length;
14474 items.push(0);
14475 const gram_counts = gram_counter(normalized_value, gram_size);
14476 let sum_of_square_gram_counts = 0;
14477 let gram;
14478 let gram_count;
14479 for (gram in gram_counts) {
14480 gram_count = gram_counts[gram];
14481 sum_of_square_gram_counts += Math.pow(gram_count, 2);
14482 if (gram in this.match_dict) {
14483 this.match_dict[gram].push([index, gram_count]);
14484 }
14485 else {
14486 this.match_dict[gram] = [[index, gram_count]];
14487 }
14488 }
14489 const vector_normal = Math.sqrt(sum_of_square_gram_counts);
14490 items[index] = [vector_normal, normalized_value];
14491 this.items[gram_size] = items;
14492 this.exact_set[normalized_value] = value;
14493 }
14494 get(value) {
14495 const normalized_value = value.toLowerCase();
14496 const result = this.exact_set[normalized_value];
14497 if (result) {
14498 return [[1, result]];
14499 }
14500 let results = [];
14501 // start with high gram size and if there are no results, go to lower gram sizes
14502 for (let gram_size = GRAM_SIZE_UPPER; gram_size >= GRAM_SIZE_LOWER; --gram_size) {
14503 results = this.__get(value, gram_size);
14504 if (results) {
14505 return results;
14506 }
14507 }
14508 return null;
14509 }
14510 __get(value, gram_size) {
14511 const normalized_value = value.toLowerCase();
14512 const matches = {};
14513 const gram_counts = gram_counter(normalized_value, gram_size);
14514 const items = this.items[gram_size];
14515 let sum_of_square_gram_counts = 0;
14516 let gram;
14517 let gram_count;
14518 let i;
14519 let index;
14520 let other_gram_count;
14521 for (gram in gram_counts) {
14522 gram_count = gram_counts[gram];
14523 sum_of_square_gram_counts += Math.pow(gram_count, 2);
14524 if (gram in this.match_dict) {
14525 for (i = 0; i < this.match_dict[gram].length; ++i) {
14526 index = this.match_dict[gram][i][0];
14527 other_gram_count = this.match_dict[gram][i][1];
14528 if (index in matches) {
14529 matches[index] += gram_count * other_gram_count;
14530 }
14531 else {
14532 matches[index] = gram_count * other_gram_count;
14533 }
14534 }
14535 }
14536 }
14537 const vector_normal = Math.sqrt(sum_of_square_gram_counts);
14538 let results = [];
14539 let match_score;
14540 // build a results list of [score, str]
14541 for (const match_index in matches) {
14542 match_score = matches[match_index];
14543 results.push([
14544 match_score / (vector_normal * items[match_index][0]),
14545 items[match_index][1],
14546 ]);
14547 }
14548 results.sort(sort_descending);
14549 let new_results = [];
14550 const end_index = Math.min(50, results.length);
14551 // truncate somewhat arbitrarily to 50
14552 for (let i = 0; i < end_index; ++i) {
14553 new_results.push([
14554 _distance(results[i][1], normalized_value),
14555 results[i][1],
14556 ]);
14557 }
14558 results = new_results;
14559 results.sort(sort_descending);
14560 new_results = [];
14561 for (let i = 0; i < results.length; ++i) {
14562 if (results[i][0] == results[0][0]) {
14563 new_results.push([results[i][0], this.exact_set[results[i][1]]]);
14564 }
14565 }
14566 return new_results;
14567 }
14568 }
14569
14570 function list$1(items, conjunction = 'or') {
14571 if (items.length === 1)
14572 return items[0];
14573 return `${items.slice(0, -1).join(', ')} ${conjunction} ${items[items.length - 1]}`;
14574 }
14575
14576 // eslint-disable-next-line no-useless-escape
14577 const valid_tag_name = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
14578 const meta_tags = new Map([
14579 ['svelte:head', 'Head'],
14580 ['svelte:options', 'Options'],
14581 ['svelte:window', 'Window'],
14582 ['svelte:body', 'Body']
14583 ]);
14584 const valid_meta_tags = Array.from(meta_tags.keys()).concat('svelte:self', 'svelte:component');
14585 const specials = new Map([
14586 [
14587 'script',
14588 {
14589 read: read_script,
14590 property: 'js',
14591 },
14592 ],
14593 [
14594 'style',
14595 {
14596 read: read_style,
14597 property: 'css',
14598 },
14599 ],
14600 ]);
14601 const SELF = /^svelte:self(?=[\s/>])/;
14602 const COMPONENT = /^svelte:component(?=[\s/>])/;
14603 function parent_is_head(stack) {
14604 let i = stack.length;
14605 while (i--) {
14606 const { type } = stack[i];
14607 if (type === 'Head')
14608 return true;
14609 if (type === 'Element' || type === 'InlineComponent')
14610 return false;
14611 }
14612 return false;
14613 }
14614 function tag(parser) {
14615 const start = parser.index++;
14616 let parent = parser.current();
14617 if (parser.eat('!--')) {
14618 const data = parser.read_until(/-->/);
14619 parser.eat('-->', true, 'comment was left open, expected -->');
14620 parser.current().children.push({
14621 start,
14622 end: parser.index,
14623 type: 'Comment',
14624 data,
14625 });
14626 return;
14627 }
14628 const is_closing_tag = parser.eat('/');
14629 const name = read_tag_name(parser);
14630 if (meta_tags.has(name)) {
14631 const slug = meta_tags.get(name).toLowerCase();
14632 if (is_closing_tag) {
14633 if ((name === 'svelte:window' || name === 'svelte:body') &&
14634 parser.current().children.length) {
14635 parser.error({
14636 code: `invalid-${slug}-content`,
14637 message: `<${name}> cannot have children`
14638 }, parser.current().children[0].start);
14639 }
14640 }
14641 else {
14642 if (name in parser.meta_tags) {
14643 parser.error({
14644 code: `duplicate-${slug}`,
14645 message: `A component can only have one <${name}> tag`
14646 }, start);
14647 }
14648 if (parser.stack.length > 1) {
14649 parser.error({
14650 code: `invalid-${slug}-placement`,
14651 message: `<${name}> tags cannot be inside elements or blocks`
14652 }, start);
14653 }
14654 parser.meta_tags[name] = true;
14655 }
14656 }
14657 const type = meta_tags.has(name)
14658 ? meta_tags.get(name)
14659 : (/[A-Z]/.test(name[0]) || name === 'svelte:self' || name === 'svelte:component') ? 'InlineComponent'
14660 : name === 'title' && parent_is_head(parser.stack) ? 'Title'
14661 : name === 'slot' && !parser.customElement ? 'Slot' : 'Element';
14662 const element = {
14663 start,
14664 end: null,
14665 type,
14666 name,
14667 attributes: [],
14668 children: [],
14669 };
14670 parser.allow_whitespace();
14671 if (is_closing_tag) {
14672 if (is_void(name)) {
14673 parser.error({
14674 code: `invalid-void-content`,
14675 message: `<${name}> is a void element and cannot have children, or a closing tag`
14676 }, start);
14677 }
14678 parser.eat('>', true);
14679 // close any elements that don't have their own closing tags, e.g. <div><p></div>
14680 while (parent.name !== name) {
14681 if (parent.type !== 'Element') {
14682 const message = parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name
14683 ? `</${name}> attempted to close <${name}> that was already automatically closed by <${parser.last_auto_closed_tag.reason}>`
14684 : `</${name}> attempted to close an element that was not open`;
14685 parser.error({
14686 code: `invalid-closing-tag`,
14687 message
14688 }, start);
14689 }
14690 parent.end = start;
14691 parser.stack.pop();
14692 parent = parser.current();
14693 }
14694 parent.end = parser.index;
14695 parser.stack.pop();
14696 if (parser.last_auto_closed_tag && parser.stack.length < parser.last_auto_closed_tag.depth) {
14697 parser.last_auto_closed_tag = null;
14698 }
14699 return;
14700 }
14701 else if (closing_tag_omitted(parent.name, name)) {
14702 parent.end = start;
14703 parser.stack.pop();
14704 parser.last_auto_closed_tag = {
14705 tag: parent.name,
14706 reason: name,
14707 depth: parser.stack.length,
14708 };
14709 }
14710 const unique_names = new Set();
14711 let attribute;
14712 while ((attribute = read_attribute(parser, unique_names))) {
14713 element.attributes.push(attribute);
14714 parser.allow_whitespace();
14715 }
14716 if (name === 'svelte:component') {
14717 const index = element.attributes.findIndex(attr => attr.type === 'Attribute' && attr.name === 'this');
14718 if (!~index) {
14719 parser.error({
14720 code: `missing-component-definition`,
14721 message: `<svelte:component> must have a 'this' attribute`
14722 }, start);
14723 }
14724 const definition = element.attributes.splice(index, 1)[0];
14725 if (definition.value === true || definition.value.length !== 1 || definition.value[0].type === 'Text') {
14726 parser.error({
14727 code: `invalid-component-definition`,
14728 message: `invalid component definition`
14729 }, definition.start);
14730 }
14731 element.expression = definition.value[0].expression;
14732 }
14733 // special cases – top-level <script> and <style>
14734 if (specials.has(name) && parser.stack.length === 1) {
14735 const special = specials.get(name);
14736 parser.eat('>', true);
14737 const content = special.read(parser, start, element.attributes);
14738 if (content)
14739 parser[special.property].push(content);
14740 return;
14741 }
14742 parser.current().children.push(element);
14743 const self_closing = parser.eat('/') || is_void(name);
14744 parser.eat('>', true);
14745 if (self_closing) {
14746 // don't push self-closing elements onto the stack
14747 element.end = parser.index;
14748 }
14749 else if (name === 'textarea') {
14750 // special case
14751 element.children = read_sequence(parser, () => parser.template.slice(parser.index, parser.index + 11) === '</textarea>');
14752 parser.read(/<\/textarea>/);
14753 element.end = parser.index;
14754 }
14755 else if (name === 'script') {
14756 // special case
14757 const start = parser.index;
14758 const data = parser.read_until(/<\/script>/);
14759 const end = parser.index;
14760 element.children.push({ start, end, type: 'Text', data });
14761 parser.eat('</script>', true);
14762 element.end = parser.index;
14763 }
14764 else if (name === 'style') {
14765 // special case
14766 const start = parser.index;
14767 const data = parser.read_until(/<\/style>/);
14768 const end = parser.index;
14769 element.children.push({ start, end, type: 'Text', data });
14770 parser.eat('</style>', true);
14771 }
14772 else {
14773 parser.stack.push(element);
14774 }
14775 }
14776 function read_tag_name(parser) {
14777 const start = parser.index;
14778 if (parser.read(SELF)) {
14779 // check we're inside a block, otherwise this
14780 // will cause infinite recursion
14781 let i = parser.stack.length;
14782 let legal = false;
14783 while (i--) {
14784 const fragment = parser.stack[i];
14785 if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock' || fragment.type === 'InlineComponent') {
14786 legal = true;
14787 break;
14788 }
14789 }
14790 if (!legal) {
14791 parser.error({
14792 code: `invalid-self-placement`,
14793 message: `<svelte:self> components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components`
14794 }, start);
14795 }
14796 return 'svelte:self';
14797 }
14798 if (parser.read(COMPONENT))
14799 return 'svelte:component';
14800 const name = parser.read_until(/(\s|\/|>)/);
14801 if (meta_tags.has(name))
14802 return name;
14803 if (name.startsWith('svelte:')) {
14804 const match = fuzzymatch(name.slice(7), valid_meta_tags);
14805 let message = `Valid <svelte:...> tag names are ${list$1(valid_meta_tags)}`;
14806 if (match)
14807 message += ` (did you mean '${match}'?)`;
14808 parser.error({
14809 code: 'invalid-tag-name',
14810 message
14811 }, start);
14812 }
14813 if (!valid_tag_name.test(name)) {
14814 parser.error({
14815 code: `invalid-tag-name`,
14816 message: `Expected valid tag name`
14817 }, start);
14818 }
14819 return name;
14820 }
14821 function read_attribute(parser, unique_names) {
14822 const start = parser.index;
14823 function check_unique(name) {
14824 if (unique_names.has(name)) {
14825 parser.error({
14826 code: `duplicate-attribute`,
14827 message: 'Attributes need to be unique'
14828 }, start);
14829 }
14830 unique_names.add(name);
14831 }
14832 if (parser.eat('{')) {
14833 parser.allow_whitespace();
14834 if (parser.eat('...')) {
14835 const expression = read_expression(parser);
14836 parser.allow_whitespace();
14837 parser.eat('}', true);
14838 return {
14839 start,
14840 end: parser.index,
14841 type: 'Spread',
14842 expression
14843 };
14844 }
14845 else {
14846 const value_start = parser.index;
14847 const name = parser.read_identifier();
14848 parser.allow_whitespace();
14849 parser.eat('}', true);
14850 check_unique(name);
14851 return {
14852 start,
14853 end: parser.index,
14854 type: 'Attribute',
14855 name,
14856 value: [{
14857 start: value_start,
14858 end: value_start + name.length,
14859 type: 'AttributeShorthand',
14860 expression: {
14861 start: value_start,
14862 end: value_start + name.length,
14863 type: 'Identifier',
14864 name
14865 }
14866 }]
14867 };
14868 }
14869 }
14870 // eslint-disable-next-line no-useless-escape
14871 const name = parser.read_until(/[\s=\/>"']/);
14872 if (!name)
14873 return null;
14874 let end = parser.index;
14875 parser.allow_whitespace();
14876 const colon_index = name.indexOf(':');
14877 const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index));
14878 let value = true;
14879 if (parser.eat('=')) {
14880 parser.allow_whitespace();
14881 value = read_attribute_value(parser);
14882 end = parser.index;
14883 }
14884 else if (parser.match_regex(/["']/)) {
14885 parser.error({
14886 code: `unexpected-token`,
14887 message: `Expected =`
14888 }, parser.index);
14889 }
14890 if (type) {
14891 const [directive_name, ...modifiers] = name.slice(colon_index + 1).split('|');
14892 if (type === 'Binding' && directive_name !== 'this') {
14893 check_unique(directive_name);
14894 }
14895 else if (type !== 'EventHandler') {
14896 check_unique(name);
14897 }
14898 if (type === 'Ref') {
14899 parser.error({
14900 code: `invalid-ref-directive`,
14901 message: `The ref directive is no longer supported — use \`bind:this={${directive_name}}\` instead`
14902 }, start);
14903 }
14904 if (value[0]) {
14905 if (value.length > 1 || value[0].type === 'Text') {
14906 parser.error({
14907 code: `invalid-directive-value`,
14908 message: `Directive value must be a JavaScript expression enclosed in curly braces`
14909 }, value[0].start);
14910 }
14911 }
14912 const directive = {
14913 start,
14914 end,
14915 type,
14916 name: directive_name,
14917 modifiers,
14918 expression: (value[0] && value[0].expression) || null
14919 };
14920 if (type === 'Transition') {
14921 const direction = name.slice(0, colon_index);
14922 directive.intro = direction === 'in' || direction === 'transition';
14923 directive.outro = direction === 'out' || direction === 'transition';
14924 }
14925 if (!directive.expression && (type === 'Binding' || type === 'Class')) {
14926 directive.expression = {
14927 start: directive.start + colon_index + 1,
14928 end: directive.end,
14929 type: 'Identifier',
14930 name: directive.name
14931 };
14932 }
14933 return directive;
14934 }
14935 check_unique(name);
14936 return {
14937 start,
14938 end,
14939 type: 'Attribute',
14940 name,
14941 value,
14942 };
14943 }
14944 function get_directive_type(name) {
14945 if (name === 'use')
14946 return 'Action';
14947 if (name === 'animate')
14948 return 'Animation';
14949 if (name === 'bind')
14950 return 'Binding';
14951 if (name === 'class')
14952 return 'Class';
14953 if (name === 'on')
14954 return 'EventHandler';
14955 if (name === 'let')
14956 return 'Let';
14957 if (name === 'ref')
14958 return 'Ref';
14959 if (name === 'in' || name === 'out' || name === 'transition')
14960 return 'Transition';
14961 }
14962 function read_attribute_value(parser) {
14963 const quote_mark = parser.eat(`'`) ? `'` : parser.eat(`"`) ? `"` : null;
14964 const regex = (quote_mark === `'` ? /'/ :
14965 quote_mark === `"` ? /"/ :
14966 /(\/>|[\s"'=<>`])/);
14967 const value = read_sequence(parser, () => !!parser.match_regex(regex));
14968 if (quote_mark)
14969 parser.index += 1;
14970 return value;
14971 }
14972 function read_sequence(parser, done) {
14973 let current_chunk = {
14974 start: parser.index,
14975 end: null,
14976 type: 'Text',
14977 raw: '',
14978 data: null
14979 };
14980 function flush() {
14981 if (current_chunk.raw) {
14982 current_chunk.data = decode_character_references(current_chunk.raw);
14983 current_chunk.end = parser.index;
14984 chunks.push(current_chunk);
14985 }
14986 }
14987 const chunks = [];
14988 while (parser.index < parser.template.length) {
14989 const index = parser.index;
14990 if (done()) {
14991 flush();
14992 return chunks;
14993 }
14994 else if (parser.eat('{')) {
14995 flush();
14996 parser.allow_whitespace();
14997 const expression = read_expression(parser);
14998 parser.allow_whitespace();
14999 parser.eat('}', true);
15000 chunks.push({
15001 start: index,
15002 end: parser.index,
15003 type: 'MustacheTag',
15004 expression,
15005 });
15006 current_chunk = {
15007 start: parser.index,
15008 end: null,
15009 type: 'Text',
15010 raw: '',
15011 data: null
15012 };
15013 }
15014 else {
15015 current_chunk.raw += parser.template[parser.index++];
15016 }
15017 }
15018 parser.error({
15019 code: `unexpected-eof`,
15020 message: `Unexpected end of input`
15021 });
15022 }
15023
15024 const SQUARE_BRACKET_OPEN = "[".charCodeAt(0);
15025 const SQUARE_BRACKET_CLOSE = "]".charCodeAt(0);
15026 const CURLY_BRACKET_OPEN = "{".charCodeAt(0);
15027 const CURLY_BRACKET_CLOSE = "}".charCodeAt(0);
15028 function is_bracket_open(code) {
15029 return code === SQUARE_BRACKET_OPEN || code === CURLY_BRACKET_OPEN;
15030 }
15031 function is_bracket_close(code) {
15032 return code === SQUARE_BRACKET_CLOSE || code === CURLY_BRACKET_CLOSE;
15033 }
15034 function is_bracket_pair(open, close) {
15035 return ((open === SQUARE_BRACKET_OPEN && close === SQUARE_BRACKET_CLOSE) ||
15036 (open === CURLY_BRACKET_OPEN && close === CURLY_BRACKET_CLOSE));
15037 }
15038 function get_bracket_close(open) {
15039 if (open === SQUARE_BRACKET_OPEN) {
15040 return SQUARE_BRACKET_CLOSE;
15041 }
15042 if (open === CURLY_BRACKET_OPEN) {
15043 return CURLY_BRACKET_CLOSE;
15044 }
15045 }
15046
15047 function read_context(parser) {
15048 const start = parser.index;
15049 let i = parser.index;
15050 const code = full_char_code_at(parser.template, i);
15051 if (isIdentifierStart(code, true)) {
15052 return {
15053 type: "Identifier",
15054 name: parser.read_identifier(),
15055 start,
15056 end: parser.index
15057 };
15058 }
15059 if (!is_bracket_open(code)) {
15060 parser.error({
15061 code: "unexpected-token",
15062 message: "Expected identifier or destructure pattern"
15063 });
15064 }
15065 const bracket_stack = [code];
15066 i += code <= 0xffff ? 1 : 2;
15067 while (i < parser.template.length) {
15068 const code = full_char_code_at(parser.template, i);
15069 if (is_bracket_open(code)) {
15070 bracket_stack.push(code);
15071 }
15072 else if (is_bracket_close(code)) {
15073 if (!is_bracket_pair(bracket_stack[bracket_stack.length - 1], code)) {
15074 parser.error({
15075 code: "unexpected-token",
15076 message: `Expected ${String.fromCharCode(get_bracket_close(bracket_stack[bracket_stack.length - 1]))}`
15077 });
15078 }
15079 bracket_stack.pop();
15080 if (bracket_stack.length === 0) {
15081 i += code <= 0xffff ? 1 : 2;
15082 break;
15083 }
15084 }
15085 i += code <= 0xffff ? 1 : 2;
15086 }
15087 parser.index = i;
15088 const pattern_string = parser.template.slice(start, i);
15089 try {
15090 // the length of the `space_with_newline` has to be start - 1
15091 // because we added a `(` in front of the pattern_string,
15092 // which shifted the entire string to right by 1
15093 // so we offset it by removing 1 character in the `space_with_newline`
15094 // to achieve that, we remove the 1st space encountered,
15095 // so it will not affect the `column` of the node
15096 let space_with_newline = parser.template.slice(0, start).replace(/[^\n]/g, ' ');
15097 const first_space = space_with_newline.indexOf(' ');
15098 space_with_newline = space_with_newline.slice(0, first_space) + space_with_newline.slice(first_space + 1);
15099 return parse_expression_at(`${space_with_newline}(${pattern_string} = 1)`, start - 1).left;
15100 }
15101 catch (error) {
15102 parser.acorn_error(error);
15103 }
15104 }
15105
15106 function trim_start(str) {
15107 let i = 0;
15108 while (whitespace.test(str[i]))
15109 i += 1;
15110 return str.slice(i);
15111 }
15112 function trim_end(str) {
15113 let i = str.length;
15114 while (whitespace.test(str[i - 1]))
15115 i -= 1;
15116 return str.slice(0, i);
15117 }
15118
15119 function to_string(node) {
15120 switch (node.type) {
15121 case 'IfBlock':
15122 return '{#if} block';
15123 case 'ThenBlock':
15124 return '{:then} block';
15125 case 'ElseBlock':
15126 return '{:else} block';
15127 case 'PendingBlock':
15128 case 'AwaitBlock':
15129 return '{#await} block';
15130 case 'CatchBlock':
15131 return '{:catch} block';
15132 case 'EachBlock':
15133 return '{#each} block';
15134 case 'RawMustacheTag':
15135 return '{@html} block';
15136 case 'DebugTag':
15137 return '{@debug} block';
15138 case 'Element':
15139 case 'InlineComponent':
15140 case 'Slot':
15141 case 'Title':
15142 return `<${node.name}> tag`;
15143 default:
15144 return node.type;
15145 }
15146 }
15147
15148 function trim_whitespace(block, trim_before, trim_after) {
15149 if (!block.children || block.children.length === 0)
15150 return; // AwaitBlock
15151 const first_child = block.children[0];
15152 const last_child = block.children[block.children.length - 1];
15153 if (first_child.type === 'Text' && trim_before) {
15154 first_child.data = trim_start(first_child.data);
15155 if (!first_child.data)
15156 block.children.shift();
15157 }
15158 if (last_child.type === 'Text' && trim_after) {
15159 last_child.data = trim_end(last_child.data);
15160 if (!last_child.data)
15161 block.children.pop();
15162 }
15163 if (block.else) {
15164 trim_whitespace(block.else, trim_before, trim_after);
15165 }
15166 if (first_child.elseif) {
15167 trim_whitespace(first_child, trim_before, trim_after);
15168 }
15169 }
15170 function mustache(parser) {
15171 const start = parser.index;
15172 parser.index += 1;
15173 parser.allow_whitespace();
15174 // {/if}, {/each} or {/await}
15175 if (parser.eat('/')) {
15176 let block = parser.current();
15177 let expected;
15178 if (closing_tag_omitted(block.name)) {
15179 block.end = start;
15180 parser.stack.pop();
15181 block = parser.current();
15182 }
15183 if (block.type === 'ElseBlock' || block.type === 'PendingBlock' || block.type === 'ThenBlock' || block.type === 'CatchBlock') {
15184 block.end = start;
15185 parser.stack.pop();
15186 block = parser.current();
15187 expected = 'await';
15188 }
15189 if (block.type === 'IfBlock') {
15190 expected = 'if';
15191 }
15192 else if (block.type === 'EachBlock') {
15193 expected = 'each';
15194 }
15195 else if (block.type === 'AwaitBlock') {
15196 expected = 'await';
15197 }
15198 else {
15199 parser.error({
15200 code: `unexpected-block-close`,
15201 message: `Unexpected block closing tag`
15202 });
15203 }
15204 parser.eat(expected, true);
15205 parser.allow_whitespace();
15206 parser.eat('}', true);
15207 while (block.elseif) {
15208 block.end = parser.index;
15209 parser.stack.pop();
15210 block = parser.current();
15211 if (block.else) {
15212 block.else.end = start;
15213 }
15214 }
15215 // strip leading/trailing whitespace as necessary
15216 const char_before = parser.template[block.start - 1];
15217 const char_after = parser.template[parser.index];
15218 const trim_before = !char_before || whitespace.test(char_before);
15219 const trim_after = !char_after || whitespace.test(char_after);
15220 trim_whitespace(block, trim_before, trim_after);
15221 block.end = parser.index;
15222 parser.stack.pop();
15223 }
15224 else if (parser.eat(':else')) {
15225 if (parser.eat('if')) {
15226 parser.error({
15227 code: 'invalid-elseif',
15228 message: `'elseif' should be 'else if'`
15229 });
15230 }
15231 parser.allow_whitespace();
15232 // :else if
15233 if (parser.eat('if')) {
15234 const block = parser.current();
15235 if (block.type !== 'IfBlock') {
15236 parser.error({
15237 code: `invalid-elseif-placement`,
15238 message: parser.stack.some(block => block.type === 'IfBlock')
15239 ? `Expected to close ${to_string(block)} before seeing {:else if ...} block`
15240 : `Cannot have an {:else if ...} block outside an {#if ...} block`
15241 });
15242 }
15243 parser.require_whitespace();
15244 const expression = read_expression(parser);
15245 parser.allow_whitespace();
15246 parser.eat('}', true);
15247 block.else = {
15248 start: parser.index,
15249 end: null,
15250 type: 'ElseBlock',
15251 children: [
15252 {
15253 start: parser.index,
15254 end: null,
15255 type: 'IfBlock',
15256 elseif: true,
15257 expression,
15258 children: [],
15259 },
15260 ],
15261 };
15262 parser.stack.push(block.else.children[0]);
15263 }
15264 // :else
15265 else {
15266 const block = parser.current();
15267 if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
15268 parser.error({
15269 code: `invalid-else-placement`,
15270 message: parser.stack.some(block => block.type === 'IfBlock' || block.type === 'EachBlock')
15271 ? `Expected to close ${to_string(block)} before seeing {:else} block`
15272 : `Cannot have an {:else} block outside an {#if ...} or {#each ...} block`
15273 });
15274 }
15275 parser.allow_whitespace();
15276 parser.eat('}', true);
15277 block.else = {
15278 start: parser.index,
15279 end: null,
15280 type: 'ElseBlock',
15281 children: [],
15282 };
15283 parser.stack.push(block.else);
15284 }
15285 }
15286 else if (parser.match(':then') || parser.match(':catch')) {
15287 const block = parser.current();
15288 const is_then = parser.eat(':then') || !parser.eat(':catch');
15289 if (is_then) {
15290 if (block.type !== 'PendingBlock') {
15291 parser.error({
15292 code: `invalid-then-placement`,
15293 message: parser.stack.some(block => block.type === 'PendingBlock')
15294 ? `Expected to close ${to_string(block)} before seeing {:then} block`
15295 : `Cannot have an {:then} block outside an {#await ...} block`
15296 });
15297 }
15298 }
15299 else {
15300 if (block.type !== 'ThenBlock' && block.type !== 'PendingBlock') {
15301 parser.error({
15302 code: `invalid-catch-placement`,
15303 message: parser.stack.some(block => block.type === 'ThenBlock' || block.type === 'PendingBlock')
15304 ? `Expected to close ${to_string(block)} before seeing {:catch} block`
15305 : `Cannot have an {:catch} block outside an {#await ...} block`
15306 });
15307 }
15308 }
15309 block.end = start;
15310 parser.stack.pop();
15311 const await_block = parser.current();
15312 if (!parser.eat('}')) {
15313 parser.require_whitespace();
15314 await_block[is_then ? 'value' : 'error'] = read_context(parser);
15315 parser.allow_whitespace();
15316 parser.eat('}', true);
15317 }
15318 const new_block = {
15319 start,
15320 end: null,
15321 type: is_then ? 'ThenBlock' : 'CatchBlock',
15322 children: [],
15323 skip: false
15324 };
15325 await_block[is_then ? 'then' : 'catch'] = new_block;
15326 parser.stack.push(new_block);
15327 }
15328 else if (parser.eat('#')) {
15329 // {#if foo}, {#each foo} or {#await foo}
15330 let type;
15331 if (parser.eat('if')) {
15332 type = 'IfBlock';
15333 }
15334 else if (parser.eat('each')) {
15335 type = 'EachBlock';
15336 }
15337 else if (parser.eat('await')) {
15338 type = 'AwaitBlock';
15339 }
15340 else {
15341 parser.error({
15342 code: `expected-block-type`,
15343 message: `Expected if, each or await`
15344 });
15345 }
15346 parser.require_whitespace();
15347 const expression = read_expression(parser);
15348 const block = type === 'AwaitBlock' ?
15349 {
15350 start,
15351 end: null,
15352 type,
15353 expression,
15354 value: null,
15355 error: null,
15356 pending: {
15357 start: null,
15358 end: null,
15359 type: 'PendingBlock',
15360 children: [],
15361 skip: true
15362 },
15363 then: {
15364 start: null,
15365 end: null,
15366 type: 'ThenBlock',
15367 children: [],
15368 skip: true
15369 },
15370 catch: {
15371 start: null,
15372 end: null,
15373 type: 'CatchBlock',
15374 children: [],
15375 skip: true
15376 },
15377 } :
15378 {
15379 start,
15380 end: null,
15381 type,
15382 expression,
15383 children: [],
15384 };
15385 parser.allow_whitespace();
15386 // {#each} blocks must declare a context – {#each list as item}
15387 if (type === 'EachBlock') {
15388 parser.eat('as', true);
15389 parser.require_whitespace();
15390 block.context = read_context(parser);
15391 parser.allow_whitespace();
15392 if (parser.eat(',')) {
15393 parser.allow_whitespace();
15394 block.index = parser.read_identifier();
15395 if (!block.index)
15396 parser.error({
15397 code: `expected-name`,
15398 message: `Expected name`
15399 });
15400 parser.allow_whitespace();
15401 }
15402 if (parser.eat('(')) {
15403 parser.allow_whitespace();
15404 block.key = read_expression(parser);
15405 parser.allow_whitespace();
15406 parser.eat(')', true);
15407 parser.allow_whitespace();
15408 }
15409 }
15410 const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then');
15411 if (await_block_shorthand) {
15412 parser.require_whitespace();
15413 block.value = read_context(parser);
15414 parser.allow_whitespace();
15415 }
15416 const await_block_catch_shorthand = !await_block_shorthand && type === 'AwaitBlock' && parser.eat('catch');
15417 if (await_block_catch_shorthand) {
15418 parser.require_whitespace();
15419 block.error = read_context(parser);
15420 parser.allow_whitespace();
15421 }
15422 parser.eat('}', true);
15423 parser.current().children.push(block);
15424 parser.stack.push(block);
15425 if (type === 'AwaitBlock') {
15426 let child_block;
15427 if (await_block_shorthand) {
15428 block.then.skip = false;
15429 child_block = block.then;
15430 }
15431 else if (await_block_catch_shorthand) {
15432 block.catch.skip = false;
15433 child_block = block.catch;
15434 }
15435 else {
15436 block.pending.skip = false;
15437 child_block = block.pending;
15438 }
15439 child_block.start = parser.index;
15440 parser.stack.push(child_block);
15441 }
15442 }
15443 else if (parser.eat('@html')) {
15444 // {@html content} tag
15445 parser.require_whitespace();
15446 const expression = read_expression(parser);
15447 parser.allow_whitespace();
15448 parser.eat('}', true);
15449 parser.current().children.push({
15450 start,
15451 end: parser.index,
15452 type: 'RawMustacheTag',
15453 expression,
15454 });
15455 }
15456 else if (parser.eat('@debug')) {
15457 let identifiers;
15458 // Implies {@debug} which indicates "debug all"
15459 if (parser.read(/\s*}/)) {
15460 identifiers = [];
15461 }
15462 else {
15463 const expression = read_expression(parser);
15464 identifiers = expression.type === 'SequenceExpression'
15465 ? expression.expressions
15466 : [expression];
15467 identifiers.forEach(node => {
15468 if (node.type !== 'Identifier') {
15469 parser.error({
15470 code: 'invalid-debug-args',
15471 message: '{@debug ...} arguments must be identifiers, not arbitrary expressions'
15472 }, node.start);
15473 }
15474 });
15475 parser.allow_whitespace();
15476 parser.eat('}', true);
15477 }
15478 parser.current().children.push({
15479 start,
15480 end: parser.index,
15481 type: 'DebugTag',
15482 identifiers
15483 });
15484 }
15485 else {
15486 const expression = read_expression(parser);
15487 parser.allow_whitespace();
15488 parser.eat('}', true);
15489 parser.current().children.push({
15490 start,
15491 end: parser.index,
15492 type: 'MustacheTag',
15493 expression,
15494 });
15495 }
15496 }
15497
15498 function text(parser) {
15499 const start = parser.index;
15500 let data = '';
15501 while (parser.index < parser.template.length &&
15502 !parser.match('<') &&
15503 !parser.match('{')) {
15504 data += parser.template[parser.index++];
15505 }
15506 const node = {
15507 start,
15508 end: parser.index,
15509 type: 'Text',
15510 raw: data,
15511 data: decode_character_references(data),
15512 };
15513 parser.current().children.push(node);
15514 }
15515
15516 function fragment(parser) {
15517 if (parser.match('<')) {
15518 return tag;
15519 }
15520 if (parser.match('{')) {
15521 return mustache;
15522 }
15523 return text;
15524 }
15525
15526 function getLocator(source, options) {
15527 if (options === void 0) { options = {}; }
15528 var offsetLine = options.offsetLine || 0;
15529 var offsetColumn = options.offsetColumn || 0;
15530 var originalLines = source.split('\n');
15531 var start = 0;
15532 var lineRanges = originalLines.map(function (line, i) {
15533 var end = start + line.length + 1;
15534 var range = { start: start, end: end, line: i };
15535 start = end;
15536 return range;
15537 });
15538 var i = 0;
15539 function rangeContains(range, index) {
15540 return range.start <= index && index < range.end;
15541 }
15542 function getLocation(range, index) {
15543 return { line: offsetLine + range.line, column: offsetColumn + index - range.start, character: index };
15544 }
15545 function locate(search, startIndex) {
15546 if (typeof search === 'string') {
15547 search = source.indexOf(search, startIndex || 0);
15548 }
15549 var range = lineRanges[i];
15550 var d = search >= range.end ? 1 : -1;
15551 while (range) {
15552 if (rangeContains(range, search))
15553 return getLocation(range, search);
15554 i += d;
15555 range = lineRanges[i];
15556 }
15557 }
15558 return locate;
15559 }
15560 function locate(source, search, options) {
15561 if (typeof options === 'number') {
15562 throw new Error('locate takes a { startIndex, offsetLine, offsetColumn } object as the third argument');
15563 }
15564 return getLocator(source, options)(search, options && options.startIndex);
15565 }
15566
15567 function tabs_to_spaces(str) {
15568 return str.replace(/^\t+/, match => match.split('\t').join(' '));
15569 }
15570 function get_code_frame(source, line, column) {
15571 const lines = source.split('\n');
15572 const frame_start = Math.max(0, line - 2);
15573 const frame_end = Math.min(line + 3, lines.length);
15574 const digits = String(frame_end + 1).length;
15575 return lines
15576 .slice(frame_start, frame_end)
15577 .map((str, i) => {
15578 const isErrorLine = frame_start + i === line;
15579 const line_num = String(i + frame_start + 1).padStart(digits, ' ');
15580 if (isErrorLine) {
15581 const indicator = ' '.repeat(digits + 2 + tabs_to_spaces(str.slice(0, column)).length) + '^';
15582 return `${line_num}: ${tabs_to_spaces(str)}\n${indicator}`;
15583 }
15584 return `${line_num}: ${tabs_to_spaces(str)}`;
15585 })
15586 .join('\n');
15587 }
15588
15589 class CompileError extends Error {
15590 toString() {
15591 return `${this.message} (${this.start.line}:${this.start.column})\n${this.frame}`;
15592 }
15593 }
15594 function error$1(message, props) {
15595 const error = new CompileError(message);
15596 error.name = props.name;
15597 const start = locate(props.source, props.start, { offsetLine: 1 });
15598 const end = locate(props.source, props.end || props.start, { offsetLine: 1 });
15599 error.code = props.code;
15600 error.start = start;
15601 error.end = end;
15602 error.pos = props.start;
15603 error.filename = props.filename;
15604 error.frame = get_code_frame(props.source, start.line - 1, start.column);
15605 throw error;
15606 }
15607
15608 class Parser$1 {
15609 constructor(template, options) {
15610 this.index = 0;
15611 this.stack = [];
15612 this.css = [];
15613 this.js = [];
15614 this.meta_tags = {};
15615 if (typeof template !== 'string') {
15616 throw new TypeError('Template must be a string');
15617 }
15618 this.template = template.replace(/\s+$/, '');
15619 this.filename = options.filename;
15620 this.customElement = options.customElement;
15621 this.html = {
15622 start: null,
15623 end: null,
15624 type: 'Fragment',
15625 children: [],
15626 };
15627 this.stack.push(this.html);
15628 let state = fragment;
15629 while (this.index < this.template.length) {
15630 state = state(this) || fragment;
15631 }
15632 if (this.stack.length > 1) {
15633 const current = this.current();
15634 const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
15635 const slug = current.type === 'Element' ? 'element' : 'block';
15636 this.error({
15637 code: `unclosed-${slug}`,
15638 message: `${type} was left open`
15639 }, current.start);
15640 }
15641 if (state !== fragment) {
15642 this.error({
15643 code: `unexpected-eof`,
15644 message: 'Unexpected end of input'
15645 });
15646 }
15647 if (this.html.children.length) {
15648 let start = this.html.children[0].start;
15649 while (whitespace.test(template[start]))
15650 start += 1;
15651 let end = this.html.children[this.html.children.length - 1].end;
15652 while (whitespace.test(template[end - 1]))
15653 end -= 1;
15654 this.html.start = start;
15655 this.html.end = end;
15656 }
15657 else {
15658 this.html.start = this.html.end = null;
15659 }
15660 }
15661 current() {
15662 return this.stack[this.stack.length - 1];
15663 }
15664 acorn_error(err) {
15665 this.error({
15666 code: `parse-error`,
15667 message: err.message.replace(/ \(\d+:\d+\)$/, '')
15668 }, err.pos);
15669 }
15670 error({ code, message }, index = this.index) {
15671 error$1(message, {
15672 name: 'ParseError',
15673 code,
15674 source: this.template,
15675 start: index,
15676 filename: this.filename
15677 });
15678 }
15679 eat(str, required, message) {
15680 if (this.match(str)) {
15681 this.index += str.length;
15682 return true;
15683 }
15684 if (required) {
15685 this.error({
15686 code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`,
15687 message: message || `Expected ${str}`
15688 });
15689 }
15690 return false;
15691 }
15692 match(str) {
15693 return this.template.slice(this.index, this.index + str.length) === str;
15694 }
15695 match_regex(pattern) {
15696 const match = pattern.exec(this.template.slice(this.index));
15697 if (!match || match.index !== 0)
15698 return null;
15699 return match[0];
15700 }
15701 allow_whitespace() {
15702 while (this.index < this.template.length &&
15703 whitespace.test(this.template[this.index])) {
15704 this.index++;
15705 }
15706 }
15707 read(pattern) {
15708 const result = this.match_regex(pattern);
15709 if (result)
15710 this.index += result.length;
15711 return result;
15712 }
15713 read_identifier(allow_reserved = false) {
15714 const start = this.index;
15715 let i = this.index;
15716 const code = full_char_code_at(this.template, i);
15717 if (!isIdentifierStart(code, true))
15718 return null;
15719 i += code <= 0xffff ? 1 : 2;
15720 while (i < this.template.length) {
15721 const code = full_char_code_at(this.template, i);
15722 if (!isIdentifierChar(code, true))
15723 break;
15724 i += code <= 0xffff ? 1 : 2;
15725 }
15726 const identifier = this.template.slice(this.index, this.index = i);
15727 if (!allow_reserved && reserved.has(identifier)) {
15728 this.error({
15729 code: `unexpected-reserved-word`,
15730 message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`
15731 }, start);
15732 }
15733 return identifier;
15734 }
15735 read_until(pattern) {
15736 if (this.index >= this.template.length)
15737 this.error({
15738 code: `unexpected-eof`,
15739 message: 'Unexpected end of input'
15740 });
15741 const start = this.index;
15742 const match = pattern.exec(this.template.slice(start));
15743 if (match) {
15744 this.index = start + match.index;
15745 return this.template.slice(start, this.index);
15746 }
15747 this.index = this.template.length;
15748 return this.template.slice(start);
15749 }
15750 require_whitespace() {
15751 if (!whitespace.test(this.template[this.index])) {
15752 this.error({
15753 code: `missing-whitespace`,
15754 message: `Expected whitespace`
15755 });
15756 }
15757 this.allow_whitespace();
15758 }
15759 }
15760 function parse$3(template, options = {}) {
15761 const parser = new Parser$1(template, options);
15762 // TODO we may want to allow multiple <style> tags —
15763 // one scoped, one global. for now, only allow one
15764 if (parser.css.length > 1) {
15765 parser.error({
15766 code: 'duplicate-style',
15767 message: 'You can only have one top-level <style> tag per component'
15768 }, parser.css[1].start);
15769 }
15770 const instance_scripts = parser.js.filter(script => script.context === 'default');
15771 const module_scripts = parser.js.filter(script => script.context === 'module');
15772 if (instance_scripts.length > 1) {
15773 parser.error({
15774 code: `invalid-script`,
15775 message: `A component can only have one instance-level <script> element`
15776 }, instance_scripts[1].start);
15777 }
15778 if (module_scripts.length > 1) {
15779 parser.error({
15780 code: `invalid-script`,
15781 message: `A component can only have one <script context="module"> element`
15782 }, module_scripts[1].start);
15783 }
15784 return {
15785 html: parser.html,
15786 css: parser.css[0],
15787 instance: instance_scripts[0],
15788 module: module_scripts[0]
15789 };
15790 }
15791
15792 function is_head(node) {
15793 return node && node.type === 'MemberExpression' && node.object.name === '@_document' && node.property.name === 'head';
15794 }
15795
15796 class Block$1 {
15797 constructor(options) {
15798 this.dependencies = new Set();
15799 this.event_listeners = [];
15800 this.variables = new Map();
15801 this.has_update_method = false;
15802 this.parent = options.parent;
15803 this.renderer = options.renderer;
15804 this.name = options.name;
15805 this.type = options.type;
15806 this.comment = options.comment;
15807 this.wrappers = [];
15808 // for keyed each blocks
15809 this.key = options.key;
15810 this.first = null;
15811 this.bindings = options.bindings;
15812 this.chunks = {
15813 declarations: [],
15814 init: [],
15815 create: [],
15816 claim: [],
15817 hydrate: [],
15818 mount: [],
15819 measure: [],
15820 fix: [],
15821 animate: [],
15822 intro: [],
15823 update: [],
15824 outro: [],
15825 destroy: [],
15826 };
15827 this.has_animation = false;
15828 this.has_intro_method = false; // a block could have an intro method but not intro transitions, e.g. if a sibling block has intros
15829 this.has_outro_method = false;
15830 this.outros = 0;
15831 this.get_unique_name = this.renderer.component.get_unique_name_maker();
15832 this.aliases = new Map();
15833 if (this.key)
15834 this.aliases.set('key', this.get_unique_name('key'));
15835 }
15836 assign_variable_names() {
15837 const seen = new Set();
15838 const dupes = new Set();
15839 let i = this.wrappers.length;
15840 while (i--) {
15841 const wrapper = this.wrappers[i];
15842 if (!wrapper.var)
15843 continue;
15844 if (seen.has(wrapper.var.name)) {
15845 dupes.add(wrapper.var.name);
15846 }
15847 seen.add(wrapper.var.name);
15848 }
15849 const counts = new Map();
15850 i = this.wrappers.length;
15851 while (i--) {
15852 const wrapper = this.wrappers[i];
15853 if (!wrapper.var)
15854 continue;
15855 let suffix = '';
15856 if (dupes.has(wrapper.var.name)) {
15857 const i = counts.get(wrapper.var.name) || 0;
15858 counts.set(wrapper.var.name, i + 1);
15859 suffix = i;
15860 }
15861 wrapper.var.name = this.get_unique_name(wrapper.var.name + suffix).name;
15862 }
15863 }
15864 add_dependencies(dependencies) {
15865 dependencies.forEach(dependency => {
15866 this.dependencies.add(dependency);
15867 });
15868 this.has_update_method = true;
15869 if (this.parent) {
15870 this.parent.add_dependencies(dependencies);
15871 }
15872 }
15873 add_element(id, render_statement, claim_statement, parent_node, no_detach) {
15874 this.add_variable(id);
15875 this.chunks.create.push(b `${id} = ${render_statement};`);
15876 if (this.renderer.options.hydratable) {
15877 this.chunks.claim.push(b `${id} = ${claim_statement || render_statement};`);
15878 }
15879 if (parent_node) {
15880 this.chunks.mount.push(b `@append(${parent_node}, ${id});`);
15881 if (is_head(parent_node) && !no_detach)
15882 this.chunks.destroy.push(b `@detach(${id});`);
15883 }
15884 else {
15885 this.chunks.mount.push(b `@insert(#target, ${id}, #anchor);`);
15886 if (!no_detach)
15887 this.chunks.destroy.push(b `if (detaching) @detach(${id});`);
15888 }
15889 }
15890 add_intro(local) {
15891 this.has_intros = this.has_intro_method = true;
15892 if (!local && this.parent)
15893 this.parent.add_intro();
15894 }
15895 add_outro(local) {
15896 this.has_outros = this.has_outro_method = true;
15897 this.outros += 1;
15898 if (!local && this.parent)
15899 this.parent.add_outro();
15900 }
15901 add_animation() {
15902 this.has_animation = true;
15903 }
15904 add_variable(id, init) {
15905 if (this.variables.has(id.name)) {
15906 throw new Error(`Variable '${id.name}' already initialised with a different value`);
15907 }
15908 this.variables.set(id.name, { id, init });
15909 }
15910 alias(name) {
15911 if (!this.aliases.has(name)) {
15912 this.aliases.set(name, this.get_unique_name(name));
15913 }
15914 return this.aliases.get(name);
15915 }
15916 child(options) {
15917 return new Block$1(Object.assign({}, this, { key: null }, options, { parent: this }));
15918 }
15919 get_contents(key) {
15920 const { dev } = this.renderer.options;
15921 if (this.has_outros) {
15922 this.add_variable({ type: 'Identifier', name: '#current' });
15923 if (this.chunks.intro.length > 0) {
15924 this.chunks.intro.push(b `#current = true;`);
15925 this.chunks.mount.push(b `#current = true;`);
15926 }
15927 if (this.chunks.outro.length > 0) {
15928 this.chunks.outro.push(b `#current = false;`);
15929 }
15930 }
15931 if (this.autofocus) {
15932 this.chunks.mount.push(b `${this.autofocus}.focus();`);
15933 }
15934 this.render_listeners();
15935 const properties = {};
15936 const noop = x `@noop`;
15937 properties.key = key;
15938 if (this.first) {
15939 properties.first = x `null`;
15940 this.chunks.hydrate.push(b `this.first = ${this.first};`);
15941 }
15942 if (this.chunks.create.length === 0 && this.chunks.hydrate.length === 0) {
15943 properties.create = noop;
15944 }
15945 else {
15946 const hydrate = this.chunks.hydrate.length > 0 && (this.renderer.options.hydratable
15947 ? b `this.h();`
15948 : this.chunks.hydrate);
15949 properties.create = x `function #create() {
15950 ${this.chunks.create}
15951 ${hydrate}
15952 }`;
15953 }
15954 if (this.renderer.options.hydratable || this.chunks.claim.length > 0) {
15955 if (this.chunks.claim.length === 0 && this.chunks.hydrate.length === 0) {
15956 properties.claim = noop;
15957 }
15958 else {
15959 properties.claim = x `function #claim(#nodes) {
15960 ${this.chunks.claim}
15961 ${this.renderer.options.hydratable && this.chunks.hydrate.length > 0 && b `this.h();`}
15962 }`;
15963 }
15964 }
15965 if (this.renderer.options.hydratable && this.chunks.hydrate.length > 0) {
15966 properties.hydrate = x `function #hydrate() {
15967 ${this.chunks.hydrate}
15968 }`;
15969 }
15970 if (this.chunks.mount.length === 0) {
15971 properties.mount = noop;
15972 }
15973 else if (this.event_listeners.length === 0) {
15974 properties.mount = x `function #mount(#target, #anchor) {
15975 ${this.chunks.mount}
15976 }`;
15977 }
15978 else {
15979 properties.mount = x `function #mount(#target, #anchor) {
15980 ${this.chunks.mount}
15981 }`;
15982 }
15983 if (this.has_update_method || this.maintain_context) {
15984 if (this.chunks.update.length === 0 && !this.maintain_context) {
15985 properties.update = noop;
15986 }
15987 else {
15988 const ctx = this.maintain_context ? x `#new_ctx` : x `#ctx`;
15989 let dirty = { type: 'Identifier', name: '#dirty' };
15990 if (!this.renderer.context_overflow && !this.parent) {
15991 dirty = { type: 'ArrayPattern', elements: [dirty] };
15992 }
15993 properties.update = x `function #update(${ctx}, ${dirty}) {
15994 ${this.maintain_context && b `#ctx = ${ctx};`}
15995 ${this.chunks.update}
15996 }`;
15997 }
15998 }
15999 if (this.has_animation) {
16000 properties.measure = x `function #measure() {
16001 ${this.chunks.measure}
16002 }`;
16003 properties.fix = x `function #fix() {
16004 ${this.chunks.fix}
16005 }`;
16006 properties.animate = x `function #animate() {
16007 ${this.chunks.animate}
16008 }`;
16009 }
16010 if (this.has_intro_method || this.has_outro_method) {
16011 if (this.chunks.intro.length === 0) {
16012 properties.intro = noop;
16013 }
16014 else {
16015 properties.intro = x `function #intro(#local) {
16016 ${this.has_outros && b `if (#current) return;`}
16017 ${this.chunks.intro}
16018 }`;
16019 }
16020 if (this.chunks.outro.length === 0) {
16021 properties.outro = noop;
16022 }
16023 else {
16024 properties.outro = x `function #outro(#local) {
16025 ${this.chunks.outro}
16026 }`;
16027 }
16028 }
16029 if (this.chunks.destroy.length === 0) {
16030 properties.destroy = noop;
16031 }
16032 else {
16033 properties.destroy = x `function #destroy(detaching) {
16034 ${this.chunks.destroy}
16035 }`;
16036 }
16037 if (!this.renderer.component.compile_options.dev) {
16038 // allow shorthand names
16039 for (const name in properties) {
16040 const property = properties[name];
16041 if (property)
16042 property.id = null;
16043 }
16044 }
16045 const return_value = x `{
16046 key: ${properties.key},
16047 first: ${properties.first},
16048 c: ${properties.create},
16049 l: ${properties.claim},
16050 h: ${properties.hydrate},
16051 m: ${properties.mount},
16052 p: ${properties.update},
16053 r: ${properties.measure},
16054 f: ${properties.fix},
16055 a: ${properties.animate},
16056 i: ${properties.intro},
16057 o: ${properties.outro},
16058 d: ${properties.destroy}
16059 }`;
16060 const block = dev && this.get_unique_name('block');
16061 const body = b `
16062 ${this.chunks.declarations}
16063
16064 ${Array.from(this.variables.values()).map(({ id, init }) => {
16065 return init
16066 ? b `let ${id} = ${init}`
16067 : b `let ${id}`;
16068 })}
16069
16070 ${this.chunks.init}
16071
16072 ${dev
16073 ? b `
16074 const ${block} = ${return_value};
16075 @dispatch_dev("SvelteRegisterBlock", {
16076 block: ${block},
16077 id: ${this.name || 'create_fragment'}.name,
16078 type: "${this.type}",
16079 source: "${this.comment ? this.comment.replace(/"/g, '\\"') : ''}",
16080 ctx: #ctx
16081 });
16082 return ${block};`
16083 : b `
16084 return ${return_value};`}
16085 `;
16086 return body;
16087 }
16088 has_content() {
16089 return !!this.first ||
16090 this.event_listeners.length > 0 ||
16091 this.chunks.intro.length > 0 ||
16092 this.chunks.outro.length > 0 ||
16093 this.chunks.create.length > 0 ||
16094 this.chunks.hydrate.length > 0 ||
16095 this.chunks.claim.length > 0 ||
16096 this.chunks.mount.length > 0 ||
16097 this.chunks.update.length > 0 ||
16098 this.chunks.destroy.length > 0 ||
16099 this.has_animation;
16100 }
16101 render() {
16102 const key = this.key && this.get_unique_name('key');
16103 const args = [x `#ctx`];
16104 if (key)
16105 args.unshift(key);
16106 const fn = b `function ${this.name}(${args}) {
16107 ${this.get_contents(key)}
16108 }`;
16109 return this.comment
16110 ? b `
16111 // ${this.comment}
16112 ${fn}`
16113 : fn;
16114 }
16115 render_listeners(chunk = '') {
16116 if (this.event_listeners.length > 0) {
16117 this.add_variable({ type: 'Identifier', name: '#mounted' });
16118 this.chunks.destroy.push(b `#mounted = false`);
16119 const dispose = {
16120 type: 'Identifier',
16121 name: `#dispose${chunk}`
16122 };
16123 this.add_variable(dispose);
16124 if (this.event_listeners.length === 1) {
16125 this.chunks.mount.push(b `
16126 if (!#mounted) {
16127 ${dispose} = ${this.event_listeners[0]};
16128 #mounted = true;
16129 }
16130 `);
16131 this.chunks.destroy.push(b `${dispose}();`);
16132 }
16133 else {
16134 this.chunks.mount.push(b `
16135 if (!#mounted) {
16136 ${dispose} = [
16137 ${this.event_listeners}
16138 ];
16139 #mounted = true;
16140 }
16141 `);
16142 this.chunks.destroy.push(b `@run_all(${dispose});`);
16143 }
16144 }
16145 }
16146 }
16147
16148 class Wrapper {
16149 constructor(renderer, block, parent, node) {
16150 this.node = node;
16151 // make these non-enumerable so that they can be logged sensibly
16152 // (TODO in dev only?)
16153 Object.defineProperties(this, {
16154 renderer: {
16155 value: renderer
16156 },
16157 parent: {
16158 value: parent
16159 }
16160 });
16161 this.can_use_innerhtml = !renderer.options.hydratable;
16162 this.is_static_content = !renderer.options.hydratable;
16163 block.wrappers.push(this);
16164 }
16165 cannot_use_innerhtml() {
16166 this.can_use_innerhtml = false;
16167 if (this.parent)
16168 this.parent.cannot_use_innerhtml();
16169 }
16170 not_static_content() {
16171 this.is_static_content = false;
16172 if (this.parent)
16173 this.parent.not_static_content();
16174 }
16175 get_or_create_anchor(block, parent_node, parent_nodes) {
16176 // TODO use this in EachBlock and IfBlock — tricky because
16177 // children need to be created first
16178 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
16179 const anchor = needs_anchor
16180 ? block.get_unique_name(`${this.var.name}_anchor`)
16181 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16182 if (needs_anchor) {
16183 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16184 }
16185 return anchor;
16186 }
16187 get_update_mount_node(anchor) {
16188 return ((this.parent && this.parent.is_dom_node())
16189 ? this.parent.var
16190 : x `${anchor}.parentNode`);
16191 }
16192 is_dom_node() {
16193 return (this.node.type === 'Element' ||
16194 this.node.type === 'Text' ||
16195 this.node.type === 'MustacheTag');
16196 }
16197 render(_block, _parent_node, _parent_nodes) {
16198 throw Error('Wrapper class is not renderable');
16199 }
16200 }
16201
16202 function create_debugging_comment(node, component) {
16203 const { locate, source } = component;
16204 let c = node.start;
16205 if (node.type === 'ElseBlock') {
16206 while (source[c - 1] !== '{')
16207 c -= 1;
16208 while (source[c - 1] === '{')
16209 c -= 1;
16210 }
16211 let d;
16212 if (node.type === 'InlineComponent' || node.type === 'Element') {
16213 if (node.children.length) {
16214 d = node.children[0].start;
16215 while (source[d - 1] !== '>')
16216 d -= 1;
16217 }
16218 else {
16219 d = node.start;
16220 while (source[d] !== '>')
16221 d += 1;
16222 d += 1;
16223 }
16224 }
16225 else if (node.type === 'Text' || node.type === 'Comment') {
16226 d = node.end;
16227 }
16228 else {
16229 // @ts-ignore
16230 d = node.expression ? node.expression.node.end : c;
16231 while (source[d] !== '}')
16232 d += 1;
16233 while (source[d] === '}')
16234 d += 1;
16235 }
16236 const start = locate(c);
16237 const loc = `(${start.line}:${start.column})`;
16238 return `${loc} ${source.slice(c, d)}`.replace(/\s/g, ' ');
16239 }
16240
16241 class AwaitBlockBranch extends Wrapper {
16242 constructor(status, renderer, block, parent, node, strip_whitespace, next_sibling) {
16243 super(renderer, block, parent, node);
16244 this.var = null;
16245 this.status = status;
16246 this.block = block.child({
16247 comment: create_debugging_comment(node, this.renderer.component),
16248 name: this.renderer.component.get_unique_name(`create_${status}_block`),
16249 type: status
16250 });
16251 this.add_context(parent.node[status + '_node'], parent.node[status + '_contexts']);
16252 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16253 this.is_dynamic = this.block.dependencies.size > 0;
16254 }
16255 add_context(node, contexts) {
16256 if (!node)
16257 return;
16258 if (node.type === 'Identifier') {
16259 this.value = node.name;
16260 this.renderer.add_to_context(this.value, true);
16261 }
16262 else {
16263 contexts.forEach(context => {
16264 this.renderer.add_to_context(context.key.name, true);
16265 });
16266 this.value = this.block.parent.get_unique_name('value').name;
16267 this.value_contexts = contexts;
16268 this.renderer.add_to_context(this.value, true);
16269 this.is_destructured = true;
16270 }
16271 this.value_index = this.renderer.context_lookup.get(this.value).index;
16272 }
16273 render(block, parent_node, parent_nodes) {
16274 this.fragment.render(block, parent_node, parent_nodes);
16275 if (this.is_destructured) {
16276 this.render_destructure();
16277 }
16278 }
16279 render_destructure() {
16280 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}]`)};`);
16281 const get_context = this.block.renderer.component.get_unique_name(`get_${this.status}_context`);
16282 this.block.renderer.blocks.push(b `
16283 function ${get_context}(#ctx) {
16284 ${props}
16285 }
16286 `);
16287 this.block.chunks.declarations.push(b `${get_context}(#ctx)`);
16288 if (this.block.has_update_method) {
16289 this.block.chunks.update.push(b `${get_context}(#ctx)`);
16290 }
16291 }
16292 }
16293 class AwaitBlockWrapper extends Wrapper {
16294 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16295 super(renderer, block, parent, node);
16296 this.var = { type: 'Identifier', name: 'await_block' };
16297 this.cannot_use_innerhtml();
16298 this.not_static_content();
16299 block.add_dependencies(this.node.expression.dependencies);
16300 let is_dynamic = false;
16301 let has_intros = false;
16302 let has_outros = false;
16303 ['pending', 'then', 'catch'].forEach((status) => {
16304 const child = this.node[status];
16305 const branch = new AwaitBlockBranch(status, renderer, block, this, child, strip_whitespace, next_sibling);
16306 renderer.blocks.push(branch.block);
16307 if (branch.is_dynamic) {
16308 is_dynamic = true;
16309 // TODO should blocks update their own parents?
16310 block.add_dependencies(branch.block.dependencies);
16311 }
16312 if (branch.block.has_intros)
16313 has_intros = true;
16314 if (branch.block.has_outros)
16315 has_outros = true;
16316 this[status] = branch;
16317 });
16318 ['pending', 'then', 'catch'].forEach(status => {
16319 this[status].block.has_update_method = is_dynamic;
16320 this[status].block.has_intro_method = has_intros;
16321 this[status].block.has_outro_method = has_outros;
16322 });
16323 if (has_outros) {
16324 block.add_outro();
16325 }
16326 }
16327 render(block, parent_node, parent_nodes) {
16328 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
16329 const update_mount_node = this.get_update_mount_node(anchor);
16330 const snippet = this.node.expression.manipulate(block);
16331 const info = block.get_unique_name(`info`);
16332 const promise = block.get_unique_name(`promise`);
16333 block.add_variable(promise);
16334 block.maintain_context = true;
16335 const info_props = x `{
16336 ctx: #ctx,
16337 current: null,
16338 token: null,
16339 pending: ${this.pending.block.name},
16340 then: ${this.then.block.name},
16341 catch: ${this.catch.block.name},
16342 value: ${this.then.value_index},
16343 error: ${this.catch.value_index},
16344 blocks: ${this.pending.block.has_outro_method && x `[,,,]`}
16345 }`;
16346 block.chunks.init.push(b `
16347 let ${info} = ${info_props};
16348 `);
16349 block.chunks.init.push(b `
16350 @handle_promise(${promise} = ${snippet}, ${info});
16351 `);
16352 block.chunks.create.push(b `
16353 ${info}.block.c();
16354 `);
16355 if (parent_nodes && this.renderer.options.hydratable) {
16356 block.chunks.claim.push(b `
16357 ${info}.block.l(${parent_nodes});
16358 `);
16359 }
16360 const initial_mount_node = parent_node || '#target';
16361 const anchor_node = parent_node ? 'null' : '#anchor';
16362 const has_transitions = this.pending.block.has_intro_method || this.pending.block.has_outro_method;
16363 block.chunks.mount.push(b `
16364 ${info}.block.m(${initial_mount_node}, ${info}.anchor = ${anchor_node});
16365 ${info}.mount = () => ${update_mount_node};
16366 ${info}.anchor = ${anchor};
16367 `);
16368 if (has_transitions) {
16369 block.chunks.intro.push(b `@transition_in(${info}.block);`);
16370 }
16371 const dependencies = this.node.expression.dynamic_dependencies();
16372 if (dependencies.length > 0) {
16373 const condition = x `
16374 ${block.renderer.dirty(dependencies)} &&
16375 ${promise} !== (${promise} = ${snippet}) &&
16376 @handle_promise(${promise}, ${info})`;
16377 block.chunks.update.push(b `${info}.ctx = #ctx;`);
16378 if (this.pending.block.has_update_method) {
16379 block.chunks.update.push(b `
16380 if (${condition}) {
16381
16382 } else {
16383 const #child_ctx = #ctx.slice();
16384 ${this.then.value && b `#child_ctx[${this.then.value_index}] = ${info}.resolved;`}
16385 ${info}.block.p(#child_ctx, #dirty);
16386 }
16387 `);
16388 }
16389 else {
16390 block.chunks.update.push(b `
16391 ${condition}
16392 `);
16393 }
16394 }
16395 else {
16396 if (this.pending.block.has_update_method) {
16397 block.chunks.update.push(b `
16398 {
16399 const #child_ctx = #ctx.slice();
16400 ${this.then.value && b `#child_ctx[${this.then.value_index}] = ${info}.resolved;`}
16401 ${info}.block.p(#child_ctx, #dirty);
16402 }
16403 `);
16404 }
16405 }
16406 if (this.pending.block.has_outro_method) {
16407 block.chunks.outro.push(b `
16408 for (let #i = 0; #i < 3; #i += 1) {
16409 const block = ${info}.blocks[#i];
16410 @transition_out(block);
16411 }
16412 `);
16413 }
16414 block.chunks.destroy.push(b `
16415 ${info}.block.d(${parent_node ? null : 'detaching'});
16416 ${info}.token = null;
16417 ${info} = null;
16418 `);
16419 [this.pending, this.then, this.catch].forEach(branch => {
16420 branch.render(branch.block, null, x `#nodes`);
16421 });
16422 }
16423 }
16424
16425 const TRUE = x `true`;
16426 const FALSE = x `false`;
16427 class EventHandlerWrapper {
16428 constructor(node, parent) {
16429 this.node = node;
16430 this.parent = parent;
16431 if (!node.expression) {
16432 this.parent.renderer.add_to_context(node.handler_name.name);
16433 this.parent.renderer.component.partly_hoisted.push(b `
16434 function ${node.handler_name.name}(event) {
16435 @bubble($$self, event);
16436 }
16437 `);
16438 }
16439 }
16440 get_snippet(block) {
16441 const snippet = this.node.expression ? this.node.expression.manipulate(block) : block.renderer.reference(this.node.handler_name);
16442 if (this.node.reassigned) {
16443 block.maintain_context = true;
16444 return x `function () { if (@is_function(${snippet})) ${snippet}.apply(this, arguments); }`;
16445 }
16446 return snippet;
16447 }
16448 render(block, target) {
16449 let snippet = this.get_snippet(block);
16450 if (this.node.modifiers.has('preventDefault'))
16451 snippet = x `@prevent_default(${snippet})`;
16452 if (this.node.modifiers.has('stopPropagation'))
16453 snippet = x `@stop_propagation(${snippet})`;
16454 if (this.node.modifiers.has('self'))
16455 snippet = x `@self(${snippet})`;
16456 const args = [];
16457 const opts = ['passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod));
16458 if (opts.length) {
16459 args.push((opts.length === 1 && opts[0] === 'capture')
16460 ? TRUE
16461 : x `{ ${opts.map(opt => p `${opt}: true`)} }`);
16462 }
16463 else if (block.renderer.options.dev) {
16464 args.push(FALSE);
16465 }
16466 if (block.renderer.options.dev) {
16467 args.push(this.node.modifiers.has('preventDefault') ? TRUE : FALSE);
16468 args.push(this.node.modifiers.has('stopPropagation') ? TRUE : FALSE);
16469 }
16470 block.event_listeners.push(x `@listen(${target}, "${this.node.name}", ${snippet}, ${args})`);
16471 }
16472 }
16473
16474 function add_event_handlers(block, target, handlers) {
16475 handlers.forEach(handler => add_event_handler(block, target, handler));
16476 }
16477 function add_event_handler(block, target, handler) {
16478 handler.render(block, target);
16479 }
16480
16481 class BodyWrapper extends Wrapper {
16482 constructor(renderer, block, parent, node) {
16483 super(renderer, block, parent, node);
16484 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
16485 }
16486 render(block, _parent_node, _parent_nodes) {
16487 add_event_handlers(block, x `@_document.body`, this.handlers);
16488 }
16489 }
16490
16491 function add_to_set(a, b) {
16492 // @ts-ignore
16493 b.forEach(item => {
16494 a.add(item);
16495 });
16496 }
16497
16498 class DebugTagWrapper extends Wrapper {
16499 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
16500 super(renderer, block, parent, node);
16501 }
16502 render(block, _parent_node, _parent_nodes) {
16503 const { renderer } = this;
16504 const { component } = renderer;
16505 if (!renderer.options.dev)
16506 return;
16507 const { var_lookup } = component;
16508 const start = component.locate(this.node.start + 1);
16509 const end = { line: start.line, column: start.column + 6 };
16510 const loc = { start, end };
16511 const debug = {
16512 type: 'DebuggerStatement',
16513 loc
16514 };
16515 if (this.node.expressions.length === 0) {
16516 // Debug all
16517 block.chunks.create.push(debug);
16518 block.chunks.update.push(debug);
16519 }
16520 else {
16521 const log = {
16522 type: 'Identifier',
16523 name: 'log',
16524 loc
16525 };
16526 const dependencies = new Set();
16527 this.node.expressions.forEach(expression => {
16528 add_to_set(dependencies, expression.dependencies);
16529 });
16530 const contextual_identifiers = this.node.expressions
16531 .filter(e => {
16532 const variable = var_lookup.get(e.node.name);
16533 return !(variable && variable.hoistable);
16534 })
16535 .map(e => e.node.name);
16536 const logged_identifiers = this.node.expressions.map(e => p `${e.node.name}`);
16537 const debug_statements = b `
16538 ${contextual_identifiers.map(name => b `const ${name} = ${renderer.reference(name)};`)}
16539 @_console.${log}({ ${logged_identifiers} });
16540 debugger;`;
16541 if (dependencies.size) {
16542 const condition = renderer.dirty(Array.from(dependencies));
16543 block.chunks.update.push(b `
16544 if (${condition}) {
16545 ${debug_statements}
16546 }
16547 `);
16548 }
16549 block.chunks.create.push(b `{
16550 ${debug_statements}
16551 }`);
16552 }
16553 }
16554 }
16555
16556 class ElseBlockWrapper extends Wrapper {
16557 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16558 super(renderer, block, parent, node);
16559 this.var = null;
16560 this.block = block.child({
16561 comment: create_debugging_comment(node, this.renderer.component),
16562 name: this.renderer.component.get_unique_name(`create_else_block`),
16563 type: 'else'
16564 });
16565 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16566 this.is_dynamic = this.block.dependencies.size > 0;
16567 }
16568 }
16569 class EachBlockWrapper extends Wrapper {
16570 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16571 super(renderer, block, parent, node);
16572 this.updates = [];
16573 this.var = { type: 'Identifier', name: 'each' };
16574 this.cannot_use_innerhtml();
16575 this.not_static_content();
16576 const { dependencies } = node.expression;
16577 block.add_dependencies(dependencies);
16578 this.node.contexts.forEach(context => {
16579 renderer.add_to_context(context.key.name, true);
16580 });
16581 this.block = block.child({
16582 comment: create_debugging_comment(this.node, this.renderer.component),
16583 name: renderer.component.get_unique_name('create_each_block'),
16584 type: 'each',
16585 // @ts-ignore todo: probably error
16586 key: node.key,
16587 bindings: new Map(block.bindings)
16588 });
16589 // TODO this seems messy
16590 this.block.has_animation = this.node.has_animation;
16591 this.index_name = this.node.index
16592 ? { type: 'Identifier', name: this.node.index }
16593 : renderer.component.get_unique_name(`${this.node.context}_index`);
16594 const fixed_length = node.expression.node.type === 'ArrayExpression' &&
16595 node.expression.node.elements.every(element => element.type !== 'SpreadElement')
16596 ? node.expression.node.elements.length
16597 : null;
16598 // hack the sourcemap, so that if data is missing the bug
16599 // is easy to find
16600 let c = this.node.start + 2;
16601 while (renderer.component.source[c] !== 'e')
16602 c += 1;
16603 const start = renderer.component.locate(c);
16604 const end = { line: start.line, column: start.column + 4 };
16605 const length = {
16606 type: 'Identifier',
16607 name: 'length',
16608 loc: { start, end }
16609 };
16610 const each_block_value = renderer.component.get_unique_name(`${this.var.name}_value`);
16611 const iterations = block.get_unique_name(`${this.var.name}_blocks`);
16612 renderer.add_to_context(each_block_value.name, true);
16613 renderer.add_to_context(this.index_name.name, true);
16614 this.vars = {
16615 create_each_block: this.block.name,
16616 each_block_value,
16617 get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`),
16618 iterations,
16619 // optimisation for array literal
16620 fixed_length,
16621 data_length: fixed_length === null ? x `${each_block_value}.${length}` : fixed_length,
16622 view_length: fixed_length === null ? x `${iterations}.length` : fixed_length
16623 };
16624 const store = node.expression.node.type === 'Identifier' &&
16625 node.expression.node.name[0] === '$'
16626 ? node.expression.node.name.slice(1)
16627 : null;
16628 node.contexts.forEach(prop => {
16629 this.block.bindings.set(prop.key.name, {
16630 object: this.vars.each_block_value,
16631 property: this.index_name,
16632 modifier: prop.modifier,
16633 snippet: prop.modifier(x `${this.vars.each_block_value}[${this.index_name}]`),
16634 store,
16635 tail: prop.modifier(x `[${this.index_name}]`)
16636 });
16637 });
16638 if (this.node.index) {
16639 this.block.get_unique_name(this.node.index); // this prevents name collisions (#1254)
16640 }
16641 renderer.blocks.push(this.block);
16642 this.fragment = new FragmentWrapper(renderer, this.block, node.children, this, strip_whitespace, next_sibling);
16643 if (this.node.else) {
16644 this.else = new ElseBlockWrapper(renderer, block, this, this.node.else, strip_whitespace, next_sibling);
16645 renderer.blocks.push(this.else.block);
16646 if (this.else.is_dynamic) {
16647 this.block.add_dependencies(this.else.block.dependencies);
16648 }
16649 }
16650 block.add_dependencies(this.block.dependencies);
16651 if (this.block.has_outros || (this.else && this.else.block.has_outros)) {
16652 block.add_outro();
16653 }
16654 }
16655 render(block, parent_node, parent_nodes) {
16656 if (this.fragment.nodes.length === 0)
16657 return;
16658 const { renderer } = this;
16659 const { component } = renderer;
16660 const needs_anchor = this.next
16661 ? !this.next.is_dom_node() :
16662 !parent_node || !this.parent.is_dom_node();
16663 this.context_props = this.node.contexts.map(prop => b `child_ctx[${renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x `list[i]`)};`);
16664 if (this.node.has_binding)
16665 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`);
16666 if (this.node.has_binding || this.node.has_index_binding || this.node.index)
16667 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`);
16668 const snippet = this.node.expression.manipulate(block);
16669 block.chunks.init.push(b `let ${this.vars.each_block_value} = ${snippet};`);
16670 if (this.renderer.options.dev) {
16671 block.chunks.init.push(b `@validate_each_argument(${this.vars.each_block_value});`);
16672 }
16673 // TODO which is better — Object.create(array) or array.slice()?
16674 renderer.blocks.push(b `
16675 function ${this.vars.get_each_context}(#ctx, list, i) {
16676 const child_ctx = #ctx.slice();
16677 ${this.context_props}
16678 return child_ctx;
16679 }
16680 `);
16681 const initial_anchor_node = { type: 'Identifier', name: parent_node ? 'null' : '#anchor' };
16682 const initial_mount_node = parent_node || { type: 'Identifier', name: '#target' };
16683 const update_anchor_node = needs_anchor
16684 ? block.get_unique_name(`${this.var.name}_anchor`)
16685 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16686 const update_mount_node = this.get_update_mount_node(update_anchor_node);
16687 const args = {
16688 block,
16689 parent_node,
16690 parent_nodes,
16691 snippet,
16692 initial_anchor_node,
16693 initial_mount_node,
16694 update_anchor_node,
16695 update_mount_node
16696 };
16697 const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
16698 this.node.expression.dynamic_dependencies().forEach((dependency) => {
16699 all_dependencies.add(dependency);
16700 });
16701 this.dependencies = all_dependencies;
16702 if (this.node.key) {
16703 this.render_keyed(args);
16704 }
16705 else {
16706 this.render_unkeyed(args);
16707 }
16708 if (this.block.has_intro_method || this.block.has_outro_method) {
16709 block.chunks.intro.push(b `
16710 for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) {
16711 @transition_in(${this.vars.iterations}[#i]);
16712 }
16713 `);
16714 }
16715 if (needs_anchor) {
16716 block.add_element(update_anchor_node, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16717 }
16718 if (this.else) {
16719 const each_block_else = component.get_unique_name(`${this.var.name}_else`);
16720 block.chunks.init.push(b `let ${each_block_else} = null;`);
16721 // TODO neaten this up... will end up with an empty line in the block
16722 block.chunks.init.push(b `
16723 if (!${this.vars.data_length}) {
16724 ${each_block_else} = ${this.else.block.name}(#ctx);
16725 }
16726 `);
16727 block.chunks.create.push(b `
16728 if (${each_block_else}) {
16729 ${each_block_else}.c();
16730 }
16731 `);
16732 if (this.renderer.options.hydratable) {
16733 block.chunks.claim.push(b `
16734 if (${each_block_else}) {
16735 ${each_block_else}.l(${parent_nodes});
16736 }
16737 `);
16738 }
16739 block.chunks.mount.push(b `
16740 if (${each_block_else}) {
16741 ${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node});
16742 }
16743 `);
16744 const has_transitions = !!(this.else.block.has_intro_method || this.else.block.has_outro_method);
16745 const destroy_block_else = this.else.block.has_outro_method
16746 ? b `
16747 @group_outros();
16748 @transition_out(${each_block_else}, 1, 1, () => {
16749 ${each_block_else} = null;
16750 });
16751 @check_outros();`
16752 : b `
16753 ${each_block_else}.d(1);
16754 ${each_block_else} = null;`;
16755 if (this.else.block.has_update_method) {
16756 this.updates.push(b `
16757 if (!${this.vars.data_length} && ${each_block_else}) {
16758 ${each_block_else}.p(#ctx, #dirty);
16759 } else if (!${this.vars.data_length}) {
16760 ${each_block_else} = ${this.else.block.name}(#ctx);
16761 ${each_block_else}.c();
16762 ${has_transitions && b `@transition_in(${each_block_else}, 1);`}
16763 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16764 } else if (${each_block_else}) {
16765 ${destroy_block_else};
16766 }
16767 `);
16768 }
16769 else {
16770 this.updates.push(b `
16771 if (${this.vars.data_length}) {
16772 if (${each_block_else}) {
16773 ${destroy_block_else};
16774 }
16775 } else if (!${each_block_else}) {
16776 ${each_block_else} = ${this.else.block.name}(#ctx);
16777 ${each_block_else}.c();
16778 ${has_transitions && b `@transition_in(${each_block_else}, 1);`}
16779 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16780 }
16781 `);
16782 }
16783 block.chunks.destroy.push(b `
16784 if (${each_block_else}) ${each_block_else}.d(${parent_node ? '' : 'detaching'});
16785 `);
16786 }
16787 if (this.updates.length) {
16788 block.chunks.update.push(b `
16789 if (${block.renderer.dirty(Array.from(all_dependencies))}) {
16790 ${this.updates}
16791 }
16792 `);
16793 }
16794 this.fragment.render(this.block, null, x `#nodes`);
16795 if (this.else) {
16796 this.else.fragment.render(this.else.block, null, x `#nodes`);
16797 }
16798 }
16799 render_keyed({ block, parent_node, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
16800 const { create_each_block, iterations, data_length, view_length } = this.vars;
16801 const get_key = block.get_unique_name('get_key');
16802 const lookup = block.get_unique_name(`${this.var.name}_lookup`);
16803 block.add_variable(iterations, x `[]`);
16804 block.add_variable(lookup, x `new @_Map()`);
16805 if (this.fragment.nodes[0].is_dom_node()) {
16806 this.block.first = this.fragment.nodes[0].var;
16807 }
16808 else {
16809 this.block.first = this.block.get_unique_name('first');
16810 this.block.add_element(this.block.first, x `@empty()`, parent_nodes && x `@empty()`, null);
16811 }
16812 block.chunks.init.push(b `
16813 const ${get_key} = #ctx => ${this.node.key.manipulate(block)};
16814
16815 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
16816 for (let #i = 0; #i < ${data_length}; #i += 1) {
16817 let child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
16818 let key = ${get_key}(child_ctx);
16819 ${lookup}.set(key, ${iterations}[#i] = ${create_each_block}(key, child_ctx));
16820 }
16821 `);
16822 block.chunks.create.push(b `
16823 for (let #i = 0; #i < ${view_length}; #i += 1) {
16824 ${iterations}[#i].c();
16825 }
16826 `);
16827 if (parent_nodes && this.renderer.options.hydratable) {
16828 block.chunks.claim.push(b `
16829 for (let #i = 0; #i < ${view_length}; #i += 1) {
16830 ${iterations}[#i].l(${parent_nodes});
16831 }
16832 `);
16833 }
16834 block.chunks.mount.push(b `
16835 for (let #i = 0; #i < ${view_length}; #i += 1) {
16836 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
16837 }
16838 `);
16839 const dynamic = this.block.has_update_method;
16840 const destroy = this.node.has_animation
16841 ? (this.block.has_outros
16842 ? `@fix_and_outro_and_destroy_block`
16843 : `@fix_and_destroy_block`)
16844 : this.block.has_outros
16845 ? `@outro_and_destroy_block`
16846 : `@destroy_block`;
16847 if (this.dependencies.size) {
16848 this.updates.push(b `
16849 const ${this.vars.each_block_value} = ${snippet};
16850 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
16851
16852 ${this.block.has_outros && b `@group_outros();`}
16853 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`}
16854 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
16855 ${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});
16856 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
16857 ${this.block.has_outros && b `@check_outros();`}
16858 `);
16859 }
16860 if (this.block.has_outros) {
16861 block.chunks.outro.push(b `
16862 for (let #i = 0; #i < ${view_length}; #i += 1) {
16863 @transition_out(${iterations}[#i]);
16864 }
16865 `);
16866 }
16867 block.chunks.destroy.push(b `
16868 for (let #i = 0; #i < ${view_length}; #i += 1) {
16869 ${iterations}[#i].d(${parent_node ? null : 'detaching'});
16870 }
16871 `);
16872 }
16873 render_unkeyed({ block, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
16874 const { create_each_block, iterations, fixed_length, data_length, view_length } = this.vars;
16875 block.chunks.init.push(b `
16876 let ${iterations} = [];
16877
16878 for (let #i = 0; #i < ${data_length}; #i += 1) {
16879 ${iterations}[#i] = ${create_each_block}(${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i));
16880 }
16881 `);
16882 block.chunks.create.push(b `
16883 for (let #i = 0; #i < ${view_length}; #i += 1) {
16884 ${iterations}[#i].c();
16885 }
16886 `);
16887 if (parent_nodes && this.renderer.options.hydratable) {
16888 block.chunks.claim.push(b `
16889 for (let #i = 0; #i < ${view_length}; #i += 1) {
16890 ${iterations}[#i].l(${parent_nodes});
16891 }
16892 `);
16893 }
16894 block.chunks.mount.push(b `
16895 for (let #i = 0; #i < ${view_length}; #i += 1) {
16896 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
16897 }
16898 `);
16899 if (this.dependencies.size) {
16900 const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
16901 const for_loop_body = this.block.has_update_method
16902 ? b `
16903 if (${iterations}[#i]) {
16904 ${iterations}[#i].p(child_ctx, #dirty);
16905 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
16906 } else {
16907 ${iterations}[#i] = ${create_each_block}(child_ctx);
16908 ${iterations}[#i].c();
16909 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
16910 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16911 }
16912 `
16913 : has_transitions
16914 ? b `
16915 if (${iterations}[#i]) {
16916 @transition_in(${this.vars.iterations}[#i], 1);
16917 } else {
16918 ${iterations}[#i] = ${create_each_block}(child_ctx);
16919 ${iterations}[#i].c();
16920 @transition_in(${this.vars.iterations}[#i], 1);
16921 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16922 }
16923 `
16924 : b `
16925 if (!${iterations}[#i]) {
16926 ${iterations}[#i] = ${create_each_block}(child_ctx);
16927 ${iterations}[#i].c();
16928 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16929 }
16930 `;
16931 const start = this.block.has_update_method ? 0 : `#old_length`;
16932 let remove_old_blocks;
16933 if (this.block.has_outros) {
16934 const out = block.get_unique_name('out');
16935 block.chunks.init.push(b `
16936 const ${out} = i => @transition_out(${iterations}[i], 1, 1, () => {
16937 ${iterations}[i] = null;
16938 });
16939 `);
16940 remove_old_blocks = b `
16941 @group_outros();
16942 for (#i = ${data_length}; #i < ${view_length}; #i += 1) {
16943 ${out}(#i);
16944 }
16945 @check_outros();
16946 `;
16947 }
16948 else {
16949 remove_old_blocks = b `
16950 for (${this.block.has_update_method ? null : x `#i = ${data_length}`}; #i < ${this.block.has_update_method ? view_length : '#old_length'}; #i += 1) {
16951 ${iterations}[#i].d(1);
16952 }
16953 ${!fixed_length && b `${view_length} = ${data_length};`}
16954 `;
16955 }
16956 // We declare `i` as block scoped here, as the `remove_old_blocks` code
16957 // may rely on continuing where this iteration stopped.
16958 const update = b `
16959 ${!this.block.has_update_method && b `const #old_length = ${this.vars.each_block_value}.length;`}
16960 ${this.vars.each_block_value} = ${snippet};
16961 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
16962
16963 let #i;
16964 for (#i = ${start}; #i < ${data_length}; #i += 1) {
16965 const child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
16966
16967 ${for_loop_body}
16968 }
16969
16970 ${remove_old_blocks}
16971 `;
16972 this.updates.push(update);
16973 }
16974 if (this.block.has_outros) {
16975 block.chunks.outro.push(b `
16976 ${iterations} = ${iterations}.filter(@_Boolean);
16977 for (let #i = 0; #i < ${view_length}; #i += 1) {
16978 @transition_out(${iterations}[#i]);
16979 }
16980 `);
16981 }
16982 block.chunks.destroy.push(b `@destroy_each(${iterations}, detaching);`);
16983 }
16984 }
16985
16986 function string_literal(data) {
16987 return {
16988 type: 'Literal',
16989 value: data
16990 };
16991 }
16992 const escaped = {
16993 '"': '&quot;',
16994 "'": '&#39;',
16995 '&': '&amp;',
16996 '<': '&lt;',
16997 '>': '&gt;',
16998 };
16999 function escape_html(html) {
17000 return String(html).replace(/["'&<>]/g, match => escaped[match]);
17001 }
17002 function escape_template(str) {
17003 return str.replace(/(\${|`|\\)/g, '\\$1');
17004 }
17005
17006 class TextWrapper extends Wrapper {
17007 constructor(renderer, block, parent, node, data) {
17008 super(renderer, block, parent, node);
17009 this.skip = this.node.should_skip();
17010 this.data = data;
17011 this.var = (this.skip ? null : x `t`);
17012 }
17013 use_space() {
17014 if (this.renderer.component.component_options.preserveWhitespace)
17015 return false;
17016 if (/[\S\u00A0]/.test(this.data))
17017 return false;
17018 let node = this.parent && this.parent.node;
17019 while (node) {
17020 if (node.type === 'Element' && node.name === 'pre') {
17021 return false;
17022 }
17023 node = node.parent;
17024 }
17025 return true;
17026 }
17027 render(block, parent_node, parent_nodes) {
17028 if (this.skip)
17029 return;
17030 const use_space = this.use_space();
17031 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);
17032 }
17033 }
17034
17035 const 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(' ');
17036 const svg_attribute_lookup = new Map();
17037 svg_attributes.forEach(name => {
17038 svg_attribute_lookup.set(name.toLowerCase(), name);
17039 });
17040 function fix_attribute_casing(name) {
17041 name = name.toLowerCase();
17042 return svg_attribute_lookup.get(name) || name;
17043 }
17044
17045 const html = 'http://www.w3.org/1999/xhtml';
17046 const mathml = 'http://www.w3.org/1998/Math/MathML';
17047 const svg = 'http://www.w3.org/2000/svg';
17048 const xlink = 'http://www.w3.org/1999/xlink';
17049 const xml = 'http://www.w3.org/XML/1998/namespace';
17050 const xmlns = 'http://www.w3.org/2000/xmlns';
17051 const valid_namespaces = [
17052 'html',
17053 'mathml',
17054 'svg',
17055 'xlink',
17056 'xml',
17057 'xmlns',
17058 html,
17059 mathml,
17060 svg,
17061 xlink,
17062 xml,
17063 xmlns,
17064 ];
17065 const namespaces = { html, mathml, svg, xlink, xml, xmlns };
17066
17067 function handle_select_value_binding(attr, dependencies) {
17068 const { parent } = attr;
17069 if (parent.node.name === "select") {
17070 parent.select_binding_dependencies = dependencies;
17071 dependencies.forEach((prop) => {
17072 parent.renderer.component.indirect_dependencies.set(prop, new Set());
17073 });
17074 }
17075 }
17076
17077 class BaseAttributeWrapper {
17078 constructor(parent, block, node) {
17079 this.node = node;
17080 this.parent = parent;
17081 if (node.dependencies.size > 0) {
17082 parent.cannot_use_innerhtml();
17083 parent.not_static_content();
17084 block.add_dependencies(node.dependencies);
17085 }
17086 }
17087 render(_block) { }
17088 }
17089 class AttributeWrapper extends BaseAttributeWrapper {
17090 constructor(parent, block, node) {
17091 super(parent, block, node);
17092 if (node.dependencies.size > 0) {
17093 // special case — <option value={foo}> — see below
17094 if (this.parent.node.name === 'option' && node.name === 'value') {
17095 let select = this.parent;
17096 while (select && (select.node.type !== 'Element' || select.node.name !== 'select'))
17097 // @ts-ignore todo: doublecheck this, but looks to be correct
17098 select = select.parent;
17099 if (select && select.select_binding_dependencies) {
17100 select.select_binding_dependencies.forEach(prop => {
17101 this.node.dependencies.forEach((dependency) => {
17102 this.parent.renderer.component.indirect_dependencies.get(prop).add(dependency);
17103 });
17104 });
17105 }
17106 }
17107 if (node.name === 'value') {
17108 handle_select_value_binding(this, node.dependencies);
17109 }
17110 }
17111 this.name = fix_attribute_casing(this.node.name);
17112 this.metadata = this.get_metadata();
17113 this.is_indirectly_bound_value = is_indirectly_bound_value(this);
17114 this.property_name = this.is_indirectly_bound_value
17115 ? '__value'
17116 : this.metadata && this.metadata.property_name;
17117 this.is_src = this.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
17118 this.is_select_value_attribute = this.name === 'value' && this.parent.node.name === 'select';
17119 this.is_input_value = this.name === 'value' && this.parent.node.name === 'input';
17120 this.should_cache = should_cache(this);
17121 }
17122 render(block) {
17123 const element = this.parent;
17124 const { name, property_name, should_cache, is_indirectly_bound_value } = this;
17125 // xlink is a special case... we could maybe extend this to generic
17126 // namespaced attributes but I'm not sure that's applicable in
17127 // HTML5?
17128 const method = /-/.test(element.node.name)
17129 ? '@set_custom_element_data'
17130 : name.slice(0, 6) === 'xlink:'
17131 ? '@xlink_attr'
17132 : '@attr';
17133 const is_legacy_input_type = element.renderer.component.compile_options.legacy && name === 'type' && this.parent.node.name === 'input';
17134 const dependencies = this.get_dependencies();
17135 const value = this.get_value(block);
17136 let updater;
17137 const init = this.get_init(block, value);
17138 if (is_legacy_input_type) {
17139 block.chunks.hydrate.push(b `@set_input_type(${element.var}, ${init});`);
17140 updater = b `@set_input_type(${element.var}, ${should_cache ? this.last : value});`;
17141 }
17142 else if (this.is_select_value_attribute) {
17143 // annoying special case
17144 const is_multiple_select = element.node.get_static_attribute_value('multiple');
17145 if (is_multiple_select) {
17146 updater = b `@select_options(${element.var}, ${value});`;
17147 }
17148 else {
17149 updater = b `@select_option(${element.var}, ${value});`;
17150 }
17151 block.chunks.mount.push(b `
17152 ${updater}
17153 `);
17154 }
17155 else if (this.is_src) {
17156 block.chunks.hydrate.push(b `if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${this.last});`);
17157 updater = b `${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
17158 }
17159 else if (property_name) {
17160 block.chunks.hydrate.push(b `${element.var}.${property_name} = ${init};`);
17161 updater = block.renderer.options.dev
17162 ? b `@prop_dev(${element.var}, "${property_name}", ${should_cache ? this.last : value});`
17163 : b `${element.var}.${property_name} = ${should_cache ? this.last : value};`;
17164 }
17165 else {
17166 block.chunks.hydrate.push(b `${method}(${element.var}, "${name}", ${init});`);
17167 updater = b `${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
17168 }
17169 if (is_indirectly_bound_value) {
17170 const update_value = b `${element.var}.value = ${element.var}.__value;`;
17171 block.chunks.hydrate.push(update_value);
17172 updater = b `
17173 ${updater}
17174 ${update_value};
17175 `;
17176 }
17177 if (dependencies.length > 0) {
17178 const condition = this.get_dom_update_conditions(block, block.renderer.dirty(dependencies));
17179 block.chunks.update.push(b `
17180 if (${condition}) {
17181 ${updater}
17182 }`);
17183 }
17184 // special case – autofocus. has to be handled in a bit of a weird way
17185 if (this.node.is_true && name === 'autofocus') {
17186 block.autofocus = element.var;
17187 }
17188 }
17189 get_init(block, value) {
17190 this.last = this.should_cache && block.get_unique_name(`${this.parent.var.name}_${this.name.replace(/[^a-zA-Z_$]/g, '_')}_value`);
17191 if (this.should_cache)
17192 block.add_variable(this.last);
17193 return this.should_cache ? x `${this.last} = ${value}` : value;
17194 }
17195 get_dom_update_conditions(block, dependency_condition) {
17196 const { property_name, should_cache, last } = this;
17197 const element = this.parent;
17198 const value = this.get_value(block);
17199 let condition = dependency_condition;
17200 if (should_cache) {
17201 condition = this.is_src
17202 ? x `${condition} && (${element.var}.src !== (${last} = ${value}))`
17203 : x `${condition} && (${last} !== (${last} = ${value}))`;
17204 }
17205 if (this.is_input_value) {
17206 const type = element.node.get_static_attribute_value('type');
17207 if (type === null || type === "" || type === "text" || type === "email" || type === "password") {
17208 condition = x `${condition} && ${element.var}.${property_name} !== ${should_cache ? last : value}`;
17209 }
17210 }
17211 if (block.has_outros) {
17212 condition = x `!#current || ${condition}`;
17213 }
17214 return condition;
17215 }
17216 get_dependencies() {
17217 const node_dependencies = this.node.get_dependencies();
17218 const dependencies = new Set(node_dependencies);
17219 node_dependencies.forEach((prop) => {
17220 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17221 if (indirect_dependencies) {
17222 indirect_dependencies.forEach(indirect_dependency => {
17223 dependencies.add(indirect_dependency);
17224 });
17225 }
17226 });
17227 return Array.from(dependencies);
17228 }
17229 get_metadata() {
17230 if (this.parent.node.namespace)
17231 return null;
17232 const metadata = attribute_lookup[this.name];
17233 if (metadata && metadata.applies_to && !metadata.applies_to.includes(this.parent.node.name))
17234 return null;
17235 return metadata;
17236 }
17237 get_value(block) {
17238 if (this.node.is_true) {
17239 if (this.metadata && boolean_attribute.has(this.metadata.property_name.toLowerCase())) {
17240 return x `true`;
17241 }
17242 return x `""`;
17243 }
17244 if (this.node.chunks.length === 0)
17245 return x `""`;
17246 // TODO some of this code is repeated in Tag.ts — would be good to
17247 // DRY it out if that's possible without introducing crazy indirection
17248 if (this.node.chunks.length === 1) {
17249 return this.node.chunks[0].type === 'Text'
17250 ? string_literal(this.node.chunks[0].data)
17251 : this.node.chunks[0].manipulate(block);
17252 }
17253 let value = this.node.name === 'class'
17254 ? this.get_class_name_text(block)
17255 : this.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17256 // '{foo} {bar}' — treat as string concatenation
17257 if (this.node.chunks[0].type !== 'Text') {
17258 value = x `"" + ${value}`;
17259 }
17260 return value;
17261 }
17262 get_class_name_text(block) {
17263 const scoped_css = this.node.chunks.some((chunk) => chunk.synthetic);
17264 const rendered = this.render_chunks(block);
17265 if (scoped_css && rendered.length === 2) {
17266 // we have a situation like class={possiblyUndefined}
17267 rendered[0] = x `@null_to_empty(${rendered[0]})`;
17268 }
17269 return rendered.reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17270 }
17271 render_chunks(block) {
17272 return this.node.chunks.map((chunk) => {
17273 if (chunk.type === 'Text') {
17274 return string_literal(chunk.data);
17275 }
17276 return chunk.manipulate(block);
17277 });
17278 }
17279 stringify() {
17280 if (this.node.is_true)
17281 return '';
17282 const value = this.node.chunks;
17283 if (value.length === 0)
17284 return `=""`;
17285 return `="${value.map(chunk => {
17286 return chunk.type === 'Text'
17287 ? chunk.data.replace(/"/g, '\\"')
17288 : `\${${chunk.manipulate()}}`;
17289 }).join('')}"`;
17290 }
17291 }
17292 // source: https://html.spec.whatwg.org/multipage/indices.html
17293 const attribute_lookup = {
17294 allowfullscreen: { property_name: 'allowFullscreen', applies_to: ['iframe'] },
17295 allowpaymentrequest: { property_name: 'allowPaymentRequest', applies_to: ['iframe'] },
17296 async: { applies_to: ['script'] },
17297 autofocus: { applies_to: ['button', 'input', 'keygen', 'select', 'textarea'] },
17298 autoplay: { applies_to: ['audio', 'video'] },
17299 checked: { applies_to: ['input'] },
17300 controls: { applies_to: ['audio', 'video'] },
17301 default: { applies_to: ['track'] },
17302 defer: { applies_to: ['script'] },
17303 disabled: {
17304 applies_to: [
17305 'button',
17306 'fieldset',
17307 'input',
17308 'keygen',
17309 'optgroup',
17310 'option',
17311 'select',
17312 'textarea',
17313 ],
17314 },
17315 formnovalidate: { property_name: 'formNoValidate', applies_to: ['button', 'input'] },
17316 hidden: {},
17317 indeterminate: { applies_to: ['input'] },
17318 ismap: { property_name: 'isMap', applies_to: ['img'] },
17319 loop: { applies_to: ['audio', 'bgsound', 'video'] },
17320 multiple: { applies_to: ['input', 'select'] },
17321 muted: { applies_to: ['audio', 'video'] },
17322 nomodule: { property_name: 'noModule', applies_to: ['script'] },
17323 novalidate: { property_name: 'noValidate', applies_to: ['form'] },
17324 open: { applies_to: ['details', 'dialog'] },
17325 playsinline: { property_name: 'playsInline', applies_to: ['video'] },
17326 readonly: { property_name: 'readOnly', applies_to: ['input', 'textarea'] },
17327 required: { applies_to: ['input', 'select', 'textarea'] },
17328 reversed: { applies_to: ['ol'] },
17329 selected: { applies_to: ['option'] },
17330 value: {
17331 applies_to: [
17332 'button',
17333 'option',
17334 'input',
17335 'li',
17336 'meter',
17337 'progress',
17338 'param',
17339 'select',
17340 'textarea',
17341 ],
17342 },
17343 };
17344 Object.keys(attribute_lookup).forEach(name => {
17345 const metadata = attribute_lookup[name];
17346 if (!metadata.property_name)
17347 metadata.property_name = name;
17348 });
17349 // source: https://html.spec.whatwg.org/multipage/indices.html
17350 const boolean_attribute = new Set([
17351 'allowfullscreen',
17352 'allowpaymentrequest',
17353 'async',
17354 'autofocus',
17355 'autoplay',
17356 'checked',
17357 'controls',
17358 'default',
17359 'defer',
17360 'disabled',
17361 'formnovalidate',
17362 'hidden',
17363 'ismap',
17364 'itemscope',
17365 'loop',
17366 'multiple',
17367 'muted',
17368 'nomodule',
17369 'novalidate',
17370 'open',
17371 'playsinline',
17372 'readonly',
17373 'required',
17374 'reversed',
17375 'selected'
17376 ]);
17377 function should_cache(attribute) {
17378 return attribute.is_src || attribute.node.should_cache();
17379 }
17380 function is_indirectly_bound_value(attribute) {
17381 const element = attribute.parent;
17382 return attribute.name === 'value' &&
17383 (element.node.name === 'option' || // TODO check it's actually bound
17384 (element.node.name === 'input' &&
17385 element.node.bindings.some((binding) => /checked|group/.test(binding.name))));
17386 }
17387
17388 class StyleAttributeWrapper extends AttributeWrapper {
17389 render(block) {
17390 const style_props = optimize_style(this.node.chunks);
17391 if (!style_props)
17392 return super.render(block);
17393 style_props.forEach((prop) => {
17394 let value;
17395 if (is_dynamic(prop.value)) {
17396 const prop_dependencies = new Set();
17397 value = prop.value
17398 .map(chunk => {
17399 if (chunk.type === 'Text') {
17400 return string_literal(chunk.data);
17401 }
17402 else {
17403 add_to_set(prop_dependencies, chunk.dynamic_dependencies());
17404 return chunk.manipulate(block);
17405 }
17406 })
17407 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17408 // TODO is this necessary? style.setProperty always treats value as string, no?
17409 // if (prop.value.length === 1 || prop.value[0].type !== 'Text') {
17410 // value = x`"" + ${value}`;
17411 // }
17412 if (prop_dependencies.size) {
17413 let condition = block.renderer.dirty(Array.from(prop_dependencies));
17414 if (block.has_outros) {
17415 condition = x `!#current || ${condition}`;
17416 }
17417 const update = b `
17418 if (${condition}) {
17419 @set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});
17420 }`;
17421 block.chunks.update.push(update);
17422 }
17423 }
17424 else {
17425 value = string_literal(prop.value[0].data);
17426 }
17427 block.chunks.hydrate.push(b `@set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});`);
17428 });
17429 }
17430 }
17431 function optimize_style(value) {
17432 const props = [];
17433 let chunks = value.slice();
17434 while (chunks.length) {
17435 const chunk = chunks[0];
17436 if (chunk.type !== 'Text')
17437 return null;
17438 const key_match = /^\s*([\w-]+):\s*/.exec(chunk.data);
17439 if (!key_match)
17440 return null;
17441 const key = key_match[1];
17442 const offset = key_match.index + key_match[0].length;
17443 const remaining_data = chunk.data.slice(offset);
17444 if (remaining_data) {
17445 chunks[0] = {
17446 start: chunk.start + offset,
17447 end: chunk.end,
17448 type: 'Text',
17449 data: remaining_data
17450 };
17451 }
17452 else {
17453 chunks.shift();
17454 }
17455 const result = get_style_value(chunks);
17456 props.push({ key, value: result.value, important: result.important });
17457 chunks = result.chunks;
17458 }
17459 return props;
17460 }
17461 function get_style_value(chunks) {
17462 const value = [];
17463 let in_url = false;
17464 let quote_mark = null;
17465 let escaped = false;
17466 let closed = false;
17467 while (chunks.length && !closed) {
17468 const chunk = chunks.shift();
17469 if (chunk.type === 'Text') {
17470 let c = 0;
17471 while (c < chunk.data.length) {
17472 const char = chunk.data[c];
17473 if (escaped) {
17474 escaped = false;
17475 }
17476 else if (char === '\\') {
17477 escaped = true;
17478 }
17479 else if (char === quote_mark) {
17480 quote_mark = null;
17481 }
17482 else if (char === '"' || char === "'") {
17483 quote_mark = char;
17484 }
17485 else if (char === ')' && in_url) {
17486 in_url = false;
17487 }
17488 else if (char === 'u' && chunk.data.slice(c, c + 4) === 'url(') {
17489 in_url = true;
17490 }
17491 else if (char === ';' && !in_url && !quote_mark) {
17492 closed = true;
17493 break;
17494 }
17495 c += 1;
17496 }
17497 if (c > 0) {
17498 value.push({
17499 type: 'Text',
17500 start: chunk.start,
17501 end: chunk.start + c,
17502 data: chunk.data.slice(0, c)
17503 });
17504 }
17505 while (/[;\s]/.test(chunk.data[c]))
17506 c += 1;
17507 const remaining_data = chunk.data.slice(c);
17508 if (remaining_data) {
17509 chunks.unshift({
17510 start: chunk.start + c,
17511 end: chunk.end,
17512 type: 'Text',
17513 data: remaining_data
17514 });
17515 break;
17516 }
17517 }
17518 else {
17519 value.push(chunk);
17520 }
17521 }
17522 let important = false;
17523 const last_chunk = value[value.length - 1];
17524 if (last_chunk && last_chunk.type === 'Text' && /\s*!important\s*$/.test(last_chunk.data)) {
17525 important = true;
17526 last_chunk.data = last_chunk.data.replace(/\s*!important\s*$/, '');
17527 if (!last_chunk.data)
17528 value.pop();
17529 }
17530 return {
17531 chunks,
17532 value,
17533 important
17534 };
17535 }
17536 function is_dynamic(value) {
17537 return value.length > 1 || value[0].type !== 'Text';
17538 }
17539
17540 class SpreadAttributeWrapper extends BaseAttributeWrapper {
17541 }
17542
17543 function get_object(node) {
17544 while (node.type === 'MemberExpression')
17545 node = node.object;
17546 return node;
17547 }
17548
17549 function replace_object(node, replacement) {
17550 if (node.type === 'Identifier')
17551 return replacement;
17552 const ancestor = node;
17553 let parent;
17554 while (node.type === 'MemberExpression') {
17555 parent = node;
17556 node = node.object;
17557 }
17558 parent.object = replacement;
17559 return ancestor;
17560 }
17561
17562 function flatten_reference(node) {
17563 const nodes = [];
17564 const parts = [];
17565 while (node.type === 'MemberExpression') {
17566 nodes.unshift(node.property);
17567 if (!node.computed) {
17568 parts.unshift(node.property.name);
17569 }
17570 else {
17571 const computed_property = to_string$1(node.property);
17572 if (computed_property) {
17573 parts.unshift(`[${computed_property}]`);
17574 }
17575 }
17576 node = node.object;
17577 }
17578 const name = node.type === 'Identifier'
17579 ? node.name
17580 : node.type === 'ThisExpression' ? 'this' : null;
17581 nodes.unshift(node);
17582 parts.unshift(name);
17583 return { name, nodes, parts };
17584 }
17585 function to_string$1(node) {
17586 switch (node.type) {
17587 case 'Literal':
17588 return String(node.value);
17589 case 'Identifier':
17590 return node.name;
17591 }
17592 }
17593
17594 function mark_each_block_bindings(parent, binding) {
17595 // we need to ensure that the each block creates a context including
17596 // the list and the index, if they're not otherwise referenced
17597 binding.expression.references.forEach(name => {
17598 const each_block = parent.node.scope.get_owner(name);
17599 if (each_block) {
17600 each_block.has_binding = true;
17601 }
17602 });
17603 if (binding.name === "group") {
17604 // for `<input bind:group={} >`, we make sure that all the each blocks creates context with `index`
17605 for (const name of binding.expression.contextual_dependencies) {
17606 const each_block = parent.node.scope.get_owner(name);
17607 each_block.has_index_binding = true;
17608 }
17609 }
17610 }
17611
17612 class BindingWrapper {
17613 constructor(block, node, parent) {
17614 this.node = node;
17615 this.parent = parent;
17616 const { dependencies } = this.node.expression;
17617 block.add_dependencies(dependencies);
17618 // TODO does this also apply to e.g. `<input type='checkbox' bind:group='foo'>`?
17619 handle_select_value_binding(this, dependencies);
17620 if (node.is_contextual) {
17621 mark_each_block_bindings(this.parent, this.node);
17622 }
17623 this.object = get_object(this.node.expression.node).name;
17624 // view to model
17625 this.handler = get_event_handler(this, parent.renderer, block, this.object, this.node.raw_expression);
17626 this.snippet = this.node.expression.manipulate(block);
17627 this.is_readonly = this.node.is_readonly;
17628 this.needs_lock = this.node.name === 'currentTime'; // TODO others?
17629 }
17630 get_dependencies() {
17631 const dependencies = new Set(this.node.expression.dependencies);
17632 this.node.expression.dependencies.forEach((prop) => {
17633 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17634 if (indirect_dependencies) {
17635 indirect_dependencies.forEach(indirect_dependency => {
17636 dependencies.add(indirect_dependency);
17637 });
17638 }
17639 });
17640 return dependencies;
17641 }
17642 is_readonly_media_attribute() {
17643 return this.node.is_readonly_media_attribute();
17644 }
17645 render(block, lock) {
17646 if (this.is_readonly)
17647 return;
17648 const { parent } = this;
17649 const update_conditions = this.needs_lock ? [x `!${lock}`] : [];
17650 const mount_conditions = [];
17651 const dependency_array = Array.from(this.get_dependencies());
17652 if (dependency_array.length > 0) {
17653 update_conditions.push(block.renderer.dirty(dependency_array));
17654 }
17655 if (parent.node.name === "input") {
17656 const type = parent.node.get_static_attribute_value("type");
17657 if (type === null ||
17658 type === "" ||
17659 type === "text" ||
17660 type === "email" ||
17661 type === "password") {
17662 update_conditions.push(x `${parent.var}.${this.node.name} !== ${this.snippet}`);
17663 }
17664 else if (type === "number") {
17665 update_conditions.push(x `@to_number(${parent.var}.${this.node.name}) !== ${this.snippet}`);
17666 }
17667 }
17668 // model to view
17669 let update_dom = get_dom_updater(parent, this);
17670 let mount_dom = update_dom;
17671 // special cases
17672 switch (this.node.name) {
17673 case 'group':
17674 {
17675 const { binding_group, is_context, contexts, index } = get_binding_group(parent.renderer, this.node, block);
17676 block.renderer.add_to_context(`$$binding_groups`);
17677 if (is_context) {
17678 if (contexts.length > 1) {
17679 let binding_group = x `${block.renderer.reference('$$binding_groups')}[${index}]`;
17680 for (const name of contexts.slice(0, -1)) {
17681 binding_group = x `${binding_group}[${block.renderer.reference(name)}]`;
17682 block.chunks.init.push(b `${binding_group} = ${binding_group} || [];`);
17683 }
17684 }
17685 block.chunks.init.push(b `${binding_group(true)} = [];`);
17686 }
17687 block.chunks.hydrate.push(b `${binding_group(true)}.push(${parent.var});`);
17688 block.chunks.destroy.push(b `${binding_group(true)}.splice(${binding_group(true)}.indexOf(${parent.var}), 1);`);
17689 break;
17690 }
17691 case 'textContent':
17692 update_conditions.push(x `${this.snippet} !== ${parent.var}.textContent`);
17693 mount_conditions.push(x `${this.snippet} !== void 0`);
17694 break;
17695 case 'innerHTML':
17696 update_conditions.push(x `${this.snippet} !== ${parent.var}.innerHTML`);
17697 mount_conditions.push(x `${this.snippet} !== void 0`);
17698 break;
17699 case 'currentTime':
17700 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17701 mount_dom = null;
17702 break;
17703 case 'playbackRate':
17704 case 'volume':
17705 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17706 mount_conditions.push(x `!@_isNaN(${this.snippet})`);
17707 break;
17708 case 'paused':
17709 {
17710 // this is necessary to prevent audio restarting by itself
17711 const last = block.get_unique_name(`${parent.var.name}_is_paused`);
17712 block.add_variable(last, x `true`);
17713 update_conditions.push(x `${last} !== (${last} = ${this.snippet})`);
17714 update_dom = b `${parent.var}[${last} ? "pause" : "play"]();`;
17715 mount_dom = null;
17716 break;
17717 }
17718 case 'value':
17719 if (parent.node.get_static_attribute_value('type') === 'file') {
17720 update_dom = null;
17721 mount_dom = null;
17722 }
17723 }
17724 if (update_dom) {
17725 if (update_conditions.length > 0) {
17726 const condition = update_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17727 block.chunks.update.push(b `
17728 if (${condition}) {
17729 ${update_dom}
17730 }
17731 `);
17732 }
17733 else {
17734 block.chunks.update.push(update_dom);
17735 }
17736 }
17737 if (mount_dom) {
17738 if (mount_conditions.length > 0) {
17739 const condition = mount_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17740 block.chunks.mount.push(b `
17741 if (${condition}) {
17742 ${mount_dom}
17743 }
17744 `);
17745 }
17746 else {
17747 block.chunks.mount.push(mount_dom);
17748 }
17749 }
17750 }
17751 }
17752 function get_dom_updater(element, binding) {
17753 const { node } = element;
17754 if (binding.is_readonly_media_attribute()) {
17755 return null;
17756 }
17757 if (binding.node.name === 'this') {
17758 return null;
17759 }
17760 if (node.name === 'select') {
17761 return node.get_static_attribute_value('multiple') === true ?
17762 b `@select_options(${element.var}, ${binding.snippet})` :
17763 b `@select_option(${element.var}, ${binding.snippet})`;
17764 }
17765 if (binding.node.name === 'group') {
17766 const type = node.get_static_attribute_value('type');
17767 const condition = type === 'checkbox'
17768 ? x `~${binding.snippet}.indexOf(${element.var}.__value)`
17769 : x `${element.var}.__value === ${binding.snippet}`;
17770 return b `${element.var}.checked = ${condition};`;
17771 }
17772 if (binding.node.name === 'value') {
17773 return b `@set_input_value(${element.var}, ${binding.snippet});`;
17774 }
17775 return b `${element.var}.${binding.node.name} = ${binding.snippet};`;
17776 }
17777 function get_binding_group(renderer, value, block) {
17778 const { parts } = flatten_reference(value.raw_expression);
17779 let keypath = parts.join('.');
17780 const contexts = [];
17781 for (const dep of value.expression.contextual_dependencies) {
17782 const context = block.bindings.get(dep);
17783 let key;
17784 let name;
17785 if (context) {
17786 key = context.object.name;
17787 name = context.property.name;
17788 }
17789 else {
17790 key = dep;
17791 name = dep;
17792 }
17793 keypath = `${key}@${keypath}`;
17794 contexts.push(name);
17795 }
17796 if (!renderer.binding_groups.has(keypath)) {
17797 const index = renderer.binding_groups.size;
17798 contexts.forEach(context => {
17799 renderer.add_to_context(context, true);
17800 });
17801 renderer.binding_groups.set(keypath, {
17802 binding_group: (to_reference = false) => {
17803 let binding_group = '$$binding_groups';
17804 let _secondary_indexes = contexts;
17805 if (to_reference) {
17806 binding_group = block.renderer.reference(binding_group);
17807 _secondary_indexes = _secondary_indexes.map(name => block.renderer.reference(name));
17808 }
17809 if (_secondary_indexes.length > 0) {
17810 let obj = x `${binding_group}[${index}]`;
17811 _secondary_indexes.forEach(secondary_index => {
17812 obj = x `${obj}[${secondary_index}]`;
17813 });
17814 return obj;
17815 }
17816 else {
17817 return x `${binding_group}[${index}]`;
17818 }
17819 },
17820 is_context: contexts.length > 0,
17821 contexts,
17822 index,
17823 });
17824 }
17825 return renderer.binding_groups.get(keypath);
17826 }
17827 function get_event_handler(binding, renderer, block, name, lhs) {
17828 const contextual_dependencies = new Set(binding.node.expression.contextual_dependencies);
17829 const context = block.bindings.get(name);
17830 let set_store;
17831 if (context) {
17832 const { object, property, store, snippet } = context;
17833 lhs = replace_object(lhs, snippet);
17834 contextual_dependencies.add(object.name);
17835 contextual_dependencies.add(property.name);
17836 contextual_dependencies.delete(name);
17837 if (store) {
17838 set_store = b `${store}.set(${`$${store}`});`;
17839 }
17840 }
17841 else {
17842 const object = get_object(lhs);
17843 if (object.name[0] === '$') {
17844 const store = object.name.slice(1);
17845 set_store = b `${store}.set(${object.name});`;
17846 }
17847 }
17848 const value = get_value_from_dom(renderer, binding.parent, binding, block, contextual_dependencies);
17849 const mutation = b `
17850 ${lhs} = ${value};
17851 ${set_store}
17852 `;
17853 return {
17854 uses_context: binding.node.is_contextual || binding.node.expression.uses_context,
17855 mutation,
17856 contextual_dependencies,
17857 lhs,
17858 };
17859 }
17860 function get_value_from_dom(renderer, element, binding, block, contextual_dependencies) {
17861 const { node } = element;
17862 const { name } = binding.node;
17863 if (name === 'this') {
17864 return x `$$value`;
17865 }
17866 // <select bind:value='selected>
17867 if (node.name === 'select') {
17868 return node.get_static_attribute_value('multiple') === true ?
17869 x `@select_multiple_value(this)` :
17870 x `@select_value(this)`;
17871 }
17872 const type = node.get_static_attribute_value('type');
17873 // <input type='checkbox' bind:group='foo'>
17874 if (name === 'group') {
17875 if (type === 'checkbox') {
17876 const { binding_group, contexts } = get_binding_group(renderer, binding.node, block);
17877 add_to_set(contextual_dependencies, contexts);
17878 return x `@get_binding_group_value(${binding_group()}, this.__value, this.checked)`;
17879 }
17880 return x `this.__value`;
17881 }
17882 // <input type='range|number' bind:value>
17883 if (type === 'range' || type === 'number') {
17884 return x `@to_number(this.${name})`;
17885 }
17886 if ((name === 'buffered' || name === 'seekable' || name === 'played')) {
17887 return x `@time_ranges_to_array(this.${name})`;
17888 }
17889 // everything else
17890 return x `this.${name}`;
17891 }
17892
17893 function add_actions(block, target, actions) {
17894 actions.forEach(action => add_action(block, target, action));
17895 }
17896 function add_action(block, target, action) {
17897 const { expression } = action;
17898 let snippet;
17899 let dependencies;
17900 if (expression) {
17901 snippet = expression.manipulate(block);
17902 dependencies = expression.dynamic_dependencies();
17903 }
17904 const id = block.get_unique_name(`${action.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action`);
17905 block.add_variable(id);
17906 const fn = block.renderer.reference(action.name);
17907 block.event_listeners.push(x `@action_destroyer(${id} = ${fn}.call(null, ${target}, ${snippet}))`);
17908 if (dependencies && dependencies.length > 0) {
17909 let condition = x `${id} && @is_function(${id}.update)`;
17910 if (dependencies.length > 0) {
17911 condition = x `${condition} && ${block.renderer.dirty(dependencies)}`;
17912 }
17913 block.chunks.update.push(b `if (${condition}) ${id}.update.call(null, ${snippet});`);
17914 }
17915 }
17916
17917 function get_slot_definition(block, scope, lets) {
17918 if (lets.length === 0)
17919 return { block, scope };
17920 const context_input = {
17921 type: 'ObjectPattern',
17922 properties: lets.map(l => ({
17923 type: 'Property',
17924 kind: 'init',
17925 key: l.name,
17926 value: l.value || l.name
17927 }))
17928 };
17929 const properties = [];
17930 const value_map = new Map();
17931 lets.forEach(l => {
17932 let value;
17933 if (l.names.length > 1) {
17934 // more than one, probably destructuring
17935 const unique_name = block.get_unique_name(l.names.join('_')).name;
17936 value_map.set(l.value, unique_name);
17937 value = { type: 'Identifier', name: unique_name };
17938 }
17939 else {
17940 value = l.value || l.name;
17941 }
17942 properties.push({
17943 type: 'Property',
17944 kind: 'init',
17945 key: l.name,
17946 value,
17947 });
17948 });
17949 const changes_input = {
17950 type: 'ObjectPattern',
17951 properties,
17952 };
17953 const names = new Set();
17954 const names_lookup = new Map();
17955 lets.forEach(l => {
17956 l.names.forEach(name => {
17957 names.add(name);
17958 if (value_map.has(l.value)) {
17959 names_lookup.set(name, value_map.get(l.value));
17960 }
17961 });
17962 });
17963 const context = {
17964 type: 'ObjectExpression',
17965 properties: Array.from(names).map(name => p `${block.renderer.context_lookup.get(name).index}: ${name}`)
17966 };
17967 const { context_lookup } = block.renderer;
17968 // i am well aware that this code is gross
17969 // TODO: context-overflow make it less gross
17970 const changes = {
17971 type: 'ParenthesizedExpression',
17972 get expression() {
17973 if (block.renderer.context_overflow) {
17974 const grouped = [];
17975 Array.from(names).forEach(name => {
17976 const i = context_lookup.get(name).index.value;
17977 const g = Math.floor(i / 31);
17978 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
17979 if (!grouped[g])
17980 grouped[g] = [];
17981 grouped[g].push({ name: lookup_name, n: i % 31 });
17982 });
17983 const elements = [];
17984 for (let g = 0; g < grouped.length; g += 1) {
17985 elements[g] = grouped[g]
17986 ? grouped[g]
17987 .map(({ name, n }) => x `${name} ? ${1 << n} : 0`)
17988 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`)
17989 : x `0`;
17990 }
17991 return {
17992 type: 'ArrayExpression',
17993 elements
17994 };
17995 }
17996 return Array.from(names)
17997 .map(name => {
17998 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
17999 const i = context_lookup.get(name).index.value;
18000 return x `${lookup_name} ? ${1 << i} : 0`;
18001 })
18002 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
18003 }
18004 };
18005 return {
18006 block,
18007 scope,
18008 get_context: x `${context_input} => ${context}`,
18009 get_changes: x `${changes_input} => ${changes}`
18010 };
18011 }
18012
18013 function compare_node(a, b) {
18014 if (a === b)
18015 return true;
18016 if (!a || !b)
18017 return false;
18018 if (a.type !== b.type)
18019 return false;
18020 switch (a.type) {
18021 case "Identifier":
18022 return a.name === b.name;
18023 case "MemberExpression":
18024 return (compare_node(a.object, b.object) &&
18025 compare_node(a.property, b.property) &&
18026 a.computed === b.computed);
18027 case 'Literal':
18028 return a.value === b.value;
18029 }
18030 }
18031
18032 function bind_this(component, block, binding, variable) {
18033 const fn = component.get_unique_name(`${variable.name}_binding`);
18034 block.renderer.add_to_context(fn.name);
18035 const callee = block.renderer.reference(fn.name);
18036 const { contextual_dependencies, mutation } = binding.handler;
18037 const dependencies = binding.get_dependencies();
18038 const body = b `
18039 ${mutation}
18040 ${Array.from(dependencies)
18041 .filter(dep => dep[0] !== '$')
18042 .filter(dep => !contextual_dependencies.has(dep))
18043 .map(dep => b `${block.renderer.invalidate(dep)};`)}
18044 `;
18045 if (contextual_dependencies.size) {
18046 const params = Array.from(contextual_dependencies).map(name => ({
18047 type: 'Identifier',
18048 name
18049 }));
18050 component.partly_hoisted.push(b `
18051 function ${fn}($$value, ${params}) {
18052 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
18053 ${body}
18054 });
18055 }
18056 `);
18057 const alias_map = new Map();
18058 const args = [];
18059 for (let id of params) {
18060 const value = block.renderer.reference(id.name);
18061 let found = false;
18062 if (block.variables.has(id.name)) {
18063 let alias = id.name;
18064 for (let i = 1; block.variables.has(alias) && !compare_node(block.variables.get(alias).init, value); alias = `${id.name}_${i++}`)
18065 ;
18066 alias_map.set(alias, id.name);
18067 id = { type: 'Identifier', name: alias };
18068 found = block.variables.has(alias);
18069 }
18070 args.push(id);
18071 if (!found) {
18072 block.add_variable(id, value);
18073 }
18074 }
18075 const assign = block.get_unique_name(`assign_${variable.name}`);
18076 const unassign = block.get_unique_name(`unassign_${variable.name}`);
18077 block.chunks.init.push(b `
18078 const ${assign} = () => ${callee}(${variable}, ${args});
18079 const ${unassign} = () => ${callee}(null, ${args});
18080 `);
18081 const condition = Array.from(args)
18082 .map(name => x `${name} !== ${block.renderer.reference(alias_map.get(name.name) || name.name)}`)
18083 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
18084 // we push unassign and unshift assign so that references are
18085 // nulled out before they're created, to avoid glitches
18086 // with shifting indices
18087 block.chunks.update.push(b `
18088 if (${condition}) {
18089 ${unassign}();
18090 ${args.map(a => b `${a} = ${block.renderer.reference(alias_map.get(a.name) || a.name)}`)};
18091 ${assign}();
18092 }`);
18093 block.chunks.destroy.push(b `${unassign}();`);
18094 return b `${assign}();`;
18095 }
18096 component.partly_hoisted.push(b `
18097 function ${fn}($$value) {
18098 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
18099 ${body}
18100 });
18101 }
18102 `);
18103 block.chunks.destroy.push(b `${callee}(null);`);
18104 return b `${callee}(${variable});`;
18105 }
18106
18107 class Node$1 {
18108 constructor(component, parent, _scope, info) {
18109 this.start = info.start;
18110 this.end = info.end;
18111 this.type = info.type;
18112 // this makes properties non-enumerable, which makes logging
18113 // bearable. might have a performance cost. TODO remove in prod?
18114 Object.defineProperties(this, {
18115 component: {
18116 value: component
18117 },
18118 parent: {
18119 value: parent
18120 }
18121 });
18122 }
18123 cannot_use_innerhtml() {
18124 if (this.can_use_innerhtml !== false) {
18125 this.can_use_innerhtml = false;
18126 if (this.parent)
18127 this.parent.cannot_use_innerhtml();
18128 }
18129 }
18130 find_nearest(selector) {
18131 if (selector.test(this.type))
18132 return this;
18133 if (this.parent)
18134 return this.parent.find_nearest(selector);
18135 }
18136 get_static_attribute_value(name) {
18137 const attribute = this.attributes && this.attributes.find((attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === name);
18138 if (!attribute)
18139 return null;
18140 if (attribute.is_true)
18141 return true;
18142 if (attribute.chunks.length === 0)
18143 return '';
18144 if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
18145 return attribute.chunks[0].data;
18146 }
18147 return null;
18148 }
18149 has_ancestor(type) {
18150 return this.parent ?
18151 this.parent.type === type || this.parent.has_ancestor(type) :
18152 false;
18153 }
18154 }
18155
18156 function create_scopes(expression) {
18157 return analyze(expression);
18158 }
18159
18160 function is_dynamic$1(variable) {
18161 if (variable) {
18162 if (variable.mutated || variable.reassigned)
18163 return true; // dynamic internal state
18164 if (!variable.module && variable.writable && variable.export_name)
18165 return true; // writable props
18166 }
18167 return false;
18168 }
18169
18170 function nodes_match(a, b) {
18171 if (!!a !== !!b)
18172 return false;
18173 if (Array.isArray(a) !== Array.isArray(b))
18174 return false;
18175 if (a && typeof a === 'object') {
18176 if (Array.isArray(a)) {
18177 if (a.length !== b.length)
18178 return false;
18179 return a.every((child, i) => nodes_match(child, b[i]));
18180 }
18181 const a_keys = Object.keys(a).sort();
18182 const b_keys = Object.keys(b).sort();
18183 if (a_keys.length !== b_keys.length)
18184 return false;
18185 let i = a_keys.length;
18186 while (i--) {
18187 const key = a_keys[i];
18188 if (b_keys[i] !== key)
18189 return false;
18190 if (key === 'start' || key === 'end')
18191 continue;
18192 if (!nodes_match(a[key], b[key])) {
18193 return false;
18194 }
18195 }
18196 return true;
18197 }
18198 return a === b;
18199 }
18200
18201 function invalidate(renderer, scope, node, names, main_execution_context = false) {
18202 const { component } = renderer;
18203 const [head, ...tail] = Array.from(names)
18204 .filter(name => {
18205 const owner = scope.find_owner(name);
18206 return !owner || owner === component.instance_scope;
18207 })
18208 .map(name => component.var_lookup.get(name))
18209 .filter(variable => {
18210 return variable && (!variable.hoistable &&
18211 !variable.global &&
18212 !variable.module &&
18213 (variable.referenced ||
18214 variable.subscribable ||
18215 variable.is_reactive_dependency ||
18216 variable.export_name ||
18217 variable.name[0] === '$'));
18218 });
18219 function get_invalidated(variable, node) {
18220 if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') {
18221 return node || x `${variable.name}`;
18222 }
18223 return renderer.invalidate(variable.name);
18224 }
18225 if (head) {
18226 component.has_reactive_assignments = true;
18227 if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) {
18228 return get_invalidated(head, node);
18229 }
18230 else {
18231 const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
18232 const extra_args = tail.map(variable => get_invalidated(variable));
18233 const pass_value = (extra_args.length > 0 ||
18234 (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
18235 (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier')));
18236 if (pass_value) {
18237 extra_args.unshift({
18238 type: 'Identifier',
18239 name: head.name
18240 });
18241 }
18242 let invalidate = is_store_value
18243 ? x `@set_store_value(${head.name.slice(1)}, ${node}, ${extra_args})`
18244 : !main_execution_context
18245 ? x `$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`
18246 : node;
18247 if (head.subscribable && head.reassigned) {
18248 const subscribe = `$$subscribe_${head.name}`;
18249 invalidate = x `${subscribe}(${invalidate})`;
18250 }
18251 return invalidate;
18252 }
18253 }
18254 return node;
18255 }
18256
18257 const reserved_keywords = new Set(["$$props", "$$restProps"]);
18258 function is_reserved_keyword(name) {
18259 return reserved_keywords.has(name);
18260 }
18261
18262 class Expression {
18263 // todo: owner type
18264 constructor(component, owner, template_scope, info, lazy) {
18265 this.type = 'Expression';
18266 this.references = new Set();
18267 this.dependencies = new Set();
18268 this.contextual_dependencies = new Set();
18269 this.declarations = [];
18270 this.uses_context = false;
18271 // TODO revert to direct property access in prod?
18272 Object.defineProperties(this, {
18273 component: {
18274 value: component
18275 }
18276 });
18277 this.node = info;
18278 this.template_scope = template_scope;
18279 this.owner = owner;
18280 const { dependencies, contextual_dependencies, references } = this;
18281 let { map, scope } = create_scopes(info);
18282 this.scope = scope;
18283 this.scope_map = map;
18284 const expression = this;
18285 let function_expression;
18286 // discover dependencies, but don't change the code yet
18287 walk(info, {
18288 enter(node, parent, key) {
18289 // don't manipulate shorthand props twice
18290 if (key === 'value' && parent.shorthand)
18291 return;
18292 if (map.has(node)) {
18293 scope = map.get(node);
18294 }
18295 if (!function_expression && /FunctionExpression/.test(node.type)) {
18296 function_expression = node;
18297 }
18298 if (isReference(node, parent)) {
18299 const { name, nodes } = flatten_reference(node);
18300 references.add(name);
18301 if (scope.has(name))
18302 return;
18303 if (name[0] === '$') {
18304 const store_name = name.slice(1);
18305 if (template_scope.names.has(store_name) || scope.has(store_name)) {
18306 component.error(node, {
18307 code: `contextual-store`,
18308 message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
18309 });
18310 }
18311 }
18312 if (template_scope.is_let(name)) {
18313 if (!function_expression) { // TODO should this be `!lazy` ?
18314 contextual_dependencies.add(name);
18315 dependencies.add(name);
18316 }
18317 }
18318 else if (template_scope.names.has(name)) {
18319 expression.uses_context = true;
18320 contextual_dependencies.add(name);
18321 const owner = template_scope.get_owner(name);
18322 const is_index = owner.type === 'EachBlock' && owner.key && name === owner.index;
18323 if (!lazy || is_index) {
18324 template_scope.dependencies_for_name.get(name).forEach(name => dependencies.add(name));
18325 }
18326 }
18327 else {
18328 if (!lazy) {
18329 dependencies.add(name);
18330 }
18331 component.add_reference(name);
18332 component.warn_if_undefined(name, nodes[0], template_scope);
18333 }
18334 this.skip();
18335 }
18336 // track any assignments from template expressions as mutable
18337 let names;
18338 let deep = false;
18339 if (function_expression) {
18340 if (node.type === 'AssignmentExpression') {
18341 deep = node.left.type === 'MemberExpression';
18342 names = extract_names(deep ? get_object(node.left) : node.left);
18343 }
18344 else if (node.type === 'UpdateExpression') {
18345 names = extract_names(get_object(node.argument));
18346 }
18347 }
18348 if (names) {
18349 names.forEach(name => {
18350 if (template_scope.names.has(name)) {
18351 template_scope.dependencies_for_name.get(name).forEach(name => {
18352 const variable = component.var_lookup.get(name);
18353 if (variable)
18354 variable[deep ? 'mutated' : 'reassigned'] = true;
18355 });
18356 const each_block = template_scope.get_owner(name);
18357 each_block.has_binding = true;
18358 }
18359 else {
18360 component.add_reference(name);
18361 const variable = component.var_lookup.get(name);
18362 if (variable)
18363 variable[deep ? 'mutated' : 'reassigned'] = true;
18364 }
18365 });
18366 }
18367 },
18368 leave(node) {
18369 if (map.has(node)) {
18370 scope = scope.parent;
18371 }
18372 if (node === function_expression) {
18373 function_expression = null;
18374 }
18375 }
18376 });
18377 }
18378 dynamic_dependencies() {
18379 return Array.from(this.dependencies).filter(name => {
18380 if (this.template_scope.is_let(name))
18381 return true;
18382 if (is_reserved_keyword(name))
18383 return true;
18384 const variable = this.component.var_lookup.get(name);
18385 return is_dynamic$1(variable);
18386 });
18387 }
18388 // TODO move this into a render-dom wrapper?
18389 manipulate(block) {
18390 // TODO ideally we wouldn't end up calling this method
18391 // multiple times
18392 if (this.manipulated)
18393 return this.manipulated;
18394 const { component, declarations, scope_map: map, template_scope, owner } = this;
18395 let scope = this.scope;
18396 let function_expression;
18397 let dependencies;
18398 let contextual_dependencies;
18399 const node = walk(this.node, {
18400 enter(node, parent) {
18401 if (node.type === 'Property' && node.shorthand) {
18402 node.value = JSON.parse(JSON.stringify(node.value));
18403 node.shorthand = false;
18404 }
18405 if (map.has(node)) {
18406 scope = map.get(node);
18407 }
18408 if (node.type === 'Identifier' && isReference(node, parent)) {
18409 const { name } = flatten_reference(node);
18410 if (scope.has(name))
18411 return;
18412 if (function_expression) {
18413 if (template_scope.names.has(name)) {
18414 contextual_dependencies.add(name);
18415 template_scope.dependencies_for_name.get(name).forEach(dependency => {
18416 dependencies.add(dependency);
18417 });
18418 }
18419 else {
18420 dependencies.add(name);
18421 component.add_reference(name); // TODO is this redundant/misplaced?
18422 }
18423 }
18424 else if (is_contextual(component, template_scope, name)) {
18425 const reference = block.renderer.reference(node);
18426 this.replace(reference);
18427 }
18428 this.skip();
18429 }
18430 if (!function_expression) {
18431 if (node.type === 'AssignmentExpression') ;
18432 if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
18433 function_expression = node;
18434 dependencies = new Set();
18435 contextual_dependencies = new Set();
18436 }
18437 }
18438 },
18439 leave(node, parent) {
18440 if (map.has(node))
18441 scope = scope.parent;
18442 if (node === function_expression) {
18443 const id = component.get_unique_name(sanitize(get_function_name(node, owner)));
18444 const declaration = b `const ${id} = ${node}`;
18445 if (dependencies.size === 0 && contextual_dependencies.size === 0) {
18446 // we can hoist this out of the component completely
18447 component.fully_hoisted.push(declaration);
18448 this.replace(id);
18449 component.add_var({
18450 name: id.name,
18451 internal: true,
18452 hoistable: true,
18453 referenced: true
18454 });
18455 }
18456 else if (contextual_dependencies.size === 0) {
18457 // function can be hoisted inside the component init
18458 component.partly_hoisted.push(declaration);
18459 block.renderer.add_to_context(id.name);
18460 this.replace(block.renderer.reference(id));
18461 }
18462 else {
18463 // we need a combo block/init recipe
18464 const deps = Array.from(contextual_dependencies);
18465 node.params = [
18466 ...deps.map(name => ({ type: 'Identifier', name })),
18467 ...node.params
18468 ];
18469 const context_args = deps.map(name => block.renderer.reference(name));
18470 component.partly_hoisted.push(declaration);
18471 block.renderer.add_to_context(id.name);
18472 const callee = block.renderer.reference(id);
18473 this.replace(id);
18474 if (node.params.length > 0) {
18475 declarations.push(b `
18476 function ${id}(...args) {
18477 return ${callee}(${context_args}, ...args);
18478 }
18479 `);
18480 }
18481 else {
18482 declarations.push(b `
18483 function ${id}() {
18484 return ${callee}(${context_args});
18485 }
18486 `);
18487 }
18488 }
18489 function_expression = null;
18490 dependencies = null;
18491 contextual_dependencies = null;
18492 if (parent && parent.type === 'Property') {
18493 parent.method = false;
18494 }
18495 }
18496 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
18497 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
18498 const object_name = get_object(assignee).name;
18499 if (scope.has(object_name))
18500 return;
18501 // normally (`a = 1`, `b.c = 2`), there'll be a single name
18502 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
18503 // may be more, in which case we need to tack the extra ones
18504 // onto the initial function call
18505 const names = new Set(extract_names(assignee));
18506 const traced = new Set();
18507 names.forEach(name => {
18508 const dependencies = template_scope.dependencies_for_name.get(name);
18509 if (dependencies) {
18510 dependencies.forEach(name => traced.add(name));
18511 }
18512 else {
18513 traced.add(name);
18514 }
18515 });
18516 const context = block.bindings.get(object_name);
18517 if (context) {
18518 // for `{#each array as item}`
18519 // replace `item = 1` to `each_array[each_index] = 1`, this allow us to mutate the array
18520 // rather than mutating the local `item` variable
18521 const { snippet, object, property } = context;
18522 const replaced = replace_object(assignee, snippet);
18523 if (node.type === 'AssignmentExpression') {
18524 node.left = replaced;
18525 }
18526 else {
18527 node.argument = replaced;
18528 }
18529 contextual_dependencies.add(object.name);
18530 contextual_dependencies.add(property.name);
18531 }
18532 this.replace(invalidate(block.renderer, scope, node, traced));
18533 }
18534 }
18535 });
18536 if (declarations.length > 0) {
18537 block.maintain_context = true;
18538 declarations.forEach(declaration => {
18539 block.chunks.init.push(declaration);
18540 });
18541 }
18542 return (this.manipulated = node);
18543 }
18544 }
18545 function get_function_name(_node, parent) {
18546 if (parent.type === 'EventHandler') {
18547 return `${parent.name}_handler`;
18548 }
18549 if (parent.type === 'Action') {
18550 return `${parent.name}_function`;
18551 }
18552 return 'func';
18553 }
18554 function is_contextual(component, scope, name) {
18555 if (is_reserved_keyword(name))
18556 return true;
18557 // if it's a name below root scope, it's contextual
18558 if (!scope.is_top_level(name))
18559 return true;
18560 const variable = component.var_lookup.get(name);
18561 // hoistables, module declarations, and imports are non-contextual
18562 if (!variable || variable.hoistable)
18563 return false;
18564 // assume contextual
18565 return true;
18566 }
18567
18568 class Action extends Node$1 {
18569 constructor(component, parent, scope, info) {
18570 super(component, parent, scope, info);
18571 component.warn_if_undefined(info.name, info, scope);
18572 this.name = info.name;
18573 component.add_reference(info.name.split('.')[0]);
18574 this.expression = info.expression
18575 ? new Expression(component, this, scope, info.expression)
18576 : null;
18577 this.uses_context = this.expression && this.expression.uses_context;
18578 }
18579 }
18580
18581 class Tag extends Wrapper {
18582 constructor(renderer, block, parent, node) {
18583 super(renderer, block, parent, node);
18584 this.cannot_use_innerhtml();
18585 if (!this.is_dependencies_static()) {
18586 this.not_static_content();
18587 }
18588 block.add_dependencies(node.expression.dependencies);
18589 }
18590 is_dependencies_static() {
18591 return this.node.expression.contextual_dependencies.size === 0 && this.node.expression.dynamic_dependencies().length === 0;
18592 }
18593 rename_this_method(block, update) {
18594 const dependencies = this.node.expression.dynamic_dependencies();
18595 let snippet = this.node.expression.manipulate(block);
18596 const value = this.node.should_cache && block.get_unique_name(`${this.var.name}_value`);
18597 const content = this.node.should_cache ? value : snippet;
18598 snippet = x `${snippet} + ""`;
18599 if (this.node.should_cache)
18600 block.add_variable(value, snippet); // TODO may need to coerce snippet to string
18601 if (dependencies.length > 0) {
18602 let condition = block.renderer.dirty(dependencies);
18603 if (block.has_outros) {
18604 condition = x `!#current || ${condition}`;
18605 }
18606 const update_cached_value = x `${value} !== (${value} = ${snippet})`;
18607 if (this.node.should_cache) {
18608 condition = x `${condition} && ${update_cached_value}`;
18609 }
18610 block.chunks.update.push(b `if (${condition}) ${update(content)}`);
18611 }
18612 return { init: content };
18613 }
18614 }
18615
18616 class MustacheTagWrapper extends Tag {
18617 constructor(renderer, block, parent, node) {
18618 super(renderer, block, parent, node);
18619 this.var = { type: 'Identifier', name: 't' };
18620 }
18621 render(block, parent_node, parent_nodes) {
18622 const { init } = this.rename_this_method(block, value => x `@set_data(${this.var}, ${value})`);
18623 block.add_element(this.var, x `@text(${init})`, parent_nodes && x `@claim_text(${parent_nodes}, ${init})`, parent_node);
18624 }
18625 }
18626
18627 class RawMustacheTagWrapper extends Tag {
18628 constructor(renderer, block, parent, node) {
18629 super(renderer, block, parent, node);
18630 this.var = { type: 'Identifier', name: 'raw' };
18631 this.cannot_use_innerhtml();
18632 this.not_static_content();
18633 }
18634 render(block, parent_node, _parent_nodes) {
18635 const in_head = is_head(parent_node);
18636 const can_use_innerhtml = !in_head && parent_node && !this.prev && !this.next;
18637 if (can_use_innerhtml) {
18638 const insert = content => b `${parent_node}.innerHTML = ${content};`[0];
18639 const { init } = this.rename_this_method(block, content => insert(content));
18640 block.chunks.mount.push(insert(init));
18641 }
18642 else {
18643 const needs_anchor = in_head || (this.next ? !this.next.is_dom_node() : (!this.parent || !this.parent.is_dom_node()));
18644 const html_tag = block.get_unique_name('html_tag');
18645 const html_anchor = needs_anchor && block.get_unique_name('html_anchor');
18646 block.add_variable(html_tag);
18647 const { init } = this.rename_this_method(block, content => x `${html_tag}.p(${content})`);
18648 const update_anchor = needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
18649 block.chunks.hydrate.push(b `${html_tag} = new @HtmlTag(${update_anchor});`);
18650 block.chunks.mount.push(b `${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`);
18651 if (needs_anchor) {
18652 block.add_element(html_anchor, x `@empty()`, x `@empty()`, parent_node);
18653 }
18654 if (!parent_node || in_head) {
18655 block.chunks.destroy.push(b `if (detaching) ${html_tag}.d();`);
18656 }
18657 }
18658 }
18659 }
18660
18661 const events = [
18662 {
18663 event_names: ['input'],
18664 filter: (node, _name) => node.name === 'textarea' ||
18665 node.name === 'input' && !/radio|checkbox|range|file/.test(node.get_static_attribute_value('type'))
18666 },
18667 {
18668 event_names: ['input'],
18669 filter: (node, name) => (name === 'textContent' || name === 'innerHTML') &&
18670 node.attributes.some(attribute => attribute.name === 'contenteditable')
18671 },
18672 {
18673 event_names: ['change'],
18674 filter: (node, _name) => node.name === 'select' ||
18675 node.name === 'input' && /radio|checkbox|file/.test(node.get_static_attribute_value('type'))
18676 },
18677 {
18678 event_names: ['change', 'input'],
18679 filter: (node, _name) => node.name === 'input' && node.get_static_attribute_value('type') === 'range'
18680 },
18681 {
18682 event_names: ['elementresize'],
18683 filter: (_node, name) => dimensions.test(name)
18684 },
18685 // media events
18686 {
18687 event_names: ['timeupdate'],
18688 filter: (node, name) => node.is_media_node() &&
18689 (name === 'currentTime' || name === 'played' || name === 'ended')
18690 },
18691 {
18692 event_names: ['durationchange'],
18693 filter: (node, name) => node.is_media_node() &&
18694 name === 'duration'
18695 },
18696 {
18697 event_names: ['play', 'pause'],
18698 filter: (node, name) => node.is_media_node() &&
18699 name === 'paused'
18700 },
18701 {
18702 event_names: ['progress'],
18703 filter: (node, name) => node.is_media_node() &&
18704 name === 'buffered'
18705 },
18706 {
18707 event_names: ['loadedmetadata'],
18708 filter: (node, name) => node.is_media_node() &&
18709 (name === 'buffered' || name === 'seekable')
18710 },
18711 {
18712 event_names: ['volumechange'],
18713 filter: (node, name) => node.is_media_node() &&
18714 (name === 'volume' || name === 'muted')
18715 },
18716 {
18717 event_names: ['ratechange'],
18718 filter: (node, name) => node.is_media_node() &&
18719 name === 'playbackRate'
18720 },
18721 {
18722 event_names: ['seeking', 'seeked'],
18723 filter: (node, name) => node.is_media_node() &&
18724 (name === 'seeking')
18725 },
18726 {
18727 event_names: ['ended'],
18728 filter: (node, name) => node.is_media_node() &&
18729 name === 'ended'
18730 },
18731 {
18732 event_names: ['resize'],
18733 filter: (node, name) => node.is_media_node() &&
18734 (name === 'videoHeight' || name === 'videoWidth')
18735 },
18736 // details event
18737 {
18738 event_names: ['toggle'],
18739 filter: (node, _name) => node.name === 'details'
18740 },
18741 ];
18742 class ElementWrapper extends Wrapper {
18743 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
18744 super(renderer, block, parent, node);
18745 this.var = {
18746 type: 'Identifier',
18747 name: node.name.replace(/[^a-zA-Z0-9_$]/g, '_')
18748 };
18749 this.void = is_void(node.name);
18750 this.class_dependencies = [];
18751 if (this.node.children.length) {
18752 this.node.lets.forEach(l => {
18753 extract_names(l.value || l.name).forEach(name => {
18754 renderer.add_to_context(name, true);
18755 });
18756 });
18757 }
18758 this.attributes = this.node.attributes.map(attribute => {
18759 if (attribute.name === 'slot') {
18760 // TODO make separate subclass for this?
18761 let owner = this.parent;
18762 while (owner) {
18763 if (owner.node.type === 'InlineComponent') {
18764 break;
18765 }
18766 if (owner.node.type === 'Element' && /-/.test(owner.node.name)) {
18767 break;
18768 }
18769 owner = owner.parent;
18770 }
18771 if (owner && owner.node.type === 'InlineComponent') {
18772 const name = attribute.get_static_value();
18773 if (!owner.slots.has(name)) {
18774 const child_block = block.child({
18775 comment: create_debugging_comment(node, this.renderer.component),
18776 name: this.renderer.component.get_unique_name(`create_${sanitize(name)}_slot`),
18777 type: 'slot'
18778 });
18779 const { scope, lets } = this.node;
18780 const seen = new Set(lets.map(l => l.name.name));
18781 owner.node.lets.forEach(l => {
18782 if (!seen.has(l.name.name))
18783 lets.push(l);
18784 });
18785 owner.slots.set(name, get_slot_definition(child_block, scope, lets));
18786 this.renderer.blocks.push(child_block);
18787 }
18788 this.slot_block = owner.slots.get(name).block;
18789 block = this.slot_block;
18790 }
18791 }
18792 if (attribute.name === 'style') {
18793 return new StyleAttributeWrapper(this, block, attribute);
18794 }
18795 if (attribute.type === 'Spread') {
18796 return new SpreadAttributeWrapper(this, block, attribute);
18797 }
18798 return new AttributeWrapper(this, block, attribute);
18799 });
18800 // ordinarily, there'll only be one... but we need to handle
18801 // the rare case where an element can have multiple bindings,
18802 // e.g. <audio bind:paused bind:currentTime>
18803 this.bindings = this.node.bindings.map(binding => new BindingWrapper(block, binding, this));
18804 this.event_handlers = this.node.handlers.map(event_handler => new EventHandlerWrapper(event_handler, this));
18805 if (node.intro || node.outro) {
18806 if (node.intro)
18807 block.add_intro(node.intro.is_local);
18808 if (node.outro)
18809 block.add_outro(node.outro.is_local);
18810 }
18811 if (node.animation) {
18812 block.add_animation();
18813 }
18814 // add directive and handler dependencies
18815 [node.animation, node.outro, ...node.actions, ...node.classes].forEach(directive => {
18816 if (directive && directive.expression) {
18817 block.add_dependencies(directive.expression.dependencies);
18818 }
18819 });
18820 node.handlers.forEach(handler => {
18821 if (handler.expression) {
18822 block.add_dependencies(handler.expression.dependencies);
18823 }
18824 });
18825 if (this.parent) {
18826 if (node.actions.length > 0 ||
18827 node.animation ||
18828 node.bindings.length > 0 ||
18829 node.classes.length > 0 ||
18830 node.intro || node.outro ||
18831 node.handlers.length > 0 ||
18832 this.node.name === 'option' ||
18833 renderer.options.dev) {
18834 this.parent.cannot_use_innerhtml(); // need to use add_location
18835 this.parent.not_static_content();
18836 }
18837 }
18838 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
18839 if (this.slot_block) {
18840 block.parent.add_dependencies(block.dependencies);
18841 // appalling hack
18842 const index = block.parent.wrappers.indexOf(this);
18843 block.parent.wrappers.splice(index, 1);
18844 block.wrappers.push(this);
18845 }
18846 }
18847 render(block, parent_node, parent_nodes) {
18848 const { renderer } = this;
18849 if (this.node.name === 'noscript')
18850 return;
18851 if (this.slot_block) {
18852 block = this.slot_block;
18853 }
18854 const node = this.var;
18855 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
18856 const children = x `@children(${this.node.name === 'template' ? x `${node}.content` : node})`;
18857 block.add_variable(node);
18858 const render_statement = this.get_render_statement(block);
18859 block.chunks.create.push(b `${node} = ${render_statement};`);
18860 if (renderer.options.hydratable) {
18861 if (parent_nodes) {
18862 block.chunks.claim.push(b `
18863 ${node} = ${this.get_claim_statement(parent_nodes)};
18864 `);
18865 if (!this.void && this.node.children.length > 0) {
18866 block.chunks.claim.push(b `
18867 var ${nodes} = ${children};
18868 `);
18869 }
18870 }
18871 else {
18872 block.chunks.claim.push(b `${node} = ${render_statement};`);
18873 }
18874 }
18875 if (parent_node) {
18876 block.chunks.mount.push(b `@append(${parent_node}, ${node});`);
18877 if (is_head(parent_node)) {
18878 block.chunks.destroy.push(b `@detach(${node});`);
18879 }
18880 }
18881 else {
18882 block.chunks.mount.push(b `@insert(#target, ${node}, #anchor);`);
18883 // TODO we eventually need to consider what happens to elements
18884 // that belong to the same outgroup as an outroing element...
18885 block.chunks.destroy.push(b `if (detaching) @detach(${node});`);
18886 }
18887 // insert static children with textContent or innerHTML
18888 const can_use_textcontent = this.can_use_textcontent();
18889 if (!this.node.namespace && (this.can_use_innerhtml || can_use_textcontent) && this.fragment.nodes.length > 0) {
18890 if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
18891 block.chunks.create.push(b `${node}.textContent = ${string_literal(this.fragment.nodes[0].data)};`);
18892 }
18893 else {
18894 const state = {
18895 quasi: {
18896 type: 'TemplateElement',
18897 value: { raw: '' }
18898 }
18899 };
18900 const literal = {
18901 type: 'TemplateLiteral',
18902 expressions: [],
18903 quasis: []
18904 };
18905 const can_use_raw_text = !this.can_use_innerhtml && can_use_textcontent;
18906 to_html(this.fragment.nodes, block, literal, state, can_use_raw_text);
18907 literal.quasis.push(state.quasi);
18908 block.chunks.create.push(b `${node}.${this.can_use_innerhtml ? 'innerHTML' : 'textContent'} = ${literal};`);
18909 }
18910 }
18911 else {
18912 this.fragment.nodes.forEach((child) => {
18913 child.render(block, this.node.name === 'template' ? x `${node}.content` : node, nodes);
18914 });
18915 }
18916 const event_handler_or_binding_uses_context = (this.bindings.some(binding => binding.handler.uses_context) ||
18917 this.node.handlers.some(handler => handler.uses_context) ||
18918 this.node.actions.some(action => action.uses_context));
18919 if (event_handler_or_binding_uses_context) {
18920 block.maintain_context = true;
18921 }
18922 this.add_attributes(block);
18923 this.add_directives_in_order(block);
18924 this.add_transitions(block);
18925 this.add_animation(block);
18926 this.add_classes(block);
18927 this.add_manual_style_scoping(block);
18928 if (nodes && this.renderer.options.hydratable && !this.void) {
18929 block.chunks.claim.push(b `${this.node.children.length > 0 ? nodes : children}.forEach(@detach);`);
18930 }
18931 if (renderer.options.dev) {
18932 const loc = renderer.locate(this.node.start);
18933 block.chunks.hydrate.push(b `@add_location(${this.var}, ${renderer.file_var}, ${loc.line - 1}, ${loc.column}, ${this.node.start});`);
18934 }
18935 }
18936 can_use_textcontent() {
18937 return this.is_static_content && this.fragment.nodes.every(node => node.node.type === 'Text' || node.node.type === 'MustacheTag');
18938 }
18939 get_render_statement(block) {
18940 const { name, namespace } = this.node;
18941 if (namespace === namespaces.svg) {
18942 return x `@svg_element("${name}")`;
18943 }
18944 if (namespace) {
18945 return x `@_document.createElementNS("${namespace}", "${name}")`;
18946 }
18947 const is = this.attributes.find(attr => attr.node.name === 'is');
18948 if (is) {
18949 return x `@element_is("${name}", ${is.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`)})`;
18950 }
18951 return x `@element("${name}")`;
18952 }
18953 get_claim_statement(nodes) {
18954 const attributes = this.node.attributes
18955 .filter((attr) => attr.type === 'Attribute')
18956 .map((attr) => p `${attr.name}: true`);
18957 const name = this.node.namespace
18958 ? this.node.name
18959 : this.node.name.toUpperCase();
18960 const svg = this.node.namespace === namespaces.svg ? 1 : null;
18961 return x `@claim_element(${nodes}, "${name}", { ${attributes} }, ${svg})`;
18962 }
18963 add_directives_in_order(block) {
18964 const binding_groups = events
18965 .map(event => ({
18966 events: event.event_names,
18967 bindings: this.bindings
18968 .filter(binding => binding.node.name !== 'this')
18969 .filter(binding => event.filter(this.node, binding.node.name))
18970 }))
18971 .filter(group => group.bindings.length);
18972 const this_binding = this.bindings.find(b => b.node.name === 'this');
18973 function getOrder(item) {
18974 if (item instanceof EventHandlerWrapper) {
18975 return item.node.start;
18976 }
18977 else if (item instanceof BindingWrapper) {
18978 return item.node.start;
18979 }
18980 else if (item instanceof Action) {
18981 return item.start;
18982 }
18983 else {
18984 return item.bindings[0].node.start;
18985 }
18986 }
18987 [
18988 ...binding_groups,
18989 ...this.event_handlers,
18990 this_binding,
18991 ...this.node.actions
18992 ]
18993 .filter(Boolean)
18994 .sort((a, b) => getOrder(a) - getOrder(b))
18995 .forEach(item => {
18996 if (item instanceof EventHandlerWrapper) {
18997 add_event_handler(block, this.var, item);
18998 }
18999 else if (item instanceof BindingWrapper) {
19000 this.add_this_binding(block, item);
19001 }
19002 else if (item instanceof Action) {
19003 add_action(block, this.var, item);
19004 }
19005 else {
19006 this.add_bindings(block, item);
19007 }
19008 });
19009 }
19010 add_bindings(block, binding_group) {
19011 const { renderer } = this;
19012 if (binding_group.bindings.length === 0)
19013 return;
19014 renderer.component.has_reactive_assignments = true;
19015 const lock = binding_group.bindings.some(binding => binding.needs_lock) ?
19016 block.get_unique_name(`${this.var.name}_updating`) :
19017 null;
19018 if (lock)
19019 block.add_variable(lock, x `false`);
19020 const handler = renderer.component.get_unique_name(`${this.var.name}_${binding_group.events.join('_')}_handler`);
19021 renderer.add_to_context(handler.name);
19022 // TODO figure out how to handle locks
19023 const needs_lock = binding_group.bindings.some(binding => binding.needs_lock);
19024 const dependencies = new Set();
19025 const contextual_dependencies = new Set();
19026 binding_group.bindings.forEach(binding => {
19027 // TODO this is a mess
19028 add_to_set(dependencies, binding.get_dependencies());
19029 add_to_set(contextual_dependencies, binding.handler.contextual_dependencies);
19030 binding.render(block, lock);
19031 });
19032 // media bindings — awkward special case. The native timeupdate events
19033 // fire too infrequently, so we need to take matters into our
19034 // own hands
19035 let animation_frame;
19036 if (binding_group.events[0] === 'timeupdate') {
19037 animation_frame = block.get_unique_name(`${this.var.name}_animationframe`);
19038 block.add_variable(animation_frame);
19039 }
19040 const has_local_function = contextual_dependencies.size > 0 || needs_lock || animation_frame;
19041 let callee = renderer.reference(handler);
19042 // TODO dry this out — similar code for event handlers and component bindings
19043 if (has_local_function) {
19044 const args = Array.from(contextual_dependencies).map(name => renderer.reference(name));
19045 // need to create a block-local function that calls an instance-level function
19046 if (animation_frame) {
19047 block.chunks.init.push(b `
19048 function ${handler}() {
19049 @_cancelAnimationFrame(${animation_frame});
19050 if (!${this.var}.paused) {
19051 ${animation_frame} = @raf(${handler});
19052 ${needs_lock && b `${lock} = true;`}
19053 }
19054 ${callee}.call(${this.var}, ${args});
19055 }
19056 `);
19057 }
19058 else {
19059 block.chunks.init.push(b `
19060 function ${handler}() {
19061 ${needs_lock && b `${lock} = true;`}
19062 ${callee}.call(${this.var}, ${args});
19063 }
19064 `);
19065 }
19066 callee = handler;
19067 }
19068 const params = Array.from(contextual_dependencies).map(name => ({
19069 type: 'Identifier',
19070 name
19071 }));
19072 this.renderer.component.partly_hoisted.push(b `
19073 function ${handler}(${params}) {
19074 ${binding_group.bindings.map(b => b.handler.mutation)}
19075 ${Array.from(dependencies)
19076 .filter(dep => dep[0] !== '$')
19077 .filter(dep => !contextual_dependencies.has(dep))
19078 .map(dep => b `${this.renderer.invalidate(dep)};`)}
19079 }
19080 `);
19081 binding_group.events.forEach(name => {
19082 if (name === 'elementresize') {
19083 // special case
19084 const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`);
19085 block.add_variable(resize_listener);
19086 block.chunks.mount.push(b `${resize_listener} = @add_resize_listener(${this.var}, ${callee}.bind(${this.var}));`);
19087 block.chunks.destroy.push(b `${resize_listener}();`);
19088 }
19089 else {
19090 block.event_listeners.push(x `@listen(${this.var}, "${name}", ${callee})`);
19091 }
19092 });
19093 const some_initial_state_is_undefined = binding_group.bindings
19094 .map(binding => x `${binding.snippet} === void 0`)
19095 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
19096 const should_initialise = (this.node.name === 'select' ||
19097 binding_group.bindings.find(binding => {
19098 return (binding.node.name === 'indeterminate' ||
19099 binding.node.name === 'textContent' ||
19100 binding.node.name === 'innerHTML' ||
19101 binding.is_readonly_media_attribute());
19102 }));
19103 if (should_initialise) {
19104 const callback = has_local_function ? handler : x `() => ${callee}.call(${this.var})`;
19105 block.chunks.hydrate.push(b `if (${some_initial_state_is_undefined}) @add_render_callback(${callback});`);
19106 }
19107 if (binding_group.events[0] === 'elementresize') {
19108 block.chunks.hydrate.push(b `@add_render_callback(() => ${callee}.call(${this.var}));`);
19109 }
19110 if (lock) {
19111 block.chunks.update.push(b `${lock} = false;`);
19112 }
19113 }
19114 add_this_binding(block, this_binding) {
19115 const { renderer } = this;
19116 renderer.component.has_reactive_assignments = true;
19117 const binding_callback = bind_this(renderer.component, block, this_binding, this.var);
19118 block.chunks.mount.push(binding_callback);
19119 }
19120 add_attributes(block) {
19121 // Get all the class dependencies first
19122 this.attributes.forEach((attribute) => {
19123 if (attribute.node.name === 'class') {
19124 const dependencies = attribute.node.get_dependencies();
19125 this.class_dependencies.push(...dependencies);
19126 }
19127 });
19128 if (this.node.attributes.some(attr => attr.is_spread)) {
19129 this.add_spread_attributes(block);
19130 return;
19131 }
19132 this.attributes.forEach((attribute) => {
19133 attribute.render(block);
19134 });
19135 }
19136 add_spread_attributes(block) {
19137 const levels = block.get_unique_name(`${this.var.name}_levels`);
19138 const data = block.get_unique_name(`${this.var.name}_data`);
19139 const initial_props = [];
19140 const updates = [];
19141 this.attributes
19142 .forEach(attr => {
19143 const dependencies = attr.node.get_dependencies();
19144 const condition = dependencies.length > 0
19145 ? block.renderer.dirty(dependencies)
19146 : null;
19147 if (attr instanceof SpreadAttributeWrapper) {
19148 const snippet = attr.node.expression.manipulate(block);
19149 initial_props.push(snippet);
19150 updates.push(condition ? x `${condition} && ${snippet}` : snippet);
19151 }
19152 else {
19153 const name = attr.property_name || attr.name;
19154 initial_props.push(x `{ ${name}: ${attr.get_init(block, attr.get_value(block))} }`);
19155 const snippet = x `{ ${name}: ${attr.should_cache ? attr.last : attr.get_value(block)} }`;
19156 updates.push(condition ? x `${attr.get_dom_update_conditions(block, condition)} && ${snippet}` : snippet);
19157 }
19158 });
19159 block.chunks.init.push(b `
19160 let ${levels} = [${initial_props}];
19161
19162 let ${data} = {};
19163 for (let #i = 0; #i < ${levels}.length; #i += 1) {
19164 ${data} = @assign(${data}, ${levels}[#i]);
19165 }
19166 `);
19167 const fn = this.node.namespace === namespaces.svg ? x `@set_svg_attributes` : x `@set_attributes`;
19168 block.chunks.hydrate.push(b `${fn}(${this.var}, ${data});`);
19169 block.chunks.update.push(b `
19170 ${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
19171 ${updates}
19172 ]));
19173 `);
19174 // handle edge cases for elements
19175 if (this.node.name === 'select') {
19176 const dependencies = new Set();
19177 for (const attr of this.attributes) {
19178 for (const dep of attr.node.dependencies) {
19179 dependencies.add(dep);
19180 }
19181 }
19182 block.chunks.mount.push(b `
19183 if (${data}.multiple) @select_options(${this.var}, ${data}.value);
19184 `);
19185 block.chunks.update.push(b `
19186 if (${block.renderer.dirty(Array.from(dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value);
19187 `);
19188 }
19189 }
19190 add_transitions(block) {
19191 const { intro, outro } = this.node;
19192 if (!intro && !outro)
19193 return;
19194 if (intro === outro) {
19195 // bidirectional transition
19196 const name = block.get_unique_name(`${this.var.name}_transition`);
19197 const snippet = intro.expression
19198 ? intro.expression.manipulate(block)
19199 : x `{}`;
19200 block.add_variable(name);
19201 const fn = this.renderer.reference(intro.name);
19202 const intro_block = b `
19203 @add_render_callback(() => {
19204 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, true);
19205 ${name}.run(1);
19206 });
19207 `;
19208 const outro_block = b `
19209 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, false);
19210 ${name}.run(0);
19211 `;
19212 if (intro.is_local) {
19213 block.chunks.intro.push(b `
19214 if (#local) {
19215 ${intro_block}
19216 }
19217 `);
19218 block.chunks.outro.push(b `
19219 if (#local) {
19220 ${outro_block}
19221 }
19222 `);
19223 }
19224 else {
19225 block.chunks.intro.push(intro_block);
19226 block.chunks.outro.push(outro_block);
19227 }
19228 block.chunks.destroy.push(b `if (detaching && ${name}) ${name}.end();`);
19229 }
19230 else {
19231 const intro_name = intro && block.get_unique_name(`${this.var.name}_intro`);
19232 const outro_name = outro && block.get_unique_name(`${this.var.name}_outro`);
19233 if (intro) {
19234 block.add_variable(intro_name);
19235 const snippet = intro.expression
19236 ? intro.expression.manipulate(block)
19237 : x `{}`;
19238 const fn = this.renderer.reference(intro.name);
19239 let intro_block;
19240 if (outro) {
19241 intro_block = b `
19242 @add_render_callback(() => {
19243 if (${outro_name}) ${outro_name}.end(1);
19244 if (!${intro_name}) ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
19245 ${intro_name}.start();
19246 });
19247 `;
19248 block.chunks.outro.push(b `if (${intro_name}) ${intro_name}.invalidate();`);
19249 }
19250 else {
19251 intro_block = b `
19252 if (!${intro_name}) {
19253 @add_render_callback(() => {
19254 ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
19255 ${intro_name}.start();
19256 });
19257 }
19258 `;
19259 }
19260 if (intro.is_local) {
19261 intro_block = b `
19262 if (#local) {
19263 ${intro_block}
19264 }
19265 `;
19266 }
19267 block.chunks.intro.push(intro_block);
19268 }
19269 if (outro) {
19270 block.add_variable(outro_name);
19271 const snippet = outro.expression
19272 ? outro.expression.manipulate(block)
19273 : x `{}`;
19274 const fn = this.renderer.reference(outro.name);
19275 if (!intro) {
19276 block.chunks.intro.push(b `
19277 if (${outro_name}) ${outro_name}.end(1);
19278 `);
19279 }
19280 // TODO hide elements that have outro'd (unless they belong to a still-outroing
19281 // group) prior to their removal from the DOM
19282 let outro_block = b `
19283 ${outro_name} = @create_out_transition(${this.var}, ${fn}, ${snippet});
19284 `;
19285 if (outro.is_local) {
19286 outro_block = b `
19287 if (#local) {
19288 ${outro_block}
19289 }
19290 `;
19291 }
19292 block.chunks.outro.push(outro_block);
19293 block.chunks.destroy.push(b `if (detaching && ${outro_name}) ${outro_name}.end();`);
19294 }
19295 }
19296 }
19297 add_animation(block) {
19298 if (!this.node.animation)
19299 return;
19300 const { outro } = this.node;
19301 const rect = block.get_unique_name('rect');
19302 const stop_animation = block.get_unique_name('stop_animation');
19303 block.add_variable(rect);
19304 block.add_variable(stop_animation, x `@noop`);
19305 block.chunks.measure.push(b `
19306 ${rect} = ${this.var}.getBoundingClientRect();
19307 `);
19308 block.chunks.fix.push(b `
19309 @fix_position(${this.var});
19310 ${stop_animation}();
19311 ${outro && b `@add_transform(${this.var}, ${rect});`}
19312 `);
19313 const params = this.node.animation.expression ? this.node.animation.expression.manipulate(block) : x `{}`;
19314 const name = this.renderer.reference(this.node.animation.name);
19315 block.chunks.animate.push(b `
19316 ${stop_animation}();
19317 ${stop_animation} = @create_animation(${this.var}, ${rect}, ${name}, ${params});
19318 `);
19319 }
19320 add_classes(block) {
19321 const has_spread = this.node.attributes.some(attr => attr.is_spread);
19322 this.node.classes.forEach(class_directive => {
19323 const { expression, name } = class_directive;
19324 let snippet;
19325 let dependencies;
19326 if (expression) {
19327 snippet = expression.manipulate(block);
19328 dependencies = expression.dependencies;
19329 }
19330 else {
19331 snippet = name;
19332 dependencies = new Set([name]);
19333 }
19334 const updater = b `@toggle_class(${this.var}, "${name}", ${snippet});`;
19335 block.chunks.hydrate.push(updater);
19336 if (has_spread) {
19337 block.chunks.update.push(updater);
19338 }
19339 else if ((dependencies && dependencies.size > 0) || this.class_dependencies.length) {
19340 const all_dependencies = this.class_dependencies.concat(...dependencies);
19341 const condition = block.renderer.dirty(all_dependencies);
19342 block.chunks.update.push(b `
19343 if (${condition}) {
19344 ${updater}
19345 }`);
19346 }
19347 });
19348 }
19349 add_manual_style_scoping(block) {
19350 if (this.node.needs_manual_style_scoping) {
19351 const updater = b `@toggle_class(${this.var}, "${this.node.component.stylesheet.id}", true);`;
19352 block.chunks.hydrate.push(updater);
19353 block.chunks.update.push(updater);
19354 }
19355 }
19356 }
19357 function to_html(wrappers, block, literal, state, can_use_raw_text) {
19358 wrappers.forEach(wrapper => {
19359 if (wrapper instanceof TextWrapper) {
19360 if (wrapper.use_space())
19361 state.quasi.value.raw += ' ';
19362 const parent = wrapper.node.parent;
19363 const raw = parent && (parent.name === 'script' ||
19364 parent.name === 'style' ||
19365 can_use_raw_text);
19366 state.quasi.value.raw += (raw ? wrapper.data : escape_html(wrapper.data))
19367 .replace(/\\/g, '\\\\')
19368 .replace(/`/g, '\\`')
19369 .replace(/\$/g, '\\$');
19370 }
19371 else if (wrapper instanceof MustacheTagWrapper || wrapper instanceof RawMustacheTagWrapper) {
19372 literal.quasis.push(state.quasi);
19373 literal.expressions.push(wrapper.node.expression.manipulate(block));
19374 state.quasi = {
19375 type: 'TemplateElement',
19376 value: { raw: '' }
19377 };
19378 }
19379 else if (wrapper.node.name === 'noscript') ;
19380 else {
19381 // element
19382 state.quasi.value.raw += `<${wrapper.node.name}`;
19383 wrapper.attributes.forEach((attr) => {
19384 state.quasi.value.raw += ` ${fix_attribute_casing(attr.node.name)}="`;
19385 attr.node.chunks.forEach(chunk => {
19386 if (chunk.type === 'Text') {
19387 state.quasi.value.raw += escape_html(chunk.data);
19388 }
19389 else {
19390 literal.quasis.push(state.quasi);
19391 literal.expressions.push(chunk.manipulate(block));
19392 state.quasi = {
19393 type: 'TemplateElement',
19394 value: { raw: '' }
19395 };
19396 }
19397 });
19398 state.quasi.value.raw += `"`;
19399 });
19400 state.quasi.value.raw += '>';
19401 if (!wrapper.void) {
19402 to_html(wrapper.fragment.nodes, block, literal, state);
19403 state.quasi.value.raw += `</${wrapper.node.name}>`;
19404 }
19405 }
19406 });
19407 }
19408
19409 class HeadWrapper extends Wrapper {
19410 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19411 super(renderer, block, parent, node);
19412 this.can_use_innerhtml = false;
19413 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
19414 }
19415 render(block, _parent_node, _parent_nodes) {
19416 let nodes;
19417 if (this.renderer.options.hydratable && this.fragment.nodes.length) {
19418 nodes = block.get_unique_name('head_nodes');
19419 block.chunks.claim.push(b `const ${nodes} = @query_selector_all('[data-svelte="${this.node.id}"]', @_document.head);`);
19420 }
19421 this.fragment.render(block, x `@_document.head`, nodes);
19422 if (nodes && this.renderer.options.hydratable) {
19423 block.chunks.claim.push(b `${nodes}.forEach(@detach);`);
19424 }
19425 }
19426 }
19427
19428 function is_else_if(node) {
19429 return (node && node.children.length === 1 && node.children[0].type === 'IfBlock');
19430 }
19431 class IfBlockBranch extends Wrapper {
19432 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19433 super(renderer, block, parent, node);
19434 this.var = null;
19435 const { expression } = node;
19436 const is_else = !expression;
19437 if (expression) {
19438 this.dependencies = expression.dynamic_dependencies();
19439 // TODO is this the right rule? or should any non-reference count?
19440 // const should_cache = !is_reference(expression.node, null) && dependencies.length > 0;
19441 let should_cache = false;
19442 walk(expression.node, {
19443 enter(node) {
19444 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
19445 should_cache = true;
19446 }
19447 }
19448 });
19449 if (should_cache) {
19450 this.condition = block.get_unique_name(`show_if`);
19451 this.snippet = expression.manipulate(block);
19452 }
19453 else {
19454 this.condition = expression.manipulate(block);
19455 }
19456 }
19457 this.block = block.child({
19458 comment: create_debugging_comment(node, parent.renderer.component),
19459 name: parent.renderer.component.get_unique_name(is_else ? `create_else_block` : `create_if_block`),
19460 type: node.expression ? 'if' : 'else'
19461 });
19462 this.fragment = new FragmentWrapper(renderer, this.block, node.children, parent, strip_whitespace, next_sibling);
19463 this.is_dynamic = this.block.dependencies.size > 0;
19464 }
19465 }
19466 class IfBlockWrapper extends Wrapper {
19467 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19468 super(renderer, block, parent, node);
19469 this.needs_update = false;
19470 this.var = { type: 'Identifier', name: 'if_block' };
19471 this.cannot_use_innerhtml();
19472 this.not_static_content();
19473 this.branches = [];
19474 const blocks = [];
19475 let is_dynamic = false;
19476 let has_intros = false;
19477 let has_outros = false;
19478 const create_branches = (node) => {
19479 const branch = new IfBlockBranch(renderer, block, this, node, strip_whitespace, next_sibling);
19480 this.branches.push(branch);
19481 blocks.push(branch.block);
19482 block.add_dependencies(node.expression.dependencies);
19483 if (branch.block.dependencies.size > 0) {
19484 // the condition, or its contents, is dynamic
19485 is_dynamic = true;
19486 block.add_dependencies(branch.block.dependencies);
19487 }
19488 if (branch.dependencies && branch.dependencies.length > 0) {
19489 // the condition itself is dynamic
19490 this.needs_update = true;
19491 }
19492 if (branch.block.has_intros)
19493 has_intros = true;
19494 if (branch.block.has_outros)
19495 has_outros = true;
19496 if (is_else_if(node.else)) {
19497 create_branches(node.else.children[0]);
19498 }
19499 else if (node.else) {
19500 const branch = new IfBlockBranch(renderer, block, this, node.else, strip_whitespace, next_sibling);
19501 this.branches.push(branch);
19502 blocks.push(branch.block);
19503 if (branch.block.dependencies.size > 0) {
19504 is_dynamic = true;
19505 block.add_dependencies(branch.block.dependencies);
19506 }
19507 if (branch.block.has_intros)
19508 has_intros = true;
19509 if (branch.block.has_outros)
19510 has_outros = true;
19511 }
19512 };
19513 create_branches(this.node);
19514 blocks.forEach(block => {
19515 block.has_update_method = is_dynamic;
19516 block.has_intro_method = has_intros;
19517 block.has_outro_method = has_outros;
19518 });
19519 renderer.blocks.push(...blocks);
19520 }
19521 render(block, parent_node, parent_nodes) {
19522 const name = this.var;
19523 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
19524 const anchor = needs_anchor
19525 ? block.get_unique_name(`${this.var.name}_anchor`)
19526 : (this.next && this.next.var) || 'null';
19527 const has_else = !(this.branches[this.branches.length - 1].condition);
19528 const if_exists_condition = has_else ? null : name;
19529 const dynamic = this.branches[0].block.has_update_method; // can use [0] as proxy for all, since they necessarily have the same value
19530 const has_intros = this.branches[0].block.has_intro_method;
19531 const has_outros = this.branches[0].block.has_outro_method;
19532 const has_transitions = has_intros || has_outros;
19533 const vars = { name, anchor, if_exists_condition, has_else, has_transitions };
19534 const detaching = parent_node && !is_head(parent_node) ? null : 'detaching';
19535 if (this.node.else) {
19536 this.branches.forEach(branch => {
19537 if (branch.snippet)
19538 block.add_variable(branch.condition);
19539 });
19540 if (has_outros) {
19541 this.render_compound_with_outros(block, parent_node, parent_nodes, dynamic, vars, detaching);
19542 block.chunks.outro.push(b `@transition_out(${name});`);
19543 }
19544 else {
19545 this.render_compound(block, parent_node, parent_nodes, dynamic, vars, detaching);
19546 }
19547 }
19548 else {
19549 this.render_simple(block, parent_node, parent_nodes, dynamic, vars, detaching);
19550 if (has_outros) {
19551 block.chunks.outro.push(b `@transition_out(${name});`);
19552 }
19553 }
19554 if (if_exists_condition) {
19555 block.chunks.create.push(b `if (${if_exists_condition}) ${name}.c();`);
19556 }
19557 else {
19558 block.chunks.create.push(b `${name}.c();`);
19559 }
19560 if (parent_nodes && this.renderer.options.hydratable) {
19561 if (if_exists_condition) {
19562 block.chunks.claim.push(b `if (${if_exists_condition}) ${name}.l(${parent_nodes});`);
19563 }
19564 else {
19565 block.chunks.claim.push(b `${name}.l(${parent_nodes});`);
19566 }
19567 }
19568 if (has_intros || has_outros) {
19569 block.chunks.intro.push(b `@transition_in(${name});`);
19570 }
19571 if (needs_anchor) {
19572 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
19573 }
19574 this.branches.forEach(branch => {
19575 branch.fragment.render(branch.block, null, x `#nodes`);
19576 });
19577 }
19578 render_compound(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, if_exists_condition, has_transitions }, detaching) {
19579 const select_block_type = this.renderer.component.get_unique_name(`select_block_type`);
19580 const current_block_type = block.get_unique_name(`current_block_type`);
19581 const get_block = has_else
19582 ? x `${current_block_type}(#ctx)`
19583 : x `${current_block_type} && ${current_block_type}(#ctx)`;
19584 if (this.needs_update) {
19585 block.chunks.init.push(b `
19586 function ${select_block_type}(#ctx, #dirty) {
19587 ${this.branches.map(({ dependencies, condition, snippet, block }) => condition
19588 ? b `
19589 ${snippet && (dependencies.length > 0
19590 ? b `if (${condition} == null || ${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
19591 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
19592 if (${condition}) return ${block.name};`
19593 : b `return ${block.name};`)}
19594 }
19595 `);
19596 }
19597 else {
19598 block.chunks.init.push(b `
19599 function ${select_block_type}(#ctx, #dirty) {
19600 ${this.branches.map(({ condition, snippet, block }) => condition
19601 ? b `if (${snippet || condition}) return ${block.name};`
19602 : b `return ${block.name};`)}
19603 }
19604 `);
19605 }
19606 block.chunks.init.push(b `
19607 let ${current_block_type} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
19608 let ${name} = ${get_block};
19609 `);
19610 const initial_mount_node = parent_node || '#target';
19611 const anchor_node = parent_node ? 'null' : '#anchor';
19612 if (if_exists_condition) {
19613 block.chunks.mount.push(b `if (${if_exists_condition}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
19614 }
19615 else {
19616 block.chunks.mount.push(b `${name}.m(${initial_mount_node}, ${anchor_node});`);
19617 }
19618 if (this.needs_update) {
19619 const update_mount_node = this.get_update_mount_node(anchor);
19620 const change_block = b `
19621 ${if_exists_condition ? b `if (${if_exists_condition}) ${name}.d(1)` : b `${name}.d(1)`};
19622 ${name} = ${get_block};
19623 if (${name}) {
19624 ${name}.c();
19625 ${has_transitions && b `@transition_in(${name}, 1);`}
19626 ${name}.m(${update_mount_node}, ${anchor});
19627 }
19628 `;
19629 if (dynamic) {
19630 block.chunks.update.push(b `
19631 if (${current_block_type} === (${current_block_type} = ${select_block_type}(#ctx, #dirty)) && ${name}) {
19632 ${name}.p(#ctx, #dirty);
19633 } else {
19634 ${change_block}
19635 }
19636 `);
19637 }
19638 else {
19639 block.chunks.update.push(b `
19640 if (${current_block_type} !== (${current_block_type} = ${select_block_type}(#ctx, #dirty))) {
19641 ${change_block}
19642 }
19643 `);
19644 }
19645 }
19646 else if (dynamic) {
19647 if (if_exists_condition) {
19648 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
19649 }
19650 else {
19651 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
19652 }
19653 }
19654 if (if_exists_condition) {
19655 block.chunks.destroy.push(b `
19656 if (${if_exists_condition}) {
19657 ${name}.d(${detaching});
19658 }
19659 `);
19660 }
19661 else {
19662 block.chunks.destroy.push(b `
19663 ${name}.d(${detaching});
19664 `);
19665 }
19666 }
19667 // if any of the siblings have outros, we need to keep references to the blocks
19668 // (TODO does this only apply to bidi transitions?)
19669 render_compound_with_outros(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, has_transitions, if_exists_condition }, detaching) {
19670 const select_block_type = this.renderer.component.get_unique_name(`select_block_type`);
19671 const current_block_type_index = block.get_unique_name(`current_block_type_index`);
19672 const previous_block_index = block.get_unique_name(`previous_block_index`);
19673 const if_block_creators = block.get_unique_name(`if_block_creators`);
19674 const if_blocks = block.get_unique_name(`if_blocks`);
19675 const if_current_block_type_index = has_else
19676 ? nodes => nodes
19677 : nodes => b `if (~${current_block_type_index}) { ${nodes} }`;
19678 block.add_variable(current_block_type_index);
19679 block.add_variable(name);
19680 block.chunks.init.push(b `
19681 const ${if_block_creators} = [
19682 ${this.branches.map(branch => branch.block.name)}
19683 ];
19684
19685 const ${if_blocks} = [];
19686
19687 ${this.needs_update
19688 ? b `
19689 function ${select_block_type}(#ctx, #dirty) {
19690 ${this.branches.map(({ dependencies, condition, snippet }, i) => condition
19691 ? b `
19692 ${snippet && (dependencies.length > 0
19693 ? b `if (${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
19694 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
19695 if (${condition}) return ${i};`
19696 : b `return ${i};`)}
19697 ${!has_else && b `return -1;`}
19698 }
19699 `
19700 : b `
19701 function ${select_block_type}(#ctx, #dirty) {
19702 ${this.branches.map(({ condition, snippet }, i) => condition
19703 ? b `if (${snippet || condition}) return ${i};`
19704 : b `return ${i};`)}
19705 ${!has_else && b `return -1;`}
19706 }
19707 `}
19708 `);
19709 if (has_else) {
19710 block.chunks.init.push(b `
19711 ${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
19712 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19713 `);
19714 }
19715 else {
19716 block.chunks.init.push(b `
19717 if (~(${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}))) {
19718 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19719 }
19720 `);
19721 }
19722 const initial_mount_node = parent_node || '#target';
19723 const anchor_node = parent_node ? 'null' : '#anchor';
19724 block.chunks.mount.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].m(${initial_mount_node}, ${anchor_node});`));
19725 if (this.needs_update) {
19726 const update_mount_node = this.get_update_mount_node(anchor);
19727 const destroy_old_block = b `
19728 @group_outros();
19729 @transition_out(${if_blocks}[${previous_block_index}], 1, 1, () => {
19730 ${if_blocks}[${previous_block_index}] = null;
19731 });
19732 @check_outros();
19733 `;
19734 const create_new_block = b `
19735 ${name} = ${if_blocks}[${current_block_type_index}];
19736 if (!${name}) {
19737 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19738 ${name}.c();
19739 }
19740 ${has_transitions && b `@transition_in(${name}, 1);`}
19741 ${name}.m(${update_mount_node}, ${anchor});
19742 `;
19743 const change_block = has_else
19744 ? b `
19745 ${destroy_old_block}
19746
19747 ${create_new_block}
19748 `
19749 : b `
19750 if (${name}) {
19751 ${destroy_old_block}
19752 }
19753
19754 if (~${current_block_type_index}) {
19755 ${create_new_block}
19756 } else {
19757 ${name} = null;
19758 }
19759 `;
19760 if (dynamic) {
19761 block.chunks.update.push(b `
19762 let ${previous_block_index} = ${current_block_type_index};
19763 ${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
19764 if (${current_block_type_index} === ${previous_block_index}) {
19765 ${if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].p(#ctx, #dirty);`)}
19766 } else {
19767 ${change_block}
19768 }
19769 `);
19770 }
19771 else {
19772 block.chunks.update.push(b `
19773 let ${previous_block_index} = ${current_block_type_index};
19774 ${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
19775 if (${current_block_type_index} !== ${previous_block_index}) {
19776 ${change_block}
19777 }
19778 `);
19779 }
19780 }
19781 else if (dynamic) {
19782 if (if_exists_condition) {
19783 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
19784 }
19785 else {
19786 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
19787 }
19788 }
19789 block.chunks.destroy.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].d(${detaching});`));
19790 }
19791 render_simple(block, parent_node, _parent_nodes, dynamic, { name, anchor, if_exists_condition, has_transitions }, detaching) {
19792 const branch = this.branches[0];
19793 if (branch.snippet)
19794 block.add_variable(branch.condition, branch.snippet);
19795 block.chunks.init.push(b `
19796 let ${name} = ${branch.condition} && ${branch.block.name}(#ctx);
19797 `);
19798 const initial_mount_node = parent_node || '#target';
19799 const anchor_node = parent_node ? 'null' : '#anchor';
19800 block.chunks.mount.push(b `if (${name}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
19801 if (branch.dependencies.length > 0) {
19802 const update_mount_node = this.get_update_mount_node(anchor);
19803 const enter = b `
19804 if (${name}) {
19805 ${dynamic && b `${name}.p(#ctx, #dirty);`}
19806 ${has_transitions &&
19807 b `if (${block.renderer.dirty(branch.dependencies)}) {
19808 @transition_in(${name}, 1);
19809 }`}
19810 } else {
19811 ${name} = ${branch.block.name}(#ctx);
19812 ${name}.c();
19813 ${has_transitions && b `@transition_in(${name}, 1);`}
19814 ${name}.m(${update_mount_node}, ${anchor});
19815 }
19816 `;
19817 if (branch.snippet) {
19818 block.chunks.update.push(b `if (${block.renderer.dirty(branch.dependencies)}) ${branch.condition} = ${branch.snippet}`);
19819 }
19820 // no `p()` here — we don't want to update outroing nodes,
19821 // as that will typically result in glitching
19822 if (branch.block.has_outro_method) {
19823 block.chunks.update.push(b `
19824 if (${branch.condition}) {
19825 ${enter}
19826 } else if (${name}) {
19827 @group_outros();
19828 @transition_out(${name}, 1, 1, () => {
19829 ${name} = null;
19830 });
19831 @check_outros();
19832 }
19833 `);
19834 }
19835 else {
19836 block.chunks.update.push(b `
19837 if (${branch.condition}) {
19838 ${enter}
19839 } else if (${name}) {
19840 ${name}.d(1);
19841 ${name} = null;
19842 }
19843 `);
19844 }
19845 }
19846 else if (dynamic) {
19847 block.chunks.update.push(b `
19848 if (${branch.condition}) ${name}.p(#ctx, #dirty);
19849 `);
19850 }
19851 if (if_exists_condition) {
19852 block.chunks.destroy.push(b `
19853 if (${if_exists_condition}) ${name}.d(${detaching});
19854 `);
19855 }
19856 else {
19857 block.chunks.destroy.push(b `
19858 ${name}.d(${detaching});
19859 `);
19860 }
19861 }
19862 get_initial_dirty_bit() {
19863 const _this = this;
19864 // TODO: context-overflow make it less gross
19865 const val = x `-1`;
19866 return {
19867 get type() {
19868 return _this.renderer.context_overflow ? 'ArrayExpression' : 'UnaryExpression';
19869 },
19870 // as [-1]
19871 elements: [val],
19872 // as -1
19873 operator: val.operator,
19874 prefix: val.prefix,
19875 argument: val.argument,
19876 };
19877 }
19878 }
19879
19880 class InlineComponentWrapper extends Wrapper {
19881 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19882 super(renderer, block, parent, node);
19883 this.slots = new Map();
19884 this.cannot_use_innerhtml();
19885 this.not_static_content();
19886 if (this.node.expression) {
19887 block.add_dependencies(this.node.expression.dependencies);
19888 }
19889 this.node.attributes.forEach(attr => {
19890 block.add_dependencies(attr.dependencies);
19891 });
19892 this.node.bindings.forEach(binding => {
19893 if (binding.is_contextual) {
19894 mark_each_block_bindings(this, binding);
19895 }
19896 block.add_dependencies(binding.expression.dependencies);
19897 });
19898 this.node.handlers.forEach(handler => {
19899 if (handler.expression) {
19900 block.add_dependencies(handler.expression.dependencies);
19901 }
19902 });
19903 this.var = {
19904 type: 'Identifier',
19905 name: (this.node.name === 'svelte:self' ? renderer.component.name.name :
19906 this.node.name === 'svelte:component' ? 'switch_instance' :
19907 sanitize(this.node.name)).toLowerCase()
19908 };
19909 if (this.node.children.length) {
19910 this.node.lets.forEach(l => {
19911 extract_names(l.value || l.name).forEach(name => {
19912 renderer.add_to_context(name, true);
19913 });
19914 });
19915 const default_slot = block.child({
19916 comment: create_debugging_comment(node, renderer.component),
19917 name: renderer.component.get_unique_name(`create_default_slot`),
19918 type: 'slot'
19919 });
19920 this.renderer.blocks.push(default_slot);
19921 this.slots.set('default', get_slot_definition(default_slot, this.node.scope, this.node.lets));
19922 this.fragment = new FragmentWrapper(renderer, default_slot, node.children, this, strip_whitespace, next_sibling);
19923 const dependencies = new Set();
19924 // TODO is this filtering necessary? (I *think* so)
19925 default_slot.dependencies.forEach(name => {
19926 if (!this.node.scope.is_let(name)) {
19927 dependencies.add(name);
19928 }
19929 });
19930 block.add_dependencies(dependencies);
19931 }
19932 block.add_outro();
19933 }
19934 warn_if_reactive() {
19935 const { name } = this.node;
19936 const variable = this.renderer.component.var_lookup.get(name);
19937 if (!variable) {
19938 return;
19939 }
19940 if (variable.reassigned || variable.export_name || variable.is_reactive_dependency) {
19941 this.renderer.component.warn(this.node, {
19942 code: 'reactive-component',
19943 message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`,
19944 });
19945 }
19946 }
19947 render(block, parent_node, parent_nodes) {
19948 this.warn_if_reactive();
19949 const { renderer } = this;
19950 const { component } = renderer;
19951 const name = this.var;
19952 block.add_variable(name);
19953 const component_opts = x `{}`;
19954 const statements = [];
19955 const updates = [];
19956 if (this.fragment) {
19957 this.renderer.add_to_context('$$scope', true);
19958 const default_slot = this.slots.get('default');
19959 this.fragment.nodes.forEach((child) => {
19960 child.render(default_slot.block, null, x `#nodes`);
19961 });
19962 }
19963 let props;
19964 const name_changes = block.get_unique_name(`${name.name}_changes`);
19965 const uses_spread = !!this.node.attributes.find(a => a.is_spread);
19966 // removing empty slot
19967 for (const slot of this.slots.keys()) {
19968 if (!this.slots.get(slot).block.has_content()) {
19969 this.renderer.remove_block(this.slots.get(slot).block);
19970 this.slots.delete(slot);
19971 }
19972 }
19973 const initial_props = this.slots.size > 0
19974 ? [
19975 p `$$slots: {
19976 ${Array.from(this.slots).map(([name, slot]) => {
19977 return p `${name}: [${slot.block.name}, ${slot.get_context || null}, ${slot.get_changes || null}]`;
19978 })}
19979 }`,
19980 p `$$scope: {
19981 ctx: #ctx
19982 }`
19983 ]
19984 : [];
19985 const attribute_object = uses_spread
19986 ? x `{ ${initial_props} }`
19987 : x `{
19988 ${this.node.attributes.map(attr => p `${attr.name}: ${attr.get_value(block)}`)},
19989 ${initial_props}
19990 }`;
19991 if (this.node.attributes.length || this.node.bindings.length || initial_props.length) {
19992 if (!uses_spread && this.node.bindings.length === 0) {
19993 component_opts.properties.push(p `props: ${attribute_object}`);
19994 }
19995 else {
19996 props = block.get_unique_name(`${name.name}_props`);
19997 component_opts.properties.push(p `props: ${props}`);
19998 }
19999 }
20000 if (component.compile_options.dev) {
20001 // TODO this is a terrible hack, but without it the component
20002 // will complain that options.target is missing. This would
20003 // work better if components had separate public and private
20004 // APIs
20005 component_opts.properties.push(p `$$inline: true`);
20006 }
20007 const fragment_dependencies = new Set(this.fragment ? ['$$scope'] : []);
20008 this.slots.forEach(slot => {
20009 slot.block.dependencies.forEach(name => {
20010 const is_let = slot.scope.is_let(name);
20011 const variable = renderer.component.var_lookup.get(name);
20012 if (is_let || is_dynamic$1(variable))
20013 fragment_dependencies.add(name);
20014 });
20015 });
20016 const dynamic_attributes = this.node.attributes.filter(a => a.get_dependencies().length > 0);
20017 if (!uses_spread && (dynamic_attributes.length > 0 || this.node.bindings.length > 0 || fragment_dependencies.size > 0)) {
20018 updates.push(b `const ${name_changes} = {};`);
20019 }
20020 if (this.node.attributes.length) {
20021 if (uses_spread) {
20022 const levels = block.get_unique_name(`${this.var.name}_spread_levels`);
20023 const initial_props = [];
20024 const changes = [];
20025 const all_dependencies = new Set();
20026 this.node.attributes.forEach(attr => {
20027 add_to_set(all_dependencies, attr.dependencies);
20028 });
20029 this.node.attributes.forEach((attr, i) => {
20030 const { name, dependencies } = attr;
20031 const condition = dependencies.size > 0 && (dependencies.size !== all_dependencies.size)
20032 ? renderer.dirty(Array.from(dependencies))
20033 : null;
20034 const unchanged = dependencies.size === 0;
20035 let change_object;
20036 if (attr.is_spread) {
20037 const value = attr.expression.manipulate(block);
20038 initial_props.push(value);
20039 let value_object = value;
20040 if (attr.expression.node.type !== 'ObjectExpression') {
20041 value_object = x `@get_spread_object(${value})`;
20042 }
20043 change_object = value_object;
20044 }
20045 else {
20046 const obj = x `{ ${name}: ${attr.get_value(block)} }`;
20047 initial_props.push(obj);
20048 change_object = obj;
20049 }
20050 changes.push(unchanged
20051 ? x `${levels}[${i}]`
20052 : condition
20053 ? x `${condition} && ${change_object}`
20054 : change_object);
20055 });
20056 block.chunks.init.push(b `
20057 const ${levels} = [
20058 ${initial_props}
20059 ];
20060 `);
20061 statements.push(b `
20062 for (let #i = 0; #i < ${levels}.length; #i += 1) {
20063 ${props} = @assign(${props}, ${levels}[#i]);
20064 }
20065 `);
20066 if (all_dependencies.size) {
20067 const condition = renderer.dirty(Array.from(all_dependencies));
20068 updates.push(b `
20069 const ${name_changes} = ${condition} ? @get_spread_update(${levels}, [
20070 ${changes}
20071 ]) : {}
20072 `);
20073 }
20074 else {
20075 updates.push(b `
20076 const ${name_changes} = {};
20077 `);
20078 }
20079 }
20080 else {
20081 dynamic_attributes.forEach((attribute) => {
20082 const dependencies = attribute.get_dependencies();
20083 if (dependencies.length > 0) {
20084 const condition = renderer.dirty(dependencies);
20085 updates.push(b `
20086 if (${condition}) ${name_changes}.${attribute.name} = ${attribute.get_value(block)};
20087 `);
20088 }
20089 });
20090 }
20091 }
20092 if (fragment_dependencies.size > 0) {
20093 updates.push(b `
20094 if (${renderer.dirty(Array.from(fragment_dependencies))}) {
20095 ${name_changes}.$$scope = { dirty: #dirty, ctx: #ctx };
20096 }`);
20097 }
20098 const munged_bindings = this.node.bindings.map(binding => {
20099 component.has_reactive_assignments = true;
20100 if (binding.name === 'this') {
20101 return bind_this(component, block, new BindingWrapper(block, binding, this), this.var);
20102 }
20103 const id = component.get_unique_name(`${this.var.name}_${binding.name}_binding`);
20104 renderer.add_to_context(id.name);
20105 const callee = renderer.reference(id);
20106 const updating = block.get_unique_name(`updating_${binding.name}`);
20107 block.add_variable(updating);
20108 const snippet = binding.expression.manipulate(block);
20109 statements.push(b `
20110 if (${snippet} !== void 0) {
20111 ${props}.${binding.name} = ${snippet};
20112 }`);
20113 updates.push(b `
20114 if (!${updating} && ${renderer.dirty(Array.from(binding.expression.dependencies))}) {
20115 ${updating} = true;
20116 ${name_changes}.${binding.name} = ${snippet};
20117 @add_flush_callback(() => ${updating} = false);
20118 }
20119 `);
20120 const contextual_dependencies = Array.from(binding.expression.contextual_dependencies);
20121 const dependencies = Array.from(binding.expression.dependencies);
20122 let lhs = binding.raw_expression;
20123 if (binding.is_contextual && binding.expression.node.type === 'Identifier') {
20124 // bind:x={y} — we can't just do `y = x`, we need to
20125 // to `array[index] = x;
20126 const { name } = binding.expression.node;
20127 const { object, property, snippet } = block.bindings.get(name);
20128 lhs = snippet;
20129 contextual_dependencies.push(object.name, property.name);
20130 }
20131 const params = [x `#value`];
20132 if (contextual_dependencies.length > 0) {
20133 const args = [];
20134 contextual_dependencies.forEach(name => {
20135 params.push({
20136 type: 'Identifier',
20137 name
20138 });
20139 renderer.add_to_context(name, true);
20140 args.push(renderer.reference(name));
20141 });
20142 block.chunks.init.push(b `
20143 function ${id}(#value) {
20144 ${callee}.call(null, #value, ${args});
20145 }
20146 `);
20147 block.maintain_context = true; // TODO put this somewhere more logical
20148 }
20149 else {
20150 block.chunks.init.push(b `
20151 function ${id}(#value) {
20152 ${callee}.call(null, #value);
20153 }
20154 `);
20155 }
20156 const body = b `
20157 function ${id}(${params}) {
20158 ${lhs} = #value;
20159 ${renderer.invalidate(dependencies[0])};
20160 }
20161 `;
20162 component.partly_hoisted.push(body);
20163 return b `@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
20164 });
20165 const munged_handlers = this.node.handlers.map(handler => {
20166 const event_handler = new EventHandlerWrapper(handler, this);
20167 let snippet = event_handler.get_snippet(block);
20168 if (handler.modifiers.has('once'))
20169 snippet = x `@once(${snippet})`;
20170 return b `${name}.$on("${handler.name}", ${snippet});`;
20171 });
20172 if (this.node.name === 'svelte:component') {
20173 const switch_value = block.get_unique_name('switch_value');
20174 const switch_props = block.get_unique_name('switch_props');
20175 const snippet = this.node.expression.manipulate(block);
20176 block.chunks.init.push(b `
20177 var ${switch_value} = ${snippet};
20178
20179 function ${switch_props}(#ctx) {
20180 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
20181 ${props && b `let ${props} = ${attribute_object};`}`}
20182 ${statements}
20183 return ${component_opts};
20184 }
20185
20186 if (${switch_value}) {
20187 ${name} = new ${switch_value}(${switch_props}(#ctx));
20188
20189 ${munged_bindings}
20190 ${munged_handlers}
20191 }
20192 `);
20193 block.chunks.create.push(b `if (${name}) @create_component(${name}.$$.fragment);`);
20194 if (parent_nodes && this.renderer.options.hydratable) {
20195 block.chunks.claim.push(b `if (${name}) @claim_component(${name}.$$.fragment, ${parent_nodes});`);
20196 }
20197 block.chunks.mount.push(b `
20198 if (${name}) {
20199 @mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20200 }
20201 `);
20202 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
20203 const update_mount_node = this.get_update_mount_node(anchor);
20204 if (updates.length) {
20205 block.chunks.update.push(b `
20206 ${updates}
20207 `);
20208 }
20209 block.chunks.update.push(b `
20210 if (${switch_value} !== (${switch_value} = ${snippet})) {
20211 if (${name}) {
20212 @group_outros();
20213 const old_component = ${name};
20214 @transition_out(old_component.$$.fragment, 1, 0, () => {
20215 @destroy_component(old_component, 1);
20216 });
20217 @check_outros();
20218 }
20219
20220 if (${switch_value}) {
20221 ${name} = new ${switch_value}(${switch_props}(#ctx));
20222
20223 ${munged_bindings}
20224 ${munged_handlers}
20225
20226 @create_component(${name}.$$.fragment);
20227 @transition_in(${name}.$$.fragment, 1);
20228 @mount_component(${name}, ${update_mount_node}, ${anchor});
20229 } else {
20230 ${name} = null;
20231 }
20232 } else if (${switch_value}) {
20233 ${updates.length > 0 && b `${name}.$set(${name_changes});`}
20234 }
20235 `);
20236 block.chunks.intro.push(b `
20237 if (${name}) @transition_in(${name}.$$.fragment, #local);
20238 `);
20239 block.chunks.outro.push(b `if (${name}) @transition_out(${name}.$$.fragment, #local);`);
20240 block.chunks.destroy.push(b `if (${name}) @destroy_component(${name}, ${parent_node ? null : 'detaching'});`);
20241 }
20242 else {
20243 const expression = this.node.name === 'svelte:self'
20244 ? component.name
20245 : this.renderer.reference(this.node.name);
20246 block.chunks.init.push(b `
20247 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
20248 ${props && b `let ${props} = ${attribute_object};`}`}
20249 ${statements}
20250 ${name} = new ${expression}(${component_opts});
20251
20252 ${munged_bindings}
20253 ${munged_handlers}
20254 `);
20255 block.chunks.create.push(b `@create_component(${name}.$$.fragment);`);
20256 if (parent_nodes && this.renderer.options.hydratable) {
20257 block.chunks.claim.push(b `@claim_component(${name}.$$.fragment, ${parent_nodes});`);
20258 }
20259 block.chunks.mount.push(b `@mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});`);
20260 block.chunks.intro.push(b `
20261 @transition_in(${name}.$$.fragment, #local);
20262 `);
20263 if (updates.length) {
20264 block.chunks.update.push(b `
20265 ${updates}
20266 ${name}.$set(${name_changes});
20267 `);
20268 }
20269 block.chunks.destroy.push(b `
20270 @destroy_component(${name}, ${parent_node ? null : 'detaching'});
20271 `);
20272 block.chunks.outro.push(b `@transition_out(${name}.$$.fragment, #local);`);
20273 }
20274 }
20275 }
20276
20277 function get_slot_data(values, block = null) {
20278 return {
20279 type: 'ObjectExpression',
20280 properties: Array.from(values.values())
20281 .filter(attribute => attribute.name !== 'name')
20282 .map(attribute => {
20283 const value = get_value(block, attribute);
20284 return p `${attribute.name}: ${value}`;
20285 })
20286 };
20287 }
20288 function get_value(block, attribute) {
20289 if (attribute.is_true)
20290 return x `true`;
20291 if (attribute.chunks.length === 0)
20292 return x `""`;
20293 let value = attribute.chunks
20294 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : (block ? chunk.manipulate(block) : chunk.node))
20295 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20296 if (attribute.chunks.length > 1 && attribute.chunks[0].type !== 'Text') {
20297 value = x `"" + ${value}`;
20298 }
20299 return value;
20300 }
20301
20302 class SlotWrapper extends Wrapper {
20303 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20304 super(renderer, block, parent, node);
20305 this.fallback = null;
20306 this.var = { type: 'Identifier', name: 'slot' };
20307 this.dependencies = new Set(['$$scope']);
20308 this.cannot_use_innerhtml();
20309 this.not_static_content();
20310 if (this.node.children.length) {
20311 this.fallback = block.child({
20312 comment: create_debugging_comment(this.node.children[0], this.renderer.component),
20313 name: this.renderer.component.get_unique_name(`fallback_block`),
20314 type: 'fallback'
20315 });
20316 renderer.blocks.push(this.fallback);
20317 }
20318 this.fragment = new FragmentWrapper(renderer, this.fallback, node.children, this, strip_whitespace, next_sibling);
20319 this.node.values.forEach(attribute => {
20320 add_to_set(this.dependencies, attribute.dependencies);
20321 });
20322 block.add_dependencies(this.dependencies);
20323 // we have to do this, just in case
20324 block.add_intro();
20325 block.add_outro();
20326 }
20327 render(block, parent_node, parent_nodes) {
20328 const { renderer } = this;
20329 const { slot_name } = this.node;
20330 let get_slot_changes_fn;
20331 let get_slot_context_fn;
20332 if (this.node.values.size > 0) {
20333 get_slot_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_changes`);
20334 get_slot_context_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_context`);
20335 const changes = x `{}`;
20336 const dependencies = new Set();
20337 this.node.values.forEach(attribute => {
20338 attribute.chunks.forEach(chunk => {
20339 if (chunk.dependencies) {
20340 add_to_set(dependencies, chunk.contextual_dependencies);
20341 // add_to_set(dependencies, (chunk as Expression).dependencies);
20342 chunk.dependencies.forEach(name => {
20343 const variable = renderer.component.var_lookup.get(name);
20344 if (variable && !variable.hoistable)
20345 dependencies.add(name);
20346 });
20347 }
20348 });
20349 const dynamic_dependencies = Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name));
20350 if (dynamic_dependencies.length > 0) {
20351 changes.properties.push(p `${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`);
20352 }
20353 });
20354 renderer.blocks.push(b `
20355 const ${get_slot_changes_fn} = #dirty => ${changes};
20356 const ${get_slot_context_fn} = #ctx => ${get_slot_data(this.node.values, block)};
20357 `);
20358 }
20359 else {
20360 get_slot_changes_fn = 'null';
20361 get_slot_context_fn = 'null';
20362 }
20363 let has_fallback = !!this.fallback;
20364 if (this.fallback) {
20365 this.fragment.render(this.fallback, null, x `#nodes`);
20366 has_fallback = this.fallback.has_content();
20367 if (!has_fallback) {
20368 renderer.remove_block(this.fallback);
20369 }
20370 }
20371 const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`);
20372 const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
20373 const slot_or_fallback = has_fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot;
20374 block.chunks.init.push(b `
20375 const ${slot_definition} = ${renderer.reference('$$slots')}.${slot_name};
20376 const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn});
20377 ${has_fallback ? b `const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
20378 `);
20379 block.chunks.create.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.c();`);
20380 if (renderer.options.hydratable) {
20381 block.chunks.claim.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});`);
20382 }
20383 block.chunks.mount.push(b `
20384 if (${slot_or_fallback}) {
20385 ${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20386 }
20387 `);
20388 block.chunks.intro.push(b `@transition_in(${slot_or_fallback}, #local);`);
20389 block.chunks.outro.push(b `@transition_out(${slot_or_fallback}, #local);`);
20390 const dynamic_dependencies = Array.from(this.dependencies).filter((name) => this.is_dependency_dynamic(name));
20391 const fallback_dynamic_dependencies = has_fallback
20392 ? Array.from(this.fallback.dependencies).filter((name) => this.is_dependency_dynamic(name))
20393 : [];
20394 const slot_update = b `
20395 if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
20396 @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn});
20397 }
20398 `;
20399 const fallback_update = has_fallback && fallback_dynamic_dependencies.length > 0 && b `
20400 if (${slot_or_fallback} && ${slot_or_fallback}.p && ${renderer.dirty(fallback_dynamic_dependencies)}) {
20401 ${slot_or_fallback}.p(#ctx, #dirty);
20402 }
20403 `;
20404 if (fallback_update) {
20405 block.chunks.update.push(b `
20406 if (${slot}) {
20407 ${slot_update}
20408 } else {
20409 ${fallback_update}
20410 }
20411 `);
20412 }
20413 else {
20414 block.chunks.update.push(b `
20415 if (${slot}) {
20416 ${slot_update}
20417 }
20418 `);
20419 }
20420 block.chunks.destroy.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`);
20421 }
20422 is_dependency_dynamic(name) {
20423 if (name === '$$scope')
20424 return true;
20425 if (this.node.scope.is_let(name))
20426 return true;
20427 if (is_reserved_keyword(name))
20428 return true;
20429 const variable = this.renderer.component.var_lookup.get(name);
20430 return is_dynamic$1(variable);
20431 }
20432 }
20433
20434 class TitleWrapper extends Wrapper {
20435 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
20436 super(renderer, block, parent, node);
20437 }
20438 render(block, _parent_node, _parent_nodes) {
20439 const is_dynamic = !!this.node.children.find(node => node.type !== 'Text');
20440 if (is_dynamic) {
20441 let value;
20442 const all_dependencies = new Set();
20443 // TODO some of this code is repeated in Tag.ts — would be good to
20444 // DRY it out if that's possible without introducing crazy indirection
20445 if (this.node.children.length === 1) {
20446 // single {tag} — may be a non-string
20447 // @ts-ignore todo: check this
20448 const { expression } = this.node.children[0];
20449 value = expression.manipulate(block);
20450 add_to_set(all_dependencies, expression.dependencies);
20451 }
20452 else {
20453 // '{foo} {bar}' — treat as string concatenation
20454 value = this.node.children
20455 .map(chunk => {
20456 if (chunk.type === 'Text')
20457 return string_literal(chunk.data);
20458 chunk.expression.dependencies.forEach(d => {
20459 all_dependencies.add(d);
20460 });
20461 return chunk.expression.manipulate(block);
20462 })
20463 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20464 if (this.node.children[0].type !== 'Text') {
20465 value = x `"" + ${value}`;
20466 }
20467 }
20468 const last = this.node.should_cache && block.get_unique_name(`title_value`);
20469 if (this.node.should_cache)
20470 block.add_variable(last);
20471 const init = this.node.should_cache ? x `${last} = ${value}` : value;
20472 block.chunks.init.push(b `@_document.title = ${init};`);
20473 const updater = b `@_document.title = ${this.node.should_cache ? last : value};`;
20474 if (all_dependencies.size) {
20475 const dependencies = Array.from(all_dependencies);
20476 let condition = block.renderer.dirty(dependencies);
20477 if (block.has_outros) {
20478 condition = x `!#current || ${condition}`;
20479 }
20480 if (this.node.should_cache) {
20481 condition = x `${condition} && (${last} !== (${last} = ${value}))`;
20482 }
20483 block.chunks.update.push(b `
20484 if (${condition}) {
20485 ${updater}
20486 }`);
20487 }
20488 }
20489 else {
20490 const value = this.node.children.length > 0
20491 ? string_literal(this.node.children[0].data)
20492 : x `""`;
20493 block.chunks.hydrate.push(b `@_document.title = ${value};`);
20494 }
20495 }
20496 }
20497
20498 const associated_events = {
20499 innerWidth: 'resize',
20500 innerHeight: 'resize',
20501 outerWidth: 'resize',
20502 outerHeight: 'resize',
20503 scrollX: 'scroll',
20504 scrollY: 'scroll',
20505 };
20506 const properties = {
20507 scrollX: 'pageXOffset',
20508 scrollY: 'pageYOffset'
20509 };
20510 const readonly = new Set([
20511 'innerWidth',
20512 'innerHeight',
20513 'outerWidth',
20514 'outerHeight',
20515 'online',
20516 ]);
20517 class WindowWrapper extends Wrapper {
20518 constructor(renderer, block, parent, node) {
20519 super(renderer, block, parent, node);
20520 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
20521 }
20522 render(block, _parent_node, _parent_nodes) {
20523 const { renderer } = this;
20524 const { component } = renderer;
20525 const events = {};
20526 const bindings = {};
20527 add_actions(block, '@_window', this.node.actions);
20528 add_event_handlers(block, '@_window', this.handlers);
20529 this.node.bindings.forEach(binding => {
20530 // in dev mode, throw if read-only values are written to
20531 if (readonly.has(binding.name)) {
20532 renderer.readonly.add(binding.expression.node.name);
20533 }
20534 bindings[binding.name] = binding.expression.node.name;
20535 // bind:online is a special case, we need to listen for two separate events
20536 if (binding.name === 'online')
20537 return;
20538 const associated_event = associated_events[binding.name];
20539 const property = properties[binding.name] || binding.name;
20540 if (!events[associated_event])
20541 events[associated_event] = [];
20542 events[associated_event].push({
20543 name: binding.expression.node.name,
20544 value: property
20545 });
20546 });
20547 const scrolling = block.get_unique_name(`scrolling`);
20548 const clear_scrolling = block.get_unique_name(`clear_scrolling`);
20549 const scrolling_timeout = block.get_unique_name(`scrolling_timeout`);
20550 Object.keys(events).forEach(event => {
20551 const id = block.get_unique_name(`onwindow${event}`);
20552 const props = events[event];
20553 renderer.add_to_context(id.name);
20554 const fn = renderer.reference(id.name);
20555 if (event === 'scroll') {
20556 // TODO other bidirectional bindings...
20557 block.add_variable(scrolling, x `false`);
20558 block.add_variable(clear_scrolling, x `() => { ${scrolling} = false }`);
20559 block.add_variable(scrolling_timeout);
20560 const condition = bindings.scrollX && bindings.scrollY
20561 ? x `"${bindings.scrollX}" in this._state || "${bindings.scrollY}" in this._state`
20562 : x `"${bindings.scrollX || bindings.scrollY}" in this._state`;
20563 const scrollX = bindings.scrollX && x `this._state.${bindings.scrollX}`;
20564 const scrollY = bindings.scrollY && x `this._state.${bindings.scrollY}`;
20565 renderer.meta_bindings.push(b `
20566 if (${condition}) {
20567 @_scrollTo(${scrollX || '@_window.pageXOffset'}, ${scrollY || '@_window.pageYOffset'});
20568 }
20569 ${scrollX && `${scrollX} = @_window.pageXOffset;`}
20570 ${scrollY && `${scrollY} = @_window.pageYOffset;`}
20571 `);
20572 block.event_listeners.push(x `
20573 @listen(@_window, "${event}", () => {
20574 ${scrolling} = true;
20575 @_clearTimeout(${scrolling_timeout});
20576 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
20577 ${fn}();
20578 })
20579 `);
20580 }
20581 else {
20582 props.forEach(prop => {
20583 renderer.meta_bindings.push(b `this._state.${prop.name} = @_window.${prop.value};`);
20584 });
20585 block.event_listeners.push(x `
20586 @listen(@_window, "${event}", ${fn})
20587 `);
20588 }
20589 component.partly_hoisted.push(b `
20590 function ${id}() {
20591 ${props.map(prop => renderer.invalidate(prop.name, x `${prop.name} = @_window.${prop.value}`))}
20592 }
20593 `);
20594 block.chunks.init.push(b `
20595 @add_render_callback(${fn});
20596 `);
20597 component.has_reactive_assignments = true;
20598 });
20599 // special case... might need to abstract this out if we add more special cases
20600 if (bindings.scrollX || bindings.scrollY) {
20601 const condition = renderer.dirty([bindings.scrollX, bindings.scrollY].filter(Boolean));
20602 const scrollX = bindings.scrollX ? renderer.reference(bindings.scrollX) : x `@_window.pageXOffset`;
20603 const scrollY = bindings.scrollY ? renderer.reference(bindings.scrollY) : x `@_window.pageYOffset`;
20604 block.chunks.update.push(b `
20605 if (${condition} && !${scrolling}) {
20606 ${scrolling} = true;
20607 @_clearTimeout(${scrolling_timeout});
20608 @_scrollTo(${scrollX}, ${scrollY});
20609 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
20610 }
20611 `);
20612 }
20613 // another special case. (I'm starting to think these are all special cases.)
20614 if (bindings.online) {
20615 const id = block.get_unique_name(`onlinestatuschanged`);
20616 const name = bindings.online;
20617 renderer.add_to_context(id.name);
20618 const reference = renderer.reference(id.name);
20619 component.partly_hoisted.push(b `
20620 function ${id}() {
20621 ${renderer.invalidate(name, x `${name} = @_navigator.onLine`)}
20622 }
20623 `);
20624 block.chunks.init.push(b `
20625 @add_render_callback(${reference});
20626 `);
20627 block.event_listeners.push(x `@listen(@_window, "online", ${reference})`, x `@listen(@_window, "offline", ${reference})`);
20628 component.has_reactive_assignments = true;
20629 }
20630 }
20631 }
20632
20633 function link(next, prev) {
20634 prev.next = next;
20635 if (next)
20636 next.prev = prev;
20637 }
20638
20639 const wrappers = {
20640 AwaitBlock: AwaitBlockWrapper,
20641 Body: BodyWrapper,
20642 Comment: null,
20643 DebugTag: DebugTagWrapper,
20644 EachBlock: EachBlockWrapper,
20645 Element: ElementWrapper,
20646 Head: HeadWrapper,
20647 IfBlock: IfBlockWrapper,
20648 InlineComponent: InlineComponentWrapper,
20649 MustacheTag: MustacheTagWrapper,
20650 Options: null,
20651 RawMustacheTag: RawMustacheTagWrapper,
20652 Slot: SlotWrapper,
20653 Text: TextWrapper,
20654 Title: TitleWrapper,
20655 Window: WindowWrapper
20656 };
20657 function trimmable_at(child, next_sibling) {
20658 // Whitespace is trimmable if one of the following is true:
20659 // The child and its sibling share a common nearest each block (not at an each block boundary)
20660 // The next sibling's previous node is an each block
20661 return (next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/)) || next_sibling.node.prev.type === 'EachBlock';
20662 }
20663 class FragmentWrapper {
20664 constructor(renderer, block, nodes, parent, strip_whitespace, next_sibling) {
20665 this.nodes = [];
20666 let last_child;
20667 let window_wrapper;
20668 let i = nodes.length;
20669 while (i--) {
20670 const child = nodes[i];
20671 if (!child.type) {
20672 throw new Error(`missing type`);
20673 }
20674 if (!(child.type in wrappers)) {
20675 throw new Error(`TODO implement ${child.type}`);
20676 }
20677 // special case — this is an easy way to remove whitespace surrounding
20678 // <svelte:window/>. lil hacky but it works
20679 if (child.type === 'Window') {
20680 window_wrapper = new WindowWrapper(renderer, block, parent, child);
20681 continue;
20682 }
20683 if (child.type === 'Text') {
20684 let { data } = child;
20685 // We want to remove trailing whitespace inside an element/component/block,
20686 // *unless* there is no whitespace between this node and its next sibling
20687 if (this.nodes.length === 0) {
20688 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'));
20689 if (should_trim) {
20690 data = trim_end(data);
20691 if (!data)
20692 continue;
20693 }
20694 }
20695 // glue text nodes (which could e.g. be separated by comments) together
20696 if (last_child && last_child.node.type === 'Text') {
20697 last_child.data = data + last_child.data;
20698 continue;
20699 }
20700 const wrapper = new TextWrapper(renderer, block, parent, child, data);
20701 if (wrapper.skip)
20702 continue;
20703 this.nodes.unshift(wrapper);
20704 link(last_child, last_child = wrapper);
20705 }
20706 else {
20707 const Wrapper = wrappers[child.type];
20708 if (!Wrapper)
20709 continue;
20710 const wrapper = new Wrapper(renderer, block, parent, child, strip_whitespace, last_child || next_sibling);
20711 this.nodes.unshift(wrapper);
20712 link(last_child, last_child = wrapper);
20713 }
20714 }
20715 if (strip_whitespace) {
20716 const first = this.nodes[0];
20717 if (first && first.node.type === 'Text') {
20718 first.data = trim_start(first.data);
20719 if (!first.data) {
20720 first.var = null;
20721 this.nodes.shift();
20722 if (this.nodes[0]) {
20723 this.nodes[0].prev = null;
20724 }
20725 }
20726 }
20727 }
20728 if (window_wrapper) {
20729 this.nodes.unshift(window_wrapper);
20730 link(last_child, window_wrapper);
20731 }
20732 }
20733 render(block, parent_node, parent_nodes) {
20734 for (let i = 0; i < this.nodes.length; i += 1) {
20735 this.nodes[i].render(block, parent_node, parent_nodes);
20736 }
20737 }
20738 }
20739
20740 class Renderer {
20741 constructor(component, options) {
20742 this.context = [];
20743 this.initial_context = [];
20744 this.context_lookup = new Map();
20745 this.blocks = [];
20746 this.readonly = new Set();
20747 this.meta_bindings = []; // initial values for e.g. window.innerWidth, if there's a <svelte:window> meta tag
20748 this.binding_groups = new Map();
20749 this.component = component;
20750 this.options = options;
20751 this.locate = component.locate; // TODO messy
20752 this.file_var = options.dev && this.component.get_unique_name('file');
20753 component.vars.filter(v => !v.hoistable || (v.export_name && !v.module)).forEach(v => this.add_to_context(v.name));
20754 // ensure store values are included in context
20755 component.vars.filter(v => v.subscribable).forEach(v => this.add_to_context(`$${v.name}`));
20756 reserved_keywords.forEach(keyword => {
20757 if (component.var_lookup.has(keyword)) {
20758 this.add_to_context(keyword);
20759 }
20760 });
20761 if (component.slots.size > 0) {
20762 this.add_to_context('$$scope');
20763 this.add_to_context('$$slots');
20764 }
20765 if (this.binding_groups.size > 0) {
20766 this.add_to_context('$$binding_groups');
20767 }
20768 // main block
20769 this.block = new Block$1({
20770 renderer: this,
20771 name: null,
20772 type: 'component',
20773 key: null,
20774 bindings: new Map(),
20775 dependencies: new Set(),
20776 });
20777 this.block.has_update_method = true;
20778 this.fragment = new FragmentWrapper(this, this.block, component.fragment.children, null, true, null);
20779 // TODO messy
20780 this.blocks.forEach(block => {
20781 if (block instanceof Block$1) {
20782 block.assign_variable_names();
20783 }
20784 });
20785 this.block.assign_variable_names();
20786 this.fragment.render(this.block, null, x `#nodes`);
20787 this.context_overflow = this.context.length > 31;
20788 this.context.forEach(member => {
20789 const { variable } = member;
20790 if (variable) {
20791 member.priority += 2;
20792 if (variable.mutated || variable.reassigned)
20793 member.priority += 4;
20794 // these determine whether variable is included in initial context
20795 // array, so must have the highest priority
20796 if (variable.export_name)
20797 member.priority += 16;
20798 if (variable.referenced)
20799 member.priority += 32;
20800 }
20801 else if (member.is_non_contextual) {
20802 // determine whether variable is included in initial context
20803 // array, so must have the highest priority
20804 member.priority += 8;
20805 }
20806 if (!member.is_contextual) {
20807 member.priority += 1;
20808 }
20809 });
20810 this.context.sort((a, b) => (b.priority - a.priority) || (a.index.value - b.index.value));
20811 this.context.forEach((member, i) => member.index.value = i);
20812 let i = this.context.length;
20813 while (i--) {
20814 const member = this.context[i];
20815 if (member.variable) {
20816 if (member.variable.referenced || member.variable.export_name)
20817 break;
20818 }
20819 else if (member.is_non_contextual) {
20820 break;
20821 }
20822 }
20823 this.initial_context = this.context.slice(0, i + 1);
20824 }
20825 add_to_context(name, contextual = false) {
20826 if (!this.context_lookup.has(name)) {
20827 const member = {
20828 name,
20829 index: { type: 'Literal', value: this.context.length },
20830 is_contextual: false,
20831 is_non_contextual: false,
20832 variable: null,
20833 priority: 0
20834 };
20835 this.context_lookup.set(name, member);
20836 this.context.push(member);
20837 }
20838 const member = this.context_lookup.get(name);
20839 if (contextual) {
20840 member.is_contextual = true;
20841 }
20842 else {
20843 member.is_non_contextual = true;
20844 const variable = this.component.var_lookup.get(name);
20845 member.variable = variable;
20846 }
20847 return member;
20848 }
20849 invalidate(name, value) {
20850 const variable = this.component.var_lookup.get(name);
20851 const member = this.context_lookup.get(name);
20852 if (variable && (variable.subscribable && (variable.reassigned || variable.export_name))) {
20853 return x `${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
20854 }
20855 if (name[0] === '$' && name[1] !== '$') {
20856 return x `${name.slice(1)}.set(${value || name})`;
20857 }
20858 if (variable && (variable.module || (!variable.referenced &&
20859 !variable.is_reactive_dependency &&
20860 !variable.export_name &&
20861 !name.startsWith('$$')))) {
20862 return value || name;
20863 }
20864 if (value) {
20865 return x `$$invalidate(${member.index}, ${value})`;
20866 }
20867 // if this is a reactive declaration, invalidate dependencies recursively
20868 const deps = new Set([name]);
20869 deps.forEach(name => {
20870 const reactive_declarations = this.component.reactive_declarations.filter(x => x.assignees.has(name));
20871 reactive_declarations.forEach(declaration => {
20872 declaration.dependencies.forEach(name => {
20873 deps.add(name);
20874 });
20875 });
20876 });
20877 // TODO ideally globals etc wouldn't be here in the first place
20878 const filtered = Array.from(deps).filter(n => this.context_lookup.has(n));
20879 if (!filtered.length)
20880 return null;
20881 return filtered
20882 .map(n => x `$$invalidate(${this.context_lookup.get(n).index}, ${n})`)
20883 .reduce((lhs, rhs) => x `${lhs}, ${rhs}`);
20884 }
20885 dirty(names, is_reactive_declaration = false) {
20886 const renderer = this;
20887 const dirty = (is_reactive_declaration
20888 ? x `$$self.$$.dirty`
20889 : x `#dirty`);
20890 const get_bitmask = () => {
20891 const bitmask = [];
20892 names.forEach((name) => {
20893 const member = renderer.context_lookup.get(name);
20894 if (!member)
20895 return;
20896 if (member.index.value === -1) {
20897 throw new Error(`unset index`);
20898 }
20899 const value = member.index.value;
20900 const i = (value / 31) | 0;
20901 const n = 1 << (value % 31);
20902 if (!bitmask[i])
20903 bitmask[i] = { n: 0, names: [] };
20904 bitmask[i].n |= n;
20905 bitmask[i].names.push(name);
20906 });
20907 return bitmask;
20908 };
20909 // TODO: context-overflow make it less gross
20910 return {
20911 // Using a ParenthesizedExpression allows us to create
20912 // the expression lazily. TODO would be better if
20913 // context was determined before rendering, so that
20914 // this indirection was unnecessary
20915 type: 'ParenthesizedExpression',
20916 get expression() {
20917 const bitmask = get_bitmask();
20918 if (!bitmask.length) {
20919 return x `${dirty} & /*${names.join(', ')}*/ 0`;
20920 }
20921 if (renderer.context_overflow) {
20922 return bitmask
20923 .map((b, i) => ({ b, i }))
20924 .filter(({ b }) => b)
20925 .map(({ b, i }) => x `${dirty}[${i}] & /*${b.names.join(', ')}*/ ${b.n}`)
20926 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
20927 }
20928 return x `${dirty} & /*${names.join(', ')}*/ ${bitmask[0].n}`;
20929 }
20930 };
20931 }
20932 reference(node) {
20933 if (typeof node === 'string') {
20934 node = { type: 'Identifier', name: node };
20935 }
20936 const { name, nodes } = flatten_reference(node);
20937 const member = this.context_lookup.get(name);
20938 // TODO is this correct?
20939 if (this.component.var_lookup.get(name)) {
20940 this.component.add_reference(name);
20941 }
20942 if (member !== undefined) {
20943 const replacement = x `/*${member.name}*/ #ctx[${member.index}]`;
20944 if (nodes[0].loc)
20945 replacement.object.loc = nodes[0].loc;
20946 nodes[0] = replacement;
20947 return nodes.reduce((lhs, rhs) => x `${lhs}.${rhs}`);
20948 }
20949 return node;
20950 }
20951 remove_block(block) {
20952 this.blocks.splice(this.blocks.indexOf(block), 1);
20953 }
20954 }
20955
20956 function dom(component, options) {
20957 const { name } = component;
20958 const renderer = new Renderer(component, options);
20959 const { block } = renderer;
20960 block.has_outro_method = true;
20961 // prevent fragment being created twice (#1063)
20962 if (options.customElement)
20963 block.chunks.create.push(b `this.c = @noop;`);
20964 const body = [];
20965 if (renderer.file_var) {
20966 const file = component.file ? x `"${component.file}"` : x `undefined`;
20967 body.push(b `const ${renderer.file_var} = ${file};`);
20968 }
20969 const css = component.stylesheet.render(options.filename, !options.customElement);
20970 const styles = component.stylesheet.has_styles && options.dev
20971 ? `${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */`
20972 : css.code;
20973 const add_css = component.get_unique_name('add_css');
20974 const should_add_css = (!options.customElement &&
20975 !!styles &&
20976 options.css !== false);
20977 if (should_add_css) {
20978 body.push(b `
20979 function ${add_css}() {
20980 var style = @element("style");
20981 style.id = "${component.stylesheet.id}-style";
20982 style.textContent = "${styles}";
20983 @append(@_document.head, style);
20984 }
20985 `);
20986 }
20987 // fix order
20988 // TODO the deconflicted names of blocks are reversed... should set them here
20989 const blocks = renderer.blocks.slice().reverse();
20990 body.push(...blocks.map(block => {
20991 // TODO this is a horrible mess — renderer.blocks
20992 // contains a mixture of Blocks and Nodes
20993 if (block.render)
20994 return block.render();
20995 return block;
20996 }));
20997 if (options.dev && !options.hydratable) {
20998 block.chunks.claim.push(b `throw new @_Error("options.hydrate only works if the component was compiled with the \`hydratable: true\` option");`);
20999 }
21000 const uses_props = component.var_lookup.has('$$props');
21001 const uses_rest = component.var_lookup.has('$$restProps');
21002 const $$props = uses_props || uses_rest ? `$$new_props` : `$$props`;
21003 const props = component.vars.filter(variable => !variable.module && variable.export_name);
21004 const writable_props = props.filter(variable => variable.writable);
21005 const omit_props_names = component.get_unique_name('omit_props_names');
21006 const compute_rest = x `@compute_rest_props($$props, ${omit_props_names.name})`;
21007 const rest = uses_rest ? b `
21008 const ${omit_props_names.name} = [${props.map(prop => `"${prop.export_name}"`).join(',')}];
21009 let $$restProps = ${compute_rest};
21010 ` : null;
21011 const set = (uses_props || uses_rest || writable_props.length > 0 || component.slots.size > 0)
21012 ? x `
21013 ${$$props} => {
21014 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`)}
21015 ${uses_rest && !uses_props && x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`}
21016 ${uses_rest && renderer.invalidate('$$restProps', x `$$restProps = ${compute_rest}`)}
21017 ${writable_props.map(prop => b `if ('${prop.export_name}' in ${$$props}) ${renderer.invalidate(prop.name, x `${prop.name} = ${$$props}.${prop.export_name}`)};`)}
21018 ${component.slots.size > 0 &&
21019 b `if ('$$scope' in ${$$props}) ${renderer.invalidate('$$scope', x `$$scope = ${$$props}.$$scope`)};`}
21020 }
21021 `
21022 : null;
21023 const accessors = [];
21024 const not_equal = component.component_options.immutable ? x `@not_equal` : x `@safe_not_equal`;
21025 let dev_props_check;
21026 let inject_state;
21027 let capture_state;
21028 let props_inject;
21029 props.forEach(prop => {
21030 const variable = component.var_lookup.get(prop.name);
21031 if (!variable.writable || component.component_options.accessors) {
21032 accessors.push({
21033 type: 'MethodDefinition',
21034 kind: 'get',
21035 key: { type: 'Identifier', name: prop.export_name },
21036 value: x `function() {
21037 return ${prop.hoistable ? prop.name : x `this.$$.ctx[${renderer.context_lookup.get(prop.name).index}]`}
21038 }`
21039 });
21040 }
21041 else if (component.compile_options.dev) {
21042 accessors.push({
21043 type: 'MethodDefinition',
21044 kind: 'get',
21045 key: { type: 'Identifier', name: prop.export_name },
21046 value: x `function() {
21047 throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
21048 }`
21049 });
21050 }
21051 if (component.component_options.accessors) {
21052 if (variable.writable && !renderer.readonly.has(prop.name)) {
21053 accessors.push({
21054 type: 'MethodDefinition',
21055 kind: 'set',
21056 key: { type: 'Identifier', name: prop.export_name },
21057 value: x `function(${prop.name}) {
21058 this.$set({ ${prop.export_name}: ${prop.name} });
21059 @flush();
21060 }`
21061 });
21062 }
21063 else if (component.compile_options.dev) {
21064 accessors.push({
21065 type: 'MethodDefinition',
21066 kind: 'set',
21067 key: { type: 'Identifier', name: prop.export_name },
21068 value: x `function(value) {
21069 throw new @_Error("<${component.tag}>: Cannot set read-only property '${prop.export_name}'");
21070 }`
21071 });
21072 }
21073 }
21074 else if (component.compile_options.dev) {
21075 accessors.push({
21076 type: 'MethodDefinition',
21077 kind: 'set',
21078 key: { type: 'Identifier', name: prop.export_name },
21079 value: x `function(value) {
21080 throw new @_Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
21081 }`
21082 });
21083 }
21084 });
21085 if (component.compile_options.dev) {
21086 // checking that expected ones were passed
21087 const expected = props.filter(prop => prop.writable && !prop.initialised);
21088 if (expected.length) {
21089 dev_props_check = b `
21090 const { ctx: #ctx } = this.$$;
21091 const props = ${options.customElement ? x `this.attributes` : x `options.props || {}`};
21092 ${expected.map(prop => b `
21093 if (${renderer.reference(prop.name)} === undefined && !('${prop.export_name}' in props)) {
21094 @_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'");
21095 }`)}
21096 `;
21097 }
21098 const capturable_vars = component.vars.filter(v => !v.internal && !v.global && !v.name.startsWith('$$'));
21099 if (capturable_vars.length > 0) {
21100 capture_state = x `() => ({ ${capturable_vars.map(prop => p `${prop.name}`)} })`;
21101 }
21102 const injectable_vars = capturable_vars.filter(v => !v.module && v.writable && v.name[0] !== '$');
21103 if (uses_props || injectable_vars.length > 0) {
21104 inject_state = x `
21105 ${$$props} => {
21106 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), $$new_props)`)}
21107 ${injectable_vars.map(v => b `if ('${v.name}' in $$props) ${renderer.invalidate(v.name, x `${v.name} = ${$$props}.${v.name}`)};`)}
21108 }
21109 `;
21110 props_inject = b `
21111 if ($$props && "$$inject" in $$props) {
21112 $$self.$inject_state($$props.$$inject);
21113 }
21114 `;
21115 }
21116 }
21117 // instrument assignments
21118 if (component.ast.instance) {
21119 let scope = component.instance_scope;
21120 const map = component.instance_scope_map;
21121 let execution_context = null;
21122 walk(component.ast.instance.content, {
21123 enter(node) {
21124 if (map.has(node)) {
21125 scope = map.get(node);
21126 if (!execution_context && !scope.block) {
21127 execution_context = node;
21128 }
21129 }
21130 else if (!execution_context && node.type === 'LabeledStatement' && node.label.name === '$') {
21131 execution_context = node;
21132 }
21133 },
21134 leave(node) {
21135 if (map.has(node)) {
21136 scope = scope.parent;
21137 }
21138 if (execution_context === node) {
21139 execution_context = null;
21140 }
21141 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
21142 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
21143 // normally (`a = 1`, `b.c = 2`), there'll be a single name
21144 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
21145 // may be more, in which case we need to tack the extra ones
21146 // onto the initial function call
21147 const names = new Set(extract_names(assignee));
21148 this.replace(invalidate(renderer, scope, node, names, execution_context === null));
21149 }
21150 }
21151 });
21152 component.rewrite_props(({ name, reassigned, export_name }) => {
21153 const value = `$${name}`;
21154 const i = renderer.context_lookup.get(`$${name}`).index;
21155 const insert = (reassigned || export_name)
21156 ? b `${`$$subscribe_${name}`}()`
21157 : b `@component_subscribe($$self, ${name}, #value => $$invalidate(${i}, ${value} = #value))`;
21158 if (component.compile_options.dev) {
21159 return b `@validate_store(${name}, '${name}'); ${insert}`;
21160 }
21161 return insert;
21162 });
21163 }
21164 const args = [x `$$self`];
21165 const has_invalidate = props.length > 0 ||
21166 component.has_reactive_assignments ||
21167 component.slots.size > 0 ||
21168 capture_state ||
21169 inject_state;
21170 if (has_invalidate) {
21171 args.push(x `$$props`, x `$$invalidate`);
21172 }
21173 else if (component.compile_options.dev) {
21174 // $$props arg is still needed for unknown prop check
21175 args.push(x `$$props`);
21176 }
21177 const has_create_fragment = component.compile_options.dev || block.has_content();
21178 if (has_create_fragment) {
21179 body.push(b `
21180 function create_fragment(#ctx) {
21181 ${block.get_contents()}
21182 }
21183 `);
21184 }
21185 body.push(b `
21186 ${component.extract_javascript(component.ast.module)}
21187
21188 ${component.fully_hoisted}
21189 `);
21190 const filtered_props = props.filter(prop => {
21191 const variable = component.var_lookup.get(prop.name);
21192 if (variable.hoistable)
21193 return false;
21194 if (prop.name[0] === '$')
21195 return false;
21196 return true;
21197 });
21198 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
21199 const instance_javascript = component.extract_javascript(component.ast.instance);
21200 const has_definition = (component.compile_options.dev ||
21201 (instance_javascript && instance_javascript.length > 0) ||
21202 filtered_props.length > 0 ||
21203 uses_props ||
21204 component.partly_hoisted.length > 0 ||
21205 renderer.initial_context.length > 0 ||
21206 component.reactive_declarations.length > 0 ||
21207 capture_state ||
21208 inject_state);
21209 const definition = has_definition
21210 ? component.alias('instance')
21211 : { type: 'Literal', value: null };
21212 const reactive_store_subscriptions = reactive_stores
21213 .filter(store => {
21214 const variable = component.var_lookup.get(store.name.slice(1));
21215 return !variable || variable.hoistable;
21216 })
21217 .map(({ name }) => b `
21218 ${component.compile_options.dev && b `@validate_store(${name.slice(1)}, '${name.slice(1)}');`}
21219 @component_subscribe($$self, ${name.slice(1)}, $$value => $$invalidate(${renderer.context_lookup.get(name).index}, ${name} = $$value));
21220 `);
21221 const resubscribable_reactive_store_unsubscribers = reactive_stores
21222 .filter(store => {
21223 const variable = component.var_lookup.get(store.name.slice(1));
21224 return variable && (variable.reassigned || variable.export_name);
21225 })
21226 .map(({ name }) => b `$$self.$$.on_destroy.push(() => ${`$$unsubscribe_${name.slice(1)}`}());`);
21227 if (has_definition) {
21228 const reactive_declarations = [];
21229 const fixed_reactive_declarations = []; // not really 'reactive' but whatever
21230 component.reactive_declarations.forEach(d => {
21231 const dependencies = Array.from(d.dependencies);
21232 const uses_rest_or_props = !!dependencies.find(n => n === '$$props' || n === '$$restProps');
21233 const writable = dependencies.filter(n => {
21234 const variable = component.var_lookup.get(n);
21235 return variable && (variable.export_name || variable.mutated || variable.reassigned);
21236 });
21237 const condition = !uses_rest_or_props && writable.length > 0 && renderer.dirty(writable, true);
21238 let statement = d.node; // TODO remove label (use d.node.body) if it's not referenced
21239 if (condition)
21240 statement = b `if (${condition}) { ${statement} }`[0];
21241 if (condition || uses_rest_or_props) {
21242 reactive_declarations.push(statement);
21243 }
21244 else {
21245 fixed_reactive_declarations.push(statement);
21246 }
21247 });
21248 const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
21249 const variable = component.var_lookup.get(name);
21250 return variable.injected && variable.name[0] !== '$';
21251 });
21252 const reactive_store_declarations = reactive_stores.map(variable => {
21253 const $name = variable.name;
21254 const name = $name.slice(1);
21255 const store = component.var_lookup.get(name);
21256 if (store && (store.reassigned || store.export_name)) {
21257 const unsubscribe = `$$unsubscribe_${name}`;
21258 const subscribe = `$$subscribe_${name}`;
21259 const i = renderer.context_lookup.get($name).index;
21260 return b `let ${$name}, ${unsubscribe} = @noop, ${subscribe} = () => (${unsubscribe}(), ${unsubscribe} = @subscribe(${name}, $$value => $$invalidate(${i}, ${$name} = $$value)), ${name})`;
21261 }
21262 return b `let ${$name};`;
21263 });
21264 let unknown_props_check;
21265 if (component.compile_options.dev && !(uses_props || uses_rest)) {
21266 unknown_props_check = b `
21267 const writable_props = [${writable_props.map(prop => x `'${prop.export_name}'`)}];
21268 @_Object.keys($$props).forEach(key => {
21269 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$') @_console.warn(\`<${component.tag}> was created with unknown prop '\${key}'\`);
21270 });
21271 `;
21272 }
21273 const return_value = {
21274 type: 'ArrayExpression',
21275 elements: renderer.initial_context.map(member => ({
21276 type: 'Identifier',
21277 name: member.name
21278 }))
21279 };
21280 body.push(b `
21281 function ${definition}(${args}) {
21282 ${rest}
21283
21284 ${reactive_store_declarations}
21285
21286 ${reactive_store_subscriptions}
21287
21288 ${resubscribable_reactive_store_unsubscribers}
21289
21290 ${instance_javascript}
21291
21292 ${unknown_props_check}
21293
21294 ${component.slots.size || component.compile_options.dev ? b `let { $$slots = {}, $$scope } = $$props;` : null}
21295 ${component.compile_options.dev && b `@validate_slots('${component.tag}', $$slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
21296
21297 ${renderer.binding_groups.size > 0 && b `const $$binding_groups = [${[...renderer.binding_groups.keys()].map(_ => x `[]`)}];`}
21298
21299 ${component.partly_hoisted}
21300
21301 ${set && b `$$self.$$set = ${set};`}
21302
21303 ${capture_state && b `$$self.$capture_state = ${capture_state};`}
21304
21305 ${inject_state && b `$$self.$inject_state = ${inject_state};`}
21306
21307 ${injected.map(name => b `let ${name};`)}
21308
21309 ${ /* before reactive declarations */props_inject}
21310
21311 ${reactive_declarations.length > 0 && b `
21312 $$self.$$.update = () => {
21313 ${reactive_declarations}
21314 };
21315 `}
21316
21317 ${fixed_reactive_declarations}
21318
21319 ${uses_props && b `$$props = @exclude_internal_props($$props);`}
21320
21321 return ${return_value};
21322 }
21323 `);
21324 }
21325 const prop_indexes = x `{
21326 ${props.filter(v => v.export_name && !v.module).map(v => p `${v.export_name}: ${renderer.context_lookup.get(v.name).index}`)}
21327 }`;
21328 let dirty;
21329 if (renderer.context_overflow) {
21330 dirty = x `[]`;
21331 for (let i = 0; i < renderer.context.length; i += 31) {
21332 dirty.elements.push(x `-1`);
21333 }
21334 }
21335 if (options.customElement) {
21336 const declaration = b `
21337 class ${name} extends @SvelteElement {
21338 constructor(options) {
21339 super();
21340
21341 ${css.code && b `this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
21342
21343 @init(this, { target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
21344
21345 ${dev_props_check}
21346
21347 if (options) {
21348 if (options.target) {
21349 @insert(options.target, this, options.anchor);
21350 }
21351
21352 ${(props.length > 0 || uses_props || uses_rest) && b `
21353 if (options.props) {
21354 this.$set(options.props);
21355 @flush();
21356 }`}
21357 }
21358 }
21359 }
21360 `[0];
21361 if (props.length > 0) {
21362 declaration.body.body.push({
21363 type: 'MethodDefinition',
21364 kind: 'get',
21365 static: true,
21366 computed: false,
21367 key: { type: 'Identifier', name: 'observedAttributes' },
21368 value: x `function() {
21369 return [${props.map(prop => x `"${prop.export_name}"`)}];
21370 }`
21371 });
21372 }
21373 declaration.body.body.push(...accessors);
21374 body.push(declaration);
21375 if (component.tag != null) {
21376 body.push(b `
21377 @_customElements.define("${component.tag}", ${name});
21378 `);
21379 }
21380 }
21381 else {
21382 const superclass = {
21383 type: 'Identifier',
21384 name: options.dev ? '@SvelteComponentDev' : '@SvelteComponent'
21385 };
21386 const declaration = b `
21387 class ${name} extends ${superclass} {
21388 constructor(options) {
21389 super(${options.dev && `options`});
21390 ${should_add_css && b `if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
21391 @init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
21392 ${options.dev && b `@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`}
21393
21394 ${dev_props_check}
21395 }
21396 }
21397 `[0];
21398 declaration.body.body.push(...accessors);
21399 body.push(declaration);
21400 }
21401 return { js: flatten$1(body, []), css };
21402 }
21403 function flatten$1(nodes, target) {
21404 for (let i = 0; i < nodes.length; i += 1) {
21405 const node = nodes[i];
21406 if (Array.isArray(node)) {
21407 flatten$1(node, target);
21408 }
21409 else {
21410 target.push(node);
21411 }
21412 }
21413 return target;
21414 }
21415
21416 function AwaitBlock (node, renderer, options) {
21417 renderer.push();
21418 renderer.render(node.pending.children, options);
21419 const pending = renderer.pop();
21420 renderer.push();
21421 renderer.render(node.then.children, options);
21422 const then = renderer.pop();
21423 renderer.add_expression(x `
21424 function(__value) {
21425 if (@is_promise(__value)) return ${pending};
21426 return (function(${node.then_node ? node.then_node : ''}) { return ${then}; }(__value));
21427 }(${node.expression.node})
21428 `);
21429 }
21430
21431 function Comment$1 (_node, _renderer, _options) {
21432 // TODO preserve comments
21433 // if (options.preserveComments) {
21434 // renderer.append(`<!--${node.data}-->`);
21435 // }
21436 }
21437
21438 function DebugTag (node, renderer, options) {
21439 if (!options.dev)
21440 return;
21441 const filename = options.filename || null;
21442 const { line, column } = options.locate(node.start + 1);
21443 const obj = x `{
21444 ${node.expressions.map(e => p `${e.node.name}`)}
21445 }`;
21446 renderer.add_expression(x `@debug(${filename ? x `"${filename}"` : x `null`}, ${line - 1}, ${column}, ${obj})`);
21447 }
21448
21449 function EachBlock (node, renderer, options) {
21450 const args = [node.context_node];
21451 if (node.index)
21452 args.push({ type: 'Identifier', name: node.index });
21453 renderer.push();
21454 renderer.render(node.children, options);
21455 const result = renderer.pop();
21456 const consequent = x `@each(${node.expression.node}, (${args}) => ${result})`;
21457 if (node.else) {
21458 renderer.push();
21459 renderer.render(node.else.children, options);
21460 const alternate = renderer.pop();
21461 renderer.add_expression(x `${node.expression.node}.length ? ${consequent} : ${alternate}`);
21462 }
21463 else {
21464 renderer.add_expression(consequent);
21465 }
21466 }
21467
21468 function get_class_attribute_value(attribute) {
21469 // handle special case — `class={possiblyUndefined}` with scoped CSS
21470 if (attribute.chunks.length === 2 && attribute.chunks[1].synthetic) {
21471 const value = attribute.chunks[0].node;
21472 return x `@escape(@null_to_empty(${value})) + "${attribute.chunks[1].data}"`;
21473 }
21474 return get_attribute_value(attribute);
21475 }
21476 function get_attribute_value(attribute) {
21477 if (attribute.chunks.length === 0)
21478 return x `""`;
21479 return attribute.chunks
21480 .map((chunk) => {
21481 return chunk.type === 'Text'
21482 ? string_literal(chunk.data.replace(/"/g, '&quot;'))
21483 : x `@escape(${chunk.node})`;
21484 })
21485 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
21486 }
21487
21488 function get_slot_scope(lets) {
21489 if (lets.length === 0)
21490 return null;
21491 return {
21492 type: 'ObjectPattern',
21493 properties: lets.map(l => {
21494 return {
21495 type: 'Property',
21496 kind: 'init',
21497 method: false,
21498 shorthand: false,
21499 computed: false,
21500 key: l.name,
21501 value: l.value || l.name
21502 };
21503 })
21504 };
21505 }
21506
21507 // source: https://html.spec.whatwg.org/multipage/indices.html
21508 const boolean_attributes = new Set([
21509 'allowfullscreen',
21510 'allowpaymentrequest',
21511 'async',
21512 'autofocus',
21513 'autoplay',
21514 'checked',
21515 'controls',
21516 'default',
21517 'defer',
21518 'disabled',
21519 'formnovalidate',
21520 'hidden',
21521 'ismap',
21522 'loop',
21523 'multiple',
21524 'muted',
21525 'nomodule',
21526 'novalidate',
21527 'open',
21528 'playsinline',
21529 'readonly',
21530 'required',
21531 'reversed',
21532 'selected'
21533 ]);
21534
21535 // similar logic from `compile/render_dom/wrappers/Fragment`
21536 // We want to remove trailing whitespace inside an element/component/block,
21537 // *unless* there is no whitespace between this node and its next sibling
21538 function remove_whitespace_children(children, next) {
21539 const nodes = [];
21540 let last_child;
21541 let i = children.length;
21542 while (i--) {
21543 const child = children[i];
21544 if (child.type === 'Text') {
21545 if (child.should_skip()) {
21546 continue;
21547 }
21548 let { data } = child;
21549 if (nodes.length === 0) {
21550 const should_trim = next
21551 ? next.type === 'Text' &&
21552 /^\s/.test(next.data) &&
21553 trimmable_at$1(child, next)
21554 : !child.has_ancestor('EachBlock');
21555 if (should_trim) {
21556 data = trim_end(data);
21557 if (!data)
21558 continue;
21559 }
21560 }
21561 // glue text nodes (which could e.g. be separated by comments) together
21562 if (last_child && last_child.type === 'Text') {
21563 last_child.data = data + last_child.data;
21564 continue;
21565 }
21566 nodes.unshift(child);
21567 link(last_child, last_child = child);
21568 }
21569 else {
21570 nodes.unshift(child);
21571 link(last_child, last_child = child);
21572 }
21573 }
21574 const first = nodes[0];
21575 if (first && first.type === 'Text') {
21576 first.data = trim_start(first.data);
21577 if (!first.data) {
21578 first.var = null;
21579 nodes.shift();
21580 if (nodes[0]) {
21581 nodes[0].prev = null;
21582 }
21583 }
21584 }
21585 return nodes;
21586 }
21587 function trimmable_at$1(child, next_sibling) {
21588 // Whitespace is trimmable if one of the following is true:
21589 // The child and its sibling share a common nearest each block (not at an each block boundary)
21590 // The next sibling's previous node is an each block
21591 return (next_sibling.find_nearest(/EachBlock/) ===
21592 child.find_nearest(/EachBlock/) || next_sibling.prev.type === 'EachBlock');
21593 }
21594
21595 function Element (node, renderer, options) {
21596 const children = remove_whitespace_children(node.children, node.next);
21597 // awkward special case
21598 let node_contents;
21599 const contenteditable = (node.name !== 'textarea' &&
21600 node.name !== 'input' &&
21601 node.attributes.some((attribute) => attribute.name === 'contenteditable'));
21602 const slot = node.get_static_attribute_value('slot');
21603 const nearest_inline_component = node.find_nearest(/InlineComponent/);
21604 if (slot && nearest_inline_component) {
21605 renderer.push();
21606 }
21607 renderer.add_string(`<${node.name}`);
21608 const class_expression_list = node.classes.map(class_directive => {
21609 const { expression, name } = class_directive;
21610 const snippet = expression ? expression.node : x `#ctx.${name}`; // TODO is this right?
21611 return x `${snippet} ? "${name}" : ""`;
21612 });
21613 if (node.needs_manual_style_scoping) {
21614 class_expression_list.push(x `"${node.component.stylesheet.id}"`);
21615 }
21616 const class_expression = class_expression_list.length > 0 &&
21617 class_expression_list.reduce((lhs, rhs) => x `${lhs} + ' ' + ${rhs}`);
21618 if (node.attributes.some(attr => attr.is_spread)) {
21619 // TODO dry this out
21620 const args = [];
21621 node.attributes.forEach(attribute => {
21622 if (attribute.is_spread) {
21623 args.push(attribute.expression.node);
21624 }
21625 else {
21626 const name = attribute.name.toLowerCase();
21627 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
21628 node_contents = get_attribute_value(attribute);
21629 }
21630 else if (attribute.is_true) {
21631 args.push(x `{ ${attribute.name}: true }`);
21632 }
21633 else if (boolean_attributes.has(name) &&
21634 attribute.chunks.length === 1 &&
21635 attribute.chunks[0].type !== 'Text') {
21636 // a boolean attribute with one non-Text chunk
21637 args.push(x `{ ${attribute.name}: ${attribute.chunks[0].node} || null }`);
21638 }
21639 else {
21640 args.push(x `{ ${attribute.name}: ${get_attribute_value(attribute)} }`);
21641 }
21642 }
21643 });
21644 renderer.add_expression(x `@spread([${args}], ${class_expression})`);
21645 }
21646 else {
21647 let add_class_attribute = !!class_expression;
21648 node.attributes.forEach(attribute => {
21649 const name = attribute.name.toLowerCase();
21650 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
21651 node_contents = get_attribute_value(attribute);
21652 }
21653 else if (attribute.is_true) {
21654 renderer.add_string(` ${attribute.name}`);
21655 }
21656 else if (boolean_attributes.has(name) &&
21657 attribute.chunks.length === 1 &&
21658 attribute.chunks[0].type !== 'Text') {
21659 // a boolean attribute with one non-Text chunk
21660 renderer.add_string(` `);
21661 renderer.add_expression(x `${attribute.chunks[0].node} ? "${attribute.name}" : ""`);
21662 }
21663 else if (name === 'class' && class_expression) {
21664 add_class_attribute = false;
21665 renderer.add_string(` ${attribute.name}="`);
21666 renderer.add_expression(x `[${get_class_attribute_value(attribute)}, ${class_expression}].join(' ').trim()`);
21667 renderer.add_string(`"`);
21668 }
21669 else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') {
21670 const snippet = attribute.chunks[0].node;
21671 renderer.add_expression(x `@add_attribute("${attribute.name}", ${snippet}, ${boolean_attributes.has(name) ? 1 : 0})`);
21672 }
21673 else {
21674 renderer.add_string(` ${attribute.name}="`);
21675 renderer.add_expression((name === 'class' ? get_class_attribute_value : get_attribute_value)(attribute));
21676 renderer.add_string(`"`);
21677 }
21678 });
21679 if (add_class_attribute) {
21680 renderer.add_expression(x `@add_classes([${class_expression}].join(' ').trim())`);
21681 }
21682 }
21683 node.bindings.forEach(binding => {
21684 const { name, expression } = binding;
21685 if (binding.is_readonly) {
21686 return;
21687 }
21688 if (name === 'group') ;
21689 else if (contenteditable && (name === 'textContent' || name === 'innerHTML')) {
21690 node_contents = expression.node;
21691 // TODO where was this used?
21692 // value = name === 'textContent' ? x`@escape($$value)` : x`$$value`;
21693 }
21694 else if (binding.name === 'value' && node.name === 'textarea') {
21695 const snippet = expression.node;
21696 node_contents = x `${snippet} || ""`;
21697 }
21698 else {
21699 const snippet = expression.node;
21700 renderer.add_expression(x `@add_attribute("${name}", ${snippet}, 1)`);
21701 }
21702 });
21703 if (options.hydratable && options.head_id) {
21704 renderer.add_string(` data-svelte="${options.head_id}"`);
21705 }
21706 renderer.add_string('>');
21707 if (node_contents !== undefined) {
21708 if (contenteditable) {
21709 renderer.push();
21710 renderer.render(children, options);
21711 const result = renderer.pop();
21712 renderer.add_expression(x `($$value => $$value === void 0 ? ${result} : $$value)(${node_contents})`);
21713 }
21714 else {
21715 renderer.add_expression(node_contents);
21716 }
21717 if (!is_void(node.name)) {
21718 renderer.add_string(`</${node.name}>`);
21719 }
21720 }
21721 else if (slot && nearest_inline_component) {
21722 renderer.render(children, options);
21723 if (!is_void(node.name)) {
21724 renderer.add_string(`</${node.name}>`);
21725 }
21726 const lets = node.lets;
21727 const seen = new Set(lets.map(l => l.name.name));
21728 nearest_inline_component.lets.forEach(l => {
21729 if (!seen.has(l.name.name))
21730 lets.push(l);
21731 });
21732 options.slot_scopes.set(slot, {
21733 input: get_slot_scope(node.lets),
21734 output: renderer.pop()
21735 });
21736 }
21737 else {
21738 renderer.render(children, options);
21739 if (!is_void(node.name)) {
21740 renderer.add_string(`</${node.name}>`);
21741 }
21742 }
21743 }
21744
21745 function Head (node, renderer, options) {
21746 const head_options = Object.assign({}, options, { head_id: node.id });
21747 renderer.push();
21748 renderer.render(node.children, head_options);
21749 const result = renderer.pop();
21750 renderer.add_expression(x `$$result.head += ${result}, ""`);
21751 }
21752
21753 function HtmlTag (node, renderer, _options) {
21754 renderer.add_expression(node.expression.node);
21755 }
21756
21757 function IfBlock (node, renderer, options) {
21758 const condition = node.expression.node;
21759 renderer.push();
21760 renderer.render(node.children, options);
21761 const consequent = renderer.pop();
21762 renderer.push();
21763 if (node.else)
21764 renderer.render(node.else.children, options);
21765 const alternate = renderer.pop();
21766 renderer.add_expression(x `${condition} ? ${consequent} : ${alternate}`);
21767 }
21768
21769 function get_prop_value(attribute) {
21770 if (attribute.is_true)
21771 return x `true`;
21772 if (attribute.chunks.length === 0)
21773 return x `''`;
21774 return attribute.chunks
21775 .map(chunk => {
21776 if (chunk.type === 'Text')
21777 return string_literal(chunk.data);
21778 return chunk.node;
21779 })
21780 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
21781 }
21782 function InlineComponent (node, renderer, options) {
21783 const binding_props = [];
21784 const binding_fns = [];
21785 node.bindings.forEach(binding => {
21786 renderer.has_bindings = true;
21787 // TODO this probably won't work for contextual bindings
21788 const snippet = binding.expression.node;
21789 binding_props.push(p `${binding.name}: ${snippet}`);
21790 binding_fns.push(p `${binding.name}: $$value => { ${snippet} = $$value; $$settled = false }`);
21791 });
21792 const uses_spread = node.attributes.find(attr => attr.is_spread);
21793 let props;
21794 if (uses_spread) {
21795 props = x `@_Object.assign(${node.attributes
21796 .map(attribute => {
21797 if (attribute.is_spread) {
21798 return attribute.expression.node;
21799 }
21800 else {
21801 return x `{ ${attribute.name}: ${get_prop_value(attribute)} }`;
21802 }
21803 })
21804 .concat(binding_props.map(p => x `{ ${p} }`))})`;
21805 }
21806 else {
21807 props = x `{
21808 ${node.attributes.map(attribute => p `${attribute.name}: ${get_prop_value(attribute)}`)},
21809 ${binding_props}
21810 }`;
21811 }
21812 const bindings = x `{
21813 ${binding_fns}
21814 }`;
21815 const expression = (node.name === 'svelte:self'
21816 ? renderer.name
21817 : node.name === 'svelte:component'
21818 ? x `(${node.expression.node}) || @missing_component`
21819 : node.name.split('.').reduce(((lhs, rhs) => x `${lhs}.${rhs}`)));
21820 const slot_fns = [];
21821 const children = remove_whitespace_children(node.children, node.next);
21822 if (children.length) {
21823 const slot_scopes = new Map();
21824 renderer.push();
21825 renderer.render(children, Object.assign({}, options, {
21826 slot_scopes
21827 }));
21828 slot_scopes.set('default', {
21829 input: get_slot_scope(node.lets),
21830 output: renderer.pop()
21831 });
21832 slot_scopes.forEach(({ input, output }, name) => {
21833 if (!is_empty_template_literal(output)) {
21834 slot_fns.push(p `${name}: (${input}) => ${output}`);
21835 }
21836 });
21837 }
21838 const slots = x `{
21839 ${slot_fns}
21840 }`;
21841 renderer.add_expression(x `@validate_component(${expression}, "${node.name}").$$render($$result, ${props}, ${bindings}, ${slots})`);
21842 }
21843 function is_empty_template_literal(template_literal) {
21844 return (template_literal.expressions.length === 0 &&
21845 template_literal.quasis.length === 1 &&
21846 template_literal.quasis[0].value.raw === "");
21847 }
21848
21849 function Slot (node, renderer, options) {
21850 const slot_data = get_slot_data(node.values);
21851 renderer.push();
21852 renderer.render(node.children, options);
21853 const result = renderer.pop();
21854 renderer.add_expression(x `
21855 $$slots.${node.slot_name}
21856 ? $$slots.${node.slot_name}(${slot_data})
21857 : ${result}
21858 `);
21859 }
21860
21861 function Tag$1 (node, renderer, _options) {
21862 const snippet = node.expression.node;
21863 renderer.add_expression(node.parent &&
21864 node.parent.type === 'Element' &&
21865 node.parent.name === 'style'
21866 ? snippet
21867 : x `@escape(${snippet})`);
21868 }
21869
21870 function Text (node, renderer, _options) {
21871 let text = node.data;
21872 if (!node.parent ||
21873 node.parent.type !== 'Element' ||
21874 (node.parent.name !== 'script' && node.parent.name !== 'style')) {
21875 // unless this Text node is inside a <script> or <style> element, escape &,<,>
21876 text = escape_html(text);
21877 }
21878 renderer.add_string(text);
21879 }
21880
21881 function Title (node, renderer, options) {
21882 renderer.push();
21883 renderer.add_string(`<title>`);
21884 renderer.render(node.children, options);
21885 renderer.add_string(`</title>`);
21886 const result = renderer.pop();
21887 renderer.add_expression(x `$$result.title = ${result}, ""`);
21888 }
21889
21890 function noop$1() { }
21891 const handlers$1 = {
21892 AwaitBlock,
21893 Body: noop$1,
21894 Comment: Comment$1,
21895 DebugTag,
21896 EachBlock,
21897 Element,
21898 Head,
21899 IfBlock,
21900 InlineComponent,
21901 MustacheTag: Tag$1,
21902 Options: noop$1,
21903 RawMustacheTag: HtmlTag,
21904 Slot,
21905 Text,
21906 Title,
21907 Window: noop$1
21908 };
21909 class Renderer$1 {
21910 constructor({ name }) {
21911 this.has_bindings = false;
21912 this.stack = [];
21913 this.targets = [];
21914 this.name = name;
21915 this.push();
21916 }
21917 add_string(str) {
21918 this.current.value += escape_template(str);
21919 }
21920 add_expression(node) {
21921 this.literal.quasis.push({
21922 type: 'TemplateElement',
21923 value: { raw: this.current.value, cooked: null },
21924 tail: false
21925 });
21926 this.literal.expressions.push(node);
21927 this.current.value = '';
21928 }
21929 push() {
21930 const current = this.current = { value: '' };
21931 const literal = this.literal = {
21932 type: 'TemplateLiteral',
21933 expressions: [],
21934 quasis: []
21935 };
21936 this.stack.push({ current, literal });
21937 }
21938 pop() {
21939 this.literal.quasis.push({
21940 type: 'TemplateElement',
21941 value: { raw: this.current.value, cooked: null },
21942 tail: true
21943 });
21944 const popped = this.stack.pop();
21945 const last = this.stack[this.stack.length - 1];
21946 if (last) {
21947 this.literal = last.literal;
21948 this.current = last.current;
21949 }
21950 return popped.literal;
21951 }
21952 render(nodes, options) {
21953 nodes.forEach(node => {
21954 const handler = handlers$1[node.type];
21955 if (!handler) {
21956 throw new Error(`No handler for '${node.type}' nodes`);
21957 }
21958 handler(node, this, options);
21959 });
21960 }
21961 }
21962
21963 function ssr(component, options) {
21964 const renderer = new Renderer$1({
21965 name: component.name
21966 });
21967 const { name } = component;
21968 // create $$render function
21969 renderer.render(trim(component.fragment.children), Object.assign({
21970 locate: component.locate
21971 }, options));
21972 // TODO put this inside the Renderer class
21973 const literal = renderer.pop();
21974 // TODO concatenate CSS maps
21975 const css = options.customElement ?
21976 { code: null, map: null } :
21977 component.stylesheet.render(options.filename, true);
21978 const uses_rest = component.var_lookup.has('$$restProps');
21979 const props = component.vars.filter(variable => !variable.module && variable.export_name);
21980 const rest = uses_rest ? b `let $$restProps = @compute_rest_props($$props, [${props.map(prop => `"${prop.export_name}"`).join(',')}]);` : null;
21981 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
21982 const reactive_store_values = reactive_stores
21983 .map(({ name }) => {
21984 const store_name = name.slice(1);
21985 const store = component.var_lookup.get(store_name);
21986 if (store && store.hoistable)
21987 return null;
21988 const assignment = b `${name} = @get_store_value(${store_name});`;
21989 return component.compile_options.dev
21990 ? b `@validate_store(${store_name}, '${store_name}'); ${assignment}`
21991 : assignment;
21992 })
21993 .filter(Boolean);
21994 component.rewrite_props(({ name }) => {
21995 const value = `$${name}`;
21996 let insert = b `${value} = @get_store_value(${name})`;
21997 if (component.compile_options.dev) {
21998 insert = b `@validate_store(${name}, '${name}'); ${insert}`;
21999 }
22000 return insert;
22001 });
22002 const instance_javascript = component.extract_javascript(component.ast.instance);
22003 // TODO only do this for props with a default value
22004 const parent_bindings = instance_javascript
22005 ? component.vars
22006 .filter(variable => !variable.module && variable.export_name)
22007 .map(prop => {
22008 return b `if ($$props.${prop.export_name} === void 0 && $$bindings.${prop.export_name} && ${prop.name} !== void 0) $$bindings.${prop.export_name}(${prop.name});`;
22009 })
22010 : [];
22011 const reactive_declarations = component.reactive_declarations.map(d => {
22012 const body = d.node.body;
22013 let statement = b `${body}`;
22014 if (d.declaration) {
22015 const declared = extract_names(d.declaration);
22016 const injected = declared.filter(name => {
22017 return name[0] !== '$' && component.var_lookup.get(name).injected;
22018 });
22019 const self_dependencies = injected.filter(name => d.dependencies.has(name));
22020 if (injected.length) {
22021 // in some cases we need to do `let foo; [expression]`, in
22022 // others we can do `let [expression]`
22023 const separate = (self_dependencies.length > 0 ||
22024 declared.length > injected.length);
22025 const { left, right } = body.expression;
22026 statement = separate
22027 ? b `
22028 ${injected.map(name => b `let ${name};`)}
22029 ${statement}`
22030 : b `
22031 let ${left} = ${right}`;
22032 }
22033 }
22034 else { // TODO do not add label if it's not referenced
22035 statement = b `$: { ${statement} }`;
22036 }
22037 return statement;
22038 });
22039 const main = renderer.has_bindings
22040 ? b `
22041 let $$settled;
22042 let $$rendered;
22043
22044 do {
22045 $$settled = true;
22046
22047 ${reactive_store_values}
22048
22049 ${reactive_declarations}
22050
22051 $$rendered = ${literal};
22052 } while (!$$settled);
22053
22054 return $$rendered;
22055 `
22056 : b `
22057 ${reactive_store_values}
22058
22059 ${reactive_declarations}
22060
22061 return ${literal};`;
22062 const blocks = [
22063 rest,
22064 ...reactive_stores.map(({ name }) => {
22065 const store_name = name.slice(1);
22066 const store = component.var_lookup.get(store_name);
22067 if (store && store.hoistable) {
22068 return b `let ${name} = @get_store_value(${store_name});`;
22069 }
22070 return b `let ${name};`;
22071 }),
22072 instance_javascript,
22073 ...parent_bindings,
22074 css.code && b `$$result.css.add(#css);`,
22075 main
22076 ].filter(Boolean);
22077 const js = b `
22078 ${css.code ? b `
22079 const #css = {
22080 code: "${css.code}",
22081 map: ${css.map ? string_literal(css.map.toString()) : 'null'}
22082 };` : null}
22083
22084 ${component.extract_javascript(component.ast.module)}
22085
22086 ${component.fully_hoisted}
22087
22088 const ${name} = @create_ssr_component(($$result, $$props, $$bindings, $$slots) => {
22089 ${blocks}
22090 });
22091 `;
22092 return { js, css };
22093 }
22094 function trim(nodes) {
22095 let start = 0;
22096 for (; start < nodes.length; start += 1) {
22097 const node = nodes[start];
22098 if (node.type !== 'Text')
22099 break;
22100 node.data = node.data.replace(/^\s+/, '');
22101 if (node.data)
22102 break;
22103 }
22104 let end = nodes.length;
22105 for (; end > start; end -= 1) {
22106 const node = nodes[end - 1];
22107 if (node.type !== 'Text')
22108 break;
22109 node.data = node.data.replace(/\s+$/, '');
22110 if (node.data)
22111 break;
22112 }
22113 return nodes.slice(start, end);
22114 }
22115
22116 const wrappers$1 = { esm, cjs };
22117 function create_module(program, format, name, banner, sveltePath = 'svelte', helpers, globals, imports, module_exports) {
22118 const internal_path = `${sveltePath}/internal`;
22119 helpers.sort((a, b) => (a.name < b.name) ? -1 : 1);
22120 globals.sort((a, b) => (a.name < b.name) ? -1 : 1);
22121 if (format === 'esm') {
22122 return esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
22123 }
22124 if (format === 'cjs')
22125 return cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
22126 throw new Error(`options.format is invalid (must be ${list$1(Object.keys(wrappers$1))})`);
22127 }
22128 function edit_source(source, sveltePath) {
22129 return source === 'svelte' || source.startsWith('svelte/')
22130 ? source.replace('svelte', sveltePath)
22131 : source;
22132 }
22133 function get_internal_globals(globals, helpers) {
22134 return globals.length > 0 && {
22135 type: 'VariableDeclaration',
22136 kind: 'const',
22137 declarations: [{
22138 type: 'VariableDeclarator',
22139 id: {
22140 type: 'ObjectPattern',
22141 properties: globals.map(g => ({
22142 type: 'Property',
22143 method: false,
22144 shorthand: false,
22145 computed: false,
22146 key: { type: 'Identifier', name: g.name },
22147 value: g.alias,
22148 kind: 'init'
22149 }))
22150 },
22151 init: helpers.find(({ name }) => name === 'globals').alias
22152 }]
22153 };
22154 }
22155 function esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
22156 const import_declaration = {
22157 type: 'ImportDeclaration',
22158 specifiers: helpers.map(h => ({
22159 type: 'ImportSpecifier',
22160 local: h.alias,
22161 imported: { type: 'Identifier', name: h.name }
22162 })),
22163 source: { type: 'Literal', value: internal_path }
22164 };
22165 const internal_globals = get_internal_globals(globals, helpers);
22166 // edit user imports
22167 imports.forEach(node => {
22168 node.source.value = edit_source(node.source.value, sveltePath);
22169 });
22170 const exports = module_exports.length > 0 && {
22171 type: 'ExportNamedDeclaration',
22172 specifiers: module_exports.map(x => ({
22173 type: 'Specifier',
22174 local: { type: 'Identifier', name: x.name },
22175 exported: { type: 'Identifier', name: x.as }
22176 }))
22177 };
22178 program.body = b `
22179 /* ${banner} */
22180
22181 ${import_declaration}
22182 ${internal_globals}
22183 ${imports}
22184
22185 ${program.body}
22186
22187 export default ${name};
22188 ${exports}
22189 `;
22190 }
22191 function cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
22192 const internal_requires = {
22193 type: 'VariableDeclaration',
22194 kind: 'const',
22195 declarations: [{
22196 type: 'VariableDeclarator',
22197 id: {
22198 type: 'ObjectPattern',
22199 properties: helpers.map(h => ({
22200 type: 'Property',
22201 method: false,
22202 shorthand: false,
22203 computed: false,
22204 key: { type: 'Identifier', name: h.name },
22205 value: h.alias,
22206 kind: 'init'
22207 }))
22208 },
22209 init: x `require("${internal_path}")`
22210 }]
22211 };
22212 const internal_globals = get_internal_globals(globals, helpers);
22213 const user_requires = imports.map(node => {
22214 const init = x `require("${edit_source(node.source.value, sveltePath)}")`;
22215 if (node.specifiers.length === 0) {
22216 return b `${init};`;
22217 }
22218 return {
22219 type: 'VariableDeclaration',
22220 kind: 'const',
22221 declarations: [{
22222 type: 'VariableDeclarator',
22223 id: node.specifiers[0].type === 'ImportNamespaceSpecifier'
22224 ? { type: 'Identifier', name: node.specifiers[0].local.name }
22225 : {
22226 type: 'ObjectPattern',
22227 properties: node.specifiers.map(s => ({
22228 type: 'Property',
22229 method: false,
22230 shorthand: false,
22231 computed: false,
22232 key: s.type === 'ImportSpecifier' ? s.imported : { type: 'Identifier', name: 'default' },
22233 value: s.local,
22234 kind: 'init'
22235 }))
22236 },
22237 init
22238 }]
22239 };
22240 });
22241 const exports = module_exports.map(x => b `exports.${{ type: 'Identifier', name: x.as }} = ${{ type: 'Identifier', name: x.name }};`);
22242 program.body = b `
22243 /* ${banner} */
22244
22245 "use strict";
22246 ${internal_requires}
22247 ${internal_globals}
22248 ${user_requires}
22249
22250 ${program.body}
22251
22252 exports.default = ${name};
22253 ${exports}
22254 `;
22255 }
22256
22257 var Chunk = function Chunk(start, end, content) {
22258 this.start = start;
22259 this.end = end;
22260 this.original = content;
22261
22262 this.intro = '';
22263 this.outro = '';
22264
22265 this.content = content;
22266 this.storeName = false;
22267 this.edited = false;
22268
22269 // we make these non-enumerable, for sanity while debugging
22270 Object.defineProperties(this, {
22271 previous: { writable: true, value: null },
22272 next: { writable: true, value: null }
22273 });
22274 };
22275
22276 Chunk.prototype.appendLeft = function appendLeft (content) {
22277 this.outro += content;
22278 };
22279
22280 Chunk.prototype.appendRight = function appendRight (content) {
22281 this.intro = this.intro + content;
22282 };
22283
22284 Chunk.prototype.clone = function clone () {
22285 var chunk = new Chunk(this.start, this.end, this.original);
22286
22287 chunk.intro = this.intro;
22288 chunk.outro = this.outro;
22289 chunk.content = this.content;
22290 chunk.storeName = this.storeName;
22291 chunk.edited = this.edited;
22292
22293 return chunk;
22294 };
22295
22296 Chunk.prototype.contains = function contains (index) {
22297 return this.start < index && index < this.end;
22298 };
22299
22300 Chunk.prototype.eachNext = function eachNext (fn) {
22301 var chunk = this;
22302 while (chunk) {
22303 fn(chunk);
22304 chunk = chunk.next;
22305 }
22306 };
22307
22308 Chunk.prototype.eachPrevious = function eachPrevious (fn) {
22309 var chunk = this;
22310 while (chunk) {
22311 fn(chunk);
22312 chunk = chunk.previous;
22313 }
22314 };
22315
22316 Chunk.prototype.edit = function edit (content, storeName, contentOnly) {
22317 this.content = content;
22318 if (!contentOnly) {
22319 this.intro = '';
22320 this.outro = '';
22321 }
22322 this.storeName = storeName;
22323
22324 this.edited = true;
22325
22326 return this;
22327 };
22328
22329 Chunk.prototype.prependLeft = function prependLeft (content) {
22330 this.outro = content + this.outro;
22331 };
22332
22333 Chunk.prototype.prependRight = function prependRight (content) {
22334 this.intro = content + this.intro;
22335 };
22336
22337 Chunk.prototype.split = function split (index) {
22338 var sliceIndex = index - this.start;
22339
22340 var originalBefore = this.original.slice(0, sliceIndex);
22341 var originalAfter = this.original.slice(sliceIndex);
22342
22343 this.original = originalBefore;
22344
22345 var newChunk = new Chunk(index, this.end, originalAfter);
22346 newChunk.outro = this.outro;
22347 this.outro = '';
22348
22349 this.end = index;
22350
22351 if (this.edited) {
22352 // TODO is this block necessary?...
22353 newChunk.edit('', false);
22354 this.content = '';
22355 } else {
22356 this.content = originalBefore;
22357 }
22358
22359 newChunk.next = this.next;
22360 if (newChunk.next) { newChunk.next.previous = newChunk; }
22361 newChunk.previous = this;
22362 this.next = newChunk;
22363
22364 return newChunk;
22365 };
22366
22367 Chunk.prototype.toString = function toString () {
22368 return this.intro + this.content + this.outro;
22369 };
22370
22371 Chunk.prototype.trimEnd = function trimEnd (rx) {
22372 this.outro = this.outro.replace(rx, '');
22373 if (this.outro.length) { return true; }
22374
22375 var trimmed = this.content.replace(rx, '');
22376
22377 if (trimmed.length) {
22378 if (trimmed !== this.content) {
22379 this.split(this.start + trimmed.length).edit('', undefined, true);
22380 }
22381 return true;
22382
22383 } else {
22384 this.edit('', undefined, true);
22385
22386 this.intro = this.intro.replace(rx, '');
22387 if (this.intro.length) { return true; }
22388 }
22389 };
22390
22391 Chunk.prototype.trimStart = function trimStart (rx) {
22392 this.intro = this.intro.replace(rx, '');
22393 if (this.intro.length) { return true; }
22394
22395 var trimmed = this.content.replace(rx, '');
22396
22397 if (trimmed.length) {
22398 if (trimmed !== this.content) {
22399 this.split(this.end - trimmed.length);
22400 this.edit('', undefined, true);
22401 }
22402 return true;
22403
22404 } else {
22405 this.edit('', undefined, true);
22406
22407 this.outro = this.outro.replace(rx, '');
22408 if (this.outro.length) { return true; }
22409 }
22410 };
22411
22412 var btoa$1 = function () {
22413 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
22414 };
22415 if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
22416 btoa$1 = function (str) { return window.btoa(unescape(encodeURIComponent(str))); };
22417 } else if (typeof Buffer === 'function') {
22418 btoa$1 = function (str) { return Buffer.from(str, 'utf-8').toString('base64'); };
22419 }
22420
22421 var SourceMap = function SourceMap(properties) {
22422 this.version = 3;
22423 this.file = properties.file;
22424 this.sources = properties.sources;
22425 this.sourcesContent = properties.sourcesContent;
22426 this.names = properties.names;
22427 this.mappings = encode(properties.mappings);
22428 };
22429
22430 SourceMap.prototype.toString = function toString () {
22431 return JSON.stringify(this);
22432 };
22433
22434 SourceMap.prototype.toUrl = function toUrl () {
22435 return 'data:application/json;charset=utf-8;base64,' + btoa$1(this.toString());
22436 };
22437
22438 function guessIndent(code) {
22439 var lines = code.split('\n');
22440
22441 var tabbed = lines.filter(function (line) { return /^\t+/.test(line); });
22442 var spaced = lines.filter(function (line) { return /^ {2,}/.test(line); });
22443
22444 if (tabbed.length === 0 && spaced.length === 0) {
22445 return null;
22446 }
22447
22448 // More lines tabbed than spaced? Assume tabs, and
22449 // default to tabs in the case of a tie (or nothing
22450 // to go on)
22451 if (tabbed.length >= spaced.length) {
22452 return '\t';
22453 }
22454
22455 // Otherwise, we need to guess the multiple
22456 var min = spaced.reduce(function (previous, current) {
22457 var numSpaces = /^ +/.exec(current)[0].length;
22458 return Math.min(numSpaces, previous);
22459 }, Infinity);
22460
22461 return new Array(min + 1).join(' ');
22462 }
22463
22464 function getRelativePath(from, to) {
22465 var fromParts = from.split(/[/\\]/);
22466 var toParts = to.split(/[/\\]/);
22467
22468 fromParts.pop(); // get dirname
22469
22470 while (fromParts[0] === toParts[0]) {
22471 fromParts.shift();
22472 toParts.shift();
22473 }
22474
22475 if (fromParts.length) {
22476 var i = fromParts.length;
22477 while (i--) { fromParts[i] = '..'; }
22478 }
22479
22480 return fromParts.concat(toParts).join('/');
22481 }
22482
22483 var toString$1 = Object.prototype.toString;
22484
22485 function isObject(thing) {
22486 return toString$1.call(thing) === '[object Object]';
22487 }
22488
22489 function getLocator$1(source) {
22490 var originalLines = source.split('\n');
22491 var lineOffsets = [];
22492
22493 for (var i = 0, pos = 0; i < originalLines.length; i++) {
22494 lineOffsets.push(pos);
22495 pos += originalLines[i].length + 1;
22496 }
22497
22498 return function locate(index) {
22499 var i = 0;
22500 var j = lineOffsets.length;
22501 while (i < j) {
22502 var m = (i + j) >> 1;
22503 if (index < lineOffsets[m]) {
22504 j = m;
22505 } else {
22506 i = m + 1;
22507 }
22508 }
22509 var line = i - 1;
22510 var column = index - lineOffsets[line];
22511 return { line: line, column: column };
22512 };
22513 }
22514
22515 var Mappings = function Mappings(hires) {
22516 this.hires = hires;
22517 this.generatedCodeLine = 0;
22518 this.generatedCodeColumn = 0;
22519 this.raw = [];
22520 this.rawSegments = this.raw[this.generatedCodeLine] = [];
22521 this.pending = null;
22522 };
22523
22524 Mappings.prototype.addEdit = function addEdit (sourceIndex, content, loc, nameIndex) {
22525 if (content.length) {
22526 var segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
22527 if (nameIndex >= 0) {
22528 segment.push(nameIndex);
22529 }
22530 this.rawSegments.push(segment);
22531 } else if (this.pending) {
22532 this.rawSegments.push(this.pending);
22533 }
22534
22535 this.advance(content);
22536 this.pending = null;
22537 };
22538
22539 Mappings.prototype.addUneditedChunk = function addUneditedChunk (sourceIndex, chunk, original, loc, sourcemapLocations) {
22540 var originalCharIndex = chunk.start;
22541 var first = true;
22542
22543 while (originalCharIndex < chunk.end) {
22544 if (this.hires || first || sourcemapLocations[originalCharIndex]) {
22545 this.rawSegments.push([this.generatedCodeColumn, sourceIndex, loc.line, loc.column]);
22546 }
22547
22548 if (original[originalCharIndex] === '\n') {
22549 loc.line += 1;
22550 loc.column = 0;
22551 this.generatedCodeLine += 1;
22552 this.raw[this.generatedCodeLine] = this.rawSegments = [];
22553 this.generatedCodeColumn = 0;
22554 } else {
22555 loc.column += 1;
22556 this.generatedCodeColumn += 1;
22557 }
22558
22559 originalCharIndex += 1;
22560 first = false;
22561 }
22562
22563 this.pending = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
22564 };
22565
22566 Mappings.prototype.advance = function advance (str) {
22567 if (!str) { return; }
22568
22569 var lines = str.split('\n');
22570
22571 if (lines.length > 1) {
22572 for (var i = 0; i < lines.length - 1; i++) {
22573 this.generatedCodeLine++;
22574 this.raw[this.generatedCodeLine] = this.rawSegments = [];
22575 }
22576 this.generatedCodeColumn = 0;
22577 }
22578
22579 this.generatedCodeColumn += lines[lines.length - 1].length;
22580 };
22581
22582 var n = '\n';
22583
22584 var warned = {
22585 insertLeft: false,
22586 insertRight: false,
22587 storeName: false
22588 };
22589
22590 var MagicString = function MagicString(string, options) {
22591 if ( options === void 0 ) options = {};
22592
22593 var chunk = new Chunk(0, string.length, string);
22594
22595 Object.defineProperties(this, {
22596 original: { writable: true, value: string },
22597 outro: { writable: true, value: '' },
22598 intro: { writable: true, value: '' },
22599 firstChunk: { writable: true, value: chunk },
22600 lastChunk: { writable: true, value: chunk },
22601 lastSearchedChunk: { writable: true, value: chunk },
22602 byStart: { writable: true, value: {} },
22603 byEnd: { writable: true, value: {} },
22604 filename: { writable: true, value: options.filename },
22605 indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
22606 sourcemapLocations: { writable: true, value: {} },
22607 storedNames: { writable: true, value: {} },
22608 indentStr: { writable: true, value: guessIndent(string) }
22609 });
22610
22611 this.byStart[0] = chunk;
22612 this.byEnd[string.length] = chunk;
22613 };
22614
22615 MagicString.prototype.addSourcemapLocation = function addSourcemapLocation (char) {
22616 this.sourcemapLocations[char] = true;
22617 };
22618
22619 MagicString.prototype.append = function append (content) {
22620 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
22621
22622 this.outro += content;
22623 return this;
22624 };
22625
22626 MagicString.prototype.appendLeft = function appendLeft (index, content) {
22627 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22628
22629 this._split(index);
22630
22631 var chunk = this.byEnd[index];
22632
22633 if (chunk) {
22634 chunk.appendLeft(content);
22635 } else {
22636 this.intro += content;
22637 }
22638 return this;
22639 };
22640
22641 MagicString.prototype.appendRight = function appendRight (index, content) {
22642 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22643
22644 this._split(index);
22645
22646 var chunk = this.byStart[index];
22647
22648 if (chunk) {
22649 chunk.appendRight(content);
22650 } else {
22651 this.outro += content;
22652 }
22653 return this;
22654 };
22655
22656 MagicString.prototype.clone = function clone () {
22657 var cloned = new MagicString(this.original, { filename: this.filename });
22658
22659 var originalChunk = this.firstChunk;
22660 var clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());
22661
22662 while (originalChunk) {
22663 cloned.byStart[clonedChunk.start] = clonedChunk;
22664 cloned.byEnd[clonedChunk.end] = clonedChunk;
22665
22666 var nextOriginalChunk = originalChunk.next;
22667 var nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
22668
22669 if (nextClonedChunk) {
22670 clonedChunk.next = nextClonedChunk;
22671 nextClonedChunk.previous = clonedChunk;
22672
22673 clonedChunk = nextClonedChunk;
22674 }
22675
22676 originalChunk = nextOriginalChunk;
22677 }
22678
22679 cloned.lastChunk = clonedChunk;
22680
22681 if (this.indentExclusionRanges) {
22682 cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
22683 }
22684
22685 Object.keys(this.sourcemapLocations).forEach(function (loc) {
22686 cloned.sourcemapLocations[loc] = true;
22687 });
22688
22689 return cloned;
22690 };
22691
22692 MagicString.prototype.generateDecodedMap = function generateDecodedMap (options) {
22693 var this$1 = this;
22694
22695 options = options || {};
22696
22697 var sourceIndex = 0;
22698 var names = Object.keys(this.storedNames);
22699 var mappings = new Mappings(options.hires);
22700
22701 var locate = getLocator$1(this.original);
22702
22703 if (this.intro) {
22704 mappings.advance(this.intro);
22705 }
22706
22707 this.firstChunk.eachNext(function (chunk) {
22708 var loc = locate(chunk.start);
22709
22710 if (chunk.intro.length) { mappings.advance(chunk.intro); }
22711
22712 if (chunk.edited) {
22713 mappings.addEdit(
22714 sourceIndex,
22715 chunk.content,
22716 loc,
22717 chunk.storeName ? names.indexOf(chunk.original) : -1
22718 );
22719 } else {
22720 mappings.addUneditedChunk(sourceIndex, chunk, this$1.original, loc, this$1.sourcemapLocations);
22721 }
22722
22723 if (chunk.outro.length) { mappings.advance(chunk.outro); }
22724 });
22725
22726 return {
22727 file: options.file ? options.file.split(/[/\\]/).pop() : null,
22728 sources: [options.source ? getRelativePath(options.file || '', options.source) : null],
22729 sourcesContent: options.includeContent ? [this.original] : [null],
22730 names: names,
22731 mappings: mappings.raw
22732 };
22733 };
22734
22735 MagicString.prototype.generateMap = function generateMap (options) {
22736 return new SourceMap(this.generateDecodedMap(options));
22737 };
22738
22739 MagicString.prototype.getIndentString = function getIndentString () {
22740 return this.indentStr === null ? '\t' : this.indentStr;
22741 };
22742
22743 MagicString.prototype.indent = function indent (indentStr, options) {
22744 var pattern = /^[^\r\n]/gm;
22745
22746 if (isObject(indentStr)) {
22747 options = indentStr;
22748 indentStr = undefined;
22749 }
22750
22751 indentStr = indentStr !== undefined ? indentStr : this.indentStr || '\t';
22752
22753 if (indentStr === '') { return this; } // noop
22754
22755 options = options || {};
22756
22757 // Process exclusion ranges
22758 var isExcluded = {};
22759
22760 if (options.exclude) {
22761 var exclusions =
22762 typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;
22763 exclusions.forEach(function (exclusion) {
22764 for (var i = exclusion[0]; i < exclusion[1]; i += 1) {
22765 isExcluded[i] = true;
22766 }
22767 });
22768 }
22769
22770 var shouldIndentNextCharacter = options.indentStart !== false;
22771 var replacer = function (match) {
22772 if (shouldIndentNextCharacter) { return ("" + indentStr + match); }
22773 shouldIndentNextCharacter = true;
22774 return match;
22775 };
22776
22777 this.intro = this.intro.replace(pattern, replacer);
22778
22779 var charIndex = 0;
22780 var chunk = this.firstChunk;
22781
22782 while (chunk) {
22783 var end = chunk.end;
22784
22785 if (chunk.edited) {
22786 if (!isExcluded[charIndex]) {
22787 chunk.content = chunk.content.replace(pattern, replacer);
22788
22789 if (chunk.content.length) {
22790 shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';
22791 }
22792 }
22793 } else {
22794 charIndex = chunk.start;
22795
22796 while (charIndex < end) {
22797 if (!isExcluded[charIndex]) {
22798 var char = this.original[charIndex];
22799
22800 if (char === '\n') {
22801 shouldIndentNextCharacter = true;
22802 } else if (char !== '\r' && shouldIndentNextCharacter) {
22803 shouldIndentNextCharacter = false;
22804
22805 if (charIndex === chunk.start) {
22806 chunk.prependRight(indentStr);
22807 } else {
22808 this._splitChunk(chunk, charIndex);
22809 chunk = chunk.next;
22810 chunk.prependRight(indentStr);
22811 }
22812 }
22813 }
22814
22815 charIndex += 1;
22816 }
22817 }
22818
22819 charIndex = chunk.end;
22820 chunk = chunk.next;
22821 }
22822
22823 this.outro = this.outro.replace(pattern, replacer);
22824
22825 return this;
22826 };
22827
22828 MagicString.prototype.insert = function insert () {
22829 throw new Error('magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)');
22830 };
22831
22832 MagicString.prototype.insertLeft = function insertLeft (index, content) {
22833 if (!warned.insertLeft) {
22834 console.warn('magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead'); // eslint-disable-line no-console
22835 warned.insertLeft = true;
22836 }
22837
22838 return this.appendLeft(index, content);
22839 };
22840
22841 MagicString.prototype.insertRight = function insertRight (index, content) {
22842 if (!warned.insertRight) {
22843 console.warn('magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead'); // eslint-disable-line no-console
22844 warned.insertRight = true;
22845 }
22846
22847 return this.prependRight(index, content);
22848 };
22849
22850 MagicString.prototype.move = function move (start, end, index) {
22851 if (index >= start && index <= end) { throw new Error('Cannot move a selection inside itself'); }
22852
22853 this._split(start);
22854 this._split(end);
22855 this._split(index);
22856
22857 var first = this.byStart[start];
22858 var last = this.byEnd[end];
22859
22860 var oldLeft = first.previous;
22861 var oldRight = last.next;
22862
22863 var newRight = this.byStart[index];
22864 if (!newRight && last === this.lastChunk) { return this; }
22865 var newLeft = newRight ? newRight.previous : this.lastChunk;
22866
22867 if (oldLeft) { oldLeft.next = oldRight; }
22868 if (oldRight) { oldRight.previous = oldLeft; }
22869
22870 if (newLeft) { newLeft.next = first; }
22871 if (newRight) { newRight.previous = last; }
22872
22873 if (!first.previous) { this.firstChunk = last.next; }
22874 if (!last.next) {
22875 this.lastChunk = first.previous;
22876 this.lastChunk.next = null;
22877 }
22878
22879 first.previous = newLeft;
22880 last.next = newRight || null;
22881
22882 if (!newLeft) { this.firstChunk = first; }
22883 if (!newRight) { this.lastChunk = last; }
22884 return this;
22885 };
22886
22887 MagicString.prototype.overwrite = function overwrite (start, end, content, options) {
22888 if (typeof content !== 'string') { throw new TypeError('replacement content must be a string'); }
22889
22890 while (start < 0) { start += this.original.length; }
22891 while (end < 0) { end += this.original.length; }
22892
22893 if (end > this.original.length) { throw new Error('end is out of bounds'); }
22894 if (start === end)
22895 { throw new Error('Cannot overwrite a zero-length range – use appendLeft or prependRight instead'); }
22896
22897 this._split(start);
22898 this._split(end);
22899
22900 if (options === true) {
22901 if (!warned.storeName) {
22902 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
22903 warned.storeName = true;
22904 }
22905
22906 options = { storeName: true };
22907 }
22908 var storeName = options !== undefined ? options.storeName : false;
22909 var contentOnly = options !== undefined ? options.contentOnly : false;
22910
22911 if (storeName) {
22912 var original = this.original.slice(start, end);
22913 this.storedNames[original] = true;
22914 }
22915
22916 var first = this.byStart[start];
22917 var last = this.byEnd[end];
22918
22919 if (first) {
22920 if (end > first.end && first.next !== this.byStart[first.end]) {
22921 throw new Error('Cannot overwrite across a split point');
22922 }
22923
22924 first.edit(content, storeName, contentOnly);
22925
22926 if (first !== last) {
22927 var chunk = first.next;
22928 while (chunk !== last) {
22929 chunk.edit('', false);
22930 chunk = chunk.next;
22931 }
22932
22933 chunk.edit('', false);
22934 }
22935 } else {
22936 // must be inserting at the end
22937 var newChunk = new Chunk(start, end, '').edit(content, storeName);
22938
22939 // TODO last chunk in the array may not be the last chunk, if it's moved...
22940 last.next = newChunk;
22941 newChunk.previous = last;
22942 }
22943 return this;
22944 };
22945
22946 MagicString.prototype.prepend = function prepend (content) {
22947 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
22948
22949 this.intro = content + this.intro;
22950 return this;
22951 };
22952
22953 MagicString.prototype.prependLeft = function prependLeft (index, content) {
22954 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22955
22956 this._split(index);
22957
22958 var chunk = this.byEnd[index];
22959
22960 if (chunk) {
22961 chunk.prependLeft(content);
22962 } else {
22963 this.intro = content + this.intro;
22964 }
22965 return this;
22966 };
22967
22968 MagicString.prototype.prependRight = function prependRight (index, content) {
22969 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22970
22971 this._split(index);
22972
22973 var chunk = this.byStart[index];
22974
22975 if (chunk) {
22976 chunk.prependRight(content);
22977 } else {
22978 this.outro = content + this.outro;
22979 }
22980 return this;
22981 };
22982
22983 MagicString.prototype.remove = function remove (start, end) {
22984 while (start < 0) { start += this.original.length; }
22985 while (end < 0) { end += this.original.length; }
22986
22987 if (start === end) { return this; }
22988
22989 if (start < 0 || end > this.original.length) { throw new Error('Character is out of bounds'); }
22990 if (start > end) { throw new Error('end must be greater than start'); }
22991
22992 this._split(start);
22993 this._split(end);
22994
22995 var chunk = this.byStart[start];
22996
22997 while (chunk) {
22998 chunk.intro = '';
22999 chunk.outro = '';
23000 chunk.edit('');
23001
23002 chunk = end > chunk.end ? this.byStart[chunk.end] : null;
23003 }
23004 return this;
23005 };
23006
23007 MagicString.prototype.lastChar = function lastChar () {
23008 if (this.outro.length)
23009 { return this.outro[this.outro.length - 1]; }
23010 var chunk = this.lastChunk;
23011 do {
23012 if (chunk.outro.length)
23013 { return chunk.outro[chunk.outro.length - 1]; }
23014 if (chunk.content.length)
23015 { return chunk.content[chunk.content.length - 1]; }
23016 if (chunk.intro.length)
23017 { return chunk.intro[chunk.intro.length - 1]; }
23018 } while (chunk = chunk.previous);
23019 if (this.intro.length)
23020 { return this.intro[this.intro.length - 1]; }
23021 return '';
23022 };
23023
23024 MagicString.prototype.lastLine = function lastLine () {
23025 var lineIndex = this.outro.lastIndexOf(n);
23026 if (lineIndex !== -1)
23027 { return this.outro.substr(lineIndex + 1); }
23028 var lineStr = this.outro;
23029 var chunk = this.lastChunk;
23030 do {
23031 if (chunk.outro.length > 0) {
23032 lineIndex = chunk.outro.lastIndexOf(n);
23033 if (lineIndex !== -1)
23034 { return chunk.outro.substr(lineIndex + 1) + lineStr; }
23035 lineStr = chunk.outro + lineStr;
23036 }
23037
23038 if (chunk.content.length > 0) {
23039 lineIndex = chunk.content.lastIndexOf(n);
23040 if (lineIndex !== -1)
23041 { return chunk.content.substr(lineIndex + 1) + lineStr; }
23042 lineStr = chunk.content + lineStr;
23043 }
23044
23045 if (chunk.intro.length > 0) {
23046 lineIndex = chunk.intro.lastIndexOf(n);
23047 if (lineIndex !== -1)
23048 { return chunk.intro.substr(lineIndex + 1) + lineStr; }
23049 lineStr = chunk.intro + lineStr;
23050 }
23051 } while (chunk = chunk.previous);
23052 lineIndex = this.intro.lastIndexOf(n);
23053 if (lineIndex !== -1)
23054 { return this.intro.substr(lineIndex + 1) + lineStr; }
23055 return this.intro + lineStr;
23056 };
23057
23058 MagicString.prototype.slice = function slice (start, end) {
23059 if ( start === void 0 ) start = 0;
23060 if ( end === void 0 ) end = this.original.length;
23061
23062 while (start < 0) { start += this.original.length; }
23063 while (end < 0) { end += this.original.length; }
23064
23065 var result = '';
23066
23067 // find start chunk
23068 var chunk = this.firstChunk;
23069 while (chunk && (chunk.start > start || chunk.end <= start)) {
23070 // found end chunk before start
23071 if (chunk.start < end && chunk.end >= end) {
23072 return result;
23073 }
23074
23075 chunk = chunk.next;
23076 }
23077
23078 if (chunk && chunk.edited && chunk.start !== start)
23079 { throw new Error(("Cannot use replaced character " + start + " as slice start anchor.")); }
23080
23081 var startChunk = chunk;
23082 while (chunk) {
23083 if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
23084 result += chunk.intro;
23085 }
23086
23087 var containsEnd = chunk.start < end && chunk.end >= end;
23088 if (containsEnd && chunk.edited && chunk.end !== end)
23089 { throw new Error(("Cannot use replaced character " + end + " as slice end anchor.")); }
23090
23091 var sliceStart = startChunk === chunk ? start - chunk.start : 0;
23092 var sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
23093
23094 result += chunk.content.slice(sliceStart, sliceEnd);
23095
23096 if (chunk.outro && (!containsEnd || chunk.end === end)) {
23097 result += chunk.outro;
23098 }
23099
23100 if (containsEnd) {
23101 break;
23102 }
23103
23104 chunk = chunk.next;
23105 }
23106
23107 return result;
23108 };
23109
23110 // TODO deprecate this? not really very useful
23111 MagicString.prototype.snip = function snip (start, end) {
23112 var clone = this.clone();
23113 clone.remove(0, start);
23114 clone.remove(end, clone.original.length);
23115
23116 return clone;
23117 };
23118
23119 MagicString.prototype._split = function _split (index) {
23120 if (this.byStart[index] || this.byEnd[index]) { return; }
23121
23122 var chunk = this.lastSearchedChunk;
23123 var searchForward = index > chunk.end;
23124
23125 while (chunk) {
23126 if (chunk.contains(index)) { return this._splitChunk(chunk, index); }
23127
23128 chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
23129 }
23130 };
23131
23132 MagicString.prototype._splitChunk = function _splitChunk (chunk, index) {
23133 if (chunk.edited && chunk.content.length) {
23134 // zero-length edited chunks are a special case (overlapping replacements)
23135 var loc = getLocator$1(this.original)(index);
23136 throw new Error(
23137 ("Cannot split a chunk that has already been edited (" + (loc.line) + ":" + (loc.column) + " – \"" + (chunk.original) + "\")")
23138 );
23139 }
23140
23141 var newChunk = chunk.split(index);
23142
23143 this.byEnd[index] = chunk;
23144 this.byStart[index] = newChunk;
23145 this.byEnd[newChunk.end] = newChunk;
23146
23147 if (chunk === this.lastChunk) { this.lastChunk = newChunk; }
23148
23149 this.lastSearchedChunk = chunk;
23150 return true;
23151 };
23152
23153 MagicString.prototype.toString = function toString () {
23154 var str = this.intro;
23155
23156 var chunk = this.firstChunk;
23157 while (chunk) {
23158 str += chunk.toString();
23159 chunk = chunk.next;
23160 }
23161
23162 return str + this.outro;
23163 };
23164
23165 MagicString.prototype.isEmpty = function isEmpty () {
23166 var chunk = this.firstChunk;
23167 do {
23168 if (chunk.intro.length && chunk.intro.trim() ||
23169 chunk.content.length && chunk.content.trim() ||
23170 chunk.outro.length && chunk.outro.trim())
23171 { return false; }
23172 } while (chunk = chunk.next);
23173 return true;
23174 };
23175
23176 MagicString.prototype.length = function length () {
23177 var chunk = this.firstChunk;
23178 var length = 0;
23179 do {
23180 length += chunk.intro.length + chunk.content.length + chunk.outro.length;
23181 } while (chunk = chunk.next);
23182 return length;
23183 };
23184
23185 MagicString.prototype.trimLines = function trimLines () {
23186 return this.trim('[\\r\\n]');
23187 };
23188
23189 MagicString.prototype.trim = function trim (charType) {
23190 return this.trimStart(charType).trimEnd(charType);
23191 };
23192
23193 MagicString.prototype.trimEndAborted = function trimEndAborted (charType) {
23194 var rx = new RegExp((charType || '\\s') + '+$');
23195
23196 this.outro = this.outro.replace(rx, '');
23197 if (this.outro.length) { return true; }
23198
23199 var chunk = this.lastChunk;
23200
23201 do {
23202 var end = chunk.end;
23203 var aborted = chunk.trimEnd(rx);
23204
23205 // if chunk was trimmed, we have a new lastChunk
23206 if (chunk.end !== end) {
23207 if (this.lastChunk === chunk) {
23208 this.lastChunk = chunk.next;
23209 }
23210
23211 this.byEnd[chunk.end] = chunk;
23212 this.byStart[chunk.next.start] = chunk.next;
23213 this.byEnd[chunk.next.end] = chunk.next;
23214 }
23215
23216 if (aborted) { return true; }
23217 chunk = chunk.previous;
23218 } while (chunk);
23219
23220 return false;
23221 };
23222
23223 MagicString.prototype.trimEnd = function trimEnd (charType) {
23224 this.trimEndAborted(charType);
23225 return this;
23226 };
23227 MagicString.prototype.trimStartAborted = function trimStartAborted (charType) {
23228 var rx = new RegExp('^' + (charType || '\\s') + '+');
23229
23230 this.intro = this.intro.replace(rx, '');
23231 if (this.intro.length) { return true; }
23232
23233 var chunk = this.firstChunk;
23234
23235 do {
23236 var end = chunk.end;
23237 var aborted = chunk.trimStart(rx);
23238
23239 if (chunk.end !== end) {
23240 // special case...
23241 if (chunk === this.lastChunk) { this.lastChunk = chunk.next; }
23242
23243 this.byEnd[chunk.end] = chunk;
23244 this.byStart[chunk.next.start] = chunk.next;
23245 this.byEnd[chunk.next.end] = chunk.next;
23246 }
23247
23248 if (aborted) { return true; }
23249 chunk = chunk.next;
23250 } while (chunk);
23251
23252 return false;
23253 };
23254
23255 MagicString.prototype.trimStart = function trimStart (charType) {
23256 this.trimStartAborted(charType);
23257 return this;
23258 };
23259
23260 const UNKNOWN = {};
23261 function gather_possible_values(node, set) {
23262 if (node.type === 'Literal') {
23263 set.add(node.value);
23264 }
23265 else if (node.type === 'ConditionalExpression') {
23266 gather_possible_values(node.consequent, set);
23267 gather_possible_values(node.alternate, set);
23268 }
23269 else {
23270 set.add(UNKNOWN);
23271 }
23272 }
23273
23274 var BlockAppliesToNode;
23275 (function (BlockAppliesToNode) {
23276 BlockAppliesToNode[BlockAppliesToNode["NotPossible"] = 0] = "NotPossible";
23277 BlockAppliesToNode[BlockAppliesToNode["Possible"] = 1] = "Possible";
23278 BlockAppliesToNode[BlockAppliesToNode["UnknownSelectorType"] = 2] = "UnknownSelectorType";
23279 })(BlockAppliesToNode || (BlockAppliesToNode = {}));
23280 class Selector$1 {
23281 constructor(node, stylesheet) {
23282 this.node = node;
23283 this.stylesheet = stylesheet;
23284 this.blocks = group_selectors(node);
23285 // take trailing :global(...) selectors out of consideration
23286 let i = this.blocks.length;
23287 while (i > 0) {
23288 if (!this.blocks[i - 1].global)
23289 break;
23290 i -= 1;
23291 }
23292 this.local_blocks = this.blocks.slice(0, i);
23293 this.used = this.local_blocks.length === 0;
23294 }
23295 apply(node, stack) {
23296 const to_encapsulate = [];
23297 apply_selector(this.local_blocks.slice(), node, stack.slice(), to_encapsulate);
23298 if (to_encapsulate.length > 0) {
23299 to_encapsulate.forEach(({ node, block }) => {
23300 this.stylesheet.nodes_with_css_class.add(node);
23301 block.should_encapsulate = true;
23302 });
23303 this.used = true;
23304 }
23305 }
23306 minify(code) {
23307 let c = null;
23308 this.blocks.forEach((block, i) => {
23309 if (i > 0) {
23310 if (block.start - c > 1) {
23311 code.overwrite(c, block.start, block.combinator.name || ' ');
23312 }
23313 }
23314 c = block.end;
23315 });
23316 }
23317 transform(code, attr, max_amount_class_specificity_increased) {
23318 const amount_class_specificity_to_increase = max_amount_class_specificity_increased - this.blocks.filter(block => block.should_encapsulate).length;
23319 attr = attr.repeat(amount_class_specificity_to_increase + 1);
23320 function encapsulate_block(block) {
23321 let i = block.selectors.length;
23322 while (i--) {
23323 const selector = block.selectors[i];
23324 if (selector.type === 'PseudoElementSelector' || selector.type === 'PseudoClassSelector') {
23325 if (selector.name !== 'root') {
23326 if (i === 0)
23327 code.prependRight(selector.start, attr);
23328 }
23329 continue;
23330 }
23331 if (selector.type === 'TypeSelector' && selector.name === '*') {
23332 code.overwrite(selector.start, selector.end, attr);
23333 }
23334 else {
23335 code.appendLeft(selector.end, attr);
23336 }
23337 break;
23338 }
23339 }
23340 this.blocks.forEach((block) => {
23341 if (block.global) {
23342 const selector = block.selectors[0];
23343 const first = selector.children[0];
23344 const last = selector.children[selector.children.length - 1];
23345 code.remove(selector.start, first.start).remove(last.end, selector.end);
23346 }
23347 if (block.should_encapsulate)
23348 encapsulate_block(block);
23349 });
23350 }
23351 validate(component) {
23352 this.blocks.forEach((block) => {
23353 let i = block.selectors.length;
23354 while (i-- > 1) {
23355 const selector = block.selectors[i];
23356 if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
23357 component.error(selector, {
23358 code: `css-invalid-global`,
23359 message: `:global(...) must be the first element in a compound selector`
23360 });
23361 }
23362 }
23363 });
23364 let start = 0;
23365 let end = this.blocks.length;
23366 for (; start < end; start += 1) {
23367 if (!this.blocks[start].global)
23368 break;
23369 }
23370 for (; end > start; end -= 1) {
23371 if (!this.blocks[end - 1].global)
23372 break;
23373 }
23374 for (let i = start; i < end; i += 1) {
23375 if (this.blocks[i].global) {
23376 component.error(this.blocks[i].selectors[0], {
23377 code: `css-invalid-global`,
23378 message: `:global(...) can be at the start or end of a selector sequence, but not in the middle`
23379 });
23380 }
23381 }
23382 }
23383 get_amount_class_specificity_increased() {
23384 let count = 0;
23385 for (const block of this.blocks) {
23386 if (block.should_encapsulate) {
23387 count++;
23388 }
23389 }
23390 return count;
23391 }
23392 }
23393 function apply_selector(blocks, node, stack, to_encapsulate) {
23394 const block = blocks.pop();
23395 if (!block)
23396 return false;
23397 if (!node) {
23398 return blocks.every(block => block.global);
23399 }
23400 switch (block_might_apply_to_node(block, node)) {
23401 case BlockAppliesToNode.NotPossible:
23402 return false;
23403 case BlockAppliesToNode.UnknownSelectorType:
23404 // bail. TODO figure out what these could be
23405 to_encapsulate.push({ node, block });
23406 return true;
23407 }
23408 if (block.combinator) {
23409 if (block.combinator.type === 'WhiteSpace') {
23410 for (const ancestor_block of blocks) {
23411 if (ancestor_block.global) {
23412 continue;
23413 }
23414 for (const stack_node of stack) {
23415 if (block_might_apply_to_node(ancestor_block, stack_node) !== BlockAppliesToNode.NotPossible) {
23416 to_encapsulate.push({ node: stack_node, block: ancestor_block });
23417 }
23418 }
23419 if (to_encapsulate.length) {
23420 to_encapsulate.push({ node, block });
23421 return true;
23422 }
23423 }
23424 if (blocks.every(block => block.global)) {
23425 to_encapsulate.push({ node, block });
23426 return true;
23427 }
23428 return false;
23429 }
23430 else if (block.combinator.name === '>') {
23431 if (apply_selector(blocks, stack.pop(), stack, to_encapsulate)) {
23432 to_encapsulate.push({ node, block });
23433 return true;
23434 }
23435 return false;
23436 }
23437 // TODO other combinators
23438 to_encapsulate.push({ node, block });
23439 return true;
23440 }
23441 to_encapsulate.push({ node, block });
23442 return true;
23443 }
23444 function block_might_apply_to_node(block, node) {
23445 let i = block.selectors.length;
23446 while (i--) {
23447 const selector = block.selectors[i];
23448 const name = typeof selector.name === 'string' && selector.name.replace(/\\(.)/g, '$1');
23449 if (selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector') {
23450 continue;
23451 }
23452 if (selector.type === 'PseudoClassSelector' && name === 'global') {
23453 // TODO shouldn't see this here... maybe we should enforce that :global(...)
23454 // cannot be sandwiched between non-global selectors?
23455 return BlockAppliesToNode.NotPossible;
23456 }
23457 if (selector.type === 'ClassSelector') {
23458 if (!attribute_matches(node, 'class', name, '~=', false) && !node.classes.some(c => c.name === name))
23459 return BlockAppliesToNode.NotPossible;
23460 }
23461 else if (selector.type === 'IdSelector') {
23462 if (!attribute_matches(node, 'id', name, '=', false))
23463 return BlockAppliesToNode.NotPossible;
23464 }
23465 else if (selector.type === 'AttributeSelector') {
23466 if (!attribute_matches(node, selector.name.name, selector.value && unquote(selector.value), selector.matcher, selector.flags))
23467 return BlockAppliesToNode.NotPossible;
23468 }
23469 else if (selector.type === 'TypeSelector') {
23470 if (node.name.toLowerCase() !== name.toLowerCase() && name !== '*')
23471 return BlockAppliesToNode.NotPossible;
23472 }
23473 else {
23474 return BlockAppliesToNode.UnknownSelectorType;
23475 }
23476 }
23477 return BlockAppliesToNode.Possible;
23478 }
23479 function test_attribute(operator, expected_value, case_insensitive, value) {
23480 if (case_insensitive) {
23481 expected_value = expected_value.toLowerCase();
23482 value = value.toLowerCase();
23483 }
23484 switch (operator) {
23485 case '=': return value === expected_value;
23486 case '~=': return value.split(/\s/).includes(expected_value);
23487 case '|=': return `${value}-`.startsWith(`${expected_value}-`);
23488 case '^=': return value.startsWith(expected_value);
23489 case '$=': return value.endsWith(expected_value);
23490 case '*=': return value.includes(expected_value);
23491 default: throw new Error(`this shouldn't happen`);
23492 }
23493 }
23494 function attribute_matches(node, name, expected_value, operator, case_insensitive) {
23495 const spread = node.attributes.find(attr => attr.type === 'Spread');
23496 if (spread)
23497 return true;
23498 if (node.bindings.some((binding) => binding.name === name))
23499 return true;
23500 const attr = node.attributes.find((attr) => attr.name === name);
23501 if (!attr)
23502 return false;
23503 if (attr.is_true)
23504 return operator === null;
23505 if (!expected_value)
23506 return true;
23507 if (attr.chunks.length === 1) {
23508 const value = attr.chunks[0];
23509 if (!value)
23510 return false;
23511 if (value.type === 'Text')
23512 return test_attribute(operator, expected_value, case_insensitive, value.data);
23513 }
23514 const possible_values = new Set();
23515 let prev_values = [];
23516 for (const chunk of attr.chunks) {
23517 const current_possible_values = new Set();
23518 if (chunk.type === 'Text') {
23519 current_possible_values.add(chunk.data);
23520 }
23521 else {
23522 gather_possible_values(chunk.node, current_possible_values);
23523 }
23524 // impossible to find out all combinations
23525 if (current_possible_values.has(UNKNOWN))
23526 return true;
23527 if (prev_values.length > 0) {
23528 const start_with_space = [];
23529 const remaining = [];
23530 current_possible_values.forEach((current_possible_value) => {
23531 if (/^\s/.test(current_possible_value)) {
23532 start_with_space.push(current_possible_value);
23533 }
23534 else {
23535 remaining.push(current_possible_value);
23536 }
23537 });
23538 if (remaining.length > 0) {
23539 if (start_with_space.length > 0) {
23540 prev_values.forEach(prev_value => possible_values.add(prev_value));
23541 }
23542 const combined = [];
23543 prev_values.forEach((prev_value) => {
23544 remaining.forEach((value) => {
23545 combined.push(prev_value + value);
23546 });
23547 });
23548 prev_values = combined;
23549 start_with_space.forEach((value) => {
23550 if (/\s$/.test(value)) {
23551 possible_values.add(value);
23552 }
23553 else {
23554 prev_values.push(value);
23555 }
23556 });
23557 continue;
23558 }
23559 else {
23560 prev_values.forEach(prev_value => possible_values.add(prev_value));
23561 prev_values = [];
23562 }
23563 }
23564 current_possible_values.forEach((current_possible_value) => {
23565 if (/\s$/.test(current_possible_value)) {
23566 possible_values.add(current_possible_value);
23567 }
23568 else {
23569 prev_values.push(current_possible_value);
23570 }
23571 });
23572 if (prev_values.length < current_possible_values.size) {
23573 prev_values.push(' ');
23574 }
23575 if (prev_values.length > 20) {
23576 // might grow exponentially, bail out
23577 return true;
23578 }
23579 }
23580 prev_values.forEach(prev_value => possible_values.add(prev_value));
23581 if (possible_values.has(UNKNOWN))
23582 return true;
23583 for (const value of possible_values) {
23584 if (test_attribute(operator, expected_value, case_insensitive, value))
23585 return true;
23586 }
23587 return false;
23588 }
23589 function unquote(value) {
23590 if (value.type === 'Identifier')
23591 return value.name;
23592 const str = value.value;
23593 if (str[0] === str[str.length - 1] && str[0] === "'" || str[0] === '"') {
23594 return str.slice(1, str.length - 1);
23595 }
23596 return str;
23597 }
23598 class Block$2 {
23599 constructor(combinator) {
23600 this.combinator = combinator;
23601 this.global = false;
23602 this.selectors = [];
23603 this.start = null;
23604 this.end = null;
23605 this.should_encapsulate = false;
23606 }
23607 add(selector) {
23608 if (this.selectors.length === 0) {
23609 this.start = selector.start;
23610 this.global = selector.type === 'PseudoClassSelector' && selector.name === 'global';
23611 }
23612 this.selectors.push(selector);
23613 this.end = selector.end;
23614 }
23615 }
23616 function group_selectors(selector) {
23617 let block = new Block$2(null);
23618 const blocks = [block];
23619 selector.children.forEach((child) => {
23620 if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
23621 block = new Block$2(child);
23622 blocks.push(block);
23623 }
23624 else {
23625 block.add(child);
23626 }
23627 });
23628 return blocks;
23629 }
23630
23631 // https://github.com/darkskyapp/string-hash/blob/master/index.js
23632 function hash(str) {
23633 str = str.replace(/\r/g, "");
23634 let hash = 5381;
23635 let i = str.length;
23636 while (i--)
23637 hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
23638 return (hash >>> 0).toString(36);
23639 }
23640
23641 function remove_css_prefix(name) {
23642 return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, '');
23643 }
23644 const is_keyframes_node = (node) => remove_css_prefix(node.name) === 'keyframes';
23645 const at_rule_has_declaration = ({ block }) => block &&
23646 block.children &&
23647 block.children.find((node) => node.type === 'Declaration');
23648 function minify_declarations(code, start, declarations) {
23649 let c = start;
23650 declarations.forEach((declaration, i) => {
23651 const separator = i > 0 ? ';' : '';
23652 if ((declaration.node.start - c) > separator.length) {
23653 code.overwrite(c, declaration.node.start, separator);
23654 }
23655 declaration.minify(code);
23656 c = declaration.node.end;
23657 });
23658 return c;
23659 }
23660 class Rule$1 {
23661 constructor(node, stylesheet, parent) {
23662 this.node = node;
23663 this.parent = parent;
23664 this.selectors = node.selector.children.map((node) => new Selector$1(node, stylesheet));
23665 this.declarations = node.block.children.map((node) => new Declaration$1(node));
23666 }
23667 apply(node, stack) {
23668 this.selectors.forEach(selector => selector.apply(node, stack)); // TODO move the logic in here?
23669 }
23670 is_used(dev) {
23671 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
23672 return true;
23673 if (this.declarations.length === 0)
23674 return dev;
23675 return this.selectors.some(s => s.used);
23676 }
23677 minify(code, _dev) {
23678 let c = this.node.start;
23679 let started = false;
23680 this.selectors.forEach((selector) => {
23681 if (selector.used) {
23682 const separator = started ? ',' : '';
23683 if ((selector.node.start - c) > separator.length) {
23684 code.overwrite(c, selector.node.start, separator);
23685 }
23686 selector.minify(code);
23687 c = selector.node.end;
23688 started = true;
23689 }
23690 });
23691 code.remove(c, this.node.block.start);
23692 c = this.node.block.start + 1;
23693 c = minify_declarations(code, c, this.declarations);
23694 code.remove(c, this.node.block.end - 1);
23695 }
23696 transform(code, id, keyframes, max_amount_class_specificity_increased) {
23697 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
23698 return true;
23699 const attr = `.${id}`;
23700 this.selectors.forEach(selector => selector.transform(code, attr, max_amount_class_specificity_increased));
23701 this.declarations.forEach(declaration => declaration.transform(code, keyframes));
23702 }
23703 validate(component) {
23704 this.selectors.forEach(selector => {
23705 selector.validate(component);
23706 });
23707 }
23708 warn_on_unused_selector(handler) {
23709 this.selectors.forEach(selector => {
23710 if (!selector.used)
23711 handler(selector);
23712 });
23713 }
23714 get_max_amount_class_specificity_increased() {
23715 return Math.max(...this.selectors.map(selector => selector.get_amount_class_specificity_increased()));
23716 }
23717 }
23718 class Declaration$1 {
23719 constructor(node) {
23720 this.node = node;
23721 }
23722 transform(code, keyframes) {
23723 const property = this.node.property && remove_css_prefix(this.node.property.toLowerCase());
23724 if (property === 'animation' || property === 'animation-name') {
23725 this.node.value.children.forEach((block) => {
23726 if (block.type === 'Identifier') {
23727 const name = block.name;
23728 if (keyframes.has(name)) {
23729 code.overwrite(block.start, block.end, keyframes.get(name));
23730 }
23731 }
23732 });
23733 }
23734 }
23735 minify(code) {
23736 if (!this.node.property)
23737 return; // @apply, and possibly other weird cases?
23738 const c = this.node.start + this.node.property.length;
23739 const first = this.node.value.children
23740 ? this.node.value.children[0]
23741 : this.node.value;
23742 let start = first.start;
23743 while (/\s/.test(code.original[start]))
23744 start += 1;
23745 if (start - c > 1) {
23746 code.overwrite(c, start, ':');
23747 }
23748 }
23749 }
23750 class Atrule$1 {
23751 constructor(node) {
23752 this.node = node;
23753 this.children = [];
23754 this.declarations = [];
23755 }
23756 apply(node, stack) {
23757 if (this.node.name === 'media' || this.node.name === 'supports') {
23758 this.children.forEach(child => {
23759 child.apply(node, stack);
23760 });
23761 }
23762 else if (is_keyframes_node(this.node)) {
23763 this.children.forEach((rule) => {
23764 rule.selectors.forEach(selector => {
23765 selector.used = true;
23766 });
23767 });
23768 }
23769 }
23770 is_used(_dev) {
23771 return true; // TODO
23772 }
23773 minify(code, dev) {
23774 if (this.node.name === 'media') {
23775 const expression_char = code.original[this.node.expression.start];
23776 let c = this.node.start + (expression_char === '(' ? 6 : 7);
23777 if (this.node.expression.start > c)
23778 code.remove(c, this.node.expression.start);
23779 this.node.expression.children.forEach((query) => {
23780 // TODO minify queries
23781 c = query.end;
23782 });
23783 code.remove(c, this.node.block.start);
23784 }
23785 else if (this.node.name === 'supports') {
23786 let c = this.node.start + 9;
23787 if (this.node.expression.start - c > 1)
23788 code.overwrite(c, this.node.expression.start, ' ');
23789 this.node.expression.children.forEach((query) => {
23790 // TODO minify queries
23791 c = query.end;
23792 });
23793 code.remove(c, this.node.block.start);
23794 }
23795 else {
23796 let c = this.node.start + this.node.name.length + 1;
23797 if (this.node.expression) {
23798 if (this.node.expression.start - c > 1)
23799 code.overwrite(c, this.node.expression.start, ' ');
23800 c = this.node.expression.end;
23801 }
23802 if (this.node.block && this.node.block.start - c > 0) {
23803 code.remove(c, this.node.block.start);
23804 }
23805 }
23806 // TODO other atrules
23807 if (this.node.block) {
23808 let c = this.node.block.start + 1;
23809 if (this.declarations.length) {
23810 c = minify_declarations(code, c, this.declarations);
23811 // if the atrule has children, leave the last declaration semicolon alone
23812 if (this.children.length)
23813 c++;
23814 }
23815 this.children.forEach(child => {
23816 if (child.is_used(dev)) {
23817 code.remove(c, child.node.start);
23818 child.minify(code, dev);
23819 c = child.node.end;
23820 }
23821 });
23822 code.remove(c, this.node.block.end - 1);
23823 }
23824 }
23825 transform(code, id, keyframes, max_amount_class_specificity_increased) {
23826 if (is_keyframes_node(this.node)) {
23827 this.node.expression.children.forEach(({ type, name, start, end }) => {
23828 if (type === 'Identifier') {
23829 if (name.startsWith('-global-')) {
23830 code.remove(start, start + 8);
23831 this.children.forEach((rule) => {
23832 rule.selectors.forEach(selector => {
23833 selector.used = true;
23834 });
23835 });
23836 }
23837 else {
23838 code.overwrite(start, end, keyframes.get(name));
23839 }
23840 }
23841 });
23842 }
23843 this.children.forEach(child => {
23844 child.transform(code, id, keyframes, max_amount_class_specificity_increased);
23845 });
23846 }
23847 validate(component) {
23848 this.children.forEach(child => {
23849 child.validate(component);
23850 });
23851 }
23852 warn_on_unused_selector(handler) {
23853 if (this.node.name !== 'media')
23854 return;
23855 this.children.forEach(child => {
23856 child.warn_on_unused_selector(handler);
23857 });
23858 }
23859 get_max_amount_class_specificity_increased() {
23860 return Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
23861 }
23862 }
23863 class Stylesheet {
23864 constructor(source, ast, filename, dev) {
23865 this.children = [];
23866 this.keyframes = new Map();
23867 this.nodes_with_css_class = new Set();
23868 this.source = source;
23869 this.ast = ast;
23870 this.filename = filename;
23871 this.dev = dev;
23872 if (ast.css && ast.css.children.length) {
23873 this.id = `svelte-${hash(ast.css.content.styles)}`;
23874 this.has_styles = true;
23875 const stack = [];
23876 let depth = 0;
23877 let current_atrule = null;
23878 walk(ast.css, {
23879 enter: (node) => {
23880 if (node.type === 'Atrule') {
23881 const atrule = new Atrule$1(node);
23882 stack.push(atrule);
23883 if (current_atrule) {
23884 current_atrule.children.push(atrule);
23885 }
23886 else if (depth <= 1) {
23887 this.children.push(atrule);
23888 }
23889 if (is_keyframes_node(node)) {
23890 node.expression.children.forEach((expression) => {
23891 if (expression.type === 'Identifier' && !expression.name.startsWith('-global-')) {
23892 this.keyframes.set(expression.name, `${this.id}-${expression.name}`);
23893 }
23894 });
23895 }
23896 else if (at_rule_has_declaration(node)) {
23897 const at_rule_declarations = node.block.children
23898 .filter(node => node.type === 'Declaration')
23899 .map(node => new Declaration$1(node));
23900 atrule.declarations.push(...at_rule_declarations);
23901 }
23902 current_atrule = atrule;
23903 }
23904 if (node.type === 'Rule') {
23905 const rule = new Rule$1(node, this, current_atrule);
23906 if (current_atrule) {
23907 current_atrule.children.push(rule);
23908 }
23909 else if (depth <= 1) {
23910 this.children.push(rule);
23911 }
23912 }
23913 depth += 1;
23914 },
23915 leave: (node) => {
23916 if (node.type === 'Atrule') {
23917 stack.pop();
23918 current_atrule = stack[stack.length - 1];
23919 }
23920 depth -= 1;
23921 }
23922 });
23923 }
23924 else {
23925 this.has_styles = false;
23926 }
23927 }
23928 apply(node) {
23929 if (!this.has_styles)
23930 return;
23931 const stack = [];
23932 let parent = node;
23933 while (parent = parent.parent) {
23934 if (parent.type === 'Element')
23935 stack.unshift(parent);
23936 }
23937 for (let i = 0; i < this.children.length; i += 1) {
23938 const child = this.children[i];
23939 child.apply(node, stack);
23940 }
23941 }
23942 reify() {
23943 this.nodes_with_css_class.forEach((node) => {
23944 node.add_css_class();
23945 });
23946 }
23947 render(file, should_transform_selectors) {
23948 if (!this.has_styles) {
23949 return { code: null, map: null };
23950 }
23951 const code = new MagicString(this.source);
23952 walk(this.ast.css, {
23953 enter: (node) => {
23954 code.addSourcemapLocation(node.start);
23955 code.addSourcemapLocation(node.end);
23956 }
23957 });
23958 if (should_transform_selectors) {
23959 const max = Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
23960 this.children.forEach((child) => {
23961 child.transform(code, this.id, this.keyframes, max);
23962 });
23963 }
23964 let c = 0;
23965 this.children.forEach(child => {
23966 if (child.is_used(this.dev)) {
23967 code.remove(c, child.node.start);
23968 child.minify(code, this.dev);
23969 c = child.node.end;
23970 }
23971 });
23972 code.remove(c, this.source.length);
23973 return {
23974 code: code.toString(),
23975 map: code.generateMap({
23976 includeContent: true,
23977 source: this.filename,
23978 file
23979 })
23980 };
23981 }
23982 validate(component) {
23983 this.children.forEach(child => {
23984 child.validate(component);
23985 });
23986 }
23987 warn_on_unused_selectors(component) {
23988 this.children.forEach(child => {
23989 child.warn_on_unused_selector((selector) => {
23990 component.warn(selector.node, {
23991 code: `css-unused-selector`,
23992 message: `Unused CSS selector`
23993 });
23994 });
23995 });
23996 }
23997 }
23998
23999 const test = typeof process !== 'undefined' && process.env.TEST;
24000
24001 class AbstractBlock extends Node$1 {
24002 constructor(component, parent, scope, info) {
24003 super(component, parent, scope, info);
24004 }
24005 warn_if_empty_block() {
24006 if (!this.children || this.children.length > 1)
24007 return;
24008 const child = this.children[0];
24009 if (!child || (child.type === 'Text' && !/[^ \r\n\f\v\t]/.test(child.data))) {
24010 this.component.warn(this, {
24011 code: 'empty-block',
24012 message: 'Empty block'
24013 });
24014 }
24015 }
24016 }
24017
24018 class PendingBlock extends AbstractBlock {
24019 constructor(component, parent, scope, info) {
24020 super(component, parent, scope, info);
24021 this.children = map_children(component, parent, scope, info.children);
24022 if (!info.skip) {
24023 this.warn_if_empty_block();
24024 }
24025 }
24026 }
24027
24028 class ThenBlock extends AbstractBlock {
24029 constructor(component, parent, scope, info) {
24030 super(component, parent, scope, info);
24031 this.scope = scope.child();
24032 if (parent.then_node) {
24033 parent.then_contexts.forEach(context => {
24034 this.scope.add(context.key.name, parent.expression.dependencies, this);
24035 });
24036 }
24037 this.children = map_children(component, parent, this.scope, info.children);
24038 if (!info.skip) {
24039 this.warn_if_empty_block();
24040 }
24041 }
24042 }
24043
24044 class CatchBlock extends AbstractBlock {
24045 constructor(component, parent, scope, info) {
24046 super(component, parent, scope, info);
24047 this.scope = scope.child();
24048 if (parent.catch_node) {
24049 parent.catch_contexts.forEach(context => {
24050 this.scope.add(context.key.name, parent.expression.dependencies, this);
24051 });
24052 }
24053 this.children = map_children(component, parent, this.scope, info.children);
24054 if (!info.skip) {
24055 this.warn_if_empty_block();
24056 }
24057 }
24058 }
24059
24060 function unpack_destructuring(contexts, node, modifier) {
24061 if (!node)
24062 return;
24063 if (node.type === 'Identifier') {
24064 contexts.push({
24065 key: node,
24066 modifier
24067 });
24068 }
24069 else if (node.type === 'RestElement') {
24070 contexts.push({
24071 key: node.argument,
24072 modifier
24073 });
24074 }
24075 else if (node.type === 'ArrayPattern') {
24076 node.elements.forEach((element, i) => {
24077 if (element && element.type === 'RestElement') {
24078 unpack_destructuring(contexts, element, node => x `${modifier(node)}.slice(${i})`);
24079 }
24080 else if (element && element.type === 'AssignmentPattern') {
24081 unpack_destructuring(contexts, element.left, node => x `${modifier(node)}[${i}] !== undefined ? ${modifier(node)}[${i}] : ${element.right}`);
24082 }
24083 else {
24084 unpack_destructuring(contexts, element, node => x `${modifier(node)}[${i}]`);
24085 }
24086 });
24087 }
24088 else if (node.type === 'ObjectPattern') {
24089 const used_properties = [];
24090 node.properties.forEach((property) => {
24091 if (property.type === 'RestElement') {
24092 unpack_destructuring(contexts, property.argument, node => x `@object_without_properties(${modifier(node)}, [${used_properties}])`);
24093 }
24094 else {
24095 const key = property.key;
24096 const value = property.value;
24097 used_properties.push(x `"${key.name}"`);
24098 if (value.type === 'AssignmentPattern') {
24099 unpack_destructuring(contexts, value.left, node => x `${modifier(node)}.${key.name} !== undefined ? ${modifier(node)}.${key.name} : ${value.right}`);
24100 }
24101 else {
24102 unpack_destructuring(contexts, value, node => x `${modifier(node)}.${key.name}`);
24103 }
24104 }
24105 });
24106 }
24107 }
24108
24109 class AwaitBlock$1 extends Node$1 {
24110 constructor(component, parent, scope, info) {
24111 super(component, parent, scope, info);
24112 this.expression = new Expression(component, this, scope, info.expression);
24113 this.then_node = info.value;
24114 this.catch_node = info.error;
24115 if (this.then_node) {
24116 this.then_contexts = [];
24117 unpack_destructuring(this.then_contexts, info.value, node => node);
24118 }
24119 if (this.catch_node) {
24120 this.catch_contexts = [];
24121 unpack_destructuring(this.catch_contexts, info.error, node => node);
24122 }
24123 this.pending = new PendingBlock(component, this, scope, info.pending);
24124 this.then = new ThenBlock(component, this, scope, info.then);
24125 this.catch = new CatchBlock(component, this, scope, info.catch);
24126 }
24127 }
24128
24129 class EventHandler extends Node$1 {
24130 constructor(component, parent, template_scope, info) {
24131 super(component, parent, template_scope, info);
24132 this.uses_context = false;
24133 this.can_make_passive = false;
24134 this.name = info.name;
24135 this.modifiers = new Set(info.modifiers);
24136 if (info.expression) {
24137 this.expression = new Expression(component, this, template_scope, info.expression);
24138 this.uses_context = this.expression.uses_context;
24139 if (/FunctionExpression/.test(info.expression.type) && info.expression.params.length === 0) {
24140 // TODO make this detection more accurate — if `event.preventDefault` isn't called, and
24141 // `event` is passed to another function, we can make it passive
24142 this.can_make_passive = true;
24143 }
24144 else if (info.expression.type === 'Identifier') {
24145 let node = component.node_for_declaration.get(info.expression.name);
24146 if (node) {
24147 if (node.type === 'VariableDeclaration') {
24148 // for `const handleClick = () => {...}`, we want the [arrow] function expression node
24149 const declarator = node.declarations.find(d => d.id.name === info.expression.name);
24150 node = declarator && declarator.init;
24151 }
24152 if (node && (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') && node.params.length === 0) {
24153 this.can_make_passive = true;
24154 }
24155 }
24156 }
24157 }
24158 else {
24159 this.handler_name = component.get_unique_name(`${sanitize(this.name)}_handler`);
24160 }
24161 }
24162 get reassigned() {
24163 if (!this.expression) {
24164 return false;
24165 }
24166 const node = this.expression.node;
24167 if (/FunctionExpression/.test(node.type)) {
24168 return false;
24169 }
24170 return this.expression.dynamic_dependencies().length > 0;
24171 }
24172 }
24173
24174 class Body extends Node$1 {
24175 constructor(component, parent, scope, info) {
24176 super(component, parent, scope, info);
24177 this.handlers = [];
24178 info.attributes.forEach(node => {
24179 if (node.type === 'EventHandler') {
24180 this.handlers.push(new EventHandler(component, this, scope, node));
24181 }
24182 });
24183 }
24184 }
24185
24186 const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m;
24187 class Comment$2 extends Node$1 {
24188 constructor(component, parent, scope, info) {
24189 super(component, parent, scope, info);
24190 this.data = info.data;
24191 const match = pattern.exec(this.data);
24192 this.ignores = match ? match[1].split(/[^\S]/).map(x => x.trim()).filter(Boolean) : [];
24193 }
24194 }
24195
24196 class ElseBlock extends AbstractBlock {
24197 constructor(component, parent, scope, info) {
24198 super(component, parent, scope, info);
24199 this.children = map_children(component, this, scope, info.children);
24200 this.warn_if_empty_block();
24201 }
24202 }
24203
24204 class EachBlock$1 extends AbstractBlock {
24205 constructor(component, parent, scope, info) {
24206 super(component, parent, scope, info);
24207 this.has_binding = false;
24208 this.has_index_binding = false;
24209 this.expression = new Expression(component, this, scope, info.expression);
24210 this.context = info.context.name || 'each'; // TODO this is used to facilitate binding; currently fails with destructuring
24211 this.context_node = info.context;
24212 this.index = info.index;
24213 this.scope = scope.child();
24214 this.contexts = [];
24215 unpack_destructuring(this.contexts, info.context, node => node);
24216 this.contexts.forEach(context => {
24217 this.scope.add(context.key.name, this.expression.dependencies, this);
24218 });
24219 if (this.index) {
24220 // index can only change if this is a keyed each block
24221 const dependencies = info.key ? this.expression.dependencies : new Set([]);
24222 this.scope.add(this.index, dependencies, this);
24223 }
24224 this.key = info.key
24225 ? new Expression(component, this, this.scope, info.key)
24226 : null;
24227 this.has_animation = false;
24228 this.children = map_children(component, this, this.scope, info.children);
24229 if (this.has_animation) {
24230 if (this.children.length !== 1) {
24231 const child = this.children.find(child => !!child.animation);
24232 component.error(child.animation, {
24233 code: `invalid-animation`,
24234 message: `An element that use the animate directive must be the sole child of a keyed each block`
24235 });
24236 }
24237 }
24238 this.warn_if_empty_block();
24239 this.else = info.else
24240 ? new ElseBlock(component, this, this.scope, info.else)
24241 : null;
24242 }
24243 }
24244
24245 class Attribute extends Node$1 {
24246 constructor(component, parent, scope, info) {
24247 super(component, parent, scope, info);
24248 this.scope = scope;
24249 if (info.type === 'Spread') {
24250 this.name = null;
24251 this.is_spread = true;
24252 this.is_true = false;
24253 this.expression = new Expression(component, this, scope, info.expression);
24254 this.dependencies = this.expression.dependencies;
24255 this.chunks = null;
24256 this.is_static = false;
24257 }
24258 else {
24259 this.name = info.name;
24260 this.is_true = info.value === true;
24261 this.is_static = true;
24262 this.dependencies = new Set();
24263 this.chunks = this.is_true
24264 ? []
24265 : info.value.map(node => {
24266 if (node.type === 'Text')
24267 return node;
24268 this.is_static = false;
24269 const expression = new Expression(component, this, scope, node.expression);
24270 add_to_set(this.dependencies, expression.dependencies);
24271 return expression;
24272 });
24273 }
24274 }
24275 get_dependencies() {
24276 if (this.is_spread)
24277 return this.expression.dynamic_dependencies();
24278 const dependencies = new Set();
24279 this.chunks.forEach(chunk => {
24280 if (chunk.type === 'Expression') {
24281 add_to_set(dependencies, chunk.dynamic_dependencies());
24282 }
24283 });
24284 return Array.from(dependencies);
24285 }
24286 get_value(block) {
24287 if (this.is_true)
24288 return x `true`;
24289 if (this.chunks.length === 0)
24290 return x `""`;
24291 if (this.chunks.length === 1) {
24292 return this.chunks[0].type === 'Text'
24293 ? string_literal(this.chunks[0].data)
24294 : this.chunks[0].manipulate(block);
24295 }
24296 let expression = this.chunks
24297 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : chunk.manipulate(block))
24298 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
24299 if (this.chunks[0].type !== 'Text') {
24300 expression = x `"" + ${expression}`;
24301 }
24302 return expression;
24303 }
24304 get_static_value() {
24305 if (this.is_spread || this.dependencies.size > 0)
24306 return null;
24307 return this.is_true
24308 ? true
24309 : this.chunks[0]
24310 // method should be called only when `is_static = true`
24311 ? this.chunks[0].data
24312 : '';
24313 }
24314 should_cache() {
24315 return this.is_static
24316 ? false
24317 : this.chunks.length === 1
24318 // @ts-ignore todo: probably error
24319 ? this.chunks[0].node.type !== 'Identifier' || this.scope.names.has(this.chunks[0].node.name)
24320 : true;
24321 }
24322 }
24323
24324 // TODO this should live in a specific binding
24325 const read_only_media_attributes = new Set([
24326 'duration',
24327 'buffered',
24328 'seekable',
24329 'played',
24330 'seeking',
24331 'ended',
24332 'videoHeight',
24333 'videoWidth'
24334 ]);
24335 class Binding extends Node$1 {
24336 constructor(component, parent, scope, info) {
24337 super(component, parent, scope, info);
24338 if (info.expression.type !== 'Identifier' && info.expression.type !== 'MemberExpression') {
24339 component.error(info, {
24340 code: 'invalid-directive-value',
24341 message: 'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
24342 });
24343 }
24344 this.name = info.name;
24345 this.expression = new Expression(component, this, scope, info.expression);
24346 this.raw_expression = JSON.parse(JSON.stringify(info.expression));
24347 const { name } = get_object(this.expression.node);
24348 this.is_contextual = Array.from(this.expression.references).some(name => scope.names.has(name));
24349 // make sure we track this as a mutable ref
24350 if (scope.is_let(name)) {
24351 component.error(this, {
24352 code: 'invalid-binding',
24353 message: 'Cannot bind to a variable declared with the let: directive'
24354 });
24355 }
24356 else if (scope.names.has(name)) {
24357 if (scope.is_await(name)) {
24358 component.error(this, {
24359 code: 'invalid-binding',
24360 message: 'Cannot bind to a variable declared with {#await ... then} or {:catch} blocks'
24361 });
24362 }
24363 scope.dependencies_for_name.get(name).forEach(name => {
24364 const variable = component.var_lookup.get(name);
24365 if (variable) {
24366 variable.mutated = true;
24367 }
24368 });
24369 }
24370 else {
24371 const variable = component.var_lookup.get(name);
24372 if (!variable || variable.global)
24373 component.error(this.expression.node, {
24374 code: 'binding-undeclared',
24375 message: `${name} is not declared`
24376 });
24377 variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
24378 if (info.expression.type === 'Identifier' && !variable.writable)
24379 component.error(this.expression.node, {
24380 code: 'invalid-binding',
24381 message: 'Cannot bind to a variable which is not writable',
24382 });
24383 }
24384 const type = parent.get_static_attribute_value('type');
24385 this.is_readonly = (dimensions.test(this.name) ||
24386 (parent.is_media_node && parent.is_media_node() && read_only_media_attributes.has(this.name)) ||
24387 (parent.name === 'input' && type === 'file') // TODO others?
24388 );
24389 }
24390 is_readonly_media_attribute() {
24391 return read_only_media_attributes.has(this.name);
24392 }
24393 }
24394
24395 class Transition extends Node$1 {
24396 constructor(component, parent, scope, info) {
24397 super(component, parent, scope, info);
24398 component.warn_if_undefined(info.name, info, scope);
24399 this.name = info.name;
24400 component.add_reference(info.name.split('.')[0]);
24401 this.directive = info.intro && info.outro ? 'transition' : info.intro ? 'in' : 'out';
24402 this.is_local = info.modifiers.includes('local');
24403 if ((info.intro && parent.intro) || (info.outro && parent.outro)) {
24404 const parent_transition = (parent.intro || parent.outro);
24405 const message = this.directive === parent_transition.directive
24406 ? `An element can only have one '${this.directive}' directive`
24407 : `An element cannot have both ${describe(parent_transition)} directive and ${describe(this)} directive`;
24408 component.error(info, {
24409 code: `duplicate-transition`,
24410 message
24411 });
24412 }
24413 this.expression = info.expression
24414 ? new Expression(component, this, scope, info.expression, true)
24415 : null;
24416 }
24417 }
24418 function describe(transition) {
24419 return transition.directive === 'transition'
24420 ? `a 'transition'`
24421 : `an '${transition.directive}'`;
24422 }
24423
24424 class Animation extends Node$1 {
24425 constructor(component, parent, scope, info) {
24426 super(component, parent, scope, info);
24427 component.warn_if_undefined(info.name, info, scope);
24428 this.name = info.name;
24429 component.add_reference(info.name.split('.')[0]);
24430 if (parent.animation) {
24431 component.error(this, {
24432 code: `duplicate-animation`,
24433 message: `An element can only have one 'animate' directive`
24434 });
24435 }
24436 const block = parent.parent;
24437 if (!block || block.type !== 'EachBlock' || !block.key) {
24438 // TODO can we relax the 'immediate child' rule?
24439 component.error(this, {
24440 code: `invalid-animation`,
24441 message: `An element that use the animate directive must be the immediate child of a keyed each block`
24442 });
24443 }
24444 block.has_animation = true;
24445 this.expression = info.expression
24446 ? new Expression(component, this, scope, info.expression, true)
24447 : null;
24448 }
24449 }
24450
24451 class Class extends Node$1 {
24452 constructor(component, parent, scope, info) {
24453 super(component, parent, scope, info);
24454 this.name = info.name;
24455 this.expression = info.expression
24456 ? new Expression(component, this, scope, info.expression)
24457 : null;
24458 }
24459 }
24460
24461 // Whitespace inside one of these elements will not result in
24462 // a whitespace node being created in any circumstances. (This
24463 // list is almost certainly very incomplete)
24464 const elements_without_text = new Set([
24465 'audio',
24466 'datalist',
24467 'dl',
24468 'optgroup',
24469 'select',
24470 'video',
24471 ]);
24472 class Text$1 extends Node$1 {
24473 constructor(component, parent, scope, info) {
24474 super(component, parent, scope, info);
24475 this.data = info.data;
24476 this.synthetic = info.synthetic || false;
24477 }
24478 should_skip() {
24479 if (/\S/.test(this.data))
24480 return false;
24481 const parent_element = this.find_nearest(/(?:Element|InlineComponent|Head)/);
24482 if (!parent_element)
24483 return false;
24484 if (parent_element.type === 'Head')
24485 return true;
24486 if (parent_element.type === 'InlineComponent')
24487 return parent_element.children.length === 1 && this === parent_element.children[0];
24488 // svg namespace exclusions
24489 if (/svg$/.test(parent_element.namespace)) {
24490 if (this.prev && this.prev.type === "Element" && this.prev.name === "tspan")
24491 return false;
24492 }
24493 return parent_element.namespace || elements_without_text.has(parent_element.name);
24494 }
24495 }
24496
24497 const applicable = new Set(['Identifier', 'ObjectExpression', 'ArrayExpression', 'Property']);
24498 class Let extends Node$1 {
24499 constructor(component, parent, scope, info) {
24500 super(component, parent, scope, info);
24501 this.names = [];
24502 this.name = { type: 'Identifier', name: info.name };
24503 const { names } = this;
24504 if (info.expression) {
24505 this.value = info.expression;
24506 walk(info.expression, {
24507 enter(node) {
24508 if (!applicable.has(node.type)) {
24509 component.error(node, {
24510 code: 'invalid-let',
24511 message: `let directive value must be an identifier or an object/array pattern`
24512 });
24513 }
24514 if (node.type === 'Identifier') {
24515 names.push(node.name);
24516 }
24517 // slightly unfortunate hack
24518 if (node.type === 'ArrayExpression') {
24519 node.type = 'ArrayPattern';
24520 }
24521 if (node.type === 'ObjectExpression') {
24522 node.type = 'ObjectPattern';
24523 }
24524 }
24525 });
24526 }
24527 else {
24528 names.push(this.name.name);
24529 }
24530 }
24531 }
24532
24533 const 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)$/;
24534 const 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(' ');
24535 const aria_attribute_set = new Set(aria_attributes);
24536 const aria_roles = 'alert alertdialog application article banner blockquote button caption cell checkbox code columnheader combobox complementary contentinfo definition deletion dialog directory document emphasis feed figure form generic grid gridcell group heading img link list listbox listitem log main marquee math meter menu menubar menuitem menuitemcheckbox menuitemradio navigation none note option paragraph presentation progressbar radio radiogroup region row rowgroup rowheader scrollbar search searchbox separator slider spinbutton status strong subscript superscript switch tab table tablist tabpanel term textbox time timer toolbar tooltip tree treegrid treeitem'.split(' ');
24537 const aria_role_set = new Set(aria_roles);
24538 const a11y_required_attributes = {
24539 a: ['href'],
24540 area: ['alt', 'aria-label', 'aria-labelledby'],
24541 // html-has-lang
24542 html: ['lang'],
24543 // iframe-has-title
24544 iframe: ['title'],
24545 img: ['alt'],
24546 object: ['title', 'aria-label', 'aria-labelledby']
24547 };
24548 const a11y_distracting_elements = new Set([
24549 'blink',
24550 'marquee'
24551 ]);
24552 const a11y_required_content = new Set([
24553 // anchor-has-content
24554 'a',
24555 // heading-has-content
24556 'h1',
24557 'h2',
24558 'h3',
24559 'h4',
24560 'h5',
24561 'h6'
24562 ]);
24563 const a11y_no_onchange = new Set([
24564 'select',
24565 'option'
24566 ]);
24567 const a11y_labelable = new Set([
24568 "button",
24569 "input",
24570 "keygen",
24571 "meter",
24572 "output",
24573 "progress",
24574 "select",
24575 "textarea"
24576 ]);
24577 const invisible_elements = new Set(['meta', 'html', 'script', 'style']);
24578 const valid_modifiers = new Set([
24579 'preventDefault',
24580 'stopPropagation',
24581 'capture',
24582 'once',
24583 'passive',
24584 'self'
24585 ]);
24586 const passive_events = new Set([
24587 'wheel',
24588 'touchstart',
24589 'touchmove',
24590 'touchend',
24591 'touchcancel'
24592 ]);
24593 function get_namespace(parent, element, explicit_namespace) {
24594 const parent_element = parent.find_nearest(/^Element/);
24595 if (!parent_element) {
24596 return explicit_namespace || (svg$1.test(element.name)
24597 ? namespaces.svg
24598 : null);
24599 }
24600 if (svg$1.test(element.name.toLowerCase()))
24601 return namespaces.svg;
24602 if (parent_element.name.toLowerCase() === 'foreignobject')
24603 return null;
24604 return parent_element.namespace;
24605 }
24606 class Element$1 extends Node$1 {
24607 constructor(component, parent, scope, info) {
24608 super(component, parent, scope, info);
24609 this.attributes = [];
24610 this.actions = [];
24611 this.bindings = [];
24612 this.classes = [];
24613 this.handlers = [];
24614 this.lets = [];
24615 this.intro = null;
24616 this.outro = null;
24617 this.animation = null;
24618 this.name = info.name;
24619 this.namespace = get_namespace(parent, this, component.namespace);
24620 if (this.name === 'textarea') {
24621 if (info.children.length > 0) {
24622 const value_attribute = info.attributes.find(node => node.name === 'value');
24623 if (value_attribute) {
24624 component.error(value_attribute, {
24625 code: `textarea-duplicate-value`,
24626 message: `A <textarea> can have either a value attribute or (equivalently) child content, but not both`
24627 });
24628 }
24629 // this is an egregious hack, but it's the easiest way to get <textarea>
24630 // children treated the same way as a value attribute
24631 info.attributes.push({
24632 type: 'Attribute',
24633 name: 'value',
24634 value: info.children
24635 });
24636 info.children = [];
24637 }
24638 }
24639 if (this.name === 'option') {
24640 // Special case — treat these the same way:
24641 // <option>{foo}</option>
24642 // <option value={foo}>{foo}</option>
24643 const value_attribute = info.attributes.find(attribute => attribute.name === 'value');
24644 if (!value_attribute) {
24645 info.attributes.push({
24646 type: 'Attribute',
24647 name: 'value',
24648 value: info.children,
24649 synthetic: true
24650 });
24651 }
24652 }
24653 const has_let = info.attributes.some(node => node.type === 'Let');
24654 if (has_let) {
24655 scope = scope.child();
24656 }
24657 // Binding relies on Attribute, defer its evaluation
24658 const order = ['Binding']; // everything else is -1
24659 info.attributes.sort((a, b) => order.indexOf(a.type) - order.indexOf(b.type));
24660 info.attributes.forEach(node => {
24661 switch (node.type) {
24662 case 'Action':
24663 this.actions.push(new Action(component, this, scope, node));
24664 break;
24665 case 'Attribute':
24666 case 'Spread':
24667 // special case
24668 if (node.name === 'xmlns')
24669 this.namespace = node.value[0].data;
24670 this.attributes.push(new Attribute(component, this, scope, node));
24671 break;
24672 case 'Binding':
24673 this.bindings.push(new Binding(component, this, scope, node));
24674 break;
24675 case 'Class':
24676 this.classes.push(new Class(component, this, scope, node));
24677 break;
24678 case 'EventHandler':
24679 this.handlers.push(new EventHandler(component, this, scope, node));
24680 break;
24681 case 'Let': {
24682 const l = new Let(component, this, scope, node);
24683 this.lets.push(l);
24684 const dependencies = new Set([l.name.name]);
24685 l.names.forEach(name => {
24686 scope.add(name, dependencies, this);
24687 });
24688 break;
24689 }
24690 case 'Transition':
24691 {
24692 const transition = new Transition(component, this, scope, node);
24693 if (node.intro)
24694 this.intro = transition;
24695 if (node.outro)
24696 this.outro = transition;
24697 break;
24698 }
24699 case 'Animation':
24700 this.animation = new Animation(component, this, scope, node);
24701 break;
24702 default:
24703 throw new Error(`Not implemented: ${node.type}`);
24704 }
24705 });
24706 this.scope = scope;
24707 this.children = map_children(component, this, this.scope, info.children);
24708 this.validate();
24709 component.stylesheet.apply(this);
24710 }
24711 validate() {
24712 if (a11y_distracting_elements.has(this.name)) {
24713 // no-distracting-elements
24714 this.component.warn(this, {
24715 code: `a11y-distracting-elements`,
24716 message: `A11y: Avoid <${this.name}> elements`
24717 });
24718 }
24719 if (this.name === 'figcaption') {
24720 let { parent } = this;
24721 let is_figure_parent = false;
24722 while (parent) {
24723 if (parent.name === 'figure') {
24724 is_figure_parent = true;
24725 break;
24726 }
24727 if (parent.type === 'Element') {
24728 break;
24729 }
24730 parent = parent.parent;
24731 }
24732 if (!is_figure_parent) {
24733 this.component.warn(this, {
24734 code: `a11y-structure`,
24735 message: `A11y: <figcaption> must be an immediate child of <figure>`
24736 });
24737 }
24738 }
24739 if (this.name === 'figure') {
24740 const children = this.children.filter(node => {
24741 if (node.type === 'Comment')
24742 return false;
24743 if (node.type === 'Text')
24744 return /\S/.test(node.data);
24745 return true;
24746 });
24747 const index = children.findIndex(child => child.name === 'figcaption');
24748 if (index !== -1 && (index !== 0 && index !== children.length - 1)) {
24749 this.component.warn(children[index], {
24750 code: `a11y-structure`,
24751 message: `A11y: <figcaption> must be first or last child of <figure>`
24752 });
24753 }
24754 }
24755 this.validate_attributes();
24756 this.validate_special_cases();
24757 this.validate_bindings();
24758 this.validate_content();
24759 this.validate_event_handlers();
24760 }
24761 validate_attributes() {
24762 const { component, parent } = this;
24763 const attribute_map = new Map();
24764 this.attributes.forEach(attribute => {
24765 if (attribute.is_spread)
24766 return;
24767 const name = attribute.name.toLowerCase();
24768 // aria-props
24769 if (name.startsWith('aria-')) {
24770 if (invisible_elements.has(this.name)) {
24771 // aria-unsupported-elements
24772 component.warn(attribute, {
24773 code: `a11y-aria-attributes`,
24774 message: `A11y: <${this.name}> should not have aria-* attributes`
24775 });
24776 }
24777 const type = name.slice(5);
24778 if (!aria_attribute_set.has(type)) {
24779 const match = fuzzymatch(type, aria_attributes);
24780 let message = `A11y: Unknown aria attribute 'aria-${type}'`;
24781 if (match)
24782 message += ` (did you mean '${match}'?)`;
24783 component.warn(attribute, {
24784 code: `a11y-unknown-aria-attribute`,
24785 message
24786 });
24787 }
24788 if (name === 'aria-hidden' && /^h[1-6]$/.test(this.name)) {
24789 component.warn(attribute, {
24790 code: `a11y-hidden`,
24791 message: `A11y: <${this.name}> element should not be hidden`
24792 });
24793 }
24794 }
24795 // aria-role
24796 if (name === 'role') {
24797 if (invisible_elements.has(this.name)) {
24798 // aria-unsupported-elements
24799 component.warn(attribute, {
24800 code: `a11y-misplaced-role`,
24801 message: `A11y: <${this.name}> should not have role attribute`
24802 });
24803 }
24804 const value = attribute.get_static_value();
24805 // @ts-ignore
24806 if (value && !aria_role_set.has(value)) {
24807 // @ts-ignore
24808 const match = fuzzymatch(value, aria_roles);
24809 let message = `A11y: Unknown role '${value}'`;
24810 if (match)
24811 message += ` (did you mean '${match}'?)`;
24812 component.warn(attribute, {
24813 code: `a11y-unknown-role`,
24814 message
24815 });
24816 }
24817 }
24818 // no-access-key
24819 if (name === 'accesskey') {
24820 component.warn(attribute, {
24821 code: `a11y-accesskey`,
24822 message: `A11y: Avoid using accesskey`
24823 });
24824 }
24825 // no-autofocus
24826 if (name === 'autofocus') {
24827 component.warn(attribute, {
24828 code: `a11y-autofocus`,
24829 message: `A11y: Avoid using autofocus`
24830 });
24831 }
24832 // scope
24833 if (name === 'scope' && this.name !== 'th') {
24834 component.warn(attribute, {
24835 code: `a11y-misplaced-scope`,
24836 message: `A11y: The scope attribute should only be used with <th> elements`
24837 });
24838 }
24839 // tabindex-no-positive
24840 if (name === 'tabindex') {
24841 const value = attribute.get_static_value();
24842 // @ts-ignore todo is tabindex=true correct case?
24843 if (!isNaN(value) && +value > 0) {
24844 component.warn(attribute, {
24845 code: `a11y-positive-tabindex`,
24846 message: `A11y: avoid tabindex values above zero`
24847 });
24848 }
24849 }
24850 if (/(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/.test(name)) {
24851 component.error(attribute, {
24852 code: `illegal-attribute`,
24853 message: `'${name}' is not a valid attribute name`,
24854 });
24855 }
24856 if (name === 'slot') {
24857 if (!attribute.is_static) {
24858 component.error(attribute, {
24859 code: `invalid-slot-attribute`,
24860 message: `slot attribute cannot have a dynamic value`
24861 });
24862 }
24863 if (component.slot_outlets.has(name)) {
24864 component.error(attribute, {
24865 code: `duplicate-slot-attribute`,
24866 message: `Duplicate '${name}' slot`
24867 });
24868 component.slot_outlets.add(name);
24869 }
24870 if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
24871 component.error(attribute, {
24872 code: `invalid-slotted-content`,
24873 message: `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`,
24874 });
24875 }
24876 }
24877 if (name === 'is') {
24878 component.warn(attribute, {
24879 code: 'avoid-is',
24880 message: `The 'is' attribute is not supported cross-browser and should be avoided`
24881 });
24882 }
24883 attribute_map.set(attribute.name, attribute);
24884 });
24885 }
24886 validate_special_cases() {
24887 const { component, attributes, handlers } = this;
24888 const attribute_map = new Map();
24889 const handlers_map = new Map();
24890 attributes.forEach(attribute => (attribute_map.set(attribute.name, attribute)));
24891 handlers.forEach(handler => (handlers_map.set(handler.name, handler)));
24892 if (this.name === 'a') {
24893 const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
24894 const id_attribute = attribute_map.get('id');
24895 const name_attribute = attribute_map.get('name');
24896 if (href_attribute) {
24897 const href_value = href_attribute.get_static_value();
24898 if (href_value === '' || href_value === '#' || /^\W*javascript:/i.test(href_value)) {
24899 component.warn(href_attribute, {
24900 code: `a11y-invalid-attribute`,
24901 message: `A11y: '${href_value}' is not a valid ${href_attribute.name} attribute`
24902 });
24903 }
24904 }
24905 else {
24906 const id_attribute_valid = id_attribute && id_attribute.get_static_value() !== '';
24907 const name_attribute_valid = name_attribute && name_attribute.get_static_value() !== '';
24908 if (!id_attribute_valid && !name_attribute_valid) {
24909 component.warn(this, {
24910 code: `a11y-missing-attribute`,
24911 message: `A11y: <a> element should have an href attribute`
24912 });
24913 }
24914 }
24915 }
24916 else {
24917 const required_attributes = a11y_required_attributes[this.name];
24918 if (required_attributes) {
24919 const has_attribute = required_attributes.some(name => attribute_map.has(name));
24920 if (!has_attribute) {
24921 should_have_attribute(this, required_attributes);
24922 }
24923 }
24924 }
24925 if (this.name === 'input') {
24926 const type = attribute_map.get('type');
24927 if (type && type.get_static_value() === 'image') {
24928 const required_attributes = ['alt', 'aria-label', 'aria-labelledby'];
24929 const has_attribute = required_attributes.some(name => attribute_map.has(name));
24930 if (!has_attribute) {
24931 should_have_attribute(this, required_attributes, 'input type="image"');
24932 }
24933 }
24934 }
24935 if (this.name === 'img') {
24936 const alt_attribute = attribute_map.get('alt');
24937 const aria_hidden_attribute = attribute_map.get('aria-hidden');
24938 const aria_hidden_exist = aria_hidden_attribute && aria_hidden_attribute.get_static_value();
24939 if (alt_attribute && !aria_hidden_exist) {
24940 const alt_value = alt_attribute.get_static_value();
24941 if (/\b(image|picture|photo)\b/i.test(alt_value)) {
24942 component.warn(this, {
24943 code: `a11y-img-redundant-alt`,
24944 message: `A11y: Screenreaders already announce <img> elements as an image.`
24945 });
24946 }
24947 }
24948 }
24949 if (this.name === 'label') {
24950 const has_input_child = this.children.some(i => (i instanceof Element$1 && a11y_labelable.has(i.name)));
24951 if (!attribute_map.has('for') && !has_input_child) {
24952 component.warn(this, {
24953 code: `a11y-label-has-associated-control`,
24954 message: `A11y: A form label must be associated with a control.`
24955 });
24956 }
24957 }
24958 if (this.is_media_node()) {
24959 if (attribute_map.has('muted')) {
24960 return;
24961 }
24962 let has_caption;
24963 const track = this.children.find((i) => i.name === 'track');
24964 if (track) {
24965 has_caption = track.attributes.find(a => a.name === 'kind' && a.get_static_value() === 'captions');
24966 }
24967 if (!has_caption) {
24968 component.warn(this, {
24969 code: `a11y-media-has-caption`,
24970 message: `A11y: Media elements must have a <track kind="captions">`
24971 });
24972 }
24973 }
24974 if (a11y_no_onchange.has(this.name)) {
24975 if (handlers_map.has('change') && !handlers_map.has('blur')) {
24976 component.warn(this, {
24977 code: `a11y-no-onchange`,
24978 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.`
24979 });
24980 }
24981 }
24982 }
24983 validate_bindings() {
24984 const { component } = this;
24985 const check_type_attribute = () => {
24986 const attribute = this.attributes.find((attribute) => attribute.name === 'type');
24987 if (!attribute)
24988 return null;
24989 if (!attribute.is_static) {
24990 component.error(attribute, {
24991 code: `invalid-type`,
24992 message: `'type' attribute cannot be dynamic if input uses two-way binding`
24993 });
24994 }
24995 const value = attribute.get_static_value();
24996 if (value === true) {
24997 component.error(attribute, {
24998 code: `missing-type`,
24999 message: `'type' attribute must be specified`
25000 });
25001 }
25002 return value;
25003 };
25004 this.bindings.forEach(binding => {
25005 const { name } = binding;
25006 if (name === 'value') {
25007 if (this.name !== 'input' &&
25008 this.name !== 'textarea' &&
25009 this.name !== 'select') {
25010 component.error(binding, {
25011 code: `invalid-binding`,
25012 message: `'value' is not a valid binding on <${this.name}> elements`
25013 });
25014 }
25015 if (this.name === 'select') {
25016 const attribute = this.attributes.find((attribute) => attribute.name === 'multiple');
25017 if (attribute && !attribute.is_static) {
25018 component.error(attribute, {
25019 code: `dynamic-multiple-attribute`,
25020 message: `'multiple' attribute cannot be dynamic if select uses two-way binding`
25021 });
25022 }
25023 }
25024 else {
25025 check_type_attribute();
25026 }
25027 }
25028 else if (name === 'checked' || name === 'indeterminate') {
25029 if (this.name !== 'input') {
25030 component.error(binding, {
25031 code: `invalid-binding`,
25032 message: `'${name}' is not a valid binding on <${this.name}> elements`
25033 });
25034 }
25035 const type = check_type_attribute();
25036 if (type !== 'checkbox') {
25037 let message = `'${name}' binding can only be used with <input type="checkbox">`;
25038 if (type === 'radio')
25039 message += ` — for <input type="radio">, use 'group' binding`;
25040 component.error(binding, { code: `invalid-binding`, message });
25041 }
25042 }
25043 else if (name === 'group') {
25044 if (this.name !== 'input') {
25045 component.error(binding, {
25046 code: `invalid-binding`,
25047 message: `'group' is not a valid binding on <${this.name}> elements`
25048 });
25049 }
25050 const type = check_type_attribute();
25051 if (type !== 'checkbox' && type !== 'radio') {
25052 component.error(binding, {
25053 code: `invalid-binding`,
25054 message: `'group' binding can only be used with <input type="checkbox"> or <input type="radio">`
25055 });
25056 }
25057 }
25058 else if (name === 'files') {
25059 if (this.name !== 'input') {
25060 component.error(binding, {
25061 code: `invalid-binding`,
25062 message: `'files' is not a valid binding on <${this.name}> elements`
25063 });
25064 }
25065 const type = check_type_attribute();
25066 if (type !== 'file') {
25067 component.error(binding, {
25068 code: `invalid-binding`,
25069 message: `'files' binding can only be used with <input type="file">`
25070 });
25071 }
25072 }
25073 else if (name === 'open') {
25074 if (this.name !== 'details') {
25075 component.error(binding, {
25076 code: `invalid-binding`,
25077 message: `'${name}' binding can only be used with <details>`
25078 });
25079 }
25080 }
25081 else if (name === 'currentTime' ||
25082 name === 'duration' ||
25083 name === 'paused' ||
25084 name === 'buffered' ||
25085 name === 'seekable' ||
25086 name === 'played' ||
25087 name === 'volume' ||
25088 name === 'muted' ||
25089 name === 'playbackRate' ||
25090 name === 'seeking' ||
25091 name === 'ended') {
25092 if (this.name !== 'audio' && this.name !== 'video') {
25093 component.error(binding, {
25094 code: `invalid-binding`,
25095 message: `'${name}' binding can only be used with <audio> or <video>`
25096 });
25097 }
25098 }
25099 else if (name === 'videoHeight' ||
25100 name === 'videoWidth') {
25101 if (this.name !== 'video') {
25102 component.error(binding, {
25103 code: `invalid-binding`,
25104 message: `'${name}' binding can only be used with <video>`
25105 });
25106 }
25107 }
25108 else if (dimensions.test(name)) {
25109 if (this.name === 'svg' && (name === 'offsetWidth' || name === 'offsetHeight')) {
25110 component.error(binding, {
25111 code: 'invalid-binding',
25112 message: `'${binding.name}' is not a valid binding on <svg>. Use '${name.replace('offset', 'client')}' instead`
25113 });
25114 }
25115 else if (svg$1.test(this.name)) {
25116 component.error(binding, {
25117 code: 'invalid-binding',
25118 message: `'${binding.name}' is not a valid binding on SVG elements`
25119 });
25120 }
25121 else if (is_void(this.name)) {
25122 component.error(binding, {
25123 code: 'invalid-binding',
25124 message: `'${binding.name}' is not a valid binding on void elements like <${this.name}>. Use a wrapper element instead`
25125 });
25126 }
25127 }
25128 else if (name === 'textContent' ||
25129 name === 'innerHTML') {
25130 const contenteditable = this.attributes.find((attribute) => attribute.name === 'contenteditable');
25131 if (!contenteditable) {
25132 component.error(binding, {
25133 code: `missing-contenteditable-attribute`,
25134 message: `'contenteditable' attribute is required for textContent and innerHTML two-way bindings`
25135 });
25136 }
25137 else if (contenteditable && !contenteditable.is_static) {
25138 component.error(contenteditable, {
25139 code: `dynamic-contenteditable-attribute`,
25140 message: `'contenteditable' attribute cannot be dynamic if element uses two-way binding`
25141 });
25142 }
25143 }
25144 else if (name !== 'this') {
25145 component.error(binding, {
25146 code: `invalid-binding`,
25147 message: `'${binding.name}' is not a valid binding`
25148 });
25149 }
25150 });
25151 }
25152 validate_content() {
25153 if (!a11y_required_content.has(this.name))
25154 return;
25155 if (this.bindings
25156 .some((binding) => ['textContent', 'innerHTML'].includes(binding.name)))
25157 return;
25158 if (this.children.length === 0) {
25159 this.component.warn(this, {
25160 code: `a11y-missing-content`,
25161 message: `A11y: <${this.name}> element should have child content`
25162 });
25163 }
25164 }
25165 validate_event_handlers() {
25166 const { component } = this;
25167 this.handlers.forEach(handler => {
25168 if (handler.modifiers.has('passive') && handler.modifiers.has('preventDefault')) {
25169 component.error(handler, {
25170 code: 'invalid-event-modifier',
25171 message: `The 'passive' and 'preventDefault' modifiers cannot be used together`
25172 });
25173 }
25174 handler.modifiers.forEach(modifier => {
25175 if (!valid_modifiers.has(modifier)) {
25176 component.error(handler, {
25177 code: 'invalid-event-modifier',
25178 message: `Valid event modifiers are ${list$1(Array.from(valid_modifiers))}`
25179 });
25180 }
25181 if (modifier === 'passive') {
25182 if (passive_events.has(handler.name)) {
25183 if (handler.can_make_passive) {
25184 component.warn(handler, {
25185 code: 'redundant-event-modifier',
25186 message: `Touch event handlers that don't use the 'event' object are passive by default`
25187 });
25188 }
25189 }
25190 else {
25191 component.warn(handler, {
25192 code: 'redundant-event-modifier',
25193 message: `The passive modifier only works with wheel and touch events`
25194 });
25195 }
25196 }
25197 if (component.compile_options.legacy && (modifier === 'once' || modifier === 'passive')) {
25198 // TODO this could be supported, but it would need a few changes to
25199 // how event listeners work
25200 component.error(handler, {
25201 code: 'invalid-event-modifier',
25202 message: `The '${modifier}' modifier cannot be used in legacy mode`
25203 });
25204 }
25205 });
25206 if (passive_events.has(handler.name) && handler.can_make_passive && !handler.modifiers.has('preventDefault')) {
25207 // touch/wheel events should be passive by default
25208 handler.modifiers.add('passive');
25209 }
25210 });
25211 }
25212 is_media_node() {
25213 return this.name === 'audio' || this.name === 'video';
25214 }
25215 add_css_class() {
25216 if (this.attributes.some(attr => attr.is_spread)) {
25217 this.needs_manual_style_scoping = true;
25218 return;
25219 }
25220 const { id } = this.component.stylesheet;
25221 const class_attribute = this.attributes.find(a => a.name === 'class');
25222 if (class_attribute && !class_attribute.is_true) {
25223 if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') {
25224 class_attribute.chunks[0].data += ` ${id}`;
25225 }
25226 else {
25227 class_attribute.chunks.push(new Text$1(this.component, this, this.scope, {
25228 type: 'Text',
25229 data: ` ${id}`,
25230 synthetic: true
25231 }));
25232 }
25233 }
25234 else {
25235 this.attributes.push(new Attribute(this.component, this, this.scope, {
25236 type: 'Attribute',
25237 name: 'class',
25238 value: [{ type: 'Text', data: id, synthetic: true }]
25239 }));
25240 }
25241 }
25242 }
25243 function should_have_attribute(node, attributes, name = node.name) {
25244 const article = /^[aeiou]/.test(attributes[0]) ? 'an' : 'a';
25245 const sequence = attributes.length > 1 ?
25246 attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}` :
25247 attributes[0];
25248 node.component.warn(node, {
25249 code: `a11y-missing-attribute`,
25250 message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
25251 });
25252 }
25253 function within_custom_element(parent) {
25254 while (parent) {
25255 if (parent.type === 'InlineComponent')
25256 return false;
25257 if (parent.type === 'Element' && /-/.test(parent.name))
25258 return true;
25259 parent = parent.parent;
25260 }
25261 return false;
25262 }
25263
25264 class Head$1 extends Node$1 {
25265 constructor(component, parent, scope, info) {
25266 super(component, parent, scope, info);
25267 if (info.attributes.length) {
25268 component.error(info.attributes[0], {
25269 code: `invalid-attribute`,
25270 message: `<svelte:head> should not have any attributes or directives`
25271 });
25272 }
25273 this.children = map_children(component, parent, scope, info.children.filter(child => {
25274 return (child.type !== 'Text' || /\S/.test(child.data));
25275 }));
25276 if (this.children.length > 0) {
25277 this.id = `svelte-${hash(this.component.source.slice(this.start, this.end))}`;
25278 }
25279 }
25280 }
25281
25282 class IfBlock$1 extends AbstractBlock {
25283 constructor(component, parent, scope, info) {
25284 super(component, parent, scope, info);
25285 this.expression = new Expression(component, this, scope, info.expression);
25286 this.children = map_children(component, this, scope, info.children);
25287 this.else = info.else
25288 ? new ElseBlock(component, this, scope, info.else)
25289 : null;
25290 this.warn_if_empty_block();
25291 }
25292 }
25293
25294 class InlineComponent$1 extends Node$1 {
25295 constructor(component, parent, scope, info) {
25296 super(component, parent, scope, info);
25297 this.attributes = [];
25298 this.bindings = [];
25299 this.handlers = [];
25300 this.lets = [];
25301 if (info.name !== 'svelte:component' && info.name !== 'svelte:self') {
25302 const name = info.name.split('.')[0]; // accommodate namespaces
25303 component.warn_if_undefined(name, info, scope);
25304 component.add_reference(name);
25305 }
25306 this.name = info.name;
25307 this.expression = this.name === 'svelte:component'
25308 ? new Expression(component, this, scope, info.expression)
25309 : null;
25310 info.attributes.forEach(node => {
25311 /* eslint-disable no-fallthrough */
25312 switch (node.type) {
25313 case 'Action':
25314 component.error(node, {
25315 code: `invalid-action`,
25316 message: `Actions can only be applied to DOM elements, not components`
25317 });
25318 case 'Attribute':
25319 if (node.name === 'slot') {
25320 component.error(node, {
25321 code: `invalid-prop`,
25322 message: `'slot' is reserved for future use in named slots`
25323 });
25324 }
25325 // fallthrough
25326 case 'Spread':
25327 this.attributes.push(new Attribute(component, this, scope, node));
25328 break;
25329 case 'Binding':
25330 this.bindings.push(new Binding(component, this, scope, node));
25331 break;
25332 case 'Class':
25333 component.error(node, {
25334 code: `invalid-class`,
25335 message: `Classes can only be applied to DOM elements, not components`
25336 });
25337 case 'EventHandler':
25338 this.handlers.push(new EventHandler(component, this, scope, node));
25339 break;
25340 case 'Let':
25341 this.lets.push(new Let(component, this, scope, node));
25342 break;
25343 case 'Transition':
25344 component.error(node, {
25345 code: `invalid-transition`,
25346 message: `Transitions can only be applied to DOM elements, not components`
25347 });
25348 default:
25349 throw new Error(`Not implemented: ${node.type}`);
25350 }
25351 /* eslint-enable no-fallthrough */
25352 });
25353 if (this.lets.length > 0) {
25354 this.scope = scope.child();
25355 this.lets.forEach(l => {
25356 const dependencies = new Set([l.name.name]);
25357 l.names.forEach(name => {
25358 this.scope.add(name, dependencies, this);
25359 });
25360 });
25361 }
25362 else {
25363 this.scope = scope;
25364 }
25365 this.handlers.forEach(handler => {
25366 handler.modifiers.forEach(modifier => {
25367 if (modifier !== 'once') {
25368 component.error(handler, {
25369 code: 'invalid-event-modifier',
25370 message: `Event modifiers other than 'once' can only be used on DOM elements`
25371 });
25372 }
25373 });
25374 });
25375 this.children = map_children(component, this, this.scope, info.children);
25376 }
25377 }
25378
25379 class Tag$2 extends Node$1 {
25380 constructor(component, parent, scope, info) {
25381 super(component, parent, scope, info);
25382 this.expression = new Expression(component, this, scope, info.expression);
25383 this.should_cache = (info.expression.type !== 'Identifier' ||
25384 (this.expression.dependencies.size && scope.names.has(info.expression.name)));
25385 }
25386 }
25387
25388 class MustacheTag extends Tag$2 {
25389 }
25390
25391 class Options extends Node$1 {
25392 }
25393
25394 class RawMustacheTag extends Tag$2 {
25395 }
25396
25397 class DebugTag$1 extends Node$1 {
25398 constructor(component, parent, scope, info) {
25399 super(component, parent, scope, info);
25400 this.expressions = info.identifiers.map(node => {
25401 return new Expression(component, parent, scope, node);
25402 });
25403 }
25404 }
25405
25406 class Slot$1 extends Element$1 {
25407 constructor(component, parent, scope, info) {
25408 super(component, parent, scope, info);
25409 this.values = new Map();
25410 info.attributes.forEach(attr => {
25411 if (attr.type !== 'Attribute') {
25412 component.error(attr, {
25413 code: `invalid-slot-directive`,
25414 message: `<slot> cannot have directives`
25415 });
25416 }
25417 if (attr.name === 'name') {
25418 if (attr.value.length !== 1 || attr.value[0].type !== 'Text') {
25419 component.error(attr, {
25420 code: `dynamic-slot-name`,
25421 message: `<slot> name cannot be dynamic`
25422 });
25423 }
25424 this.slot_name = attr.value[0].data;
25425 if (this.slot_name === 'default') {
25426 component.error(attr, {
25427 code: `invalid-slot-name`,
25428 message: `default is a reserved word — it cannot be used as a slot name`
25429 });
25430 }
25431 }
25432 this.values.set(attr.name, new Attribute(component, this, scope, attr));
25433 });
25434 if (!this.slot_name)
25435 this.slot_name = 'default';
25436 if (this.slot_name === 'default') {
25437 // if this is the default slot, add our dependencies to any
25438 // other slots (which inherit our slot values) that were
25439 // previously encountered
25440 component.slots.forEach((slot) => {
25441 this.values.forEach((attribute, name) => {
25442 if (!slot.values.has(name)) {
25443 slot.values.set(name, attribute);
25444 }
25445 });
25446 });
25447 }
25448 else if (component.slots.has('default')) {
25449 // otherwise, go the other way — inherit values from
25450 // a previously encountered default slot
25451 const default_slot = component.slots.get('default');
25452 default_slot.values.forEach((attribute, name) => {
25453 if (!this.values.has(name)) {
25454 this.values.set(name, attribute);
25455 }
25456 });
25457 }
25458 component.slots.set(this.slot_name, this);
25459 }
25460 }
25461
25462 class Title$1 extends Node$1 {
25463 constructor(component, parent, scope, info) {
25464 super(component, parent, scope, info);
25465 this.children = map_children(component, parent, scope, info.children);
25466 if (info.attributes.length > 0) {
25467 component.error(info.attributes[0], {
25468 code: `illegal-attribute`,
25469 message: `<title> cannot have attributes`
25470 });
25471 }
25472 info.children.forEach(child => {
25473 if (child.type !== 'Text' && child.type !== 'MustacheTag') {
25474 component.error(child, {
25475 code: 'illegal-structure',
25476 message: `<title> can only contain text and {tags}`
25477 });
25478 }
25479 });
25480 this.should_cache = info.children.length === 1
25481 ? (info.children[0].type !== 'Identifier' ||
25482 scope.names.has(info.children[0].name))
25483 : true;
25484 }
25485 }
25486
25487 const valid_bindings = [
25488 'innerWidth',
25489 'innerHeight',
25490 'outerWidth',
25491 'outerHeight',
25492 'scrollX',
25493 'scrollY',
25494 'online'
25495 ];
25496 class Window extends Node$1 {
25497 constructor(component, parent, scope, info) {
25498 super(component, parent, scope, info);
25499 this.handlers = [];
25500 this.bindings = [];
25501 this.actions = [];
25502 info.attributes.forEach(node => {
25503 if (node.type === 'EventHandler') {
25504 this.handlers.push(new EventHandler(component, this, scope, node));
25505 }
25506 else if (node.type === 'Binding') {
25507 if (node.expression.type !== 'Identifier') {
25508 const { parts } = flatten_reference(node.expression);
25509 // TODO is this constraint necessary?
25510 component.error(node.expression, {
25511 code: `invalid-binding`,
25512 message: `Bindings on <svelte:window> must be to top-level properties, e.g. '${parts[parts.length - 1]}' rather than '${parts.join('.')}'`
25513 });
25514 }
25515 if (!~valid_bindings.indexOf(node.name)) {
25516 const match = (node.name === 'width' ? 'innerWidth' :
25517 node.name === 'height' ? 'innerHeight' :
25518 fuzzymatch(node.name, valid_bindings));
25519 const message = `'${node.name}' is not a valid binding on <svelte:window>`;
25520 if (match) {
25521 component.error(node, {
25522 code: `invalid-binding`,
25523 message: `${message} (did you mean '${match}'?)`
25524 });
25525 }
25526 else {
25527 component.error(node, {
25528 code: `invalid-binding`,
25529 message: `${message} — valid bindings are ${list$1(valid_bindings)}`
25530 });
25531 }
25532 }
25533 this.bindings.push(new Binding(component, this, scope, node));
25534 }
25535 else if (node.type === 'Action') {
25536 this.actions.push(new Action(component, this, scope, node));
25537 }
25538 });
25539 }
25540 }
25541
25542 function get_constructor(type) {
25543 switch (type) {
25544 case 'AwaitBlock': return AwaitBlock$1;
25545 case 'Body': return Body;
25546 case 'Comment': return Comment$2;
25547 case 'EachBlock': return EachBlock$1;
25548 case 'Element': return Element$1;
25549 case 'Head': return Head$1;
25550 case 'IfBlock': return IfBlock$1;
25551 case 'InlineComponent': return InlineComponent$1;
25552 case 'MustacheTag': return MustacheTag;
25553 case 'Options': return Options;
25554 case 'RawMustacheTag': return RawMustacheTag;
25555 case 'DebugTag': return DebugTag$1;
25556 case 'Slot': return Slot$1;
25557 case 'Text': return Text$1;
25558 case 'Title': return Title$1;
25559 case 'Window': return Window;
25560 default: throw new Error(`Not implemented: ${type}`);
25561 }
25562 }
25563 function map_children(component, parent, scope, children) {
25564 let last = null;
25565 let ignores = [];
25566 return children.map(child => {
25567 const constructor = get_constructor(child.type);
25568 const use_ignores = child.type !== 'Text' && child.type !== 'Comment' && ignores.length;
25569 if (use_ignores)
25570 component.push_ignores(ignores);
25571 const node = new constructor(component, parent, scope, child);
25572 if (use_ignores)
25573 component.pop_ignores(), ignores = [];
25574 if (node.type === 'Comment' && node.ignores.length) {
25575 ignores.push(...node.ignores);
25576 }
25577 if (last)
25578 last.next = node;
25579 node.prev = last;
25580 last = node;
25581 return node;
25582 });
25583 }
25584
25585 class TemplateScope {
25586 constructor(parent) {
25587 this.owners = new Map();
25588 this.parent = parent;
25589 this.names = new Set(parent ? parent.names : []);
25590 this.dependencies_for_name = new Map(parent ? parent.dependencies_for_name : []);
25591 }
25592 add(name, dependencies, owner) {
25593 this.names.add(name);
25594 this.dependencies_for_name.set(name, dependencies);
25595 this.owners.set(name, owner);
25596 return this;
25597 }
25598 child() {
25599 const child = new TemplateScope(this);
25600 return child;
25601 }
25602 is_top_level(name) {
25603 return !this.parent || !this.names.has(name) && this.parent.is_top_level(name);
25604 }
25605 get_owner(name) {
25606 return this.owners.get(name) || (this.parent && this.parent.get_owner(name));
25607 }
25608 is_let(name) {
25609 const owner = this.get_owner(name);
25610 return owner && (owner.type === 'Element' || owner.type === 'InlineComponent');
25611 }
25612 is_await(name) {
25613 const owner = this.get_owner(name);
25614 return owner && (owner.type === 'ThenBlock' || owner.type === 'CatchBlock');
25615 }
25616 }
25617
25618 class Fragment extends Node$1 {
25619 constructor(component, info) {
25620 const scope = new TemplateScope();
25621 super(component, null, scope, info);
25622 this.scope = scope;
25623 this.children = map_children(component, this, scope, info.children);
25624 }
25625 }
25626
25627 // This file is automatically generated
25628 var internal_exports = new Set(["HtmlTag", "SvelteComponent", "SvelteComponentDev", "SvelteElement", "action_destroyer", "add_attribute", "add_classes", "add_flush_callback", "add_location", "add_render_callback", "add_resize_listener", "add_transform", "afterUpdate", "append", "append_dev", "assign", "attr", "attr_dev", "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", "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_slot_changes", "get_slot_context", "get_spread_object", "get_spread_update", "get_store_value", "globals", "group_outros", "handle_promise", "has_prop", "identity", "init", "insert", "insert_dev", "intros", "invalid_attribute_name_character", "is_client", "is_crossorigin", "is_empty", "is_function", "is_promise", "listen", "listen_dev", "loop", "loop_guard", "missing_component", "mount_component", "noop", "not_equal", "now", "null_to_empty", "object_without_properties", "onDestroy", "onMount", "once", "outro_and_destroy_block", "prevent_default", "prop_dev", "query_selector_all", "raf", "run", "run_all", "safe_not_equal", "schedule_update", "select_multiple_value", "select_option", "select_options", "select_value", "self", "setContext", "set_attributes", "set_current_component", "set_custom_element_data", "set_data", "set_data_dev", "set_input_type", "set_input_value", "set_now", "set_raf", "set_store_value", "set_style", "set_svg_attributes", "space", "spread", "stop_propagation", "subscribe", "svg_element", "text", "tick", "time_ranges_to_array", "to_number", "toggle_class", "transition_in", "transition_out", "update_keyed_each", "update_slot", "validate_component", "validate_each_argument", "validate_each_keys", "validate_slots", "validate_store", "xlink_attr"]);
25629
25630 function is_used_as_reference(node, parent) {
25631 if (!isReference(node, parent)) {
25632 return false;
25633 }
25634 if (!parent) {
25635 return true;
25636 }
25637 /* eslint-disable no-fallthrough */
25638 switch (parent.type) {
25639 // disregard the `foo` in `const foo = bar`
25640 case 'VariableDeclarator':
25641 return node !== parent.id;
25642 // disregard the `foo`, `bar` in `function foo(bar){}`
25643 case 'FunctionDeclaration':
25644 // disregard the `foo` in `import { foo } from 'foo'`
25645 case 'ImportSpecifier':
25646 // disregard the `foo` in `import foo from 'foo'`
25647 case 'ImportDefaultSpecifier':
25648 // disregard the `foo` in `import * as foo from 'foo'`
25649 case 'ImportNamespaceSpecifier':
25650 // disregard the `foo` in `export { foo }`
25651 case 'ExportSpecifier':
25652 return false;
25653 default:
25654 return true;
25655 }
25656 }
25657
25658 function check_graph_for_cycles(edges) {
25659 const graph = edges.reduce((g, edge) => {
25660 const [u, v] = edge;
25661 if (!g.has(u))
25662 g.set(u, []);
25663 if (!g.has(v))
25664 g.set(v, []);
25665 g.get(u).push(v);
25666 return g;
25667 }, new Map());
25668 const visited = new Set();
25669 const on_stack = new Set();
25670 const cycles = [];
25671 function visit(v) {
25672 visited.add(v);
25673 on_stack.add(v);
25674 graph.get(v).forEach(w => {
25675 if (!visited.has(w)) {
25676 visit(w);
25677 }
25678 else if (on_stack.has(w)) {
25679 cycles.push([...on_stack, w]);
25680 }
25681 });
25682 on_stack.delete(v);
25683 }
25684 graph.forEach((_, v) => {
25685 if (!visited.has(v)) {
25686 visit(v);
25687 }
25688 });
25689 return cycles[0];
25690 }
25691
25692 class Component {
25693 constructor(ast, source, name, compile_options, stats, warnings) {
25694 this.ignore_stack = [];
25695 this.vars = [];
25696 this.var_lookup = new Map();
25697 this.imports = [];
25698 this.hoistable_nodes = new Set();
25699 this.node_for_declaration = new Map();
25700 this.partly_hoisted = [];
25701 this.fully_hoisted = [];
25702 this.reactive_declarations = [];
25703 this.reactive_declaration_nodes = new Set();
25704 this.has_reactive_assignments = false;
25705 this.injected_reactive_declaration_vars = new Set();
25706 this.helpers = new Map();
25707 this.globals = new Map();
25708 this.indirect_dependencies = new Map();
25709 this.aliases = new Map();
25710 this.used_names = new Set();
25711 this.globally_used_names = new Set();
25712 this.slots = new Map();
25713 this.slot_outlets = new Set();
25714 this.name = { type: 'Identifier', name };
25715 this.stats = stats;
25716 this.warnings = warnings;
25717 this.ast = ast;
25718 this.source = source;
25719 this.compile_options = compile_options;
25720 // the instance JS gets mutated, so we park
25721 // a copy here for later. TODO this feels gross
25722 this.original_ast = {
25723 html: ast.html,
25724 css: ast.css,
25725 instance: ast.instance && JSON.parse(JSON.stringify(ast.instance)),
25726 module: ast.module
25727 };
25728 this.file =
25729 compile_options.filename &&
25730 (typeof process !== 'undefined'
25731 ? compile_options.filename
25732 .replace(process.cwd(), '')
25733 .replace(/^[/\\]/, '')
25734 : compile_options.filename);
25735 this.locate = getLocator(this.source, { offsetLine: 1 });
25736 // styles
25737 this.stylesheet = new Stylesheet(source, ast, compile_options.filename, compile_options.dev);
25738 this.stylesheet.validate(this);
25739 this.component_options = process_component_options(this, this.ast.html.children);
25740 this.namespace =
25741 namespaces[this.component_options.namespace] ||
25742 this.component_options.namespace;
25743 if (compile_options.customElement) {
25744 if (this.component_options.tag === undefined &&
25745 compile_options.tag === undefined) {
25746 const svelteOptions = ast.html.children.find(child => child.name === 'svelte:options') || { start: 0, end: 0 };
25747 this.warn(svelteOptions, {
25748 code: 'custom-element-no-tag',
25749 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}/>`,
25750 });
25751 }
25752 this.tag = this.component_options.tag || compile_options.tag;
25753 }
25754 else {
25755 this.tag = this.name.name;
25756 }
25757 this.walk_module_js();
25758 this.walk_instance_js_pre_template();
25759 this.fragment = new Fragment(this, ast.html);
25760 this.name = this.get_unique_name(name);
25761 this.walk_instance_js_post_template();
25762 if (!compile_options.customElement)
25763 this.stylesheet.reify();
25764 this.stylesheet.warn_on_unused_selectors(this);
25765 }
25766 add_var(variable) {
25767 this.vars.push(variable);
25768 this.var_lookup.set(variable.name, variable);
25769 }
25770 add_reference(name) {
25771 const variable = this.var_lookup.get(name);
25772 if (variable) {
25773 variable.referenced = true;
25774 }
25775 else if (is_reserved_keyword(name)) {
25776 this.add_var({
25777 name,
25778 injected: true,
25779 referenced: true,
25780 });
25781 }
25782 else if (name[0] === '$') {
25783 this.add_var({
25784 name,
25785 injected: true,
25786 referenced: true,
25787 mutated: true,
25788 writable: true,
25789 });
25790 const subscribable_name = name.slice(1);
25791 const variable = this.var_lookup.get(subscribable_name);
25792 if (variable) {
25793 variable.referenced = true;
25794 variable.subscribable = true;
25795 }
25796 }
25797 else {
25798 this.used_names.add(name);
25799 }
25800 }
25801 alias(name) {
25802 if (!this.aliases.has(name)) {
25803 this.aliases.set(name, this.get_unique_name(name));
25804 }
25805 return this.aliases.get(name);
25806 }
25807 global(name) {
25808 const alias = this.alias(name);
25809 this.globals.set(name, alias);
25810 return alias;
25811 }
25812 generate(result) {
25813 let js = null;
25814 let css = null;
25815 if (result) {
25816 const { compile_options, name } = this;
25817 const { format = 'esm' } = compile_options;
25818 const banner = `${this.file ? `${this.file} ` : ``}generated by Svelte v${'3.24.1'}`;
25819 const program = { type: 'Program', body: result.js };
25820 walk(program, {
25821 enter: (node, parent, key) => {
25822 if (node.type === 'Identifier') {
25823 if (node.name[0] === '@') {
25824 if (node.name[1] === '_') {
25825 const alias = this.global(node.name.slice(2));
25826 node.name = alias.name;
25827 }
25828 else {
25829 let name = node.name.slice(1);
25830 if (compile_options.dev) {
25831 if (internal_exports.has(`${name}_dev`)) {
25832 name += '_dev';
25833 }
25834 else if (internal_exports.has(`${name}Dev`)) {
25835 name += 'Dev';
25836 }
25837 }
25838 const alias = this.alias(name);
25839 this.helpers.set(name, alias);
25840 node.name = alias.name;
25841 }
25842 }
25843 else if (node.name[0] !== '#' && !is_valid(node.name)) {
25844 // this hack allows x`foo.${bar}` where bar could be invalid
25845 const literal = { type: 'Literal', value: node.name };
25846 if (parent.type === 'Property' && key === 'key') {
25847 parent.key = literal;
25848 }
25849 else if (parent.type === 'MemberExpression' && key === 'property') {
25850 parent.property = literal;
25851 parent.computed = true;
25852 }
25853 }
25854 }
25855 }
25856 });
25857 const referenced_globals = Array.from(this.globals, ([name, alias]) => name !== alias.name && { name, alias }).filter(Boolean);
25858 if (referenced_globals.length) {
25859 this.helpers.set('globals', this.alias('globals'));
25860 }
25861 const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({
25862 name,
25863 alias,
25864 }));
25865 create_module(program, format, name, banner, compile_options.sveltePath, imported_helpers, referenced_globals, this.imports, this.vars
25866 .filter(variable => variable.module && variable.export_name)
25867 .map(variable => ({
25868 name: variable.name,
25869 as: variable.export_name,
25870 })));
25871 css = compile_options.customElement
25872 ? { code: null, map: null }
25873 : result.css;
25874 js = print(program, {
25875 sourceMapSource: compile_options.filename
25876 });
25877 js.map.sources = [
25878 compile_options.filename ? get_relative_path(compile_options.outputFilename || '', compile_options.filename) : null
25879 ];
25880 js.map.sourcesContent = [
25881 this.source
25882 ];
25883 }
25884 return {
25885 js,
25886 css,
25887 ast: this.original_ast,
25888 warnings: this.warnings,
25889 vars: this.vars
25890 .filter(v => !v.global && !v.internal)
25891 .map(v => ({
25892 name: v.name,
25893 export_name: v.export_name || null,
25894 injected: v.injected || false,
25895 module: v.module || false,
25896 mutated: v.mutated || false,
25897 reassigned: v.reassigned || false,
25898 referenced: v.referenced || false,
25899 writable: v.writable || false,
25900 referenced_from_script: v.referenced_from_script || false,
25901 })),
25902 stats: this.stats.render(),
25903 };
25904 }
25905 get_unique_name(name, scope) {
25906 if (test)
25907 name = `${name}$`;
25908 let alias = name;
25909 for (let i = 1; reserved.has(alias) ||
25910 this.var_lookup.has(alias) ||
25911 this.used_names.has(alias) ||
25912 this.globally_used_names.has(alias) ||
25913 (scope && scope.has(alias)); alias = `${name}_${i++}`)
25914 ;
25915 this.used_names.add(alias);
25916 return { type: 'Identifier', name: alias };
25917 }
25918 get_unique_name_maker() {
25919 const local_used_names = new Set();
25920 function add(name) {
25921 local_used_names.add(name);
25922 }
25923 reserved.forEach(add);
25924 internal_exports.forEach(add);
25925 this.var_lookup.forEach((_value, key) => add(key));
25926 return (name) => {
25927 if (test)
25928 name = `${name}$`;
25929 let alias = name;
25930 for (let i = 1; this.used_names.has(alias) || local_used_names.has(alias); alias = `${name}_${i++}`)
25931 ;
25932 local_used_names.add(alias);
25933 this.globally_used_names.add(alias);
25934 return {
25935 type: 'Identifier',
25936 name: alias
25937 };
25938 };
25939 }
25940 error(pos, e) {
25941 error$1(e.message, {
25942 name: 'ValidationError',
25943 code: e.code,
25944 source: this.source,
25945 start: pos.start,
25946 end: pos.end,
25947 filename: this.compile_options.filename,
25948 });
25949 }
25950 warn(pos, warning) {
25951 if (this.ignores && this.ignores.has(warning.code)) {
25952 return;
25953 }
25954 const start = this.locate(pos.start);
25955 const end = this.locate(pos.end);
25956 const frame = get_code_frame(this.source, start.line - 1, start.column);
25957 this.warnings.push({
25958 code: warning.code,
25959 message: warning.message,
25960 frame,
25961 start,
25962 end,
25963 pos: pos.start,
25964 filename: this.compile_options.filename,
25965 toString: () => `${warning.message} (${start.line}:${start.column})\n${frame}`,
25966 });
25967 }
25968 extract_imports(node) {
25969 this.imports.push(node);
25970 }
25971 extract_exports(node) {
25972 if (node.type === 'ExportDefaultDeclaration') {
25973 this.error(node, {
25974 code: `default-export`,
25975 message: `A component cannot have a default export`,
25976 });
25977 }
25978 if (node.type === 'ExportNamedDeclaration') {
25979 if (node.source) {
25980 this.error(node, {
25981 code: `not-implemented`,
25982 message: `A component currently cannot have an export ... from`,
25983 });
25984 }
25985 if (node.declaration) {
25986 if (node.declaration.type === 'VariableDeclaration') {
25987 node.declaration.declarations.forEach(declarator => {
25988 extract_names(declarator.id).forEach(name => {
25989 const variable = this.var_lookup.get(name);
25990 variable.export_name = name;
25991 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
25992 this.warn(declarator, {
25993 code: `unused-export-let`,
25994 message: `${this.name.name} has unused export property '${name}'. If it is for external reference only, please consider using \`export const ${name}\``
25995 });
25996 }
25997 });
25998 });
25999 }
26000 else {
26001 const { name } = node.declaration.id;
26002 const variable = this.var_lookup.get(name);
26003 variable.export_name = name;
26004 }
26005 return node.declaration;
26006 }
26007 else {
26008 node.specifiers.forEach(specifier => {
26009 const variable = this.var_lookup.get(specifier.local.name);
26010 if (variable) {
26011 variable.export_name = specifier.exported.name;
26012 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
26013 this.warn(specifier, {
26014 code: `unused-export-let`,
26015 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}\``
26016 });
26017 }
26018 }
26019 });
26020 return null;
26021 }
26022 }
26023 }
26024 extract_javascript(script) {
26025 if (!script)
26026 return null;
26027 return script.content.body.filter(node => {
26028 if (!node)
26029 return false;
26030 if (this.hoistable_nodes.has(node))
26031 return false;
26032 if (this.reactive_declaration_nodes.has(node))
26033 return false;
26034 if (node.type === 'ImportDeclaration')
26035 return false;
26036 if (node.type === 'ExportDeclaration' && node.specifiers.length > 0)
26037 return false;
26038 return true;
26039 });
26040 }
26041 walk_module_js() {
26042 const component = this;
26043 const script = this.ast.module;
26044 if (!script)
26045 return;
26046 walk(script.content, {
26047 enter(node) {
26048 if (node.type === 'LabeledStatement' && node.label.name === '$') {
26049 component.warn(node, {
26050 code: 'module-script-reactive-declaration',
26051 message: '$: has no effect in a module script',
26052 });
26053 }
26054 },
26055 });
26056 const { scope, globals } = create_scopes(script.content);
26057 this.module_scope = scope;
26058 scope.declarations.forEach((node, name) => {
26059 if (name[0] === '$') {
26060 this.error(node, {
26061 code: 'illegal-declaration',
26062 message: `The $ prefix is reserved, and cannot be used for variable and import names`,
26063 });
26064 }
26065 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
26066 this.add_var({
26067 name,
26068 module: true,
26069 hoistable: true,
26070 writable
26071 });
26072 });
26073 globals.forEach((node, name) => {
26074 if (name[0] === '$') {
26075 this.error(node, {
26076 code: 'illegal-subscription',
26077 message: `Cannot reference store value inside <script context="module">`,
26078 });
26079 }
26080 else {
26081 this.add_var({
26082 name,
26083 global: true,
26084 hoistable: true
26085 });
26086 }
26087 });
26088 const { body } = script.content;
26089 let i = body.length;
26090 while (--i >= 0) {
26091 const node = body[i];
26092 if (node.type === 'ImportDeclaration') {
26093 this.extract_imports(node);
26094 body.splice(i, 1);
26095 }
26096 if (/^Export/.test(node.type)) {
26097 const replacement = this.extract_exports(node);
26098 if (replacement) {
26099 body[i] = replacement;
26100 }
26101 else {
26102 body.splice(i, 1);
26103 }
26104 }
26105 }
26106 }
26107 walk_instance_js_pre_template() {
26108 const script = this.ast.instance;
26109 if (!script)
26110 return;
26111 // inject vars for reactive declarations
26112 script.content.body.forEach(node => {
26113 if (node.type !== 'LabeledStatement')
26114 return;
26115 if (node.body.type !== 'ExpressionStatement')
26116 return;
26117 const { expression } = node.body;
26118 if (expression.type !== 'AssignmentExpression')
26119 return;
26120 if (expression.left.type === 'MemberExpression')
26121 return;
26122 extract_names(expression.left).forEach(name => {
26123 if (!this.var_lookup.has(name) && name[0] !== '$') {
26124 this.injected_reactive_declaration_vars.add(name);
26125 }
26126 });
26127 });
26128 const { scope: instance_scope, map, globals } = create_scopes(script.content);
26129 this.instance_scope = instance_scope;
26130 this.instance_scope_map = map;
26131 instance_scope.declarations.forEach((node, name) => {
26132 if (name[0] === '$') {
26133 this.error(node, {
26134 code: 'illegal-declaration',
26135 message: `The $ prefix is reserved, and cannot be used for variable and import names`,
26136 });
26137 }
26138 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
26139 this.add_var({
26140 name,
26141 initialised: instance_scope.initialised_declarations.has(name),
26142 writable
26143 });
26144 this.node_for_declaration.set(name, node);
26145 });
26146 globals.forEach((node, name) => {
26147 if (this.var_lookup.has(name))
26148 return;
26149 if (this.injected_reactive_declaration_vars.has(name)) {
26150 this.add_var({
26151 name,
26152 injected: true,
26153 writable: true,
26154 reassigned: true,
26155 initialised: true,
26156 });
26157 }
26158 else if (is_reserved_keyword(name)) {
26159 this.add_var({
26160 name,
26161 injected: true,
26162 });
26163 }
26164 else if (name[0] === '$') {
26165 if (name === '$' || name[1] === '$') {
26166 this.error(node, {
26167 code: 'illegal-global',
26168 message: `${name} is an illegal variable name`
26169 });
26170 }
26171 this.add_var({
26172 name,
26173 injected: true,
26174 mutated: true,
26175 writable: true,
26176 });
26177 this.add_reference(name.slice(1));
26178 const variable = this.var_lookup.get(name.slice(1));
26179 if (variable) {
26180 variable.subscribable = true;
26181 variable.referenced_from_script = true;
26182 }
26183 }
26184 else {
26185 this.add_var({
26186 name,
26187 global: true,
26188 hoistable: true
26189 });
26190 }
26191 });
26192 this.track_references_and_mutations();
26193 }
26194 walk_instance_js_post_template() {
26195 const script = this.ast.instance;
26196 if (!script)
26197 return;
26198 this.post_template_walk();
26199 this.hoist_instance_declarations();
26200 this.extract_reactive_declarations();
26201 }
26202 post_template_walk() {
26203 const script = this.ast.instance;
26204 if (!script)
26205 return;
26206 const component = this;
26207 const { content } = script;
26208 const { instance_scope, instance_scope_map: map } = this;
26209 let scope = instance_scope;
26210 const to_remove = [];
26211 const remove = (parent, prop, index) => {
26212 to_remove.unshift([parent, prop, index]);
26213 };
26214 let scope_updated = false;
26215 let generator_count = 0;
26216 walk(content, {
26217 enter(node, parent, prop, index) {
26218 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
26219 generator_count++;
26220 }
26221 if (map.has(node)) {
26222 scope = map.get(node);
26223 }
26224 if (node.type === 'ImportDeclaration') {
26225 component.extract_imports(node);
26226 // TODO: to use actual remove
26227 remove(parent, prop, index);
26228 return this.skip();
26229 }
26230 if (/^Export/.test(node.type)) {
26231 const replacement = component.extract_exports(node);
26232 if (replacement) {
26233 this.replace(replacement);
26234 }
26235 else {
26236 // TODO: to use actual remove
26237 remove(parent, prop, index);
26238 }
26239 return this.skip();
26240 }
26241 component.warn_on_undefined_store_value_references(node, parent, scope);
26242 },
26243 leave(node) {
26244 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
26245 generator_count--;
26246 }
26247 // do it on leave, to prevent infinite loop
26248 if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0 && generator_count <= 0) {
26249 const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout);
26250 if (to_replace_for_loop_protect) {
26251 this.replace(to_replace_for_loop_protect);
26252 scope_updated = true;
26253 }
26254 }
26255 if (map.has(node)) {
26256 scope = scope.parent;
26257 }
26258 },
26259 });
26260 for (const [parent, prop, index] of to_remove) {
26261 if (parent) {
26262 if (index !== null) {
26263 parent[prop].splice(index, 1);
26264 }
26265 else {
26266 delete parent[prop];
26267 }
26268 }
26269 }
26270 if (scope_updated) {
26271 const { scope, map } = create_scopes(script.content);
26272 this.instance_scope = scope;
26273 this.instance_scope_map = map;
26274 }
26275 }
26276 track_references_and_mutations() {
26277 const script = this.ast.instance;
26278 if (!script)
26279 return;
26280 const component = this;
26281 const { content } = script;
26282 const { instance_scope, module_scope, instance_scope_map: map } = this;
26283 let scope = instance_scope;
26284 walk(content, {
26285 enter(node, parent) {
26286 if (map.has(node)) {
26287 scope = map.get(node);
26288 }
26289 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
26290 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
26291 const names = extract_names(assignee);
26292 const deep = assignee.type === 'MemberExpression';
26293 names.forEach(name => {
26294 const scope_owner = scope.find_owner(name);
26295 if (scope_owner !== null
26296 ? scope_owner === instance_scope
26297 : module_scope && module_scope.has(name)) {
26298 const variable = component.var_lookup.get(name);
26299 variable[deep ? 'mutated' : 'reassigned'] = true;
26300 }
26301 });
26302 }
26303 if (is_used_as_reference(node, parent)) {
26304 const object = get_object(node);
26305 if (scope.find_owner(object.name) === instance_scope) {
26306 const variable = component.var_lookup.get(object.name);
26307 variable.referenced_from_script = true;
26308 }
26309 }
26310 },
26311 leave(node) {
26312 if (map.has(node)) {
26313 scope = scope.parent;
26314 }
26315 },
26316 });
26317 }
26318 warn_on_undefined_store_value_references(node, parent, scope) {
26319 if (node.type === 'LabeledStatement' &&
26320 node.label.name === '$' &&
26321 parent.type !== 'Program') {
26322 this.warn(node, {
26323 code: 'non-top-level-reactive-declaration',
26324 message: '$: has no effect outside of the top-level',
26325 });
26326 }
26327 if (isReference(node, parent)) {
26328 const object = get_object(node);
26329 const { name } = object;
26330 if (name[0] === '$') {
26331 if (!scope.has(name)) {
26332 this.warn_if_undefined(name, object, null);
26333 }
26334 if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
26335 this.error(node, {
26336 code: `contextual-store`,
26337 message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
26338 });
26339 }
26340 }
26341 }
26342 }
26343 loop_protect(node, scope, timeout) {
26344 if (node.type === 'WhileStatement' ||
26345 node.type === 'ForStatement' ||
26346 node.type === 'DoWhileStatement') {
26347 const guard = this.get_unique_name('guard', scope);
26348 this.used_names.add(guard.name);
26349 const before = b `const ${guard} = @loop_guard(${timeout})`;
26350 const inside = b `${guard}();`;
26351 // wrap expression statement with BlockStatement
26352 if (node.body.type !== 'BlockStatement') {
26353 node.body = {
26354 type: 'BlockStatement',
26355 body: [node.body],
26356 };
26357 }
26358 node.body.body.push(inside[0]);
26359 return {
26360 type: 'BlockStatement',
26361 body: [
26362 before[0],
26363 node,
26364 ],
26365 };
26366 }
26367 return null;
26368 }
26369 rewrite_props(get_insert) {
26370 if (!this.ast.instance)
26371 return;
26372 const component = this;
26373 const { instance_scope, instance_scope_map: map } = this;
26374 let scope = instance_scope;
26375 walk(this.ast.instance.content, {
26376 enter(node, parent, key, index) {
26377 if (/Function/.test(node.type)) {
26378 return this.skip();
26379 }
26380 if (map.has(node)) {
26381 scope = map.get(node);
26382 }
26383 if (node.type === 'VariableDeclaration') {
26384 if (node.kind === 'var' || scope === instance_scope) {
26385 node.declarations.forEach(declarator => {
26386 if (declarator.id.type !== 'Identifier') {
26387 const inserts = [];
26388 extract_names(declarator.id).forEach(name => {
26389 const variable = component.var_lookup.get(name);
26390 if (variable.export_name) {
26391 // TODO is this still true post-#3539?
26392 component.error(declarator, {
26393 code: 'destructured-prop',
26394 message: `Cannot declare props in destructured declaration`,
26395 });
26396 }
26397 if (variable.subscribable) {
26398 inserts.push(get_insert(variable));
26399 }
26400 });
26401 if (inserts.length) {
26402 parent[key].splice(index + 1, 0, ...inserts);
26403 }
26404 return;
26405 }
26406 const { name } = declarator.id;
26407 const variable = component.var_lookup.get(name);
26408 if (variable.export_name && variable.writable) {
26409 const insert = variable.subscribable
26410 ? get_insert(variable)
26411 : null;
26412 parent[key].splice(index + 1, 0, insert);
26413 declarator.id = {
26414 type: 'ObjectPattern',
26415 properties: [{
26416 type: 'Property',
26417 method: false,
26418 shorthand: false,
26419 computed: false,
26420 kind: 'init',
26421 key: { type: 'Identifier', name: variable.export_name },
26422 value: declarator.init
26423 ? {
26424 type: 'AssignmentPattern',
26425 left: declarator.id,
26426 right: declarator.init
26427 }
26428 : declarator.id
26429 }]
26430 };
26431 declarator.init = x `$$props`;
26432 }
26433 else if (variable.subscribable) {
26434 const insert = get_insert(variable);
26435 parent[key].splice(index + 1, 0, ...insert);
26436 }
26437 });
26438 }
26439 }
26440 },
26441 leave(node, parent, _key, index) {
26442 if (map.has(node)) {
26443 scope = scope.parent;
26444 }
26445 if (node.type === 'ExportNamedDeclaration' && node.declaration) {
26446 parent.body[index] = node.declaration;
26447 }
26448 },
26449 });
26450 }
26451 hoist_instance_declarations() {
26452 // we can safely hoist variable declarations that are
26453 // initialised to literals, and functions that don't
26454 // reference instance variables other than other
26455 // hoistable functions. TODO others?
26456 const { hoistable_nodes, var_lookup, injected_reactive_declaration_vars, imports, } = this;
26457 const top_level_function_declarations = new Map();
26458 const { body } = this.ast.instance.content;
26459 for (let i = 0; i < body.length; i += 1) {
26460 const node = body[i];
26461 if (node.type === 'VariableDeclaration') {
26462 const all_hoistable = node.declarations.every(d => {
26463 if (!d.init)
26464 return false;
26465 if (d.init.type !== 'Literal')
26466 return false;
26467 // everything except const values can be changed by e.g. svelte devtools
26468 // which means we can't hoist it
26469 if (node.kind !== 'const' && this.compile_options.dev)
26470 return false;
26471 const { name } = d.id;
26472 const v = this.var_lookup.get(name);
26473 if (v.reassigned)
26474 return false;
26475 if (v.export_name)
26476 return false;
26477 if (this.var_lookup.get(name).reassigned)
26478 return false;
26479 if (this.vars.find(variable => variable.name === name && variable.module))
26480 return false;
26481 return true;
26482 });
26483 if (all_hoistable) {
26484 node.declarations.forEach(d => {
26485 const variable = this.var_lookup.get(d.id.name);
26486 variable.hoistable = true;
26487 });
26488 hoistable_nodes.add(node);
26489 body.splice(i--, 1);
26490 this.fully_hoisted.push(node);
26491 }
26492 }
26493 if (node.type === 'ExportNamedDeclaration' &&
26494 node.declaration &&
26495 node.declaration.type === 'FunctionDeclaration') {
26496 top_level_function_declarations.set(node.declaration.id.name, node);
26497 }
26498 if (node.type === 'FunctionDeclaration') {
26499 top_level_function_declarations.set(node.id.name, node);
26500 }
26501 }
26502 const checked = new Set();
26503 const walking = new Set();
26504 const is_hoistable = fn_declaration => {
26505 if (fn_declaration.type === 'ExportNamedDeclaration') {
26506 fn_declaration = fn_declaration.declaration;
26507 }
26508 const instance_scope = this.instance_scope;
26509 let scope = this.instance_scope;
26510 const map = this.instance_scope_map;
26511 let hoistable = true;
26512 // handle cycles
26513 walking.add(fn_declaration);
26514 walk(fn_declaration, {
26515 enter(node, parent) {
26516 if (!hoistable)
26517 return this.skip();
26518 if (map.has(node)) {
26519 scope = map.get(node);
26520 }
26521 if (isReference(node, parent)) {
26522 const { name } = flatten_reference(node);
26523 const owner = scope.find_owner(name);
26524 if (injected_reactive_declaration_vars.has(name)) {
26525 hoistable = false;
26526 }
26527 else if (name[0] === '$' && !owner) {
26528 hoistable = false;
26529 }
26530 else if (owner === instance_scope) {
26531 const variable = var_lookup.get(name);
26532 if (variable.reassigned || variable.mutated)
26533 hoistable = false;
26534 if (name === fn_declaration.id.name)
26535 return;
26536 if (variable.hoistable)
26537 return;
26538 if (top_level_function_declarations.has(name)) {
26539 const other_declaration = top_level_function_declarations.get(name);
26540 if (walking.has(other_declaration)) {
26541 hoistable = false;
26542 }
26543 else if (other_declaration.type === 'ExportNamedDeclaration' &&
26544 walking.has(other_declaration.declaration)) {
26545 hoistable = false;
26546 }
26547 else if (!is_hoistable(other_declaration)) {
26548 hoistable = false;
26549 }
26550 }
26551 else {
26552 hoistable = false;
26553 }
26554 }
26555 this.skip();
26556 }
26557 },
26558 leave(node) {
26559 if (map.has(node)) {
26560 scope = scope.parent;
26561 }
26562 },
26563 });
26564 checked.add(fn_declaration);
26565 walking.delete(fn_declaration);
26566 return hoistable;
26567 };
26568 for (const [name, node] of top_level_function_declarations) {
26569 if (is_hoistable(node)) {
26570 const variable = this.var_lookup.get(name);
26571 variable.hoistable = true;
26572 hoistable_nodes.add(node);
26573 const i = body.indexOf(node);
26574 body.splice(i, 1);
26575 this.fully_hoisted.push(node);
26576 }
26577 }
26578 for (const { specifiers } of imports) {
26579 for (const specifier of specifiers) {
26580 const variable = var_lookup.get(specifier.local.name);
26581 if (!variable.mutated || variable.subscribable) {
26582 variable.hoistable = true;
26583 }
26584 }
26585 }
26586 }
26587 extract_reactive_declarations() {
26588 const component = this;
26589 const unsorted_reactive_declarations = [];
26590 this.ast.instance.content.body.forEach(node => {
26591 if (node.type === 'LabeledStatement' && node.label.name === '$') {
26592 this.reactive_declaration_nodes.add(node);
26593 const assignees = new Set();
26594 const assignee_nodes = new Set();
26595 const dependencies = new Set();
26596 let scope = this.instance_scope;
26597 const map = this.instance_scope_map;
26598 walk(node.body, {
26599 enter(node, parent) {
26600 if (map.has(node)) {
26601 scope = map.get(node);
26602 }
26603 if (node.type === 'AssignmentExpression') {
26604 const left = get_object(node.left);
26605 extract_identifiers(left).forEach(node => {
26606 assignee_nodes.add(node);
26607 assignees.add(node.name);
26608 });
26609 if (node.operator !== '=') {
26610 dependencies.add(left.name);
26611 }
26612 }
26613 else if (node.type === 'UpdateExpression') {
26614 const identifier = get_object(node.argument);
26615 assignees.add(identifier.name);
26616 }
26617 else if (isReference(node, parent)) {
26618 const identifier = get_object(node);
26619 if (!assignee_nodes.has(identifier)) {
26620 const { name } = identifier;
26621 const owner = scope.find_owner(name);
26622 const variable = component.var_lookup.get(name);
26623 if (variable)
26624 variable.is_reactive_dependency = true;
26625 const is_writable_or_mutated = variable && (variable.writable || variable.mutated);
26626 if ((!owner || owner === component.instance_scope) &&
26627 (name[0] === '$' || is_writable_or_mutated)) {
26628 dependencies.add(name);
26629 }
26630 }
26631 this.skip();
26632 }
26633 },
26634 leave(node) {
26635 if (map.has(node)) {
26636 scope = scope.parent;
26637 }
26638 },
26639 });
26640 const { expression } = node.body;
26641 const declaration = expression && expression.left;
26642 unsorted_reactive_declarations.push({
26643 assignees,
26644 dependencies,
26645 node,
26646 declaration,
26647 });
26648 }
26649 });
26650 const lookup = new Map();
26651 unsorted_reactive_declarations.forEach(declaration => {
26652 declaration.assignees.forEach(name => {
26653 if (!lookup.has(name)) {
26654 lookup.set(name, []);
26655 }
26656 // TODO warn or error if a name is assigned to in
26657 // multiple reactive declarations?
26658 lookup.get(name).push(declaration);
26659 });
26660 });
26661 const cycle = check_graph_for_cycles(unsorted_reactive_declarations.reduce((acc, declaration) => {
26662 declaration.assignees.forEach(v => {
26663 declaration.dependencies.forEach(w => {
26664 if (!declaration.assignees.has(w)) {
26665 acc.push([v, w]);
26666 }
26667 });
26668 });
26669 return acc;
26670 }, []));
26671 if (cycle && cycle.length) {
26672 const declarationList = lookup.get(cycle[0]);
26673 const declaration = declarationList[0];
26674 this.error(declaration.node, {
26675 code: 'cyclical-reactive-declaration',
26676 message: `Cyclical dependency detected: ${cycle.join(' → ')}`
26677 });
26678 }
26679 const add_declaration = declaration => {
26680 if (this.reactive_declarations.includes(declaration))
26681 return;
26682 declaration.dependencies.forEach(name => {
26683 if (declaration.assignees.has(name))
26684 return;
26685 const earlier_declarations = lookup.get(name);
26686 if (earlier_declarations)
26687 earlier_declarations.forEach(add_declaration);
26688 });
26689 this.reactive_declarations.push(declaration);
26690 };
26691 unsorted_reactive_declarations.forEach(add_declaration);
26692 }
26693 warn_if_undefined(name, node, template_scope) {
26694 if (name[0] === '$') {
26695 if (name === '$' || name[1] === '$' && !is_reserved_keyword(name)) {
26696 this.error(node, {
26697 code: 'illegal-global',
26698 message: `${name} is an illegal variable name`
26699 });
26700 }
26701 this.has_reactive_assignments = true; // TODO does this belong here?
26702 if (is_reserved_keyword(name))
26703 return;
26704 name = name.slice(1);
26705 }
26706 if (this.var_lookup.has(name) && !this.var_lookup.get(name).global)
26707 return;
26708 if (template_scope && template_scope.names.has(name))
26709 return;
26710 if (globals.has(name) && node.type !== 'InlineComponent')
26711 return;
26712 let message = `'${name}' is not defined`;
26713 if (!this.ast.instance)
26714 message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;
26715 this.warn(node, {
26716 code: 'missing-declaration',
26717 message,
26718 });
26719 }
26720 push_ignores(ignores) {
26721 this.ignores = new Set(this.ignores || []);
26722 add_to_set(this.ignores, ignores);
26723 this.ignore_stack.push(this.ignores);
26724 }
26725 pop_ignores() {
26726 this.ignore_stack.pop();
26727 this.ignores = this.ignore_stack[this.ignore_stack.length - 1];
26728 }
26729 }
26730 function process_component_options(component, nodes) {
26731 const component_options = {
26732 immutable: component.compile_options.immutable || false,
26733 accessors: 'accessors' in component.compile_options
26734 ? component.compile_options.accessors
26735 : !!component.compile_options.customElement,
26736 preserveWhitespace: !!component.compile_options.preserveWhitespace,
26737 };
26738 const node = nodes.find(node => node.name === 'svelte:options');
26739 function get_value(attribute, code, message) {
26740 const { value } = attribute;
26741 const chunk = value[0];
26742 if (!chunk)
26743 return true;
26744 if (value.length > 1) {
26745 component.error(attribute, { code, message });
26746 }
26747 if (chunk.type === 'Text')
26748 return chunk.data;
26749 if (chunk.expression.type !== 'Literal') {
26750 component.error(attribute, { code, message });
26751 }
26752 return chunk.expression.value;
26753 }
26754 if (node) {
26755 node.attributes.forEach(attribute => {
26756 if (attribute.type === 'Attribute') {
26757 const { name } = attribute;
26758 switch (name) {
26759 case 'tag': {
26760 const code = 'invalid-tag-attribute';
26761 const message = `'tag' must be a string literal`;
26762 const tag = get_value(attribute, code, message);
26763 if (typeof tag !== 'string' && tag !== null)
26764 component.error(attribute, { code, message });
26765 if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
26766 component.error(attribute, {
26767 code: `invalid-tag-property`,
26768 message: `tag name must be two or more words joined by the '-' character`,
26769 });
26770 }
26771 if (tag && !component.compile_options.customElement) {
26772 component.warn(attribute, {
26773 code: 'missing-custom-element-compile-options',
26774 message: `The 'tag' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?`
26775 });
26776 }
26777 component_options.tag = tag;
26778 break;
26779 }
26780 case 'namespace': {
26781 const code = 'invalid-namespace-attribute';
26782 const message = `The 'namespace' attribute must be a string literal representing a valid namespace`;
26783 const ns = get_value(attribute, code, message);
26784 if (typeof ns !== 'string')
26785 component.error(attribute, { code, message });
26786 if (valid_namespaces.indexOf(ns) === -1) {
26787 const match = fuzzymatch(ns, valid_namespaces);
26788 if (match) {
26789 component.error(attribute, {
26790 code: `invalid-namespace-property`,
26791 message: `Invalid namespace '${ns}' (did you mean '${match}'?)`,
26792 });
26793 }
26794 else {
26795 component.error(attribute, {
26796 code: `invalid-namespace-property`,
26797 message: `Invalid namespace '${ns}'`,
26798 });
26799 }
26800 }
26801 component_options.namespace = ns;
26802 break;
26803 }
26804 case 'accessors':
26805 case 'immutable':
26806 case 'preserveWhitespace': {
26807 const code = `invalid-${name}-value`;
26808 const message = `${name} attribute must be true or false`;
26809 const value = get_value(attribute, code, message);
26810 if (typeof value !== 'boolean')
26811 component.error(attribute, { code, message });
26812 component_options[name] = value;
26813 break;
26814 }
26815 default:
26816 component.error(attribute, {
26817 code: `invalid-options-attribute`,
26818 message: `<svelte:options> unknown attribute`,
26819 });
26820 }
26821 }
26822 else {
26823 component.error(attribute, {
26824 code: `invalid-options-attribute`,
26825 message: `<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes`,
26826 });
26827 }
26828 });
26829 }
26830 return component_options;
26831 }
26832 function get_relative_path(from, to) {
26833 const from_parts = from.split(/[/\\]/);
26834 const to_parts = to.split(/[/\\]/);
26835 from_parts.pop(); // get dirname
26836 while (from_parts[0] === to_parts[0]) {
26837 from_parts.shift();
26838 to_parts.shift();
26839 }
26840 if (from_parts.length) {
26841 let i = from_parts.length;
26842 while (i--)
26843 from_parts[i] = '..';
26844 }
26845 return from_parts.concat(to_parts).join('/');
26846 }
26847
26848 function get_name_from_filename(filename) {
26849 if (!filename)
26850 return null;
26851 const parts = filename.split(/[/\\]/).map(encodeURI);
26852 if (parts.length > 1) {
26853 const index_match = parts[parts.length - 1].match(/^index(\.\w+)/);
26854 if (index_match) {
26855 parts.pop();
26856 parts[parts.length - 1] += index_match[1];
26857 }
26858 }
26859 const base = parts.pop()
26860 .replace(/%/g, 'u')
26861 .replace(/\.[^.]+$/, "")
26862 .replace(/[^a-zA-Z_$0-9]+/g, '_')
26863 .replace(/^_/, '')
26864 .replace(/_$/, '')
26865 .replace(/^(\d)/, '_$1');
26866 if (!base) {
26867 throw new Error(`Could not derive component name from file ${filename}`);
26868 }
26869 return base[0].toUpperCase() + base.slice(1);
26870 }
26871
26872 const valid_options = [
26873 'format',
26874 'name',
26875 'filename',
26876 'generate',
26877 'outputFilename',
26878 'cssOutputFilename',
26879 'sveltePath',
26880 'dev',
26881 'accessors',
26882 'immutable',
26883 'hydratable',
26884 'legacy',
26885 'customElement',
26886 'tag',
26887 'css',
26888 'loopGuardTimeout',
26889 'preserveComments',
26890 'preserveWhitespace'
26891 ];
26892 function validate_options(options, warnings) {
26893 const { name, filename, loopGuardTimeout, dev } = options;
26894 Object.keys(options).forEach(key => {
26895 if (!valid_options.includes(key)) {
26896 const match = fuzzymatch(key, valid_options);
26897 let message = `Unrecognized option '${key}'`;
26898 if (match)
26899 message += ` (did you mean '${match}'?)`;
26900 throw new Error(message);
26901 }
26902 });
26903 if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) {
26904 throw new Error(`options.name must be a valid identifier (got '${name}')`);
26905 }
26906 if (name && /^[a-z]/.test(name)) {
26907 const message = `options.name should be capitalised`;
26908 warnings.push({
26909 code: `options-lowercase-name`,
26910 message,
26911 filename,
26912 toString: () => message,
26913 });
26914 }
26915 if (loopGuardTimeout && !dev) {
26916 const message = 'options.loopGuardTimeout is for options.dev = true only';
26917 warnings.push({
26918 code: `options-loop-guard-timeout`,
26919 message,
26920 filename,
26921 toString: () => message,
26922 });
26923 }
26924 }
26925 function compile(source, options = {}) {
26926 options = assign({ generate: 'dom', dev: false }, options);
26927 const stats = new Stats();
26928 const warnings = [];
26929 validate_options(options, warnings);
26930 stats.start('parse');
26931 const ast = parse$3(source, options);
26932 stats.stop('parse');
26933 stats.start('create component');
26934 const component = new Component(ast, source, options.name || get_name_from_filename(options.filename) || 'Component', options, stats, warnings);
26935 stats.stop('create component');
26936 const result = options.generate === false
26937 ? null
26938 : options.generate === 'ssr'
26939 ? ssr(component, options)
26940 : dom(component, options);
26941 return component.generate(result);
26942 }
26943
26944 function parse_attributes(str) {
26945 const attrs = {};
26946 str.split(/\s+/).filter(Boolean).forEach(attr => {
26947 const p = attr.indexOf('=');
26948 if (p === -1) {
26949 attrs[attr] = true;
26950 }
26951 else {
26952 attrs[attr.slice(0, p)] = `'"`.includes(attr[p + 1]) ?
26953 attr.slice(p + 2, -1) :
26954 attr.slice(p + 1);
26955 }
26956 });
26957 return attrs;
26958 }
26959 async function replace_async(str, re, func) {
26960 const replacements = [];
26961 str.replace(re, (...args) => {
26962 replacements.push(func(...args).then(res => ({
26963 offset: args[args.length - 2],
26964 length: args[0].length,
26965 replacement: res,
26966 })));
26967 return '';
26968 });
26969 let out = '';
26970 let last_end = 0;
26971 for (const { offset, length, replacement } of await Promise.all(replacements)) {
26972 out += str.slice(last_end, offset) + replacement;
26973 last_end = offset + length;
26974 }
26975 out += str.slice(last_end);
26976 return out;
26977 }
26978 async function preprocess(source, preprocessor, options) {
26979 // @ts-ignore todo: doublecheck
26980 const filename = (options && options.filename) || preprocessor.filename; // legacy
26981 const dependencies = [];
26982 const preprocessors = Array.isArray(preprocessor) ? preprocessor : [preprocessor];
26983 const markup = preprocessors.map(p => p.markup).filter(Boolean);
26984 const script = preprocessors.map(p => p.script).filter(Boolean);
26985 const style = preprocessors.map(p => p.style).filter(Boolean);
26986 for (const fn of markup) {
26987 const processed = await fn({
26988 content: source,
26989 filename
26990 });
26991 if (processed && processed.dependencies)
26992 dependencies.push(...processed.dependencies);
26993 source = processed ? processed.code : source;
26994 }
26995 for (const fn of script) {
26996 source = await replace_async(source, /<!--[^]*?-->|<script(\s[^]*?)?(?:>([^]*?)<\/script>|\/>)/gi, async (match, attributes = '', content = '') => {
26997 if (!attributes && !content) {
26998 return match;
26999 }
27000 attributes = attributes || '';
27001 const processed = await fn({
27002 content,
27003 attributes: parse_attributes(attributes),
27004 filename
27005 });
27006 if (processed && processed.dependencies)
27007 dependencies.push(...processed.dependencies);
27008 return processed ? `<script${attributes}>${processed.code}</script>` : match;
27009 });
27010 }
27011 for (const fn of style) {
27012 source = await replace_async(source, /<!--[^]*?-->|<style(\s[^]*?)?(?:>([^]*?)<\/style>|\/>)/gi, async (match, attributes = '', content = '') => {
27013 if (!attributes && !content) {
27014 return match;
27015 }
27016 const processed = await fn({
27017 content,
27018 attributes: parse_attributes(attributes),
27019 filename
27020 });
27021 if (processed && processed.dependencies)
27022 dependencies.push(...processed.dependencies);
27023 return processed ? `<style${attributes}>${processed.code}</style>` : match;
27024 });
27025 }
27026 return {
27027 // TODO return separated output, in future version where svelte.compile supports it:
27028 // style: { code: styleCode, map: styleMap },
27029 // script { code: scriptCode, map: scriptMap },
27030 // markup { code: markupCode, map: markupMap },
27031 code: source,
27032 dependencies: [...new Set(dependencies)],
27033 toString() {
27034 return source;
27035 }
27036 };
27037 }
27038
27039 const VERSION = '3.24.1';
27040
27041 exports.VERSION = VERSION;
27042 exports.compile = compile;
27043 exports.parse = parse$3;
27044 exports.preprocess = preprocess;
27045 exports.walk = walk;
27046
27047 Object.defineProperty(exports, '__esModule', { value: true });
27048
27049})));
27050//# sourceMappingURL=compiler.js.map
27051
\No newline at end of file