UNPKG

917 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 parser.error({
14683 code: `invalid-closing-tag`,
14684 message: `</${name}> attempted to close an element that was not open`
14685 }, start);
14686 parent.end = start;
14687 parser.stack.pop();
14688 parent = parser.current();
14689 }
14690 parent.end = parser.index;
14691 parser.stack.pop();
14692 return;
14693 }
14694 else if (closing_tag_omitted(parent.name, name)) {
14695 parent.end = start;
14696 parser.stack.pop();
14697 }
14698 const unique_names = new Set();
14699 let attribute;
14700 while ((attribute = read_attribute(parser, unique_names))) {
14701 element.attributes.push(attribute);
14702 parser.allow_whitespace();
14703 }
14704 if (name === 'svelte:component') {
14705 const index = element.attributes.findIndex(attr => attr.type === 'Attribute' && attr.name === 'this');
14706 if (!~index) {
14707 parser.error({
14708 code: `missing-component-definition`,
14709 message: `<svelte:component> must have a 'this' attribute`
14710 }, start);
14711 }
14712 const definition = element.attributes.splice(index, 1)[0];
14713 if (definition.value === true || definition.value.length !== 1 || definition.value[0].type === 'Text') {
14714 parser.error({
14715 code: `invalid-component-definition`,
14716 message: `invalid component definition`
14717 }, definition.start);
14718 }
14719 element.expression = definition.value[0].expression;
14720 }
14721 // special cases – top-level <script> and <style>
14722 if (specials.has(name) && parser.stack.length === 1) {
14723 const special = specials.get(name);
14724 parser.eat('>', true);
14725 const content = special.read(parser, start, element.attributes);
14726 if (content)
14727 parser[special.property].push(content);
14728 return;
14729 }
14730 parser.current().children.push(element);
14731 const self_closing = parser.eat('/') || is_void(name);
14732 parser.eat('>', true);
14733 if (self_closing) {
14734 // don't push self-closing elements onto the stack
14735 element.end = parser.index;
14736 }
14737 else if (name === 'textarea') {
14738 // special case
14739 element.children = read_sequence(parser, () => parser.template.slice(parser.index, parser.index + 11) === '</textarea>');
14740 parser.read(/<\/textarea>/);
14741 element.end = parser.index;
14742 }
14743 else if (name === 'script') {
14744 // special case
14745 const start = parser.index;
14746 const data = parser.read_until(/<\/script>/);
14747 const end = parser.index;
14748 element.children.push({ start, end, type: 'Text', data });
14749 parser.eat('</script>', true);
14750 element.end = parser.index;
14751 }
14752 else if (name === 'style') {
14753 // special case
14754 const start = parser.index;
14755 const data = parser.read_until(/<\/style>/);
14756 const end = parser.index;
14757 element.children.push({ start, end, type: 'Text', data });
14758 parser.eat('</style>', true);
14759 }
14760 else {
14761 parser.stack.push(element);
14762 }
14763 }
14764 function read_tag_name(parser) {
14765 const start = parser.index;
14766 if (parser.read(SELF)) {
14767 // check we're inside a block, otherwise this
14768 // will cause infinite recursion
14769 let i = parser.stack.length;
14770 let legal = false;
14771 while (i--) {
14772 const fragment = parser.stack[i];
14773 if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock' || fragment.type === 'InlineComponent') {
14774 legal = true;
14775 break;
14776 }
14777 }
14778 if (!legal) {
14779 parser.error({
14780 code: `invalid-self-placement`,
14781 message: `<svelte:self> components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components`
14782 }, start);
14783 }
14784 return 'svelte:self';
14785 }
14786 if (parser.read(COMPONENT))
14787 return 'svelte:component';
14788 const name = parser.read_until(/(\s|\/|>)/);
14789 if (meta_tags.has(name))
14790 return name;
14791 if (name.startsWith('svelte:')) {
14792 const match = fuzzymatch(name.slice(7), valid_meta_tags);
14793 let message = `Valid <svelte:...> tag names are ${list$1(valid_meta_tags)}`;
14794 if (match)
14795 message += ` (did you mean '${match}'?)`;
14796 parser.error({
14797 code: 'invalid-tag-name',
14798 message
14799 }, start);
14800 }
14801 if (!valid_tag_name.test(name)) {
14802 parser.error({
14803 code: `invalid-tag-name`,
14804 message: `Expected valid tag name`
14805 }, start);
14806 }
14807 return name;
14808 }
14809 function read_attribute(parser, unique_names) {
14810 const start = parser.index;
14811 function check_unique(name) {
14812 if (unique_names.has(name)) {
14813 parser.error({
14814 code: `duplicate-attribute`,
14815 message: 'Attributes need to be unique'
14816 }, start);
14817 }
14818 unique_names.add(name);
14819 }
14820 if (parser.eat('{')) {
14821 parser.allow_whitespace();
14822 if (parser.eat('...')) {
14823 const expression = read_expression(parser);
14824 parser.allow_whitespace();
14825 parser.eat('}', true);
14826 return {
14827 start,
14828 end: parser.index,
14829 type: 'Spread',
14830 expression
14831 };
14832 }
14833 else {
14834 const value_start = parser.index;
14835 const name = parser.read_identifier();
14836 parser.allow_whitespace();
14837 parser.eat('}', true);
14838 check_unique(name);
14839 return {
14840 start,
14841 end: parser.index,
14842 type: 'Attribute',
14843 name,
14844 value: [{
14845 start: value_start,
14846 end: value_start + name.length,
14847 type: 'AttributeShorthand',
14848 expression: {
14849 start: value_start,
14850 end: value_start + name.length,
14851 type: 'Identifier',
14852 name
14853 }
14854 }]
14855 };
14856 }
14857 }
14858 // eslint-disable-next-line no-useless-escape
14859 const name = parser.read_until(/[\s=\/>"']/);
14860 if (!name)
14861 return null;
14862 let end = parser.index;
14863 parser.allow_whitespace();
14864 const colon_index = name.indexOf(':');
14865 const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index));
14866 let value = true;
14867 if (parser.eat('=')) {
14868 parser.allow_whitespace();
14869 value = read_attribute_value(parser);
14870 end = parser.index;
14871 }
14872 else if (parser.match_regex(/["']/)) {
14873 parser.error({
14874 code: `unexpected-token`,
14875 message: `Expected =`
14876 }, parser.index);
14877 }
14878 if (type) {
14879 const [directive_name, ...modifiers] = name.slice(colon_index + 1).split('|');
14880 if (type === 'Binding' && directive_name !== 'this') {
14881 check_unique(directive_name);
14882 }
14883 else if (type !== 'EventHandler') {
14884 check_unique(name);
14885 }
14886 if (type === 'Ref') {
14887 parser.error({
14888 code: `invalid-ref-directive`,
14889 message: `The ref directive is no longer supported — use \`bind:this={${directive_name}}\` instead`
14890 }, start);
14891 }
14892 if (value[0]) {
14893 if (value.length > 1 || value[0].type === 'Text') {
14894 parser.error({
14895 code: `invalid-directive-value`,
14896 message: `Directive value must be a JavaScript expression enclosed in curly braces`
14897 }, value[0].start);
14898 }
14899 }
14900 const directive = {
14901 start,
14902 end,
14903 type,
14904 name: directive_name,
14905 modifiers,
14906 expression: (value[0] && value[0].expression) || null
14907 };
14908 if (type === 'Transition') {
14909 const direction = name.slice(0, colon_index);
14910 directive.intro = direction === 'in' || direction === 'transition';
14911 directive.outro = direction === 'out' || direction === 'transition';
14912 }
14913 if (!directive.expression && (type === 'Binding' || type === 'Class')) {
14914 directive.expression = {
14915 start: directive.start + colon_index + 1,
14916 end: directive.end,
14917 type: 'Identifier',
14918 name: directive.name
14919 };
14920 }
14921 return directive;
14922 }
14923 check_unique(name);
14924 return {
14925 start,
14926 end,
14927 type: 'Attribute',
14928 name,
14929 value,
14930 };
14931 }
14932 function get_directive_type(name) {
14933 if (name === 'use')
14934 return 'Action';
14935 if (name === 'animate')
14936 return 'Animation';
14937 if (name === 'bind')
14938 return 'Binding';
14939 if (name === 'class')
14940 return 'Class';
14941 if (name === 'on')
14942 return 'EventHandler';
14943 if (name === 'let')
14944 return 'Let';
14945 if (name === 'ref')
14946 return 'Ref';
14947 if (name === 'in' || name === 'out' || name === 'transition')
14948 return 'Transition';
14949 }
14950 function read_attribute_value(parser) {
14951 const quote_mark = parser.eat(`'`) ? `'` : parser.eat(`"`) ? `"` : null;
14952 const regex = (quote_mark === `'` ? /'/ :
14953 quote_mark === `"` ? /"/ :
14954 /(\/>|[\s"'=<>`])/);
14955 const value = read_sequence(parser, () => !!parser.match_regex(regex));
14956 if (quote_mark)
14957 parser.index += 1;
14958 return value;
14959 }
14960 function read_sequence(parser, done) {
14961 let current_chunk = {
14962 start: parser.index,
14963 end: null,
14964 type: 'Text',
14965 raw: '',
14966 data: null
14967 };
14968 function flush() {
14969 if (current_chunk.raw) {
14970 current_chunk.data = decode_character_references(current_chunk.raw);
14971 current_chunk.end = parser.index;
14972 chunks.push(current_chunk);
14973 }
14974 }
14975 const chunks = [];
14976 while (parser.index < parser.template.length) {
14977 const index = parser.index;
14978 if (done()) {
14979 flush();
14980 return chunks;
14981 }
14982 else if (parser.eat('{')) {
14983 flush();
14984 parser.allow_whitespace();
14985 const expression = read_expression(parser);
14986 parser.allow_whitespace();
14987 parser.eat('}', true);
14988 chunks.push({
14989 start: index,
14990 end: parser.index,
14991 type: 'MustacheTag',
14992 expression,
14993 });
14994 current_chunk = {
14995 start: parser.index,
14996 end: null,
14997 type: 'Text',
14998 raw: '',
14999 data: null
15000 };
15001 }
15002 else {
15003 current_chunk.raw += parser.template[parser.index++];
15004 }
15005 }
15006 parser.error({
15007 code: `unexpected-eof`,
15008 message: `Unexpected end of input`
15009 });
15010 }
15011
15012 const SQUARE_BRACKET_OPEN = "[".charCodeAt(0);
15013 const SQUARE_BRACKET_CLOSE = "]".charCodeAt(0);
15014 const CURLY_BRACKET_OPEN = "{".charCodeAt(0);
15015 const CURLY_BRACKET_CLOSE = "}".charCodeAt(0);
15016 function is_bracket_open(code) {
15017 return code === SQUARE_BRACKET_OPEN || code === CURLY_BRACKET_OPEN;
15018 }
15019 function is_bracket_close(code) {
15020 return code === SQUARE_BRACKET_CLOSE || code === CURLY_BRACKET_CLOSE;
15021 }
15022 function is_bracket_pair(open, close) {
15023 return ((open === SQUARE_BRACKET_OPEN && close === SQUARE_BRACKET_CLOSE) ||
15024 (open === CURLY_BRACKET_OPEN && close === CURLY_BRACKET_CLOSE));
15025 }
15026 function get_bracket_close(open) {
15027 if (open === SQUARE_BRACKET_OPEN) {
15028 return SQUARE_BRACKET_CLOSE;
15029 }
15030 if (open === CURLY_BRACKET_OPEN) {
15031 return CURLY_BRACKET_CLOSE;
15032 }
15033 }
15034
15035 function read_context(parser) {
15036 const start = parser.index;
15037 let i = parser.index;
15038 const code = full_char_code_at(parser.template, i);
15039 if (isIdentifierStart(code, true)) {
15040 return {
15041 type: "Identifier",
15042 name: parser.read_identifier(),
15043 start,
15044 end: parser.index
15045 };
15046 }
15047 if (!is_bracket_open(code)) {
15048 parser.error({
15049 code: "unexpected-token",
15050 message: "Expected identifier or destructure pattern"
15051 });
15052 }
15053 const bracket_stack = [code];
15054 i += code <= 0xffff ? 1 : 2;
15055 while (i < parser.template.length) {
15056 const code = full_char_code_at(parser.template, i);
15057 if (is_bracket_open(code)) {
15058 bracket_stack.push(code);
15059 }
15060 else if (is_bracket_close(code)) {
15061 if (!is_bracket_pair(bracket_stack[bracket_stack.length - 1], code)) {
15062 parser.error({
15063 code: "unexpected-token",
15064 message: `Expected ${String.fromCharCode(get_bracket_close(bracket_stack[bracket_stack.length - 1]))}`
15065 });
15066 }
15067 bracket_stack.pop();
15068 if (bracket_stack.length === 0) {
15069 i += code <= 0xffff ? 1 : 2;
15070 break;
15071 }
15072 }
15073 i += code <= 0xffff ? 1 : 2;
15074 }
15075 parser.index = i;
15076 const pattern_string = parser.template.slice(start, i);
15077 try {
15078 // the length of the `space_with_newline` has to be start - 1
15079 // because we added a `(` in front of the pattern_string,
15080 // which shifted the entire string to right by 1
15081 // so we offset it by removing 1 character in the `space_with_newline`
15082 // to achieve that, we remove the 1st space encountered,
15083 // so it will not affect the `column` of the node
15084 let space_with_newline = parser.template.slice(0, start).replace(/[^\n]/g, ' ');
15085 const first_space = space_with_newline.indexOf(' ');
15086 space_with_newline = space_with_newline.slice(0, first_space) + space_with_newline.slice(first_space + 1);
15087 return parse_expression_at(`${space_with_newline}(${pattern_string} = 1)`, start - 1).left;
15088 }
15089 catch (error) {
15090 parser.acorn_error(error);
15091 }
15092 }
15093
15094 function trim_start(str) {
15095 let i = 0;
15096 while (whitespace.test(str[i]))
15097 i += 1;
15098 return str.slice(i);
15099 }
15100 function trim_end(str) {
15101 let i = str.length;
15102 while (whitespace.test(str[i - 1]))
15103 i -= 1;
15104 return str.slice(0, i);
15105 }
15106
15107 function to_string(node) {
15108 switch (node.type) {
15109 case 'IfBlock':
15110 return '{#if} block';
15111 case 'ThenBlock':
15112 return '{:then} block';
15113 case 'ElseBlock':
15114 return '{:else} block';
15115 case 'PendingBlock':
15116 case 'AwaitBlock':
15117 return '{#await} block';
15118 case 'CatchBlock':
15119 return '{:catch} block';
15120 case 'EachBlock':
15121 return '{#each} block';
15122 case 'RawMustacheTag':
15123 return '{@html} block';
15124 case 'DebugTag':
15125 return '{@debug} block';
15126 case 'Element':
15127 case 'InlineComponent':
15128 case 'Slot':
15129 case 'Title':
15130 return `<${node.name}> tag`;
15131 default:
15132 return node.type;
15133 }
15134 }
15135
15136 function trim_whitespace(block, trim_before, trim_after) {
15137 if (!block.children || block.children.length === 0)
15138 return; // AwaitBlock
15139 const first_child = block.children[0];
15140 const last_child = block.children[block.children.length - 1];
15141 if (first_child.type === 'Text' && trim_before) {
15142 first_child.data = trim_start(first_child.data);
15143 if (!first_child.data)
15144 block.children.shift();
15145 }
15146 if (last_child.type === 'Text' && trim_after) {
15147 last_child.data = trim_end(last_child.data);
15148 if (!last_child.data)
15149 block.children.pop();
15150 }
15151 if (block.else) {
15152 trim_whitespace(block.else, trim_before, trim_after);
15153 }
15154 if (first_child.elseif) {
15155 trim_whitespace(first_child, trim_before, trim_after);
15156 }
15157 }
15158 function mustache(parser) {
15159 const start = parser.index;
15160 parser.index += 1;
15161 parser.allow_whitespace();
15162 // {/if}, {/each} or {/await}
15163 if (parser.eat('/')) {
15164 let block = parser.current();
15165 let expected;
15166 if (closing_tag_omitted(block.name)) {
15167 block.end = start;
15168 parser.stack.pop();
15169 block = parser.current();
15170 }
15171 if (block.type === 'ElseBlock' || block.type === 'PendingBlock' || block.type === 'ThenBlock' || block.type === 'CatchBlock') {
15172 block.end = start;
15173 parser.stack.pop();
15174 block = parser.current();
15175 expected = 'await';
15176 }
15177 if (block.type === 'IfBlock') {
15178 expected = 'if';
15179 }
15180 else if (block.type === 'EachBlock') {
15181 expected = 'each';
15182 }
15183 else if (block.type === 'AwaitBlock') {
15184 expected = 'await';
15185 }
15186 else {
15187 parser.error({
15188 code: `unexpected-block-close`,
15189 message: `Unexpected block closing tag`
15190 });
15191 }
15192 parser.eat(expected, true);
15193 parser.allow_whitespace();
15194 parser.eat('}', true);
15195 while (block.elseif) {
15196 block.end = parser.index;
15197 parser.stack.pop();
15198 block = parser.current();
15199 if (block.else) {
15200 block.else.end = start;
15201 }
15202 }
15203 // strip leading/trailing whitespace as necessary
15204 const char_before = parser.template[block.start - 1];
15205 const char_after = parser.template[parser.index];
15206 const trim_before = !char_before || whitespace.test(char_before);
15207 const trim_after = !char_after || whitespace.test(char_after);
15208 trim_whitespace(block, trim_before, trim_after);
15209 block.end = parser.index;
15210 parser.stack.pop();
15211 }
15212 else if (parser.eat(':else')) {
15213 if (parser.eat('if')) {
15214 parser.error({
15215 code: 'invalid-elseif',
15216 message: `'elseif' should be 'else if'`
15217 });
15218 }
15219 parser.allow_whitespace();
15220 // :else if
15221 if (parser.eat('if')) {
15222 const block = parser.current();
15223 if (block.type !== 'IfBlock') {
15224 parser.error({
15225 code: `invalid-elseif-placement`,
15226 message: parser.stack.some(block => block.type === 'IfBlock')
15227 ? `Expected to close ${to_string(block)} before seeing {:else if ...} block`
15228 : `Cannot have an {:else if ...} block outside an {#if ...} block`
15229 });
15230 }
15231 parser.require_whitespace();
15232 const expression = read_expression(parser);
15233 parser.allow_whitespace();
15234 parser.eat('}', true);
15235 block.else = {
15236 start: parser.index,
15237 end: null,
15238 type: 'ElseBlock',
15239 children: [
15240 {
15241 start: parser.index,
15242 end: null,
15243 type: 'IfBlock',
15244 elseif: true,
15245 expression,
15246 children: [],
15247 },
15248 ],
15249 };
15250 parser.stack.push(block.else.children[0]);
15251 }
15252 // :else
15253 else {
15254 const block = parser.current();
15255 if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
15256 parser.error({
15257 code: `invalid-else-placement`,
15258 message: parser.stack.some(block => block.type === 'IfBlock' || block.type === 'EachBlock')
15259 ? `Expected to close ${to_string(block)} before seeing {:else} block`
15260 : `Cannot have an {:else} block outside an {#if ...} or {#each ...} block`
15261 });
15262 }
15263 parser.allow_whitespace();
15264 parser.eat('}', true);
15265 block.else = {
15266 start: parser.index,
15267 end: null,
15268 type: 'ElseBlock',
15269 children: [],
15270 };
15271 parser.stack.push(block.else);
15272 }
15273 }
15274 else if (parser.match(':then') || parser.match(':catch')) {
15275 const block = parser.current();
15276 const is_then = parser.eat(':then') || !parser.eat(':catch');
15277 if (is_then) {
15278 if (block.type !== 'PendingBlock') {
15279 parser.error({
15280 code: `invalid-then-placement`,
15281 message: parser.stack.some(block => block.type === 'PendingBlock')
15282 ? `Expected to close ${to_string(block)} before seeing {:then} block`
15283 : `Cannot have an {:then} block outside an {#await ...} block`
15284 });
15285 }
15286 }
15287 else {
15288 if (block.type !== 'ThenBlock' && block.type !== 'PendingBlock') {
15289 parser.error({
15290 code: `invalid-catch-placement`,
15291 message: parser.stack.some(block => block.type === 'ThenBlock' || block.type === 'PendingBlock')
15292 ? `Expected to close ${to_string(block)} before seeing {:catch} block`
15293 : `Cannot have an {:catch} block outside an {#await ...} block`
15294 });
15295 }
15296 }
15297 block.end = start;
15298 parser.stack.pop();
15299 const await_block = parser.current();
15300 if (!parser.eat('}')) {
15301 parser.require_whitespace();
15302 await_block[is_then ? 'value' : 'error'] = read_context(parser);
15303 parser.allow_whitespace();
15304 parser.eat('}', true);
15305 }
15306 const new_block = {
15307 start,
15308 end: null,
15309 type: is_then ? 'ThenBlock' : 'CatchBlock',
15310 children: [],
15311 skip: false
15312 };
15313 await_block[is_then ? 'then' : 'catch'] = new_block;
15314 parser.stack.push(new_block);
15315 }
15316 else if (parser.eat('#')) {
15317 // {#if foo}, {#each foo} or {#await foo}
15318 let type;
15319 if (parser.eat('if')) {
15320 type = 'IfBlock';
15321 }
15322 else if (parser.eat('each')) {
15323 type = 'EachBlock';
15324 }
15325 else if (parser.eat('await')) {
15326 type = 'AwaitBlock';
15327 }
15328 else {
15329 parser.error({
15330 code: `expected-block-type`,
15331 message: `Expected if, each or await`
15332 });
15333 }
15334 parser.require_whitespace();
15335 const expression = read_expression(parser);
15336 const block = type === 'AwaitBlock' ?
15337 {
15338 start,
15339 end: null,
15340 type,
15341 expression,
15342 value: null,
15343 error: null,
15344 pending: {
15345 start: null,
15346 end: null,
15347 type: 'PendingBlock',
15348 children: [],
15349 skip: true
15350 },
15351 then: {
15352 start: null,
15353 end: null,
15354 type: 'ThenBlock',
15355 children: [],
15356 skip: true
15357 },
15358 catch: {
15359 start: null,
15360 end: null,
15361 type: 'CatchBlock',
15362 children: [],
15363 skip: true
15364 },
15365 } :
15366 {
15367 start,
15368 end: null,
15369 type,
15370 expression,
15371 children: [],
15372 };
15373 parser.allow_whitespace();
15374 // {#each} blocks must declare a context – {#each list as item}
15375 if (type === 'EachBlock') {
15376 parser.eat('as', true);
15377 parser.require_whitespace();
15378 block.context = read_context(parser);
15379 parser.allow_whitespace();
15380 if (parser.eat(',')) {
15381 parser.allow_whitespace();
15382 block.index = parser.read_identifier();
15383 if (!block.index)
15384 parser.error({
15385 code: `expected-name`,
15386 message: `Expected name`
15387 });
15388 parser.allow_whitespace();
15389 }
15390 if (parser.eat('(')) {
15391 parser.allow_whitespace();
15392 block.key = read_expression(parser);
15393 parser.allow_whitespace();
15394 parser.eat(')', true);
15395 parser.allow_whitespace();
15396 }
15397 }
15398 const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then');
15399 if (await_block_shorthand) {
15400 parser.require_whitespace();
15401 block.value = read_context(parser);
15402 parser.allow_whitespace();
15403 }
15404 const await_block_catch_shorthand = !await_block_shorthand && type === 'AwaitBlock' && parser.eat('catch');
15405 if (await_block_catch_shorthand) {
15406 parser.require_whitespace();
15407 block.error = read_context(parser);
15408 parser.allow_whitespace();
15409 }
15410 parser.eat('}', true);
15411 parser.current().children.push(block);
15412 parser.stack.push(block);
15413 if (type === 'AwaitBlock') {
15414 let child_block;
15415 if (await_block_shorthand) {
15416 block.then.skip = false;
15417 child_block = block.then;
15418 }
15419 else if (await_block_catch_shorthand) {
15420 block.catch.skip = false;
15421 child_block = block.catch;
15422 }
15423 else {
15424 block.pending.skip = false;
15425 child_block = block.pending;
15426 }
15427 child_block.start = parser.index;
15428 parser.stack.push(child_block);
15429 }
15430 }
15431 else if (parser.eat('@html')) {
15432 // {@html content} tag
15433 parser.require_whitespace();
15434 const expression = read_expression(parser);
15435 parser.allow_whitespace();
15436 parser.eat('}', true);
15437 parser.current().children.push({
15438 start,
15439 end: parser.index,
15440 type: 'RawMustacheTag',
15441 expression,
15442 });
15443 }
15444 else if (parser.eat('@debug')) {
15445 let identifiers;
15446 // Implies {@debug} which indicates "debug all"
15447 if (parser.read(/\s*}/)) {
15448 identifiers = [];
15449 }
15450 else {
15451 const expression = read_expression(parser);
15452 identifiers = expression.type === 'SequenceExpression'
15453 ? expression.expressions
15454 : [expression];
15455 identifiers.forEach(node => {
15456 if (node.type !== 'Identifier') {
15457 parser.error({
15458 code: 'invalid-debug-args',
15459 message: '{@debug ...} arguments must be identifiers, not arbitrary expressions'
15460 }, node.start);
15461 }
15462 });
15463 parser.allow_whitespace();
15464 parser.eat('}', true);
15465 }
15466 parser.current().children.push({
15467 start,
15468 end: parser.index,
15469 type: 'DebugTag',
15470 identifiers
15471 });
15472 }
15473 else {
15474 const expression = read_expression(parser);
15475 parser.allow_whitespace();
15476 parser.eat('}', true);
15477 parser.current().children.push({
15478 start,
15479 end: parser.index,
15480 type: 'MustacheTag',
15481 expression,
15482 });
15483 }
15484 }
15485
15486 function text(parser) {
15487 const start = parser.index;
15488 let data = '';
15489 while (parser.index < parser.template.length &&
15490 !parser.match('<') &&
15491 !parser.match('{')) {
15492 data += parser.template[parser.index++];
15493 }
15494 const node = {
15495 start,
15496 end: parser.index,
15497 type: 'Text',
15498 raw: data,
15499 data: decode_character_references(data),
15500 };
15501 parser.current().children.push(node);
15502 }
15503
15504 function fragment(parser) {
15505 if (parser.match('<')) {
15506 return tag;
15507 }
15508 if (parser.match('{')) {
15509 return mustache;
15510 }
15511 return text;
15512 }
15513
15514 function getLocator(source, options) {
15515 if (options === void 0) { options = {}; }
15516 var offsetLine = options.offsetLine || 0;
15517 var offsetColumn = options.offsetColumn || 0;
15518 var originalLines = source.split('\n');
15519 var start = 0;
15520 var lineRanges = originalLines.map(function (line, i) {
15521 var end = start + line.length + 1;
15522 var range = { start: start, end: end, line: i };
15523 start = end;
15524 return range;
15525 });
15526 var i = 0;
15527 function rangeContains(range, index) {
15528 return range.start <= index && index < range.end;
15529 }
15530 function getLocation(range, index) {
15531 return { line: offsetLine + range.line, column: offsetColumn + index - range.start, character: index };
15532 }
15533 function locate(search, startIndex) {
15534 if (typeof search === 'string') {
15535 search = source.indexOf(search, startIndex || 0);
15536 }
15537 var range = lineRanges[i];
15538 var d = search >= range.end ? 1 : -1;
15539 while (range) {
15540 if (rangeContains(range, search))
15541 return getLocation(range, search);
15542 i += d;
15543 range = lineRanges[i];
15544 }
15545 }
15546 return locate;
15547 }
15548 function locate(source, search, options) {
15549 if (typeof options === 'number') {
15550 throw new Error('locate takes a { startIndex, offsetLine, offsetColumn } object as the third argument');
15551 }
15552 return getLocator(source, options)(search, options && options.startIndex);
15553 }
15554
15555 function tabs_to_spaces(str) {
15556 return str.replace(/^\t+/, match => match.split('\t').join(' '));
15557 }
15558 function get_code_frame(source, line, column) {
15559 const lines = source.split('\n');
15560 const frame_start = Math.max(0, line - 2);
15561 const frame_end = Math.min(line + 3, lines.length);
15562 const digits = String(frame_end + 1).length;
15563 return lines
15564 .slice(frame_start, frame_end)
15565 .map((str, i) => {
15566 const isErrorLine = frame_start + i === line;
15567 const line_num = String(i + frame_start + 1).padStart(digits, ' ');
15568 if (isErrorLine) {
15569 const indicator = ' '.repeat(digits + 2 + tabs_to_spaces(str.slice(0, column)).length) + '^';
15570 return `${line_num}: ${tabs_to_spaces(str)}\n${indicator}`;
15571 }
15572 return `${line_num}: ${tabs_to_spaces(str)}`;
15573 })
15574 .join('\n');
15575 }
15576
15577 class CompileError extends Error {
15578 toString() {
15579 return `${this.message} (${this.start.line}:${this.start.column})\n${this.frame}`;
15580 }
15581 }
15582 function error$1(message, props) {
15583 const error = new CompileError(message);
15584 error.name = props.name;
15585 const start = locate(props.source, props.start, { offsetLine: 1 });
15586 const end = locate(props.source, props.end || props.start, { offsetLine: 1 });
15587 error.code = props.code;
15588 error.start = start;
15589 error.end = end;
15590 error.pos = props.start;
15591 error.filename = props.filename;
15592 error.frame = get_code_frame(props.source, start.line - 1, start.column);
15593 throw error;
15594 }
15595
15596 class Parser$1 {
15597 constructor(template, options) {
15598 this.index = 0;
15599 this.stack = [];
15600 this.css = [];
15601 this.js = [];
15602 this.meta_tags = {};
15603 if (typeof template !== 'string') {
15604 throw new TypeError('Template must be a string');
15605 }
15606 this.template = template.replace(/\s+$/, '');
15607 this.filename = options.filename;
15608 this.customElement = options.customElement;
15609 this.html = {
15610 start: null,
15611 end: null,
15612 type: 'Fragment',
15613 children: [],
15614 };
15615 this.stack.push(this.html);
15616 let state = fragment;
15617 while (this.index < this.template.length) {
15618 state = state(this) || fragment;
15619 }
15620 if (this.stack.length > 1) {
15621 const current = this.current();
15622 const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
15623 const slug = current.type === 'Element' ? 'element' : 'block';
15624 this.error({
15625 code: `unclosed-${slug}`,
15626 message: `${type} was left open`
15627 }, current.start);
15628 }
15629 if (state !== fragment) {
15630 this.error({
15631 code: `unexpected-eof`,
15632 message: 'Unexpected end of input'
15633 });
15634 }
15635 if (this.html.children.length) {
15636 let start = this.html.children[0].start;
15637 while (whitespace.test(template[start]))
15638 start += 1;
15639 let end = this.html.children[this.html.children.length - 1].end;
15640 while (whitespace.test(template[end - 1]))
15641 end -= 1;
15642 this.html.start = start;
15643 this.html.end = end;
15644 }
15645 else {
15646 this.html.start = this.html.end = null;
15647 }
15648 }
15649 current() {
15650 return this.stack[this.stack.length - 1];
15651 }
15652 acorn_error(err) {
15653 this.error({
15654 code: `parse-error`,
15655 message: err.message.replace(/ \(\d+:\d+\)$/, '')
15656 }, err.pos);
15657 }
15658 error({ code, message }, index = this.index) {
15659 error$1(message, {
15660 name: 'ParseError',
15661 code,
15662 source: this.template,
15663 start: index,
15664 filename: this.filename
15665 });
15666 }
15667 eat(str, required, message) {
15668 if (this.match(str)) {
15669 this.index += str.length;
15670 return true;
15671 }
15672 if (required) {
15673 this.error({
15674 code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`,
15675 message: message || `Expected ${str}`
15676 });
15677 }
15678 return false;
15679 }
15680 match(str) {
15681 return this.template.slice(this.index, this.index + str.length) === str;
15682 }
15683 match_regex(pattern) {
15684 const match = pattern.exec(this.template.slice(this.index));
15685 if (!match || match.index !== 0)
15686 return null;
15687 return match[0];
15688 }
15689 allow_whitespace() {
15690 while (this.index < this.template.length &&
15691 whitespace.test(this.template[this.index])) {
15692 this.index++;
15693 }
15694 }
15695 read(pattern) {
15696 const result = this.match_regex(pattern);
15697 if (result)
15698 this.index += result.length;
15699 return result;
15700 }
15701 read_identifier(allow_reserved = false) {
15702 const start = this.index;
15703 let i = this.index;
15704 const code = full_char_code_at(this.template, i);
15705 if (!isIdentifierStart(code, true))
15706 return null;
15707 i += code <= 0xffff ? 1 : 2;
15708 while (i < this.template.length) {
15709 const code = full_char_code_at(this.template, i);
15710 if (!isIdentifierChar(code, true))
15711 break;
15712 i += code <= 0xffff ? 1 : 2;
15713 }
15714 const identifier = this.template.slice(this.index, this.index = i);
15715 if (!allow_reserved && reserved.has(identifier)) {
15716 this.error({
15717 code: `unexpected-reserved-word`,
15718 message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`
15719 }, start);
15720 }
15721 return identifier;
15722 }
15723 read_until(pattern) {
15724 if (this.index >= this.template.length)
15725 this.error({
15726 code: `unexpected-eof`,
15727 message: 'Unexpected end of input'
15728 });
15729 const start = this.index;
15730 const match = pattern.exec(this.template.slice(start));
15731 if (match) {
15732 this.index = start + match.index;
15733 return this.template.slice(start, this.index);
15734 }
15735 this.index = this.template.length;
15736 return this.template.slice(start);
15737 }
15738 require_whitespace() {
15739 if (!whitespace.test(this.template[this.index])) {
15740 this.error({
15741 code: `missing-whitespace`,
15742 message: `Expected whitespace`
15743 });
15744 }
15745 this.allow_whitespace();
15746 }
15747 }
15748 function parse$3(template, options = {}) {
15749 const parser = new Parser$1(template, options);
15750 // TODO we may want to allow multiple <style> tags —
15751 // one scoped, one global. for now, only allow one
15752 if (parser.css.length > 1) {
15753 parser.error({
15754 code: 'duplicate-style',
15755 message: 'You can only have one top-level <style> tag per component'
15756 }, parser.css[1].start);
15757 }
15758 const instance_scripts = parser.js.filter(script => script.context === 'default');
15759 const module_scripts = parser.js.filter(script => script.context === 'module');
15760 if (instance_scripts.length > 1) {
15761 parser.error({
15762 code: `invalid-script`,
15763 message: `A component can only have one instance-level <script> element`
15764 }, instance_scripts[1].start);
15765 }
15766 if (module_scripts.length > 1) {
15767 parser.error({
15768 code: `invalid-script`,
15769 message: `A component can only have one <script context="module"> element`
15770 }, module_scripts[1].start);
15771 }
15772 return {
15773 html: parser.html,
15774 css: parser.css[0],
15775 instance: instance_scripts[0],
15776 module: module_scripts[0]
15777 };
15778 }
15779
15780 function is_head(node) {
15781 return node && node.type === 'MemberExpression' && node.object.name === '@_document' && node.property.name === 'head';
15782 }
15783
15784 class Block$1 {
15785 constructor(options) {
15786 this.dependencies = new Set();
15787 this.event_listeners = [];
15788 this.variables = new Map();
15789 this.has_update_method = false;
15790 this.parent = options.parent;
15791 this.renderer = options.renderer;
15792 this.name = options.name;
15793 this.type = options.type;
15794 this.comment = options.comment;
15795 this.wrappers = [];
15796 // for keyed each blocks
15797 this.key = options.key;
15798 this.first = null;
15799 this.bindings = options.bindings;
15800 this.chunks = {
15801 declarations: [],
15802 init: [],
15803 create: [],
15804 claim: [],
15805 hydrate: [],
15806 mount: [],
15807 measure: [],
15808 fix: [],
15809 animate: [],
15810 intro: [],
15811 update: [],
15812 outro: [],
15813 destroy: [],
15814 };
15815 this.has_animation = false;
15816 this.has_intro_method = false; // a block could have an intro method but not intro transitions, e.g. if a sibling block has intros
15817 this.has_outro_method = false;
15818 this.outros = 0;
15819 this.get_unique_name = this.renderer.component.get_unique_name_maker();
15820 this.aliases = new Map();
15821 if (this.key)
15822 this.aliases.set('key', this.get_unique_name('key'));
15823 }
15824 assign_variable_names() {
15825 const seen = new Set();
15826 const dupes = new Set();
15827 let i = this.wrappers.length;
15828 while (i--) {
15829 const wrapper = this.wrappers[i];
15830 if (!wrapper.var)
15831 continue;
15832 if (seen.has(wrapper.var.name)) {
15833 dupes.add(wrapper.var.name);
15834 }
15835 seen.add(wrapper.var.name);
15836 }
15837 const counts = new Map();
15838 i = this.wrappers.length;
15839 while (i--) {
15840 const wrapper = this.wrappers[i];
15841 if (!wrapper.var)
15842 continue;
15843 let suffix = '';
15844 if (dupes.has(wrapper.var.name)) {
15845 const i = counts.get(wrapper.var.name) || 0;
15846 counts.set(wrapper.var.name, i + 1);
15847 suffix = i;
15848 }
15849 wrapper.var.name = this.get_unique_name(wrapper.var.name + suffix).name;
15850 }
15851 }
15852 add_dependencies(dependencies) {
15853 dependencies.forEach(dependency => {
15854 this.dependencies.add(dependency);
15855 });
15856 this.has_update_method = true;
15857 if (this.parent) {
15858 this.parent.add_dependencies(dependencies);
15859 }
15860 }
15861 add_element(id, render_statement, claim_statement, parent_node, no_detach) {
15862 this.add_variable(id);
15863 this.chunks.create.push(b `${id} = ${render_statement};`);
15864 if (this.renderer.options.hydratable) {
15865 this.chunks.claim.push(b `${id} = ${claim_statement || render_statement};`);
15866 }
15867 if (parent_node) {
15868 this.chunks.mount.push(b `@append(${parent_node}, ${id});`);
15869 if (is_head(parent_node) && !no_detach)
15870 this.chunks.destroy.push(b `@detach(${id});`);
15871 }
15872 else {
15873 this.chunks.mount.push(b `@insert(#target, ${id}, #anchor);`);
15874 if (!no_detach)
15875 this.chunks.destroy.push(b `if (detaching) @detach(${id});`);
15876 }
15877 }
15878 add_intro(local) {
15879 this.has_intros = this.has_intro_method = true;
15880 if (!local && this.parent)
15881 this.parent.add_intro();
15882 }
15883 add_outro(local) {
15884 this.has_outros = this.has_outro_method = true;
15885 this.outros += 1;
15886 if (!local && this.parent)
15887 this.parent.add_outro();
15888 }
15889 add_animation() {
15890 this.has_animation = true;
15891 }
15892 add_variable(id, init) {
15893 if (this.variables.has(id.name)) {
15894 throw new Error(`Variable '${id.name}' already initialised with a different value`);
15895 }
15896 this.variables.set(id.name, { id, init });
15897 }
15898 alias(name) {
15899 if (!this.aliases.has(name)) {
15900 this.aliases.set(name, this.get_unique_name(name));
15901 }
15902 return this.aliases.get(name);
15903 }
15904 child(options) {
15905 return new Block$1(Object.assign({}, this, { key: null }, options, { parent: this }));
15906 }
15907 get_contents(key) {
15908 const { dev } = this.renderer.options;
15909 if (this.has_outros) {
15910 this.add_variable({ type: 'Identifier', name: '#current' });
15911 if (this.chunks.intro.length > 0) {
15912 this.chunks.intro.push(b `#current = true;`);
15913 this.chunks.mount.push(b `#current = true;`);
15914 }
15915 if (this.chunks.outro.length > 0) {
15916 this.chunks.outro.push(b `#current = false;`);
15917 }
15918 }
15919 if (this.autofocus) {
15920 this.chunks.mount.push(b `${this.autofocus}.focus();`);
15921 }
15922 this.render_listeners();
15923 const properties = {};
15924 const noop = x `@noop`;
15925 properties.key = key;
15926 if (this.first) {
15927 properties.first = x `null`;
15928 this.chunks.hydrate.push(b `this.first = ${this.first};`);
15929 }
15930 if (this.chunks.create.length === 0 && this.chunks.hydrate.length === 0) {
15931 properties.create = noop;
15932 }
15933 else {
15934 const hydrate = this.chunks.hydrate.length > 0 && (this.renderer.options.hydratable
15935 ? b `this.h();`
15936 : this.chunks.hydrate);
15937 properties.create = x `function #create() {
15938 ${this.chunks.create}
15939 ${hydrate}
15940 }`;
15941 }
15942 if (this.renderer.options.hydratable || this.chunks.claim.length > 0) {
15943 if (this.chunks.claim.length === 0 && this.chunks.hydrate.length === 0) {
15944 properties.claim = noop;
15945 }
15946 else {
15947 properties.claim = x `function #claim(#nodes) {
15948 ${this.chunks.claim}
15949 ${this.renderer.options.hydratable && this.chunks.hydrate.length > 0 && b `this.h();`}
15950 }`;
15951 }
15952 }
15953 if (this.renderer.options.hydratable && this.chunks.hydrate.length > 0) {
15954 properties.hydrate = x `function #hydrate() {
15955 ${this.chunks.hydrate}
15956 }`;
15957 }
15958 if (this.chunks.mount.length === 0) {
15959 properties.mount = noop;
15960 }
15961 else if (this.event_listeners.length === 0) {
15962 properties.mount = x `function #mount(#target, #anchor) {
15963 ${this.chunks.mount}
15964 }`;
15965 }
15966 else {
15967 properties.mount = x `function #mount(#target, #anchor) {
15968 ${this.chunks.mount}
15969 }`;
15970 }
15971 if (this.has_update_method || this.maintain_context) {
15972 if (this.chunks.update.length === 0 && !this.maintain_context) {
15973 properties.update = noop;
15974 }
15975 else {
15976 const ctx = this.maintain_context ? x `#new_ctx` : x `#ctx`;
15977 let dirty = { type: 'Identifier', name: '#dirty' };
15978 if (!this.renderer.context_overflow && !this.parent) {
15979 dirty = { type: 'ArrayPattern', elements: [dirty] };
15980 }
15981 properties.update = x `function #update(${ctx}, ${dirty}) {
15982 ${this.maintain_context && b `#ctx = ${ctx};`}
15983 ${this.chunks.update}
15984 }`;
15985 }
15986 }
15987 if (this.has_animation) {
15988 properties.measure = x `function #measure() {
15989 ${this.chunks.measure}
15990 }`;
15991 properties.fix = x `function #fix() {
15992 ${this.chunks.fix}
15993 }`;
15994 properties.animate = x `function #animate() {
15995 ${this.chunks.animate}
15996 }`;
15997 }
15998 if (this.has_intro_method || this.has_outro_method) {
15999 if (this.chunks.intro.length === 0) {
16000 properties.intro = noop;
16001 }
16002 else {
16003 properties.intro = x `function #intro(#local) {
16004 ${this.has_outros && b `if (#current) return;`}
16005 ${this.chunks.intro}
16006 }`;
16007 }
16008 if (this.chunks.outro.length === 0) {
16009 properties.outro = noop;
16010 }
16011 else {
16012 properties.outro = x `function #outro(#local) {
16013 ${this.chunks.outro}
16014 }`;
16015 }
16016 }
16017 if (this.chunks.destroy.length === 0) {
16018 properties.destroy = noop;
16019 }
16020 else {
16021 properties.destroy = x `function #destroy(detaching) {
16022 ${this.chunks.destroy}
16023 }`;
16024 }
16025 if (!this.renderer.component.compile_options.dev) {
16026 // allow shorthand names
16027 for (const name in properties) {
16028 const property = properties[name];
16029 if (property)
16030 property.id = null;
16031 }
16032 }
16033 const return_value = x `{
16034 key: ${properties.key},
16035 first: ${properties.first},
16036 c: ${properties.create},
16037 l: ${properties.claim},
16038 h: ${properties.hydrate},
16039 m: ${properties.mount},
16040 p: ${properties.update},
16041 r: ${properties.measure},
16042 f: ${properties.fix},
16043 a: ${properties.animate},
16044 i: ${properties.intro},
16045 o: ${properties.outro},
16046 d: ${properties.destroy}
16047 }`;
16048 const block = dev && this.get_unique_name('block');
16049 const body = b `
16050 ${this.chunks.declarations}
16051
16052 ${Array.from(this.variables.values()).map(({ id, init }) => {
16053 return init
16054 ? b `let ${id} = ${init}`
16055 : b `let ${id}`;
16056 })}
16057
16058 ${this.chunks.init}
16059
16060 ${dev
16061 ? b `
16062 const ${block} = ${return_value};
16063 @dispatch_dev("SvelteRegisterBlock", {
16064 block: ${block},
16065 id: ${this.name || 'create_fragment'}.name,
16066 type: "${this.type}",
16067 source: "${this.comment ? this.comment.replace(/"/g, '\\"') : ''}",
16068 ctx: #ctx
16069 });
16070 return ${block};`
16071 : b `
16072 return ${return_value};`}
16073 `;
16074 return body;
16075 }
16076 has_content() {
16077 return !!this.first ||
16078 this.event_listeners.length > 0 ||
16079 this.chunks.intro.length > 0 ||
16080 this.chunks.outro.length > 0 ||
16081 this.chunks.create.length > 0 ||
16082 this.chunks.hydrate.length > 0 ||
16083 this.chunks.claim.length > 0 ||
16084 this.chunks.mount.length > 0 ||
16085 this.chunks.update.length > 0 ||
16086 this.chunks.destroy.length > 0 ||
16087 this.has_animation;
16088 }
16089 render() {
16090 const key = this.key && this.get_unique_name('key');
16091 const args = [x `#ctx`];
16092 if (key)
16093 args.unshift(key);
16094 const fn = b `function ${this.name}(${args}) {
16095 ${this.get_contents(key)}
16096 }`;
16097 return this.comment
16098 ? b `
16099 // ${this.comment}
16100 ${fn}`
16101 : fn;
16102 }
16103 render_listeners(chunk = '') {
16104 if (this.event_listeners.length > 0) {
16105 this.add_variable({ type: 'Identifier', name: '#mounted' });
16106 this.chunks.destroy.push(b `#mounted = false`);
16107 const dispose = {
16108 type: 'Identifier',
16109 name: `#dispose${chunk}`
16110 };
16111 this.add_variable(dispose);
16112 if (this.event_listeners.length === 1) {
16113 this.chunks.mount.push(b `
16114 if (!#mounted) {
16115 ${dispose} = ${this.event_listeners[0]};
16116 #mounted = true;
16117 }
16118 `);
16119 this.chunks.destroy.push(b `${dispose}();`);
16120 }
16121 else {
16122 this.chunks.mount.push(b `
16123 if (!#mounted) {
16124 ${dispose} = [
16125 ${this.event_listeners}
16126 ];
16127 #mounted = true;
16128 }
16129 `);
16130 this.chunks.destroy.push(b `@run_all(${dispose});`);
16131 }
16132 }
16133 }
16134 }
16135
16136 class Wrapper {
16137 constructor(renderer, block, parent, node) {
16138 this.node = node;
16139 // make these non-enumerable so that they can be logged sensibly
16140 // (TODO in dev only?)
16141 Object.defineProperties(this, {
16142 renderer: {
16143 value: renderer
16144 },
16145 parent: {
16146 value: parent
16147 }
16148 });
16149 this.can_use_innerhtml = !renderer.options.hydratable;
16150 this.is_static_content = !renderer.options.hydratable;
16151 block.wrappers.push(this);
16152 }
16153 cannot_use_innerhtml() {
16154 this.can_use_innerhtml = false;
16155 if (this.parent)
16156 this.parent.cannot_use_innerhtml();
16157 }
16158 not_static_content() {
16159 this.is_static_content = false;
16160 if (this.parent)
16161 this.parent.not_static_content();
16162 }
16163 get_or_create_anchor(block, parent_node, parent_nodes) {
16164 // TODO use this in EachBlock and IfBlock — tricky because
16165 // children need to be created first
16166 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
16167 const anchor = needs_anchor
16168 ? block.get_unique_name(`${this.var.name}_anchor`)
16169 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16170 if (needs_anchor) {
16171 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16172 }
16173 return anchor;
16174 }
16175 get_update_mount_node(anchor) {
16176 return ((this.parent && this.parent.is_dom_node())
16177 ? this.parent.var
16178 : x `${anchor}.parentNode`);
16179 }
16180 is_dom_node() {
16181 return (this.node.type === 'Element' ||
16182 this.node.type === 'Text' ||
16183 this.node.type === 'MustacheTag');
16184 }
16185 render(_block, _parent_node, _parent_nodes) {
16186 throw Error('Wrapper class is not renderable');
16187 }
16188 }
16189
16190 function create_debugging_comment(node, component) {
16191 const { locate, source } = component;
16192 let c = node.start;
16193 if (node.type === 'ElseBlock') {
16194 while (source[c - 1] !== '{')
16195 c -= 1;
16196 while (source[c - 1] === '{')
16197 c -= 1;
16198 }
16199 let d;
16200 if (node.type === 'InlineComponent' || node.type === 'Element') {
16201 if (node.children.length) {
16202 d = node.children[0].start;
16203 while (source[d - 1] !== '>')
16204 d -= 1;
16205 }
16206 else {
16207 d = node.start;
16208 while (source[d] !== '>')
16209 d += 1;
16210 d += 1;
16211 }
16212 }
16213 else if (node.type === 'Text' || node.type === 'Comment') {
16214 d = node.end;
16215 }
16216 else {
16217 // @ts-ignore
16218 d = node.expression ? node.expression.node.end : c;
16219 while (source[d] !== '}')
16220 d += 1;
16221 while (source[d] === '}')
16222 d += 1;
16223 }
16224 const start = locate(c);
16225 const loc = `(${start.line}:${start.column})`;
16226 return `${loc} ${source.slice(c, d)}`.replace(/\s/g, ' ');
16227 }
16228
16229 class AwaitBlockBranch extends Wrapper {
16230 constructor(status, renderer, block, parent, node, strip_whitespace, next_sibling) {
16231 super(renderer, block, parent, node);
16232 this.var = null;
16233 this.status = status;
16234 this.block = block.child({
16235 comment: create_debugging_comment(node, this.renderer.component),
16236 name: this.renderer.component.get_unique_name(`create_${status}_block`),
16237 type: status
16238 });
16239 this.add_context(parent.node[status + '_node'], parent.node[status + '_contexts']);
16240 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16241 this.is_dynamic = this.block.dependencies.size > 0;
16242 }
16243 add_context(node, contexts) {
16244 if (!node)
16245 return;
16246 if (node.type === 'Identifier') {
16247 this.value = node.name;
16248 this.renderer.add_to_context(this.value, true);
16249 }
16250 else {
16251 contexts.forEach(context => {
16252 this.renderer.add_to_context(context.key.name, true);
16253 });
16254 this.value = this.block.parent.get_unique_name('value').name;
16255 this.value_contexts = contexts;
16256 this.renderer.add_to_context(this.value, true);
16257 this.is_destructured = true;
16258 }
16259 this.value_index = this.renderer.context_lookup.get(this.value).index;
16260 }
16261 render(block, parent_node, parent_nodes) {
16262 this.fragment.render(block, parent_node, parent_nodes);
16263 if (this.is_destructured) {
16264 this.render_destructure();
16265 }
16266 }
16267 render_destructure() {
16268 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}]`)};`);
16269 const get_context = this.block.renderer.component.get_unique_name(`get_${this.status}_context`);
16270 this.block.renderer.blocks.push(b `
16271 function ${get_context}(#ctx) {
16272 ${props}
16273 }
16274 `);
16275 this.block.chunks.declarations.push(b `${get_context}(#ctx)`);
16276 if (this.block.has_update_method) {
16277 this.block.chunks.update.push(b `${get_context}(#ctx)`);
16278 }
16279 }
16280 }
16281 class AwaitBlockWrapper extends Wrapper {
16282 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16283 super(renderer, block, parent, node);
16284 this.var = { type: 'Identifier', name: 'await_block' };
16285 this.cannot_use_innerhtml();
16286 this.not_static_content();
16287 block.add_dependencies(this.node.expression.dependencies);
16288 let is_dynamic = false;
16289 let has_intros = false;
16290 let has_outros = false;
16291 ['pending', 'then', 'catch'].forEach((status) => {
16292 const child = this.node[status];
16293 const branch = new AwaitBlockBranch(status, renderer, block, this, child, strip_whitespace, next_sibling);
16294 renderer.blocks.push(branch.block);
16295 if (branch.is_dynamic) {
16296 is_dynamic = true;
16297 // TODO should blocks update their own parents?
16298 block.add_dependencies(branch.block.dependencies);
16299 }
16300 if (branch.block.has_intros)
16301 has_intros = true;
16302 if (branch.block.has_outros)
16303 has_outros = true;
16304 this[status] = branch;
16305 });
16306 ['pending', 'then', 'catch'].forEach(status => {
16307 this[status].block.has_update_method = is_dynamic;
16308 this[status].block.has_intro_method = has_intros;
16309 this[status].block.has_outro_method = has_outros;
16310 });
16311 if (has_outros) {
16312 block.add_outro();
16313 }
16314 }
16315 render(block, parent_node, parent_nodes) {
16316 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
16317 const update_mount_node = this.get_update_mount_node(anchor);
16318 const snippet = this.node.expression.manipulate(block);
16319 const info = block.get_unique_name(`info`);
16320 const promise = block.get_unique_name(`promise`);
16321 block.add_variable(promise);
16322 block.maintain_context = true;
16323 const info_props = x `{
16324 ctx: #ctx,
16325 current: null,
16326 token: null,
16327 pending: ${this.pending.block.name},
16328 then: ${this.then.block.name},
16329 catch: ${this.catch.block.name},
16330 value: ${this.then.value_index},
16331 error: ${this.catch.value_index},
16332 blocks: ${this.pending.block.has_outro_method && x `[,,,]`}
16333 }`;
16334 block.chunks.init.push(b `
16335 let ${info} = ${info_props};
16336 `);
16337 block.chunks.init.push(b `
16338 @handle_promise(${promise} = ${snippet}, ${info});
16339 `);
16340 block.chunks.create.push(b `
16341 ${info}.block.c();
16342 `);
16343 if (parent_nodes && this.renderer.options.hydratable) {
16344 block.chunks.claim.push(b `
16345 ${info}.block.l(${parent_nodes});
16346 `);
16347 }
16348 const initial_mount_node = parent_node || '#target';
16349 const anchor_node = parent_node ? 'null' : '#anchor';
16350 const has_transitions = this.pending.block.has_intro_method || this.pending.block.has_outro_method;
16351 block.chunks.mount.push(b `
16352 ${info}.block.m(${initial_mount_node}, ${info}.anchor = ${anchor_node});
16353 ${info}.mount = () => ${update_mount_node};
16354 ${info}.anchor = ${anchor};
16355 `);
16356 if (has_transitions) {
16357 block.chunks.intro.push(b `@transition_in(${info}.block);`);
16358 }
16359 const dependencies = this.node.expression.dynamic_dependencies();
16360 if (dependencies.length > 0) {
16361 const condition = x `
16362 ${block.renderer.dirty(dependencies)} &&
16363 ${promise} !== (${promise} = ${snippet}) &&
16364 @handle_promise(${promise}, ${info})`;
16365 block.chunks.update.push(b `${info}.ctx = #ctx;`);
16366 if (this.pending.block.has_update_method) {
16367 block.chunks.update.push(b `
16368 if (${condition}) {
16369
16370 } else {
16371 const #child_ctx = #ctx.slice();
16372 ${this.then.value && b `#child_ctx[${this.then.value_index}] = ${info}.resolved;`}
16373 ${info}.block.p(#child_ctx, #dirty);
16374 }
16375 `);
16376 }
16377 else {
16378 block.chunks.update.push(b `
16379 ${condition}
16380 `);
16381 }
16382 }
16383 else {
16384 if (this.pending.block.has_update_method) {
16385 block.chunks.update.push(b `
16386 {
16387 const #child_ctx = #ctx.slice();
16388 ${this.then.value && b `#child_ctx[${this.then.value_index}] = ${info}.resolved;`}
16389 ${info}.block.p(#child_ctx, #dirty);
16390 }
16391 `);
16392 }
16393 }
16394 if (this.pending.block.has_outro_method) {
16395 block.chunks.outro.push(b `
16396 for (let #i = 0; #i < 3; #i += 1) {
16397 const block = ${info}.blocks[#i];
16398 @transition_out(block);
16399 }
16400 `);
16401 }
16402 block.chunks.destroy.push(b `
16403 ${info}.block.d(${parent_node ? null : 'detaching'});
16404 ${info}.token = null;
16405 ${info} = null;
16406 `);
16407 [this.pending, this.then, this.catch].forEach(branch => {
16408 branch.render(branch.block, null, x `#nodes`);
16409 });
16410 }
16411 }
16412
16413 const TRUE = x `true`;
16414 const FALSE = x `false`;
16415 class EventHandlerWrapper {
16416 constructor(node, parent) {
16417 this.node = node;
16418 this.parent = parent;
16419 if (!node.expression) {
16420 this.parent.renderer.add_to_context(node.handler_name.name);
16421 this.parent.renderer.component.partly_hoisted.push(b `
16422 function ${node.handler_name.name}(event) {
16423 @bubble($$self, event);
16424 }
16425 `);
16426 }
16427 }
16428 get_snippet(block) {
16429 const snippet = this.node.expression ? this.node.expression.manipulate(block) : block.renderer.reference(this.node.handler_name);
16430 if (this.node.reassigned) {
16431 block.maintain_context = true;
16432 return x `function () { if (@is_function(${snippet})) ${snippet}.apply(this, arguments); }`;
16433 }
16434 return snippet;
16435 }
16436 render(block, target) {
16437 let snippet = this.get_snippet(block);
16438 if (this.node.modifiers.has('preventDefault'))
16439 snippet = x `@prevent_default(${snippet})`;
16440 if (this.node.modifiers.has('stopPropagation'))
16441 snippet = x `@stop_propagation(${snippet})`;
16442 if (this.node.modifiers.has('self'))
16443 snippet = x `@self(${snippet})`;
16444 const args = [];
16445 const opts = ['passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod));
16446 if (opts.length) {
16447 args.push((opts.length === 1 && opts[0] === 'capture')
16448 ? TRUE
16449 : x `{ ${opts.map(opt => p `${opt}: true`)} }`);
16450 }
16451 else if (block.renderer.options.dev) {
16452 args.push(FALSE);
16453 }
16454 if (block.renderer.options.dev) {
16455 args.push(this.node.modifiers.has('preventDefault') ? TRUE : FALSE);
16456 args.push(this.node.modifiers.has('stopPropagation') ? TRUE : FALSE);
16457 }
16458 block.event_listeners.push(x `@listen(${target}, "${this.node.name}", ${snippet}, ${args})`);
16459 }
16460 }
16461
16462 function add_event_handlers(block, target, handlers) {
16463 handlers.forEach(handler => add_event_handler(block, target, handler));
16464 }
16465 function add_event_handler(block, target, handler) {
16466 handler.render(block, target);
16467 }
16468
16469 class BodyWrapper extends Wrapper {
16470 constructor(renderer, block, parent, node) {
16471 super(renderer, block, parent, node);
16472 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
16473 }
16474 render(block, _parent_node, _parent_nodes) {
16475 add_event_handlers(block, x `@_document.body`, this.handlers);
16476 }
16477 }
16478
16479 function add_to_set(a, b) {
16480 // @ts-ignore
16481 b.forEach(item => {
16482 a.add(item);
16483 });
16484 }
16485
16486 class DebugTagWrapper extends Wrapper {
16487 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
16488 super(renderer, block, parent, node);
16489 }
16490 render(block, _parent_node, _parent_nodes) {
16491 const { renderer } = this;
16492 const { component } = renderer;
16493 if (!renderer.options.dev)
16494 return;
16495 const { var_lookup } = component;
16496 const start = component.locate(this.node.start + 1);
16497 const end = { line: start.line, column: start.column + 6 };
16498 const loc = { start, end };
16499 const debug = {
16500 type: 'DebuggerStatement',
16501 loc
16502 };
16503 if (this.node.expressions.length === 0) {
16504 // Debug all
16505 block.chunks.create.push(debug);
16506 block.chunks.update.push(debug);
16507 }
16508 else {
16509 const log = {
16510 type: 'Identifier',
16511 name: 'log',
16512 loc
16513 };
16514 const dependencies = new Set();
16515 this.node.expressions.forEach(expression => {
16516 add_to_set(dependencies, expression.dependencies);
16517 });
16518 const contextual_identifiers = this.node.expressions
16519 .filter(e => {
16520 const variable = var_lookup.get(e.node.name);
16521 return !(variable && variable.hoistable);
16522 })
16523 .map(e => e.node.name);
16524 const logged_identifiers = this.node.expressions.map(e => p `${e.node.name}`);
16525 const debug_statements = b `
16526 ${contextual_identifiers.map(name => b `const ${name} = ${renderer.reference(name)};`)}
16527 @_console.${log}({ ${logged_identifiers} });
16528 debugger;`;
16529 if (dependencies.size) {
16530 const condition = renderer.dirty(Array.from(dependencies));
16531 block.chunks.update.push(b `
16532 if (${condition}) {
16533 ${debug_statements}
16534 }
16535 `);
16536 }
16537 block.chunks.create.push(b `{
16538 ${debug_statements}
16539 }`);
16540 }
16541 }
16542 }
16543
16544 class ElseBlockWrapper extends Wrapper {
16545 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16546 super(renderer, block, parent, node);
16547 this.var = null;
16548 this.block = block.child({
16549 comment: create_debugging_comment(node, this.renderer.component),
16550 name: this.renderer.component.get_unique_name(`create_else_block`),
16551 type: 'else'
16552 });
16553 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16554 this.is_dynamic = this.block.dependencies.size > 0;
16555 }
16556 }
16557 class EachBlockWrapper extends Wrapper {
16558 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16559 super(renderer, block, parent, node);
16560 this.updates = [];
16561 this.var = { type: 'Identifier', name: 'each' };
16562 this.cannot_use_innerhtml();
16563 this.not_static_content();
16564 const { dependencies } = node.expression;
16565 block.add_dependencies(dependencies);
16566 this.node.contexts.forEach(context => {
16567 renderer.add_to_context(context.key.name, true);
16568 });
16569 this.block = block.child({
16570 comment: create_debugging_comment(this.node, this.renderer.component),
16571 name: renderer.component.get_unique_name('create_each_block'),
16572 type: 'each',
16573 // @ts-ignore todo: probably error
16574 key: node.key,
16575 bindings: new Map(block.bindings)
16576 });
16577 // TODO this seems messy
16578 this.block.has_animation = this.node.has_animation;
16579 this.index_name = this.node.index
16580 ? { type: 'Identifier', name: this.node.index }
16581 : renderer.component.get_unique_name(`${this.node.context}_index`);
16582 const fixed_length = node.expression.node.type === 'ArrayExpression' &&
16583 node.expression.node.elements.every(element => element.type !== 'SpreadElement')
16584 ? node.expression.node.elements.length
16585 : null;
16586 // hack the sourcemap, so that if data is missing the bug
16587 // is easy to find
16588 let c = this.node.start + 2;
16589 while (renderer.component.source[c] !== 'e')
16590 c += 1;
16591 const start = renderer.component.locate(c);
16592 const end = { line: start.line, column: start.column + 4 };
16593 const length = {
16594 type: 'Identifier',
16595 name: 'length',
16596 loc: { start, end }
16597 };
16598 const each_block_value = renderer.component.get_unique_name(`${this.var.name}_value`);
16599 const iterations = block.get_unique_name(`${this.var.name}_blocks`);
16600 renderer.add_to_context(each_block_value.name, true);
16601 renderer.add_to_context(this.index_name.name, true);
16602 this.vars = {
16603 create_each_block: this.block.name,
16604 each_block_value,
16605 get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`),
16606 iterations,
16607 // optimisation for array literal
16608 fixed_length,
16609 data_length: fixed_length === null ? x `${each_block_value}.${length}` : fixed_length,
16610 view_length: fixed_length === null ? x `${iterations}.length` : fixed_length
16611 };
16612 const store = node.expression.node.type === 'Identifier' &&
16613 node.expression.node.name[0] === '$'
16614 ? node.expression.node.name.slice(1)
16615 : null;
16616 node.contexts.forEach(prop => {
16617 this.block.bindings.set(prop.key.name, {
16618 object: this.vars.each_block_value,
16619 property: this.index_name,
16620 modifier: prop.modifier,
16621 snippet: prop.modifier(x `${this.vars.each_block_value}[${this.index_name}]`),
16622 store,
16623 tail: prop.modifier(x `[${this.index_name}]`)
16624 });
16625 });
16626 if (this.node.index) {
16627 this.block.get_unique_name(this.node.index); // this prevents name collisions (#1254)
16628 }
16629 renderer.blocks.push(this.block);
16630 this.fragment = new FragmentWrapper(renderer, this.block, node.children, this, strip_whitespace, next_sibling);
16631 if (this.node.else) {
16632 this.else = new ElseBlockWrapper(renderer, block, this, this.node.else, strip_whitespace, next_sibling);
16633 renderer.blocks.push(this.else.block);
16634 if (this.else.is_dynamic) {
16635 this.block.add_dependencies(this.else.block.dependencies);
16636 }
16637 }
16638 block.add_dependencies(this.block.dependencies);
16639 if (this.block.has_outros || (this.else && this.else.block.has_outros)) {
16640 block.add_outro();
16641 }
16642 }
16643 render(block, parent_node, parent_nodes) {
16644 if (this.fragment.nodes.length === 0)
16645 return;
16646 const { renderer } = this;
16647 const { component } = renderer;
16648 const needs_anchor = this.next
16649 ? !this.next.is_dom_node() :
16650 !parent_node || !this.parent.is_dom_node();
16651 this.context_props = this.node.contexts.map(prop => b `child_ctx[${renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x `list[i]`)};`);
16652 if (this.node.has_binding)
16653 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`);
16654 if (this.node.has_binding || this.node.has_index_binding || this.node.index)
16655 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`);
16656 const snippet = this.node.expression.manipulate(block);
16657 block.chunks.init.push(b `let ${this.vars.each_block_value} = ${snippet};`);
16658 if (this.renderer.options.dev) {
16659 block.chunks.init.push(b `@validate_each_argument(${this.vars.each_block_value});`);
16660 }
16661 // TODO which is better — Object.create(array) or array.slice()?
16662 renderer.blocks.push(b `
16663 function ${this.vars.get_each_context}(#ctx, list, i) {
16664 const child_ctx = #ctx.slice();
16665 ${this.context_props}
16666 return child_ctx;
16667 }
16668 `);
16669 const initial_anchor_node = { type: 'Identifier', name: parent_node ? 'null' : '#anchor' };
16670 const initial_mount_node = parent_node || { type: 'Identifier', name: '#target' };
16671 const update_anchor_node = needs_anchor
16672 ? block.get_unique_name(`${this.var.name}_anchor`)
16673 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16674 const update_mount_node = this.get_update_mount_node(update_anchor_node);
16675 const args = {
16676 block,
16677 parent_node,
16678 parent_nodes,
16679 snippet,
16680 initial_anchor_node,
16681 initial_mount_node,
16682 update_anchor_node,
16683 update_mount_node
16684 };
16685 const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
16686 this.node.expression.dynamic_dependencies().forEach((dependency) => {
16687 all_dependencies.add(dependency);
16688 });
16689 this.dependencies = all_dependencies;
16690 if (this.node.key) {
16691 this.render_keyed(args);
16692 }
16693 else {
16694 this.render_unkeyed(args);
16695 }
16696 if (this.block.has_intro_method || this.block.has_outro_method) {
16697 block.chunks.intro.push(b `
16698 for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) {
16699 @transition_in(${this.vars.iterations}[#i]);
16700 }
16701 `);
16702 }
16703 if (needs_anchor) {
16704 block.add_element(update_anchor_node, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16705 }
16706 if (this.else) {
16707 const each_block_else = component.get_unique_name(`${this.var.name}_else`);
16708 block.chunks.init.push(b `let ${each_block_else} = null;`);
16709 // TODO neaten this up... will end up with an empty line in the block
16710 block.chunks.init.push(b `
16711 if (!${this.vars.data_length}) {
16712 ${each_block_else} = ${this.else.block.name}(#ctx);
16713 }
16714 `);
16715 block.chunks.create.push(b `
16716 if (${each_block_else}) {
16717 ${each_block_else}.c();
16718 }
16719 `);
16720 if (this.renderer.options.hydratable) {
16721 block.chunks.claim.push(b `
16722 if (${each_block_else}) {
16723 ${each_block_else}.l(${parent_nodes});
16724 }
16725 `);
16726 }
16727 block.chunks.mount.push(b `
16728 if (${each_block_else}) {
16729 ${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node});
16730 }
16731 `);
16732 if (this.else.block.has_update_method) {
16733 this.updates.push(b `
16734 if (!${this.vars.data_length} && ${each_block_else}) {
16735 ${each_block_else}.p(#ctx, #dirty);
16736 } else if (!${this.vars.data_length}) {
16737 ${each_block_else} = ${this.else.block.name}(#ctx);
16738 ${each_block_else}.c();
16739 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16740 } else if (${each_block_else}) {
16741 ${each_block_else}.d(1);
16742 ${each_block_else} = null;
16743 }
16744 `);
16745 }
16746 else {
16747 this.updates.push(b `
16748 if (${this.vars.data_length}) {
16749 if (${each_block_else}) {
16750 ${each_block_else}.d(1);
16751 ${each_block_else} = null;
16752 }
16753 } else if (!${each_block_else}) {
16754 ${each_block_else} = ${this.else.block.name}(#ctx);
16755 ${each_block_else}.c();
16756 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16757 }
16758 `);
16759 }
16760 block.chunks.destroy.push(b `
16761 if (${each_block_else}) ${each_block_else}.d(${parent_node ? '' : 'detaching'});
16762 `);
16763 }
16764 if (this.updates.length) {
16765 block.chunks.update.push(b `
16766 if (${block.renderer.dirty(Array.from(all_dependencies))}) {
16767 ${this.updates}
16768 }
16769 `);
16770 }
16771 this.fragment.render(this.block, null, x `#nodes`);
16772 if (this.else) {
16773 this.else.fragment.render(this.else.block, null, x `#nodes`);
16774 }
16775 }
16776 render_keyed({ block, parent_node, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
16777 const { create_each_block, iterations, data_length, view_length } = this.vars;
16778 const get_key = block.get_unique_name('get_key');
16779 const lookup = block.get_unique_name(`${this.var.name}_lookup`);
16780 block.add_variable(iterations, x `[]`);
16781 block.add_variable(lookup, x `new @_Map()`);
16782 if (this.fragment.nodes[0].is_dom_node()) {
16783 this.block.first = this.fragment.nodes[0].var;
16784 }
16785 else {
16786 this.block.first = this.block.get_unique_name('first');
16787 this.block.add_element(this.block.first, x `@empty()`, parent_nodes && x `@empty()`, null);
16788 }
16789 block.chunks.init.push(b `
16790 const ${get_key} = #ctx => ${this.node.key.manipulate(block)};
16791
16792 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
16793 for (let #i = 0; #i < ${data_length}; #i += 1) {
16794 let child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
16795 let key = ${get_key}(child_ctx);
16796 ${lookup}.set(key, ${iterations}[#i] = ${create_each_block}(key, child_ctx));
16797 }
16798 `);
16799 block.chunks.create.push(b `
16800 for (let #i = 0; #i < ${view_length}; #i += 1) {
16801 ${iterations}[#i].c();
16802 }
16803 `);
16804 if (parent_nodes && this.renderer.options.hydratable) {
16805 block.chunks.claim.push(b `
16806 for (let #i = 0; #i < ${view_length}; #i += 1) {
16807 ${iterations}[#i].l(${parent_nodes});
16808 }
16809 `);
16810 }
16811 block.chunks.mount.push(b `
16812 for (let #i = 0; #i < ${view_length}; #i += 1) {
16813 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
16814 }
16815 `);
16816 const dynamic = this.block.has_update_method;
16817 const destroy = this.node.has_animation
16818 ? (this.block.has_outros
16819 ? `@fix_and_outro_and_destroy_block`
16820 : `@fix_and_destroy_block`)
16821 : this.block.has_outros
16822 ? `@outro_and_destroy_block`
16823 : `@destroy_block`;
16824 if (this.dependencies.size) {
16825 this.updates.push(b `
16826 const ${this.vars.each_block_value} = ${snippet};
16827 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
16828
16829 ${this.block.has_outros && b `@group_outros();`}
16830 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`}
16831 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
16832 ${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});
16833 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
16834 ${this.block.has_outros && b `@check_outros();`}
16835 `);
16836 }
16837 if (this.block.has_outros) {
16838 block.chunks.outro.push(b `
16839 for (let #i = 0; #i < ${view_length}; #i += 1) {
16840 @transition_out(${iterations}[#i]);
16841 }
16842 `);
16843 }
16844 block.chunks.destroy.push(b `
16845 for (let #i = 0; #i < ${view_length}; #i += 1) {
16846 ${iterations}[#i].d(${parent_node ? null : 'detaching'});
16847 }
16848 `);
16849 }
16850 render_unkeyed({ block, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
16851 const { create_each_block, iterations, fixed_length, data_length, view_length } = this.vars;
16852 block.chunks.init.push(b `
16853 let ${iterations} = [];
16854
16855 for (let #i = 0; #i < ${data_length}; #i += 1) {
16856 ${iterations}[#i] = ${create_each_block}(${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i));
16857 }
16858 `);
16859 block.chunks.create.push(b `
16860 for (let #i = 0; #i < ${view_length}; #i += 1) {
16861 ${iterations}[#i].c();
16862 }
16863 `);
16864 if (parent_nodes && this.renderer.options.hydratable) {
16865 block.chunks.claim.push(b `
16866 for (let #i = 0; #i < ${view_length}; #i += 1) {
16867 ${iterations}[#i].l(${parent_nodes});
16868 }
16869 `);
16870 }
16871 block.chunks.mount.push(b `
16872 for (let #i = 0; #i < ${view_length}; #i += 1) {
16873 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
16874 }
16875 `);
16876 if (this.dependencies.size) {
16877 const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
16878 const for_loop_body = this.block.has_update_method
16879 ? b `
16880 if (${iterations}[#i]) {
16881 ${iterations}[#i].p(child_ctx, #dirty);
16882 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
16883 } else {
16884 ${iterations}[#i] = ${create_each_block}(child_ctx);
16885 ${iterations}[#i].c();
16886 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
16887 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16888 }
16889 `
16890 : has_transitions
16891 ? b `
16892 if (${iterations}[#i]) {
16893 @transition_in(${this.vars.iterations}[#i], 1);
16894 } else {
16895 ${iterations}[#i] = ${create_each_block}(child_ctx);
16896 ${iterations}[#i].c();
16897 @transition_in(${this.vars.iterations}[#i], 1);
16898 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16899 }
16900 `
16901 : b `
16902 if (!${iterations}[#i]) {
16903 ${iterations}[#i] = ${create_each_block}(child_ctx);
16904 ${iterations}[#i].c();
16905 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16906 }
16907 `;
16908 const start = this.block.has_update_method ? 0 : `#old_length`;
16909 let remove_old_blocks;
16910 if (this.block.has_outros) {
16911 const out = block.get_unique_name('out');
16912 block.chunks.init.push(b `
16913 const ${out} = i => @transition_out(${iterations}[i], 1, 1, () => {
16914 ${iterations}[i] = null;
16915 });
16916 `);
16917 remove_old_blocks = b `
16918 @group_outros();
16919 for (#i = ${data_length}; #i < ${view_length}; #i += 1) {
16920 ${out}(#i);
16921 }
16922 @check_outros();
16923 `;
16924 }
16925 else {
16926 remove_old_blocks = b `
16927 for (${this.block.has_update_method ? null : x `#i = ${data_length}`}; #i < ${this.block.has_update_method ? view_length : '#old_length'}; #i += 1) {
16928 ${iterations}[#i].d(1);
16929 }
16930 ${!fixed_length && b `${view_length} = ${data_length};`}
16931 `;
16932 }
16933 // We declare `i` as block scoped here, as the `remove_old_blocks` code
16934 // may rely on continuing where this iteration stopped.
16935 const update = b `
16936 ${!this.block.has_update_method && b `const #old_length = ${this.vars.each_block_value}.length;`}
16937 ${this.vars.each_block_value} = ${snippet};
16938 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
16939
16940 let #i;
16941 for (#i = ${start}; #i < ${data_length}; #i += 1) {
16942 const child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
16943
16944 ${for_loop_body}
16945 }
16946
16947 ${remove_old_blocks}
16948 `;
16949 this.updates.push(update);
16950 }
16951 if (this.block.has_outros) {
16952 block.chunks.outro.push(b `
16953 ${iterations} = ${iterations}.filter(@_Boolean);
16954 for (let #i = 0; #i < ${view_length}; #i += 1) {
16955 @transition_out(${iterations}[#i]);
16956 }
16957 `);
16958 }
16959 block.chunks.destroy.push(b `@destroy_each(${iterations}, detaching);`);
16960 }
16961 }
16962
16963 function string_literal(data) {
16964 return {
16965 type: 'Literal',
16966 value: data
16967 };
16968 }
16969 const escaped = {
16970 '"': '&quot;',
16971 "'": '&#39;',
16972 '&': '&amp;',
16973 '<': '&lt;',
16974 '>': '&gt;',
16975 };
16976 function escape_html(html) {
16977 return String(html).replace(/["'&<>]/g, match => escaped[match]);
16978 }
16979 function escape_template(str) {
16980 return str.replace(/(\${|`|\\)/g, '\\$1');
16981 }
16982
16983 class TextWrapper extends Wrapper {
16984 constructor(renderer, block, parent, node, data) {
16985 super(renderer, block, parent, node);
16986 this.skip = this.node.should_skip();
16987 this.data = data;
16988 this.var = (this.skip ? null : x `t`);
16989 }
16990 use_space() {
16991 if (this.renderer.component.component_options.preserveWhitespace)
16992 return false;
16993 if (/[\S\u00A0]/.test(this.data))
16994 return false;
16995 let node = this.parent && this.parent.node;
16996 while (node) {
16997 if (node.type === 'Element' && node.name === 'pre') {
16998 return false;
16999 }
17000 node = node.parent;
17001 }
17002 return true;
17003 }
17004 render(block, parent_node, parent_nodes) {
17005 if (this.skip)
17006 return;
17007 const use_space = this.use_space();
17008 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);
17009 }
17010 }
17011
17012 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(' ');
17013 const svg_attribute_lookup = new Map();
17014 svg_attributes.forEach(name => {
17015 svg_attribute_lookup.set(name.toLowerCase(), name);
17016 });
17017 function fix_attribute_casing(name) {
17018 name = name.toLowerCase();
17019 return svg_attribute_lookup.get(name) || name;
17020 }
17021
17022 const html = 'http://www.w3.org/1999/xhtml';
17023 const mathml = 'http://www.w3.org/1998/Math/MathML';
17024 const svg = 'http://www.w3.org/2000/svg';
17025 const xlink = 'http://www.w3.org/1999/xlink';
17026 const xml = 'http://www.w3.org/XML/1998/namespace';
17027 const xmlns = 'http://www.w3.org/2000/xmlns';
17028 const valid_namespaces = [
17029 'html',
17030 'mathml',
17031 'svg',
17032 'xlink',
17033 'xml',
17034 'xmlns',
17035 html,
17036 mathml,
17037 svg,
17038 xlink,
17039 xml,
17040 xmlns,
17041 ];
17042 const namespaces = { html, mathml, svg, xlink, xml, xmlns };
17043
17044 function handle_select_value_binding(attr, dependencies) {
17045 const { parent } = attr;
17046 if (parent.node.name === "select") {
17047 parent.select_binding_dependencies = dependencies;
17048 dependencies.forEach((prop) => {
17049 parent.renderer.component.indirect_dependencies.set(prop, new Set());
17050 });
17051 }
17052 }
17053
17054 class BaseAttributeWrapper {
17055 constructor(parent, block, node) {
17056 this.node = node;
17057 this.parent = parent;
17058 if (node.dependencies.size > 0) {
17059 parent.cannot_use_innerhtml();
17060 parent.not_static_content();
17061 block.add_dependencies(node.dependencies);
17062 }
17063 }
17064 render(_block) { }
17065 }
17066 class AttributeWrapper extends BaseAttributeWrapper {
17067 constructor(parent, block, node) {
17068 super(parent, block, node);
17069 if (node.dependencies.size > 0) {
17070 // special case — <option value={foo}> — see below
17071 if (this.parent.node.name === 'option' && node.name === 'value') {
17072 let select = this.parent;
17073 while (select && (select.node.type !== 'Element' || select.node.name !== 'select'))
17074 // @ts-ignore todo: doublecheck this, but looks to be correct
17075 select = select.parent;
17076 if (select && select.select_binding_dependencies) {
17077 select.select_binding_dependencies.forEach(prop => {
17078 this.node.dependencies.forEach((dependency) => {
17079 this.parent.renderer.component.indirect_dependencies.get(prop).add(dependency);
17080 });
17081 });
17082 }
17083 }
17084 if (node.name === 'value') {
17085 handle_select_value_binding(this, node.dependencies);
17086 }
17087 }
17088 this.name = fix_attribute_casing(this.node.name);
17089 this.metadata = this.get_metadata();
17090 this.is_indirectly_bound_value = is_indirectly_bound_value(this);
17091 this.property_name = this.is_indirectly_bound_value
17092 ? '__value'
17093 : this.metadata && this.metadata.property_name;
17094 this.is_src = this.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
17095 this.is_select_value_attribute = this.name === 'value' && this.parent.node.name === 'select';
17096 this.is_input_value = this.name === 'value' && this.parent.node.name === 'input';
17097 this.should_cache = should_cache(this);
17098 }
17099 render(block) {
17100 const element = this.parent;
17101 const { name, property_name, should_cache, is_indirectly_bound_value } = this;
17102 // xlink is a special case... we could maybe extend this to generic
17103 // namespaced attributes but I'm not sure that's applicable in
17104 // HTML5?
17105 const method = /-/.test(element.node.name)
17106 ? '@set_custom_element_data'
17107 : name.slice(0, 6) === 'xlink:'
17108 ? '@xlink_attr'
17109 : '@attr';
17110 const is_legacy_input_type = element.renderer.component.compile_options.legacy && name === 'type' && this.parent.node.name === 'input';
17111 const dependencies = this.get_dependencies();
17112 const value = this.get_value(block);
17113 let updater;
17114 const init = this.get_init(block, value);
17115 if (is_legacy_input_type) {
17116 block.chunks.hydrate.push(b `@set_input_type(${element.var}, ${init});`);
17117 updater = b `@set_input_type(${element.var}, ${should_cache ? this.last : value});`;
17118 }
17119 else if (this.is_select_value_attribute) {
17120 // annoying special case
17121 const is_multiple_select = element.node.get_static_attribute_value('multiple');
17122 if (is_multiple_select) {
17123 updater = b `@select_options(${element.var}, ${value});`;
17124 }
17125 else {
17126 updater = b `@select_option(${element.var}, ${value});`;
17127 }
17128 block.chunks.mount.push(b `
17129 ${updater}
17130 `);
17131 }
17132 else if (this.is_src) {
17133 block.chunks.hydrate.push(b `if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${this.last});`);
17134 updater = b `${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
17135 }
17136 else if (property_name) {
17137 block.chunks.hydrate.push(b `${element.var}.${property_name} = ${init};`);
17138 updater = block.renderer.options.dev
17139 ? b `@prop_dev(${element.var}, "${property_name}", ${should_cache ? this.last : value});`
17140 : b `${element.var}.${property_name} = ${should_cache ? this.last : value};`;
17141 }
17142 else {
17143 block.chunks.hydrate.push(b `${method}(${element.var}, "${name}", ${init});`);
17144 updater = b `${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
17145 }
17146 if (is_indirectly_bound_value) {
17147 const update_value = b `${element.var}.value = ${element.var}.__value;`;
17148 block.chunks.hydrate.push(update_value);
17149 updater = b `
17150 ${updater}
17151 ${update_value};
17152 `;
17153 }
17154 if (dependencies.length > 0) {
17155 const condition = this.get_dom_update_conditions(block, block.renderer.dirty(dependencies));
17156 block.chunks.update.push(b `
17157 if (${condition}) {
17158 ${updater}
17159 }`);
17160 }
17161 // special case – autofocus. has to be handled in a bit of a weird way
17162 if (this.node.is_true && name === 'autofocus') {
17163 block.autofocus = element.var;
17164 }
17165 }
17166 get_init(block, value) {
17167 this.last = this.should_cache && block.get_unique_name(`${this.parent.var.name}_${this.name.replace(/[^a-zA-Z_$]/g, '_')}_value`);
17168 if (this.should_cache)
17169 block.add_variable(this.last);
17170 return this.should_cache ? x `${this.last} = ${value}` : value;
17171 }
17172 get_dom_update_conditions(block, dependency_condition) {
17173 const { property_name, should_cache, last } = this;
17174 const element = this.parent;
17175 const value = this.get_value(block);
17176 let condition = dependency_condition;
17177 if (should_cache) {
17178 condition = this.is_src
17179 ? x `${condition} && (${element.var}.src !== (${last} = ${value}))`
17180 : x `${condition} && (${last} !== (${last} = ${value}))`;
17181 }
17182 if (this.is_input_value) {
17183 const type = element.node.get_static_attribute_value('type');
17184 if (type === null || type === "" || type === "text" || type === "email" || type === "password") {
17185 condition = x `${condition} && ${element.var}.${property_name} !== ${should_cache ? last : value}`;
17186 }
17187 }
17188 if (block.has_outros) {
17189 condition = x `!#current || ${condition}`;
17190 }
17191 return condition;
17192 }
17193 get_dependencies() {
17194 const node_dependencies = this.node.get_dependencies();
17195 const dependencies = new Set(node_dependencies);
17196 node_dependencies.forEach((prop) => {
17197 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17198 if (indirect_dependencies) {
17199 indirect_dependencies.forEach(indirect_dependency => {
17200 dependencies.add(indirect_dependency);
17201 });
17202 }
17203 });
17204 return Array.from(dependencies);
17205 }
17206 get_metadata() {
17207 if (this.parent.node.namespace)
17208 return null;
17209 const metadata = attribute_lookup[this.name];
17210 if (metadata && metadata.applies_to && !metadata.applies_to.includes(this.parent.node.name))
17211 return null;
17212 return metadata;
17213 }
17214 get_value(block) {
17215 if (this.node.is_true) {
17216 if (this.metadata && boolean_attribute.has(this.metadata.property_name.toLowerCase())) {
17217 return x `true`;
17218 }
17219 return x `""`;
17220 }
17221 if (this.node.chunks.length === 0)
17222 return x `""`;
17223 // TODO some of this code is repeated in Tag.ts — would be good to
17224 // DRY it out if that's possible without introducing crazy indirection
17225 if (this.node.chunks.length === 1) {
17226 return this.node.chunks[0].type === 'Text'
17227 ? string_literal(this.node.chunks[0].data)
17228 : this.node.chunks[0].manipulate(block);
17229 }
17230 let value = this.node.name === 'class'
17231 ? this.get_class_name_text(block)
17232 : this.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17233 // '{foo} {bar}' — treat as string concatenation
17234 if (this.node.chunks[0].type !== 'Text') {
17235 value = x `"" + ${value}`;
17236 }
17237 return value;
17238 }
17239 get_class_name_text(block) {
17240 const scoped_css = this.node.chunks.some((chunk) => chunk.synthetic);
17241 const rendered = this.render_chunks(block);
17242 if (scoped_css && rendered.length === 2) {
17243 // we have a situation like class={possiblyUndefined}
17244 rendered[0] = x `@null_to_empty(${rendered[0]})`;
17245 }
17246 return rendered.reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17247 }
17248 render_chunks(block) {
17249 return this.node.chunks.map((chunk) => {
17250 if (chunk.type === 'Text') {
17251 return string_literal(chunk.data);
17252 }
17253 return chunk.manipulate(block);
17254 });
17255 }
17256 stringify() {
17257 if (this.node.is_true)
17258 return '';
17259 const value = this.node.chunks;
17260 if (value.length === 0)
17261 return `=""`;
17262 return `="${value.map(chunk => {
17263 return chunk.type === 'Text'
17264 ? chunk.data.replace(/"/g, '\\"')
17265 : `\${${chunk.manipulate()}}`;
17266 }).join('')}"`;
17267 }
17268 }
17269 // source: https://html.spec.whatwg.org/multipage/indices.html
17270 const attribute_lookup = {
17271 allowfullscreen: { property_name: 'allowFullscreen', applies_to: ['iframe'] },
17272 allowpaymentrequest: { property_name: 'allowPaymentRequest', applies_to: ['iframe'] },
17273 async: { applies_to: ['script'] },
17274 autofocus: { applies_to: ['button', 'input', 'keygen', 'select', 'textarea'] },
17275 autoplay: { applies_to: ['audio', 'video'] },
17276 checked: { applies_to: ['input'] },
17277 controls: { applies_to: ['audio', 'video'] },
17278 default: { applies_to: ['track'] },
17279 defer: { applies_to: ['script'] },
17280 disabled: {
17281 applies_to: [
17282 'button',
17283 'fieldset',
17284 'input',
17285 'keygen',
17286 'optgroup',
17287 'option',
17288 'select',
17289 'textarea',
17290 ],
17291 },
17292 formnovalidate: { property_name: 'formNoValidate', applies_to: ['button', 'input'] },
17293 hidden: {},
17294 indeterminate: { applies_to: ['input'] },
17295 ismap: { property_name: 'isMap', applies_to: ['img'] },
17296 loop: { applies_to: ['audio', 'bgsound', 'video'] },
17297 multiple: { applies_to: ['input', 'select'] },
17298 muted: { applies_to: ['audio', 'video'] },
17299 nomodule: { property_name: 'noModule', applies_to: ['script'] },
17300 novalidate: { property_name: 'noValidate', applies_to: ['form'] },
17301 open: { applies_to: ['details', 'dialog'] },
17302 playsinline: { property_name: 'playsInline', applies_to: ['video'] },
17303 readonly: { property_name: 'readOnly', applies_to: ['input', 'textarea'] },
17304 required: { applies_to: ['input', 'select', 'textarea'] },
17305 reversed: { applies_to: ['ol'] },
17306 selected: { applies_to: ['option'] },
17307 value: {
17308 applies_to: [
17309 'button',
17310 'option',
17311 'input',
17312 'li',
17313 'meter',
17314 'progress',
17315 'param',
17316 'select',
17317 'textarea',
17318 ],
17319 },
17320 };
17321 Object.keys(attribute_lookup).forEach(name => {
17322 const metadata = attribute_lookup[name];
17323 if (!metadata.property_name)
17324 metadata.property_name = name;
17325 });
17326 // source: https://html.spec.whatwg.org/multipage/indices.html
17327 const boolean_attribute = new Set([
17328 'allowfullscreen',
17329 'allowpaymentrequest',
17330 'async',
17331 'autofocus',
17332 'autoplay',
17333 'checked',
17334 'controls',
17335 'default',
17336 'defer',
17337 'disabled',
17338 'formnovalidate',
17339 'hidden',
17340 'ismap',
17341 'itemscope',
17342 'loop',
17343 'multiple',
17344 'muted',
17345 'nomodule',
17346 'novalidate',
17347 'open',
17348 'playsinline',
17349 'readonly',
17350 'required',
17351 'reversed',
17352 'selected'
17353 ]);
17354 function should_cache(attribute) {
17355 return attribute.is_src || attribute.node.should_cache();
17356 }
17357 function is_indirectly_bound_value(attribute) {
17358 const element = attribute.parent;
17359 return attribute.name === 'value' &&
17360 (element.node.name === 'option' || // TODO check it's actually bound
17361 (element.node.name === 'input' &&
17362 element.node.bindings.some((binding) => /checked|group/.test(binding.name))));
17363 }
17364
17365 class StyleAttributeWrapper extends AttributeWrapper {
17366 render(block) {
17367 const style_props = optimize_style(this.node.chunks);
17368 if (!style_props)
17369 return super.render(block);
17370 style_props.forEach((prop) => {
17371 let value;
17372 if (is_dynamic(prop.value)) {
17373 const prop_dependencies = new Set();
17374 value = prop.value
17375 .map(chunk => {
17376 if (chunk.type === 'Text') {
17377 return string_literal(chunk.data);
17378 }
17379 else {
17380 add_to_set(prop_dependencies, chunk.dynamic_dependencies());
17381 return chunk.manipulate(block);
17382 }
17383 })
17384 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17385 // TODO is this necessary? style.setProperty always treats value as string, no?
17386 // if (prop.value.length === 1 || prop.value[0].type !== 'Text') {
17387 // value = x`"" + ${value}`;
17388 // }
17389 if (prop_dependencies.size) {
17390 let condition = block.renderer.dirty(Array.from(prop_dependencies));
17391 if (block.has_outros) {
17392 condition = x `!#current || ${condition}`;
17393 }
17394 const update = b `
17395 if (${condition}) {
17396 @set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});
17397 }`;
17398 block.chunks.update.push(update);
17399 }
17400 }
17401 else {
17402 value = string_literal(prop.value[0].data);
17403 }
17404 block.chunks.hydrate.push(b `@set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});`);
17405 });
17406 }
17407 }
17408 function optimize_style(value) {
17409 const props = [];
17410 let chunks = value.slice();
17411 while (chunks.length) {
17412 const chunk = chunks[0];
17413 if (chunk.type !== 'Text')
17414 return null;
17415 const key_match = /^\s*([\w-]+):\s*/.exec(chunk.data);
17416 if (!key_match)
17417 return null;
17418 const key = key_match[1];
17419 const offset = key_match.index + key_match[0].length;
17420 const remaining_data = chunk.data.slice(offset);
17421 if (remaining_data) {
17422 chunks[0] = {
17423 start: chunk.start + offset,
17424 end: chunk.end,
17425 type: 'Text',
17426 data: remaining_data
17427 };
17428 }
17429 else {
17430 chunks.shift();
17431 }
17432 const result = get_style_value(chunks);
17433 props.push({ key, value: result.value, important: result.important });
17434 chunks = result.chunks;
17435 }
17436 return props;
17437 }
17438 function get_style_value(chunks) {
17439 const value = [];
17440 let in_url = false;
17441 let quote_mark = null;
17442 let escaped = false;
17443 let closed = false;
17444 while (chunks.length && !closed) {
17445 const chunk = chunks.shift();
17446 if (chunk.type === 'Text') {
17447 let c = 0;
17448 while (c < chunk.data.length) {
17449 const char = chunk.data[c];
17450 if (escaped) {
17451 escaped = false;
17452 }
17453 else if (char === '\\') {
17454 escaped = true;
17455 }
17456 else if (char === quote_mark) {
17457 quote_mark = null;
17458 }
17459 else if (char === '"' || char === "'") {
17460 quote_mark = char;
17461 }
17462 else if (char === ')' && in_url) {
17463 in_url = false;
17464 }
17465 else if (char === 'u' && chunk.data.slice(c, c + 4) === 'url(') {
17466 in_url = true;
17467 }
17468 else if (char === ';' && !in_url && !quote_mark) {
17469 closed = true;
17470 break;
17471 }
17472 c += 1;
17473 }
17474 if (c > 0) {
17475 value.push({
17476 type: 'Text',
17477 start: chunk.start,
17478 end: chunk.start + c,
17479 data: chunk.data.slice(0, c)
17480 });
17481 }
17482 while (/[;\s]/.test(chunk.data[c]))
17483 c += 1;
17484 const remaining_data = chunk.data.slice(c);
17485 if (remaining_data) {
17486 chunks.unshift({
17487 start: chunk.start + c,
17488 end: chunk.end,
17489 type: 'Text',
17490 data: remaining_data
17491 });
17492 break;
17493 }
17494 }
17495 else {
17496 value.push(chunk);
17497 }
17498 }
17499 let important = false;
17500 const last_chunk = value[value.length - 1];
17501 if (last_chunk && last_chunk.type === 'Text' && /\s*!important\s*$/.test(last_chunk.data)) {
17502 important = true;
17503 last_chunk.data = last_chunk.data.replace(/\s*!important\s*$/, '');
17504 if (!last_chunk.data)
17505 value.pop();
17506 }
17507 return {
17508 chunks,
17509 value,
17510 important
17511 };
17512 }
17513 function is_dynamic(value) {
17514 return value.length > 1 || value[0].type !== 'Text';
17515 }
17516
17517 class SpreadAttributeWrapper extends BaseAttributeWrapper {
17518 }
17519
17520 function get_object(node) {
17521 while (node.type === 'MemberExpression')
17522 node = node.object;
17523 return node;
17524 }
17525
17526 function replace_object(node, replacement) {
17527 if (node.type === 'Identifier')
17528 return replacement;
17529 const ancestor = node;
17530 let parent;
17531 while (node.type === 'MemberExpression') {
17532 parent = node;
17533 node = node.object;
17534 }
17535 parent.object = replacement;
17536 return ancestor;
17537 }
17538
17539 function flatten_reference(node) {
17540 const nodes = [];
17541 const parts = [];
17542 while (node.type === 'MemberExpression') {
17543 nodes.unshift(node.property);
17544 if (!node.computed) {
17545 parts.unshift(node.property.name);
17546 }
17547 else {
17548 const computed_property = to_string$1(node.property);
17549 if (computed_property) {
17550 parts.unshift(`[${computed_property}]`);
17551 }
17552 }
17553 node = node.object;
17554 }
17555 const name = node.type === 'Identifier'
17556 ? node.name
17557 : node.type === 'ThisExpression' ? 'this' : null;
17558 nodes.unshift(node);
17559 parts.unshift(name);
17560 return { name, nodes, parts };
17561 }
17562 function to_string$1(node) {
17563 switch (node.type) {
17564 case 'Literal':
17565 return String(node.value);
17566 case 'Identifier':
17567 return node.name;
17568 }
17569 }
17570
17571 function mark_each_block_bindings(parent, binding) {
17572 // we need to ensure that the each block creates a context including
17573 // the list and the index, if they're not otherwise referenced
17574 const object = get_object(binding.expression.node).name;
17575 const each_block = parent.node.scope.get_owner(object);
17576 each_block.has_binding = true;
17577 if (binding.name === "group") {
17578 // for `<input bind:group={} >`, we make sure that all the each blocks creates context with `index`
17579 for (const name of binding.expression.contextual_dependencies) {
17580 const each_block = parent.node.scope.get_owner(name);
17581 each_block.has_index_binding = true;
17582 }
17583 }
17584 }
17585
17586 class BindingWrapper {
17587 constructor(block, node, parent) {
17588 this.node = node;
17589 this.parent = parent;
17590 const { dependencies } = this.node.expression;
17591 block.add_dependencies(dependencies);
17592 // TODO does this also apply to e.g. `<input type='checkbox' bind:group='foo'>`?
17593 handle_select_value_binding(this, dependencies);
17594 if (node.is_contextual) {
17595 mark_each_block_bindings(this.parent, this.node);
17596 }
17597 this.object = get_object(this.node.expression.node).name;
17598 // view to model
17599 this.handler = get_event_handler(this, parent.renderer, block, this.object, this.node.raw_expression);
17600 this.snippet = this.node.expression.manipulate(block);
17601 this.is_readonly = this.node.is_readonly;
17602 this.needs_lock = this.node.name === 'currentTime'; // TODO others?
17603 }
17604 get_dependencies() {
17605 const dependencies = new Set(this.node.expression.dependencies);
17606 this.node.expression.dependencies.forEach((prop) => {
17607 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17608 if (indirect_dependencies) {
17609 indirect_dependencies.forEach(indirect_dependency => {
17610 dependencies.add(indirect_dependency);
17611 });
17612 }
17613 });
17614 return dependencies;
17615 }
17616 is_readonly_media_attribute() {
17617 return this.node.is_readonly_media_attribute();
17618 }
17619 render(block, lock) {
17620 if (this.is_readonly)
17621 return;
17622 const { parent } = this;
17623 const update_conditions = this.needs_lock ? [x `!${lock}`] : [];
17624 const mount_conditions = [];
17625 const dependency_array = Array.from(this.get_dependencies());
17626 if (dependency_array.length > 0) {
17627 update_conditions.push(block.renderer.dirty(dependency_array));
17628 }
17629 if (parent.node.name === "input") {
17630 const type = parent.node.get_static_attribute_value("type");
17631 if (type === null ||
17632 type === "" ||
17633 type === "text" ||
17634 type === "email" ||
17635 type === "password") {
17636 update_conditions.push(x `${parent.var}.${this.node.name} !== ${this.snippet}`);
17637 }
17638 else if (type === "number") {
17639 update_conditions.push(x `@to_number(${parent.var}.${this.node.name}) !== ${this.snippet}`);
17640 }
17641 }
17642 // model to view
17643 let update_dom = get_dom_updater(parent, this);
17644 let mount_dom = update_dom;
17645 // special cases
17646 switch (this.node.name) {
17647 case 'group':
17648 {
17649 const { binding_group, is_context, contexts, index } = get_binding_group(parent.renderer, this.node, block);
17650 block.renderer.add_to_context(`$$binding_groups`);
17651 if (is_context) {
17652 if (contexts.length > 1) {
17653 let binding_group = x `${block.renderer.reference('$$binding_groups')}[${index}]`;
17654 for (const name of contexts.slice(0, -1)) {
17655 binding_group = x `${binding_group}[${block.renderer.reference(name)}]`;
17656 block.chunks.init.push(b `${binding_group} = ${binding_group} || [];`);
17657 }
17658 }
17659 block.chunks.init.push(b `${binding_group(true)} = [];`);
17660 }
17661 block.chunks.hydrate.push(b `${binding_group(true)}.push(${parent.var});`);
17662 block.chunks.destroy.push(b `${binding_group(true)}.splice(${binding_group(true)}.indexOf(${parent.var}), 1);`);
17663 break;
17664 }
17665 case 'textContent':
17666 update_conditions.push(x `${this.snippet} !== ${parent.var}.textContent`);
17667 mount_conditions.push(x `${this.snippet} !== void 0`);
17668 break;
17669 case 'innerHTML':
17670 update_conditions.push(x `${this.snippet} !== ${parent.var}.innerHTML`);
17671 mount_conditions.push(x `${this.snippet} !== void 0`);
17672 break;
17673 case 'currentTime':
17674 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17675 mount_dom = null;
17676 break;
17677 case 'playbackRate':
17678 case 'volume':
17679 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17680 mount_conditions.push(x `!@_isNaN(${this.snippet})`);
17681 break;
17682 case 'paused':
17683 {
17684 // this is necessary to prevent audio restarting by itself
17685 const last = block.get_unique_name(`${parent.var.name}_is_paused`);
17686 block.add_variable(last, x `true`);
17687 update_conditions.push(x `${last} !== (${last} = ${this.snippet})`);
17688 update_dom = b `${parent.var}[${last} ? "pause" : "play"]();`;
17689 mount_dom = null;
17690 break;
17691 }
17692 case 'value':
17693 if (parent.node.get_static_attribute_value('type') === 'file') {
17694 update_dom = null;
17695 mount_dom = null;
17696 }
17697 }
17698 if (update_dom) {
17699 if (update_conditions.length > 0) {
17700 const condition = update_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17701 block.chunks.update.push(b `
17702 if (${condition}) {
17703 ${update_dom}
17704 }
17705 `);
17706 }
17707 else {
17708 block.chunks.update.push(update_dom);
17709 }
17710 }
17711 if (mount_dom) {
17712 if (mount_conditions.length > 0) {
17713 const condition = mount_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17714 block.chunks.mount.push(b `
17715 if (${condition}) {
17716 ${mount_dom}
17717 }
17718 `);
17719 }
17720 else {
17721 block.chunks.mount.push(mount_dom);
17722 }
17723 }
17724 }
17725 }
17726 function get_dom_updater(element, binding) {
17727 const { node } = element;
17728 if (binding.is_readonly_media_attribute()) {
17729 return null;
17730 }
17731 if (binding.node.name === 'this') {
17732 return null;
17733 }
17734 if (node.name === 'select') {
17735 return node.get_static_attribute_value('multiple') === true ?
17736 b `@select_options(${element.var}, ${binding.snippet})` :
17737 b `@select_option(${element.var}, ${binding.snippet})`;
17738 }
17739 if (binding.node.name === 'group') {
17740 const type = node.get_static_attribute_value('type');
17741 const condition = type === 'checkbox'
17742 ? x `~${binding.snippet}.indexOf(${element.var}.__value)`
17743 : x `${element.var}.__value === ${binding.snippet}`;
17744 return b `${element.var}.checked = ${condition};`;
17745 }
17746 if (binding.node.name === 'value') {
17747 return b `@set_input_value(${element.var}, ${binding.snippet});`;
17748 }
17749 return b `${element.var}.${binding.node.name} = ${binding.snippet};`;
17750 }
17751 function get_binding_group(renderer, value, block) {
17752 const { parts } = flatten_reference(value.raw_expression);
17753 let keypath = parts.join('.');
17754 const contexts = [];
17755 for (const dep of value.expression.contextual_dependencies) {
17756 const context = block.bindings.get(dep);
17757 let key;
17758 let name;
17759 if (context) {
17760 key = context.object.name;
17761 name = context.property.name;
17762 }
17763 else {
17764 key = dep;
17765 name = dep;
17766 }
17767 keypath = `${key}@${keypath}`;
17768 contexts.push(name);
17769 }
17770 if (!renderer.binding_groups.has(keypath)) {
17771 const index = renderer.binding_groups.size;
17772 contexts.forEach(context => {
17773 renderer.add_to_context(context, true);
17774 });
17775 renderer.binding_groups.set(keypath, {
17776 binding_group: (to_reference = false) => {
17777 let binding_group = '$$binding_groups';
17778 let _secondary_indexes = contexts;
17779 if (to_reference) {
17780 binding_group = block.renderer.reference(binding_group);
17781 _secondary_indexes = _secondary_indexes.map(name => block.renderer.reference(name));
17782 }
17783 if (_secondary_indexes.length > 0) {
17784 let obj = x `${binding_group}[${index}]`;
17785 _secondary_indexes.forEach(secondary_index => {
17786 obj = x `${obj}[${secondary_index}]`;
17787 });
17788 return obj;
17789 }
17790 else {
17791 return x `${binding_group}[${index}]`;
17792 }
17793 },
17794 is_context: contexts.length > 0,
17795 contexts,
17796 index,
17797 });
17798 }
17799 return renderer.binding_groups.get(keypath);
17800 }
17801 function get_event_handler(binding, renderer, block, name, lhs) {
17802 const contextual_dependencies = new Set(binding.node.expression.contextual_dependencies);
17803 const context = block.bindings.get(name);
17804 let set_store;
17805 if (context) {
17806 const { object, property, store, snippet } = context;
17807 lhs = replace_object(lhs, snippet);
17808 contextual_dependencies.add(object.name);
17809 contextual_dependencies.add(property.name);
17810 contextual_dependencies.delete(name);
17811 if (store) {
17812 set_store = b `${store}.set(${`$${store}`});`;
17813 }
17814 }
17815 else {
17816 const object = get_object(lhs);
17817 if (object.name[0] === '$') {
17818 const store = object.name.slice(1);
17819 set_store = b `${store}.set(${object.name});`;
17820 }
17821 }
17822 const value = get_value_from_dom(renderer, binding.parent, binding, block, contextual_dependencies);
17823 const mutation = b `
17824 ${lhs} = ${value};
17825 ${set_store}
17826 `;
17827 return {
17828 uses_context: binding.node.is_contextual || binding.node.expression.uses_context,
17829 mutation,
17830 contextual_dependencies,
17831 lhs,
17832 };
17833 }
17834 function get_value_from_dom(renderer, element, binding, block, contextual_dependencies) {
17835 const { node } = element;
17836 const { name } = binding.node;
17837 if (name === 'this') {
17838 return x `$$value`;
17839 }
17840 // <select bind:value='selected>
17841 if (node.name === 'select') {
17842 return node.get_static_attribute_value('multiple') === true ?
17843 x `@select_multiple_value(this)` :
17844 x `@select_value(this)`;
17845 }
17846 const type = node.get_static_attribute_value('type');
17847 // <input type='checkbox' bind:group='foo'>
17848 if (name === 'group') {
17849 if (type === 'checkbox') {
17850 const { binding_group, contexts } = get_binding_group(renderer, binding.node, block);
17851 add_to_set(contextual_dependencies, contexts);
17852 return x `@get_binding_group_value(${binding_group()}, this.__value, this.checked)`;
17853 }
17854 return x `this.__value`;
17855 }
17856 // <input type='range|number' bind:value>
17857 if (type === 'range' || type === 'number') {
17858 return x `@to_number(this.${name})`;
17859 }
17860 if ((name === 'buffered' || name === 'seekable' || name === 'played')) {
17861 return x `@time_ranges_to_array(this.${name})`;
17862 }
17863 // everything else
17864 return x `this.${name}`;
17865 }
17866
17867 function add_actions(block, target, actions) {
17868 actions.forEach(action => add_action(block, target, action));
17869 }
17870 function add_action(block, target, action) {
17871 const { expression } = action;
17872 let snippet;
17873 let dependencies;
17874 if (expression) {
17875 snippet = expression.manipulate(block);
17876 dependencies = expression.dynamic_dependencies();
17877 }
17878 const id = block.get_unique_name(`${action.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action`);
17879 block.add_variable(id);
17880 const fn = block.renderer.reference(action.name);
17881 block.event_listeners.push(x `@action_destroyer(${id} = ${fn}.call(null, ${target}, ${snippet}))`);
17882 if (dependencies && dependencies.length > 0) {
17883 let condition = x `${id} && @is_function(${id}.update)`;
17884 if (dependencies.length > 0) {
17885 condition = x `${condition} && ${block.renderer.dirty(dependencies)}`;
17886 }
17887 block.chunks.update.push(b `if (${condition}) ${id}.update.call(null, ${snippet});`);
17888 }
17889 }
17890
17891 function get_slot_definition(block, scope, lets) {
17892 if (lets.length === 0)
17893 return { block, scope };
17894 const context_input = {
17895 type: 'ObjectPattern',
17896 properties: lets.map(l => ({
17897 type: 'Property',
17898 kind: 'init',
17899 key: l.name,
17900 value: l.value || l.name
17901 }))
17902 };
17903 const properties = [];
17904 const value_map = new Map();
17905 lets.forEach(l => {
17906 let value;
17907 if (l.names.length > 1) {
17908 // more than one, probably destructuring
17909 const unique_name = block.get_unique_name(l.names.join('_')).name;
17910 value_map.set(l.value, unique_name);
17911 value = { type: 'Identifier', name: unique_name };
17912 }
17913 else {
17914 value = l.value || l.name;
17915 }
17916 properties.push({
17917 type: 'Property',
17918 kind: 'init',
17919 key: l.name,
17920 value,
17921 });
17922 });
17923 const changes_input = {
17924 type: 'ObjectPattern',
17925 properties,
17926 };
17927 const names = new Set();
17928 const names_lookup = new Map();
17929 lets.forEach(l => {
17930 l.names.forEach(name => {
17931 names.add(name);
17932 if (value_map.has(l.value)) {
17933 names_lookup.set(name, value_map.get(l.value));
17934 }
17935 });
17936 });
17937 const context = {
17938 type: 'ObjectExpression',
17939 properties: Array.from(names).map(name => p `${block.renderer.context_lookup.get(name).index}: ${name}`)
17940 };
17941 const { context_lookup } = block.renderer;
17942 // i am well aware that this code is gross
17943 // TODO: context-overflow make it less gross
17944 const changes = {
17945 type: 'ParenthesizedExpression',
17946 get expression() {
17947 if (block.renderer.context_overflow) {
17948 const grouped = [];
17949 Array.from(names).forEach(name => {
17950 const i = context_lookup.get(name).index.value;
17951 const g = Math.floor(i / 31);
17952 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
17953 if (!grouped[g])
17954 grouped[g] = [];
17955 grouped[g].push({ name: lookup_name, n: i % 31 });
17956 });
17957 const elements = [];
17958 for (let g = 0; g < grouped.length; g += 1) {
17959 elements[g] = grouped[g]
17960 ? grouped[g]
17961 .map(({ name, n }) => x `${name} ? ${1 << n} : 0`)
17962 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`)
17963 : x `0`;
17964 }
17965 return {
17966 type: 'ArrayExpression',
17967 elements
17968 };
17969 }
17970 return Array.from(names)
17971 .map(name => {
17972 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
17973 const i = context_lookup.get(name).index.value;
17974 return x `${lookup_name} ? ${1 << i} : 0`;
17975 })
17976 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
17977 }
17978 };
17979 return {
17980 block,
17981 scope,
17982 get_context: x `${context_input} => ${context}`,
17983 get_changes: x `${changes_input} => ${changes}`
17984 };
17985 }
17986
17987 function compare_node(a, b) {
17988 if (a === b)
17989 return true;
17990 if (!a || !b)
17991 return false;
17992 if (a.type !== b.type)
17993 return false;
17994 switch (a.type) {
17995 case "Identifier":
17996 return a.name === b.name;
17997 case "MemberExpression":
17998 return (compare_node(a.object, b.object) &&
17999 compare_node(a.property, b.property) &&
18000 a.computed === b.computed);
18001 case 'Literal':
18002 return a.value === b.value;
18003 }
18004 }
18005
18006 function bind_this(component, block, binding, variable) {
18007 const fn = component.get_unique_name(`${variable.name}_binding`);
18008 block.renderer.add_to_context(fn.name);
18009 const callee = block.renderer.reference(fn.name);
18010 const { contextual_dependencies, mutation } = binding.handler;
18011 const dependencies = binding.get_dependencies();
18012 const body = b `
18013 ${mutation}
18014 ${Array.from(dependencies)
18015 .filter(dep => dep[0] !== '$')
18016 .filter(dep => !contextual_dependencies.has(dep))
18017 .map(dep => b `${block.renderer.invalidate(dep)};`)}
18018 `;
18019 if (contextual_dependencies.size) {
18020 const params = Array.from(contextual_dependencies).map(name => ({
18021 type: 'Identifier',
18022 name
18023 }));
18024 component.partly_hoisted.push(b `
18025 function ${fn}($$value, ${params}) {
18026 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
18027 ${body}
18028 });
18029 }
18030 `);
18031 const alias_map = new Map();
18032 const args = [];
18033 for (let id of params) {
18034 const value = block.renderer.reference(id.name);
18035 let found = false;
18036 if (block.variables.has(id.name)) {
18037 let alias = id.name;
18038 for (let i = 1; block.variables.has(alias) && !compare_node(block.variables.get(alias).init, value); alias = `${id.name}_${i++}`)
18039 ;
18040 alias_map.set(alias, id.name);
18041 id = { type: 'Identifier', name: alias };
18042 found = block.variables.has(alias);
18043 }
18044 args.push(id);
18045 if (!found) {
18046 block.add_variable(id, value);
18047 }
18048 }
18049 const assign = block.get_unique_name(`assign_${variable.name}`);
18050 const unassign = block.get_unique_name(`unassign_${variable.name}`);
18051 block.chunks.init.push(b `
18052 const ${assign} = () => ${callee}(${variable}, ${args});
18053 const ${unassign} = () => ${callee}(null, ${args});
18054 `);
18055 const condition = Array.from(args)
18056 .map(name => x `${name} !== ${block.renderer.reference(alias_map.get(name.name) || name.name)}`)
18057 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
18058 // we push unassign and unshift assign so that references are
18059 // nulled out before they're created, to avoid glitches
18060 // with shifting indices
18061 block.chunks.update.push(b `
18062 if (${condition}) {
18063 ${unassign}();
18064 ${args.map(a => b `${a} = ${block.renderer.reference(alias_map.get(a.name) || a.name)}`)};
18065 ${assign}();
18066 }`);
18067 block.chunks.destroy.push(b `${unassign}();`);
18068 return b `${assign}();`;
18069 }
18070 component.partly_hoisted.push(b `
18071 function ${fn}($$value) {
18072 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
18073 ${body}
18074 });
18075 }
18076 `);
18077 block.chunks.destroy.push(b `${callee}(null);`);
18078 return b `${callee}(${variable});`;
18079 }
18080
18081 class Node$1 {
18082 constructor(component, parent, _scope, info) {
18083 this.start = info.start;
18084 this.end = info.end;
18085 this.type = info.type;
18086 // this makes properties non-enumerable, which makes logging
18087 // bearable. might have a performance cost. TODO remove in prod?
18088 Object.defineProperties(this, {
18089 component: {
18090 value: component
18091 },
18092 parent: {
18093 value: parent
18094 }
18095 });
18096 }
18097 cannot_use_innerhtml() {
18098 if (this.can_use_innerhtml !== false) {
18099 this.can_use_innerhtml = false;
18100 if (this.parent)
18101 this.parent.cannot_use_innerhtml();
18102 }
18103 }
18104 find_nearest(selector) {
18105 if (selector.test(this.type))
18106 return this;
18107 if (this.parent)
18108 return this.parent.find_nearest(selector);
18109 }
18110 get_static_attribute_value(name) {
18111 const attribute = this.attributes && this.attributes.find((attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === name);
18112 if (!attribute)
18113 return null;
18114 if (attribute.is_true)
18115 return true;
18116 if (attribute.chunks.length === 0)
18117 return '';
18118 if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
18119 return attribute.chunks[0].data;
18120 }
18121 return null;
18122 }
18123 has_ancestor(type) {
18124 return this.parent ?
18125 this.parent.type === type || this.parent.has_ancestor(type) :
18126 false;
18127 }
18128 }
18129
18130 function create_scopes(expression) {
18131 return analyze(expression);
18132 }
18133
18134 function is_dynamic$1(variable) {
18135 if (variable) {
18136 if (variable.mutated || variable.reassigned)
18137 return true; // dynamic internal state
18138 if (!variable.module && variable.writable && variable.export_name)
18139 return true; // writable props
18140 }
18141 return false;
18142 }
18143
18144 function nodes_match(a, b) {
18145 if (!!a !== !!b)
18146 return false;
18147 if (Array.isArray(a) !== Array.isArray(b))
18148 return false;
18149 if (a && typeof a === 'object') {
18150 if (Array.isArray(a)) {
18151 if (a.length !== b.length)
18152 return false;
18153 return a.every((child, i) => nodes_match(child, b[i]));
18154 }
18155 const a_keys = Object.keys(a).sort();
18156 const b_keys = Object.keys(b).sort();
18157 if (a_keys.length !== b_keys.length)
18158 return false;
18159 let i = a_keys.length;
18160 while (i--) {
18161 const key = a_keys[i];
18162 if (b_keys[i] !== key)
18163 return false;
18164 if (key === 'start' || key === 'end')
18165 continue;
18166 if (!nodes_match(a[key], b[key])) {
18167 return false;
18168 }
18169 }
18170 return true;
18171 }
18172 return a === b;
18173 }
18174
18175 function invalidate(renderer, scope, node, names, main_execution_context = false) {
18176 const { component } = renderer;
18177 const [head, ...tail] = Array.from(names)
18178 .filter(name => {
18179 const owner = scope.find_owner(name);
18180 return !owner || owner === component.instance_scope;
18181 })
18182 .map(name => component.var_lookup.get(name))
18183 .filter(variable => {
18184 return variable && (!variable.hoistable &&
18185 !variable.global &&
18186 !variable.module &&
18187 (variable.referenced ||
18188 variable.subscribable ||
18189 variable.is_reactive_dependency ||
18190 variable.export_name ||
18191 variable.name[0] === '$'));
18192 });
18193 function get_invalidated(variable, node) {
18194 if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') {
18195 return node || x `${variable.name}`;
18196 }
18197 return renderer.invalidate(variable.name);
18198 }
18199 if (head) {
18200 component.has_reactive_assignments = true;
18201 if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) {
18202 return get_invalidated(head, node);
18203 }
18204 else {
18205 const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
18206 const extra_args = tail.map(variable => get_invalidated(variable));
18207 const pass_value = (extra_args.length > 0 ||
18208 (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
18209 (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier')));
18210 if (pass_value) {
18211 extra_args.unshift({
18212 type: 'Identifier',
18213 name: head.name
18214 });
18215 }
18216 let invalidate = is_store_value
18217 ? x `@set_store_value(${head.name.slice(1)}, ${node}, ${extra_args})`
18218 : !main_execution_context
18219 ? x `$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`
18220 : node;
18221 if (head.subscribable && head.reassigned) {
18222 const subscribe = `$$subscribe_${head.name}`;
18223 invalidate = x `${subscribe}(${invalidate})`;
18224 }
18225 return invalidate;
18226 }
18227 }
18228 return node;
18229 }
18230
18231 const reserved_keywords = new Set(["$$props", "$$restProps"]);
18232 function is_reserved_keyword(name) {
18233 return reserved_keywords.has(name);
18234 }
18235
18236 class Expression {
18237 // todo: owner type
18238 constructor(component, owner, template_scope, info, lazy) {
18239 this.type = 'Expression';
18240 this.dependencies = new Set();
18241 this.contextual_dependencies = new Set();
18242 this.declarations = [];
18243 this.uses_context = false;
18244 // TODO revert to direct property access in prod?
18245 Object.defineProperties(this, {
18246 component: {
18247 value: component
18248 }
18249 });
18250 this.node = info;
18251 this.template_scope = template_scope;
18252 this.owner = owner;
18253 const { dependencies, contextual_dependencies } = this;
18254 let { map, scope } = create_scopes(info);
18255 this.scope = scope;
18256 this.scope_map = map;
18257 const expression = this;
18258 let function_expression;
18259 // discover dependencies, but don't change the code yet
18260 walk(info, {
18261 enter(node, parent, key) {
18262 // don't manipulate shorthand props twice
18263 if (key === 'value' && parent.shorthand)
18264 return;
18265 if (map.has(node)) {
18266 scope = map.get(node);
18267 }
18268 if (!function_expression && /FunctionExpression/.test(node.type)) {
18269 function_expression = node;
18270 }
18271 if (isReference(node, parent)) {
18272 const { name, nodes } = flatten_reference(node);
18273 if (scope.has(name))
18274 return;
18275 if (name[0] === '$') {
18276 const store_name = name.slice(1);
18277 if (template_scope.names.has(store_name) || scope.has(store_name)) {
18278 component.error(node, {
18279 code: `contextual-store`,
18280 message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
18281 });
18282 }
18283 }
18284 if (template_scope.is_let(name)) {
18285 if (!function_expression) { // TODO should this be `!lazy` ?
18286 contextual_dependencies.add(name);
18287 dependencies.add(name);
18288 }
18289 }
18290 else if (template_scope.names.has(name)) {
18291 expression.uses_context = true;
18292 contextual_dependencies.add(name);
18293 const owner = template_scope.get_owner(name);
18294 const is_index = owner.type === 'EachBlock' && owner.key && name === owner.index;
18295 if (!lazy || is_index) {
18296 template_scope.dependencies_for_name.get(name).forEach(name => dependencies.add(name));
18297 }
18298 }
18299 else {
18300 if (!lazy) {
18301 dependencies.add(name);
18302 }
18303 component.add_reference(name);
18304 component.warn_if_undefined(name, nodes[0], template_scope);
18305 }
18306 this.skip();
18307 }
18308 // track any assignments from template expressions as mutable
18309 let names;
18310 let deep = false;
18311 if (function_expression) {
18312 if (node.type === 'AssignmentExpression') {
18313 deep = node.left.type === 'MemberExpression';
18314 names = extract_names(deep ? get_object(node.left) : node.left);
18315 }
18316 else if (node.type === 'UpdateExpression') {
18317 names = extract_names(get_object(node.argument));
18318 }
18319 }
18320 if (names) {
18321 names.forEach(name => {
18322 if (template_scope.names.has(name)) {
18323 template_scope.dependencies_for_name.get(name).forEach(name => {
18324 const variable = component.var_lookup.get(name);
18325 if (variable)
18326 variable[deep ? 'mutated' : 'reassigned'] = true;
18327 });
18328 const each_block = template_scope.get_owner(name);
18329 each_block.has_binding = true;
18330 }
18331 else {
18332 component.add_reference(name);
18333 const variable = component.var_lookup.get(name);
18334 if (variable)
18335 variable[deep ? 'mutated' : 'reassigned'] = true;
18336 }
18337 });
18338 }
18339 },
18340 leave(node) {
18341 if (map.has(node)) {
18342 scope = scope.parent;
18343 }
18344 if (node === function_expression) {
18345 function_expression = null;
18346 }
18347 }
18348 });
18349 }
18350 dynamic_dependencies() {
18351 return Array.from(this.dependencies).filter(name => {
18352 if (this.template_scope.is_let(name))
18353 return true;
18354 if (is_reserved_keyword(name))
18355 return true;
18356 const variable = this.component.var_lookup.get(name);
18357 return is_dynamic$1(variable);
18358 });
18359 }
18360 // TODO move this into a render-dom wrapper?
18361 manipulate(block) {
18362 // TODO ideally we wouldn't end up calling this method
18363 // multiple times
18364 if (this.manipulated)
18365 return this.manipulated;
18366 const { component, declarations, scope_map: map, template_scope, owner } = this;
18367 let scope = this.scope;
18368 let function_expression;
18369 let dependencies;
18370 let contextual_dependencies;
18371 const node = walk(this.node, {
18372 enter(node, parent) {
18373 if (node.type === 'Property' && node.shorthand) {
18374 node.value = JSON.parse(JSON.stringify(node.value));
18375 node.shorthand = false;
18376 }
18377 if (map.has(node)) {
18378 scope = map.get(node);
18379 }
18380 if (node.type === 'Identifier' && isReference(node, parent)) {
18381 const { name } = flatten_reference(node);
18382 if (scope.has(name))
18383 return;
18384 if (function_expression) {
18385 if (template_scope.names.has(name)) {
18386 contextual_dependencies.add(name);
18387 template_scope.dependencies_for_name.get(name).forEach(dependency => {
18388 dependencies.add(dependency);
18389 });
18390 }
18391 else {
18392 dependencies.add(name);
18393 component.add_reference(name); // TODO is this redundant/misplaced?
18394 }
18395 }
18396 else if (is_contextual(component, template_scope, name)) {
18397 const reference = block.renderer.reference(node);
18398 this.replace(reference);
18399 }
18400 this.skip();
18401 }
18402 if (!function_expression) {
18403 if (node.type === 'AssignmentExpression') ;
18404 if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
18405 function_expression = node;
18406 dependencies = new Set();
18407 contextual_dependencies = new Set();
18408 }
18409 }
18410 },
18411 leave(node, parent) {
18412 if (map.has(node))
18413 scope = scope.parent;
18414 if (node === function_expression) {
18415 const id = component.get_unique_name(sanitize(get_function_name(node, owner)));
18416 const declaration = b `const ${id} = ${node}`;
18417 if (dependencies.size === 0 && contextual_dependencies.size === 0) {
18418 // we can hoist this out of the component completely
18419 component.fully_hoisted.push(declaration);
18420 this.replace(id);
18421 component.add_var({
18422 name: id.name,
18423 internal: true,
18424 hoistable: true,
18425 referenced: true
18426 });
18427 }
18428 else if (contextual_dependencies.size === 0) {
18429 // function can be hoisted inside the component init
18430 component.partly_hoisted.push(declaration);
18431 block.renderer.add_to_context(id.name);
18432 this.replace(block.renderer.reference(id));
18433 }
18434 else {
18435 // we need a combo block/init recipe
18436 const deps = Array.from(contextual_dependencies);
18437 node.params = [
18438 ...deps.map(name => ({ type: 'Identifier', name })),
18439 ...node.params
18440 ];
18441 const context_args = deps.map(name => block.renderer.reference(name));
18442 component.partly_hoisted.push(declaration);
18443 block.renderer.add_to_context(id.name);
18444 const callee = block.renderer.reference(id);
18445 this.replace(id);
18446 if (node.params.length > 0) {
18447 declarations.push(b `
18448 function ${id}(...args) {
18449 return ${callee}(${context_args}, ...args);
18450 }
18451 `);
18452 }
18453 else {
18454 declarations.push(b `
18455 function ${id}() {
18456 return ${callee}(${context_args});
18457 }
18458 `);
18459 }
18460 }
18461 function_expression = null;
18462 dependencies = null;
18463 contextual_dependencies = null;
18464 if (parent && parent.type === 'Property') {
18465 parent.method = false;
18466 }
18467 }
18468 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
18469 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
18470 const object_name = get_object(assignee).name;
18471 if (scope.has(object_name))
18472 return;
18473 // normally (`a = 1`, `b.c = 2`), there'll be a single name
18474 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
18475 // may be more, in which case we need to tack the extra ones
18476 // onto the initial function call
18477 const names = new Set(extract_names(assignee));
18478 const traced = new Set();
18479 names.forEach(name => {
18480 const dependencies = template_scope.dependencies_for_name.get(name);
18481 if (dependencies) {
18482 dependencies.forEach(name => traced.add(name));
18483 }
18484 else {
18485 traced.add(name);
18486 }
18487 });
18488 const context = block.bindings.get(object_name);
18489 if (context) {
18490 // for `{#each array as item}`
18491 // replace `item = 1` to `each_array[each_index] = 1`, this allow us to mutate the array
18492 // rather than mutating the local `item` variable
18493 const { snippet, object, property } = context;
18494 const replaced = replace_object(assignee, snippet);
18495 if (node.type === 'AssignmentExpression') {
18496 node.left = replaced;
18497 }
18498 else {
18499 node.argument = replaced;
18500 }
18501 contextual_dependencies.add(object.name);
18502 contextual_dependencies.add(property.name);
18503 }
18504 this.replace(invalidate(block.renderer, scope, node, traced));
18505 }
18506 }
18507 });
18508 if (declarations.length > 0) {
18509 block.maintain_context = true;
18510 declarations.forEach(declaration => {
18511 block.chunks.init.push(declaration);
18512 });
18513 }
18514 return (this.manipulated = node);
18515 }
18516 }
18517 function get_function_name(_node, parent) {
18518 if (parent.type === 'EventHandler') {
18519 return `${parent.name}_handler`;
18520 }
18521 if (parent.type === 'Action') {
18522 return `${parent.name}_function`;
18523 }
18524 return 'func';
18525 }
18526 function is_contextual(component, scope, name) {
18527 if (is_reserved_keyword(name))
18528 return true;
18529 // if it's a name below root scope, it's contextual
18530 if (!scope.is_top_level(name))
18531 return true;
18532 const variable = component.var_lookup.get(name);
18533 // hoistables, module declarations, and imports are non-contextual
18534 if (!variable || variable.hoistable)
18535 return false;
18536 // assume contextual
18537 return true;
18538 }
18539
18540 class Action extends Node$1 {
18541 constructor(component, parent, scope, info) {
18542 super(component, parent, scope, info);
18543 component.warn_if_undefined(info.name, info, scope);
18544 this.name = info.name;
18545 component.add_reference(info.name.split('.')[0]);
18546 this.expression = info.expression
18547 ? new Expression(component, this, scope, info.expression)
18548 : null;
18549 this.uses_context = this.expression && this.expression.uses_context;
18550 }
18551 }
18552
18553 class Tag extends Wrapper {
18554 constructor(renderer, block, parent, node) {
18555 super(renderer, block, parent, node);
18556 this.cannot_use_innerhtml();
18557 if (!this.is_dependencies_static()) {
18558 this.not_static_content();
18559 }
18560 block.add_dependencies(node.expression.dependencies);
18561 }
18562 is_dependencies_static() {
18563 return this.node.expression.contextual_dependencies.size === 0 && this.node.expression.dynamic_dependencies().length === 0;
18564 }
18565 rename_this_method(block, update) {
18566 const dependencies = this.node.expression.dynamic_dependencies();
18567 let snippet = this.node.expression.manipulate(block);
18568 const value = this.node.should_cache && block.get_unique_name(`${this.var.name}_value`);
18569 const content = this.node.should_cache ? value : snippet;
18570 snippet = x `${snippet} + ""`;
18571 if (this.node.should_cache)
18572 block.add_variable(value, snippet); // TODO may need to coerce snippet to string
18573 if (dependencies.length > 0) {
18574 let condition = block.renderer.dirty(dependencies);
18575 if (block.has_outros) {
18576 condition = x `!#current || ${condition}`;
18577 }
18578 const update_cached_value = x `${value} !== (${value} = ${snippet})`;
18579 if (this.node.should_cache) {
18580 condition = x `${condition} && ${update_cached_value}`;
18581 }
18582 block.chunks.update.push(b `if (${condition}) ${update(content)}`);
18583 }
18584 return { init: content };
18585 }
18586 }
18587
18588 class MustacheTagWrapper extends Tag {
18589 constructor(renderer, block, parent, node) {
18590 super(renderer, block, parent, node);
18591 this.var = { type: 'Identifier', name: 't' };
18592 }
18593 render(block, parent_node, parent_nodes) {
18594 const { init } = this.rename_this_method(block, value => x `@set_data(${this.var}, ${value})`);
18595 block.add_element(this.var, x `@text(${init})`, parent_nodes && x `@claim_text(${parent_nodes}, ${init})`, parent_node);
18596 }
18597 }
18598
18599 class RawMustacheTagWrapper extends Tag {
18600 constructor(renderer, block, parent, node) {
18601 super(renderer, block, parent, node);
18602 this.var = { type: 'Identifier', name: 'raw' };
18603 this.cannot_use_innerhtml();
18604 this.not_static_content();
18605 }
18606 render(block, parent_node, _parent_nodes) {
18607 const in_head = is_head(parent_node);
18608 const can_use_innerhtml = !in_head && parent_node && !this.prev && !this.next;
18609 if (can_use_innerhtml) {
18610 const insert = content => b `${parent_node}.innerHTML = ${content};`[0];
18611 const { init } = this.rename_this_method(block, content => insert(content));
18612 block.chunks.mount.push(insert(init));
18613 }
18614 else {
18615 const needs_anchor = in_head || (this.next ? !this.next.is_dom_node() : (!this.parent || !this.parent.is_dom_node()));
18616 const html_tag = block.get_unique_name('html_tag');
18617 const html_anchor = needs_anchor && block.get_unique_name('html_anchor');
18618 block.add_variable(html_tag);
18619 const { init } = this.rename_this_method(block, content => x `${html_tag}.p(${content})`);
18620 const update_anchor = needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
18621 block.chunks.hydrate.push(b `${html_tag} = new @HtmlTag(${update_anchor});`);
18622 block.chunks.mount.push(b `${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`);
18623 if (needs_anchor) {
18624 block.add_element(html_anchor, x `@empty()`, x `@empty()`, parent_node);
18625 }
18626 if (!parent_node || in_head) {
18627 block.chunks.destroy.push(b `if (detaching) ${html_tag}.d();`);
18628 }
18629 }
18630 }
18631 }
18632
18633 const events = [
18634 {
18635 event_names: ['input'],
18636 filter: (node, _name) => node.name === 'textarea' ||
18637 node.name === 'input' && !/radio|checkbox|range|file/.test(node.get_static_attribute_value('type'))
18638 },
18639 {
18640 event_names: ['input'],
18641 filter: (node, name) => (name === 'textContent' || name === 'innerHTML') &&
18642 node.attributes.some(attribute => attribute.name === 'contenteditable')
18643 },
18644 {
18645 event_names: ['change'],
18646 filter: (node, _name) => node.name === 'select' ||
18647 node.name === 'input' && /radio|checkbox|file/.test(node.get_static_attribute_value('type'))
18648 },
18649 {
18650 event_names: ['change', 'input'],
18651 filter: (node, _name) => node.name === 'input' && node.get_static_attribute_value('type') === 'range'
18652 },
18653 {
18654 event_names: ['elementresize'],
18655 filter: (_node, name) => dimensions.test(name)
18656 },
18657 // media events
18658 {
18659 event_names: ['timeupdate'],
18660 filter: (node, name) => node.is_media_node() &&
18661 (name === 'currentTime' || name === 'played' || name === 'ended')
18662 },
18663 {
18664 event_names: ['durationchange'],
18665 filter: (node, name) => node.is_media_node() &&
18666 name === 'duration'
18667 },
18668 {
18669 event_names: ['play', 'pause'],
18670 filter: (node, name) => node.is_media_node() &&
18671 name === 'paused'
18672 },
18673 {
18674 event_names: ['progress'],
18675 filter: (node, name) => node.is_media_node() &&
18676 name === 'buffered'
18677 },
18678 {
18679 event_names: ['loadedmetadata'],
18680 filter: (node, name) => node.is_media_node() &&
18681 (name === 'buffered' || name === 'seekable')
18682 },
18683 {
18684 event_names: ['volumechange'],
18685 filter: (node, name) => node.is_media_node() &&
18686 (name === 'volume' || name === 'muted')
18687 },
18688 {
18689 event_names: ['ratechange'],
18690 filter: (node, name) => node.is_media_node() &&
18691 name === 'playbackRate'
18692 },
18693 {
18694 event_names: ['seeking', 'seeked'],
18695 filter: (node, name) => node.is_media_node() &&
18696 (name === 'seeking')
18697 },
18698 {
18699 event_names: ['ended'],
18700 filter: (node, name) => node.is_media_node() &&
18701 name === 'ended'
18702 },
18703 {
18704 event_names: ['resize'],
18705 filter: (node, name) => node.is_media_node() &&
18706 (name === 'videoHeight' || name === 'videoWidth')
18707 },
18708 // details event
18709 {
18710 event_names: ['toggle'],
18711 filter: (node, _name) => node.name === 'details'
18712 },
18713 ];
18714 class ElementWrapper extends Wrapper {
18715 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
18716 super(renderer, block, parent, node);
18717 this.var = {
18718 type: 'Identifier',
18719 name: node.name.replace(/[^a-zA-Z0-9_$]/g, '_')
18720 };
18721 this.void = is_void(node.name);
18722 this.class_dependencies = [];
18723 if (this.node.children.length) {
18724 this.node.lets.forEach(l => {
18725 extract_names(l.value || l.name).forEach(name => {
18726 renderer.add_to_context(name, true);
18727 });
18728 });
18729 }
18730 this.attributes = this.node.attributes.map(attribute => {
18731 if (attribute.name === 'slot') {
18732 // TODO make separate subclass for this?
18733 let owner = this.parent;
18734 while (owner) {
18735 if (owner.node.type === 'InlineComponent') {
18736 break;
18737 }
18738 if (owner.node.type === 'Element' && /-/.test(owner.node.name)) {
18739 break;
18740 }
18741 owner = owner.parent;
18742 }
18743 if (owner && owner.node.type === 'InlineComponent') {
18744 const name = attribute.get_static_value();
18745 if (!owner.slots.has(name)) {
18746 const child_block = block.child({
18747 comment: create_debugging_comment(node, this.renderer.component),
18748 name: this.renderer.component.get_unique_name(`create_${sanitize(name)}_slot`),
18749 type: 'slot'
18750 });
18751 const { scope, lets } = this.node;
18752 const seen = new Set(lets.map(l => l.name.name));
18753 owner.node.lets.forEach(l => {
18754 if (!seen.has(l.name.name))
18755 lets.push(l);
18756 });
18757 owner.slots.set(name, get_slot_definition(child_block, scope, lets));
18758 this.renderer.blocks.push(child_block);
18759 }
18760 this.slot_block = owner.slots.get(name).block;
18761 block = this.slot_block;
18762 }
18763 }
18764 if (attribute.name === 'style') {
18765 return new StyleAttributeWrapper(this, block, attribute);
18766 }
18767 if (attribute.type === 'Spread') {
18768 return new SpreadAttributeWrapper(this, block, attribute);
18769 }
18770 return new AttributeWrapper(this, block, attribute);
18771 });
18772 // ordinarily, there'll only be one... but we need to handle
18773 // the rare case where an element can have multiple bindings,
18774 // e.g. <audio bind:paused bind:currentTime>
18775 this.bindings = this.node.bindings.map(binding => new BindingWrapper(block, binding, this));
18776 this.event_handlers = this.node.handlers.map(event_handler => new EventHandlerWrapper(event_handler, this));
18777 if (node.intro || node.outro) {
18778 if (node.intro)
18779 block.add_intro(node.intro.is_local);
18780 if (node.outro)
18781 block.add_outro(node.outro.is_local);
18782 }
18783 if (node.animation) {
18784 block.add_animation();
18785 }
18786 // add directive and handler dependencies
18787 [node.animation, node.outro, ...node.actions, ...node.classes].forEach(directive => {
18788 if (directive && directive.expression) {
18789 block.add_dependencies(directive.expression.dependencies);
18790 }
18791 });
18792 node.handlers.forEach(handler => {
18793 if (handler.expression) {
18794 block.add_dependencies(handler.expression.dependencies);
18795 }
18796 });
18797 if (this.parent) {
18798 if (node.actions.length > 0 ||
18799 node.animation ||
18800 node.bindings.length > 0 ||
18801 node.classes.length > 0 ||
18802 node.intro || node.outro ||
18803 node.handlers.length > 0 ||
18804 this.node.name === 'option' ||
18805 renderer.options.dev) {
18806 this.parent.cannot_use_innerhtml(); // need to use add_location
18807 this.parent.not_static_content();
18808 }
18809 }
18810 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
18811 if (this.slot_block) {
18812 block.parent.add_dependencies(block.dependencies);
18813 // appalling hack
18814 const index = block.parent.wrappers.indexOf(this);
18815 block.parent.wrappers.splice(index, 1);
18816 block.wrappers.push(this);
18817 }
18818 }
18819 render(block, parent_node, parent_nodes) {
18820 const { renderer } = this;
18821 if (this.node.name === 'noscript')
18822 return;
18823 if (this.slot_block) {
18824 block = this.slot_block;
18825 }
18826 const node = this.var;
18827 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
18828 const children = x `@children(${this.node.name === 'template' ? x `${node}.content` : node})`;
18829 block.add_variable(node);
18830 const render_statement = this.get_render_statement(block);
18831 block.chunks.create.push(b `${node} = ${render_statement};`);
18832 if (renderer.options.hydratable) {
18833 if (parent_nodes) {
18834 block.chunks.claim.push(b `
18835 ${node} = ${this.get_claim_statement(parent_nodes)};
18836 `);
18837 if (!this.void && this.node.children.length > 0) {
18838 block.chunks.claim.push(b `
18839 var ${nodes} = ${children};
18840 `);
18841 }
18842 }
18843 else {
18844 block.chunks.claim.push(b `${node} = ${render_statement};`);
18845 }
18846 }
18847 if (parent_node) {
18848 block.chunks.mount.push(b `@append(${parent_node}, ${node});`);
18849 if (is_head(parent_node)) {
18850 block.chunks.destroy.push(b `@detach(${node});`);
18851 }
18852 }
18853 else {
18854 block.chunks.mount.push(b `@insert(#target, ${node}, #anchor);`);
18855 // TODO we eventually need to consider what happens to elements
18856 // that belong to the same outgroup as an outroing element...
18857 block.chunks.destroy.push(b `if (detaching) @detach(${node});`);
18858 }
18859 // insert static children with textContent or innerHTML
18860 const can_use_textcontent = this.can_use_textcontent();
18861 if (!this.node.namespace && (this.can_use_innerhtml || can_use_textcontent) && this.fragment.nodes.length > 0) {
18862 if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
18863 block.chunks.create.push(b `${node}.textContent = ${string_literal(this.fragment.nodes[0].data)};`);
18864 }
18865 else {
18866 const state = {
18867 quasi: {
18868 type: 'TemplateElement',
18869 value: { raw: '' }
18870 }
18871 };
18872 const literal = {
18873 type: 'TemplateLiteral',
18874 expressions: [],
18875 quasis: []
18876 };
18877 const can_use_raw_text = !this.can_use_innerhtml && can_use_textcontent;
18878 to_html(this.fragment.nodes, block, literal, state, can_use_raw_text);
18879 literal.quasis.push(state.quasi);
18880 block.chunks.create.push(b `${node}.${this.can_use_innerhtml ? 'innerHTML' : 'textContent'} = ${literal};`);
18881 }
18882 }
18883 else {
18884 this.fragment.nodes.forEach((child) => {
18885 child.render(block, this.node.name === 'template' ? x `${node}.content` : node, nodes);
18886 });
18887 }
18888 const event_handler_or_binding_uses_context = (this.bindings.some(binding => binding.handler.uses_context) ||
18889 this.node.handlers.some(handler => handler.uses_context) ||
18890 this.node.actions.some(action => action.uses_context));
18891 if (event_handler_or_binding_uses_context) {
18892 block.maintain_context = true;
18893 }
18894 this.add_attributes(block);
18895 this.add_directives_in_order(block);
18896 this.add_transitions(block);
18897 this.add_animation(block);
18898 this.add_classes(block);
18899 this.add_manual_style_scoping(block);
18900 if (nodes && this.renderer.options.hydratable && !this.void) {
18901 block.chunks.claim.push(b `${this.node.children.length > 0 ? nodes : children}.forEach(@detach);`);
18902 }
18903 if (renderer.options.dev) {
18904 const loc = renderer.locate(this.node.start);
18905 block.chunks.hydrate.push(b `@add_location(${this.var}, ${renderer.file_var}, ${loc.line - 1}, ${loc.column}, ${this.node.start});`);
18906 }
18907 }
18908 can_use_textcontent() {
18909 return this.is_static_content && this.fragment.nodes.every(node => node.node.type === 'Text' || node.node.type === 'MustacheTag');
18910 }
18911 get_render_statement(block) {
18912 const { name, namespace } = this.node;
18913 if (namespace === namespaces.svg) {
18914 return x `@svg_element("${name}")`;
18915 }
18916 if (namespace) {
18917 return x `@_document.createElementNS("${namespace}", "${name}")`;
18918 }
18919 const is = this.attributes.find(attr => attr.node.name === 'is');
18920 if (is) {
18921 return x `@element_is("${name}", ${is.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`)})`;
18922 }
18923 return x `@element("${name}")`;
18924 }
18925 get_claim_statement(nodes) {
18926 const attributes = this.node.attributes
18927 .filter((attr) => attr.type === 'Attribute')
18928 .map((attr) => p `${attr.name}: true`);
18929 const name = this.node.namespace
18930 ? this.node.name
18931 : this.node.name.toUpperCase();
18932 const svg = this.node.namespace === namespaces.svg ? 1 : null;
18933 return x `@claim_element(${nodes}, "${name}", { ${attributes} }, ${svg})`;
18934 }
18935 add_directives_in_order(block) {
18936 const binding_groups = events
18937 .map(event => ({
18938 events: event.event_names,
18939 bindings: this.bindings
18940 .filter(binding => binding.node.name !== 'this')
18941 .filter(binding => event.filter(this.node, binding.node.name))
18942 }))
18943 .filter(group => group.bindings.length);
18944 const this_binding = this.bindings.find(b => b.node.name === 'this');
18945 function getOrder(item) {
18946 if (item instanceof EventHandlerWrapper) {
18947 return item.node.start;
18948 }
18949 else if (item instanceof BindingWrapper) {
18950 return item.node.start;
18951 }
18952 else if (item instanceof Action) {
18953 return item.start;
18954 }
18955 else {
18956 return item.bindings[0].node.start;
18957 }
18958 }
18959 [
18960 ...binding_groups,
18961 ...this.event_handlers,
18962 this_binding,
18963 ...this.node.actions
18964 ]
18965 .filter(Boolean)
18966 .sort((a, b) => getOrder(a) - getOrder(b))
18967 .forEach(item => {
18968 if (item instanceof EventHandlerWrapper) {
18969 add_event_handler(block, this.var, item);
18970 }
18971 else if (item instanceof BindingWrapper) {
18972 this.add_this_binding(block, item);
18973 }
18974 else if (item instanceof Action) {
18975 add_action(block, this.var, item);
18976 }
18977 else {
18978 this.add_bindings(block, item);
18979 }
18980 });
18981 }
18982 add_bindings(block, binding_group) {
18983 const { renderer } = this;
18984 if (binding_group.bindings.length === 0)
18985 return;
18986 renderer.component.has_reactive_assignments = true;
18987 const lock = binding_group.bindings.some(binding => binding.needs_lock) ?
18988 block.get_unique_name(`${this.var.name}_updating`) :
18989 null;
18990 if (lock)
18991 block.add_variable(lock, x `false`);
18992 const handler = renderer.component.get_unique_name(`${this.var.name}_${binding_group.events.join('_')}_handler`);
18993 renderer.add_to_context(handler.name);
18994 // TODO figure out how to handle locks
18995 const needs_lock = binding_group.bindings.some(binding => binding.needs_lock);
18996 const dependencies = new Set();
18997 const contextual_dependencies = new Set();
18998 binding_group.bindings.forEach(binding => {
18999 // TODO this is a mess
19000 add_to_set(dependencies, binding.get_dependencies());
19001 add_to_set(contextual_dependencies, binding.handler.contextual_dependencies);
19002 binding.render(block, lock);
19003 });
19004 // media bindings — awkward special case. The native timeupdate events
19005 // fire too infrequently, so we need to take matters into our
19006 // own hands
19007 let animation_frame;
19008 if (binding_group.events[0] === 'timeupdate') {
19009 animation_frame = block.get_unique_name(`${this.var.name}_animationframe`);
19010 block.add_variable(animation_frame);
19011 }
19012 const has_local_function = contextual_dependencies.size > 0 || needs_lock || animation_frame;
19013 let callee = renderer.reference(handler);
19014 // TODO dry this out — similar code for event handlers and component bindings
19015 if (has_local_function) {
19016 const args = Array.from(contextual_dependencies).map(name => renderer.reference(name));
19017 // need to create a block-local function that calls an instance-level function
19018 if (animation_frame) {
19019 block.chunks.init.push(b `
19020 function ${handler}() {
19021 @_cancelAnimationFrame(${animation_frame});
19022 if (!${this.var}.paused) {
19023 ${animation_frame} = @raf(${handler});
19024 ${needs_lock && b `${lock} = true;`}
19025 }
19026 ${callee}.call(${this.var}, ${args});
19027 }
19028 `);
19029 }
19030 else {
19031 block.chunks.init.push(b `
19032 function ${handler}() {
19033 ${needs_lock && b `${lock} = true;`}
19034 ${callee}.call(${this.var}, ${args});
19035 }
19036 `);
19037 }
19038 callee = handler;
19039 }
19040 const params = Array.from(contextual_dependencies).map(name => ({
19041 type: 'Identifier',
19042 name
19043 }));
19044 this.renderer.component.partly_hoisted.push(b `
19045 function ${handler}(${params}) {
19046 ${binding_group.bindings.map(b => b.handler.mutation)}
19047 ${Array.from(dependencies)
19048 .filter(dep => dep[0] !== '$')
19049 .filter(dep => !contextual_dependencies.has(dep))
19050 .map(dep => b `${this.renderer.invalidate(dep)};`)}
19051 }
19052 `);
19053 binding_group.events.forEach(name => {
19054 if (name === 'elementresize') {
19055 // special case
19056 const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`);
19057 block.add_variable(resize_listener);
19058 block.chunks.mount.push(b `${resize_listener} = @add_resize_listener(${this.var}, ${callee}.bind(${this.var}));`);
19059 block.chunks.destroy.push(b `${resize_listener}();`);
19060 }
19061 else {
19062 block.event_listeners.push(x `@listen(${this.var}, "${name}", ${callee})`);
19063 }
19064 });
19065 const some_initial_state_is_undefined = binding_group.bindings
19066 .map(binding => x `${binding.snippet} === void 0`)
19067 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
19068 const should_initialise = (this.node.name === 'select' ||
19069 binding_group.bindings.find(binding => {
19070 return (binding.node.name === 'indeterminate' ||
19071 binding.node.name === 'textContent' ||
19072 binding.node.name === 'innerHTML' ||
19073 binding.is_readonly_media_attribute());
19074 }));
19075 if (should_initialise) {
19076 const callback = has_local_function ? handler : x `() => ${callee}.call(${this.var})`;
19077 block.chunks.hydrate.push(b `if (${some_initial_state_is_undefined}) @add_render_callback(${callback});`);
19078 }
19079 if (binding_group.events[0] === 'elementresize') {
19080 block.chunks.hydrate.push(b `@add_render_callback(() => ${callee}.call(${this.var}));`);
19081 }
19082 if (lock) {
19083 block.chunks.update.push(b `${lock} = false;`);
19084 }
19085 }
19086 add_this_binding(block, this_binding) {
19087 const { renderer } = this;
19088 renderer.component.has_reactive_assignments = true;
19089 const binding_callback = bind_this(renderer.component, block, this_binding, this.var);
19090 block.chunks.mount.push(binding_callback);
19091 }
19092 add_attributes(block) {
19093 // Get all the class dependencies first
19094 this.attributes.forEach((attribute) => {
19095 if (attribute.node.name === 'class') {
19096 const dependencies = attribute.node.get_dependencies();
19097 this.class_dependencies.push(...dependencies);
19098 }
19099 });
19100 if (this.node.attributes.some(attr => attr.is_spread)) {
19101 this.add_spread_attributes(block);
19102 return;
19103 }
19104 this.attributes.forEach((attribute) => {
19105 attribute.render(block);
19106 });
19107 }
19108 add_spread_attributes(block) {
19109 const levels = block.get_unique_name(`${this.var.name}_levels`);
19110 const data = block.get_unique_name(`${this.var.name}_data`);
19111 const initial_props = [];
19112 const updates = [];
19113 this.attributes
19114 .forEach(attr => {
19115 const dependencies = attr.node.get_dependencies();
19116 const condition = dependencies.length > 0
19117 ? block.renderer.dirty(dependencies)
19118 : null;
19119 if (attr instanceof SpreadAttributeWrapper) {
19120 const snippet = attr.node.expression.manipulate(block);
19121 initial_props.push(snippet);
19122 updates.push(condition ? x `${condition} && ${snippet}` : snippet);
19123 }
19124 else {
19125 const name = attr.property_name || attr.name;
19126 initial_props.push(x `{ ${name}: ${attr.get_init(block, attr.get_value(block))} }`);
19127 const snippet = x `{ ${name}: ${attr.should_cache ? attr.last : attr.get_value(block)} }`;
19128 updates.push(condition ? x `${attr.get_dom_update_conditions(block, condition)} && ${snippet}` : snippet);
19129 }
19130 });
19131 block.chunks.init.push(b `
19132 let ${levels} = [${initial_props}];
19133
19134 let ${data} = {};
19135 for (let #i = 0; #i < ${levels}.length; #i += 1) {
19136 ${data} = @assign(${data}, ${levels}[#i]);
19137 }
19138 `);
19139 const fn = this.node.namespace === namespaces.svg ? x `@set_svg_attributes` : x `@set_attributes`;
19140 block.chunks.hydrate.push(b `${fn}(${this.var}, ${data});`);
19141 block.chunks.update.push(b `
19142 ${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
19143 ${updates}
19144 ]));
19145 `);
19146 // handle edge cases for elements
19147 if (this.node.name === 'select') {
19148 const dependencies = new Set();
19149 for (const attr of this.attributes) {
19150 for (const dep of attr.node.dependencies) {
19151 dependencies.add(dep);
19152 }
19153 }
19154 block.chunks.mount.push(b `
19155 if (${data}.multiple) @select_options(${this.var}, ${data}.value);
19156 `);
19157 block.chunks.update.push(b `
19158 if (${block.renderer.dirty(Array.from(dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value);
19159 `);
19160 }
19161 }
19162 add_transitions(block) {
19163 const { intro, outro } = this.node;
19164 if (!intro && !outro)
19165 return;
19166 if (intro === outro) {
19167 // bidirectional transition
19168 const name = block.get_unique_name(`${this.var.name}_transition`);
19169 const snippet = intro.expression
19170 ? intro.expression.manipulate(block)
19171 : x `{}`;
19172 block.add_variable(name);
19173 const fn = this.renderer.reference(intro.name);
19174 const intro_block = b `
19175 @add_render_callback(() => {
19176 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, true);
19177 ${name}.run(1);
19178 });
19179 `;
19180 const outro_block = b `
19181 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, false);
19182 ${name}.run(0);
19183 `;
19184 if (intro.is_local) {
19185 block.chunks.intro.push(b `
19186 if (#local) {
19187 ${intro_block}
19188 }
19189 `);
19190 block.chunks.outro.push(b `
19191 if (#local) {
19192 ${outro_block}
19193 }
19194 `);
19195 }
19196 else {
19197 block.chunks.intro.push(intro_block);
19198 block.chunks.outro.push(outro_block);
19199 }
19200 block.chunks.destroy.push(b `if (detaching && ${name}) ${name}.end();`);
19201 }
19202 else {
19203 const intro_name = intro && block.get_unique_name(`${this.var.name}_intro`);
19204 const outro_name = outro && block.get_unique_name(`${this.var.name}_outro`);
19205 if (intro) {
19206 block.add_variable(intro_name);
19207 const snippet = intro.expression
19208 ? intro.expression.manipulate(block)
19209 : x `{}`;
19210 const fn = this.renderer.reference(intro.name);
19211 let intro_block;
19212 if (outro) {
19213 intro_block = b `
19214 @add_render_callback(() => {
19215 if (${outro_name}) ${outro_name}.end(1);
19216 if (!${intro_name}) ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
19217 ${intro_name}.start();
19218 });
19219 `;
19220 block.chunks.outro.push(b `if (${intro_name}) ${intro_name}.invalidate();`);
19221 }
19222 else {
19223 intro_block = b `
19224 if (!${intro_name}) {
19225 @add_render_callback(() => {
19226 ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
19227 ${intro_name}.start();
19228 });
19229 }
19230 `;
19231 }
19232 if (intro.is_local) {
19233 intro_block = b `
19234 if (#local) {
19235 ${intro_block}
19236 }
19237 `;
19238 }
19239 block.chunks.intro.push(intro_block);
19240 }
19241 if (outro) {
19242 block.add_variable(outro_name);
19243 const snippet = outro.expression
19244 ? outro.expression.manipulate(block)
19245 : x `{}`;
19246 const fn = this.renderer.reference(outro.name);
19247 if (!intro) {
19248 block.chunks.intro.push(b `
19249 if (${outro_name}) ${outro_name}.end(1);
19250 `);
19251 }
19252 // TODO hide elements that have outro'd (unless they belong to a still-outroing
19253 // group) prior to their removal from the DOM
19254 let outro_block = b `
19255 ${outro_name} = @create_out_transition(${this.var}, ${fn}, ${snippet});
19256 `;
19257 if (outro.is_local) {
19258 outro_block = b `
19259 if (#local) {
19260 ${outro_block}
19261 }
19262 `;
19263 }
19264 block.chunks.outro.push(outro_block);
19265 block.chunks.destroy.push(b `if (detaching && ${outro_name}) ${outro_name}.end();`);
19266 }
19267 }
19268 }
19269 add_animation(block) {
19270 if (!this.node.animation)
19271 return;
19272 const { outro } = this.node;
19273 const rect = block.get_unique_name('rect');
19274 const stop_animation = block.get_unique_name('stop_animation');
19275 block.add_variable(rect);
19276 block.add_variable(stop_animation, x `@noop`);
19277 block.chunks.measure.push(b `
19278 ${rect} = ${this.var}.getBoundingClientRect();
19279 `);
19280 block.chunks.fix.push(b `
19281 @fix_position(${this.var});
19282 ${stop_animation}();
19283 ${outro && b `@add_transform(${this.var}, ${rect});`}
19284 `);
19285 const params = this.node.animation.expression ? this.node.animation.expression.manipulate(block) : x `{}`;
19286 const name = this.renderer.reference(this.node.animation.name);
19287 block.chunks.animate.push(b `
19288 ${stop_animation}();
19289 ${stop_animation} = @create_animation(${this.var}, ${rect}, ${name}, ${params});
19290 `);
19291 }
19292 add_classes(block) {
19293 const has_spread = this.node.attributes.some(attr => attr.is_spread);
19294 this.node.classes.forEach(class_directive => {
19295 const { expression, name } = class_directive;
19296 let snippet;
19297 let dependencies;
19298 if (expression) {
19299 snippet = expression.manipulate(block);
19300 dependencies = expression.dependencies;
19301 }
19302 else {
19303 snippet = name;
19304 dependencies = new Set([name]);
19305 }
19306 const updater = b `@toggle_class(${this.var}, "${name}", ${snippet});`;
19307 block.chunks.hydrate.push(updater);
19308 if (has_spread) {
19309 block.chunks.update.push(updater);
19310 }
19311 else if ((dependencies && dependencies.size > 0) || this.class_dependencies.length) {
19312 const all_dependencies = this.class_dependencies.concat(...dependencies);
19313 const condition = block.renderer.dirty(all_dependencies);
19314 block.chunks.update.push(b `
19315 if (${condition}) {
19316 ${updater}
19317 }`);
19318 }
19319 });
19320 }
19321 add_manual_style_scoping(block) {
19322 if (this.node.needs_manual_style_scoping) {
19323 const updater = b `@toggle_class(${this.var}, "${this.node.component.stylesheet.id}", true);`;
19324 block.chunks.hydrate.push(updater);
19325 block.chunks.update.push(updater);
19326 }
19327 }
19328 }
19329 function to_html(wrappers, block, literal, state, can_use_raw_text) {
19330 wrappers.forEach(wrapper => {
19331 if (wrapper instanceof TextWrapper) {
19332 if (wrapper.use_space())
19333 state.quasi.value.raw += ' ';
19334 const parent = wrapper.node.parent;
19335 const raw = parent && (parent.name === 'script' ||
19336 parent.name === 'style' ||
19337 can_use_raw_text);
19338 state.quasi.value.raw += (raw ? wrapper.data : escape_html(wrapper.data))
19339 .replace(/\\/g, '\\\\')
19340 .replace(/`/g, '\\`')
19341 .replace(/\$/g, '\\$');
19342 }
19343 else if (wrapper instanceof MustacheTagWrapper || wrapper instanceof RawMustacheTagWrapper) {
19344 literal.quasis.push(state.quasi);
19345 literal.expressions.push(wrapper.node.expression.manipulate(block));
19346 state.quasi = {
19347 type: 'TemplateElement',
19348 value: { raw: '' }
19349 };
19350 }
19351 else if (wrapper.node.name === 'noscript') ;
19352 else {
19353 // element
19354 state.quasi.value.raw += `<${wrapper.node.name}`;
19355 wrapper.attributes.forEach((attr) => {
19356 state.quasi.value.raw += ` ${fix_attribute_casing(attr.node.name)}="`;
19357 attr.node.chunks.forEach(chunk => {
19358 if (chunk.type === 'Text') {
19359 state.quasi.value.raw += escape_html(chunk.data);
19360 }
19361 else {
19362 literal.quasis.push(state.quasi);
19363 literal.expressions.push(chunk.manipulate(block));
19364 state.quasi = {
19365 type: 'TemplateElement',
19366 value: { raw: '' }
19367 };
19368 }
19369 });
19370 state.quasi.value.raw += `"`;
19371 });
19372 state.quasi.value.raw += '>';
19373 if (!wrapper.void) {
19374 to_html(wrapper.fragment.nodes, block, literal, state);
19375 state.quasi.value.raw += `</${wrapper.node.name}>`;
19376 }
19377 }
19378 });
19379 }
19380
19381 class HeadWrapper extends Wrapper {
19382 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19383 super(renderer, block, parent, node);
19384 this.can_use_innerhtml = false;
19385 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
19386 }
19387 render(block, _parent_node, _parent_nodes) {
19388 let nodes;
19389 if (this.renderer.options.hydratable && this.fragment.nodes.length) {
19390 nodes = block.get_unique_name('head_nodes');
19391 block.chunks.claim.push(b `const ${nodes} = @query_selector_all('[data-svelte="${this.node.id}"]', @_document.head);`);
19392 }
19393 this.fragment.render(block, x `@_document.head`, nodes);
19394 if (nodes && this.renderer.options.hydratable) {
19395 block.chunks.claim.push(b `${nodes}.forEach(@detach);`);
19396 }
19397 }
19398 }
19399
19400 function is_else_if(node) {
19401 return (node && node.children.length === 1 && node.children[0].type === 'IfBlock');
19402 }
19403 class IfBlockBranch extends Wrapper {
19404 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19405 super(renderer, block, parent, node);
19406 this.var = null;
19407 const { expression } = node;
19408 const is_else = !expression;
19409 if (expression) {
19410 this.dependencies = expression.dynamic_dependencies();
19411 // TODO is this the right rule? or should any non-reference count?
19412 // const should_cache = !is_reference(expression.node, null) && dependencies.length > 0;
19413 let should_cache = false;
19414 walk(expression.node, {
19415 enter(node) {
19416 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
19417 should_cache = true;
19418 }
19419 }
19420 });
19421 if (should_cache) {
19422 this.condition = block.get_unique_name(`show_if`);
19423 this.snippet = expression.manipulate(block);
19424 }
19425 else {
19426 this.condition = expression.manipulate(block);
19427 }
19428 }
19429 this.block = block.child({
19430 comment: create_debugging_comment(node, parent.renderer.component),
19431 name: parent.renderer.component.get_unique_name(is_else ? `create_else_block` : `create_if_block`),
19432 type: node.expression ? 'if' : 'else'
19433 });
19434 this.fragment = new FragmentWrapper(renderer, this.block, node.children, parent, strip_whitespace, next_sibling);
19435 this.is_dynamic = this.block.dependencies.size > 0;
19436 }
19437 }
19438 class IfBlockWrapper extends Wrapper {
19439 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19440 super(renderer, block, parent, node);
19441 this.needs_update = false;
19442 this.var = { type: 'Identifier', name: 'if_block' };
19443 this.cannot_use_innerhtml();
19444 this.not_static_content();
19445 this.branches = [];
19446 const blocks = [];
19447 let is_dynamic = false;
19448 let has_intros = false;
19449 let has_outros = false;
19450 const create_branches = (node) => {
19451 const branch = new IfBlockBranch(renderer, block, this, node, strip_whitespace, next_sibling);
19452 this.branches.push(branch);
19453 blocks.push(branch.block);
19454 block.add_dependencies(node.expression.dependencies);
19455 if (branch.block.dependencies.size > 0) {
19456 // the condition, or its contents, is dynamic
19457 is_dynamic = true;
19458 block.add_dependencies(branch.block.dependencies);
19459 }
19460 if (branch.dependencies && branch.dependencies.length > 0) {
19461 // the condition itself is dynamic
19462 this.needs_update = true;
19463 }
19464 if (branch.block.has_intros)
19465 has_intros = true;
19466 if (branch.block.has_outros)
19467 has_outros = true;
19468 if (is_else_if(node.else)) {
19469 create_branches(node.else.children[0]);
19470 }
19471 else if (node.else) {
19472 const branch = new IfBlockBranch(renderer, block, this, node.else, strip_whitespace, next_sibling);
19473 this.branches.push(branch);
19474 blocks.push(branch.block);
19475 if (branch.block.dependencies.size > 0) {
19476 is_dynamic = true;
19477 block.add_dependencies(branch.block.dependencies);
19478 }
19479 if (branch.block.has_intros)
19480 has_intros = true;
19481 if (branch.block.has_outros)
19482 has_outros = true;
19483 }
19484 };
19485 create_branches(this.node);
19486 blocks.forEach(block => {
19487 block.has_update_method = is_dynamic;
19488 block.has_intro_method = has_intros;
19489 block.has_outro_method = has_outros;
19490 });
19491 renderer.blocks.push(...blocks);
19492 }
19493 render(block, parent_node, parent_nodes) {
19494 const name = this.var;
19495 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
19496 const anchor = needs_anchor
19497 ? block.get_unique_name(`${this.var.name}_anchor`)
19498 : (this.next && this.next.var) || 'null';
19499 const has_else = !(this.branches[this.branches.length - 1].condition);
19500 const if_exists_condition = has_else ? null : name;
19501 const dynamic = this.branches[0].block.has_update_method; // can use [0] as proxy for all, since they necessarily have the same value
19502 const has_intros = this.branches[0].block.has_intro_method;
19503 const has_outros = this.branches[0].block.has_outro_method;
19504 const has_transitions = has_intros || has_outros;
19505 const vars = { name, anchor, if_exists_condition, has_else, has_transitions };
19506 const detaching = parent_node && !is_head(parent_node) ? null : 'detaching';
19507 if (this.node.else) {
19508 this.branches.forEach(branch => {
19509 if (branch.snippet)
19510 block.add_variable(branch.condition);
19511 });
19512 if (has_outros) {
19513 this.render_compound_with_outros(block, parent_node, parent_nodes, dynamic, vars, detaching);
19514 block.chunks.outro.push(b `@transition_out(${name});`);
19515 }
19516 else {
19517 this.render_compound(block, parent_node, parent_nodes, dynamic, vars, detaching);
19518 }
19519 }
19520 else {
19521 this.render_simple(block, parent_node, parent_nodes, dynamic, vars, detaching);
19522 if (has_outros) {
19523 block.chunks.outro.push(b `@transition_out(${name});`);
19524 }
19525 }
19526 if (if_exists_condition) {
19527 block.chunks.create.push(b `if (${if_exists_condition}) ${name}.c();`);
19528 }
19529 else {
19530 block.chunks.create.push(b `${name}.c();`);
19531 }
19532 if (parent_nodes && this.renderer.options.hydratable) {
19533 if (if_exists_condition) {
19534 block.chunks.claim.push(b `if (${if_exists_condition}) ${name}.l(${parent_nodes});`);
19535 }
19536 else {
19537 block.chunks.claim.push(b `${name}.l(${parent_nodes});`);
19538 }
19539 }
19540 if (has_intros || has_outros) {
19541 block.chunks.intro.push(b `@transition_in(${name});`);
19542 }
19543 if (needs_anchor) {
19544 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
19545 }
19546 this.branches.forEach(branch => {
19547 branch.fragment.render(branch.block, null, x `#nodes`);
19548 });
19549 }
19550 render_compound(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, if_exists_condition, has_transitions }, detaching) {
19551 const select_block_type = this.renderer.component.get_unique_name(`select_block_type`);
19552 const current_block_type = block.get_unique_name(`current_block_type`);
19553 const get_block = has_else
19554 ? x `${current_block_type}(#ctx)`
19555 : x `${current_block_type} && ${current_block_type}(#ctx)`;
19556 if (this.needs_update) {
19557 block.chunks.init.push(b `
19558 function ${select_block_type}(#ctx, #dirty) {
19559 ${this.branches.map(({ dependencies, condition, snippet, block }) => condition
19560 ? b `
19561 ${snippet && (dependencies.length > 0
19562 ? b `if (${condition} == null || ${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
19563 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
19564 if (${condition}) return ${block.name};`
19565 : b `return ${block.name};`)}
19566 }
19567 `);
19568 }
19569 else {
19570 block.chunks.init.push(b `
19571 function ${select_block_type}(#ctx, #dirty) {
19572 ${this.branches.map(({ condition, snippet, block }) => condition
19573 ? b `if (${snippet || condition}) return ${block.name};`
19574 : b `return ${block.name};`)}
19575 }
19576 `);
19577 }
19578 block.chunks.init.push(b `
19579 let ${current_block_type} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
19580 let ${name} = ${get_block};
19581 `);
19582 const initial_mount_node = parent_node || '#target';
19583 const anchor_node = parent_node ? 'null' : '#anchor';
19584 if (if_exists_condition) {
19585 block.chunks.mount.push(b `if (${if_exists_condition}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
19586 }
19587 else {
19588 block.chunks.mount.push(b `${name}.m(${initial_mount_node}, ${anchor_node});`);
19589 }
19590 if (this.needs_update) {
19591 const update_mount_node = this.get_update_mount_node(anchor);
19592 const change_block = b `
19593 ${if_exists_condition ? b `if (${if_exists_condition}) ${name}.d(1)` : b `${name}.d(1)`};
19594 ${name} = ${get_block};
19595 if (${name}) {
19596 ${name}.c();
19597 ${has_transitions && b `@transition_in(${name}, 1);`}
19598 ${name}.m(${update_mount_node}, ${anchor});
19599 }
19600 `;
19601 if (dynamic) {
19602 block.chunks.update.push(b `
19603 if (${current_block_type} === (${current_block_type} = ${select_block_type}(#ctx, #dirty)) && ${name}) {
19604 ${name}.p(#ctx, #dirty);
19605 } else {
19606 ${change_block}
19607 }
19608 `);
19609 }
19610 else {
19611 block.chunks.update.push(b `
19612 if (${current_block_type} !== (${current_block_type} = ${select_block_type}(#ctx, #dirty))) {
19613 ${change_block}
19614 }
19615 `);
19616 }
19617 }
19618 else if (dynamic) {
19619 if (if_exists_condition) {
19620 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
19621 }
19622 else {
19623 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
19624 }
19625 }
19626 if (if_exists_condition) {
19627 block.chunks.destroy.push(b `
19628 if (${if_exists_condition}) {
19629 ${name}.d(${detaching});
19630 }
19631 `);
19632 }
19633 else {
19634 block.chunks.destroy.push(b `
19635 ${name}.d(${detaching});
19636 `);
19637 }
19638 }
19639 // if any of the siblings have outros, we need to keep references to the blocks
19640 // (TODO does this only apply to bidi transitions?)
19641 render_compound_with_outros(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, has_transitions, if_exists_condition }, detaching) {
19642 const select_block_type = this.renderer.component.get_unique_name(`select_block_type`);
19643 const current_block_type_index = block.get_unique_name(`current_block_type_index`);
19644 const previous_block_index = block.get_unique_name(`previous_block_index`);
19645 const if_block_creators = block.get_unique_name(`if_block_creators`);
19646 const if_blocks = block.get_unique_name(`if_blocks`);
19647 const if_current_block_type_index = has_else
19648 ? nodes => nodes
19649 : nodes => b `if (~${current_block_type_index}) { ${nodes} }`;
19650 block.add_variable(current_block_type_index);
19651 block.add_variable(name);
19652 block.chunks.init.push(b `
19653 const ${if_block_creators} = [
19654 ${this.branches.map(branch => branch.block.name)}
19655 ];
19656
19657 const ${if_blocks} = [];
19658
19659 ${this.needs_update
19660 ? b `
19661 function ${select_block_type}(#ctx, #dirty) {
19662 ${this.branches.map(({ dependencies, condition, snippet }, i) => condition
19663 ? b `
19664 ${snippet && (dependencies.length > 0
19665 ? b `if (${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
19666 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
19667 if (${condition}) return ${i};`
19668 : b `return ${i};`)}
19669 ${!has_else && b `return -1;`}
19670 }
19671 `
19672 : b `
19673 function ${select_block_type}(#ctx, #dirty) {
19674 ${this.branches.map(({ condition, snippet }, i) => condition
19675 ? b `if (${snippet || condition}) return ${i};`
19676 : b `return ${i};`)}
19677 ${!has_else && b `return -1;`}
19678 }
19679 `}
19680 `);
19681 if (has_else) {
19682 block.chunks.init.push(b `
19683 ${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
19684 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19685 `);
19686 }
19687 else {
19688 block.chunks.init.push(b `
19689 if (~(${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}))) {
19690 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19691 }
19692 `);
19693 }
19694 const initial_mount_node = parent_node || '#target';
19695 const anchor_node = parent_node ? 'null' : '#anchor';
19696 block.chunks.mount.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].m(${initial_mount_node}, ${anchor_node});`));
19697 if (this.needs_update) {
19698 const update_mount_node = this.get_update_mount_node(anchor);
19699 const destroy_old_block = b `
19700 @group_outros();
19701 @transition_out(${if_blocks}[${previous_block_index}], 1, 1, () => {
19702 ${if_blocks}[${previous_block_index}] = null;
19703 });
19704 @check_outros();
19705 `;
19706 const create_new_block = b `
19707 ${name} = ${if_blocks}[${current_block_type_index}];
19708 if (!${name}) {
19709 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19710 ${name}.c();
19711 }
19712 ${has_transitions && b `@transition_in(${name}, 1);`}
19713 ${name}.m(${update_mount_node}, ${anchor});
19714 `;
19715 const change_block = has_else
19716 ? b `
19717 ${destroy_old_block}
19718
19719 ${create_new_block}
19720 `
19721 : b `
19722 if (${name}) {
19723 ${destroy_old_block}
19724 }
19725
19726 if (~${current_block_type_index}) {
19727 ${create_new_block}
19728 } else {
19729 ${name} = null;
19730 }
19731 `;
19732 if (dynamic) {
19733 block.chunks.update.push(b `
19734 let ${previous_block_index} = ${current_block_type_index};
19735 ${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
19736 if (${current_block_type_index} === ${previous_block_index}) {
19737 ${if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].p(#ctx, #dirty);`)}
19738 } else {
19739 ${change_block}
19740 }
19741 `);
19742 }
19743 else {
19744 block.chunks.update.push(b `
19745 let ${previous_block_index} = ${current_block_type_index};
19746 ${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
19747 if (${current_block_type_index} !== ${previous_block_index}) {
19748 ${change_block}
19749 }
19750 `);
19751 }
19752 }
19753 else if (dynamic) {
19754 if (if_exists_condition) {
19755 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
19756 }
19757 else {
19758 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
19759 }
19760 }
19761 block.chunks.destroy.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].d(${detaching});`));
19762 }
19763 render_simple(block, parent_node, _parent_nodes, dynamic, { name, anchor, if_exists_condition, has_transitions }, detaching) {
19764 const branch = this.branches[0];
19765 if (branch.snippet)
19766 block.add_variable(branch.condition, branch.snippet);
19767 block.chunks.init.push(b `
19768 let ${name} = ${branch.condition} && ${branch.block.name}(#ctx);
19769 `);
19770 const initial_mount_node = parent_node || '#target';
19771 const anchor_node = parent_node ? 'null' : '#anchor';
19772 block.chunks.mount.push(b `if (${name}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
19773 if (branch.dependencies.length > 0) {
19774 const update_mount_node = this.get_update_mount_node(anchor);
19775 const enter = b `
19776 if (${name}) {
19777 ${dynamic && b `${name}.p(#ctx, #dirty);`}
19778 ${has_transitions &&
19779 b `if (${block.renderer.dirty(branch.dependencies)}) {
19780 @transition_in(${name}, 1);
19781 }`}
19782 } else {
19783 ${name} = ${branch.block.name}(#ctx);
19784 ${name}.c();
19785 ${has_transitions && b `@transition_in(${name}, 1);`}
19786 ${name}.m(${update_mount_node}, ${anchor});
19787 }
19788 `;
19789 if (branch.snippet) {
19790 block.chunks.update.push(b `if (${block.renderer.dirty(branch.dependencies)}) ${branch.condition} = ${branch.snippet}`);
19791 }
19792 // no `p()` here — we don't want to update outroing nodes,
19793 // as that will typically result in glitching
19794 if (branch.block.has_outro_method) {
19795 block.chunks.update.push(b `
19796 if (${branch.condition}) {
19797 ${enter}
19798 } else if (${name}) {
19799 @group_outros();
19800 @transition_out(${name}, 1, 1, () => {
19801 ${name} = null;
19802 });
19803 @check_outros();
19804 }
19805 `);
19806 }
19807 else {
19808 block.chunks.update.push(b `
19809 if (${branch.condition}) {
19810 ${enter}
19811 } else if (${name}) {
19812 ${name}.d(1);
19813 ${name} = null;
19814 }
19815 `);
19816 }
19817 }
19818 else if (dynamic) {
19819 block.chunks.update.push(b `
19820 if (${branch.condition}) ${name}.p(#ctx, #dirty);
19821 `);
19822 }
19823 if (if_exists_condition) {
19824 block.chunks.destroy.push(b `
19825 if (${if_exists_condition}) ${name}.d(${detaching});
19826 `);
19827 }
19828 else {
19829 block.chunks.destroy.push(b `
19830 ${name}.d(${detaching});
19831 `);
19832 }
19833 }
19834 get_initial_dirty_bit() {
19835 const _this = this;
19836 // TODO: context-overflow make it less gross
19837 const val = x `-1`;
19838 return {
19839 get type() {
19840 return _this.renderer.context_overflow ? 'ArrayExpression' : 'UnaryExpression';
19841 },
19842 // as [-1]
19843 elements: [val],
19844 // as -1
19845 operator: val.operator,
19846 prefix: val.prefix,
19847 argument: val.argument,
19848 };
19849 }
19850 }
19851
19852 class InlineComponentWrapper extends Wrapper {
19853 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19854 super(renderer, block, parent, node);
19855 this.slots = new Map();
19856 this.cannot_use_innerhtml();
19857 this.not_static_content();
19858 if (this.node.expression) {
19859 block.add_dependencies(this.node.expression.dependencies);
19860 }
19861 this.node.attributes.forEach(attr => {
19862 block.add_dependencies(attr.dependencies);
19863 });
19864 this.node.bindings.forEach(binding => {
19865 if (binding.is_contextual) {
19866 mark_each_block_bindings(this, binding);
19867 }
19868 block.add_dependencies(binding.expression.dependencies);
19869 });
19870 this.node.handlers.forEach(handler => {
19871 if (handler.expression) {
19872 block.add_dependencies(handler.expression.dependencies);
19873 }
19874 });
19875 this.var = {
19876 type: 'Identifier',
19877 name: (this.node.name === 'svelte:self' ? renderer.component.name.name :
19878 this.node.name === 'svelte:component' ? 'switch_instance' :
19879 sanitize(this.node.name)).toLowerCase()
19880 };
19881 if (this.node.children.length) {
19882 this.node.lets.forEach(l => {
19883 extract_names(l.value || l.name).forEach(name => {
19884 renderer.add_to_context(name, true);
19885 });
19886 });
19887 const default_slot = block.child({
19888 comment: create_debugging_comment(node, renderer.component),
19889 name: renderer.component.get_unique_name(`create_default_slot`),
19890 type: 'slot'
19891 });
19892 this.renderer.blocks.push(default_slot);
19893 this.slots.set('default', get_slot_definition(default_slot, this.node.scope, this.node.lets));
19894 this.fragment = new FragmentWrapper(renderer, default_slot, node.children, this, strip_whitespace, next_sibling);
19895 const dependencies = new Set();
19896 // TODO is this filtering necessary? (I *think* so)
19897 default_slot.dependencies.forEach(name => {
19898 if (!this.node.scope.is_let(name)) {
19899 dependencies.add(name);
19900 }
19901 });
19902 block.add_dependencies(dependencies);
19903 }
19904 block.add_outro();
19905 }
19906 warn_if_reactive() {
19907 const { name } = this.node;
19908 const variable = this.renderer.component.var_lookup.get(name);
19909 if (!variable) {
19910 return;
19911 }
19912 if (variable.reassigned || variable.export_name || variable.is_reactive_dependency) {
19913 this.renderer.component.warn(this.node, {
19914 code: 'reactive-component',
19915 message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`,
19916 });
19917 }
19918 }
19919 render(block, parent_node, parent_nodes) {
19920 this.warn_if_reactive();
19921 const { renderer } = this;
19922 const { component } = renderer;
19923 const name = this.var;
19924 block.add_variable(name);
19925 const component_opts = x `{}`;
19926 const statements = [];
19927 const updates = [];
19928 if (this.fragment) {
19929 this.renderer.add_to_context('$$scope', true);
19930 const default_slot = this.slots.get('default');
19931 this.fragment.nodes.forEach((child) => {
19932 child.render(default_slot.block, null, x `#nodes`);
19933 });
19934 }
19935 let props;
19936 const name_changes = block.get_unique_name(`${name.name}_changes`);
19937 const uses_spread = !!this.node.attributes.find(a => a.is_spread);
19938 // removing empty slot
19939 for (const slot of this.slots.keys()) {
19940 if (!this.slots.get(slot).block.has_content()) {
19941 this.renderer.remove_block(this.slots.get(slot).block);
19942 this.slots.delete(slot);
19943 }
19944 }
19945 const initial_props = this.slots.size > 0
19946 ? [
19947 p `$$slots: {
19948 ${Array.from(this.slots).map(([name, slot]) => {
19949 return p `${name}: [${slot.block.name}, ${slot.get_context || null}, ${slot.get_changes || null}]`;
19950 })}
19951 }`,
19952 p `$$scope: {
19953 ctx: #ctx
19954 }`
19955 ]
19956 : [];
19957 const attribute_object = uses_spread
19958 ? x `{ ${initial_props} }`
19959 : x `{
19960 ${this.node.attributes.map(attr => p `${attr.name}: ${attr.get_value(block)}`)},
19961 ${initial_props}
19962 }`;
19963 if (this.node.attributes.length || this.node.bindings.length || initial_props.length) {
19964 if (!uses_spread && this.node.bindings.length === 0) {
19965 component_opts.properties.push(p `props: ${attribute_object}`);
19966 }
19967 else {
19968 props = block.get_unique_name(`${name.name}_props`);
19969 component_opts.properties.push(p `props: ${props}`);
19970 }
19971 }
19972 if (component.compile_options.dev) {
19973 // TODO this is a terrible hack, but without it the component
19974 // will complain that options.target is missing. This would
19975 // work better if components had separate public and private
19976 // APIs
19977 component_opts.properties.push(p `$$inline: true`);
19978 }
19979 const fragment_dependencies = new Set(this.fragment ? ['$$scope'] : []);
19980 this.slots.forEach(slot => {
19981 slot.block.dependencies.forEach(name => {
19982 const is_let = slot.scope.is_let(name);
19983 const variable = renderer.component.var_lookup.get(name);
19984 if (is_let || is_dynamic$1(variable))
19985 fragment_dependencies.add(name);
19986 });
19987 });
19988 const dynamic_attributes = this.node.attributes.filter(a => a.get_dependencies().length > 0);
19989 if (!uses_spread && (dynamic_attributes.length > 0 || this.node.bindings.length > 0 || fragment_dependencies.size > 0)) {
19990 updates.push(b `const ${name_changes} = {};`);
19991 }
19992 if (this.node.attributes.length) {
19993 if (uses_spread) {
19994 const levels = block.get_unique_name(`${this.var.name}_spread_levels`);
19995 const initial_props = [];
19996 const changes = [];
19997 const all_dependencies = new Set();
19998 this.node.attributes.forEach(attr => {
19999 add_to_set(all_dependencies, attr.dependencies);
20000 });
20001 this.node.attributes.forEach((attr, i) => {
20002 const { name, dependencies } = attr;
20003 const condition = dependencies.size > 0 && (dependencies.size !== all_dependencies.size)
20004 ? renderer.dirty(Array.from(dependencies))
20005 : null;
20006 const unchanged = dependencies.size === 0;
20007 let change_object;
20008 if (attr.is_spread) {
20009 const value = attr.expression.manipulate(block);
20010 initial_props.push(value);
20011 let value_object = value;
20012 if (attr.expression.node.type !== 'ObjectExpression') {
20013 value_object = x `@get_spread_object(${value})`;
20014 }
20015 change_object = value_object;
20016 }
20017 else {
20018 const obj = x `{ ${name}: ${attr.get_value(block)} }`;
20019 initial_props.push(obj);
20020 change_object = obj;
20021 }
20022 changes.push(unchanged
20023 ? x `${levels}[${i}]`
20024 : condition
20025 ? x `${condition} && ${change_object}`
20026 : change_object);
20027 });
20028 block.chunks.init.push(b `
20029 const ${levels} = [
20030 ${initial_props}
20031 ];
20032 `);
20033 statements.push(b `
20034 for (let #i = 0; #i < ${levels}.length; #i += 1) {
20035 ${props} = @assign(${props}, ${levels}[#i]);
20036 }
20037 `);
20038 if (all_dependencies.size) {
20039 const condition = renderer.dirty(Array.from(all_dependencies));
20040 updates.push(b `
20041 const ${name_changes} = ${condition} ? @get_spread_update(${levels}, [
20042 ${changes}
20043 ]) : {}
20044 `);
20045 }
20046 else {
20047 updates.push(b `
20048 const ${name_changes} = {};
20049 `);
20050 }
20051 }
20052 else {
20053 dynamic_attributes.forEach((attribute) => {
20054 const dependencies = attribute.get_dependencies();
20055 if (dependencies.length > 0) {
20056 const condition = renderer.dirty(dependencies);
20057 updates.push(b `
20058 if (${condition}) ${name_changes}.${attribute.name} = ${attribute.get_value(block)};
20059 `);
20060 }
20061 });
20062 }
20063 }
20064 if (fragment_dependencies.size > 0) {
20065 updates.push(b `
20066 if (${renderer.dirty(Array.from(fragment_dependencies))}) {
20067 ${name_changes}.$$scope = { dirty: #dirty, ctx: #ctx };
20068 }`);
20069 }
20070 const munged_bindings = this.node.bindings.map(binding => {
20071 component.has_reactive_assignments = true;
20072 if (binding.name === 'this') {
20073 return bind_this(component, block, new BindingWrapper(block, binding, this), this.var);
20074 }
20075 const id = component.get_unique_name(`${this.var.name}_${binding.name}_binding`);
20076 renderer.add_to_context(id.name);
20077 const callee = renderer.reference(id);
20078 const updating = block.get_unique_name(`updating_${binding.name}`);
20079 block.add_variable(updating);
20080 const snippet = binding.expression.manipulate(block);
20081 statements.push(b `
20082 if (${snippet} !== void 0) {
20083 ${props}.${binding.name} = ${snippet};
20084 }`);
20085 updates.push(b `
20086 if (!${updating} && ${renderer.dirty(Array.from(binding.expression.dependencies))}) {
20087 ${updating} = true;
20088 ${name_changes}.${binding.name} = ${snippet};
20089 @add_flush_callback(() => ${updating} = false);
20090 }
20091 `);
20092 const contextual_dependencies = Array.from(binding.expression.contextual_dependencies);
20093 const dependencies = Array.from(binding.expression.dependencies);
20094 let lhs = binding.raw_expression;
20095 if (binding.is_contextual && binding.expression.node.type === 'Identifier') {
20096 // bind:x={y} — we can't just do `y = x`, we need to
20097 // to `array[index] = x;
20098 const { name } = binding.expression.node;
20099 const { object, property, snippet } = block.bindings.get(name);
20100 lhs = snippet;
20101 contextual_dependencies.push(object.name, property.name);
20102 }
20103 const params = [x `#value`];
20104 if (contextual_dependencies.length > 0) {
20105 const args = [];
20106 contextual_dependencies.forEach(name => {
20107 params.push({
20108 type: 'Identifier',
20109 name
20110 });
20111 renderer.add_to_context(name, true);
20112 args.push(renderer.reference(name));
20113 });
20114 block.chunks.init.push(b `
20115 function ${id}(#value) {
20116 ${callee}.call(null, #value, ${args});
20117 }
20118 `);
20119 block.maintain_context = true; // TODO put this somewhere more logical
20120 }
20121 else {
20122 block.chunks.init.push(b `
20123 function ${id}(#value) {
20124 ${callee}.call(null, #value);
20125 }
20126 `);
20127 }
20128 const body = b `
20129 function ${id}(${params}) {
20130 ${lhs} = #value;
20131 ${renderer.invalidate(dependencies[0])};
20132 }
20133 `;
20134 component.partly_hoisted.push(body);
20135 return b `@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
20136 });
20137 const munged_handlers = this.node.handlers.map(handler => {
20138 const event_handler = new EventHandlerWrapper(handler, this);
20139 let snippet = event_handler.get_snippet(block);
20140 if (handler.modifiers.has('once'))
20141 snippet = x `@once(${snippet})`;
20142 return b `${name}.$on("${handler.name}", ${snippet});`;
20143 });
20144 if (this.node.name === 'svelte:component') {
20145 const switch_value = block.get_unique_name('switch_value');
20146 const switch_props = block.get_unique_name('switch_props');
20147 const snippet = this.node.expression.manipulate(block);
20148 block.chunks.init.push(b `
20149 var ${switch_value} = ${snippet};
20150
20151 function ${switch_props}(#ctx) {
20152 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
20153 ${props && b `let ${props} = ${attribute_object};`}`}
20154 ${statements}
20155 return ${component_opts};
20156 }
20157
20158 if (${switch_value}) {
20159 ${name} = new ${switch_value}(${switch_props}(#ctx));
20160
20161 ${munged_bindings}
20162 ${munged_handlers}
20163 }
20164 `);
20165 block.chunks.create.push(b `if (${name}) @create_component(${name}.$$.fragment);`);
20166 if (parent_nodes && this.renderer.options.hydratable) {
20167 block.chunks.claim.push(b `if (${name}) @claim_component(${name}.$$.fragment, ${parent_nodes});`);
20168 }
20169 block.chunks.mount.push(b `
20170 if (${name}) {
20171 @mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20172 }
20173 `);
20174 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
20175 const update_mount_node = this.get_update_mount_node(anchor);
20176 if (updates.length) {
20177 block.chunks.update.push(b `
20178 ${updates}
20179 `);
20180 }
20181 block.chunks.update.push(b `
20182 if (${switch_value} !== (${switch_value} = ${snippet})) {
20183 if (${name}) {
20184 @group_outros();
20185 const old_component = ${name};
20186 @transition_out(old_component.$$.fragment, 1, 0, () => {
20187 @destroy_component(old_component, 1);
20188 });
20189 @check_outros();
20190 }
20191
20192 if (${switch_value}) {
20193 ${name} = new ${switch_value}(${switch_props}(#ctx));
20194
20195 ${munged_bindings}
20196 ${munged_handlers}
20197
20198 @create_component(${name}.$$.fragment);
20199 @transition_in(${name}.$$.fragment, 1);
20200 @mount_component(${name}, ${update_mount_node}, ${anchor});
20201 } else {
20202 ${name} = null;
20203 }
20204 } else if (${switch_value}) {
20205 ${updates.length && b `${name}.$set(${name_changes});`}
20206 }
20207 `);
20208 block.chunks.intro.push(b `
20209 if (${name}) @transition_in(${name}.$$.fragment, #local);
20210 `);
20211 block.chunks.outro.push(b `if (${name}) @transition_out(${name}.$$.fragment, #local);`);
20212 block.chunks.destroy.push(b `if (${name}) @destroy_component(${name}, ${parent_node ? null : 'detaching'});`);
20213 }
20214 else {
20215 const expression = this.node.name === 'svelte:self'
20216 ? component.name
20217 : this.renderer.reference(this.node.name);
20218 block.chunks.init.push(b `
20219 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
20220 ${props && b `let ${props} = ${attribute_object};`}`}
20221 ${statements}
20222 ${name} = new ${expression}(${component_opts});
20223
20224 ${munged_bindings}
20225 ${munged_handlers}
20226 `);
20227 block.chunks.create.push(b `@create_component(${name}.$$.fragment);`);
20228 if (parent_nodes && this.renderer.options.hydratable) {
20229 block.chunks.claim.push(b `@claim_component(${name}.$$.fragment, ${parent_nodes});`);
20230 }
20231 block.chunks.mount.push(b `@mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});`);
20232 block.chunks.intro.push(b `
20233 @transition_in(${name}.$$.fragment, #local);
20234 `);
20235 if (updates.length) {
20236 block.chunks.update.push(b `
20237 ${updates}
20238 ${name}.$set(${name_changes});
20239 `);
20240 }
20241 block.chunks.destroy.push(b `
20242 @destroy_component(${name}, ${parent_node ? null : 'detaching'});
20243 `);
20244 block.chunks.outro.push(b `@transition_out(${name}.$$.fragment, #local);`);
20245 }
20246 }
20247 }
20248
20249 function get_slot_data(values, block = null) {
20250 return {
20251 type: 'ObjectExpression',
20252 properties: Array.from(values.values())
20253 .filter(attribute => attribute.name !== 'name')
20254 .map(attribute => {
20255 const value = get_value(block, attribute);
20256 return p `${attribute.name}: ${value}`;
20257 })
20258 };
20259 }
20260 function get_value(block, attribute) {
20261 if (attribute.is_true)
20262 return x `true`;
20263 if (attribute.chunks.length === 0)
20264 return x `""`;
20265 let value = attribute.chunks
20266 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : (block ? chunk.manipulate(block) : chunk.node))
20267 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20268 if (attribute.chunks.length > 1 && attribute.chunks[0].type !== 'Text') {
20269 value = x `"" + ${value}`;
20270 }
20271 return value;
20272 }
20273
20274 class SlotWrapper extends Wrapper {
20275 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20276 super(renderer, block, parent, node);
20277 this.fallback = null;
20278 this.var = { type: 'Identifier', name: 'slot' };
20279 this.dependencies = new Set(['$$scope']);
20280 this.cannot_use_innerhtml();
20281 this.not_static_content();
20282 if (this.node.children.length) {
20283 this.fallback = block.child({
20284 comment: create_debugging_comment(this.node.children[0], this.renderer.component),
20285 name: this.renderer.component.get_unique_name(`fallback_block`),
20286 type: 'fallback'
20287 });
20288 renderer.blocks.push(this.fallback);
20289 }
20290 this.fragment = new FragmentWrapper(renderer, this.fallback, node.children, this, strip_whitespace, next_sibling);
20291 this.node.values.forEach(attribute => {
20292 add_to_set(this.dependencies, attribute.dependencies);
20293 });
20294 block.add_dependencies(this.dependencies);
20295 // we have to do this, just in case
20296 block.add_intro();
20297 block.add_outro();
20298 }
20299 render(block, parent_node, parent_nodes) {
20300 const { renderer } = this;
20301 const { slot_name } = this.node;
20302 let get_slot_changes_fn;
20303 let get_slot_context_fn;
20304 if (this.node.values.size > 0) {
20305 get_slot_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_changes`);
20306 get_slot_context_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_context`);
20307 const changes = x `{}`;
20308 const dependencies = new Set();
20309 this.node.values.forEach(attribute => {
20310 attribute.chunks.forEach(chunk => {
20311 if (chunk.dependencies) {
20312 add_to_set(dependencies, chunk.contextual_dependencies);
20313 // add_to_set(dependencies, (chunk as Expression).dependencies);
20314 chunk.dependencies.forEach(name => {
20315 const variable = renderer.component.var_lookup.get(name);
20316 if (variable && !variable.hoistable)
20317 dependencies.add(name);
20318 });
20319 }
20320 });
20321 const dynamic_dependencies = Array.from(attribute.dependencies).filter(name => {
20322 if (this.node.scope.is_let(name))
20323 return true;
20324 const variable = renderer.component.var_lookup.get(name);
20325 return is_dynamic$1(variable);
20326 });
20327 if (dynamic_dependencies.length > 0) {
20328 changes.properties.push(p `${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`);
20329 }
20330 });
20331 renderer.blocks.push(b `
20332 const ${get_slot_changes_fn} = #dirty => ${changes};
20333 const ${get_slot_context_fn} = #ctx => ${get_slot_data(this.node.values, block)};
20334 `);
20335 }
20336 else {
20337 get_slot_changes_fn = 'null';
20338 get_slot_context_fn = 'null';
20339 }
20340 let has_fallback = !!this.fallback;
20341 if (this.fallback) {
20342 this.fragment.render(this.fallback, null, x `#nodes`);
20343 has_fallback = this.fallback.has_content();
20344 if (!has_fallback) {
20345 renderer.remove_block(this.fallback);
20346 }
20347 }
20348 const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`);
20349 const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
20350 const slot_or_fallback = has_fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot;
20351 block.chunks.init.push(b `
20352 const ${slot_definition} = ${renderer.reference('$$slots')}.${slot_name};
20353 const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn});
20354 ${has_fallback ? b `const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
20355 `);
20356 block.chunks.create.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.c();`);
20357 if (renderer.options.hydratable) {
20358 block.chunks.claim.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});`);
20359 }
20360 block.chunks.mount.push(b `
20361 if (${slot_or_fallback}) {
20362 ${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20363 }
20364 `);
20365 block.chunks.intro.push(b `@transition_in(${slot_or_fallback}, #local);`);
20366 block.chunks.outro.push(b `@transition_out(${slot_or_fallback}, #local);`);
20367 const is_dependency_dynamic = name => {
20368 if (name === '$$scope')
20369 return true;
20370 if (this.node.scope.is_let(name))
20371 return true;
20372 const variable = renderer.component.var_lookup.get(name);
20373 return is_dynamic$1(variable);
20374 };
20375 const dynamic_dependencies = Array.from(this.dependencies).filter(is_dependency_dynamic);
20376 const fallback_dynamic_dependencies = has_fallback
20377 ? Array.from(this.fallback.dependencies).filter(is_dependency_dynamic)
20378 : [];
20379 const slot_update = b `
20380 if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
20381 @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn});
20382 }
20383 `;
20384 const fallback_update = has_fallback && fallback_dynamic_dependencies.length > 0 && b `
20385 if (${slot_or_fallback} && ${slot_or_fallback}.p && ${renderer.dirty(fallback_dynamic_dependencies)}) {
20386 ${slot_or_fallback}.p(#ctx, #dirty);
20387 }
20388 `;
20389 if (fallback_update) {
20390 block.chunks.update.push(b `
20391 if (${slot}) {
20392 ${slot_update}
20393 } else {
20394 ${fallback_update}
20395 }
20396 `);
20397 }
20398 else {
20399 block.chunks.update.push(b `
20400 if (${slot}) {
20401 ${slot_update}
20402 }
20403 `);
20404 }
20405 block.chunks.destroy.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`);
20406 }
20407 }
20408
20409 class TitleWrapper extends Wrapper {
20410 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
20411 super(renderer, block, parent, node);
20412 }
20413 render(block, _parent_node, _parent_nodes) {
20414 const is_dynamic = !!this.node.children.find(node => node.type !== 'Text');
20415 if (is_dynamic) {
20416 let value;
20417 const all_dependencies = new Set();
20418 // TODO some of this code is repeated in Tag.ts — would be good to
20419 // DRY it out if that's possible without introducing crazy indirection
20420 if (this.node.children.length === 1) {
20421 // single {tag} — may be a non-string
20422 // @ts-ignore todo: check this
20423 const { expression } = this.node.children[0];
20424 value = expression.manipulate(block);
20425 add_to_set(all_dependencies, expression.dependencies);
20426 }
20427 else {
20428 // '{foo} {bar}' — treat as string concatenation
20429 value = this.node.children
20430 .map(chunk => {
20431 if (chunk.type === 'Text')
20432 return string_literal(chunk.data);
20433 chunk.expression.dependencies.forEach(d => {
20434 all_dependencies.add(d);
20435 });
20436 return chunk.expression.manipulate(block);
20437 })
20438 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20439 if (this.node.children[0].type !== 'Text') {
20440 value = x `"" + ${value}`;
20441 }
20442 }
20443 const last = this.node.should_cache && block.get_unique_name(`title_value`);
20444 if (this.node.should_cache)
20445 block.add_variable(last);
20446 const init = this.node.should_cache ? x `${last} = ${value}` : value;
20447 block.chunks.init.push(b `@_document.title = ${init};`);
20448 const updater = b `@_document.title = ${this.node.should_cache ? last : value};`;
20449 if (all_dependencies.size) {
20450 const dependencies = Array.from(all_dependencies);
20451 let condition = block.renderer.dirty(dependencies);
20452 if (block.has_outros) {
20453 condition = x `!#current || ${condition}`;
20454 }
20455 if (this.node.should_cache) {
20456 condition = x `${condition} && (${last} !== (${last} = ${value}))`;
20457 }
20458 block.chunks.update.push(b `
20459 if (${condition}) {
20460 ${updater}
20461 }`);
20462 }
20463 }
20464 else {
20465 const value = this.node.children.length > 0
20466 ? string_literal(this.node.children[0].data)
20467 : x `""`;
20468 block.chunks.hydrate.push(b `@_document.title = ${value};`);
20469 }
20470 }
20471 }
20472
20473 const associated_events = {
20474 innerWidth: 'resize',
20475 innerHeight: 'resize',
20476 outerWidth: 'resize',
20477 outerHeight: 'resize',
20478 scrollX: 'scroll',
20479 scrollY: 'scroll',
20480 };
20481 const properties = {
20482 scrollX: 'pageXOffset',
20483 scrollY: 'pageYOffset'
20484 };
20485 const readonly = new Set([
20486 'innerWidth',
20487 'innerHeight',
20488 'outerWidth',
20489 'outerHeight',
20490 'online',
20491 ]);
20492 class WindowWrapper extends Wrapper {
20493 constructor(renderer, block, parent, node) {
20494 super(renderer, block, parent, node);
20495 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
20496 }
20497 render(block, _parent_node, _parent_nodes) {
20498 const { renderer } = this;
20499 const { component } = renderer;
20500 const events = {};
20501 const bindings = {};
20502 add_actions(block, '@_window', this.node.actions);
20503 add_event_handlers(block, '@_window', this.handlers);
20504 this.node.bindings.forEach(binding => {
20505 // in dev mode, throw if read-only values are written to
20506 if (readonly.has(binding.name)) {
20507 renderer.readonly.add(binding.expression.node.name);
20508 }
20509 bindings[binding.name] = binding.expression.node.name;
20510 // bind:online is a special case, we need to listen for two separate events
20511 if (binding.name === 'online')
20512 return;
20513 const associated_event = associated_events[binding.name];
20514 const property = properties[binding.name] || binding.name;
20515 if (!events[associated_event])
20516 events[associated_event] = [];
20517 events[associated_event].push({
20518 name: binding.expression.node.name,
20519 value: property
20520 });
20521 });
20522 const scrolling = block.get_unique_name(`scrolling`);
20523 const clear_scrolling = block.get_unique_name(`clear_scrolling`);
20524 const scrolling_timeout = block.get_unique_name(`scrolling_timeout`);
20525 Object.keys(events).forEach(event => {
20526 const id = block.get_unique_name(`onwindow${event}`);
20527 const props = events[event];
20528 renderer.add_to_context(id.name);
20529 const fn = renderer.reference(id.name);
20530 if (event === 'scroll') {
20531 // TODO other bidirectional bindings...
20532 block.add_variable(scrolling, x `false`);
20533 block.add_variable(clear_scrolling, x `() => { ${scrolling} = false }`);
20534 block.add_variable(scrolling_timeout);
20535 const condition = bindings.scrollX && bindings.scrollY
20536 ? x `"${bindings.scrollX}" in this._state || "${bindings.scrollY}" in this._state`
20537 : x `"${bindings.scrollX || bindings.scrollY}" in this._state`;
20538 const scrollX = bindings.scrollX && x `this._state.${bindings.scrollX}`;
20539 const scrollY = bindings.scrollY && x `this._state.${bindings.scrollY}`;
20540 renderer.meta_bindings.push(b `
20541 if (${condition}) {
20542 @_scrollTo(${scrollX || '@_window.pageXOffset'}, ${scrollY || '@_window.pageYOffset'});
20543 }
20544 ${scrollX && `${scrollX} = @_window.pageXOffset;`}
20545 ${scrollY && `${scrollY} = @_window.pageYOffset;`}
20546 `);
20547 block.event_listeners.push(x `
20548 @listen(@_window, "${event}", () => {
20549 ${scrolling} = true;
20550 @_clearTimeout(${scrolling_timeout});
20551 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
20552 ${fn}();
20553 })
20554 `);
20555 }
20556 else {
20557 props.forEach(prop => {
20558 renderer.meta_bindings.push(b `this._state.${prop.name} = @_window.${prop.value};`);
20559 });
20560 block.event_listeners.push(x `
20561 @listen(@_window, "${event}", ${fn})
20562 `);
20563 }
20564 component.partly_hoisted.push(b `
20565 function ${id}() {
20566 ${props.map(prop => renderer.invalidate(prop.name, x `${prop.name} = @_window.${prop.value}`))}
20567 }
20568 `);
20569 block.chunks.init.push(b `
20570 @add_render_callback(${fn});
20571 `);
20572 component.has_reactive_assignments = true;
20573 });
20574 // special case... might need to abstract this out if we add more special cases
20575 if (bindings.scrollX || bindings.scrollY) {
20576 const condition = renderer.dirty([bindings.scrollX, bindings.scrollY].filter(Boolean));
20577 const scrollX = bindings.scrollX ? renderer.reference(bindings.scrollX) : x `@_window.pageXOffset`;
20578 const scrollY = bindings.scrollY ? renderer.reference(bindings.scrollY) : x `@_window.pageYOffset`;
20579 block.chunks.update.push(b `
20580 if (${condition} && !${scrolling}) {
20581 ${scrolling} = true;
20582 @_clearTimeout(${scrolling_timeout});
20583 @_scrollTo(${scrollX}, ${scrollY});
20584 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
20585 }
20586 `);
20587 }
20588 // another special case. (I'm starting to think these are all special cases.)
20589 if (bindings.online) {
20590 const id = block.get_unique_name(`onlinestatuschanged`);
20591 const name = bindings.online;
20592 renderer.add_to_context(id.name);
20593 const reference = renderer.reference(id.name);
20594 component.partly_hoisted.push(b `
20595 function ${id}() {
20596 ${renderer.invalidate(name, x `${name} = @_navigator.onLine`)}
20597 }
20598 `);
20599 block.chunks.init.push(b `
20600 @add_render_callback(${reference});
20601 `);
20602 block.event_listeners.push(x `@listen(@_window, "online", ${reference})`, x `@listen(@_window, "offline", ${reference})`);
20603 component.has_reactive_assignments = true;
20604 }
20605 }
20606 }
20607
20608 function link(next, prev) {
20609 prev.next = next;
20610 if (next)
20611 next.prev = prev;
20612 }
20613
20614 const wrappers = {
20615 AwaitBlock: AwaitBlockWrapper,
20616 Body: BodyWrapper,
20617 Comment: null,
20618 DebugTag: DebugTagWrapper,
20619 EachBlock: EachBlockWrapper,
20620 Element: ElementWrapper,
20621 Head: HeadWrapper,
20622 IfBlock: IfBlockWrapper,
20623 InlineComponent: InlineComponentWrapper,
20624 MustacheTag: MustacheTagWrapper,
20625 Options: null,
20626 RawMustacheTag: RawMustacheTagWrapper,
20627 Slot: SlotWrapper,
20628 Text: TextWrapper,
20629 Title: TitleWrapper,
20630 Window: WindowWrapper
20631 };
20632 function trimmable_at(child, next_sibling) {
20633 // Whitespace is trimmable if one of the following is true:
20634 // The child and its sibling share a common nearest each block (not at an each block boundary)
20635 // The next sibling's previous node is an each block
20636 return (next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/)) || next_sibling.node.prev.type === 'EachBlock';
20637 }
20638 class FragmentWrapper {
20639 constructor(renderer, block, nodes, parent, strip_whitespace, next_sibling) {
20640 this.nodes = [];
20641 let last_child;
20642 let window_wrapper;
20643 let i = nodes.length;
20644 while (i--) {
20645 const child = nodes[i];
20646 if (!child.type) {
20647 throw new Error(`missing type`);
20648 }
20649 if (!(child.type in wrappers)) {
20650 throw new Error(`TODO implement ${child.type}`);
20651 }
20652 // special case — this is an easy way to remove whitespace surrounding
20653 // <svelte:window/>. lil hacky but it works
20654 if (child.type === 'Window') {
20655 window_wrapper = new WindowWrapper(renderer, block, parent, child);
20656 continue;
20657 }
20658 if (child.type === 'Text') {
20659 let { data } = child;
20660 // We want to remove trailing whitespace inside an element/component/block,
20661 // *unless* there is no whitespace between this node and its next sibling
20662 if (this.nodes.length === 0) {
20663 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'));
20664 if (should_trim) {
20665 data = trim_end(data);
20666 if (!data)
20667 continue;
20668 }
20669 }
20670 // glue text nodes (which could e.g. be separated by comments) together
20671 if (last_child && last_child.node.type === 'Text') {
20672 last_child.data = data + last_child.data;
20673 continue;
20674 }
20675 const wrapper = new TextWrapper(renderer, block, parent, child, data);
20676 if (wrapper.skip)
20677 continue;
20678 this.nodes.unshift(wrapper);
20679 link(last_child, last_child = wrapper);
20680 }
20681 else {
20682 const Wrapper = wrappers[child.type];
20683 if (!Wrapper)
20684 continue;
20685 const wrapper = new Wrapper(renderer, block, parent, child, strip_whitespace, last_child || next_sibling);
20686 this.nodes.unshift(wrapper);
20687 link(last_child, last_child = wrapper);
20688 }
20689 }
20690 if (strip_whitespace) {
20691 const first = this.nodes[0];
20692 if (first && first.node.type === 'Text') {
20693 first.data = trim_start(first.data);
20694 if (!first.data) {
20695 first.var = null;
20696 this.nodes.shift();
20697 if (this.nodes[0]) {
20698 this.nodes[0].prev = null;
20699 }
20700 }
20701 }
20702 }
20703 if (window_wrapper) {
20704 this.nodes.unshift(window_wrapper);
20705 link(last_child, window_wrapper);
20706 }
20707 }
20708 render(block, parent_node, parent_nodes) {
20709 for (let i = 0; i < this.nodes.length; i += 1) {
20710 this.nodes[i].render(block, parent_node, parent_nodes);
20711 }
20712 }
20713 }
20714
20715 class Renderer {
20716 constructor(component, options) {
20717 this.context = [];
20718 this.initial_context = [];
20719 this.context_lookup = new Map();
20720 this.blocks = [];
20721 this.readonly = new Set();
20722 this.meta_bindings = []; // initial values for e.g. window.innerWidth, if there's a <svelte:window> meta tag
20723 this.binding_groups = new Map();
20724 this.component = component;
20725 this.options = options;
20726 this.locate = component.locate; // TODO messy
20727 this.file_var = options.dev && this.component.get_unique_name('file');
20728 component.vars.filter(v => !v.hoistable || (v.export_name && !v.module)).forEach(v => this.add_to_context(v.name));
20729 // ensure store values are included in context
20730 component.vars.filter(v => v.subscribable).forEach(v => this.add_to_context(`$${v.name}`));
20731 reserved_keywords.forEach(keyword => {
20732 if (component.var_lookup.has(keyword)) {
20733 this.add_to_context(keyword);
20734 }
20735 });
20736 if (component.slots.size > 0) {
20737 this.add_to_context('$$scope');
20738 this.add_to_context('$$slots');
20739 }
20740 if (this.binding_groups.size > 0) {
20741 this.add_to_context('$$binding_groups');
20742 }
20743 // main block
20744 this.block = new Block$1({
20745 renderer: this,
20746 name: null,
20747 type: 'component',
20748 key: null,
20749 bindings: new Map(),
20750 dependencies: new Set(),
20751 });
20752 this.block.has_update_method = true;
20753 this.fragment = new FragmentWrapper(this, this.block, component.fragment.children, null, true, null);
20754 // TODO messy
20755 this.blocks.forEach(block => {
20756 if (block instanceof Block$1) {
20757 block.assign_variable_names();
20758 }
20759 });
20760 this.block.assign_variable_names();
20761 this.fragment.render(this.block, null, x `#nodes`);
20762 this.context_overflow = this.context.length > 31;
20763 this.context.forEach(member => {
20764 const { variable } = member;
20765 if (variable) {
20766 member.priority += 2;
20767 if (variable.mutated || variable.reassigned)
20768 member.priority += 4;
20769 // these determine whether variable is included in initial context
20770 // array, so must have the highest priority
20771 if (variable.export_name)
20772 member.priority += 16;
20773 if (variable.referenced)
20774 member.priority += 32;
20775 }
20776 else if (member.is_non_contextual) {
20777 // determine whether variable is included in initial context
20778 // array, so must have the highest priority
20779 member.priority += 8;
20780 }
20781 if (!member.is_contextual) {
20782 member.priority += 1;
20783 }
20784 });
20785 this.context.sort((a, b) => (b.priority - a.priority) || (a.index.value - b.index.value));
20786 this.context.forEach((member, i) => member.index.value = i);
20787 let i = this.context.length;
20788 while (i--) {
20789 const member = this.context[i];
20790 if (member.variable) {
20791 if (member.variable.referenced || member.variable.export_name)
20792 break;
20793 }
20794 else if (member.is_non_contextual) {
20795 break;
20796 }
20797 }
20798 this.initial_context = this.context.slice(0, i + 1);
20799 }
20800 add_to_context(name, contextual = false) {
20801 if (!this.context_lookup.has(name)) {
20802 const member = {
20803 name,
20804 index: { type: 'Literal', value: this.context.length },
20805 is_contextual: false,
20806 is_non_contextual: false,
20807 variable: null,
20808 priority: 0
20809 };
20810 this.context_lookup.set(name, member);
20811 this.context.push(member);
20812 }
20813 const member = this.context_lookup.get(name);
20814 if (contextual) {
20815 member.is_contextual = true;
20816 }
20817 else {
20818 member.is_non_contextual = true;
20819 const variable = this.component.var_lookup.get(name);
20820 member.variable = variable;
20821 }
20822 return member;
20823 }
20824 invalidate(name, value) {
20825 const variable = this.component.var_lookup.get(name);
20826 const member = this.context_lookup.get(name);
20827 if (variable && (variable.subscribable && (variable.reassigned || variable.export_name))) {
20828 return x `${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
20829 }
20830 if (name[0] === '$' && name[1] !== '$') {
20831 return x `${name.slice(1)}.set(${value || name})`;
20832 }
20833 if (variable && (variable.module || (!variable.referenced &&
20834 !variable.is_reactive_dependency &&
20835 !variable.export_name &&
20836 !name.startsWith('$$')))) {
20837 return value || name;
20838 }
20839 if (value) {
20840 return x `$$invalidate(${member.index}, ${value})`;
20841 }
20842 // if this is a reactive declaration, invalidate dependencies recursively
20843 const deps = new Set([name]);
20844 deps.forEach(name => {
20845 const reactive_declarations = this.component.reactive_declarations.filter(x => x.assignees.has(name));
20846 reactive_declarations.forEach(declaration => {
20847 declaration.dependencies.forEach(name => {
20848 deps.add(name);
20849 });
20850 });
20851 });
20852 // TODO ideally globals etc wouldn't be here in the first place
20853 const filtered = Array.from(deps).filter(n => this.context_lookup.has(n));
20854 if (!filtered.length)
20855 return null;
20856 return filtered
20857 .map(n => x `$$invalidate(${this.context_lookup.get(n).index}, ${n})`)
20858 .reduce((lhs, rhs) => x `${lhs}, ${rhs}`);
20859 }
20860 dirty(names, is_reactive_declaration = false) {
20861 const renderer = this;
20862 const dirty = (is_reactive_declaration
20863 ? x `$$self.$$.dirty`
20864 : x `#dirty`);
20865 const get_bitmask = () => {
20866 const bitmask = [];
20867 names.forEach((name) => {
20868 const member = renderer.context_lookup.get(name);
20869 if (!member)
20870 return;
20871 if (member.index.value === -1) {
20872 throw new Error(`unset index`);
20873 }
20874 const value = member.index.value;
20875 const i = (value / 31) | 0;
20876 const n = 1 << (value % 31);
20877 if (!bitmask[i])
20878 bitmask[i] = { n: 0, names: [] };
20879 bitmask[i].n |= n;
20880 bitmask[i].names.push(name);
20881 });
20882 return bitmask;
20883 };
20884 // TODO: context-overflow make it less gross
20885 return {
20886 // Using a ParenthesizedExpression allows us to create
20887 // the expression lazily. TODO would be better if
20888 // context was determined before rendering, so that
20889 // this indirection was unnecessary
20890 type: 'ParenthesizedExpression',
20891 get expression() {
20892 const bitmask = get_bitmask();
20893 if (!bitmask.length) {
20894 return x `${dirty} & /*${names.join(', ')}*/ 0`;
20895 }
20896 if (renderer.context_overflow) {
20897 return bitmask
20898 .map((b, i) => ({ b, i }))
20899 .filter(({ b }) => b)
20900 .map(({ b, i }) => x `${dirty}[${i}] & /*${b.names.join(', ')}*/ ${b.n}`)
20901 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
20902 }
20903 return x `${dirty} & /*${names.join(', ')}*/ ${bitmask[0].n}`;
20904 }
20905 };
20906 }
20907 reference(node) {
20908 if (typeof node === 'string') {
20909 node = { type: 'Identifier', name: node };
20910 }
20911 const { name, nodes } = flatten_reference(node);
20912 const member = this.context_lookup.get(name);
20913 // TODO is this correct?
20914 if (this.component.var_lookup.get(name)) {
20915 this.component.add_reference(name);
20916 }
20917 if (member !== undefined) {
20918 const replacement = x `/*${member.name}*/ #ctx[${member.index}]`;
20919 if (nodes[0].loc)
20920 replacement.object.loc = nodes[0].loc;
20921 nodes[0] = replacement;
20922 return nodes.reduce((lhs, rhs) => x `${lhs}.${rhs}`);
20923 }
20924 return node;
20925 }
20926 remove_block(block) {
20927 this.blocks.splice(this.blocks.indexOf(block), 1);
20928 }
20929 }
20930
20931 function dom(component, options) {
20932 const { name } = component;
20933 const renderer = new Renderer(component, options);
20934 const { block } = renderer;
20935 block.has_outro_method = true;
20936 // prevent fragment being created twice (#1063)
20937 if (options.customElement)
20938 block.chunks.create.push(b `this.c = @noop;`);
20939 const body = [];
20940 if (renderer.file_var) {
20941 const file = component.file ? x `"${component.file}"` : x `undefined`;
20942 body.push(b `const ${renderer.file_var} = ${file};`);
20943 }
20944 const css = component.stylesheet.render(options.filename, !options.customElement);
20945 const styles = component.stylesheet.has_styles && options.dev
20946 ? `${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */`
20947 : css.code;
20948 const add_css = component.get_unique_name('add_css');
20949 const should_add_css = (!options.customElement &&
20950 !!styles &&
20951 options.css !== false);
20952 if (should_add_css) {
20953 body.push(b `
20954 function ${add_css}() {
20955 var style = @element("style");
20956 style.id = "${component.stylesheet.id}-style";
20957 style.textContent = "${styles}";
20958 @append(@_document.head, style);
20959 }
20960 `);
20961 }
20962 // fix order
20963 // TODO the deconflicted names of blocks are reversed... should set them here
20964 const blocks = renderer.blocks.slice().reverse();
20965 body.push(...blocks.map(block => {
20966 // TODO this is a horrible mess — renderer.blocks
20967 // contains a mixture of Blocks and Nodes
20968 if (block.render)
20969 return block.render();
20970 return block;
20971 }));
20972 if (options.dev && !options.hydratable) {
20973 block.chunks.claim.push(b `throw new @_Error("options.hydrate only works if the component was compiled with the \`hydratable: true\` option");`);
20974 }
20975 const uses_props = component.var_lookup.has('$$props');
20976 const uses_rest = component.var_lookup.has('$$restProps');
20977 const $$props = uses_props || uses_rest ? `$$new_props` : `$$props`;
20978 const props = component.vars.filter(variable => !variable.module && variable.export_name);
20979 const writable_props = props.filter(variable => variable.writable);
20980 const omit_props_names = component.get_unique_name('omit_props_names');
20981 const compute_rest = x `@compute_rest_props($$props, ${omit_props_names.name})`;
20982 const rest = uses_rest ? b `
20983 const ${omit_props_names.name} = [${props.map(prop => `"${prop.export_name}"`).join(',')}];
20984 let $$restProps = ${compute_rest};
20985 ` : null;
20986 const set = (uses_props || uses_rest || writable_props.length > 0 || component.slots.size > 0)
20987 ? x `
20988 ${$$props} => {
20989 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`)}
20990 ${uses_rest && !uses_props && x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`}
20991 ${uses_rest && renderer.invalidate('$$restProps', x `$$restProps = ${compute_rest}`)}
20992 ${writable_props.map(prop => b `if ('${prop.export_name}' in ${$$props}) ${renderer.invalidate(prop.name, x `${prop.name} = ${$$props}.${prop.export_name}`)};`)}
20993 ${component.slots.size > 0 &&
20994 b `if ('$$scope' in ${$$props}) ${renderer.invalidate('$$scope', x `$$scope = ${$$props}.$$scope`)};`}
20995 }
20996 `
20997 : null;
20998 const accessors = [];
20999 const not_equal = component.component_options.immutable ? x `@not_equal` : x `@safe_not_equal`;
21000 let dev_props_check;
21001 let inject_state;
21002 let capture_state;
21003 let props_inject;
21004 props.forEach(prop => {
21005 const variable = component.var_lookup.get(prop.name);
21006 if (!variable.writable || component.component_options.accessors) {
21007 accessors.push({
21008 type: 'MethodDefinition',
21009 kind: 'get',
21010 key: { type: 'Identifier', name: prop.export_name },
21011 value: x `function() {
21012 return ${prop.hoistable ? prop.name : x `this.$$.ctx[${renderer.context_lookup.get(prop.name).index}]`}
21013 }`
21014 });
21015 }
21016 else if (component.compile_options.dev) {
21017 accessors.push({
21018 type: 'MethodDefinition',
21019 kind: 'get',
21020 key: { type: 'Identifier', name: prop.export_name },
21021 value: x `function() {
21022 throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
21023 }`
21024 });
21025 }
21026 if (component.component_options.accessors) {
21027 if (variable.writable && !renderer.readonly.has(prop.name)) {
21028 accessors.push({
21029 type: 'MethodDefinition',
21030 kind: 'set',
21031 key: { type: 'Identifier', name: prop.export_name },
21032 value: x `function(${prop.name}) {
21033 this.$set({ ${prop.export_name}: ${prop.name} });
21034 @flush();
21035 }`
21036 });
21037 }
21038 else if (component.compile_options.dev) {
21039 accessors.push({
21040 type: 'MethodDefinition',
21041 kind: 'set',
21042 key: { type: 'Identifier', name: prop.export_name },
21043 value: x `function(value) {
21044 throw new @_Error("<${component.tag}>: Cannot set read-only property '${prop.export_name}'");
21045 }`
21046 });
21047 }
21048 }
21049 else if (component.compile_options.dev) {
21050 accessors.push({
21051 type: 'MethodDefinition',
21052 kind: 'set',
21053 key: { type: 'Identifier', name: prop.export_name },
21054 value: x `function(value) {
21055 throw new @_Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
21056 }`
21057 });
21058 }
21059 });
21060 if (component.compile_options.dev) {
21061 // checking that expected ones were passed
21062 const expected = props.filter(prop => prop.writable && !prop.initialised);
21063 if (expected.length) {
21064 dev_props_check = b `
21065 const { ctx: #ctx } = this.$$;
21066 const props = ${options.customElement ? x `this.attributes` : x `options.props || {}`};
21067 ${expected.map(prop => b `
21068 if (${renderer.reference(prop.name)} === undefined && !('${prop.export_name}' in props)) {
21069 @_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'");
21070 }`)}
21071 `;
21072 }
21073 const capturable_vars = component.vars.filter(v => !v.internal && !v.global && !v.name.startsWith('$$'));
21074 if (capturable_vars.length > 0) {
21075 capture_state = x `() => ({ ${capturable_vars.map(prop => p `${prop.name}`)} })`;
21076 }
21077 const injectable_vars = capturable_vars.filter(v => !v.module && v.writable && v.name[0] !== '$');
21078 if (uses_props || injectable_vars.length > 0) {
21079 inject_state = x `
21080 ${$$props} => {
21081 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), $$new_props)`)}
21082 ${injectable_vars.map(v => b `if ('${v.name}' in $$props) ${renderer.invalidate(v.name, x `${v.name} = ${$$props}.${v.name}`)};`)}
21083 }
21084 `;
21085 props_inject = b `
21086 if ($$props && "$$inject" in $$props) {
21087 $$self.$inject_state($$props.$$inject);
21088 }
21089 `;
21090 }
21091 }
21092 // instrument assignments
21093 if (component.ast.instance) {
21094 let scope = component.instance_scope;
21095 const map = component.instance_scope_map;
21096 let execution_context = null;
21097 walk(component.ast.instance.content, {
21098 enter(node) {
21099 if (map.has(node)) {
21100 scope = map.get(node);
21101 if (!execution_context && !scope.block) {
21102 execution_context = node;
21103 }
21104 }
21105 else if (!execution_context && node.type === 'LabeledStatement' && node.label.name === '$') {
21106 execution_context = node;
21107 }
21108 },
21109 leave(node) {
21110 if (map.has(node)) {
21111 scope = scope.parent;
21112 }
21113 if (execution_context === node) {
21114 execution_context = null;
21115 }
21116 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
21117 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
21118 // normally (`a = 1`, `b.c = 2`), there'll be a single name
21119 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
21120 // may be more, in which case we need to tack the extra ones
21121 // onto the initial function call
21122 const names = new Set(extract_names(assignee));
21123 this.replace(invalidate(renderer, scope, node, names, execution_context === null));
21124 }
21125 }
21126 });
21127 component.rewrite_props(({ name, reassigned, export_name }) => {
21128 const value = `$${name}`;
21129 const i = renderer.context_lookup.get(`$${name}`).index;
21130 const insert = (reassigned || export_name)
21131 ? b `${`$$subscribe_${name}`}()`
21132 : b `@component_subscribe($$self, ${name}, #value => $$invalidate(${i}, ${value} = #value))`;
21133 if (component.compile_options.dev) {
21134 return b `@validate_store(${name}, '${name}'); ${insert}`;
21135 }
21136 return insert;
21137 });
21138 }
21139 const args = [x `$$self`];
21140 const has_invalidate = props.length > 0 ||
21141 component.has_reactive_assignments ||
21142 component.slots.size > 0 ||
21143 capture_state ||
21144 inject_state;
21145 if (has_invalidate) {
21146 args.push(x `$$props`, x `$$invalidate`);
21147 }
21148 else if (component.compile_options.dev) {
21149 // $$props arg is still needed for unknown prop check
21150 args.push(x `$$props`);
21151 }
21152 const has_create_fragment = component.compile_options.dev || block.has_content();
21153 if (has_create_fragment) {
21154 body.push(b `
21155 function create_fragment(#ctx) {
21156 ${block.get_contents()}
21157 }
21158 `);
21159 }
21160 body.push(b `
21161 ${component.extract_javascript(component.ast.module)}
21162
21163 ${component.fully_hoisted}
21164 `);
21165 const filtered_props = props.filter(prop => {
21166 const variable = component.var_lookup.get(prop.name);
21167 if (variable.hoistable)
21168 return false;
21169 if (prop.name[0] === '$')
21170 return false;
21171 return true;
21172 });
21173 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
21174 const instance_javascript = component.extract_javascript(component.ast.instance);
21175 const has_definition = (component.compile_options.dev ||
21176 (instance_javascript && instance_javascript.length > 0) ||
21177 filtered_props.length > 0 ||
21178 uses_props ||
21179 component.partly_hoisted.length > 0 ||
21180 renderer.initial_context.length > 0 ||
21181 component.reactive_declarations.length > 0 ||
21182 capture_state ||
21183 inject_state);
21184 const definition = has_definition
21185 ? component.alias('instance')
21186 : { type: 'Literal', value: null };
21187 const reactive_store_subscriptions = reactive_stores
21188 .filter(store => {
21189 const variable = component.var_lookup.get(store.name.slice(1));
21190 return !variable || variable.hoistable;
21191 })
21192 .map(({ name }) => b `
21193 ${component.compile_options.dev && b `@validate_store(${name.slice(1)}, '${name.slice(1)}');`}
21194 @component_subscribe($$self, ${name.slice(1)}, $$value => $$invalidate(${renderer.context_lookup.get(name).index}, ${name} = $$value));
21195 `);
21196 const resubscribable_reactive_store_unsubscribers = reactive_stores
21197 .filter(store => {
21198 const variable = component.var_lookup.get(store.name.slice(1));
21199 return variable && (variable.reassigned || variable.export_name);
21200 })
21201 .map(({ name }) => b `$$self.$$.on_destroy.push(() => ${`$$unsubscribe_${name.slice(1)}`}());`);
21202 if (has_definition) {
21203 const reactive_declarations = [];
21204 const fixed_reactive_declarations = []; // not really 'reactive' but whatever
21205 component.reactive_declarations.forEach(d => {
21206 const dependencies = Array.from(d.dependencies);
21207 const uses_rest_or_props = !!dependencies.find(n => n === '$$props' || n === '$$restProps');
21208 const writable = dependencies.filter(n => {
21209 const variable = component.var_lookup.get(n);
21210 return variable && (variable.export_name || variable.mutated || variable.reassigned);
21211 });
21212 const condition = !uses_rest_or_props && writable.length > 0 && renderer.dirty(writable, true);
21213 let statement = d.node; // TODO remove label (use d.node.body) if it's not referenced
21214 if (condition)
21215 statement = b `if (${condition}) { ${statement} }`[0];
21216 if (condition || uses_rest_or_props) {
21217 reactive_declarations.push(statement);
21218 }
21219 else {
21220 fixed_reactive_declarations.push(statement);
21221 }
21222 });
21223 const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
21224 const variable = component.var_lookup.get(name);
21225 return variable.injected && variable.name[0] !== '$';
21226 });
21227 const reactive_store_declarations = reactive_stores.map(variable => {
21228 const $name = variable.name;
21229 const name = $name.slice(1);
21230 const store = component.var_lookup.get(name);
21231 if (store && (store.reassigned || store.export_name)) {
21232 const unsubscribe = `$$unsubscribe_${name}`;
21233 const subscribe = `$$subscribe_${name}`;
21234 const i = renderer.context_lookup.get($name).index;
21235 return b `let ${$name}, ${unsubscribe} = @noop, ${subscribe} = () => (${unsubscribe}(), ${unsubscribe} = @subscribe(${name}, $$value => $$invalidate(${i}, ${$name} = $$value)), ${name})`;
21236 }
21237 return b `let ${$name};`;
21238 });
21239 let unknown_props_check;
21240 if (component.compile_options.dev && !(uses_props || uses_rest)) {
21241 unknown_props_check = b `
21242 const writable_props = [${writable_props.map(prop => x `'${prop.export_name}'`)}];
21243 @_Object.keys($$props).forEach(key => {
21244 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$') @_console.warn(\`<${component.tag}> was created with unknown prop '\${key}'\`);
21245 });
21246 `;
21247 }
21248 const return_value = {
21249 type: 'ArrayExpression',
21250 elements: renderer.initial_context.map(member => ({
21251 type: 'Identifier',
21252 name: member.name
21253 }))
21254 };
21255 body.push(b `
21256 function ${definition}(${args}) {
21257 ${rest}
21258
21259 ${reactive_store_declarations}
21260
21261 ${reactive_store_subscriptions}
21262
21263 ${resubscribable_reactive_store_unsubscribers}
21264
21265 ${instance_javascript}
21266
21267 ${unknown_props_check}
21268
21269 ${component.slots.size || component.compile_options.dev ? b `let { $$slots = {}, $$scope } = $$props;` : null}
21270 ${component.compile_options.dev && b `@validate_slots('${component.tag}', $$slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
21271
21272 ${renderer.binding_groups.size > 0 && b `const $$binding_groups = [${[...renderer.binding_groups.keys()].map(_ => x `[]`)}];`}
21273
21274 ${component.partly_hoisted}
21275
21276 ${set && b `$$self.$set = ${set};`}
21277
21278 ${capture_state && b `$$self.$capture_state = ${capture_state};`}
21279
21280 ${inject_state && b `$$self.$inject_state = ${inject_state};`}
21281
21282 ${injected.map(name => b `let ${name};`)}
21283
21284 ${ /* before reactive declarations */props_inject}
21285
21286 ${reactive_declarations.length > 0 && b `
21287 $$self.$$.update = () => {
21288 ${reactive_declarations}
21289 };
21290 `}
21291
21292 ${fixed_reactive_declarations}
21293
21294 ${uses_props && b `$$props = @exclude_internal_props($$props);`}
21295
21296 return ${return_value};
21297 }
21298 `);
21299 }
21300 const prop_indexes = x `{
21301 ${props.filter(v => v.export_name && !v.module).map(v => p `${v.export_name}: ${renderer.context_lookup.get(v.name).index}`)}
21302 }`;
21303 let dirty;
21304 if (renderer.context_overflow) {
21305 dirty = x `[]`;
21306 for (let i = 0; i < renderer.context.length; i += 31) {
21307 dirty.elements.push(x `-1`);
21308 }
21309 }
21310 if (options.customElement) {
21311 const declaration = b `
21312 class ${name} extends @SvelteElement {
21313 constructor(options) {
21314 super();
21315
21316 ${css.code && b `this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
21317
21318 @init(this, { target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
21319
21320 ${dev_props_check}
21321
21322 if (options) {
21323 if (options.target) {
21324 @insert(options.target, this, options.anchor);
21325 }
21326
21327 ${(props.length > 0 || uses_props || uses_rest) && b `
21328 if (options.props) {
21329 this.$set(options.props);
21330 @flush();
21331 }`}
21332 }
21333 }
21334 }
21335 `[0];
21336 if (props.length > 0) {
21337 declaration.body.body.push({
21338 type: 'MethodDefinition',
21339 kind: 'get',
21340 static: true,
21341 computed: false,
21342 key: { type: 'Identifier', name: 'observedAttributes' },
21343 value: x `function() {
21344 return [${props.map(prop => x `"${prop.export_name}"`)}];
21345 }`
21346 });
21347 }
21348 declaration.body.body.push(...accessors);
21349 body.push(declaration);
21350 if (component.tag != null) {
21351 body.push(b `
21352 @_customElements.define("${component.tag}", ${name});
21353 `);
21354 }
21355 }
21356 else {
21357 const superclass = {
21358 type: 'Identifier',
21359 name: options.dev ? '@SvelteComponentDev' : '@SvelteComponent'
21360 };
21361 const declaration = b `
21362 class ${name} extends ${superclass} {
21363 constructor(options) {
21364 super(${options.dev && `options`});
21365 ${should_add_css && b `if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
21366 @init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
21367 ${options.dev && b `@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`}
21368
21369 ${dev_props_check}
21370 }
21371 }
21372 `[0];
21373 declaration.body.body.push(...accessors);
21374 body.push(declaration);
21375 }
21376 return { js: flatten$1(body, []), css };
21377 }
21378 function flatten$1(nodes, target) {
21379 for (let i = 0; i < nodes.length; i += 1) {
21380 const node = nodes[i];
21381 if (Array.isArray(node)) {
21382 flatten$1(node, target);
21383 }
21384 else {
21385 target.push(node);
21386 }
21387 }
21388 return target;
21389 }
21390
21391 function AwaitBlock (node, renderer, options) {
21392 renderer.push();
21393 renderer.render(node.pending.children, options);
21394 const pending = renderer.pop();
21395 renderer.push();
21396 renderer.render(node.then.children, options);
21397 const then = renderer.pop();
21398 renderer.add_expression(x `
21399 function(__value) {
21400 if (@is_promise(__value)) return ${pending};
21401 return (function(${node.then_node ? node.then_node : ''}) { return ${then}; }(__value));
21402 }(${node.expression.node})
21403 `);
21404 }
21405
21406 function Comment$1 (_node, _renderer, _options) {
21407 // TODO preserve comments
21408 // if (options.preserveComments) {
21409 // renderer.append(`<!--${node.data}-->`);
21410 // }
21411 }
21412
21413 function DebugTag (node, renderer, options) {
21414 if (!options.dev)
21415 return;
21416 const filename = options.filename || null;
21417 const { line, column } = options.locate(node.start + 1);
21418 const obj = x `{
21419 ${node.expressions.map(e => p `${e.node.name}`)}
21420 }`;
21421 renderer.add_expression(x `@debug(${filename ? x `"${filename}"` : x `null`}, ${line - 1}, ${column}, ${obj})`);
21422 }
21423
21424 function EachBlock (node, renderer, options) {
21425 const args = [node.context_node];
21426 if (node.index)
21427 args.push({ type: 'Identifier', name: node.index });
21428 renderer.push();
21429 renderer.render(node.children, options);
21430 const result = renderer.pop();
21431 const consequent = x `@each(${node.expression.node}, (${args}) => ${result})`;
21432 if (node.else) {
21433 renderer.push();
21434 renderer.render(node.else.children, options);
21435 const alternate = renderer.pop();
21436 renderer.add_expression(x `${node.expression.node}.length ? ${consequent} : ${alternate}`);
21437 }
21438 else {
21439 renderer.add_expression(consequent);
21440 }
21441 }
21442
21443 function get_class_attribute_value(attribute) {
21444 // handle special case — `class={possiblyUndefined}` with scoped CSS
21445 if (attribute.chunks.length === 2 && attribute.chunks[1].synthetic) {
21446 const value = attribute.chunks[0].node;
21447 return x `@escape(@null_to_empty(${value})) + "${attribute.chunks[1].data}"`;
21448 }
21449 return get_attribute_value(attribute);
21450 }
21451 function get_attribute_value(attribute) {
21452 if (attribute.chunks.length === 0)
21453 return x `""`;
21454 return attribute.chunks
21455 .map((chunk) => {
21456 return chunk.type === 'Text'
21457 ? string_literal(chunk.data.replace(/"/g, '&quot;'))
21458 : x `@escape(${chunk.node})`;
21459 })
21460 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
21461 }
21462
21463 function get_slot_scope(lets) {
21464 if (lets.length === 0)
21465 return null;
21466 return {
21467 type: 'ObjectPattern',
21468 properties: lets.map(l => {
21469 return {
21470 type: 'Property',
21471 kind: 'init',
21472 method: false,
21473 shorthand: false,
21474 computed: false,
21475 key: l.name,
21476 value: l.value || l.name
21477 };
21478 })
21479 };
21480 }
21481
21482 // source: https://html.spec.whatwg.org/multipage/indices.html
21483 const boolean_attributes = new Set([
21484 'allowfullscreen',
21485 'allowpaymentrequest',
21486 'async',
21487 'autofocus',
21488 'autoplay',
21489 'checked',
21490 'controls',
21491 'default',
21492 'defer',
21493 'disabled',
21494 'formnovalidate',
21495 'hidden',
21496 'ismap',
21497 'loop',
21498 'multiple',
21499 'muted',
21500 'nomodule',
21501 'novalidate',
21502 'open',
21503 'playsinline',
21504 'readonly',
21505 'required',
21506 'reversed',
21507 'selected'
21508 ]);
21509
21510 // similar logic from `compile/render_dom/wrappers/Fragment`
21511 // We want to remove trailing whitespace inside an element/component/block,
21512 // *unless* there is no whitespace between this node and its next sibling
21513 function remove_whitespace_children(children, next) {
21514 const nodes = [];
21515 let last_child;
21516 let i = children.length;
21517 while (i--) {
21518 const child = children[i];
21519 if (child.type === 'Text') {
21520 if (child.should_skip()) {
21521 continue;
21522 }
21523 let { data } = child;
21524 if (nodes.length === 0) {
21525 const should_trim = next
21526 ? next.type === 'Text' &&
21527 /^\s/.test(next.data) &&
21528 trimmable_at$1(child, next)
21529 : !child.has_ancestor('EachBlock');
21530 if (should_trim) {
21531 data = trim_end(data);
21532 if (!data)
21533 continue;
21534 }
21535 }
21536 // glue text nodes (which could e.g. be separated by comments) together
21537 if (last_child && last_child.type === 'Text') {
21538 last_child.data = data + last_child.data;
21539 continue;
21540 }
21541 nodes.unshift(child);
21542 link(last_child, last_child = child);
21543 }
21544 else {
21545 nodes.unshift(child);
21546 link(last_child, last_child = child);
21547 }
21548 }
21549 const first = nodes[0];
21550 if (first && first.type === 'Text') {
21551 first.data = trim_start(first.data);
21552 if (!first.data) {
21553 first.var = null;
21554 nodes.shift();
21555 if (nodes[0]) {
21556 nodes[0].prev = null;
21557 }
21558 }
21559 }
21560 return nodes;
21561 }
21562 function trimmable_at$1(child, next_sibling) {
21563 // Whitespace is trimmable if one of the following is true:
21564 // The child and its sibling share a common nearest each block (not at an each block boundary)
21565 // The next sibling's previous node is an each block
21566 return (next_sibling.find_nearest(/EachBlock/) ===
21567 child.find_nearest(/EachBlock/) || next_sibling.prev.type === 'EachBlock');
21568 }
21569
21570 function Element (node, renderer, options) {
21571 const children = remove_whitespace_children(node.children, node.next);
21572 // awkward special case
21573 let node_contents;
21574 const contenteditable = (node.name !== 'textarea' &&
21575 node.name !== 'input' &&
21576 node.attributes.some((attribute) => attribute.name === 'contenteditable'));
21577 const slot = node.get_static_attribute_value('slot');
21578 const nearest_inline_component = node.find_nearest(/InlineComponent/);
21579 if (slot && nearest_inline_component) {
21580 renderer.push();
21581 }
21582 renderer.add_string(`<${node.name}`);
21583 const class_expression_list = node.classes.map(class_directive => {
21584 const { expression, name } = class_directive;
21585 const snippet = expression ? expression.node : x `#ctx.${name}`; // TODO is this right?
21586 return x `${snippet} ? "${name}" : ""`;
21587 });
21588 if (node.needs_manual_style_scoping) {
21589 class_expression_list.push(x `"${node.component.stylesheet.id}"`);
21590 }
21591 const class_expression = class_expression_list.length > 0 &&
21592 class_expression_list.reduce((lhs, rhs) => x `${lhs} + ' ' + ${rhs}`);
21593 if (node.attributes.some(attr => attr.is_spread)) {
21594 // TODO dry this out
21595 const args = [];
21596 node.attributes.forEach(attribute => {
21597 if (attribute.is_spread) {
21598 args.push(attribute.expression.node);
21599 }
21600 else {
21601 const name = attribute.name.toLowerCase();
21602 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
21603 node_contents = get_attribute_value(attribute);
21604 }
21605 else if (attribute.is_true) {
21606 args.push(x `{ ${attribute.name}: true }`);
21607 }
21608 else if (boolean_attributes.has(name) &&
21609 attribute.chunks.length === 1 &&
21610 attribute.chunks[0].type !== 'Text') {
21611 // a boolean attribute with one non-Text chunk
21612 args.push(x `{ ${attribute.name}: ${attribute.chunks[0].node} || null }`);
21613 }
21614 else {
21615 args.push(x `{ ${attribute.name}: ${get_attribute_value(attribute)} }`);
21616 }
21617 }
21618 });
21619 renderer.add_expression(x `@spread([${args}], ${class_expression})`);
21620 }
21621 else {
21622 let add_class_attribute = !!class_expression;
21623 node.attributes.forEach(attribute => {
21624 const name = attribute.name.toLowerCase();
21625 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
21626 node_contents = get_attribute_value(attribute);
21627 }
21628 else if (attribute.is_true) {
21629 renderer.add_string(` ${attribute.name}`);
21630 }
21631 else if (boolean_attributes.has(name) &&
21632 attribute.chunks.length === 1 &&
21633 attribute.chunks[0].type !== 'Text') {
21634 // a boolean attribute with one non-Text chunk
21635 renderer.add_string(` `);
21636 renderer.add_expression(x `${attribute.chunks[0].node} ? "${attribute.name}" : ""`);
21637 }
21638 else if (name === 'class' && class_expression) {
21639 add_class_attribute = false;
21640 renderer.add_string(` ${attribute.name}="`);
21641 renderer.add_expression(x `[${get_class_attribute_value(attribute)}, ${class_expression}].join(' ').trim()`);
21642 renderer.add_string(`"`);
21643 }
21644 else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') {
21645 const snippet = attribute.chunks[0].node;
21646 renderer.add_expression(x `@add_attribute("${attribute.name}", ${snippet}, ${boolean_attributes.has(name) ? 1 : 0})`);
21647 }
21648 else {
21649 renderer.add_string(` ${attribute.name}="`);
21650 renderer.add_expression((name === 'class' ? get_class_attribute_value : get_attribute_value)(attribute));
21651 renderer.add_string(`"`);
21652 }
21653 });
21654 if (add_class_attribute) {
21655 renderer.add_expression(x `@add_classes([${class_expression}].join(' ').trim())`);
21656 }
21657 }
21658 node.bindings.forEach(binding => {
21659 const { name, expression } = binding;
21660 if (binding.is_readonly) {
21661 return;
21662 }
21663 if (name === 'group') ;
21664 else if (contenteditable && (name === 'textContent' || name === 'innerHTML')) {
21665 node_contents = expression.node;
21666 // TODO where was this used?
21667 // value = name === 'textContent' ? x`@escape($$value)` : x`$$value`;
21668 }
21669 else if (binding.name === 'value' && node.name === 'textarea') {
21670 const snippet = expression.node;
21671 node_contents = x `${snippet} || ""`;
21672 }
21673 else {
21674 const snippet = expression.node;
21675 renderer.add_expression(x `@add_attribute("${name}", ${snippet}, 1)`);
21676 }
21677 });
21678 if (options.hydratable && options.head_id) {
21679 renderer.add_string(` data-svelte="${options.head_id}"`);
21680 }
21681 renderer.add_string('>');
21682 if (node_contents !== undefined) {
21683 if (contenteditable) {
21684 renderer.push();
21685 renderer.render(children, options);
21686 const result = renderer.pop();
21687 renderer.add_expression(x `($$value => $$value === void 0 ? ${result} : $$value)(${node_contents})`);
21688 }
21689 else {
21690 renderer.add_expression(node_contents);
21691 }
21692 if (!is_void(node.name)) {
21693 renderer.add_string(`</${node.name}>`);
21694 }
21695 }
21696 else if (slot && nearest_inline_component) {
21697 renderer.render(children, options);
21698 if (!is_void(node.name)) {
21699 renderer.add_string(`</${node.name}>`);
21700 }
21701 const lets = node.lets;
21702 const seen = new Set(lets.map(l => l.name.name));
21703 nearest_inline_component.lets.forEach(l => {
21704 if (!seen.has(l.name.name))
21705 lets.push(l);
21706 });
21707 options.slot_scopes.set(slot, {
21708 input: get_slot_scope(node.lets),
21709 output: renderer.pop()
21710 });
21711 }
21712 else {
21713 renderer.render(children, options);
21714 if (!is_void(node.name)) {
21715 renderer.add_string(`</${node.name}>`);
21716 }
21717 }
21718 }
21719
21720 function Head (node, renderer, options) {
21721 const head_options = Object.assign({}, options, { head_id: node.id });
21722 renderer.push();
21723 renderer.render(node.children, head_options);
21724 const result = renderer.pop();
21725 renderer.add_expression(x `$$result.head += ${result}, ""`);
21726 }
21727
21728 function HtmlTag (node, renderer, _options) {
21729 renderer.add_expression(node.expression.node);
21730 }
21731
21732 function IfBlock (node, renderer, options) {
21733 const condition = node.expression.node;
21734 renderer.push();
21735 renderer.render(node.children, options);
21736 const consequent = renderer.pop();
21737 renderer.push();
21738 if (node.else)
21739 renderer.render(node.else.children, options);
21740 const alternate = renderer.pop();
21741 renderer.add_expression(x `${condition} ? ${consequent} : ${alternate}`);
21742 }
21743
21744 function get_prop_value(attribute) {
21745 if (attribute.is_true)
21746 return x `true`;
21747 if (attribute.chunks.length === 0)
21748 return x `''`;
21749 return attribute.chunks
21750 .map(chunk => {
21751 if (chunk.type === 'Text')
21752 return string_literal(chunk.data);
21753 return chunk.node;
21754 })
21755 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
21756 }
21757 function InlineComponent (node, renderer, options) {
21758 const binding_props = [];
21759 const binding_fns = [];
21760 node.bindings.forEach(binding => {
21761 renderer.has_bindings = true;
21762 // TODO this probably won't work for contextual bindings
21763 const snippet = binding.expression.node;
21764 binding_props.push(p `${binding.name}: ${snippet}`);
21765 binding_fns.push(p `${binding.name}: $$value => { ${snippet} = $$value; $$settled = false }`);
21766 });
21767 const uses_spread = node.attributes.find(attr => attr.is_spread);
21768 let props;
21769 if (uses_spread) {
21770 props = x `@_Object.assign(${node.attributes
21771 .map(attribute => {
21772 if (attribute.is_spread) {
21773 return attribute.expression.node;
21774 }
21775 else {
21776 return x `{ ${attribute.name}: ${get_prop_value(attribute)} }`;
21777 }
21778 })
21779 .concat(binding_props.map(p => x `{ ${p} }`))})`;
21780 }
21781 else {
21782 props = x `{
21783 ${node.attributes.map(attribute => p `${attribute.name}: ${get_prop_value(attribute)}`)},
21784 ${binding_props}
21785 }`;
21786 }
21787 const bindings = x `{
21788 ${binding_fns}
21789 }`;
21790 const expression = (node.name === 'svelte:self'
21791 ? renderer.name
21792 : node.name === 'svelte:component'
21793 ? x `(${node.expression.node}) || @missing_component`
21794 : node.name.split('.').reduce(((lhs, rhs) => x `${lhs}.${rhs}`)));
21795 const slot_fns = [];
21796 const children = remove_whitespace_children(node.children, node.next);
21797 if (children.length) {
21798 const slot_scopes = new Map();
21799 renderer.push();
21800 renderer.render(children, Object.assign({}, options, {
21801 slot_scopes
21802 }));
21803 slot_scopes.set('default', {
21804 input: get_slot_scope(node.lets),
21805 output: renderer.pop()
21806 });
21807 slot_scopes.forEach(({ input, output }, name) => {
21808 if (!is_empty_template_literal(output)) {
21809 slot_fns.push(p `${name}: (${input}) => ${output}`);
21810 }
21811 });
21812 }
21813 const slots = x `{
21814 ${slot_fns}
21815 }`;
21816 renderer.add_expression(x `@validate_component(${expression}, "${node.name}").$$render($$result, ${props}, ${bindings}, ${slots})`);
21817 }
21818 function is_empty_template_literal(template_literal) {
21819 return (template_literal.expressions.length === 0 &&
21820 template_literal.quasis.length === 1 &&
21821 template_literal.quasis[0].value.raw === "");
21822 }
21823
21824 function Slot (node, renderer, options) {
21825 const slot_data = get_slot_data(node.values);
21826 renderer.push();
21827 renderer.render(node.children, options);
21828 const result = renderer.pop();
21829 renderer.add_expression(x `
21830 $$slots.${node.slot_name}
21831 ? $$slots.${node.slot_name}(${slot_data})
21832 : ${result}
21833 `);
21834 }
21835
21836 function Tag$1 (node, renderer, _options) {
21837 const snippet = node.expression.node;
21838 renderer.add_expression(node.parent &&
21839 node.parent.type === 'Element' &&
21840 node.parent.name === 'style'
21841 ? snippet
21842 : x `@escape(${snippet})`);
21843 }
21844
21845 function Text (node, renderer, _options) {
21846 let text = node.data;
21847 if (!node.parent ||
21848 node.parent.type !== 'Element' ||
21849 (node.parent.name !== 'script' && node.parent.name !== 'style')) {
21850 // unless this Text node is inside a <script> or <style> element, escape &,<,>
21851 text = escape_html(text);
21852 }
21853 renderer.add_string(text);
21854 }
21855
21856 function Title (node, renderer, options) {
21857 renderer.push();
21858 renderer.add_string(`<title>`);
21859 renderer.render(node.children, options);
21860 renderer.add_string(`</title>`);
21861 const result = renderer.pop();
21862 renderer.add_expression(x `$$result.title = ${result}, ""`);
21863 }
21864
21865 function noop$1() { }
21866 const handlers$1 = {
21867 AwaitBlock,
21868 Body: noop$1,
21869 Comment: Comment$1,
21870 DebugTag,
21871 EachBlock,
21872 Element,
21873 Head,
21874 IfBlock,
21875 InlineComponent,
21876 MustacheTag: Tag$1,
21877 Options: noop$1,
21878 RawMustacheTag: HtmlTag,
21879 Slot,
21880 Text,
21881 Title,
21882 Window: noop$1
21883 };
21884 class Renderer$1 {
21885 constructor({ name }) {
21886 this.has_bindings = false;
21887 this.stack = [];
21888 this.targets = [];
21889 this.name = name;
21890 this.push();
21891 }
21892 add_string(str) {
21893 this.current.value += escape_template(str);
21894 }
21895 add_expression(node) {
21896 this.literal.quasis.push({
21897 type: 'TemplateElement',
21898 value: { raw: this.current.value, cooked: null },
21899 tail: false
21900 });
21901 this.literal.expressions.push(node);
21902 this.current.value = '';
21903 }
21904 push() {
21905 const current = this.current = { value: '' };
21906 const literal = this.literal = {
21907 type: 'TemplateLiteral',
21908 expressions: [],
21909 quasis: []
21910 };
21911 this.stack.push({ current, literal });
21912 }
21913 pop() {
21914 this.literal.quasis.push({
21915 type: 'TemplateElement',
21916 value: { raw: this.current.value, cooked: null },
21917 tail: true
21918 });
21919 const popped = this.stack.pop();
21920 const last = this.stack[this.stack.length - 1];
21921 if (last) {
21922 this.literal = last.literal;
21923 this.current = last.current;
21924 }
21925 return popped.literal;
21926 }
21927 render(nodes, options) {
21928 nodes.forEach(node => {
21929 const handler = handlers$1[node.type];
21930 if (!handler) {
21931 throw new Error(`No handler for '${node.type}' nodes`);
21932 }
21933 handler(node, this, options);
21934 });
21935 }
21936 }
21937
21938 function ssr(component, options) {
21939 const renderer = new Renderer$1({
21940 name: component.name
21941 });
21942 const { name } = component;
21943 // create $$render function
21944 renderer.render(trim(component.fragment.children), Object.assign({
21945 locate: component.locate
21946 }, options));
21947 // TODO put this inside the Renderer class
21948 const literal = renderer.pop();
21949 // TODO concatenate CSS maps
21950 const css = options.customElement ?
21951 { code: null, map: null } :
21952 component.stylesheet.render(options.filename, true);
21953 const uses_rest = component.var_lookup.has('$$restProps');
21954 const props = component.vars.filter(variable => !variable.module && variable.export_name);
21955 const rest = uses_rest ? b `let $$restProps = @compute_rest_props($$props, [${props.map(prop => `"${prop.export_name}"`).join(',')}]);` : null;
21956 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
21957 const reactive_store_values = reactive_stores
21958 .map(({ name }) => {
21959 const store_name = name.slice(1);
21960 const store = component.var_lookup.get(store_name);
21961 if (store && store.hoistable)
21962 return null;
21963 const assignment = b `${name} = @get_store_value(${store_name});`;
21964 return component.compile_options.dev
21965 ? b `@validate_store(${store_name}, '${store_name}'); ${assignment}`
21966 : assignment;
21967 })
21968 .filter(Boolean);
21969 component.rewrite_props(({ name }) => {
21970 const value = `$${name}`;
21971 let insert = b `${value} = @get_store_value(${name})`;
21972 if (component.compile_options.dev) {
21973 insert = b `@validate_store(${name}, '${name}'); ${insert}`;
21974 }
21975 return insert;
21976 });
21977 const instance_javascript = component.extract_javascript(component.ast.instance);
21978 // TODO only do this for props with a default value
21979 const parent_bindings = instance_javascript
21980 ? component.vars
21981 .filter(variable => !variable.module && variable.export_name)
21982 .map(prop => {
21983 return b `if ($$props.${prop.export_name} === void 0 && $$bindings.${prop.export_name} && ${prop.name} !== void 0) $$bindings.${prop.export_name}(${prop.name});`;
21984 })
21985 : [];
21986 const reactive_declarations = component.reactive_declarations.map(d => {
21987 const body = d.node.body;
21988 let statement = b `${body}`;
21989 if (d.declaration) {
21990 const declared = extract_names(d.declaration);
21991 const injected = declared.filter(name => {
21992 return name[0] !== '$' && component.var_lookup.get(name).injected;
21993 });
21994 const self_dependencies = injected.filter(name => d.dependencies.has(name));
21995 if (injected.length) {
21996 // in some cases we need to do `let foo; [expression]`, in
21997 // others we can do `let [expression]`
21998 const separate = (self_dependencies.length > 0 ||
21999 declared.length > injected.length);
22000 const { left, right } = body.expression;
22001 statement = separate
22002 ? b `
22003 ${injected.map(name => b `let ${name};`)}
22004 ${statement}`
22005 : b `
22006 let ${left} = ${right}`;
22007 }
22008 }
22009 else { // TODO do not add label if it's not referenced
22010 statement = b `$: { ${statement} }`;
22011 }
22012 return statement;
22013 });
22014 const main = renderer.has_bindings
22015 ? b `
22016 let $$settled;
22017 let $$rendered;
22018
22019 do {
22020 $$settled = true;
22021
22022 ${reactive_store_values}
22023
22024 ${reactive_declarations}
22025
22026 $$rendered = ${literal};
22027 } while (!$$settled);
22028
22029 return $$rendered;
22030 `
22031 : b `
22032 ${reactive_store_values}
22033
22034 ${reactive_declarations}
22035
22036 return ${literal};`;
22037 const blocks = [
22038 rest,
22039 ...reactive_stores.map(({ name }) => {
22040 const store_name = name.slice(1);
22041 const store = component.var_lookup.get(store_name);
22042 if (store && store.hoistable) {
22043 return b `let ${name} = @get_store_value(${store_name});`;
22044 }
22045 return b `let ${name};`;
22046 }),
22047 instance_javascript,
22048 ...parent_bindings,
22049 css.code && b `$$result.css.add(#css);`,
22050 main
22051 ].filter(Boolean);
22052 const js = b `
22053 ${css.code ? b `
22054 const #css = {
22055 code: "${css.code}",
22056 map: ${css.map ? string_literal(css.map.toString()) : 'null'}
22057 };` : null}
22058
22059 ${component.extract_javascript(component.ast.module)}
22060
22061 ${component.fully_hoisted}
22062
22063 const ${name} = @create_ssr_component(($$result, $$props, $$bindings, $$slots) => {
22064 ${blocks}
22065 });
22066 `;
22067 return { js, css };
22068 }
22069 function trim(nodes) {
22070 let start = 0;
22071 for (; start < nodes.length; start += 1) {
22072 const node = nodes[start];
22073 if (node.type !== 'Text')
22074 break;
22075 node.data = node.data.replace(/^\s+/, '');
22076 if (node.data)
22077 break;
22078 }
22079 let end = nodes.length;
22080 for (; end > start; end -= 1) {
22081 const node = nodes[end - 1];
22082 if (node.type !== 'Text')
22083 break;
22084 node.data = node.data.replace(/\s+$/, '');
22085 if (node.data)
22086 break;
22087 }
22088 return nodes.slice(start, end);
22089 }
22090
22091 const wrappers$1 = { esm, cjs };
22092 function create_module(program, format, name, banner, sveltePath = 'svelte', helpers, globals, imports, module_exports) {
22093 const internal_path = `${sveltePath}/internal`;
22094 helpers.sort((a, b) => (a.name < b.name) ? -1 : 1);
22095 globals.sort((a, b) => (a.name < b.name) ? -1 : 1);
22096 if (format === 'esm') {
22097 return esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
22098 }
22099 if (format === 'cjs')
22100 return cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
22101 throw new Error(`options.format is invalid (must be ${list$1(Object.keys(wrappers$1))})`);
22102 }
22103 function edit_source(source, sveltePath) {
22104 return source === 'svelte' || source.startsWith('svelte/')
22105 ? source.replace('svelte', sveltePath)
22106 : source;
22107 }
22108 function get_internal_globals(globals, helpers) {
22109 return globals.length > 0 && {
22110 type: 'VariableDeclaration',
22111 kind: 'const',
22112 declarations: [{
22113 type: 'VariableDeclarator',
22114 id: {
22115 type: 'ObjectPattern',
22116 properties: globals.map(g => ({
22117 type: 'Property',
22118 method: false,
22119 shorthand: false,
22120 computed: false,
22121 key: { type: 'Identifier', name: g.name },
22122 value: g.alias,
22123 kind: 'init'
22124 }))
22125 },
22126 init: helpers.find(({ name }) => name === 'globals').alias
22127 }]
22128 };
22129 }
22130 function esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
22131 const import_declaration = {
22132 type: 'ImportDeclaration',
22133 specifiers: helpers.map(h => ({
22134 type: 'ImportSpecifier',
22135 local: h.alias,
22136 imported: { type: 'Identifier', name: h.name }
22137 })),
22138 source: { type: 'Literal', value: internal_path }
22139 };
22140 const internal_globals = get_internal_globals(globals, helpers);
22141 // edit user imports
22142 imports.forEach(node => {
22143 node.source.value = edit_source(node.source.value, sveltePath);
22144 });
22145 const exports = module_exports.length > 0 && {
22146 type: 'ExportNamedDeclaration',
22147 specifiers: module_exports.map(x => ({
22148 type: 'Specifier',
22149 local: { type: 'Identifier', name: x.name },
22150 exported: { type: 'Identifier', name: x.as }
22151 }))
22152 };
22153 program.body = b `
22154 /* ${banner} */
22155
22156 ${import_declaration}
22157 ${internal_globals}
22158 ${imports}
22159
22160 ${program.body}
22161
22162 export default ${name};
22163 ${exports}
22164 `;
22165 }
22166 function cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
22167 const internal_requires = {
22168 type: 'VariableDeclaration',
22169 kind: 'const',
22170 declarations: [{
22171 type: 'VariableDeclarator',
22172 id: {
22173 type: 'ObjectPattern',
22174 properties: helpers.map(h => ({
22175 type: 'Property',
22176 method: false,
22177 shorthand: false,
22178 computed: false,
22179 key: { type: 'Identifier', name: h.name },
22180 value: h.alias,
22181 kind: 'init'
22182 }))
22183 },
22184 init: x `require("${internal_path}")`
22185 }]
22186 };
22187 const internal_globals = get_internal_globals(globals, helpers);
22188 const user_requires = imports.map(node => {
22189 const init = x `require("${edit_source(node.source.value, sveltePath)}")`;
22190 if (node.specifiers.length === 0) {
22191 return b `${init};`;
22192 }
22193 return {
22194 type: 'VariableDeclaration',
22195 kind: 'const',
22196 declarations: [{
22197 type: 'VariableDeclarator',
22198 id: node.specifiers[0].type === 'ImportNamespaceSpecifier'
22199 ? { type: 'Identifier', name: node.specifiers[0].local.name }
22200 : {
22201 type: 'ObjectPattern',
22202 properties: node.specifiers.map(s => ({
22203 type: 'Property',
22204 method: false,
22205 shorthand: false,
22206 computed: false,
22207 key: s.type === 'ImportSpecifier' ? s.imported : { type: 'Identifier', name: 'default' },
22208 value: s.local,
22209 kind: 'init'
22210 }))
22211 },
22212 init
22213 }]
22214 };
22215 });
22216 const exports = module_exports.map(x => b `exports.${{ type: 'Identifier', name: x.as }} = ${{ type: 'Identifier', name: x.name }};`);
22217 program.body = b `
22218 /* ${banner} */
22219
22220 "use strict";
22221 ${internal_requires}
22222 ${internal_globals}
22223 ${user_requires}
22224
22225 ${program.body}
22226
22227 exports.default = ${name};
22228 ${exports}
22229 `;
22230 }
22231
22232 var Chunk = function Chunk(start, end, content) {
22233 this.start = start;
22234 this.end = end;
22235 this.original = content;
22236
22237 this.intro = '';
22238 this.outro = '';
22239
22240 this.content = content;
22241 this.storeName = false;
22242 this.edited = false;
22243
22244 // we make these non-enumerable, for sanity while debugging
22245 Object.defineProperties(this, {
22246 previous: { writable: true, value: null },
22247 next: { writable: true, value: null }
22248 });
22249 };
22250
22251 Chunk.prototype.appendLeft = function appendLeft (content) {
22252 this.outro += content;
22253 };
22254
22255 Chunk.prototype.appendRight = function appendRight (content) {
22256 this.intro = this.intro + content;
22257 };
22258
22259 Chunk.prototype.clone = function clone () {
22260 var chunk = new Chunk(this.start, this.end, this.original);
22261
22262 chunk.intro = this.intro;
22263 chunk.outro = this.outro;
22264 chunk.content = this.content;
22265 chunk.storeName = this.storeName;
22266 chunk.edited = this.edited;
22267
22268 return chunk;
22269 };
22270
22271 Chunk.prototype.contains = function contains (index) {
22272 return this.start < index && index < this.end;
22273 };
22274
22275 Chunk.prototype.eachNext = function eachNext (fn) {
22276 var chunk = this;
22277 while (chunk) {
22278 fn(chunk);
22279 chunk = chunk.next;
22280 }
22281 };
22282
22283 Chunk.prototype.eachPrevious = function eachPrevious (fn) {
22284 var chunk = this;
22285 while (chunk) {
22286 fn(chunk);
22287 chunk = chunk.previous;
22288 }
22289 };
22290
22291 Chunk.prototype.edit = function edit (content, storeName, contentOnly) {
22292 this.content = content;
22293 if (!contentOnly) {
22294 this.intro = '';
22295 this.outro = '';
22296 }
22297 this.storeName = storeName;
22298
22299 this.edited = true;
22300
22301 return this;
22302 };
22303
22304 Chunk.prototype.prependLeft = function prependLeft (content) {
22305 this.outro = content + this.outro;
22306 };
22307
22308 Chunk.prototype.prependRight = function prependRight (content) {
22309 this.intro = content + this.intro;
22310 };
22311
22312 Chunk.prototype.split = function split (index) {
22313 var sliceIndex = index - this.start;
22314
22315 var originalBefore = this.original.slice(0, sliceIndex);
22316 var originalAfter = this.original.slice(sliceIndex);
22317
22318 this.original = originalBefore;
22319
22320 var newChunk = new Chunk(index, this.end, originalAfter);
22321 newChunk.outro = this.outro;
22322 this.outro = '';
22323
22324 this.end = index;
22325
22326 if (this.edited) {
22327 // TODO is this block necessary?...
22328 newChunk.edit('', false);
22329 this.content = '';
22330 } else {
22331 this.content = originalBefore;
22332 }
22333
22334 newChunk.next = this.next;
22335 if (newChunk.next) { newChunk.next.previous = newChunk; }
22336 newChunk.previous = this;
22337 this.next = newChunk;
22338
22339 return newChunk;
22340 };
22341
22342 Chunk.prototype.toString = function toString () {
22343 return this.intro + this.content + this.outro;
22344 };
22345
22346 Chunk.prototype.trimEnd = function trimEnd (rx) {
22347 this.outro = this.outro.replace(rx, '');
22348 if (this.outro.length) { return true; }
22349
22350 var trimmed = this.content.replace(rx, '');
22351
22352 if (trimmed.length) {
22353 if (trimmed !== this.content) {
22354 this.split(this.start + trimmed.length).edit('', undefined, true);
22355 }
22356 return true;
22357
22358 } else {
22359 this.edit('', undefined, true);
22360
22361 this.intro = this.intro.replace(rx, '');
22362 if (this.intro.length) { return true; }
22363 }
22364 };
22365
22366 Chunk.prototype.trimStart = function trimStart (rx) {
22367 this.intro = this.intro.replace(rx, '');
22368 if (this.intro.length) { return true; }
22369
22370 var trimmed = this.content.replace(rx, '');
22371
22372 if (trimmed.length) {
22373 if (trimmed !== this.content) {
22374 this.split(this.end - trimmed.length);
22375 this.edit('', undefined, true);
22376 }
22377 return true;
22378
22379 } else {
22380 this.edit('', undefined, true);
22381
22382 this.outro = this.outro.replace(rx, '');
22383 if (this.outro.length) { return true; }
22384 }
22385 };
22386
22387 var btoa$1 = function () {
22388 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
22389 };
22390 if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
22391 btoa$1 = function (str) { return window.btoa(unescape(encodeURIComponent(str))); };
22392 } else if (typeof Buffer === 'function') {
22393 btoa$1 = function (str) { return Buffer.from(str, 'utf-8').toString('base64'); };
22394 }
22395
22396 var SourceMap = function SourceMap(properties) {
22397 this.version = 3;
22398 this.file = properties.file;
22399 this.sources = properties.sources;
22400 this.sourcesContent = properties.sourcesContent;
22401 this.names = properties.names;
22402 this.mappings = encode(properties.mappings);
22403 };
22404
22405 SourceMap.prototype.toString = function toString () {
22406 return JSON.stringify(this);
22407 };
22408
22409 SourceMap.prototype.toUrl = function toUrl () {
22410 return 'data:application/json;charset=utf-8;base64,' + btoa$1(this.toString());
22411 };
22412
22413 function guessIndent(code) {
22414 var lines = code.split('\n');
22415
22416 var tabbed = lines.filter(function (line) { return /^\t+/.test(line); });
22417 var spaced = lines.filter(function (line) { return /^ {2,}/.test(line); });
22418
22419 if (tabbed.length === 0 && spaced.length === 0) {
22420 return null;
22421 }
22422
22423 // More lines tabbed than spaced? Assume tabs, and
22424 // default to tabs in the case of a tie (or nothing
22425 // to go on)
22426 if (tabbed.length >= spaced.length) {
22427 return '\t';
22428 }
22429
22430 // Otherwise, we need to guess the multiple
22431 var min = spaced.reduce(function (previous, current) {
22432 var numSpaces = /^ +/.exec(current)[0].length;
22433 return Math.min(numSpaces, previous);
22434 }, Infinity);
22435
22436 return new Array(min + 1).join(' ');
22437 }
22438
22439 function getRelativePath(from, to) {
22440 var fromParts = from.split(/[/\\]/);
22441 var toParts = to.split(/[/\\]/);
22442
22443 fromParts.pop(); // get dirname
22444
22445 while (fromParts[0] === toParts[0]) {
22446 fromParts.shift();
22447 toParts.shift();
22448 }
22449
22450 if (fromParts.length) {
22451 var i = fromParts.length;
22452 while (i--) { fromParts[i] = '..'; }
22453 }
22454
22455 return fromParts.concat(toParts).join('/');
22456 }
22457
22458 var toString$1 = Object.prototype.toString;
22459
22460 function isObject(thing) {
22461 return toString$1.call(thing) === '[object Object]';
22462 }
22463
22464 function getLocator$1(source) {
22465 var originalLines = source.split('\n');
22466 var lineOffsets = [];
22467
22468 for (var i = 0, pos = 0; i < originalLines.length; i++) {
22469 lineOffsets.push(pos);
22470 pos += originalLines[i].length + 1;
22471 }
22472
22473 return function locate(index) {
22474 var i = 0;
22475 var j = lineOffsets.length;
22476 while (i < j) {
22477 var m = (i + j) >> 1;
22478 if (index < lineOffsets[m]) {
22479 j = m;
22480 } else {
22481 i = m + 1;
22482 }
22483 }
22484 var line = i - 1;
22485 var column = index - lineOffsets[line];
22486 return { line: line, column: column };
22487 };
22488 }
22489
22490 var Mappings = function Mappings(hires) {
22491 this.hires = hires;
22492 this.generatedCodeLine = 0;
22493 this.generatedCodeColumn = 0;
22494 this.raw = [];
22495 this.rawSegments = this.raw[this.generatedCodeLine] = [];
22496 this.pending = null;
22497 };
22498
22499 Mappings.prototype.addEdit = function addEdit (sourceIndex, content, loc, nameIndex) {
22500 if (content.length) {
22501 var segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
22502 if (nameIndex >= 0) {
22503 segment.push(nameIndex);
22504 }
22505 this.rawSegments.push(segment);
22506 } else if (this.pending) {
22507 this.rawSegments.push(this.pending);
22508 }
22509
22510 this.advance(content);
22511 this.pending = null;
22512 };
22513
22514 Mappings.prototype.addUneditedChunk = function addUneditedChunk (sourceIndex, chunk, original, loc, sourcemapLocations) {
22515 var originalCharIndex = chunk.start;
22516 var first = true;
22517
22518 while (originalCharIndex < chunk.end) {
22519 if (this.hires || first || sourcemapLocations[originalCharIndex]) {
22520 this.rawSegments.push([this.generatedCodeColumn, sourceIndex, loc.line, loc.column]);
22521 }
22522
22523 if (original[originalCharIndex] === '\n') {
22524 loc.line += 1;
22525 loc.column = 0;
22526 this.generatedCodeLine += 1;
22527 this.raw[this.generatedCodeLine] = this.rawSegments = [];
22528 this.generatedCodeColumn = 0;
22529 } else {
22530 loc.column += 1;
22531 this.generatedCodeColumn += 1;
22532 }
22533
22534 originalCharIndex += 1;
22535 first = false;
22536 }
22537
22538 this.pending = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
22539 };
22540
22541 Mappings.prototype.advance = function advance (str) {
22542 if (!str) { return; }
22543
22544 var lines = str.split('\n');
22545
22546 if (lines.length > 1) {
22547 for (var i = 0; i < lines.length - 1; i++) {
22548 this.generatedCodeLine++;
22549 this.raw[this.generatedCodeLine] = this.rawSegments = [];
22550 }
22551 this.generatedCodeColumn = 0;
22552 }
22553
22554 this.generatedCodeColumn += lines[lines.length - 1].length;
22555 };
22556
22557 var n = '\n';
22558
22559 var warned = {
22560 insertLeft: false,
22561 insertRight: false,
22562 storeName: false
22563 };
22564
22565 var MagicString = function MagicString(string, options) {
22566 if ( options === void 0 ) options = {};
22567
22568 var chunk = new Chunk(0, string.length, string);
22569
22570 Object.defineProperties(this, {
22571 original: { writable: true, value: string },
22572 outro: { writable: true, value: '' },
22573 intro: { writable: true, value: '' },
22574 firstChunk: { writable: true, value: chunk },
22575 lastChunk: { writable: true, value: chunk },
22576 lastSearchedChunk: { writable: true, value: chunk },
22577 byStart: { writable: true, value: {} },
22578 byEnd: { writable: true, value: {} },
22579 filename: { writable: true, value: options.filename },
22580 indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
22581 sourcemapLocations: { writable: true, value: {} },
22582 storedNames: { writable: true, value: {} },
22583 indentStr: { writable: true, value: guessIndent(string) }
22584 });
22585
22586 this.byStart[0] = chunk;
22587 this.byEnd[string.length] = chunk;
22588 };
22589
22590 MagicString.prototype.addSourcemapLocation = function addSourcemapLocation (char) {
22591 this.sourcemapLocations[char] = true;
22592 };
22593
22594 MagicString.prototype.append = function append (content) {
22595 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
22596
22597 this.outro += content;
22598 return this;
22599 };
22600
22601 MagicString.prototype.appendLeft = function appendLeft (index, content) {
22602 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22603
22604 this._split(index);
22605
22606 var chunk = this.byEnd[index];
22607
22608 if (chunk) {
22609 chunk.appendLeft(content);
22610 } else {
22611 this.intro += content;
22612 }
22613 return this;
22614 };
22615
22616 MagicString.prototype.appendRight = function appendRight (index, content) {
22617 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22618
22619 this._split(index);
22620
22621 var chunk = this.byStart[index];
22622
22623 if (chunk) {
22624 chunk.appendRight(content);
22625 } else {
22626 this.outro += content;
22627 }
22628 return this;
22629 };
22630
22631 MagicString.prototype.clone = function clone () {
22632 var cloned = new MagicString(this.original, { filename: this.filename });
22633
22634 var originalChunk = this.firstChunk;
22635 var clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());
22636
22637 while (originalChunk) {
22638 cloned.byStart[clonedChunk.start] = clonedChunk;
22639 cloned.byEnd[clonedChunk.end] = clonedChunk;
22640
22641 var nextOriginalChunk = originalChunk.next;
22642 var nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
22643
22644 if (nextClonedChunk) {
22645 clonedChunk.next = nextClonedChunk;
22646 nextClonedChunk.previous = clonedChunk;
22647
22648 clonedChunk = nextClonedChunk;
22649 }
22650
22651 originalChunk = nextOriginalChunk;
22652 }
22653
22654 cloned.lastChunk = clonedChunk;
22655
22656 if (this.indentExclusionRanges) {
22657 cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
22658 }
22659
22660 Object.keys(this.sourcemapLocations).forEach(function (loc) {
22661 cloned.sourcemapLocations[loc] = true;
22662 });
22663
22664 return cloned;
22665 };
22666
22667 MagicString.prototype.generateDecodedMap = function generateDecodedMap (options) {
22668 var this$1 = this;
22669
22670 options = options || {};
22671
22672 var sourceIndex = 0;
22673 var names = Object.keys(this.storedNames);
22674 var mappings = new Mappings(options.hires);
22675
22676 var locate = getLocator$1(this.original);
22677
22678 if (this.intro) {
22679 mappings.advance(this.intro);
22680 }
22681
22682 this.firstChunk.eachNext(function (chunk) {
22683 var loc = locate(chunk.start);
22684
22685 if (chunk.intro.length) { mappings.advance(chunk.intro); }
22686
22687 if (chunk.edited) {
22688 mappings.addEdit(
22689 sourceIndex,
22690 chunk.content,
22691 loc,
22692 chunk.storeName ? names.indexOf(chunk.original) : -1
22693 );
22694 } else {
22695 mappings.addUneditedChunk(sourceIndex, chunk, this$1.original, loc, this$1.sourcemapLocations);
22696 }
22697
22698 if (chunk.outro.length) { mappings.advance(chunk.outro); }
22699 });
22700
22701 return {
22702 file: options.file ? options.file.split(/[/\\]/).pop() : null,
22703 sources: [options.source ? getRelativePath(options.file || '', options.source) : null],
22704 sourcesContent: options.includeContent ? [this.original] : [null],
22705 names: names,
22706 mappings: mappings.raw
22707 };
22708 };
22709
22710 MagicString.prototype.generateMap = function generateMap (options) {
22711 return new SourceMap(this.generateDecodedMap(options));
22712 };
22713
22714 MagicString.prototype.getIndentString = function getIndentString () {
22715 return this.indentStr === null ? '\t' : this.indentStr;
22716 };
22717
22718 MagicString.prototype.indent = function indent (indentStr, options) {
22719 var pattern = /^[^\r\n]/gm;
22720
22721 if (isObject(indentStr)) {
22722 options = indentStr;
22723 indentStr = undefined;
22724 }
22725
22726 indentStr = indentStr !== undefined ? indentStr : this.indentStr || '\t';
22727
22728 if (indentStr === '') { return this; } // noop
22729
22730 options = options || {};
22731
22732 // Process exclusion ranges
22733 var isExcluded = {};
22734
22735 if (options.exclude) {
22736 var exclusions =
22737 typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;
22738 exclusions.forEach(function (exclusion) {
22739 for (var i = exclusion[0]; i < exclusion[1]; i += 1) {
22740 isExcluded[i] = true;
22741 }
22742 });
22743 }
22744
22745 var shouldIndentNextCharacter = options.indentStart !== false;
22746 var replacer = function (match) {
22747 if (shouldIndentNextCharacter) { return ("" + indentStr + match); }
22748 shouldIndentNextCharacter = true;
22749 return match;
22750 };
22751
22752 this.intro = this.intro.replace(pattern, replacer);
22753
22754 var charIndex = 0;
22755 var chunk = this.firstChunk;
22756
22757 while (chunk) {
22758 var end = chunk.end;
22759
22760 if (chunk.edited) {
22761 if (!isExcluded[charIndex]) {
22762 chunk.content = chunk.content.replace(pattern, replacer);
22763
22764 if (chunk.content.length) {
22765 shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';
22766 }
22767 }
22768 } else {
22769 charIndex = chunk.start;
22770
22771 while (charIndex < end) {
22772 if (!isExcluded[charIndex]) {
22773 var char = this.original[charIndex];
22774
22775 if (char === '\n') {
22776 shouldIndentNextCharacter = true;
22777 } else if (char !== '\r' && shouldIndentNextCharacter) {
22778 shouldIndentNextCharacter = false;
22779
22780 if (charIndex === chunk.start) {
22781 chunk.prependRight(indentStr);
22782 } else {
22783 this._splitChunk(chunk, charIndex);
22784 chunk = chunk.next;
22785 chunk.prependRight(indentStr);
22786 }
22787 }
22788 }
22789
22790 charIndex += 1;
22791 }
22792 }
22793
22794 charIndex = chunk.end;
22795 chunk = chunk.next;
22796 }
22797
22798 this.outro = this.outro.replace(pattern, replacer);
22799
22800 return this;
22801 };
22802
22803 MagicString.prototype.insert = function insert () {
22804 throw new Error('magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)');
22805 };
22806
22807 MagicString.prototype.insertLeft = function insertLeft (index, content) {
22808 if (!warned.insertLeft) {
22809 console.warn('magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead'); // eslint-disable-line no-console
22810 warned.insertLeft = true;
22811 }
22812
22813 return this.appendLeft(index, content);
22814 };
22815
22816 MagicString.prototype.insertRight = function insertRight (index, content) {
22817 if (!warned.insertRight) {
22818 console.warn('magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead'); // eslint-disable-line no-console
22819 warned.insertRight = true;
22820 }
22821
22822 return this.prependRight(index, content);
22823 };
22824
22825 MagicString.prototype.move = function move (start, end, index) {
22826 if (index >= start && index <= end) { throw new Error('Cannot move a selection inside itself'); }
22827
22828 this._split(start);
22829 this._split(end);
22830 this._split(index);
22831
22832 var first = this.byStart[start];
22833 var last = this.byEnd[end];
22834
22835 var oldLeft = first.previous;
22836 var oldRight = last.next;
22837
22838 var newRight = this.byStart[index];
22839 if (!newRight && last === this.lastChunk) { return this; }
22840 var newLeft = newRight ? newRight.previous : this.lastChunk;
22841
22842 if (oldLeft) { oldLeft.next = oldRight; }
22843 if (oldRight) { oldRight.previous = oldLeft; }
22844
22845 if (newLeft) { newLeft.next = first; }
22846 if (newRight) { newRight.previous = last; }
22847
22848 if (!first.previous) { this.firstChunk = last.next; }
22849 if (!last.next) {
22850 this.lastChunk = first.previous;
22851 this.lastChunk.next = null;
22852 }
22853
22854 first.previous = newLeft;
22855 last.next = newRight || null;
22856
22857 if (!newLeft) { this.firstChunk = first; }
22858 if (!newRight) { this.lastChunk = last; }
22859 return this;
22860 };
22861
22862 MagicString.prototype.overwrite = function overwrite (start, end, content, options) {
22863 if (typeof content !== 'string') { throw new TypeError('replacement content must be a string'); }
22864
22865 while (start < 0) { start += this.original.length; }
22866 while (end < 0) { end += this.original.length; }
22867
22868 if (end > this.original.length) { throw new Error('end is out of bounds'); }
22869 if (start === end)
22870 { throw new Error('Cannot overwrite a zero-length range – use appendLeft or prependRight instead'); }
22871
22872 this._split(start);
22873 this._split(end);
22874
22875 if (options === true) {
22876 if (!warned.storeName) {
22877 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
22878 warned.storeName = true;
22879 }
22880
22881 options = { storeName: true };
22882 }
22883 var storeName = options !== undefined ? options.storeName : false;
22884 var contentOnly = options !== undefined ? options.contentOnly : false;
22885
22886 if (storeName) {
22887 var original = this.original.slice(start, end);
22888 this.storedNames[original] = true;
22889 }
22890
22891 var first = this.byStart[start];
22892 var last = this.byEnd[end];
22893
22894 if (first) {
22895 if (end > first.end && first.next !== this.byStart[first.end]) {
22896 throw new Error('Cannot overwrite across a split point');
22897 }
22898
22899 first.edit(content, storeName, contentOnly);
22900
22901 if (first !== last) {
22902 var chunk = first.next;
22903 while (chunk !== last) {
22904 chunk.edit('', false);
22905 chunk = chunk.next;
22906 }
22907
22908 chunk.edit('', false);
22909 }
22910 } else {
22911 // must be inserting at the end
22912 var newChunk = new Chunk(start, end, '').edit(content, storeName);
22913
22914 // TODO last chunk in the array may not be the last chunk, if it's moved...
22915 last.next = newChunk;
22916 newChunk.previous = last;
22917 }
22918 return this;
22919 };
22920
22921 MagicString.prototype.prepend = function prepend (content) {
22922 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
22923
22924 this.intro = content + this.intro;
22925 return this;
22926 };
22927
22928 MagicString.prototype.prependLeft = function prependLeft (index, content) {
22929 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22930
22931 this._split(index);
22932
22933 var chunk = this.byEnd[index];
22934
22935 if (chunk) {
22936 chunk.prependLeft(content);
22937 } else {
22938 this.intro = content + this.intro;
22939 }
22940 return this;
22941 };
22942
22943 MagicString.prototype.prependRight = function prependRight (index, content) {
22944 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22945
22946 this._split(index);
22947
22948 var chunk = this.byStart[index];
22949
22950 if (chunk) {
22951 chunk.prependRight(content);
22952 } else {
22953 this.outro = content + this.outro;
22954 }
22955 return this;
22956 };
22957
22958 MagicString.prototype.remove = function remove (start, end) {
22959 while (start < 0) { start += this.original.length; }
22960 while (end < 0) { end += this.original.length; }
22961
22962 if (start === end) { return this; }
22963
22964 if (start < 0 || end > this.original.length) { throw new Error('Character is out of bounds'); }
22965 if (start > end) { throw new Error('end must be greater than start'); }
22966
22967 this._split(start);
22968 this._split(end);
22969
22970 var chunk = this.byStart[start];
22971
22972 while (chunk) {
22973 chunk.intro = '';
22974 chunk.outro = '';
22975 chunk.edit('');
22976
22977 chunk = end > chunk.end ? this.byStart[chunk.end] : null;
22978 }
22979 return this;
22980 };
22981
22982 MagicString.prototype.lastChar = function lastChar () {
22983 if (this.outro.length)
22984 { return this.outro[this.outro.length - 1]; }
22985 var chunk = this.lastChunk;
22986 do {
22987 if (chunk.outro.length)
22988 { return chunk.outro[chunk.outro.length - 1]; }
22989 if (chunk.content.length)
22990 { return chunk.content[chunk.content.length - 1]; }
22991 if (chunk.intro.length)
22992 { return chunk.intro[chunk.intro.length - 1]; }
22993 } while (chunk = chunk.previous);
22994 if (this.intro.length)
22995 { return this.intro[this.intro.length - 1]; }
22996 return '';
22997 };
22998
22999 MagicString.prototype.lastLine = function lastLine () {
23000 var lineIndex = this.outro.lastIndexOf(n);
23001 if (lineIndex !== -1)
23002 { return this.outro.substr(lineIndex + 1); }
23003 var lineStr = this.outro;
23004 var chunk = this.lastChunk;
23005 do {
23006 if (chunk.outro.length > 0) {
23007 lineIndex = chunk.outro.lastIndexOf(n);
23008 if (lineIndex !== -1)
23009 { return chunk.outro.substr(lineIndex + 1) + lineStr; }
23010 lineStr = chunk.outro + lineStr;
23011 }
23012
23013 if (chunk.content.length > 0) {
23014 lineIndex = chunk.content.lastIndexOf(n);
23015 if (lineIndex !== -1)
23016 { return chunk.content.substr(lineIndex + 1) + lineStr; }
23017 lineStr = chunk.content + lineStr;
23018 }
23019
23020 if (chunk.intro.length > 0) {
23021 lineIndex = chunk.intro.lastIndexOf(n);
23022 if (lineIndex !== -1)
23023 { return chunk.intro.substr(lineIndex + 1) + lineStr; }
23024 lineStr = chunk.intro + lineStr;
23025 }
23026 } while (chunk = chunk.previous);
23027 lineIndex = this.intro.lastIndexOf(n);
23028 if (lineIndex !== -1)
23029 { return this.intro.substr(lineIndex + 1) + lineStr; }
23030 return this.intro + lineStr;
23031 };
23032
23033 MagicString.prototype.slice = function slice (start, end) {
23034 if ( start === void 0 ) start = 0;
23035 if ( end === void 0 ) end = this.original.length;
23036
23037 while (start < 0) { start += this.original.length; }
23038 while (end < 0) { end += this.original.length; }
23039
23040 var result = '';
23041
23042 // find start chunk
23043 var chunk = this.firstChunk;
23044 while (chunk && (chunk.start > start || chunk.end <= start)) {
23045 // found end chunk before start
23046 if (chunk.start < end && chunk.end >= end) {
23047 return result;
23048 }
23049
23050 chunk = chunk.next;
23051 }
23052
23053 if (chunk && chunk.edited && chunk.start !== start)
23054 { throw new Error(("Cannot use replaced character " + start + " as slice start anchor.")); }
23055
23056 var startChunk = chunk;
23057 while (chunk) {
23058 if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
23059 result += chunk.intro;
23060 }
23061
23062 var containsEnd = chunk.start < end && chunk.end >= end;
23063 if (containsEnd && chunk.edited && chunk.end !== end)
23064 { throw new Error(("Cannot use replaced character " + end + " as slice end anchor.")); }
23065
23066 var sliceStart = startChunk === chunk ? start - chunk.start : 0;
23067 var sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
23068
23069 result += chunk.content.slice(sliceStart, sliceEnd);
23070
23071 if (chunk.outro && (!containsEnd || chunk.end === end)) {
23072 result += chunk.outro;
23073 }
23074
23075 if (containsEnd) {
23076 break;
23077 }
23078
23079 chunk = chunk.next;
23080 }
23081
23082 return result;
23083 };
23084
23085 // TODO deprecate this? not really very useful
23086 MagicString.prototype.snip = function snip (start, end) {
23087 var clone = this.clone();
23088 clone.remove(0, start);
23089 clone.remove(end, clone.original.length);
23090
23091 return clone;
23092 };
23093
23094 MagicString.prototype._split = function _split (index) {
23095 if (this.byStart[index] || this.byEnd[index]) { return; }
23096
23097 var chunk = this.lastSearchedChunk;
23098 var searchForward = index > chunk.end;
23099
23100 while (chunk) {
23101 if (chunk.contains(index)) { return this._splitChunk(chunk, index); }
23102
23103 chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
23104 }
23105 };
23106
23107 MagicString.prototype._splitChunk = function _splitChunk (chunk, index) {
23108 if (chunk.edited && chunk.content.length) {
23109 // zero-length edited chunks are a special case (overlapping replacements)
23110 var loc = getLocator$1(this.original)(index);
23111 throw new Error(
23112 ("Cannot split a chunk that has already been edited (" + (loc.line) + ":" + (loc.column) + " – \"" + (chunk.original) + "\")")
23113 );
23114 }
23115
23116 var newChunk = chunk.split(index);
23117
23118 this.byEnd[index] = chunk;
23119 this.byStart[index] = newChunk;
23120 this.byEnd[newChunk.end] = newChunk;
23121
23122 if (chunk === this.lastChunk) { this.lastChunk = newChunk; }
23123
23124 this.lastSearchedChunk = chunk;
23125 return true;
23126 };
23127
23128 MagicString.prototype.toString = function toString () {
23129 var str = this.intro;
23130
23131 var chunk = this.firstChunk;
23132 while (chunk) {
23133 str += chunk.toString();
23134 chunk = chunk.next;
23135 }
23136
23137 return str + this.outro;
23138 };
23139
23140 MagicString.prototype.isEmpty = function isEmpty () {
23141 var chunk = this.firstChunk;
23142 do {
23143 if (chunk.intro.length && chunk.intro.trim() ||
23144 chunk.content.length && chunk.content.trim() ||
23145 chunk.outro.length && chunk.outro.trim())
23146 { return false; }
23147 } while (chunk = chunk.next);
23148 return true;
23149 };
23150
23151 MagicString.prototype.length = function length () {
23152 var chunk = this.firstChunk;
23153 var length = 0;
23154 do {
23155 length += chunk.intro.length + chunk.content.length + chunk.outro.length;
23156 } while (chunk = chunk.next);
23157 return length;
23158 };
23159
23160 MagicString.prototype.trimLines = function trimLines () {
23161 return this.trim('[\\r\\n]');
23162 };
23163
23164 MagicString.prototype.trim = function trim (charType) {
23165 return this.trimStart(charType).trimEnd(charType);
23166 };
23167
23168 MagicString.prototype.trimEndAborted = function trimEndAborted (charType) {
23169 var rx = new RegExp((charType || '\\s') + '+$');
23170
23171 this.outro = this.outro.replace(rx, '');
23172 if (this.outro.length) { return true; }
23173
23174 var chunk = this.lastChunk;
23175
23176 do {
23177 var end = chunk.end;
23178 var aborted = chunk.trimEnd(rx);
23179
23180 // if chunk was trimmed, we have a new lastChunk
23181 if (chunk.end !== end) {
23182 if (this.lastChunk === chunk) {
23183 this.lastChunk = chunk.next;
23184 }
23185
23186 this.byEnd[chunk.end] = chunk;
23187 this.byStart[chunk.next.start] = chunk.next;
23188 this.byEnd[chunk.next.end] = chunk.next;
23189 }
23190
23191 if (aborted) { return true; }
23192 chunk = chunk.previous;
23193 } while (chunk);
23194
23195 return false;
23196 };
23197
23198 MagicString.prototype.trimEnd = function trimEnd (charType) {
23199 this.trimEndAborted(charType);
23200 return this;
23201 };
23202 MagicString.prototype.trimStartAborted = function trimStartAborted (charType) {
23203 var rx = new RegExp('^' + (charType || '\\s') + '+');
23204
23205 this.intro = this.intro.replace(rx, '');
23206 if (this.intro.length) { return true; }
23207
23208 var chunk = this.firstChunk;
23209
23210 do {
23211 var end = chunk.end;
23212 var aborted = chunk.trimStart(rx);
23213
23214 if (chunk.end !== end) {
23215 // special case...
23216 if (chunk === this.lastChunk) { this.lastChunk = chunk.next; }
23217
23218 this.byEnd[chunk.end] = chunk;
23219 this.byStart[chunk.next.start] = chunk.next;
23220 this.byEnd[chunk.next.end] = chunk.next;
23221 }
23222
23223 if (aborted) { return true; }
23224 chunk = chunk.next;
23225 } while (chunk);
23226
23227 return false;
23228 };
23229
23230 MagicString.prototype.trimStart = function trimStart (charType) {
23231 this.trimStartAborted(charType);
23232 return this;
23233 };
23234
23235 const UNKNOWN = {};
23236 function gather_possible_values(node, set) {
23237 if (node.type === 'Literal') {
23238 set.add(node.value);
23239 }
23240 else if (node.type === 'ConditionalExpression') {
23241 gather_possible_values(node.consequent, set);
23242 gather_possible_values(node.alternate, set);
23243 }
23244 else {
23245 set.add(UNKNOWN);
23246 }
23247 }
23248
23249 var BlockAppliesToNode;
23250 (function (BlockAppliesToNode) {
23251 BlockAppliesToNode[BlockAppliesToNode["NotPossible"] = 0] = "NotPossible";
23252 BlockAppliesToNode[BlockAppliesToNode["Possible"] = 1] = "Possible";
23253 BlockAppliesToNode[BlockAppliesToNode["UnknownSelectorType"] = 2] = "UnknownSelectorType";
23254 })(BlockAppliesToNode || (BlockAppliesToNode = {}));
23255 class Selector$1 {
23256 constructor(node, stylesheet) {
23257 this.node = node;
23258 this.stylesheet = stylesheet;
23259 this.blocks = group_selectors(node);
23260 // take trailing :global(...) selectors out of consideration
23261 let i = this.blocks.length;
23262 while (i > 0) {
23263 if (!this.blocks[i - 1].global)
23264 break;
23265 i -= 1;
23266 }
23267 this.local_blocks = this.blocks.slice(0, i);
23268 this.used = this.local_blocks.length === 0;
23269 }
23270 apply(node, stack) {
23271 const to_encapsulate = [];
23272 apply_selector(this.local_blocks.slice(), node, stack.slice(), to_encapsulate);
23273 if (to_encapsulate.length > 0) {
23274 to_encapsulate.forEach(({ node, block }) => {
23275 this.stylesheet.nodes_with_css_class.add(node);
23276 block.should_encapsulate = true;
23277 });
23278 this.used = true;
23279 }
23280 }
23281 minify(code) {
23282 let c = null;
23283 this.blocks.forEach((block, i) => {
23284 if (i > 0) {
23285 if (block.start - c > 1) {
23286 code.overwrite(c, block.start, block.combinator.name || ' ');
23287 }
23288 }
23289 c = block.end;
23290 });
23291 }
23292 transform(code, attr, max_amount_class_specificity_increased) {
23293 const amount_class_specificity_to_increase = max_amount_class_specificity_increased - this.blocks.filter(block => block.should_encapsulate).length;
23294 attr = attr.repeat(amount_class_specificity_to_increase + 1);
23295 function encapsulate_block(block) {
23296 let i = block.selectors.length;
23297 while (i--) {
23298 const selector = block.selectors[i];
23299 if (selector.type === 'PseudoElementSelector' || selector.type === 'PseudoClassSelector') {
23300 if (selector.name !== 'root') {
23301 if (i === 0)
23302 code.prependRight(selector.start, attr);
23303 }
23304 continue;
23305 }
23306 if (selector.type === 'TypeSelector' && selector.name === '*') {
23307 code.overwrite(selector.start, selector.end, attr);
23308 }
23309 else {
23310 code.appendLeft(selector.end, attr);
23311 }
23312 break;
23313 }
23314 }
23315 this.blocks.forEach((block) => {
23316 if (block.global) {
23317 const selector = block.selectors[0];
23318 const first = selector.children[0];
23319 const last = selector.children[selector.children.length - 1];
23320 code.remove(selector.start, first.start).remove(last.end, selector.end);
23321 }
23322 if (block.should_encapsulate)
23323 encapsulate_block(block);
23324 });
23325 }
23326 validate(component) {
23327 this.blocks.forEach((block) => {
23328 let i = block.selectors.length;
23329 while (i-- > 1) {
23330 const selector = block.selectors[i];
23331 if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
23332 component.error(selector, {
23333 code: `css-invalid-global`,
23334 message: `:global(...) must be the first element in a compound selector`
23335 });
23336 }
23337 }
23338 });
23339 let start = 0;
23340 let end = this.blocks.length;
23341 for (; start < end; start += 1) {
23342 if (!this.blocks[start].global)
23343 break;
23344 }
23345 for (; end > start; end -= 1) {
23346 if (!this.blocks[end - 1].global)
23347 break;
23348 }
23349 for (let i = start; i < end; i += 1) {
23350 if (this.blocks[i].global) {
23351 component.error(this.blocks[i].selectors[0], {
23352 code: `css-invalid-global`,
23353 message: `:global(...) can be at the start or end of a selector sequence, but not in the middle`
23354 });
23355 }
23356 }
23357 }
23358 get_amount_class_specificity_increased() {
23359 let count = 0;
23360 for (const block of this.blocks) {
23361 if (block.should_encapsulate) {
23362 count++;
23363 }
23364 }
23365 return count;
23366 }
23367 }
23368 function apply_selector(blocks, node, stack, to_encapsulate) {
23369 const block = blocks.pop();
23370 if (!block)
23371 return false;
23372 if (!node) {
23373 return blocks.every(block => block.global);
23374 }
23375 switch (block_might_apply_to_node(block, node)) {
23376 case BlockAppliesToNode.NotPossible:
23377 return false;
23378 case BlockAppliesToNode.UnknownSelectorType:
23379 // bail. TODO figure out what these could be
23380 to_encapsulate.push({ node, block });
23381 return true;
23382 }
23383 if (block.combinator) {
23384 if (block.combinator.type === 'WhiteSpace') {
23385 for (const ancestor_block of blocks) {
23386 if (ancestor_block.global) {
23387 continue;
23388 }
23389 for (const stack_node of stack) {
23390 if (block_might_apply_to_node(ancestor_block, stack_node) !== BlockAppliesToNode.NotPossible) {
23391 to_encapsulate.push({ node: stack_node, block: ancestor_block });
23392 }
23393 }
23394 if (to_encapsulate.length) {
23395 to_encapsulate.push({ node, block });
23396 return true;
23397 }
23398 }
23399 if (blocks.every(block => block.global)) {
23400 to_encapsulate.push({ node, block });
23401 return true;
23402 }
23403 return false;
23404 }
23405 else if (block.combinator.name === '>') {
23406 if (apply_selector(blocks, stack.pop(), stack, to_encapsulate)) {
23407 to_encapsulate.push({ node, block });
23408 return true;
23409 }
23410 return false;
23411 }
23412 // TODO other combinators
23413 to_encapsulate.push({ node, block });
23414 return true;
23415 }
23416 to_encapsulate.push({ node, block });
23417 return true;
23418 }
23419 function block_might_apply_to_node(block, node) {
23420 let i = block.selectors.length;
23421 while (i--) {
23422 const selector = block.selectors[i];
23423 const name = typeof selector.name === 'string' && selector.name.replace(/\\(.)/g, '$1');
23424 if (selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector') {
23425 continue;
23426 }
23427 if (selector.type === 'PseudoClassSelector' && name === 'global') {
23428 // TODO shouldn't see this here... maybe we should enforce that :global(...)
23429 // cannot be sandwiched between non-global selectors?
23430 return BlockAppliesToNode.NotPossible;
23431 }
23432 if (selector.type === 'ClassSelector') {
23433 if (!attribute_matches(node, 'class', name, '~=', false) && !node.classes.some(c => c.name === name))
23434 return BlockAppliesToNode.NotPossible;
23435 }
23436 else if (selector.type === 'IdSelector') {
23437 if (!attribute_matches(node, 'id', name, '=', false))
23438 return BlockAppliesToNode.NotPossible;
23439 }
23440 else if (selector.type === 'AttributeSelector') {
23441 if (!attribute_matches(node, selector.name.name, selector.value && unquote(selector.value), selector.matcher, selector.flags))
23442 return BlockAppliesToNode.NotPossible;
23443 }
23444 else if (selector.type === 'TypeSelector') {
23445 if (node.name.toLowerCase() !== name.toLowerCase() && name !== '*')
23446 return BlockAppliesToNode.NotPossible;
23447 }
23448 else {
23449 return BlockAppliesToNode.UnknownSelectorType;
23450 }
23451 }
23452 return BlockAppliesToNode.Possible;
23453 }
23454 function test_attribute(operator, expected_value, case_insensitive, value) {
23455 if (case_insensitive) {
23456 expected_value = expected_value.toLowerCase();
23457 value = value.toLowerCase();
23458 }
23459 switch (operator) {
23460 case '=': return value === expected_value;
23461 case '~=': return value.split(/\s/).includes(expected_value);
23462 case '|=': return `${value}-`.startsWith(`${expected_value}-`);
23463 case '^=': return value.startsWith(expected_value);
23464 case '$=': return value.endsWith(expected_value);
23465 case '*=': return value.includes(expected_value);
23466 default: throw new Error(`this shouldn't happen`);
23467 }
23468 }
23469 function attribute_matches(node, name, expected_value, operator, case_insensitive) {
23470 const spread = node.attributes.find(attr => attr.type === 'Spread');
23471 if (spread)
23472 return true;
23473 if (node.bindings.some((binding) => binding.name === name))
23474 return true;
23475 const attr = node.attributes.find((attr) => attr.name === name);
23476 if (!attr)
23477 return false;
23478 if (attr.is_true)
23479 return operator === null;
23480 if (!expected_value)
23481 return true;
23482 if (attr.chunks.length === 1) {
23483 const value = attr.chunks[0];
23484 if (!value)
23485 return false;
23486 if (value.type === 'Text')
23487 return test_attribute(operator, expected_value, case_insensitive, value.data);
23488 }
23489 const possible_values = new Set();
23490 let prev_values = [];
23491 for (const chunk of attr.chunks) {
23492 const current_possible_values = new Set();
23493 if (chunk.type === 'Text') {
23494 current_possible_values.add(chunk.data);
23495 }
23496 else {
23497 gather_possible_values(chunk.node, current_possible_values);
23498 }
23499 // impossible to find out all combinations
23500 if (current_possible_values.has(UNKNOWN))
23501 return true;
23502 if (prev_values.length > 0) {
23503 const start_with_space = [];
23504 const remaining = [];
23505 current_possible_values.forEach((current_possible_value) => {
23506 if (/^\s/.test(current_possible_value)) {
23507 start_with_space.push(current_possible_value);
23508 }
23509 else {
23510 remaining.push(current_possible_value);
23511 }
23512 });
23513 if (remaining.length > 0) {
23514 if (start_with_space.length > 0) {
23515 prev_values.forEach(prev_value => possible_values.add(prev_value));
23516 }
23517 const combined = [];
23518 prev_values.forEach((prev_value) => {
23519 remaining.forEach((value) => {
23520 combined.push(prev_value + value);
23521 });
23522 });
23523 prev_values = combined;
23524 start_with_space.forEach((value) => {
23525 if (/\s$/.test(value)) {
23526 possible_values.add(value);
23527 }
23528 else {
23529 prev_values.push(value);
23530 }
23531 });
23532 continue;
23533 }
23534 else {
23535 prev_values.forEach(prev_value => possible_values.add(prev_value));
23536 prev_values = [];
23537 }
23538 }
23539 current_possible_values.forEach((current_possible_value) => {
23540 if (/\s$/.test(current_possible_value)) {
23541 possible_values.add(current_possible_value);
23542 }
23543 else {
23544 prev_values.push(current_possible_value);
23545 }
23546 });
23547 if (prev_values.length < current_possible_values.size) {
23548 prev_values.push(' ');
23549 }
23550 if (prev_values.length > 20) {
23551 // might grow exponentially, bail out
23552 return true;
23553 }
23554 }
23555 prev_values.forEach(prev_value => possible_values.add(prev_value));
23556 if (possible_values.has(UNKNOWN))
23557 return true;
23558 for (const value of possible_values) {
23559 if (test_attribute(operator, expected_value, case_insensitive, value))
23560 return true;
23561 }
23562 return false;
23563 }
23564 function unquote(value) {
23565 if (value.type === 'Identifier')
23566 return value.name;
23567 const str = value.value;
23568 if (str[0] === str[str.length - 1] && str[0] === "'" || str[0] === '"') {
23569 return str.slice(1, str.length - 1);
23570 }
23571 return str;
23572 }
23573 class Block$2 {
23574 constructor(combinator) {
23575 this.combinator = combinator;
23576 this.global = false;
23577 this.selectors = [];
23578 this.start = null;
23579 this.end = null;
23580 this.should_encapsulate = false;
23581 }
23582 add(selector) {
23583 if (this.selectors.length === 0) {
23584 this.start = selector.start;
23585 this.global = selector.type === 'PseudoClassSelector' && selector.name === 'global';
23586 }
23587 this.selectors.push(selector);
23588 this.end = selector.end;
23589 }
23590 }
23591 function group_selectors(selector) {
23592 let block = new Block$2(null);
23593 const blocks = [block];
23594 selector.children.forEach((child) => {
23595 if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
23596 block = new Block$2(child);
23597 blocks.push(block);
23598 }
23599 else {
23600 block.add(child);
23601 }
23602 });
23603 return blocks;
23604 }
23605
23606 // https://github.com/darkskyapp/string-hash/blob/master/index.js
23607 function hash(str) {
23608 str = str.replace(/\r/g, "");
23609 let hash = 5381;
23610 let i = str.length;
23611 while (i--)
23612 hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
23613 return (hash >>> 0).toString(36);
23614 }
23615
23616 function remove_css_prefix(name) {
23617 return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, '');
23618 }
23619 const is_keyframes_node = (node) => remove_css_prefix(node.name) === 'keyframes';
23620 const at_rule_has_declaration = ({ block }) => block &&
23621 block.children &&
23622 block.children.find((node) => node.type === 'Declaration');
23623 function minify_declarations(code, start, declarations) {
23624 let c = start;
23625 declarations.forEach((declaration, i) => {
23626 const separator = i > 0 ? ';' : '';
23627 if ((declaration.node.start - c) > separator.length) {
23628 code.overwrite(c, declaration.node.start, separator);
23629 }
23630 declaration.minify(code);
23631 c = declaration.node.end;
23632 });
23633 return c;
23634 }
23635 class Rule$1 {
23636 constructor(node, stylesheet, parent) {
23637 this.node = node;
23638 this.parent = parent;
23639 this.selectors = node.selector.children.map((node) => new Selector$1(node, stylesheet));
23640 this.declarations = node.block.children.map((node) => new Declaration$1(node));
23641 }
23642 apply(node, stack) {
23643 this.selectors.forEach(selector => selector.apply(node, stack)); // TODO move the logic in here?
23644 }
23645 is_used(dev) {
23646 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
23647 return true;
23648 if (this.declarations.length === 0)
23649 return dev;
23650 return this.selectors.some(s => s.used);
23651 }
23652 minify(code, _dev) {
23653 let c = this.node.start;
23654 let started = false;
23655 this.selectors.forEach((selector) => {
23656 if (selector.used) {
23657 const separator = started ? ',' : '';
23658 if ((selector.node.start - c) > separator.length) {
23659 code.overwrite(c, selector.node.start, separator);
23660 }
23661 selector.minify(code);
23662 c = selector.node.end;
23663 started = true;
23664 }
23665 });
23666 code.remove(c, this.node.block.start);
23667 c = this.node.block.start + 1;
23668 c = minify_declarations(code, c, this.declarations);
23669 code.remove(c, this.node.block.end - 1);
23670 }
23671 transform(code, id, keyframes, max_amount_class_specificity_increased) {
23672 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
23673 return true;
23674 const attr = `.${id}`;
23675 this.selectors.forEach(selector => selector.transform(code, attr, max_amount_class_specificity_increased));
23676 this.declarations.forEach(declaration => declaration.transform(code, keyframes));
23677 }
23678 validate(component) {
23679 this.selectors.forEach(selector => {
23680 selector.validate(component);
23681 });
23682 }
23683 warn_on_unused_selector(handler) {
23684 this.selectors.forEach(selector => {
23685 if (!selector.used)
23686 handler(selector);
23687 });
23688 }
23689 get_max_amount_class_specificity_increased() {
23690 return Math.max(...this.selectors.map(selector => selector.get_amount_class_specificity_increased()));
23691 }
23692 }
23693 class Declaration$1 {
23694 constructor(node) {
23695 this.node = node;
23696 }
23697 transform(code, keyframes) {
23698 const property = this.node.property && remove_css_prefix(this.node.property.toLowerCase());
23699 if (property === 'animation' || property === 'animation-name') {
23700 this.node.value.children.forEach((block) => {
23701 if (block.type === 'Identifier') {
23702 const name = block.name;
23703 if (keyframes.has(name)) {
23704 code.overwrite(block.start, block.end, keyframes.get(name));
23705 }
23706 }
23707 });
23708 }
23709 }
23710 minify(code) {
23711 if (!this.node.property)
23712 return; // @apply, and possibly other weird cases?
23713 const c = this.node.start + this.node.property.length;
23714 const first = this.node.value.children
23715 ? this.node.value.children[0]
23716 : this.node.value;
23717 let start = first.start;
23718 while (/\s/.test(code.original[start]))
23719 start += 1;
23720 if (start - c > 1) {
23721 code.overwrite(c, start, ':');
23722 }
23723 }
23724 }
23725 class Atrule$1 {
23726 constructor(node) {
23727 this.node = node;
23728 this.children = [];
23729 this.declarations = [];
23730 }
23731 apply(node, stack) {
23732 if (this.node.name === 'media' || this.node.name === 'supports') {
23733 this.children.forEach(child => {
23734 child.apply(node, stack);
23735 });
23736 }
23737 else if (is_keyframes_node(this.node)) {
23738 this.children.forEach((rule) => {
23739 rule.selectors.forEach(selector => {
23740 selector.used = true;
23741 });
23742 });
23743 }
23744 }
23745 is_used(_dev) {
23746 return true; // TODO
23747 }
23748 minify(code, dev) {
23749 if (this.node.name === 'media') {
23750 const expression_char = code.original[this.node.expression.start];
23751 let c = this.node.start + (expression_char === '(' ? 6 : 7);
23752 if (this.node.expression.start > c)
23753 code.remove(c, this.node.expression.start);
23754 this.node.expression.children.forEach((query) => {
23755 // TODO minify queries
23756 c = query.end;
23757 });
23758 code.remove(c, this.node.block.start);
23759 }
23760 else if (this.node.name === 'supports') {
23761 let c = this.node.start + 9;
23762 if (this.node.expression.start - c > 1)
23763 code.overwrite(c, this.node.expression.start, ' ');
23764 this.node.expression.children.forEach((query) => {
23765 // TODO minify queries
23766 c = query.end;
23767 });
23768 code.remove(c, this.node.block.start);
23769 }
23770 else {
23771 let c = this.node.start + this.node.name.length + 1;
23772 if (this.node.expression) {
23773 if (this.node.expression.start - c > 1)
23774 code.overwrite(c, this.node.expression.start, ' ');
23775 c = this.node.expression.end;
23776 }
23777 if (this.node.block && this.node.block.start - c > 0) {
23778 code.remove(c, this.node.block.start);
23779 }
23780 }
23781 // TODO other atrules
23782 if (this.node.block) {
23783 let c = this.node.block.start + 1;
23784 if (this.declarations.length) {
23785 c = minify_declarations(code, c, this.declarations);
23786 // if the atrule has children, leave the last declaration semicolon alone
23787 if (this.children.length)
23788 c++;
23789 }
23790 this.children.forEach(child => {
23791 if (child.is_used(dev)) {
23792 code.remove(c, child.node.start);
23793 child.minify(code, dev);
23794 c = child.node.end;
23795 }
23796 });
23797 code.remove(c, this.node.block.end - 1);
23798 }
23799 }
23800 transform(code, id, keyframes, max_amount_class_specificity_increased) {
23801 if (is_keyframes_node(this.node)) {
23802 this.node.expression.children.forEach(({ type, name, start, end }) => {
23803 if (type === 'Identifier') {
23804 if (name.startsWith('-global-')) {
23805 code.remove(start, start + 8);
23806 this.children.forEach((rule) => {
23807 rule.selectors.forEach(selector => {
23808 selector.used = true;
23809 });
23810 });
23811 }
23812 else {
23813 code.overwrite(start, end, keyframes.get(name));
23814 }
23815 }
23816 });
23817 }
23818 this.children.forEach(child => {
23819 child.transform(code, id, keyframes, max_amount_class_specificity_increased);
23820 });
23821 }
23822 validate(component) {
23823 this.children.forEach(child => {
23824 child.validate(component);
23825 });
23826 }
23827 warn_on_unused_selector(handler) {
23828 if (this.node.name !== 'media')
23829 return;
23830 this.children.forEach(child => {
23831 child.warn_on_unused_selector(handler);
23832 });
23833 }
23834 get_max_amount_class_specificity_increased() {
23835 return Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
23836 }
23837 }
23838 class Stylesheet {
23839 constructor(source, ast, filename, dev) {
23840 this.children = [];
23841 this.keyframes = new Map();
23842 this.nodes_with_css_class = new Set();
23843 this.source = source;
23844 this.ast = ast;
23845 this.filename = filename;
23846 this.dev = dev;
23847 if (ast.css && ast.css.children.length) {
23848 this.id = `svelte-${hash(ast.css.content.styles)}`;
23849 this.has_styles = true;
23850 const stack = [];
23851 let depth = 0;
23852 let current_atrule = null;
23853 walk(ast.css, {
23854 enter: (node) => {
23855 if (node.type === 'Atrule') {
23856 const atrule = new Atrule$1(node);
23857 stack.push(atrule);
23858 if (current_atrule) {
23859 current_atrule.children.push(atrule);
23860 }
23861 else if (depth <= 1) {
23862 this.children.push(atrule);
23863 }
23864 if (is_keyframes_node(node)) {
23865 node.expression.children.forEach((expression) => {
23866 if (expression.type === 'Identifier' && !expression.name.startsWith('-global-')) {
23867 this.keyframes.set(expression.name, `${this.id}-${expression.name}`);
23868 }
23869 });
23870 }
23871 else if (at_rule_has_declaration(node)) {
23872 const at_rule_declarations = node.block.children
23873 .filter(node => node.type === 'Declaration')
23874 .map(node => new Declaration$1(node));
23875 atrule.declarations.push(...at_rule_declarations);
23876 }
23877 current_atrule = atrule;
23878 }
23879 if (node.type === 'Rule') {
23880 const rule = new Rule$1(node, this, current_atrule);
23881 if (current_atrule) {
23882 current_atrule.children.push(rule);
23883 }
23884 else if (depth <= 1) {
23885 this.children.push(rule);
23886 }
23887 }
23888 depth += 1;
23889 },
23890 leave: (node) => {
23891 if (node.type === 'Atrule') {
23892 stack.pop();
23893 current_atrule = stack[stack.length - 1];
23894 }
23895 depth -= 1;
23896 }
23897 });
23898 }
23899 else {
23900 this.has_styles = false;
23901 }
23902 }
23903 apply(node) {
23904 if (!this.has_styles)
23905 return;
23906 const stack = [];
23907 let parent = node;
23908 while (parent = parent.parent) {
23909 if (parent.type === 'Element')
23910 stack.unshift(parent);
23911 }
23912 for (let i = 0; i < this.children.length; i += 1) {
23913 const child = this.children[i];
23914 child.apply(node, stack);
23915 }
23916 }
23917 reify() {
23918 this.nodes_with_css_class.forEach((node) => {
23919 node.add_css_class();
23920 });
23921 }
23922 render(file, should_transform_selectors) {
23923 if (!this.has_styles) {
23924 return { code: null, map: null };
23925 }
23926 const code = new MagicString(this.source);
23927 walk(this.ast.css, {
23928 enter: (node) => {
23929 code.addSourcemapLocation(node.start);
23930 code.addSourcemapLocation(node.end);
23931 }
23932 });
23933 if (should_transform_selectors) {
23934 const max = Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
23935 this.children.forEach((child) => {
23936 child.transform(code, this.id, this.keyframes, max);
23937 });
23938 }
23939 let c = 0;
23940 this.children.forEach(child => {
23941 if (child.is_used(this.dev)) {
23942 code.remove(c, child.node.start);
23943 child.minify(code, this.dev);
23944 c = child.node.end;
23945 }
23946 });
23947 code.remove(c, this.source.length);
23948 return {
23949 code: code.toString(),
23950 map: code.generateMap({
23951 includeContent: true,
23952 source: this.filename,
23953 file
23954 })
23955 };
23956 }
23957 validate(component) {
23958 this.children.forEach(child => {
23959 child.validate(component);
23960 });
23961 }
23962 warn_on_unused_selectors(component) {
23963 this.children.forEach(child => {
23964 child.warn_on_unused_selector((selector) => {
23965 component.warn(selector.node, {
23966 code: `css-unused-selector`,
23967 message: `Unused CSS selector`
23968 });
23969 });
23970 });
23971 }
23972 }
23973
23974 const test = typeof process !== 'undefined' && process.env.TEST;
23975
23976 class AbstractBlock extends Node$1 {
23977 constructor(component, parent, scope, info) {
23978 super(component, parent, scope, info);
23979 }
23980 warn_if_empty_block() {
23981 if (!this.children || this.children.length > 1)
23982 return;
23983 const child = this.children[0];
23984 if (!child || (child.type === 'Text' && !/[^ \r\n\f\v\t]/.test(child.data))) {
23985 this.component.warn(this, {
23986 code: 'empty-block',
23987 message: 'Empty block'
23988 });
23989 }
23990 }
23991 }
23992
23993 class PendingBlock extends AbstractBlock {
23994 constructor(component, parent, scope, info) {
23995 super(component, parent, scope, info);
23996 this.children = map_children(component, parent, scope, info.children);
23997 if (!info.skip) {
23998 this.warn_if_empty_block();
23999 }
24000 }
24001 }
24002
24003 class ThenBlock extends AbstractBlock {
24004 constructor(component, parent, scope, info) {
24005 super(component, parent, scope, info);
24006 this.scope = scope.child();
24007 if (parent.then_node) {
24008 parent.then_contexts.forEach(context => {
24009 this.scope.add(context.key.name, parent.expression.dependencies, this);
24010 });
24011 }
24012 this.children = map_children(component, parent, this.scope, info.children);
24013 if (!info.skip) {
24014 this.warn_if_empty_block();
24015 }
24016 }
24017 }
24018
24019 class CatchBlock extends AbstractBlock {
24020 constructor(component, parent, scope, info) {
24021 super(component, parent, scope, info);
24022 this.scope = scope.child();
24023 if (parent.catch_node) {
24024 parent.catch_contexts.forEach(context => {
24025 this.scope.add(context.key.name, parent.expression.dependencies, this);
24026 });
24027 }
24028 this.children = map_children(component, parent, this.scope, info.children);
24029 if (!info.skip) {
24030 this.warn_if_empty_block();
24031 }
24032 }
24033 }
24034
24035 function unpack_destructuring(contexts, node, modifier) {
24036 if (!node)
24037 return;
24038 if (node.type === 'Identifier') {
24039 contexts.push({
24040 key: node,
24041 modifier
24042 });
24043 }
24044 else if (node.type === 'RestElement') {
24045 contexts.push({
24046 key: node.argument,
24047 modifier
24048 });
24049 }
24050 else if (node.type === 'ArrayPattern') {
24051 node.elements.forEach((element, i) => {
24052 if (element && element.type === 'RestElement') {
24053 unpack_destructuring(contexts, element, node => x `${modifier(node)}.slice(${i})`);
24054 }
24055 else if (element && element.type === 'AssignmentPattern') {
24056 unpack_destructuring(contexts, element.left, node => x `${modifier(node)}[${i}] !== undefined ? ${modifier(node)}[${i}] : ${element.right}`);
24057 }
24058 else {
24059 unpack_destructuring(contexts, element, node => x `${modifier(node)}[${i}]`);
24060 }
24061 });
24062 }
24063 else if (node.type === 'ObjectPattern') {
24064 const used_properties = [];
24065 node.properties.forEach((property) => {
24066 if (property.type === 'RestElement') {
24067 unpack_destructuring(contexts, property.argument, node => x `@object_without_properties(${modifier(node)}, [${used_properties}])`);
24068 }
24069 else {
24070 const key = property.key;
24071 const value = property.value;
24072 used_properties.push(x `"${key.name}"`);
24073 if (value.type === 'AssignmentPattern') {
24074 unpack_destructuring(contexts, value.left, node => x `${modifier(node)}.${key.name} !== undefined ? ${modifier(node)}.${key.name} : ${value.right}`);
24075 }
24076 else {
24077 unpack_destructuring(contexts, value, node => x `${modifier(node)}.${key.name}`);
24078 }
24079 }
24080 });
24081 }
24082 }
24083
24084 class AwaitBlock$1 extends Node$1 {
24085 constructor(component, parent, scope, info) {
24086 super(component, parent, scope, info);
24087 this.expression = new Expression(component, this, scope, info.expression);
24088 this.then_node = info.value;
24089 this.catch_node = info.error;
24090 if (this.then_node) {
24091 this.then_contexts = [];
24092 unpack_destructuring(this.then_contexts, info.value, node => node);
24093 }
24094 if (this.catch_node) {
24095 this.catch_contexts = [];
24096 unpack_destructuring(this.catch_contexts, info.error, node => node);
24097 }
24098 this.pending = new PendingBlock(component, this, scope, info.pending);
24099 this.then = new ThenBlock(component, this, scope, info.then);
24100 this.catch = new CatchBlock(component, this, scope, info.catch);
24101 }
24102 }
24103
24104 class EventHandler extends Node$1 {
24105 constructor(component, parent, template_scope, info) {
24106 super(component, parent, template_scope, info);
24107 this.uses_context = false;
24108 this.can_make_passive = false;
24109 this.name = info.name;
24110 this.modifiers = new Set(info.modifiers);
24111 if (info.expression) {
24112 this.expression = new Expression(component, this, template_scope, info.expression);
24113 this.uses_context = this.expression.uses_context;
24114 if (/FunctionExpression/.test(info.expression.type) && info.expression.params.length === 0) {
24115 // TODO make this detection more accurate — if `event.preventDefault` isn't called, and
24116 // `event` is passed to another function, we can make it passive
24117 this.can_make_passive = true;
24118 }
24119 else if (info.expression.type === 'Identifier') {
24120 let node = component.node_for_declaration.get(info.expression.name);
24121 if (node) {
24122 if (node.type === 'VariableDeclaration') {
24123 // for `const handleClick = () => {...}`, we want the [arrow] function expression node
24124 const declarator = node.declarations.find(d => d.id.name === info.expression.name);
24125 node = declarator && declarator.init;
24126 }
24127 if (node && (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') && node.params.length === 0) {
24128 this.can_make_passive = true;
24129 }
24130 }
24131 }
24132 }
24133 else {
24134 this.handler_name = component.get_unique_name(`${sanitize(this.name)}_handler`);
24135 }
24136 }
24137 get reassigned() {
24138 if (!this.expression) {
24139 return false;
24140 }
24141 const node = this.expression.node;
24142 if (/FunctionExpression/.test(node.type)) {
24143 return false;
24144 }
24145 return this.expression.dynamic_dependencies().length > 0;
24146 }
24147 }
24148
24149 class Body extends Node$1 {
24150 constructor(component, parent, scope, info) {
24151 super(component, parent, scope, info);
24152 this.handlers = [];
24153 info.attributes.forEach(node => {
24154 if (node.type === 'EventHandler') {
24155 this.handlers.push(new EventHandler(component, this, scope, node));
24156 }
24157 });
24158 }
24159 }
24160
24161 const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m;
24162 class Comment$2 extends Node$1 {
24163 constructor(component, parent, scope, info) {
24164 super(component, parent, scope, info);
24165 this.data = info.data;
24166 const match = pattern.exec(this.data);
24167 this.ignores = match ? match[1].split(/[^\S]/).map(x => x.trim()).filter(Boolean) : [];
24168 }
24169 }
24170
24171 class ElseBlock extends AbstractBlock {
24172 constructor(component, parent, scope, info) {
24173 super(component, parent, scope, info);
24174 this.children = map_children(component, this, scope, info.children);
24175 this.warn_if_empty_block();
24176 }
24177 }
24178
24179 class EachBlock$1 extends AbstractBlock {
24180 constructor(component, parent, scope, info) {
24181 super(component, parent, scope, info);
24182 this.has_binding = false;
24183 this.has_index_binding = false;
24184 this.expression = new Expression(component, this, scope, info.expression);
24185 this.context = info.context.name || 'each'; // TODO this is used to facilitate binding; currently fails with destructuring
24186 this.context_node = info.context;
24187 this.index = info.index;
24188 this.scope = scope.child();
24189 this.contexts = [];
24190 unpack_destructuring(this.contexts, info.context, node => node);
24191 this.contexts.forEach(context => {
24192 this.scope.add(context.key.name, this.expression.dependencies, this);
24193 });
24194 if (this.index) {
24195 // index can only change if this is a keyed each block
24196 const dependencies = info.key ? this.expression.dependencies : new Set([]);
24197 this.scope.add(this.index, dependencies, this);
24198 }
24199 this.key = info.key
24200 ? new Expression(component, this, this.scope, info.key)
24201 : null;
24202 this.has_animation = false;
24203 this.children = map_children(component, this, this.scope, info.children);
24204 if (this.has_animation) {
24205 if (this.children.length !== 1) {
24206 const child = this.children.find(child => !!child.animation);
24207 component.error(child.animation, {
24208 code: `invalid-animation`,
24209 message: `An element that use the animate directive must be the sole child of a keyed each block`
24210 });
24211 }
24212 }
24213 this.warn_if_empty_block();
24214 this.else = info.else
24215 ? new ElseBlock(component, this, this.scope, info.else)
24216 : null;
24217 }
24218 }
24219
24220 class Attribute extends Node$1 {
24221 constructor(component, parent, scope, info) {
24222 super(component, parent, scope, info);
24223 this.scope = scope;
24224 if (info.type === 'Spread') {
24225 this.name = null;
24226 this.is_spread = true;
24227 this.is_true = false;
24228 this.expression = new Expression(component, this, scope, info.expression);
24229 this.dependencies = this.expression.dependencies;
24230 this.chunks = null;
24231 this.is_static = false;
24232 }
24233 else {
24234 this.name = info.name;
24235 this.is_true = info.value === true;
24236 this.is_static = true;
24237 this.dependencies = new Set();
24238 this.chunks = this.is_true
24239 ? []
24240 : info.value.map(node => {
24241 if (node.type === 'Text')
24242 return node;
24243 this.is_static = false;
24244 const expression = new Expression(component, this, scope, node.expression);
24245 add_to_set(this.dependencies, expression.dependencies);
24246 return expression;
24247 });
24248 }
24249 }
24250 get_dependencies() {
24251 if (this.is_spread)
24252 return this.expression.dynamic_dependencies();
24253 const dependencies = new Set();
24254 this.chunks.forEach(chunk => {
24255 if (chunk.type === 'Expression') {
24256 add_to_set(dependencies, chunk.dynamic_dependencies());
24257 }
24258 });
24259 return Array.from(dependencies);
24260 }
24261 get_value(block) {
24262 if (this.is_true)
24263 return x `true`;
24264 if (this.chunks.length === 0)
24265 return x `""`;
24266 if (this.chunks.length === 1) {
24267 return this.chunks[0].type === 'Text'
24268 ? string_literal(this.chunks[0].data)
24269 : this.chunks[0].manipulate(block);
24270 }
24271 let expression = this.chunks
24272 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : chunk.manipulate(block))
24273 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
24274 if (this.chunks[0].type !== 'Text') {
24275 expression = x `"" + ${expression}`;
24276 }
24277 return expression;
24278 }
24279 get_static_value() {
24280 if (this.is_spread || this.dependencies.size > 0)
24281 return null;
24282 return this.is_true
24283 ? true
24284 : this.chunks[0]
24285 // method should be called only when `is_static = true`
24286 ? this.chunks[0].data
24287 : '';
24288 }
24289 should_cache() {
24290 return this.is_static
24291 ? false
24292 : this.chunks.length === 1
24293 // @ts-ignore todo: probably error
24294 ? this.chunks[0].node.type !== 'Identifier' || this.scope.names.has(this.chunks[0].node.name)
24295 : true;
24296 }
24297 }
24298
24299 // TODO this should live in a specific binding
24300 const read_only_media_attributes = new Set([
24301 'duration',
24302 'buffered',
24303 'seekable',
24304 'played',
24305 'seeking',
24306 'ended',
24307 'videoHeight',
24308 'videoWidth'
24309 ]);
24310 class Binding extends Node$1 {
24311 constructor(component, parent, scope, info) {
24312 super(component, parent, scope, info);
24313 if (info.expression.type !== 'Identifier' && info.expression.type !== 'MemberExpression') {
24314 component.error(info, {
24315 code: 'invalid-directive-value',
24316 message: 'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
24317 });
24318 }
24319 this.name = info.name;
24320 this.expression = new Expression(component, this, scope, info.expression);
24321 this.raw_expression = JSON.parse(JSON.stringify(info.expression));
24322 const { name } = get_object(this.expression.node);
24323 this.is_contextual = scope.names.has(name);
24324 // make sure we track this as a mutable ref
24325 if (scope.is_let(name)) {
24326 component.error(this, {
24327 code: 'invalid-binding',
24328 message: 'Cannot bind to a variable declared with the let: directive'
24329 });
24330 }
24331 else if (this.is_contextual) {
24332 if (scope.is_await(name)) {
24333 component.error(this, {
24334 code: 'invalid-binding',
24335 message: 'Cannot bind to a variable declared with {#await ... then} or {:catch} blocks'
24336 });
24337 }
24338 scope.dependencies_for_name.get(name).forEach(name => {
24339 const variable = component.var_lookup.get(name);
24340 if (variable) {
24341 variable.mutated = true;
24342 }
24343 });
24344 }
24345 else {
24346 const variable = component.var_lookup.get(name);
24347 if (!variable || variable.global)
24348 component.error(this.expression.node, {
24349 code: 'binding-undeclared',
24350 message: `${name} is not declared`
24351 });
24352 variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
24353 if (info.expression.type === 'Identifier' && !variable.writable)
24354 component.error(this.expression.node, {
24355 code: 'invalid-binding',
24356 message: 'Cannot bind to a variable which is not writable',
24357 });
24358 }
24359 const type = parent.get_static_attribute_value('type');
24360 this.is_readonly = (dimensions.test(this.name) ||
24361 (parent.is_media_node && parent.is_media_node() && read_only_media_attributes.has(this.name)) ||
24362 (parent.name === 'input' && type === 'file') // TODO others?
24363 );
24364 }
24365 is_readonly_media_attribute() {
24366 return read_only_media_attributes.has(this.name);
24367 }
24368 }
24369
24370 class Transition extends Node$1 {
24371 constructor(component, parent, scope, info) {
24372 super(component, parent, scope, info);
24373 component.warn_if_undefined(info.name, info, scope);
24374 this.name = info.name;
24375 component.add_reference(info.name.split('.')[0]);
24376 this.directive = info.intro && info.outro ? 'transition' : info.intro ? 'in' : 'out';
24377 this.is_local = info.modifiers.includes('local');
24378 if ((info.intro && parent.intro) || (info.outro && parent.outro)) {
24379 const parent_transition = (parent.intro || parent.outro);
24380 const message = this.directive === parent_transition.directive
24381 ? `An element can only have one '${this.directive}' directive`
24382 : `An element cannot have both ${describe(parent_transition)} directive and ${describe(this)} directive`;
24383 component.error(info, {
24384 code: `duplicate-transition`,
24385 message
24386 });
24387 }
24388 this.expression = info.expression
24389 ? new Expression(component, this, scope, info.expression, true)
24390 : null;
24391 }
24392 }
24393 function describe(transition) {
24394 return transition.directive === 'transition'
24395 ? `a 'transition'`
24396 : `an '${transition.directive}'`;
24397 }
24398
24399 class Animation extends Node$1 {
24400 constructor(component, parent, scope, info) {
24401 super(component, parent, scope, info);
24402 component.warn_if_undefined(info.name, info, scope);
24403 this.name = info.name;
24404 component.add_reference(info.name.split('.')[0]);
24405 if (parent.animation) {
24406 component.error(this, {
24407 code: `duplicate-animation`,
24408 message: `An element can only have one 'animate' directive`
24409 });
24410 }
24411 const block = parent.parent;
24412 if (!block || block.type !== 'EachBlock' || !block.key) {
24413 // TODO can we relax the 'immediate child' rule?
24414 component.error(this, {
24415 code: `invalid-animation`,
24416 message: `An element that use the animate directive must be the immediate child of a keyed each block`
24417 });
24418 }
24419 block.has_animation = true;
24420 this.expression = info.expression
24421 ? new Expression(component, this, scope, info.expression, true)
24422 : null;
24423 }
24424 }
24425
24426 class Class extends Node$1 {
24427 constructor(component, parent, scope, info) {
24428 super(component, parent, scope, info);
24429 this.name = info.name;
24430 this.expression = info.expression
24431 ? new Expression(component, this, scope, info.expression)
24432 : null;
24433 }
24434 }
24435
24436 // Whitespace inside one of these elements will not result in
24437 // a whitespace node being created in any circumstances. (This
24438 // list is almost certainly very incomplete)
24439 const elements_without_text = new Set([
24440 'audio',
24441 'datalist',
24442 'dl',
24443 'optgroup',
24444 'select',
24445 'video',
24446 ]);
24447 class Text$1 extends Node$1 {
24448 constructor(component, parent, scope, info) {
24449 super(component, parent, scope, info);
24450 this.data = info.data;
24451 this.synthetic = info.synthetic || false;
24452 }
24453 should_skip() {
24454 if (/\S/.test(this.data))
24455 return false;
24456 const parent_element = this.find_nearest(/(?:Element|InlineComponent|Head)/);
24457 if (!parent_element)
24458 return false;
24459 if (parent_element.type === 'Head')
24460 return true;
24461 if (parent_element.type === 'InlineComponent')
24462 return parent_element.children.length === 1 && this === parent_element.children[0];
24463 // svg namespace exclusions
24464 if (/svg$/.test(parent_element.namespace)) {
24465 if (this.prev && this.prev.type === "Element" && this.prev.name === "tspan")
24466 return false;
24467 }
24468 return parent_element.namespace || elements_without_text.has(parent_element.name);
24469 }
24470 }
24471
24472 const applicable = new Set(['Identifier', 'ObjectExpression', 'ArrayExpression', 'Property']);
24473 class Let extends Node$1 {
24474 constructor(component, parent, scope, info) {
24475 super(component, parent, scope, info);
24476 this.names = [];
24477 this.name = { type: 'Identifier', name: info.name };
24478 const { names } = this;
24479 if (info.expression) {
24480 this.value = info.expression;
24481 walk(info.expression, {
24482 enter(node) {
24483 if (!applicable.has(node.type)) {
24484 component.error(node, {
24485 code: 'invalid-let',
24486 message: `let directive value must be an identifier or an object/array pattern`
24487 });
24488 }
24489 if (node.type === 'Identifier') {
24490 names.push(node.name);
24491 }
24492 // slightly unfortunate hack
24493 if (node.type === 'ArrayExpression') {
24494 node.type = 'ArrayPattern';
24495 }
24496 if (node.type === 'ObjectExpression') {
24497 node.type = 'ObjectPattern';
24498 }
24499 }
24500 });
24501 }
24502 else {
24503 names.push(this.name.name);
24504 }
24505 }
24506 }
24507
24508 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)$/;
24509 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(' ');
24510 const aria_attribute_set = new Set(aria_attributes);
24511 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(' ');
24512 const aria_role_set = new Set(aria_roles);
24513 const a11y_required_attributes = {
24514 a: ['href'],
24515 area: ['alt', 'aria-label', 'aria-labelledby'],
24516 // html-has-lang
24517 html: ['lang'],
24518 // iframe-has-title
24519 iframe: ['title'],
24520 img: ['alt'],
24521 object: ['title', 'aria-label', 'aria-labelledby']
24522 };
24523 const a11y_distracting_elements = new Set([
24524 'blink',
24525 'marquee'
24526 ]);
24527 const a11y_required_content = new Set([
24528 // anchor-has-content
24529 'a',
24530 // heading-has-content
24531 'h1',
24532 'h2',
24533 'h3',
24534 'h4',
24535 'h5',
24536 'h6'
24537 ]);
24538 const a11y_no_onchange = new Set([
24539 'select',
24540 'option'
24541 ]);
24542 const invisible_elements = new Set(['meta', 'html', 'script', 'style']);
24543 const valid_modifiers = new Set([
24544 'preventDefault',
24545 'stopPropagation',
24546 'capture',
24547 'once',
24548 'passive',
24549 'self'
24550 ]);
24551 const passive_events = new Set([
24552 'wheel',
24553 'touchstart',
24554 'touchmove',
24555 'touchend',
24556 'touchcancel'
24557 ]);
24558 function get_namespace(parent, element, explicit_namespace) {
24559 const parent_element = parent.find_nearest(/^Element/);
24560 if (!parent_element) {
24561 return explicit_namespace || (svg$1.test(element.name)
24562 ? namespaces.svg
24563 : null);
24564 }
24565 if (svg$1.test(element.name.toLowerCase()))
24566 return namespaces.svg;
24567 if (parent_element.name.toLowerCase() === 'foreignobject')
24568 return null;
24569 return parent_element.namespace;
24570 }
24571 class Element$1 extends Node$1 {
24572 constructor(component, parent, scope, info) {
24573 super(component, parent, scope, info);
24574 this.attributes = [];
24575 this.actions = [];
24576 this.bindings = [];
24577 this.classes = [];
24578 this.handlers = [];
24579 this.lets = [];
24580 this.intro = null;
24581 this.outro = null;
24582 this.animation = null;
24583 this.name = info.name;
24584 this.namespace = get_namespace(parent, this, component.namespace);
24585 if (this.name === 'textarea') {
24586 if (info.children.length > 0) {
24587 const value_attribute = info.attributes.find(node => node.name === 'value');
24588 if (value_attribute) {
24589 component.error(value_attribute, {
24590 code: `textarea-duplicate-value`,
24591 message: `A <textarea> can have either a value attribute or (equivalently) child content, but not both`
24592 });
24593 }
24594 // this is an egregious hack, but it's the easiest way to get <textarea>
24595 // children treated the same way as a value attribute
24596 info.attributes.push({
24597 type: 'Attribute',
24598 name: 'value',
24599 value: info.children
24600 });
24601 info.children = [];
24602 }
24603 }
24604 if (this.name === 'option') {
24605 // Special case — treat these the same way:
24606 // <option>{foo}</option>
24607 // <option value={foo}>{foo}</option>
24608 const value_attribute = info.attributes.find(attribute => attribute.name === 'value');
24609 if (!value_attribute) {
24610 info.attributes.push({
24611 type: 'Attribute',
24612 name: 'value',
24613 value: info.children,
24614 synthetic: true
24615 });
24616 }
24617 }
24618 const has_let = info.attributes.some(node => node.type === 'Let');
24619 if (has_let) {
24620 scope = scope.child();
24621 }
24622 // Binding relies on Attribute, defer its evaluation
24623 const order = ['Binding']; // everything else is -1
24624 info.attributes.sort((a, b) => order.indexOf(a.type) - order.indexOf(b.type));
24625 info.attributes.forEach(node => {
24626 switch (node.type) {
24627 case 'Action':
24628 this.actions.push(new Action(component, this, scope, node));
24629 break;
24630 case 'Attribute':
24631 case 'Spread':
24632 // special case
24633 if (node.name === 'xmlns')
24634 this.namespace = node.value[0].data;
24635 this.attributes.push(new Attribute(component, this, scope, node));
24636 break;
24637 case 'Binding':
24638 this.bindings.push(new Binding(component, this, scope, node));
24639 break;
24640 case 'Class':
24641 this.classes.push(new Class(component, this, scope, node));
24642 break;
24643 case 'EventHandler':
24644 this.handlers.push(new EventHandler(component, this, scope, node));
24645 break;
24646 case 'Let': {
24647 const l = new Let(component, this, scope, node);
24648 this.lets.push(l);
24649 const dependencies = new Set([l.name.name]);
24650 l.names.forEach(name => {
24651 scope.add(name, dependencies, this);
24652 });
24653 break;
24654 }
24655 case 'Transition':
24656 {
24657 const transition = new Transition(component, this, scope, node);
24658 if (node.intro)
24659 this.intro = transition;
24660 if (node.outro)
24661 this.outro = transition;
24662 break;
24663 }
24664 case 'Animation':
24665 this.animation = new Animation(component, this, scope, node);
24666 break;
24667 default:
24668 throw new Error(`Not implemented: ${node.type}`);
24669 }
24670 });
24671 this.scope = scope;
24672 this.children = map_children(component, this, this.scope, info.children);
24673 this.validate();
24674 component.stylesheet.apply(this);
24675 }
24676 validate() {
24677 if (a11y_distracting_elements.has(this.name)) {
24678 // no-distracting-elements
24679 this.component.warn(this, {
24680 code: `a11y-distracting-elements`,
24681 message: `A11y: Avoid <${this.name}> elements`
24682 });
24683 }
24684 if (this.name === 'figcaption') {
24685 let { parent } = this;
24686 let is_figure_parent = false;
24687 while (parent) {
24688 if (parent.name === 'figure') {
24689 is_figure_parent = true;
24690 break;
24691 }
24692 if (parent.type === 'Element') {
24693 break;
24694 }
24695 parent = parent.parent;
24696 }
24697 if (!is_figure_parent) {
24698 this.component.warn(this, {
24699 code: `a11y-structure`,
24700 message: `A11y: <figcaption> must be an immediate child of <figure>`
24701 });
24702 }
24703 }
24704 if (this.name === 'figure') {
24705 const children = this.children.filter(node => {
24706 if (node.type === 'Comment')
24707 return false;
24708 if (node.type === 'Text')
24709 return /\S/.test(node.data);
24710 return true;
24711 });
24712 const index = children.findIndex(child => child.name === 'figcaption');
24713 if (index !== -1 && (index !== 0 && index !== children.length - 1)) {
24714 this.component.warn(children[index], {
24715 code: `a11y-structure`,
24716 message: `A11y: <figcaption> must be first or last child of <figure>`
24717 });
24718 }
24719 }
24720 this.validate_attributes();
24721 this.validate_special_cases();
24722 this.validate_bindings();
24723 this.validate_content();
24724 this.validate_event_handlers();
24725 }
24726 validate_attributes() {
24727 const { component, parent } = this;
24728 const attribute_map = new Map();
24729 this.attributes.forEach(attribute => {
24730 if (attribute.is_spread)
24731 return;
24732 const name = attribute.name.toLowerCase();
24733 // aria-props
24734 if (name.startsWith('aria-')) {
24735 if (invisible_elements.has(this.name)) {
24736 // aria-unsupported-elements
24737 component.warn(attribute, {
24738 code: `a11y-aria-attributes`,
24739 message: `A11y: <${this.name}> should not have aria-* attributes`
24740 });
24741 }
24742 const type = name.slice(5);
24743 if (!aria_attribute_set.has(type)) {
24744 const match = fuzzymatch(type, aria_attributes);
24745 let message = `A11y: Unknown aria attribute 'aria-${type}'`;
24746 if (match)
24747 message += ` (did you mean '${match}'?)`;
24748 component.warn(attribute, {
24749 code: `a11y-unknown-aria-attribute`,
24750 message
24751 });
24752 }
24753 if (name === 'aria-hidden' && /^h[1-6]$/.test(this.name)) {
24754 component.warn(attribute, {
24755 code: `a11y-hidden`,
24756 message: `A11y: <${this.name}> element should not be hidden`
24757 });
24758 }
24759 }
24760 // aria-role
24761 if (name === 'role') {
24762 if (invisible_elements.has(this.name)) {
24763 // aria-unsupported-elements
24764 component.warn(attribute, {
24765 code: `a11y-misplaced-role`,
24766 message: `A11y: <${this.name}> should not have role attribute`
24767 });
24768 }
24769 const value = attribute.get_static_value();
24770 // @ts-ignore
24771 if (value && !aria_role_set.has(value)) {
24772 // @ts-ignore
24773 const match = fuzzymatch(value, aria_roles);
24774 let message = `A11y: Unknown role '${value}'`;
24775 if (match)
24776 message += ` (did you mean '${match}'?)`;
24777 component.warn(attribute, {
24778 code: `a11y-unknown-role`,
24779 message
24780 });
24781 }
24782 }
24783 // no-access-key
24784 if (name === 'accesskey') {
24785 component.warn(attribute, {
24786 code: `a11y-accesskey`,
24787 message: `A11y: Avoid using accesskey`
24788 });
24789 }
24790 // no-autofocus
24791 if (name === 'autofocus') {
24792 component.warn(attribute, {
24793 code: `a11y-autofocus`,
24794 message: `A11y: Avoid using autofocus`
24795 });
24796 }
24797 // scope
24798 if (name === 'scope' && this.name !== 'th') {
24799 component.warn(attribute, {
24800 code: `a11y-misplaced-scope`,
24801 message: `A11y: The scope attribute should only be used with <th> elements`
24802 });
24803 }
24804 // tabindex-no-positive
24805 if (name === 'tabindex') {
24806 const value = attribute.get_static_value();
24807 // @ts-ignore todo is tabindex=true correct case?
24808 if (!isNaN(value) && +value > 0) {
24809 component.warn(attribute, {
24810 code: `a11y-positive-tabindex`,
24811 message: `A11y: avoid tabindex values above zero`
24812 });
24813 }
24814 }
24815 if (/(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/.test(name)) {
24816 component.error(attribute, {
24817 code: `illegal-attribute`,
24818 message: `'${name}' is not a valid attribute name`,
24819 });
24820 }
24821 if (name === 'slot') {
24822 if (!attribute.is_static) {
24823 component.error(attribute, {
24824 code: `invalid-slot-attribute`,
24825 message: `slot attribute cannot have a dynamic value`
24826 });
24827 }
24828 if (component.slot_outlets.has(name)) {
24829 component.error(attribute, {
24830 code: `duplicate-slot-attribute`,
24831 message: `Duplicate '${name}' slot`
24832 });
24833 component.slot_outlets.add(name);
24834 }
24835 if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
24836 component.error(attribute, {
24837 code: `invalid-slotted-content`,
24838 message: `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`,
24839 });
24840 }
24841 }
24842 if (name === 'is') {
24843 component.warn(attribute, {
24844 code: 'avoid-is',
24845 message: `The 'is' attribute is not supported cross-browser and should be avoided`
24846 });
24847 }
24848 attribute_map.set(attribute.name, attribute);
24849 });
24850 }
24851 validate_special_cases() {
24852 const { component, attributes, handlers } = this;
24853 const attribute_map = new Map();
24854 const handlers_map = new Map();
24855 attributes.forEach(attribute => (attribute_map.set(attribute.name, attribute)));
24856 handlers.forEach(handler => (handlers_map.set(handler.name, handler)));
24857 if (this.name === 'a') {
24858 const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
24859 const id_attribute = attribute_map.get('id');
24860 const name_attribute = attribute_map.get('name');
24861 if (href_attribute) {
24862 const href_value = href_attribute.get_static_value();
24863 if (href_value === '' || href_value === '#' || /^\W*javascript:/i.test(href_value)) {
24864 component.warn(href_attribute, {
24865 code: `a11y-invalid-attribute`,
24866 message: `A11y: '${href_value}' is not a valid ${href_attribute.name} attribute`
24867 });
24868 }
24869 }
24870 else {
24871 const id_attribute_valid = id_attribute && id_attribute.get_static_value() !== '';
24872 const name_attribute_valid = name_attribute && name_attribute.get_static_value() !== '';
24873 if (!id_attribute_valid && !name_attribute_valid) {
24874 component.warn(this, {
24875 code: `a11y-missing-attribute`,
24876 message: `A11y: <a> element should have an href attribute`
24877 });
24878 }
24879 }
24880 }
24881 else {
24882 const required_attributes = a11y_required_attributes[this.name];
24883 if (required_attributes) {
24884 const has_attribute = required_attributes.some(name => attribute_map.has(name));
24885 if (!has_attribute) {
24886 should_have_attribute(this, required_attributes);
24887 }
24888 }
24889 }
24890 if (this.name === 'input') {
24891 const type = attribute_map.get('type');
24892 if (type && type.get_static_value() === 'image') {
24893 const required_attributes = ['alt', 'aria-label', 'aria-labelledby'];
24894 const has_attribute = required_attributes.some(name => attribute_map.has(name));
24895 if (!has_attribute) {
24896 should_have_attribute(this, required_attributes, 'input type="image"');
24897 }
24898 }
24899 }
24900 if (this.name === 'img') {
24901 const alt_attribute = attribute_map.get('alt');
24902 const aria_hidden_attribute = attribute_map.get('aria-hidden');
24903 const aria_hidden_exist = aria_hidden_attribute && aria_hidden_attribute.get_static_value();
24904 if (alt_attribute && !aria_hidden_exist) {
24905 const alt_value = alt_attribute.get_static_value();
24906 if (/\b(image|picture|photo)\b/i.test(alt_value)) {
24907 component.warn(this, {
24908 code: `a11y-img-redundant-alt`,
24909 message: `A11y: Screenreaders already announce <img> elements as an image.`
24910 });
24911 }
24912 }
24913 }
24914 if (a11y_no_onchange.has(this.name)) {
24915 if (handlers_map.has('change') && !handlers_map.has('blur')) {
24916 component.warn(this, {
24917 code: `a11y-no-onchange`,
24918 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.`
24919 });
24920 }
24921 }
24922 }
24923 validate_bindings() {
24924 const { component } = this;
24925 const check_type_attribute = () => {
24926 const attribute = this.attributes.find((attribute) => attribute.name === 'type');
24927 if (!attribute)
24928 return null;
24929 if (!attribute.is_static) {
24930 component.error(attribute, {
24931 code: `invalid-type`,
24932 message: `'type' attribute cannot be dynamic if input uses two-way binding`
24933 });
24934 }
24935 const value = attribute.get_static_value();
24936 if (value === true) {
24937 component.error(attribute, {
24938 code: `missing-type`,
24939 message: `'type' attribute must be specified`
24940 });
24941 }
24942 return value;
24943 };
24944 this.bindings.forEach(binding => {
24945 const { name } = binding;
24946 if (name === 'value') {
24947 if (this.name !== 'input' &&
24948 this.name !== 'textarea' &&
24949 this.name !== 'select') {
24950 component.error(binding, {
24951 code: `invalid-binding`,
24952 message: `'value' is not a valid binding on <${this.name}> elements`
24953 });
24954 }
24955 if (this.name === 'select') {
24956 const attribute = this.attributes.find((attribute) => attribute.name === 'multiple');
24957 if (attribute && !attribute.is_static) {
24958 component.error(attribute, {
24959 code: `dynamic-multiple-attribute`,
24960 message: `'multiple' attribute cannot be dynamic if select uses two-way binding`
24961 });
24962 }
24963 }
24964 else {
24965 check_type_attribute();
24966 }
24967 }
24968 else if (name === 'checked' || name === 'indeterminate') {
24969 if (this.name !== 'input') {
24970 component.error(binding, {
24971 code: `invalid-binding`,
24972 message: `'${name}' is not a valid binding on <${this.name}> elements`
24973 });
24974 }
24975 const type = check_type_attribute();
24976 if (type !== 'checkbox') {
24977 let message = `'${name}' binding can only be used with <input type="checkbox">`;
24978 if (type === 'radio')
24979 message += ` — for <input type="radio">, use 'group' binding`;
24980 component.error(binding, { code: `invalid-binding`, message });
24981 }
24982 }
24983 else if (name === 'group') {
24984 if (this.name !== 'input') {
24985 component.error(binding, {
24986 code: `invalid-binding`,
24987 message: `'group' is not a valid binding on <${this.name}> elements`
24988 });
24989 }
24990 const type = check_type_attribute();
24991 if (type !== 'checkbox' && type !== 'radio') {
24992 component.error(binding, {
24993 code: `invalid-binding`,
24994 message: `'group' binding can only be used with <input type="checkbox"> or <input type="radio">`
24995 });
24996 }
24997 }
24998 else if (name === 'files') {
24999 if (this.name !== 'input') {
25000 component.error(binding, {
25001 code: `invalid-binding`,
25002 message: `'files' is not a valid binding on <${this.name}> elements`
25003 });
25004 }
25005 const type = check_type_attribute();
25006 if (type !== 'file') {
25007 component.error(binding, {
25008 code: `invalid-binding`,
25009 message: `'files' binding can only be used with <input type="file">`
25010 });
25011 }
25012 }
25013 else if (name === 'open') {
25014 if (this.name !== 'details') {
25015 component.error(binding, {
25016 code: `invalid-binding`,
25017 message: `'${name}' binding can only be used with <details>`
25018 });
25019 }
25020 }
25021 else if (name === 'currentTime' ||
25022 name === 'duration' ||
25023 name === 'paused' ||
25024 name === 'buffered' ||
25025 name === 'seekable' ||
25026 name === 'played' ||
25027 name === 'volume' ||
25028 name === 'muted' ||
25029 name === 'playbackRate' ||
25030 name === 'seeking' ||
25031 name === 'ended') {
25032 if (this.name !== 'audio' && this.name !== 'video') {
25033 component.error(binding, {
25034 code: `invalid-binding`,
25035 message: `'${name}' binding can only be used with <audio> or <video>`
25036 });
25037 }
25038 }
25039 else if (name === 'videoHeight' ||
25040 name === 'videoWidth') {
25041 if (this.name !== 'video') {
25042 component.error(binding, {
25043 code: `invalid-binding`,
25044 message: `'${name}' binding can only be used with <video>`
25045 });
25046 }
25047 }
25048 else if (dimensions.test(name)) {
25049 if (this.name === 'svg' && (name === 'offsetWidth' || name === 'offsetHeight')) {
25050 component.error(binding, {
25051 code: 'invalid-binding',
25052 message: `'${binding.name}' is not a valid binding on <svg>. Use '${name.replace('offset', 'client')}' instead`
25053 });
25054 }
25055 else if (svg$1.test(this.name)) {
25056 component.error(binding, {
25057 code: 'invalid-binding',
25058 message: `'${binding.name}' is not a valid binding on SVG elements`
25059 });
25060 }
25061 else if (is_void(this.name)) {
25062 component.error(binding, {
25063 code: 'invalid-binding',
25064 message: `'${binding.name}' is not a valid binding on void elements like <${this.name}>. Use a wrapper element instead`
25065 });
25066 }
25067 }
25068 else if (name === 'textContent' ||
25069 name === 'innerHTML') {
25070 const contenteditable = this.attributes.find((attribute) => attribute.name === 'contenteditable');
25071 if (!contenteditable) {
25072 component.error(binding, {
25073 code: `missing-contenteditable-attribute`,
25074 message: `'contenteditable' attribute is required for textContent and innerHTML two-way bindings`
25075 });
25076 }
25077 else if (contenteditable && !contenteditable.is_static) {
25078 component.error(contenteditable, {
25079 code: `dynamic-contenteditable-attribute`,
25080 message: `'contenteditable' attribute cannot be dynamic if element uses two-way binding`
25081 });
25082 }
25083 }
25084 else if (name !== 'this') {
25085 component.error(binding, {
25086 code: `invalid-binding`,
25087 message: `'${binding.name}' is not a valid binding`
25088 });
25089 }
25090 });
25091 }
25092 validate_content() {
25093 if (!a11y_required_content.has(this.name))
25094 return;
25095 if (this.bindings
25096 .some((binding) => ['textContent', 'innerHTML'].includes(binding.name)))
25097 return;
25098 if (this.children.length === 0) {
25099 this.component.warn(this, {
25100 code: `a11y-missing-content`,
25101 message: `A11y: <${this.name}> element should have child content`
25102 });
25103 }
25104 }
25105 validate_event_handlers() {
25106 const { component } = this;
25107 this.handlers.forEach(handler => {
25108 if (handler.modifiers.has('passive') && handler.modifiers.has('preventDefault')) {
25109 component.error(handler, {
25110 code: 'invalid-event-modifier',
25111 message: `The 'passive' and 'preventDefault' modifiers cannot be used together`
25112 });
25113 }
25114 handler.modifiers.forEach(modifier => {
25115 if (!valid_modifiers.has(modifier)) {
25116 component.error(handler, {
25117 code: 'invalid-event-modifier',
25118 message: `Valid event modifiers are ${list$1(Array.from(valid_modifiers))}`
25119 });
25120 }
25121 if (modifier === 'passive') {
25122 if (passive_events.has(handler.name)) {
25123 if (handler.can_make_passive) {
25124 component.warn(handler, {
25125 code: 'redundant-event-modifier',
25126 message: `Touch event handlers that don't use the 'event' object are passive by default`
25127 });
25128 }
25129 }
25130 else {
25131 component.warn(handler, {
25132 code: 'redundant-event-modifier',
25133 message: `The passive modifier only works with wheel and touch events`
25134 });
25135 }
25136 }
25137 if (component.compile_options.legacy && (modifier === 'once' || modifier === 'passive')) {
25138 // TODO this could be supported, but it would need a few changes to
25139 // how event listeners work
25140 component.error(handler, {
25141 code: 'invalid-event-modifier',
25142 message: `The '${modifier}' modifier cannot be used in legacy mode`
25143 });
25144 }
25145 });
25146 if (passive_events.has(handler.name) && handler.can_make_passive && !handler.modifiers.has('preventDefault')) {
25147 // touch/wheel events should be passive by default
25148 handler.modifiers.add('passive');
25149 }
25150 });
25151 }
25152 is_media_node() {
25153 return this.name === 'audio' || this.name === 'video';
25154 }
25155 add_css_class() {
25156 if (this.attributes.some(attr => attr.is_spread)) {
25157 this.needs_manual_style_scoping = true;
25158 return;
25159 }
25160 const { id } = this.component.stylesheet;
25161 const class_attribute = this.attributes.find(a => a.name === 'class');
25162 if (class_attribute && !class_attribute.is_true) {
25163 if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') {
25164 class_attribute.chunks[0].data += ` ${id}`;
25165 }
25166 else {
25167 class_attribute.chunks.push(new Text$1(this.component, this, this.scope, {
25168 type: 'Text',
25169 data: ` ${id}`,
25170 synthetic: true
25171 }));
25172 }
25173 }
25174 else {
25175 this.attributes.push(new Attribute(this.component, this, this.scope, {
25176 type: 'Attribute',
25177 name: 'class',
25178 value: [{ type: 'Text', data: id, synthetic: true }]
25179 }));
25180 }
25181 }
25182 }
25183 function should_have_attribute(node, attributes, name = node.name) {
25184 const article = /^[aeiou]/.test(attributes[0]) ? 'an' : 'a';
25185 const sequence = attributes.length > 1 ?
25186 attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}` :
25187 attributes[0];
25188 node.component.warn(node, {
25189 code: `a11y-missing-attribute`,
25190 message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
25191 });
25192 }
25193 function within_custom_element(parent) {
25194 while (parent) {
25195 if (parent.type === 'InlineComponent')
25196 return false;
25197 if (parent.type === 'Element' && /-/.test(parent.name))
25198 return true;
25199 parent = parent.parent;
25200 }
25201 return false;
25202 }
25203
25204 class Head$1 extends Node$1 {
25205 constructor(component, parent, scope, info) {
25206 super(component, parent, scope, info);
25207 if (info.attributes.length) {
25208 component.error(info.attributes[0], {
25209 code: `invalid-attribute`,
25210 message: `<svelte:head> should not have any attributes or directives`
25211 });
25212 }
25213 this.children = map_children(component, parent, scope, info.children.filter(child => {
25214 return (child.type !== 'Text' || /\S/.test(child.data));
25215 }));
25216 if (this.children.length > 0) {
25217 this.id = `svelte-${hash(this.component.source.slice(this.start, this.end))}`;
25218 }
25219 }
25220 }
25221
25222 class IfBlock$1 extends AbstractBlock {
25223 constructor(component, parent, scope, info) {
25224 super(component, parent, scope, info);
25225 this.expression = new Expression(component, this, scope, info.expression);
25226 this.children = map_children(component, this, scope, info.children);
25227 this.else = info.else
25228 ? new ElseBlock(component, this, scope, info.else)
25229 : null;
25230 this.warn_if_empty_block();
25231 }
25232 }
25233
25234 class InlineComponent$1 extends Node$1 {
25235 constructor(component, parent, scope, info) {
25236 super(component, parent, scope, info);
25237 this.attributes = [];
25238 this.bindings = [];
25239 this.handlers = [];
25240 this.lets = [];
25241 if (info.name !== 'svelte:component' && info.name !== 'svelte:self') {
25242 const name = info.name.split('.')[0]; // accommodate namespaces
25243 component.warn_if_undefined(name, info, scope);
25244 component.add_reference(name);
25245 }
25246 this.name = info.name;
25247 this.expression = this.name === 'svelte:component'
25248 ? new Expression(component, this, scope, info.expression)
25249 : null;
25250 info.attributes.forEach(node => {
25251 /* eslint-disable no-fallthrough */
25252 switch (node.type) {
25253 case 'Action':
25254 component.error(node, {
25255 code: `invalid-action`,
25256 message: `Actions can only be applied to DOM elements, not components`
25257 });
25258 case 'Attribute':
25259 if (node.name === 'slot') {
25260 component.error(node, {
25261 code: `invalid-prop`,
25262 message: `'slot' is reserved for future use in named slots`
25263 });
25264 }
25265 // fallthrough
25266 case 'Spread':
25267 this.attributes.push(new Attribute(component, this, scope, node));
25268 break;
25269 case 'Binding':
25270 this.bindings.push(new Binding(component, this, scope, node));
25271 break;
25272 case 'Class':
25273 component.error(node, {
25274 code: `invalid-class`,
25275 message: `Classes can only be applied to DOM elements, not components`
25276 });
25277 case 'EventHandler':
25278 this.handlers.push(new EventHandler(component, this, scope, node));
25279 break;
25280 case 'Let':
25281 this.lets.push(new Let(component, this, scope, node));
25282 break;
25283 case 'Transition':
25284 component.error(node, {
25285 code: `invalid-transition`,
25286 message: `Transitions can only be applied to DOM elements, not components`
25287 });
25288 default:
25289 throw new Error(`Not implemented: ${node.type}`);
25290 }
25291 /* eslint-enable no-fallthrough */
25292 });
25293 if (this.lets.length > 0) {
25294 this.scope = scope.child();
25295 this.lets.forEach(l => {
25296 const dependencies = new Set([l.name.name]);
25297 l.names.forEach(name => {
25298 this.scope.add(name, dependencies, this);
25299 });
25300 });
25301 }
25302 else {
25303 this.scope = scope;
25304 }
25305 this.handlers.forEach(handler => {
25306 handler.modifiers.forEach(modifier => {
25307 if (modifier !== 'once') {
25308 component.error(handler, {
25309 code: 'invalid-event-modifier',
25310 message: `Event modifiers other than 'once' can only be used on DOM elements`
25311 });
25312 }
25313 });
25314 });
25315 this.children = map_children(component, this, this.scope, info.children);
25316 }
25317 }
25318
25319 class Tag$2 extends Node$1 {
25320 constructor(component, parent, scope, info) {
25321 super(component, parent, scope, info);
25322 this.expression = new Expression(component, this, scope, info.expression);
25323 this.should_cache = (info.expression.type !== 'Identifier' ||
25324 (this.expression.dependencies.size && scope.names.has(info.expression.name)));
25325 }
25326 }
25327
25328 class MustacheTag extends Tag$2 {
25329 }
25330
25331 class Options extends Node$1 {
25332 }
25333
25334 class RawMustacheTag extends Tag$2 {
25335 }
25336
25337 class DebugTag$1 extends Node$1 {
25338 constructor(component, parent, scope, info) {
25339 super(component, parent, scope, info);
25340 this.expressions = info.identifiers.map(node => {
25341 return new Expression(component, parent, scope, node);
25342 });
25343 }
25344 }
25345
25346 class Slot$1 extends Element$1 {
25347 constructor(component, parent, scope, info) {
25348 super(component, parent, scope, info);
25349 this.values = new Map();
25350 info.attributes.forEach(attr => {
25351 if (attr.type !== 'Attribute') {
25352 component.error(attr, {
25353 code: `invalid-slot-directive`,
25354 message: `<slot> cannot have directives`
25355 });
25356 }
25357 if (attr.name === 'name') {
25358 if (attr.value.length !== 1 || attr.value[0].type !== 'Text') {
25359 component.error(attr, {
25360 code: `dynamic-slot-name`,
25361 message: `<slot> name cannot be dynamic`
25362 });
25363 }
25364 this.slot_name = attr.value[0].data;
25365 if (this.slot_name === 'default') {
25366 component.error(attr, {
25367 code: `invalid-slot-name`,
25368 message: `default is a reserved word — it cannot be used as a slot name`
25369 });
25370 }
25371 }
25372 this.values.set(attr.name, new Attribute(component, this, scope, attr));
25373 });
25374 if (!this.slot_name)
25375 this.slot_name = 'default';
25376 if (this.slot_name === 'default') {
25377 // if this is the default slot, add our dependencies to any
25378 // other slots (which inherit our slot values) that were
25379 // previously encountered
25380 component.slots.forEach((slot) => {
25381 this.values.forEach((attribute, name) => {
25382 if (!slot.values.has(name)) {
25383 slot.values.set(name, attribute);
25384 }
25385 });
25386 });
25387 }
25388 else if (component.slots.has('default')) {
25389 // otherwise, go the other way — inherit values from
25390 // a previously encountered default slot
25391 const default_slot = component.slots.get('default');
25392 default_slot.values.forEach((attribute, name) => {
25393 if (!this.values.has(name)) {
25394 this.values.set(name, attribute);
25395 }
25396 });
25397 }
25398 component.slots.set(this.slot_name, this);
25399 }
25400 }
25401
25402 class Title$1 extends Node$1 {
25403 constructor(component, parent, scope, info) {
25404 super(component, parent, scope, info);
25405 this.children = map_children(component, parent, scope, info.children);
25406 if (info.attributes.length > 0) {
25407 component.error(info.attributes[0], {
25408 code: `illegal-attribute`,
25409 message: `<title> cannot have attributes`
25410 });
25411 }
25412 info.children.forEach(child => {
25413 if (child.type !== 'Text' && child.type !== 'MustacheTag') {
25414 component.error(child, {
25415 code: 'illegal-structure',
25416 message: `<title> can only contain text and {tags}`
25417 });
25418 }
25419 });
25420 this.should_cache = info.children.length === 1
25421 ? (info.children[0].type !== 'Identifier' ||
25422 scope.names.has(info.children[0].name))
25423 : true;
25424 }
25425 }
25426
25427 const valid_bindings = [
25428 'innerWidth',
25429 'innerHeight',
25430 'outerWidth',
25431 'outerHeight',
25432 'scrollX',
25433 'scrollY',
25434 'online'
25435 ];
25436 class Window extends Node$1 {
25437 constructor(component, parent, scope, info) {
25438 super(component, parent, scope, info);
25439 this.handlers = [];
25440 this.bindings = [];
25441 this.actions = [];
25442 info.attributes.forEach(node => {
25443 if (node.type === 'EventHandler') {
25444 this.handlers.push(new EventHandler(component, this, scope, node));
25445 }
25446 else if (node.type === 'Binding') {
25447 if (node.expression.type !== 'Identifier') {
25448 const { parts } = flatten_reference(node.expression);
25449 // TODO is this constraint necessary?
25450 component.error(node.expression, {
25451 code: `invalid-binding`,
25452 message: `Bindings on <svelte:window> must be to top-level properties, e.g. '${parts[parts.length - 1]}' rather than '${parts.join('.')}'`
25453 });
25454 }
25455 if (!~valid_bindings.indexOf(node.name)) {
25456 const match = (node.name === 'width' ? 'innerWidth' :
25457 node.name === 'height' ? 'innerHeight' :
25458 fuzzymatch(node.name, valid_bindings));
25459 const message = `'${node.name}' is not a valid binding on <svelte:window>`;
25460 if (match) {
25461 component.error(node, {
25462 code: `invalid-binding`,
25463 message: `${message} (did you mean '${match}'?)`
25464 });
25465 }
25466 else {
25467 component.error(node, {
25468 code: `invalid-binding`,
25469 message: `${message} — valid bindings are ${list$1(valid_bindings)}`
25470 });
25471 }
25472 }
25473 this.bindings.push(new Binding(component, this, scope, node));
25474 }
25475 else if (node.type === 'Action') {
25476 this.actions.push(new Action(component, this, scope, node));
25477 }
25478 });
25479 }
25480 }
25481
25482 function get_constructor(type) {
25483 switch (type) {
25484 case 'AwaitBlock': return AwaitBlock$1;
25485 case 'Body': return Body;
25486 case 'Comment': return Comment$2;
25487 case 'EachBlock': return EachBlock$1;
25488 case 'Element': return Element$1;
25489 case 'Head': return Head$1;
25490 case 'IfBlock': return IfBlock$1;
25491 case 'InlineComponent': return InlineComponent$1;
25492 case 'MustacheTag': return MustacheTag;
25493 case 'Options': return Options;
25494 case 'RawMustacheTag': return RawMustacheTag;
25495 case 'DebugTag': return DebugTag$1;
25496 case 'Slot': return Slot$1;
25497 case 'Text': return Text$1;
25498 case 'Title': return Title$1;
25499 case 'Window': return Window;
25500 default: throw new Error(`Not implemented: ${type}`);
25501 }
25502 }
25503 function map_children(component, parent, scope, children) {
25504 let last = null;
25505 let ignores = [];
25506 return children.map(child => {
25507 const constructor = get_constructor(child.type);
25508 const use_ignores = child.type !== 'Text' && child.type !== 'Comment' && ignores.length;
25509 if (use_ignores)
25510 component.push_ignores(ignores);
25511 const node = new constructor(component, parent, scope, child);
25512 if (use_ignores)
25513 component.pop_ignores(), ignores = [];
25514 if (node.type === 'Comment' && node.ignores.length) {
25515 ignores.push(...node.ignores);
25516 }
25517 if (last)
25518 last.next = node;
25519 node.prev = last;
25520 last = node;
25521 return node;
25522 });
25523 }
25524
25525 class TemplateScope {
25526 constructor(parent) {
25527 this.owners = new Map();
25528 this.parent = parent;
25529 this.names = new Set(parent ? parent.names : []);
25530 this.dependencies_for_name = new Map(parent ? parent.dependencies_for_name : []);
25531 }
25532 add(name, dependencies, owner) {
25533 this.names.add(name);
25534 this.dependencies_for_name.set(name, dependencies);
25535 this.owners.set(name, owner);
25536 return this;
25537 }
25538 child() {
25539 const child = new TemplateScope(this);
25540 return child;
25541 }
25542 is_top_level(name) {
25543 return !this.parent || !this.names.has(name) && this.parent.is_top_level(name);
25544 }
25545 get_owner(name) {
25546 return this.owners.get(name) || (this.parent && this.parent.get_owner(name));
25547 }
25548 is_let(name) {
25549 const owner = this.get_owner(name);
25550 return owner && (owner.type === 'Element' || owner.type === 'InlineComponent');
25551 }
25552 is_await(name) {
25553 const owner = this.get_owner(name);
25554 return owner && (owner.type === 'ThenBlock' || owner.type === 'CatchBlock');
25555 }
25556 }
25557
25558 class Fragment extends Node$1 {
25559 constructor(component, info) {
25560 const scope = new TemplateScope();
25561 super(component, null, scope, info);
25562 this.scope = scope;
25563 this.children = map_children(component, this, scope, info.children);
25564 }
25565 }
25566
25567 // This file is automatically generated
25568 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_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"]);
25569
25570 function is_used_as_reference(node, parent) {
25571 if (!isReference(node, parent)) {
25572 return false;
25573 }
25574 if (!parent) {
25575 return true;
25576 }
25577 /* eslint-disable no-fallthrough */
25578 switch (parent.type) {
25579 // disregard the `foo` in `const foo = bar`
25580 case 'VariableDeclarator':
25581 return node !== parent.id;
25582 // disregard the `foo`, `bar` in `function foo(bar){}`
25583 case 'FunctionDeclaration':
25584 // disregard the `foo` in `import { foo } from 'foo'`
25585 case 'ImportSpecifier':
25586 // disregard the `foo` in `import foo from 'foo'`
25587 case 'ImportDefaultSpecifier':
25588 // disregard the `foo` in `import * as foo from 'foo'`
25589 case 'ImportNamespaceSpecifier':
25590 // disregard the `foo` in `export { foo }`
25591 case 'ExportSpecifier':
25592 return false;
25593 default:
25594 return true;
25595 }
25596 }
25597
25598 function check_graph_for_cycles(edges) {
25599 const graph = edges.reduce((g, edge) => {
25600 const [u, v] = edge;
25601 if (!g.has(u))
25602 g.set(u, []);
25603 if (!g.has(v))
25604 g.set(v, []);
25605 g.get(u).push(v);
25606 return g;
25607 }, new Map());
25608 const visited = new Set();
25609 const on_stack = new Set();
25610 const cycles = [];
25611 function visit(v) {
25612 visited.add(v);
25613 on_stack.add(v);
25614 graph.get(v).forEach(w => {
25615 if (!visited.has(w)) {
25616 visit(w);
25617 }
25618 else if (on_stack.has(w)) {
25619 cycles.push([...on_stack, w]);
25620 }
25621 });
25622 on_stack.delete(v);
25623 }
25624 graph.forEach((_, v) => {
25625 if (!visited.has(v)) {
25626 visit(v);
25627 }
25628 });
25629 return cycles[0];
25630 }
25631
25632 class Component {
25633 constructor(ast, source, name, compile_options, stats, warnings) {
25634 this.ignore_stack = [];
25635 this.vars = [];
25636 this.var_lookup = new Map();
25637 this.imports = [];
25638 this.hoistable_nodes = new Set();
25639 this.node_for_declaration = new Map();
25640 this.partly_hoisted = [];
25641 this.fully_hoisted = [];
25642 this.reactive_declarations = [];
25643 this.reactive_declaration_nodes = new Set();
25644 this.has_reactive_assignments = false;
25645 this.injected_reactive_declaration_vars = new Set();
25646 this.helpers = new Map();
25647 this.globals = new Map();
25648 this.indirect_dependencies = new Map();
25649 this.aliases = new Map();
25650 this.used_names = new Set();
25651 this.globally_used_names = new Set();
25652 this.slots = new Map();
25653 this.slot_outlets = new Set();
25654 this.name = { type: 'Identifier', name };
25655 this.stats = stats;
25656 this.warnings = warnings;
25657 this.ast = ast;
25658 this.source = source;
25659 this.compile_options = compile_options;
25660 // the instance JS gets mutated, so we park
25661 // a copy here for later. TODO this feels gross
25662 this.original_ast = {
25663 html: ast.html,
25664 css: ast.css,
25665 instance: ast.instance && JSON.parse(JSON.stringify(ast.instance)),
25666 module: ast.module
25667 };
25668 this.file =
25669 compile_options.filename &&
25670 (typeof process !== 'undefined'
25671 ? compile_options.filename
25672 .replace(process.cwd(), '')
25673 .replace(/^[/\\]/, '')
25674 : compile_options.filename);
25675 this.locate = getLocator(this.source, { offsetLine: 1 });
25676 // styles
25677 this.stylesheet = new Stylesheet(source, ast, compile_options.filename, compile_options.dev);
25678 this.stylesheet.validate(this);
25679 this.component_options = process_component_options(this, this.ast.html.children);
25680 this.namespace =
25681 namespaces[this.component_options.namespace] ||
25682 this.component_options.namespace;
25683 if (compile_options.customElement) {
25684 if (this.component_options.tag === undefined &&
25685 compile_options.tag === undefined) {
25686 const svelteOptions = ast.html.children.find(child => child.name === 'svelte:options') || { start: 0, end: 0 };
25687 this.warn(svelteOptions, {
25688 code: 'custom-element-no-tag',
25689 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}/>`,
25690 });
25691 }
25692 this.tag = this.component_options.tag || compile_options.tag;
25693 }
25694 else {
25695 this.tag = this.name.name;
25696 }
25697 this.walk_module_js();
25698 this.walk_instance_js_pre_template();
25699 this.fragment = new Fragment(this, ast.html);
25700 this.name = this.get_unique_name(name);
25701 this.walk_instance_js_post_template();
25702 if (!compile_options.customElement)
25703 this.stylesheet.reify();
25704 this.stylesheet.warn_on_unused_selectors(this);
25705 }
25706 add_var(variable) {
25707 this.vars.push(variable);
25708 this.var_lookup.set(variable.name, variable);
25709 }
25710 add_reference(name) {
25711 const variable = this.var_lookup.get(name);
25712 if (variable) {
25713 variable.referenced = true;
25714 }
25715 else if (is_reserved_keyword(name)) {
25716 this.add_var({
25717 name,
25718 injected: true,
25719 referenced: true,
25720 });
25721 }
25722 else if (name[0] === '$') {
25723 this.add_var({
25724 name,
25725 injected: true,
25726 referenced: true,
25727 mutated: true,
25728 writable: true,
25729 });
25730 const subscribable_name = name.slice(1);
25731 const variable = this.var_lookup.get(subscribable_name);
25732 if (variable) {
25733 variable.referenced = true;
25734 variable.subscribable = true;
25735 }
25736 }
25737 else {
25738 this.used_names.add(name);
25739 }
25740 }
25741 alias(name) {
25742 if (!this.aliases.has(name)) {
25743 this.aliases.set(name, this.get_unique_name(name));
25744 }
25745 return this.aliases.get(name);
25746 }
25747 global(name) {
25748 const alias = this.alias(name);
25749 this.globals.set(name, alias);
25750 return alias;
25751 }
25752 generate(result) {
25753 let js = null;
25754 let css = null;
25755 if (result) {
25756 const { compile_options, name } = this;
25757 const { format = 'esm' } = compile_options;
25758 const banner = `${this.file ? `${this.file} ` : ``}generated by Svelte v${'3.24.0'}`;
25759 const program = { type: 'Program', body: result.js };
25760 walk(program, {
25761 enter: (node, parent, key) => {
25762 if (node.type === 'Identifier') {
25763 if (node.name[0] === '@') {
25764 if (node.name[1] === '_') {
25765 const alias = this.global(node.name.slice(2));
25766 node.name = alias.name;
25767 }
25768 else {
25769 let name = node.name.slice(1);
25770 if (compile_options.dev) {
25771 if (internal_exports.has(`${name}_dev`)) {
25772 name += '_dev';
25773 }
25774 else if (internal_exports.has(`${name}Dev`)) {
25775 name += 'Dev';
25776 }
25777 }
25778 const alias = this.alias(name);
25779 this.helpers.set(name, alias);
25780 node.name = alias.name;
25781 }
25782 }
25783 else if (node.name[0] !== '#' && !is_valid(node.name)) {
25784 // this hack allows x`foo.${bar}` where bar could be invalid
25785 const literal = { type: 'Literal', value: node.name };
25786 if (parent.type === 'Property' && key === 'key') {
25787 parent.key = literal;
25788 }
25789 else if (parent.type === 'MemberExpression' && key === 'property') {
25790 parent.property = literal;
25791 parent.computed = true;
25792 }
25793 }
25794 }
25795 }
25796 });
25797 const referenced_globals = Array.from(this.globals, ([name, alias]) => name !== alias.name && { name, alias }).filter(Boolean);
25798 if (referenced_globals.length) {
25799 this.helpers.set('globals', this.alias('globals'));
25800 }
25801 const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({
25802 name,
25803 alias,
25804 }));
25805 create_module(program, format, name, banner, compile_options.sveltePath, imported_helpers, referenced_globals, this.imports, this.vars
25806 .filter(variable => variable.module && variable.export_name)
25807 .map(variable => ({
25808 name: variable.name,
25809 as: variable.export_name,
25810 })));
25811 css = compile_options.customElement
25812 ? { code: null, map: null }
25813 : result.css;
25814 js = print(program, {
25815 sourceMapSource: compile_options.filename
25816 });
25817 js.map.sources = [
25818 compile_options.filename ? get_relative_path(compile_options.outputFilename || '', compile_options.filename) : null
25819 ];
25820 js.map.sourcesContent = [
25821 this.source
25822 ];
25823 }
25824 return {
25825 js,
25826 css,
25827 ast: this.original_ast,
25828 warnings: this.warnings,
25829 vars: this.vars
25830 .filter(v => !v.global && !v.internal)
25831 .map(v => ({
25832 name: v.name,
25833 export_name: v.export_name || null,
25834 injected: v.injected || false,
25835 module: v.module || false,
25836 mutated: v.mutated || false,
25837 reassigned: v.reassigned || false,
25838 referenced: v.referenced || false,
25839 writable: v.writable || false,
25840 referenced_from_script: v.referenced_from_script || false,
25841 })),
25842 stats: this.stats.render(),
25843 };
25844 }
25845 get_unique_name(name, scope) {
25846 if (test)
25847 name = `${name}$`;
25848 let alias = name;
25849 for (let i = 1; reserved.has(alias) ||
25850 this.var_lookup.has(alias) ||
25851 this.used_names.has(alias) ||
25852 this.globally_used_names.has(alias) ||
25853 (scope && scope.has(alias)); alias = `${name}_${i++}`)
25854 ;
25855 this.used_names.add(alias);
25856 return { type: 'Identifier', name: alias };
25857 }
25858 get_unique_name_maker() {
25859 const local_used_names = new Set();
25860 function add(name) {
25861 local_used_names.add(name);
25862 }
25863 reserved.forEach(add);
25864 internal_exports.forEach(add);
25865 this.var_lookup.forEach((_value, key) => add(key));
25866 return (name) => {
25867 if (test)
25868 name = `${name}$`;
25869 let alias = name;
25870 for (let i = 1; this.used_names.has(alias) || local_used_names.has(alias); alias = `${name}_${i++}`)
25871 ;
25872 local_used_names.add(alias);
25873 this.globally_used_names.add(alias);
25874 return {
25875 type: 'Identifier',
25876 name: alias
25877 };
25878 };
25879 }
25880 error(pos, e) {
25881 error$1(e.message, {
25882 name: 'ValidationError',
25883 code: e.code,
25884 source: this.source,
25885 start: pos.start,
25886 end: pos.end,
25887 filename: this.compile_options.filename,
25888 });
25889 }
25890 warn(pos, warning) {
25891 if (this.ignores && this.ignores.has(warning.code)) {
25892 return;
25893 }
25894 const start = this.locate(pos.start);
25895 const end = this.locate(pos.end);
25896 const frame = get_code_frame(this.source, start.line - 1, start.column);
25897 this.warnings.push({
25898 code: warning.code,
25899 message: warning.message,
25900 frame,
25901 start,
25902 end,
25903 pos: pos.start,
25904 filename: this.compile_options.filename,
25905 toString: () => `${warning.message} (${start.line}:${start.column})\n${frame}`,
25906 });
25907 }
25908 extract_imports(node) {
25909 this.imports.push(node);
25910 }
25911 extract_exports(node) {
25912 if (node.type === 'ExportDefaultDeclaration') {
25913 this.error(node, {
25914 code: `default-export`,
25915 message: `A component cannot have a default export`,
25916 });
25917 }
25918 if (node.type === 'ExportNamedDeclaration') {
25919 if (node.source) {
25920 this.error(node, {
25921 code: `not-implemented`,
25922 message: `A component currently cannot have an export ... from`,
25923 });
25924 }
25925 if (node.declaration) {
25926 if (node.declaration.type === 'VariableDeclaration') {
25927 node.declaration.declarations.forEach(declarator => {
25928 extract_names(declarator.id).forEach(name => {
25929 const variable = this.var_lookup.get(name);
25930 variable.export_name = name;
25931 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
25932 this.warn(declarator, {
25933 code: `unused-export-let`,
25934 message: `${this.name.name} has unused export property '${name}'. If it is for external reference only, please consider using \`export const ${name}\``
25935 });
25936 }
25937 });
25938 });
25939 }
25940 else {
25941 const { name } = node.declaration.id;
25942 const variable = this.var_lookup.get(name);
25943 variable.export_name = name;
25944 }
25945 return node.declaration;
25946 }
25947 else {
25948 node.specifiers.forEach(specifier => {
25949 const variable = this.var_lookup.get(specifier.local.name);
25950 if (variable) {
25951 variable.export_name = specifier.exported.name;
25952 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
25953 this.warn(specifier, {
25954 code: `unused-export-let`,
25955 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}\``
25956 });
25957 }
25958 }
25959 });
25960 return null;
25961 }
25962 }
25963 }
25964 extract_javascript(script) {
25965 if (!script)
25966 return null;
25967 return script.content.body.filter(node => {
25968 if (!node)
25969 return false;
25970 if (this.hoistable_nodes.has(node))
25971 return false;
25972 if (this.reactive_declaration_nodes.has(node))
25973 return false;
25974 if (node.type === 'ImportDeclaration')
25975 return false;
25976 if (node.type === 'ExportDeclaration' && node.specifiers.length > 0)
25977 return false;
25978 return true;
25979 });
25980 }
25981 walk_module_js() {
25982 const component = this;
25983 const script = this.ast.module;
25984 if (!script)
25985 return;
25986 walk(script.content, {
25987 enter(node) {
25988 if (node.type === 'LabeledStatement' && node.label.name === '$') {
25989 component.warn(node, {
25990 code: 'module-script-reactive-declaration',
25991 message: '$: has no effect in a module script',
25992 });
25993 }
25994 },
25995 });
25996 const { scope, globals } = create_scopes(script.content);
25997 this.module_scope = scope;
25998 scope.declarations.forEach((node, name) => {
25999 if (name[0] === '$') {
26000 this.error(node, {
26001 code: 'illegal-declaration',
26002 message: `The $ prefix is reserved, and cannot be used for variable and import names`,
26003 });
26004 }
26005 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
26006 this.add_var({
26007 name,
26008 module: true,
26009 hoistable: true,
26010 writable
26011 });
26012 });
26013 globals.forEach((node, name) => {
26014 if (name[0] === '$') {
26015 this.error(node, {
26016 code: 'illegal-subscription',
26017 message: `Cannot reference store value inside <script context="module">`,
26018 });
26019 }
26020 else {
26021 this.add_var({
26022 name,
26023 global: true,
26024 hoistable: true
26025 });
26026 }
26027 });
26028 const { body } = script.content;
26029 let i = body.length;
26030 while (--i >= 0) {
26031 const node = body[i];
26032 if (node.type === 'ImportDeclaration') {
26033 this.extract_imports(node);
26034 body.splice(i, 1);
26035 }
26036 if (/^Export/.test(node.type)) {
26037 const replacement = this.extract_exports(node);
26038 if (replacement) {
26039 body[i] = replacement;
26040 }
26041 else {
26042 body.splice(i, 1);
26043 }
26044 }
26045 }
26046 }
26047 walk_instance_js_pre_template() {
26048 const script = this.ast.instance;
26049 if (!script)
26050 return;
26051 // inject vars for reactive declarations
26052 script.content.body.forEach(node => {
26053 if (node.type !== 'LabeledStatement')
26054 return;
26055 if (node.body.type !== 'ExpressionStatement')
26056 return;
26057 const { expression } = node.body;
26058 if (expression.type !== 'AssignmentExpression')
26059 return;
26060 if (expression.left.type === 'MemberExpression')
26061 return;
26062 extract_names(expression.left).forEach(name => {
26063 if (!this.var_lookup.has(name) && name[0] !== '$') {
26064 this.injected_reactive_declaration_vars.add(name);
26065 }
26066 });
26067 });
26068 const { scope: instance_scope, map, globals } = create_scopes(script.content);
26069 this.instance_scope = instance_scope;
26070 this.instance_scope_map = map;
26071 instance_scope.declarations.forEach((node, name) => {
26072 if (name[0] === '$') {
26073 this.error(node, {
26074 code: 'illegal-declaration',
26075 message: `The $ prefix is reserved, and cannot be used for variable and import names`,
26076 });
26077 }
26078 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
26079 this.add_var({
26080 name,
26081 initialised: instance_scope.initialised_declarations.has(name),
26082 writable
26083 });
26084 this.node_for_declaration.set(name, node);
26085 });
26086 globals.forEach((node, name) => {
26087 if (this.var_lookup.has(name))
26088 return;
26089 if (this.injected_reactive_declaration_vars.has(name)) {
26090 this.add_var({
26091 name,
26092 injected: true,
26093 writable: true,
26094 reassigned: true,
26095 initialised: true,
26096 });
26097 }
26098 else if (is_reserved_keyword(name)) {
26099 this.add_var({
26100 name,
26101 injected: true,
26102 });
26103 }
26104 else if (name[0] === '$') {
26105 if (name === '$' || name[1] === '$') {
26106 this.error(node, {
26107 code: 'illegal-global',
26108 message: `${name} is an illegal variable name`
26109 });
26110 }
26111 this.add_var({
26112 name,
26113 injected: true,
26114 mutated: true,
26115 writable: true,
26116 });
26117 this.add_reference(name.slice(1));
26118 const variable = this.var_lookup.get(name.slice(1));
26119 if (variable) {
26120 variable.subscribable = true;
26121 variable.referenced_from_script = true;
26122 }
26123 }
26124 else {
26125 this.add_var({
26126 name,
26127 global: true,
26128 hoistable: true
26129 });
26130 }
26131 });
26132 this.track_references_and_mutations();
26133 }
26134 walk_instance_js_post_template() {
26135 const script = this.ast.instance;
26136 if (!script)
26137 return;
26138 this.post_template_walk();
26139 this.hoist_instance_declarations();
26140 this.extract_reactive_declarations();
26141 }
26142 post_template_walk() {
26143 const script = this.ast.instance;
26144 if (!script)
26145 return;
26146 const component = this;
26147 const { content } = script;
26148 const { instance_scope, instance_scope_map: map } = this;
26149 let scope = instance_scope;
26150 const to_remove = [];
26151 const remove = (parent, prop, index) => {
26152 to_remove.unshift([parent, prop, index]);
26153 };
26154 let scope_updated = false;
26155 let generator_count = 0;
26156 walk(content, {
26157 enter(node, parent, prop, index) {
26158 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
26159 generator_count++;
26160 }
26161 if (map.has(node)) {
26162 scope = map.get(node);
26163 }
26164 if (node.type === 'ImportDeclaration') {
26165 component.extract_imports(node);
26166 // TODO: to use actual remove
26167 remove(parent, prop, index);
26168 return this.skip();
26169 }
26170 if (/^Export/.test(node.type)) {
26171 const replacement = component.extract_exports(node);
26172 if (replacement) {
26173 this.replace(replacement);
26174 }
26175 else {
26176 // TODO: to use actual remove
26177 remove(parent, prop, index);
26178 }
26179 return this.skip();
26180 }
26181 component.warn_on_undefined_store_value_references(node, parent, scope);
26182 },
26183 leave(node) {
26184 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
26185 generator_count--;
26186 }
26187 // do it on leave, to prevent infinite loop
26188 if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0 && generator_count <= 0) {
26189 const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout);
26190 if (to_replace_for_loop_protect) {
26191 this.replace(to_replace_for_loop_protect);
26192 scope_updated = true;
26193 }
26194 }
26195 if (map.has(node)) {
26196 scope = scope.parent;
26197 }
26198 },
26199 });
26200 for (const [parent, prop, index] of to_remove) {
26201 if (parent) {
26202 if (index !== null) {
26203 parent[prop].splice(index, 1);
26204 }
26205 else {
26206 delete parent[prop];
26207 }
26208 }
26209 }
26210 if (scope_updated) {
26211 const { scope, map } = create_scopes(script.content);
26212 this.instance_scope = scope;
26213 this.instance_scope_map = map;
26214 }
26215 }
26216 track_references_and_mutations() {
26217 const script = this.ast.instance;
26218 if (!script)
26219 return;
26220 const component = this;
26221 const { content } = script;
26222 const { instance_scope, module_scope, instance_scope_map: map } = this;
26223 let scope = instance_scope;
26224 walk(content, {
26225 enter(node, parent) {
26226 if (map.has(node)) {
26227 scope = map.get(node);
26228 }
26229 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
26230 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
26231 const names = extract_names(assignee);
26232 const deep = assignee.type === 'MemberExpression';
26233 names.forEach(name => {
26234 const scope_owner = scope.find_owner(name);
26235 if (scope_owner !== null
26236 ? scope_owner === instance_scope
26237 : module_scope && module_scope.has(name)) {
26238 const variable = component.var_lookup.get(name);
26239 variable[deep ? 'mutated' : 'reassigned'] = true;
26240 }
26241 });
26242 }
26243 if (is_used_as_reference(node, parent)) {
26244 const object = get_object(node);
26245 if (scope.find_owner(object.name) === instance_scope) {
26246 const variable = component.var_lookup.get(object.name);
26247 variable.referenced_from_script = true;
26248 }
26249 }
26250 },
26251 leave(node) {
26252 if (map.has(node)) {
26253 scope = scope.parent;
26254 }
26255 },
26256 });
26257 }
26258 warn_on_undefined_store_value_references(node, parent, scope) {
26259 if (node.type === 'LabeledStatement' &&
26260 node.label.name === '$' &&
26261 parent.type !== 'Program') {
26262 this.warn(node, {
26263 code: 'non-top-level-reactive-declaration',
26264 message: '$: has no effect outside of the top-level',
26265 });
26266 }
26267 if (isReference(node, parent)) {
26268 const object = get_object(node);
26269 const { name } = object;
26270 if (name[0] === '$') {
26271 if (!scope.has(name)) {
26272 this.warn_if_undefined(name, object, null);
26273 }
26274 if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
26275 this.error(node, {
26276 code: `contextual-store`,
26277 message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
26278 });
26279 }
26280 }
26281 }
26282 }
26283 loop_protect(node, scope, timeout) {
26284 if (node.type === 'WhileStatement' ||
26285 node.type === 'ForStatement' ||
26286 node.type === 'DoWhileStatement') {
26287 const guard = this.get_unique_name('guard', scope);
26288 this.used_names.add(guard.name);
26289 const before = b `const ${guard} = @loop_guard(${timeout})`;
26290 const inside = b `${guard}();`;
26291 // wrap expression statement with BlockStatement
26292 if (node.body.type !== 'BlockStatement') {
26293 node.body = {
26294 type: 'BlockStatement',
26295 body: [node.body],
26296 };
26297 }
26298 node.body.body.push(inside[0]);
26299 return {
26300 type: 'BlockStatement',
26301 body: [
26302 before[0],
26303 node,
26304 ],
26305 };
26306 }
26307 return null;
26308 }
26309 rewrite_props(get_insert) {
26310 if (!this.ast.instance)
26311 return;
26312 const component = this;
26313 const { instance_scope, instance_scope_map: map } = this;
26314 let scope = instance_scope;
26315 walk(this.ast.instance.content, {
26316 enter(node, parent, key, index) {
26317 if (/Function/.test(node.type)) {
26318 return this.skip();
26319 }
26320 if (map.has(node)) {
26321 scope = map.get(node);
26322 }
26323 if (node.type === 'VariableDeclaration') {
26324 if (node.kind === 'var' || scope === instance_scope) {
26325 node.declarations.forEach(declarator => {
26326 if (declarator.id.type !== 'Identifier') {
26327 const inserts = [];
26328 extract_names(declarator.id).forEach(name => {
26329 const variable = component.var_lookup.get(name);
26330 if (variable.export_name) {
26331 // TODO is this still true post-#3539?
26332 component.error(declarator, {
26333 code: 'destructured-prop',
26334 message: `Cannot declare props in destructured declaration`,
26335 });
26336 }
26337 if (variable.subscribable) {
26338 inserts.push(get_insert(variable));
26339 }
26340 });
26341 if (inserts.length) {
26342 parent[key].splice(index + 1, 0, ...inserts);
26343 }
26344 return;
26345 }
26346 const { name } = declarator.id;
26347 const variable = component.var_lookup.get(name);
26348 if (variable.export_name && variable.writable) {
26349 const insert = variable.subscribable
26350 ? get_insert(variable)
26351 : null;
26352 parent[key].splice(index + 1, 0, insert);
26353 declarator.id = {
26354 type: 'ObjectPattern',
26355 properties: [{
26356 type: 'Property',
26357 method: false,
26358 shorthand: false,
26359 computed: false,
26360 kind: 'init',
26361 key: { type: 'Identifier', name: variable.export_name },
26362 value: declarator.init
26363 ? {
26364 type: 'AssignmentPattern',
26365 left: declarator.id,
26366 right: declarator.init
26367 }
26368 : declarator.id
26369 }]
26370 };
26371 declarator.init = x `$$props`;
26372 }
26373 else if (variable.subscribable) {
26374 const insert = get_insert(variable);
26375 parent[key].splice(index + 1, 0, ...insert);
26376 }
26377 });
26378 }
26379 }
26380 },
26381 leave(node, parent, _key, index) {
26382 if (map.has(node)) {
26383 scope = scope.parent;
26384 }
26385 if (node.type === 'ExportNamedDeclaration' && node.declaration) {
26386 parent.body[index] = node.declaration;
26387 }
26388 },
26389 });
26390 }
26391 hoist_instance_declarations() {
26392 // we can safely hoist variable declarations that are
26393 // initialised to literals, and functions that don't
26394 // reference instance variables other than other
26395 // hoistable functions. TODO others?
26396 const { hoistable_nodes, var_lookup, injected_reactive_declaration_vars, imports, } = this;
26397 const top_level_function_declarations = new Map();
26398 const { body } = this.ast.instance.content;
26399 for (let i = 0; i < body.length; i += 1) {
26400 const node = body[i];
26401 if (node.type === 'VariableDeclaration') {
26402 const all_hoistable = node.declarations.every(d => {
26403 if (!d.init)
26404 return false;
26405 if (d.init.type !== 'Literal')
26406 return false;
26407 // everything except const values can be changed by e.g. svelte devtools
26408 // which means we can't hoist it
26409 if (node.kind !== 'const' && this.compile_options.dev)
26410 return false;
26411 const { name } = d.id;
26412 const v = this.var_lookup.get(name);
26413 if (v.reassigned)
26414 return false;
26415 if (v.export_name)
26416 return false;
26417 if (this.var_lookup.get(name).reassigned)
26418 return false;
26419 if (this.vars.find(variable => variable.name === name && variable.module))
26420 return false;
26421 return true;
26422 });
26423 if (all_hoistable) {
26424 node.declarations.forEach(d => {
26425 const variable = this.var_lookup.get(d.id.name);
26426 variable.hoistable = true;
26427 });
26428 hoistable_nodes.add(node);
26429 body.splice(i--, 1);
26430 this.fully_hoisted.push(node);
26431 }
26432 }
26433 if (node.type === 'ExportNamedDeclaration' &&
26434 node.declaration &&
26435 node.declaration.type === 'FunctionDeclaration') {
26436 top_level_function_declarations.set(node.declaration.id.name, node);
26437 }
26438 if (node.type === 'FunctionDeclaration') {
26439 top_level_function_declarations.set(node.id.name, node);
26440 }
26441 }
26442 const checked = new Set();
26443 const walking = new Set();
26444 const is_hoistable = fn_declaration => {
26445 if (fn_declaration.type === 'ExportNamedDeclaration') {
26446 fn_declaration = fn_declaration.declaration;
26447 }
26448 const instance_scope = this.instance_scope;
26449 let scope = this.instance_scope;
26450 const map = this.instance_scope_map;
26451 let hoistable = true;
26452 // handle cycles
26453 walking.add(fn_declaration);
26454 walk(fn_declaration, {
26455 enter(node, parent) {
26456 if (!hoistable)
26457 return this.skip();
26458 if (map.has(node)) {
26459 scope = map.get(node);
26460 }
26461 if (isReference(node, parent)) {
26462 const { name } = flatten_reference(node);
26463 const owner = scope.find_owner(name);
26464 if (injected_reactive_declaration_vars.has(name)) {
26465 hoistable = false;
26466 }
26467 else if (name[0] === '$' && !owner) {
26468 hoistable = false;
26469 }
26470 else if (owner === instance_scope) {
26471 const variable = var_lookup.get(name);
26472 if (variable.reassigned || variable.mutated)
26473 hoistable = false;
26474 if (name === fn_declaration.id.name)
26475 return;
26476 if (variable.hoistable)
26477 return;
26478 if (top_level_function_declarations.has(name)) {
26479 const other_declaration = top_level_function_declarations.get(name);
26480 if (walking.has(other_declaration)) {
26481 hoistable = false;
26482 }
26483 else if (other_declaration.type === 'ExportNamedDeclaration' &&
26484 walking.has(other_declaration.declaration)) {
26485 hoistable = false;
26486 }
26487 else if (!is_hoistable(other_declaration)) {
26488 hoistable = false;
26489 }
26490 }
26491 else {
26492 hoistable = false;
26493 }
26494 }
26495 this.skip();
26496 }
26497 },
26498 leave(node) {
26499 if (map.has(node)) {
26500 scope = scope.parent;
26501 }
26502 },
26503 });
26504 checked.add(fn_declaration);
26505 walking.delete(fn_declaration);
26506 return hoistable;
26507 };
26508 for (const [name, node] of top_level_function_declarations) {
26509 if (is_hoistable(node)) {
26510 const variable = this.var_lookup.get(name);
26511 variable.hoistable = true;
26512 hoistable_nodes.add(node);
26513 const i = body.indexOf(node);
26514 body.splice(i, 1);
26515 this.fully_hoisted.push(node);
26516 }
26517 }
26518 for (const { specifiers } of imports) {
26519 for (const specifier of specifiers) {
26520 const variable = var_lookup.get(specifier.local.name);
26521 if (!variable.mutated || variable.subscribable) {
26522 variable.hoistable = true;
26523 }
26524 }
26525 }
26526 }
26527 extract_reactive_declarations() {
26528 const component = this;
26529 const unsorted_reactive_declarations = [];
26530 this.ast.instance.content.body.forEach(node => {
26531 if (node.type === 'LabeledStatement' && node.label.name === '$') {
26532 this.reactive_declaration_nodes.add(node);
26533 const assignees = new Set();
26534 const assignee_nodes = new Set();
26535 const dependencies = new Set();
26536 let scope = this.instance_scope;
26537 const map = this.instance_scope_map;
26538 walk(node.body, {
26539 enter(node, parent) {
26540 if (map.has(node)) {
26541 scope = map.get(node);
26542 }
26543 if (node.type === 'AssignmentExpression') {
26544 const left = get_object(node.left);
26545 extract_identifiers(left).forEach(node => {
26546 assignee_nodes.add(node);
26547 assignees.add(node.name);
26548 });
26549 if (node.operator !== '=') {
26550 dependencies.add(left.name);
26551 }
26552 }
26553 else if (node.type === 'UpdateExpression') {
26554 const identifier = get_object(node.argument);
26555 assignees.add(identifier.name);
26556 }
26557 else if (isReference(node, parent)) {
26558 const identifier = get_object(node);
26559 if (!assignee_nodes.has(identifier)) {
26560 const { name } = identifier;
26561 const owner = scope.find_owner(name);
26562 const variable = component.var_lookup.get(name);
26563 if (variable)
26564 variable.is_reactive_dependency = true;
26565 const is_writable_or_mutated = variable && (variable.writable || variable.mutated);
26566 if ((!owner || owner === component.instance_scope) &&
26567 (name[0] === '$' || is_writable_or_mutated)) {
26568 dependencies.add(name);
26569 }
26570 }
26571 this.skip();
26572 }
26573 },
26574 leave(node) {
26575 if (map.has(node)) {
26576 scope = scope.parent;
26577 }
26578 },
26579 });
26580 const { expression } = node.body;
26581 const declaration = expression && expression.left;
26582 unsorted_reactive_declarations.push({
26583 assignees,
26584 dependencies,
26585 node,
26586 declaration,
26587 });
26588 }
26589 });
26590 const lookup = new Map();
26591 unsorted_reactive_declarations.forEach(declaration => {
26592 declaration.assignees.forEach(name => {
26593 if (!lookup.has(name)) {
26594 lookup.set(name, []);
26595 }
26596 // TODO warn or error if a name is assigned to in
26597 // multiple reactive declarations?
26598 lookup.get(name).push(declaration);
26599 });
26600 });
26601 const cycle = check_graph_for_cycles(unsorted_reactive_declarations.reduce((acc, declaration) => {
26602 declaration.assignees.forEach(v => {
26603 declaration.dependencies.forEach(w => {
26604 if (!declaration.assignees.has(w)) {
26605 acc.push([v, w]);
26606 }
26607 });
26608 });
26609 return acc;
26610 }, []));
26611 if (cycle && cycle.length) {
26612 const declarationList = lookup.get(cycle[0]);
26613 const declaration = declarationList[0];
26614 this.error(declaration.node, {
26615 code: 'cyclical-reactive-declaration',
26616 message: `Cyclical dependency detected: ${cycle.join(' → ')}`
26617 });
26618 }
26619 const add_declaration = declaration => {
26620 if (this.reactive_declarations.includes(declaration))
26621 return;
26622 declaration.dependencies.forEach(name => {
26623 if (declaration.assignees.has(name))
26624 return;
26625 const earlier_declarations = lookup.get(name);
26626 if (earlier_declarations)
26627 earlier_declarations.forEach(add_declaration);
26628 });
26629 this.reactive_declarations.push(declaration);
26630 };
26631 unsorted_reactive_declarations.forEach(add_declaration);
26632 }
26633 warn_if_undefined(name, node, template_scope) {
26634 if (name[0] === '$') {
26635 if (name === '$' || name[1] === '$' && !is_reserved_keyword(name)) {
26636 this.error(node, {
26637 code: 'illegal-global',
26638 message: `${name} is an illegal variable name`
26639 });
26640 }
26641 this.has_reactive_assignments = true; // TODO does this belong here?
26642 if (is_reserved_keyword(name))
26643 return;
26644 name = name.slice(1);
26645 }
26646 if (this.var_lookup.has(name) && !this.var_lookup.get(name).global)
26647 return;
26648 if (template_scope && template_scope.names.has(name))
26649 return;
26650 if (globals.has(name) && node.type !== 'InlineComponent')
26651 return;
26652 let message = `'${name}' is not defined`;
26653 if (!this.ast.instance)
26654 message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;
26655 this.warn(node, {
26656 code: 'missing-declaration',
26657 message,
26658 });
26659 }
26660 push_ignores(ignores) {
26661 this.ignores = new Set(this.ignores || []);
26662 add_to_set(this.ignores, ignores);
26663 this.ignore_stack.push(this.ignores);
26664 }
26665 pop_ignores() {
26666 this.ignore_stack.pop();
26667 this.ignores = this.ignore_stack[this.ignore_stack.length - 1];
26668 }
26669 }
26670 function process_component_options(component, nodes) {
26671 const component_options = {
26672 immutable: component.compile_options.immutable || false,
26673 accessors: 'accessors' in component.compile_options
26674 ? component.compile_options.accessors
26675 : !!component.compile_options.customElement,
26676 preserveWhitespace: !!component.compile_options.preserveWhitespace,
26677 };
26678 const node = nodes.find(node => node.name === 'svelte:options');
26679 function get_value(attribute, code, message) {
26680 const { value } = attribute;
26681 const chunk = value[0];
26682 if (!chunk)
26683 return true;
26684 if (value.length > 1) {
26685 component.error(attribute, { code, message });
26686 }
26687 if (chunk.type === 'Text')
26688 return chunk.data;
26689 if (chunk.expression.type !== 'Literal') {
26690 component.error(attribute, { code, message });
26691 }
26692 return chunk.expression.value;
26693 }
26694 if (node) {
26695 node.attributes.forEach(attribute => {
26696 if (attribute.type === 'Attribute') {
26697 const { name } = attribute;
26698 switch (name) {
26699 case 'tag': {
26700 const code = 'invalid-tag-attribute';
26701 const message = `'tag' must be a string literal`;
26702 const tag = get_value(attribute, code, message);
26703 if (typeof tag !== 'string' && tag !== null)
26704 component.error(attribute, { code, message });
26705 if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
26706 component.error(attribute, {
26707 code: `invalid-tag-property`,
26708 message: `tag name must be two or more words joined by the '-' character`,
26709 });
26710 }
26711 if (tag && !component.compile_options.customElement) {
26712 component.warn(attribute, {
26713 code: 'missing-custom-element-compile-options',
26714 message: `The 'tag' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?`
26715 });
26716 }
26717 component_options.tag = tag;
26718 break;
26719 }
26720 case 'namespace': {
26721 const code = 'invalid-namespace-attribute';
26722 const message = `The 'namespace' attribute must be a string literal representing a valid namespace`;
26723 const ns = get_value(attribute, code, message);
26724 if (typeof ns !== 'string')
26725 component.error(attribute, { code, message });
26726 if (valid_namespaces.indexOf(ns) === -1) {
26727 const match = fuzzymatch(ns, valid_namespaces);
26728 if (match) {
26729 component.error(attribute, {
26730 code: `invalid-namespace-property`,
26731 message: `Invalid namespace '${ns}' (did you mean '${match}'?)`,
26732 });
26733 }
26734 else {
26735 component.error(attribute, {
26736 code: `invalid-namespace-property`,
26737 message: `Invalid namespace '${ns}'`,
26738 });
26739 }
26740 }
26741 component_options.namespace = ns;
26742 break;
26743 }
26744 case 'accessors':
26745 case 'immutable':
26746 case 'preserveWhitespace': {
26747 const code = `invalid-${name}-value`;
26748 const message = `${name} attribute must be true or false`;
26749 const value = get_value(attribute, code, message);
26750 if (typeof value !== 'boolean')
26751 component.error(attribute, { code, message });
26752 component_options[name] = value;
26753 break;
26754 }
26755 default:
26756 component.error(attribute, {
26757 code: `invalid-options-attribute`,
26758 message: `<svelte:options> unknown attribute`,
26759 });
26760 }
26761 }
26762 else {
26763 component.error(attribute, {
26764 code: `invalid-options-attribute`,
26765 message: `<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes`,
26766 });
26767 }
26768 });
26769 }
26770 return component_options;
26771 }
26772 function get_relative_path(from, to) {
26773 const from_parts = from.split(/[/\\]/);
26774 const to_parts = to.split(/[/\\]/);
26775 from_parts.pop(); // get dirname
26776 while (from_parts[0] === to_parts[0]) {
26777 from_parts.shift();
26778 to_parts.shift();
26779 }
26780 if (from_parts.length) {
26781 let i = from_parts.length;
26782 while (i--)
26783 from_parts[i] = '..';
26784 }
26785 return from_parts.concat(to_parts).join('/');
26786 }
26787
26788 function get_name_from_filename(filename) {
26789 if (!filename)
26790 return null;
26791 const parts = filename.split(/[/\\]/).map(encodeURI);
26792 if (parts.length > 1) {
26793 const index_match = parts[parts.length - 1].match(/^index(\.\w+)/);
26794 if (index_match) {
26795 parts.pop();
26796 parts[parts.length - 1] += index_match[1];
26797 }
26798 }
26799 const base = parts.pop()
26800 .replace(/%/g, 'u')
26801 .replace(/\.[^.]+$/, "")
26802 .replace(/[^a-zA-Z_$0-9]+/g, '_')
26803 .replace(/^_/, '')
26804 .replace(/_$/, '')
26805 .replace(/^(\d)/, '_$1');
26806 if (!base) {
26807 throw new Error(`Could not derive component name from file ${filename}`);
26808 }
26809 return base[0].toUpperCase() + base.slice(1);
26810 }
26811
26812 const valid_options = [
26813 'format',
26814 'name',
26815 'filename',
26816 'generate',
26817 'outputFilename',
26818 'cssOutputFilename',
26819 'sveltePath',
26820 'dev',
26821 'accessors',
26822 'immutable',
26823 'hydratable',
26824 'legacy',
26825 'customElement',
26826 'tag',
26827 'css',
26828 'loopGuardTimeout',
26829 'preserveComments',
26830 'preserveWhitespace'
26831 ];
26832 function validate_options(options, warnings) {
26833 const { name, filename, loopGuardTimeout, dev } = options;
26834 Object.keys(options).forEach(key => {
26835 if (!valid_options.includes(key)) {
26836 const match = fuzzymatch(key, valid_options);
26837 let message = `Unrecognized option '${key}'`;
26838 if (match)
26839 message += ` (did you mean '${match}'?)`;
26840 throw new Error(message);
26841 }
26842 });
26843 if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) {
26844 throw new Error(`options.name must be a valid identifier (got '${name}')`);
26845 }
26846 if (name && /^[a-z]/.test(name)) {
26847 const message = `options.name should be capitalised`;
26848 warnings.push({
26849 code: `options-lowercase-name`,
26850 message,
26851 filename,
26852 toString: () => message,
26853 });
26854 }
26855 if (loopGuardTimeout && !dev) {
26856 const message = 'options.loopGuardTimeout is for options.dev = true only';
26857 warnings.push({
26858 code: `options-loop-guard-timeout`,
26859 message,
26860 filename,
26861 toString: () => message,
26862 });
26863 }
26864 }
26865 function compile(source, options = {}) {
26866 options = assign({ generate: 'dom', dev: false }, options);
26867 const stats = new Stats();
26868 const warnings = [];
26869 validate_options(options, warnings);
26870 stats.start('parse');
26871 const ast = parse$3(source, options);
26872 stats.stop('parse');
26873 stats.start('create component');
26874 const component = new Component(ast, source, options.name || get_name_from_filename(options.filename) || 'Component', options, stats, warnings);
26875 stats.stop('create component');
26876 const result = options.generate === false
26877 ? null
26878 : options.generate === 'ssr'
26879 ? ssr(component, options)
26880 : dom(component, options);
26881 return component.generate(result);
26882 }
26883
26884 function parse_attributes(str) {
26885 const attrs = {};
26886 str.split(/\s+/).filter(Boolean).forEach(attr => {
26887 const p = attr.indexOf('=');
26888 if (p === -1) {
26889 attrs[attr] = true;
26890 }
26891 else {
26892 attrs[attr.slice(0, p)] = `'"`.includes(attr[p + 1]) ?
26893 attr.slice(p + 2, -1) :
26894 attr.slice(p + 1);
26895 }
26896 });
26897 return attrs;
26898 }
26899 async function replace_async(str, re, func) {
26900 const replacements = [];
26901 str.replace(re, (...args) => {
26902 replacements.push(func(...args).then(res => ({
26903 offset: args[args.length - 2],
26904 length: args[0].length,
26905 replacement: res,
26906 })));
26907 return '';
26908 });
26909 let out = '';
26910 let last_end = 0;
26911 for (const { offset, length, replacement } of await Promise.all(replacements)) {
26912 out += str.slice(last_end, offset) + replacement;
26913 last_end = offset + length;
26914 }
26915 out += str.slice(last_end);
26916 return out;
26917 }
26918 async function preprocess(source, preprocessor, options) {
26919 // @ts-ignore todo: doublecheck
26920 const filename = (options && options.filename) || preprocessor.filename; // legacy
26921 const dependencies = [];
26922 const preprocessors = Array.isArray(preprocessor) ? preprocessor : [preprocessor];
26923 const markup = preprocessors.map(p => p.markup).filter(Boolean);
26924 const script = preprocessors.map(p => p.script).filter(Boolean);
26925 const style = preprocessors.map(p => p.style).filter(Boolean);
26926 for (const fn of markup) {
26927 const processed = await fn({
26928 content: source,
26929 filename
26930 });
26931 if (processed && processed.dependencies)
26932 dependencies.push(...processed.dependencies);
26933 source = processed ? processed.code : source;
26934 }
26935 for (const fn of script) {
26936 source = await replace_async(source, /<!--[^]*?-->|<script(\s[^]*?)?(?:>([^]*?)<\/script>|\/>)/gi, async (match, attributes = '', content = '') => {
26937 if (!attributes && !content) {
26938 return match;
26939 }
26940 attributes = attributes || '';
26941 const processed = await fn({
26942 content,
26943 attributes: parse_attributes(attributes),
26944 filename
26945 });
26946 if (processed && processed.dependencies)
26947 dependencies.push(...processed.dependencies);
26948 return processed ? `<script${attributes}>${processed.code}</script>` : match;
26949 });
26950 }
26951 for (const fn of style) {
26952 source = await replace_async(source, /<!--[^]*?-->|<style(\s[^]*?)?(?:>([^]*?)<\/style>|\/>)/gi, async (match, attributes = '', content = '') => {
26953 if (!attributes && !content) {
26954 return match;
26955 }
26956 const processed = await fn({
26957 content,
26958 attributes: parse_attributes(attributes),
26959 filename
26960 });
26961 if (processed && processed.dependencies)
26962 dependencies.push(...processed.dependencies);
26963 return processed ? `<style${attributes}>${processed.code}</style>` : match;
26964 });
26965 }
26966 return {
26967 // TODO return separated output, in future version where svelte.compile supports it:
26968 // style: { code: styleCode, map: styleMap },
26969 // script { code: scriptCode, map: scriptMap },
26970 // markup { code: markupCode, map: markupMap },
26971 code: source,
26972 dependencies: [...new Set(dependencies)],
26973 toString() {
26974 return source;
26975 }
26976 };
26977 }
26978
26979 const VERSION = '3.24.0';
26980
26981 exports.VERSION = VERSION;
26982 exports.compile = compile;
26983 exports.parse = parse$3;
26984 exports.preprocess = preprocess;
26985 exports.walk = walk;
26986
26987 Object.defineProperty(exports, '__esModule', { value: true });
26988
26989})));
26990//# sourceMappingURL=compiler.js.map
26991
\No newline at end of file