UNPKG

905 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-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\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\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\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-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7c6\ua7f7-\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-\uab67\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\u0b56\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\u0d82\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\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\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,477,28,11,0,9,21,155,22,13,52,76,44,33,24,27,35,30,0,12,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,0,33,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,0,161,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,270,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,754,9486,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,42710,42,4148,12,221,3,5761,15,7472,3104,541];
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,525,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,4,9,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,232,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,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,262,6,10,9,419,13,1495,6,110,6,6,9,792487,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 arrow: new TokenType("=>", beforeExpr),
229 template: new TokenType("template"),
230 invalidTemplate: new TokenType("invalidTemplate"),
231 ellipsis: new TokenType("...", beforeExpr),
232 backQuote: new TokenType("`", startsExpr),
233 dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
234
235 // Operators. These carry several kinds of properties to help the
236 // parser use them properly (the presence of these properties is
237 // what categorizes them as operators).
238 //
239 // `binop`, when present, specifies that this operator is a binary
240 // operator, and will refer to its precedence.
241 //
242 // `prefix` and `postfix` mark the operator as a prefix or postfix
243 // unary operator.
244 //
245 // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
246 // binary operators with a very low precedence, that should result
247 // in AssignmentExpression nodes.
248
249 eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
250 assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
251 incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
252 prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
253 logicalOR: binop("||", 1),
254 logicalAND: binop("&&", 2),
255 bitwiseOR: binop("|", 3),
256 bitwiseXOR: binop("^", 4),
257 bitwiseAND: binop("&", 5),
258 equality: binop("==/!=/===/!==", 6),
259 relational: binop("</>/<=/>=", 7),
260 bitShift: binop("<</>>/>>>", 8),
261 plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
262 modulo: binop("%", 10),
263 star: binop("*", 10),
264 slash: binop("/", 10),
265 starstar: new TokenType("**", {beforeExpr: true}),
266
267 // Keyword token types.
268 _break: kw("break"),
269 _case: kw("case", beforeExpr),
270 _catch: kw("catch"),
271 _continue: kw("continue"),
272 _debugger: kw("debugger"),
273 _default: kw("default", beforeExpr),
274 _do: kw("do", {isLoop: true, beforeExpr: true}),
275 _else: kw("else", beforeExpr),
276 _finally: kw("finally"),
277 _for: kw("for", {isLoop: true}),
278 _function: kw("function", startsExpr),
279 _if: kw("if"),
280 _return: kw("return", beforeExpr),
281 _switch: kw("switch"),
282 _throw: kw("throw", beforeExpr),
283 _try: kw("try"),
284 _var: kw("var"),
285 _const: kw("const"),
286 _while: kw("while", {isLoop: true}),
287 _with: kw("with"),
288 _new: kw("new", {beforeExpr: true, startsExpr: true}),
289 _this: kw("this", startsExpr),
290 _super: kw("super", startsExpr),
291 _class: kw("class", startsExpr),
292 _extends: kw("extends", beforeExpr),
293 _export: kw("export"),
294 _import: kw("import", startsExpr),
295 _null: kw("null", startsExpr),
296 _true: kw("true", startsExpr),
297 _false: kw("false", startsExpr),
298 _in: kw("in", {beforeExpr: true, binop: 7}),
299 _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
300 _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
301 _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
302 _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
303 };
304
305 // Matches a whole line break (where CRLF is considered a single
306 // line break). Used to count lines.
307
308 var lineBreak = /\r\n?|\n|\u2028|\u2029/;
309 var lineBreakG = new RegExp(lineBreak.source, "g");
310
311 function isNewLine(code, ecma2019String) {
312 return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029))
313 }
314
315 var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
316
317 var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
318
319 var ref = Object.prototype;
320 var hasOwnProperty = ref.hasOwnProperty;
321 var toString = ref.toString;
322
323 // Checks if an object has a property.
324
325 function has(obj, propName) {
326 return hasOwnProperty.call(obj, propName)
327 }
328
329 var isArray = Array.isArray || (function (obj) { return (
330 toString.call(obj) === "[object Array]"
331 ); });
332
333 function wordsRegexp(words) {
334 return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
335 }
336
337 // These are used when `options.locations` is on, for the
338 // `startLoc` and `endLoc` properties.
339
340 var Position = function Position(line, col) {
341 this.line = line;
342 this.column = col;
343 };
344
345 Position.prototype.offset = function offset (n) {
346 return new Position(this.line, this.column + n)
347 };
348
349 var SourceLocation = function SourceLocation(p, start, end) {
350 this.start = start;
351 this.end = end;
352 if (p.sourceFile !== null) { this.source = p.sourceFile; }
353 };
354
355 // The `getLineInfo` function is mostly useful when the
356 // `locations` option is off (for performance reasons) and you
357 // want to find the line/column position for a given character
358 // offset. `input` should be the code string that the offset refers
359 // into.
360
361 function getLineInfo(input, offset) {
362 for (var line = 1, cur = 0;;) {
363 lineBreakG.lastIndex = cur;
364 var match = lineBreakG.exec(input);
365 if (match && match.index < offset) {
366 ++line;
367 cur = match.index + match[0].length;
368 } else {
369 return new Position(line, offset - cur)
370 }
371 }
372 }
373
374 // A second optional argument can be given to further configure
375 // the parser process. These options are recognized:
376
377 var defaultOptions = {
378 // `ecmaVersion` indicates the ECMAScript version to parse. Must be
379 // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10
380 // (2019). This influences support for strict mode, the set of
381 // reserved words, and support for new syntax features. The default
382 // is 10.
383 ecmaVersion: 10,
384 // `sourceType` indicates the mode the code should be parsed in.
385 // Can be either `"script"` or `"module"`. This influences global
386 // strict mode and parsing of `import` and `export` declarations.
387 sourceType: "script",
388 // `onInsertedSemicolon` can be a callback that will be called
389 // when a semicolon is automatically inserted. It will be passed
390 // the position of the comma as an offset, and if `locations` is
391 // enabled, it is given the location as a `{line, column}` object
392 // as second argument.
393 onInsertedSemicolon: null,
394 // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
395 // trailing commas.
396 onTrailingComma: null,
397 // By default, reserved words are only enforced if ecmaVersion >= 5.
398 // Set `allowReserved` to a boolean value to explicitly turn this on
399 // an off. When this option has the value "never", reserved words
400 // and keywords can also not be used as property names.
401 allowReserved: null,
402 // When enabled, a return at the top level is not considered an
403 // error.
404 allowReturnOutsideFunction: false,
405 // When enabled, import/export statements are not constrained to
406 // appearing at the top of the program.
407 allowImportExportEverywhere: false,
408 // When enabled, await identifiers are allowed to appear at the top-level scope,
409 // but they are still not allowed in non-async functions.
410 allowAwaitOutsideFunction: false,
411 // When enabled, hashbang directive in the beginning of file
412 // is allowed and treated as a line comment.
413 allowHashBang: false,
414 // When `locations` is on, `loc` properties holding objects with
415 // `start` and `end` properties in `{line, column}` form (with
416 // line being 1-based and column 0-based) will be attached to the
417 // nodes.
418 locations: false,
419 // A function can be passed as `onToken` option, which will
420 // cause Acorn to call that function with object in the same
421 // format as tokens returned from `tokenizer().getToken()`. Note
422 // that you are not allowed to call the parser from the
423 // callback—that will corrupt its internal state.
424 onToken: null,
425 // A function can be passed as `onComment` option, which will
426 // cause Acorn to call that function with `(block, text, start,
427 // end)` parameters whenever a comment is skipped. `block` is a
428 // boolean indicating whether this is a block (`/* */`) comment,
429 // `text` is the content of the comment, and `start` and `end` are
430 // character offsets that denote the start and end of the comment.
431 // When the `locations` option is on, two more parameters are
432 // passed, the full `{line, column}` locations of the start and
433 // end of the comments. Note that you are not allowed to call the
434 // parser from the callback—that will corrupt its internal state.
435 onComment: null,
436 // Nodes have their start and end characters offsets recorded in
437 // `start` and `end` properties (directly on the node, rather than
438 // the `loc` object, which holds line/column data. To also add a
439 // [semi-standardized][range] `range` property holding a `[start,
440 // end]` array with the same numbers, set the `ranges` option to
441 // `true`.
442 //
443 // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
444 ranges: false,
445 // It is possible to parse multiple files into a single AST by
446 // passing the tree produced by parsing the first file as
447 // `program` option in subsequent parses. This will add the
448 // toplevel forms of the parsed file to the `Program` (top) node
449 // of an existing parse tree.
450 program: null,
451 // When `locations` is on, you can pass this to record the source
452 // file in every node's `loc` object.
453 sourceFile: null,
454 // This value, if given, is stored in every node, whether
455 // `locations` is on or off.
456 directSourceFile: null,
457 // When enabled, parenthesized expressions are represented by
458 // (non-standard) ParenthesizedExpression nodes
459 preserveParens: false
460 };
461
462 // Interpret and default an options object
463
464 function getOptions(opts) {
465 var options = {};
466
467 for (var opt in defaultOptions)
468 { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; }
469
470 if (options.ecmaVersion >= 2015)
471 { options.ecmaVersion -= 2009; }
472
473 if (options.allowReserved == null)
474 { options.allowReserved = options.ecmaVersion < 5; }
475
476 if (isArray(options.onToken)) {
477 var tokens = options.onToken;
478 options.onToken = function (token) { return tokens.push(token); };
479 }
480 if (isArray(options.onComment))
481 { options.onComment = pushComment(options, options.onComment); }
482
483 return options
484 }
485
486 function pushComment(options, array) {
487 return function(block, text, start, end, startLoc, endLoc) {
488 var comment = {
489 type: block ? "Block" : "Line",
490 value: text,
491 start: start,
492 end: end
493 };
494 if (options.locations)
495 { comment.loc = new SourceLocation(this, startLoc, endLoc); }
496 if (options.ranges)
497 { comment.range = [start, end]; }
498 array.push(comment);
499 }
500 }
501
502 // Each scope gets a bitset that may contain these flags
503 var
504 SCOPE_TOP = 1,
505 SCOPE_FUNCTION = 2,
506 SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION,
507 SCOPE_ASYNC = 4,
508 SCOPE_GENERATOR = 8,
509 SCOPE_ARROW = 16,
510 SCOPE_SIMPLE_CATCH = 32,
511 SCOPE_SUPER = 64,
512 SCOPE_DIRECT_SUPER = 128;
513
514 function functionFlags(async, generator) {
515 return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0)
516 }
517
518 // Used in checkLVal and declareName to determine the type of a binding
519 var
520 BIND_NONE = 0, // Not a binding
521 BIND_VAR = 1, // Var-style binding
522 BIND_LEXICAL = 2, // Let- or const-style binding
523 BIND_FUNCTION = 3, // Function declaration
524 BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding
525 BIND_OUTSIDE = 5; // Special case for function names as bound inside the function
526
527 var Parser = function Parser(options, input, startPos) {
528 this.options = options = getOptions(options);
529 this.sourceFile = options.sourceFile;
530 this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]);
531 var reserved = "";
532 if (options.allowReserved !== true) {
533 for (var v = options.ecmaVersion;; v--)
534 { if (reserved = reservedWords[v]) { break } }
535 if (options.sourceType === "module") { reserved += " await"; }
536 }
537 this.reservedWords = wordsRegexp(reserved);
538 var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
539 this.reservedWordsStrict = wordsRegexp(reservedStrict);
540 this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind);
541 this.input = String(input);
542
543 // Used to signal to callers of `readWord1` whether the word
544 // contained any escape sequences. This is needed because words with
545 // escape sequences must not be interpreted as keywords.
546 this.containsEsc = false;
547
548 // Set up token state
549
550 // The current position of the tokenizer in the input.
551 if (startPos) {
552 this.pos = startPos;
553 this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
554 this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
555 } else {
556 this.pos = this.lineStart = 0;
557 this.curLine = 1;
558 }
559
560 // Properties of the current token:
561 // Its type
562 this.type = types.eof;
563 // For tokens that include more information than their type, the value
564 this.value = null;
565 // Its start and end offset
566 this.start = this.end = this.pos;
567 // And, if locations are used, the {line, column} object
568 // corresponding to those offsets
569 this.startLoc = this.endLoc = this.curPosition();
570
571 // Position information for the previous token
572 this.lastTokEndLoc = this.lastTokStartLoc = null;
573 this.lastTokStart = this.lastTokEnd = this.pos;
574
575 // The context stack is used to superficially track syntactic
576 // context to predict whether a regular expression is allowed in a
577 // given position.
578 this.context = this.initialContext();
579 this.exprAllowed = true;
580
581 // Figure out if it's a module code.
582 this.inModule = options.sourceType === "module";
583 this.strict = this.inModule || this.strictDirective(this.pos);
584
585 // Used to signify the start of a potential arrow function
586 this.potentialArrowAt = -1;
587
588 // Positions to delayed-check that yield/await does not exist in default parameters.
589 this.yieldPos = this.awaitPos = this.awaitIdentPos = 0;
590 // Labels in scope.
591 this.labels = [];
592 // Thus-far undefined exports.
593 this.undefinedExports = {};
594
595 // If enabled, skip leading hashbang line.
596 if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
597 { this.skipLineComment(2); }
598
599 // Scope tracking for duplicate variable names (see scope.js)
600 this.scopeStack = [];
601 this.enterScope(SCOPE_TOP);
602
603 // For RegExp validation
604 this.regexpState = null;
605 };
606
607 var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true } };
608
609 Parser.prototype.parse = function parse () {
610 var node = this.options.program || this.startNode();
611 this.nextToken();
612 return this.parseTopLevel(node)
613 };
614
615 prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 };
616 prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 };
617 prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 };
618 prototypeAccessors.allowSuper.get = function () { return (this.currentThisScope().flags & SCOPE_SUPER) > 0 };
619 prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 };
620 prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) };
621
622 // Switch to a getter for 7.0.0.
623 Parser.prototype.inNonArrowFunction = function inNonArrowFunction () { return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0 };
624
625 Parser.extend = function extend () {
626 var plugins = [], len = arguments.length;
627 while ( len-- ) plugins[ len ] = arguments[ len ];
628
629 var cls = this;
630 for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
631 return cls
632 };
633
634 Parser.parse = function parse (input, options) {
635 return new this(options, input).parse()
636 };
637
638 Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) {
639 var parser = new this(options, input, pos);
640 parser.nextToken();
641 return parser.parseExpression()
642 };
643
644 Parser.tokenizer = function tokenizer (input, options) {
645 return new this(options, input)
646 };
647
648 Object.defineProperties( Parser.prototype, prototypeAccessors );
649
650 var pp = Parser.prototype;
651
652 // ## Parser utilities
653
654 var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)")/;
655 pp.strictDirective = function(start) {
656 for (;;) {
657 // Try to find string literal.
658 skipWhiteSpace.lastIndex = start;
659 start += skipWhiteSpace.exec(this.input)[0].length;
660 var match = literal.exec(this.input.slice(start));
661 if (!match) { return false }
662 if ((match[1] || match[2]) === "use strict") { return true }
663 start += match[0].length;
664
665 // Skip semicolon, if any.
666 skipWhiteSpace.lastIndex = start;
667 start += skipWhiteSpace.exec(this.input)[0].length;
668 if (this.input[start] === ";")
669 { start++; }
670 }
671 };
672
673 // Predicate that tests whether the next token is of the given
674 // type, and if yes, consumes it as a side effect.
675
676 pp.eat = function(type) {
677 if (this.type === type) {
678 this.next();
679 return true
680 } else {
681 return false
682 }
683 };
684
685 // Tests whether parsed token is a contextual keyword.
686
687 pp.isContextual = function(name) {
688 return this.type === types.name && this.value === name && !this.containsEsc
689 };
690
691 // Consumes contextual keyword if possible.
692
693 pp.eatContextual = function(name) {
694 if (!this.isContextual(name)) { return false }
695 this.next();
696 return true
697 };
698
699 // Asserts that following token is given contextual keyword.
700
701 pp.expectContextual = function(name) {
702 if (!this.eatContextual(name)) { this.unexpected(); }
703 };
704
705 // Test whether a semicolon can be inserted at the current position.
706
707 pp.canInsertSemicolon = function() {
708 return this.type === types.eof ||
709 this.type === types.braceR ||
710 lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
711 };
712
713 pp.insertSemicolon = function() {
714 if (this.canInsertSemicolon()) {
715 if (this.options.onInsertedSemicolon)
716 { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
717 return true
718 }
719 };
720
721 // Consume a semicolon, or, failing that, see if we are allowed to
722 // pretend that there is a semicolon at this position.
723
724 pp.semicolon = function() {
725 if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); }
726 };
727
728 pp.afterTrailingComma = function(tokType, notNext) {
729 if (this.type === tokType) {
730 if (this.options.onTrailingComma)
731 { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
732 if (!notNext)
733 { this.next(); }
734 return true
735 }
736 };
737
738 // Expect a token of a given type. If found, consume it, otherwise,
739 // raise an unexpected token error.
740
741 pp.expect = function(type) {
742 this.eat(type) || this.unexpected();
743 };
744
745 // Raise an unexpected token error.
746
747 pp.unexpected = function(pos) {
748 this.raise(pos != null ? pos : this.start, "Unexpected token");
749 };
750
751 function DestructuringErrors() {
752 this.shorthandAssign =
753 this.trailingComma =
754 this.parenthesizedAssign =
755 this.parenthesizedBind =
756 this.doubleProto =
757 -1;
758 }
759
760 pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {
761 if (!refDestructuringErrors) { return }
762 if (refDestructuringErrors.trailingComma > -1)
763 { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
764 var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
765 if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); }
766 };
767
768 pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
769 if (!refDestructuringErrors) { return false }
770 var shorthandAssign = refDestructuringErrors.shorthandAssign;
771 var doubleProto = refDestructuringErrors.doubleProto;
772 if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 }
773 if (shorthandAssign >= 0)
774 { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); }
775 if (doubleProto >= 0)
776 { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); }
777 };
778
779 pp.checkYieldAwaitInDefaultParams = function() {
780 if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
781 { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
782 if (this.awaitPos)
783 { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
784 };
785
786 pp.isSimpleAssignTarget = function(expr) {
787 if (expr.type === "ParenthesizedExpression")
788 { return this.isSimpleAssignTarget(expr.expression) }
789 return expr.type === "Identifier" || expr.type === "MemberExpression"
790 };
791
792 var pp$1 = Parser.prototype;
793
794 // ### Statement parsing
795
796 // Parse a program. Initializes the parser, reads any number of
797 // statements, and wraps them in a Program node. Optionally takes a
798 // `program` argument. If present, the statements will be appended
799 // to its body instead of creating a new node.
800
801 pp$1.parseTopLevel = function(node) {
802 var exports = {};
803 if (!node.body) { node.body = []; }
804 while (this.type !== types.eof) {
805 var stmt = this.parseStatement(null, true, exports);
806 node.body.push(stmt);
807 }
808 if (this.inModule)
809 { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1)
810 {
811 var name = list[i];
812
813 this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined"));
814 } }
815 this.adaptDirectivePrologue(node.body);
816 this.next();
817 node.sourceType = this.options.sourceType;
818 return this.finishNode(node, "Program")
819 };
820
821 var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};
822
823 pp$1.isLet = function(context) {
824 if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false }
825 skipWhiteSpace.lastIndex = this.pos;
826 var skip = skipWhiteSpace.exec(this.input);
827 var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
828 // For ambiguous cases, determine if a LexicalDeclaration (or only a
829 // Statement) is allowed here. If context is not empty then only a Statement
830 // is allowed. However, `let [` is an explicit negative lookahead for
831 // ExpressionStatement, so special-case it first.
832 if (nextCh === 91) { return true } // '['
833 if (context) { return false }
834
835 if (nextCh === 123) { return true } // '{'
836 if (isIdentifierStart(nextCh, true)) {
837 var pos = next + 1;
838 while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; }
839 var ident = this.input.slice(next, pos);
840 if (!keywordRelationalOperator.test(ident)) { return true }
841 }
842 return false
843 };
844
845 // check 'async [no LineTerminator here] function'
846 // - 'async /*foo*/ function' is OK.
847 // - 'async /*\n*/ function' is invalid.
848 pp$1.isAsyncFunction = function() {
849 if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
850 { return false }
851
852 skipWhiteSpace.lastIndex = this.pos;
853 var skip = skipWhiteSpace.exec(this.input);
854 var next = this.pos + skip[0].length;
855 return !lineBreak.test(this.input.slice(this.pos, next)) &&
856 this.input.slice(next, next + 8) === "function" &&
857 (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))
858 };
859
860 // Parse a single statement.
861 //
862 // If expecting a statement and finding a slash operator, parse a
863 // regular expression literal. This is to handle cases like
864 // `if (foo) /blah/.exec(foo)`, where looking at the previous token
865 // does not help.
866
867 pp$1.parseStatement = function(context, topLevel, exports) {
868 var starttype = this.type, node = this.startNode(), kind;
869
870 if (this.isLet(context)) {
871 starttype = types._var;
872 kind = "let";
873 }
874
875 // Most types of statements are recognized by the keyword they
876 // start with. Many are trivial to parse, some require a bit of
877 // complexity.
878
879 switch (starttype) {
880 case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
881 case types._debugger: return this.parseDebuggerStatement(node)
882 case types._do: return this.parseDoStatement(node)
883 case types._for: return this.parseForStatement(node)
884 case types._function:
885 // Function as sole body of either an if statement or a labeled statement
886 // works, but not when it is part of a labeled statement that is the sole
887 // body of an if statement.
888 if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); }
889 return this.parseFunctionStatement(node, false, !context)
890 case types._class:
891 if (context) { this.unexpected(); }
892 return this.parseClass(node, true)
893 case types._if: return this.parseIfStatement(node)
894 case types._return: return this.parseReturnStatement(node)
895 case types._switch: return this.parseSwitchStatement(node)
896 case types._throw: return this.parseThrowStatement(node)
897 case types._try: return this.parseTryStatement(node)
898 case types._const: case types._var:
899 kind = kind || this.value;
900 if (context && kind !== "var") { this.unexpected(); }
901 return this.parseVarStatement(node, kind)
902 case types._while: return this.parseWhileStatement(node)
903 case types._with: return this.parseWithStatement(node)
904 case types.braceL: return this.parseBlock(true, node)
905 case types.semi: return this.parseEmptyStatement(node)
906 case types._export:
907 case types._import:
908 if (this.options.ecmaVersion > 10 && starttype === types._import) {
909 skipWhiteSpace.lastIndex = this.pos;
910 var skip = skipWhiteSpace.exec(this.input);
911 var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
912 if (nextCh === 40) // '('
913 { return this.parseExpressionStatement(node, this.parseExpression()) }
914 }
915
916 if (!this.options.allowImportExportEverywhere) {
917 if (!topLevel)
918 { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
919 if (!this.inModule)
920 { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
921 }
922 return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports)
923
924 // If the statement does not start with a statement keyword or a
925 // brace, it's an ExpressionStatement or LabeledStatement. We
926 // simply start parsing an expression, and afterwards, if the
927 // next token is a colon and the expression was a simple
928 // Identifier node, we switch to interpreting it as a label.
929 default:
930 if (this.isAsyncFunction()) {
931 if (context) { this.unexpected(); }
932 this.next();
933 return this.parseFunctionStatement(node, true, !context)
934 }
935
936 var maybeName = this.value, expr = this.parseExpression();
937 if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon))
938 { return this.parseLabeledStatement(node, maybeName, expr, context) }
939 else { return this.parseExpressionStatement(node, expr) }
940 }
941 };
942
943 pp$1.parseBreakContinueStatement = function(node, keyword) {
944 var isBreak = keyword === "break";
945 this.next();
946 if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; }
947 else if (this.type !== types.name) { this.unexpected(); }
948 else {
949 node.label = this.parseIdent();
950 this.semicolon();
951 }
952
953 // Verify that there is an actual destination to break or
954 // continue to.
955 var i = 0;
956 for (; i < this.labels.length; ++i) {
957 var lab = this.labels[i];
958 if (node.label == null || lab.name === node.label.name) {
959 if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
960 if (node.label && isBreak) { break }
961 }
962 }
963 if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
964 return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
965 };
966
967 pp$1.parseDebuggerStatement = function(node) {
968 this.next();
969 this.semicolon();
970 return this.finishNode(node, "DebuggerStatement")
971 };
972
973 pp$1.parseDoStatement = function(node) {
974 this.next();
975 this.labels.push(loopLabel);
976 node.body = this.parseStatement("do");
977 this.labels.pop();
978 this.expect(types._while);
979 node.test = this.parseParenExpression();
980 if (this.options.ecmaVersion >= 6)
981 { this.eat(types.semi); }
982 else
983 { this.semicolon(); }
984 return this.finishNode(node, "DoWhileStatement")
985 };
986
987 // Disambiguating between a `for` and a `for`/`in` or `for`/`of`
988 // loop is non-trivial. Basically, we have to parse the init `var`
989 // statement or expression, disallowing the `in` operator (see
990 // the second parameter to `parseExpression`), and then check
991 // whether the next token is `in` or `of`. When there is no init
992 // part (semicolon immediately after the opening parenthesis), it
993 // is a regular `for` loop.
994
995 pp$1.parseForStatement = function(node) {
996 this.next();
997 var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1;
998 this.labels.push(loopLabel);
999 this.enterScope(0);
1000 this.expect(types.parenL);
1001 if (this.type === types.semi) {
1002 if (awaitAt > -1) { this.unexpected(awaitAt); }
1003 return this.parseFor(node, null)
1004 }
1005 var isLet = this.isLet();
1006 if (this.type === types._var || this.type === types._const || isLet) {
1007 var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
1008 this.next();
1009 this.parseVar(init$1, true, kind);
1010 this.finishNode(init$1, "VariableDeclaration");
1011 if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1) {
1012 if (this.options.ecmaVersion >= 9) {
1013 if (this.type === types._in) {
1014 if (awaitAt > -1) { this.unexpected(awaitAt); }
1015 } else { node.await = awaitAt > -1; }
1016 }
1017 return this.parseForIn(node, init$1)
1018 }
1019 if (awaitAt > -1) { this.unexpected(awaitAt); }
1020 return this.parseFor(node, init$1)
1021 }
1022 var refDestructuringErrors = new DestructuringErrors;
1023 var init = this.parseExpression(true, refDestructuringErrors);
1024 if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
1025 if (this.options.ecmaVersion >= 9) {
1026 if (this.type === types._in) {
1027 if (awaitAt > -1) { this.unexpected(awaitAt); }
1028 } else { node.await = awaitAt > -1; }
1029 }
1030 this.toAssignable(init, false, refDestructuringErrors);
1031 this.checkLVal(init);
1032 return this.parseForIn(node, init)
1033 } else {
1034 this.checkExpressionErrors(refDestructuringErrors, true);
1035 }
1036 if (awaitAt > -1) { this.unexpected(awaitAt); }
1037 return this.parseFor(node, init)
1038 };
1039
1040 pp$1.parseFunctionStatement = function(node, isAsync, declarationPosition) {
1041 this.next();
1042 return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync)
1043 };
1044
1045 pp$1.parseIfStatement = function(node) {
1046 this.next();
1047 node.test = this.parseParenExpression();
1048 // allow function declarations in branches, but only in non-strict mode
1049 node.consequent = this.parseStatement("if");
1050 node.alternate = this.eat(types._else) ? this.parseStatement("if") : null;
1051 return this.finishNode(node, "IfStatement")
1052 };
1053
1054 pp$1.parseReturnStatement = function(node) {
1055 if (!this.inFunction && !this.options.allowReturnOutsideFunction)
1056 { this.raise(this.start, "'return' outside of function"); }
1057 this.next();
1058
1059 // In `return` (and `break`/`continue`), the keywords with
1060 // optional arguments, we eagerly look for a semicolon or the
1061 // possibility to insert one.
1062
1063 if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; }
1064 else { node.argument = this.parseExpression(); this.semicolon(); }
1065 return this.finishNode(node, "ReturnStatement")
1066 };
1067
1068 pp$1.parseSwitchStatement = function(node) {
1069 this.next();
1070 node.discriminant = this.parseParenExpression();
1071 node.cases = [];
1072 this.expect(types.braceL);
1073 this.labels.push(switchLabel);
1074 this.enterScope(0);
1075
1076 // Statements under must be grouped (by label) in SwitchCase
1077 // nodes. `cur` is used to keep the node that we are currently
1078 // adding statements to.
1079
1080 var cur;
1081 for (var sawDefault = false; this.type !== types.braceR;) {
1082 if (this.type === types._case || this.type === types._default) {
1083 var isCase = this.type === types._case;
1084 if (cur) { this.finishNode(cur, "SwitchCase"); }
1085 node.cases.push(cur = this.startNode());
1086 cur.consequent = [];
1087 this.next();
1088 if (isCase) {
1089 cur.test = this.parseExpression();
1090 } else {
1091 if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); }
1092 sawDefault = true;
1093 cur.test = null;
1094 }
1095 this.expect(types.colon);
1096 } else {
1097 if (!cur) { this.unexpected(); }
1098 cur.consequent.push(this.parseStatement(null));
1099 }
1100 }
1101 this.exitScope();
1102 if (cur) { this.finishNode(cur, "SwitchCase"); }
1103 this.next(); // Closing brace
1104 this.labels.pop();
1105 return this.finishNode(node, "SwitchStatement")
1106 };
1107
1108 pp$1.parseThrowStatement = function(node) {
1109 this.next();
1110 if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
1111 { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
1112 node.argument = this.parseExpression();
1113 this.semicolon();
1114 return this.finishNode(node, "ThrowStatement")
1115 };
1116
1117 // Reused empty array added for node fields that are always empty.
1118
1119 var empty = [];
1120
1121 pp$1.parseTryStatement = function(node) {
1122 this.next();
1123 node.block = this.parseBlock();
1124 node.handler = null;
1125 if (this.type === types._catch) {
1126 var clause = this.startNode();
1127 this.next();
1128 if (this.eat(types.parenL)) {
1129 clause.param = this.parseBindingAtom();
1130 var simple = clause.param.type === "Identifier";
1131 this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0);
1132 this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL);
1133 this.expect(types.parenR);
1134 } else {
1135 if (this.options.ecmaVersion < 10) { this.unexpected(); }
1136 clause.param = null;
1137 this.enterScope(0);
1138 }
1139 clause.body = this.parseBlock(false);
1140 this.exitScope();
1141 node.handler = this.finishNode(clause, "CatchClause");
1142 }
1143 node.finalizer = this.eat(types._finally) ? this.parseBlock() : null;
1144 if (!node.handler && !node.finalizer)
1145 { this.raise(node.start, "Missing catch or finally clause"); }
1146 return this.finishNode(node, "TryStatement")
1147 };
1148
1149 pp$1.parseVarStatement = function(node, kind) {
1150 this.next();
1151 this.parseVar(node, false, kind);
1152 this.semicolon();
1153 return this.finishNode(node, "VariableDeclaration")
1154 };
1155
1156 pp$1.parseWhileStatement = function(node) {
1157 this.next();
1158 node.test = this.parseParenExpression();
1159 this.labels.push(loopLabel);
1160 node.body = this.parseStatement("while");
1161 this.labels.pop();
1162 return this.finishNode(node, "WhileStatement")
1163 };
1164
1165 pp$1.parseWithStatement = function(node) {
1166 if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
1167 this.next();
1168 node.object = this.parseParenExpression();
1169 node.body = this.parseStatement("with");
1170 return this.finishNode(node, "WithStatement")
1171 };
1172
1173 pp$1.parseEmptyStatement = function(node) {
1174 this.next();
1175 return this.finishNode(node, "EmptyStatement")
1176 };
1177
1178 pp$1.parseLabeledStatement = function(node, maybeName, expr, context) {
1179 for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1)
1180 {
1181 var label = list[i$1];
1182
1183 if (label.name === maybeName)
1184 { this.raise(expr.start, "Label '" + maybeName + "' is already declared");
1185 } }
1186 var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null;
1187 for (var i = this.labels.length - 1; i >= 0; i--) {
1188 var label$1 = this.labels[i];
1189 if (label$1.statementStart === node.start) {
1190 // Update information about previous labels on this node
1191 label$1.statementStart = this.start;
1192 label$1.kind = kind;
1193 } else { break }
1194 }
1195 this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
1196 node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label");
1197 this.labels.pop();
1198 node.label = expr;
1199 return this.finishNode(node, "LabeledStatement")
1200 };
1201
1202 pp$1.parseExpressionStatement = function(node, expr) {
1203 node.expression = expr;
1204 this.semicolon();
1205 return this.finishNode(node, "ExpressionStatement")
1206 };
1207
1208 // Parse a semicolon-enclosed block of statements, handling `"use
1209 // strict"` declarations when `allowStrict` is true (used for
1210 // function bodies).
1211
1212 pp$1.parseBlock = function(createNewLexicalScope, node) {
1213 if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;
1214 if ( node === void 0 ) node = this.startNode();
1215
1216 node.body = [];
1217 this.expect(types.braceL);
1218 if (createNewLexicalScope) { this.enterScope(0); }
1219 while (!this.eat(types.braceR)) {
1220 var stmt = this.parseStatement(null);
1221 node.body.push(stmt);
1222 }
1223 if (createNewLexicalScope) { this.exitScope(); }
1224 return this.finishNode(node, "BlockStatement")
1225 };
1226
1227 // Parse a regular `for` loop. The disambiguation code in
1228 // `parseStatement` will already have parsed the init statement or
1229 // expression.
1230
1231 pp$1.parseFor = function(node, init) {
1232 node.init = init;
1233 this.expect(types.semi);
1234 node.test = this.type === types.semi ? null : this.parseExpression();
1235 this.expect(types.semi);
1236 node.update = this.type === types.parenR ? null : this.parseExpression();
1237 this.expect(types.parenR);
1238 node.body = this.parseStatement("for");
1239 this.exitScope();
1240 this.labels.pop();
1241 return this.finishNode(node, "ForStatement")
1242 };
1243
1244 // Parse a `for`/`in` and `for`/`of` loop, which are almost
1245 // same from parser's perspective.
1246
1247 pp$1.parseForIn = function(node, init) {
1248 var isForIn = this.type === types._in;
1249 this.next();
1250
1251 if (
1252 init.type === "VariableDeclaration" &&
1253 init.declarations[0].init != null &&
1254 (
1255 !isForIn ||
1256 this.options.ecmaVersion < 8 ||
1257 this.strict ||
1258 init.kind !== "var" ||
1259 init.declarations[0].id.type !== "Identifier"
1260 )
1261 ) {
1262 this.raise(
1263 init.start,
1264 ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer")
1265 );
1266 } else if (init.type === "AssignmentPattern") {
1267 this.raise(init.start, "Invalid left-hand side in for-loop");
1268 }
1269 node.left = init;
1270 node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign();
1271 this.expect(types.parenR);
1272 node.body = this.parseStatement("for");
1273 this.exitScope();
1274 this.labels.pop();
1275 return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement")
1276 };
1277
1278 // Parse a list of variable declarations.
1279
1280 pp$1.parseVar = function(node, isFor, kind) {
1281 node.declarations = [];
1282 node.kind = kind;
1283 for (;;) {
1284 var decl = this.startNode();
1285 this.parseVarId(decl, kind);
1286 if (this.eat(types.eq)) {
1287 decl.init = this.parseMaybeAssign(isFor);
1288 } else if (kind === "const" && !(this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
1289 this.unexpected();
1290 } else if (decl.id.type !== "Identifier" && !(isFor && (this.type === types._in || this.isContextual("of")))) {
1291 this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value");
1292 } else {
1293 decl.init = null;
1294 }
1295 node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
1296 if (!this.eat(types.comma)) { break }
1297 }
1298 return node
1299 };
1300
1301 pp$1.parseVarId = function(decl, kind) {
1302 decl.id = this.parseBindingAtom();
1303 this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false);
1304 };
1305
1306 var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4;
1307
1308 // Parse a function declaration or literal (depending on the
1309 // `statement & FUNC_STATEMENT`).
1310
1311 // Remove `allowExpressionBody` for 7.0.0, as it is only called with false
1312 pp$1.parseFunction = function(node, statement, allowExpressionBody, isAsync) {
1313 this.initFunction(node);
1314 if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) {
1315 if (this.type === types.star && (statement & FUNC_HANGING_STATEMENT))
1316 { this.unexpected(); }
1317 node.generator = this.eat(types.star);
1318 }
1319 if (this.options.ecmaVersion >= 8)
1320 { node.async = !!isAsync; }
1321
1322 if (statement & FUNC_STATEMENT) {
1323 node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name ? null : this.parseIdent();
1324 if (node.id && !(statement & FUNC_HANGING_STATEMENT))
1325 // If it is a regular function declaration in sloppy mode, then it is
1326 // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
1327 // mode depends on properties of the current scope (see
1328 // treatFunctionsAsVar).
1329 { this.checkLVal(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); }
1330 }
1331
1332 var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
1333 this.yieldPos = 0;
1334 this.awaitPos = 0;
1335 this.awaitIdentPos = 0;
1336 this.enterScope(functionFlags(node.async, node.generator));
1337
1338 if (!(statement & FUNC_STATEMENT))
1339 { node.id = this.type === types.name ? this.parseIdent() : null; }
1340
1341 this.parseFunctionParams(node);
1342 this.parseFunctionBody(node, allowExpressionBody, false);
1343
1344 this.yieldPos = oldYieldPos;
1345 this.awaitPos = oldAwaitPos;
1346 this.awaitIdentPos = oldAwaitIdentPos;
1347 return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression")
1348 };
1349
1350 pp$1.parseFunctionParams = function(node) {
1351 this.expect(types.parenL);
1352 node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
1353 this.checkYieldAwaitInDefaultParams();
1354 };
1355
1356 // Parse a class declaration or literal (depending on the
1357 // `isStatement` parameter).
1358
1359 pp$1.parseClass = function(node, isStatement) {
1360 this.next();
1361
1362 // ecma-262 14.6 Class Definitions
1363 // A class definition is always strict mode code.
1364 var oldStrict = this.strict;
1365 this.strict = true;
1366
1367 this.parseClassId(node, isStatement);
1368 this.parseClassSuper(node);
1369 var classBody = this.startNode();
1370 var hadConstructor = false;
1371 classBody.body = [];
1372 this.expect(types.braceL);
1373 while (!this.eat(types.braceR)) {
1374 var element = this.parseClassElement(node.superClass !== null);
1375 if (element) {
1376 classBody.body.push(element);
1377 if (element.type === "MethodDefinition" && element.kind === "constructor") {
1378 if (hadConstructor) { this.raise(element.start, "Duplicate constructor in the same class"); }
1379 hadConstructor = true;
1380 }
1381 }
1382 }
1383 node.body = this.finishNode(classBody, "ClassBody");
1384 this.strict = oldStrict;
1385 return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
1386 };
1387
1388 pp$1.parseClassElement = function(constructorAllowsSuper) {
1389 var this$1 = this;
1390
1391 if (this.eat(types.semi)) { return null }
1392
1393 var method = this.startNode();
1394 var tryContextual = function (k, noLineBreak) {
1395 if ( noLineBreak === void 0 ) noLineBreak = false;
1396
1397 var start = this$1.start, startLoc = this$1.startLoc;
1398 if (!this$1.eatContextual(k)) { return false }
1399 if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true }
1400 if (method.key) { this$1.unexpected(); }
1401 method.computed = false;
1402 method.key = this$1.startNodeAt(start, startLoc);
1403 method.key.name = k;
1404 this$1.finishNode(method.key, "Identifier");
1405 return false
1406 };
1407
1408 method.kind = "method";
1409 method.static = tryContextual("static");
1410 var isGenerator = this.eat(types.star);
1411 var isAsync = false;
1412 if (!isGenerator) {
1413 if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) {
1414 isAsync = true;
1415 isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
1416 } else if (tryContextual("get")) {
1417 method.kind = "get";
1418 } else if (tryContextual("set")) {
1419 method.kind = "set";
1420 }
1421 }
1422 if (!method.key) { this.parsePropertyName(method); }
1423 var key = method.key;
1424 var allowsDirectSuper = false;
1425 if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" ||
1426 key.type === "Literal" && key.value === "constructor")) {
1427 if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); }
1428 if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); }
1429 if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); }
1430 method.kind = "constructor";
1431 allowsDirectSuper = constructorAllowsSuper;
1432 } else if (method.static && key.type === "Identifier" && key.name === "prototype") {
1433 this.raise(key.start, "Classes may not have a static property named prototype");
1434 }
1435 this.parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper);
1436 if (method.kind === "get" && method.value.params.length !== 0)
1437 { this.raiseRecoverable(method.value.start, "getter should have no params"); }
1438 if (method.kind === "set" && method.value.params.length !== 1)
1439 { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); }
1440 if (method.kind === "set" && method.value.params[0].type === "RestElement")
1441 { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); }
1442 return method
1443 };
1444
1445 pp$1.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) {
1446 method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper);
1447 return this.finishNode(method, "MethodDefinition")
1448 };
1449
1450 pp$1.parseClassId = function(node, isStatement) {
1451 if (this.type === types.name) {
1452 node.id = this.parseIdent();
1453 if (isStatement)
1454 { this.checkLVal(node.id, BIND_LEXICAL, false); }
1455 } else {
1456 if (isStatement === true)
1457 { this.unexpected(); }
1458 node.id = null;
1459 }
1460 };
1461
1462 pp$1.parseClassSuper = function(node) {
1463 node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null;
1464 };
1465
1466 // Parses module export declaration.
1467
1468 pp$1.parseExport = function(node, exports) {
1469 this.next();
1470 // export * from '...'
1471 if (this.eat(types.star)) {
1472 this.expectContextual("from");
1473 if (this.type !== types.string) { this.unexpected(); }
1474 node.source = this.parseExprAtom();
1475 this.semicolon();
1476 return this.finishNode(node, "ExportAllDeclaration")
1477 }
1478 if (this.eat(types._default)) { // export default ...
1479 this.checkExport(exports, "default", this.lastTokStart);
1480 var isAsync;
1481 if (this.type === types._function || (isAsync = this.isAsyncFunction())) {
1482 var fNode = this.startNode();
1483 this.next();
1484 if (isAsync) { this.next(); }
1485 node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync);
1486 } else if (this.type === types._class) {
1487 var cNode = this.startNode();
1488 node.declaration = this.parseClass(cNode, "nullableID");
1489 } else {
1490 node.declaration = this.parseMaybeAssign();
1491 this.semicolon();
1492 }
1493 return this.finishNode(node, "ExportDefaultDeclaration")
1494 }
1495 // export var|const|let|function|class ...
1496 if (this.shouldParseExportStatement()) {
1497 node.declaration = this.parseStatement(null);
1498 if (node.declaration.type === "VariableDeclaration")
1499 { this.checkVariableExport(exports, node.declaration.declarations); }
1500 else
1501 { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); }
1502 node.specifiers = [];
1503 node.source = null;
1504 } else { // export { x, y as z } [from '...']
1505 node.declaration = null;
1506 node.specifiers = this.parseExportSpecifiers(exports);
1507 if (this.eatContextual("from")) {
1508 if (this.type !== types.string) { this.unexpected(); }
1509 node.source = this.parseExprAtom();
1510 } else {
1511 for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
1512 // check for keywords used as local names
1513 var spec = list[i];
1514
1515 this.checkUnreserved(spec.local);
1516 // check if export is defined
1517 this.checkLocalExport(spec.local);
1518 }
1519
1520 node.source = null;
1521 }
1522 this.semicolon();
1523 }
1524 return this.finishNode(node, "ExportNamedDeclaration")
1525 };
1526
1527 pp$1.checkExport = function(exports, name, pos) {
1528 if (!exports) { return }
1529 if (has(exports, name))
1530 { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
1531 exports[name] = true;
1532 };
1533
1534 pp$1.checkPatternExport = function(exports, pat) {
1535 var type = pat.type;
1536 if (type === "Identifier")
1537 { this.checkExport(exports, pat.name, pat.start); }
1538 else if (type === "ObjectPattern")
1539 { for (var i = 0, list = pat.properties; i < list.length; i += 1)
1540 {
1541 var prop = list[i];
1542
1543 this.checkPatternExport(exports, prop);
1544 } }
1545 else if (type === "ArrayPattern")
1546 { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
1547 var elt = list$1[i$1];
1548
1549 if (elt) { this.checkPatternExport(exports, elt); }
1550 } }
1551 else if (type === "Property")
1552 { this.checkPatternExport(exports, pat.value); }
1553 else if (type === "AssignmentPattern")
1554 { this.checkPatternExport(exports, pat.left); }
1555 else if (type === "RestElement")
1556 { this.checkPatternExport(exports, pat.argument); }
1557 else if (type === "ParenthesizedExpression")
1558 { this.checkPatternExport(exports, pat.expression); }
1559 };
1560
1561 pp$1.checkVariableExport = function(exports, decls) {
1562 if (!exports) { return }
1563 for (var i = 0, list = decls; i < list.length; i += 1)
1564 {
1565 var decl = list[i];
1566
1567 this.checkPatternExport(exports, decl.id);
1568 }
1569 };
1570
1571 pp$1.shouldParseExportStatement = function() {
1572 return this.type.keyword === "var" ||
1573 this.type.keyword === "const" ||
1574 this.type.keyword === "class" ||
1575 this.type.keyword === "function" ||
1576 this.isLet() ||
1577 this.isAsyncFunction()
1578 };
1579
1580 // Parses a comma-separated list of module exports.
1581
1582 pp$1.parseExportSpecifiers = function(exports) {
1583 var nodes = [], first = true;
1584 // export { x, y as z } [from '...']
1585 this.expect(types.braceL);
1586 while (!this.eat(types.braceR)) {
1587 if (!first) {
1588 this.expect(types.comma);
1589 if (this.afterTrailingComma(types.braceR)) { break }
1590 } else { first = false; }
1591
1592 var node = this.startNode();
1593 node.local = this.parseIdent(true);
1594 node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local;
1595 this.checkExport(exports, node.exported.name, node.exported.start);
1596 nodes.push(this.finishNode(node, "ExportSpecifier"));
1597 }
1598 return nodes
1599 };
1600
1601 // Parses import declaration.
1602
1603 pp$1.parseImport = function(node) {
1604 this.next();
1605 // import '...'
1606 if (this.type === types.string) {
1607 node.specifiers = empty;
1608 node.source = this.parseExprAtom();
1609 } else {
1610 node.specifiers = this.parseImportSpecifiers();
1611 this.expectContextual("from");
1612 node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
1613 }
1614 this.semicolon();
1615 return this.finishNode(node, "ImportDeclaration")
1616 };
1617
1618 // Parses a comma-separated list of module imports.
1619
1620 pp$1.parseImportSpecifiers = function() {
1621 var nodes = [], first = true;
1622 if (this.type === types.name) {
1623 // import defaultObj, { x, y as z } from '...'
1624 var node = this.startNode();
1625 node.local = this.parseIdent();
1626 this.checkLVal(node.local, BIND_LEXICAL);
1627 nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
1628 if (!this.eat(types.comma)) { return nodes }
1629 }
1630 if (this.type === types.star) {
1631 var node$1 = this.startNode();
1632 this.next();
1633 this.expectContextual("as");
1634 node$1.local = this.parseIdent();
1635 this.checkLVal(node$1.local, BIND_LEXICAL);
1636 nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
1637 return nodes
1638 }
1639 this.expect(types.braceL);
1640 while (!this.eat(types.braceR)) {
1641 if (!first) {
1642 this.expect(types.comma);
1643 if (this.afterTrailingComma(types.braceR)) { break }
1644 } else { first = false; }
1645
1646 var node$2 = this.startNode();
1647 node$2.imported = this.parseIdent(true);
1648 if (this.eatContextual("as")) {
1649 node$2.local = this.parseIdent();
1650 } else {
1651 this.checkUnreserved(node$2.imported);
1652 node$2.local = node$2.imported;
1653 }
1654 this.checkLVal(node$2.local, BIND_LEXICAL);
1655 nodes.push(this.finishNode(node$2, "ImportSpecifier"));
1656 }
1657 return nodes
1658 };
1659
1660 // Set `ExpressionStatement#directive` property for directive prologues.
1661 pp$1.adaptDirectivePrologue = function(statements) {
1662 for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
1663 statements[i].directive = statements[i].expression.raw.slice(1, -1);
1664 }
1665 };
1666 pp$1.isDirectiveCandidate = function(statement) {
1667 return (
1668 statement.type === "ExpressionStatement" &&
1669 statement.expression.type === "Literal" &&
1670 typeof statement.expression.value === "string" &&
1671 // Reject parenthesized strings.
1672 (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
1673 )
1674 };
1675
1676 var pp$2 = Parser.prototype;
1677
1678 // Convert existing expression atom to assignable pattern
1679 // if possible.
1680
1681 pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) {
1682 if (this.options.ecmaVersion >= 6 && node) {
1683 switch (node.type) {
1684 case "Identifier":
1685 if (this.inAsync && node.name === "await")
1686 { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); }
1687 break
1688
1689 case "ObjectPattern":
1690 case "ArrayPattern":
1691 case "RestElement":
1692 break
1693
1694 case "ObjectExpression":
1695 node.type = "ObjectPattern";
1696 if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1697 for (var i = 0, list = node.properties; i < list.length; i += 1) {
1698 var prop = list[i];
1699
1700 this.toAssignable(prop, isBinding);
1701 // Early error:
1702 // AssignmentRestProperty[Yield, Await] :
1703 // `...` DestructuringAssignmentTarget[Yield, Await]
1704 //
1705 // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
1706 if (
1707 prop.type === "RestElement" &&
1708 (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")
1709 ) {
1710 this.raise(prop.argument.start, "Unexpected token");
1711 }
1712 }
1713 break
1714
1715 case "Property":
1716 // AssignmentProperty has type === "Property"
1717 if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); }
1718 this.toAssignable(node.value, isBinding);
1719 break
1720
1721 case "ArrayExpression":
1722 node.type = "ArrayPattern";
1723 if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1724 this.toAssignableList(node.elements, isBinding);
1725 break
1726
1727 case "SpreadElement":
1728 node.type = "RestElement";
1729 this.toAssignable(node.argument, isBinding);
1730 if (node.argument.type === "AssignmentPattern")
1731 { this.raise(node.argument.start, "Rest elements cannot have a default value"); }
1732 break
1733
1734 case "AssignmentExpression":
1735 if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); }
1736 node.type = "AssignmentPattern";
1737 delete node.operator;
1738 this.toAssignable(node.left, isBinding);
1739 // falls through to AssignmentPattern
1740
1741 case "AssignmentPattern":
1742 break
1743
1744 case "ParenthesizedExpression":
1745 this.toAssignable(node.expression, isBinding, refDestructuringErrors);
1746 break
1747
1748 case "MemberExpression":
1749 if (!isBinding) { break }
1750
1751 default:
1752 this.raise(node.start, "Assigning to rvalue");
1753 }
1754 } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1755 return node
1756 };
1757
1758 // Convert list of expression atoms to binding list.
1759
1760 pp$2.toAssignableList = function(exprList, isBinding) {
1761 var end = exprList.length;
1762 for (var i = 0; i < end; i++) {
1763 var elt = exprList[i];
1764 if (elt) { this.toAssignable(elt, isBinding); }
1765 }
1766 if (end) {
1767 var last = exprList[end - 1];
1768 if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
1769 { this.unexpected(last.argument.start); }
1770 }
1771 return exprList
1772 };
1773
1774 // Parses spread element.
1775
1776 pp$2.parseSpread = function(refDestructuringErrors) {
1777 var node = this.startNode();
1778 this.next();
1779 node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
1780 return this.finishNode(node, "SpreadElement")
1781 };
1782
1783 pp$2.parseRestBinding = function() {
1784 var node = this.startNode();
1785 this.next();
1786
1787 // RestElement inside of a function parameter must be an identifier
1788 if (this.options.ecmaVersion === 6 && this.type !== types.name)
1789 { this.unexpected(); }
1790
1791 node.argument = this.parseBindingAtom();
1792
1793 return this.finishNode(node, "RestElement")
1794 };
1795
1796 // Parses lvalue (assignable) atom.
1797
1798 pp$2.parseBindingAtom = function() {
1799 if (this.options.ecmaVersion >= 6) {
1800 switch (this.type) {
1801 case types.bracketL:
1802 var node = this.startNode();
1803 this.next();
1804 node.elements = this.parseBindingList(types.bracketR, true, true);
1805 return this.finishNode(node, "ArrayPattern")
1806
1807 case types.braceL:
1808 return this.parseObj(true)
1809 }
1810 }
1811 return this.parseIdent()
1812 };
1813
1814 pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
1815 var elts = [], first = true;
1816 while (!this.eat(close)) {
1817 if (first) { first = false; }
1818 else { this.expect(types.comma); }
1819 if (allowEmpty && this.type === types.comma) {
1820 elts.push(null);
1821 } else if (allowTrailingComma && this.afterTrailingComma(close)) {
1822 break
1823 } else if (this.type === types.ellipsis) {
1824 var rest = this.parseRestBinding();
1825 this.parseBindingListItem(rest);
1826 elts.push(rest);
1827 if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); }
1828 this.expect(close);
1829 break
1830 } else {
1831 var elem = this.parseMaybeDefault(this.start, this.startLoc);
1832 this.parseBindingListItem(elem);
1833 elts.push(elem);
1834 }
1835 }
1836 return elts
1837 };
1838
1839 pp$2.parseBindingListItem = function(param) {
1840 return param
1841 };
1842
1843 // Parses assignment pattern around given atom if possible.
1844
1845 pp$2.parseMaybeDefault = function(startPos, startLoc, left) {
1846 left = left || this.parseBindingAtom();
1847 if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left }
1848 var node = this.startNodeAt(startPos, startLoc);
1849 node.left = left;
1850 node.right = this.parseMaybeAssign();
1851 return this.finishNode(node, "AssignmentPattern")
1852 };
1853
1854 // Verify that a node is an lval — something that can be assigned
1855 // to.
1856 // bindingType can be either:
1857 // 'var' indicating that the lval creates a 'var' binding
1858 // 'let' indicating that the lval creates a lexical ('let' or 'const') binding
1859 // 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references
1860
1861 pp$2.checkLVal = function(expr, bindingType, checkClashes) {
1862 if ( bindingType === void 0 ) bindingType = BIND_NONE;
1863
1864 switch (expr.type) {
1865 case "Identifier":
1866 if (bindingType === BIND_LEXICAL && expr.name === "let")
1867 { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); }
1868 if (this.strict && this.reservedWordsStrictBind.test(expr.name))
1869 { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
1870 if (checkClashes) {
1871 if (has(checkClashes, expr.name))
1872 { this.raiseRecoverable(expr.start, "Argument name clash"); }
1873 checkClashes[expr.name] = true;
1874 }
1875 if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); }
1876 break
1877
1878 case "MemberExpression":
1879 if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); }
1880 break
1881
1882 case "ObjectPattern":
1883 for (var i = 0, list = expr.properties; i < list.length; i += 1)
1884 {
1885 var prop = list[i];
1886
1887 this.checkLVal(prop, bindingType, checkClashes);
1888 }
1889 break
1890
1891 case "Property":
1892 // AssignmentProperty has type === "Property"
1893 this.checkLVal(expr.value, bindingType, checkClashes);
1894 break
1895
1896 case "ArrayPattern":
1897 for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
1898 var elem = list$1[i$1];
1899
1900 if (elem) { this.checkLVal(elem, bindingType, checkClashes); }
1901 }
1902 break
1903
1904 case "AssignmentPattern":
1905 this.checkLVal(expr.left, bindingType, checkClashes);
1906 break
1907
1908 case "RestElement":
1909 this.checkLVal(expr.argument, bindingType, checkClashes);
1910 break
1911
1912 case "ParenthesizedExpression":
1913 this.checkLVal(expr.expression, bindingType, checkClashes);
1914 break
1915
1916 default:
1917 this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue");
1918 }
1919 };
1920
1921 // A recursive descent parser operates by defining functions for all
1922
1923 var pp$3 = Parser.prototype;
1924
1925 // Check if property name clashes with already added.
1926 // Object/class getters and setters are not allowed to clash —
1927 // either with each other or with an init property — and in
1928 // strict mode, init properties are also not allowed to be repeated.
1929
1930 pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) {
1931 if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
1932 { return }
1933 if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
1934 { return }
1935 var key = prop.key;
1936 var name;
1937 switch (key.type) {
1938 case "Identifier": name = key.name; break
1939 case "Literal": name = String(key.value); break
1940 default: return
1941 }
1942 var kind = prop.kind;
1943 if (this.options.ecmaVersion >= 6) {
1944 if (name === "__proto__" && kind === "init") {
1945 if (propHash.proto) {
1946 if (refDestructuringErrors) {
1947 if (refDestructuringErrors.doubleProto < 0)
1948 { refDestructuringErrors.doubleProto = key.start; }
1949 // Backwards-compat kludge. Can be removed in version 6.0
1950 } else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); }
1951 }
1952 propHash.proto = true;
1953 }
1954 return
1955 }
1956 name = "$" + name;
1957 var other = propHash[name];
1958 if (other) {
1959 var redefinition;
1960 if (kind === "init") {
1961 redefinition = this.strict && other.init || other.get || other.set;
1962 } else {
1963 redefinition = other.init || other[kind];
1964 }
1965 if (redefinition)
1966 { this.raiseRecoverable(key.start, "Redefinition of property"); }
1967 } else {
1968 other = propHash[name] = {
1969 init: false,
1970 get: false,
1971 set: false
1972 };
1973 }
1974 other[kind] = true;
1975 };
1976
1977 // ### Expression parsing
1978
1979 // These nest, from the most general expression type at the top to
1980 // 'atomic', nondivisible expression types at the bottom. Most of
1981 // the functions will simply let the function(s) below them parse,
1982 // and, *if* the syntactic construct they handle is present, wrap
1983 // the AST node that the inner parser gave them in another node.
1984
1985 // Parse a full expression. The optional arguments are used to
1986 // forbid the `in` operator (in for loops initalization expressions)
1987 // and provide reference for storing '=' operator inside shorthand
1988 // property assignment in contexts where both object expression
1989 // and object pattern might appear (so it's possible to raise
1990 // delayed syntax error at correct position).
1991
1992 pp$3.parseExpression = function(noIn, refDestructuringErrors) {
1993 var startPos = this.start, startLoc = this.startLoc;
1994 var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
1995 if (this.type === types.comma) {
1996 var node = this.startNodeAt(startPos, startLoc);
1997 node.expressions = [expr];
1998 while (this.eat(types.comma)) { node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); }
1999 return this.finishNode(node, "SequenceExpression")
2000 }
2001 return expr
2002 };
2003
2004 // Parse an assignment expression. This includes applications of
2005 // operators like `+=`.
2006
2007 pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
2008 if (this.isContextual("yield")) {
2009 if (this.inGenerator) { return this.parseYield(noIn) }
2010 // The tokenizer will assume an expression is allowed after
2011 // `yield`, but this isn't that kind of yield
2012 else { this.exprAllowed = false; }
2013 }
2014
2015 var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1;
2016 if (refDestructuringErrors) {
2017 oldParenAssign = refDestructuringErrors.parenthesizedAssign;
2018 oldTrailingComma = refDestructuringErrors.trailingComma;
2019 refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
2020 } else {
2021 refDestructuringErrors = new DestructuringErrors;
2022 ownDestructuringErrors = true;
2023 }
2024
2025 var startPos = this.start, startLoc = this.startLoc;
2026 if (this.type === types.parenL || this.type === types.name)
2027 { this.potentialArrowAt = this.start; }
2028 var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
2029 if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
2030 if (this.type.isAssign) {
2031 var node = this.startNodeAt(startPos, startLoc);
2032 node.operator = this.value;
2033 node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left;
2034 if (!ownDestructuringErrors) {
2035 refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
2036 }
2037 if (refDestructuringErrors.shorthandAssign >= node.left.start)
2038 { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly
2039 this.checkLVal(left);
2040 this.next();
2041 node.right = this.parseMaybeAssign(noIn);
2042 return this.finishNode(node, "AssignmentExpression")
2043 } else {
2044 if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
2045 }
2046 if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
2047 if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
2048 return left
2049 };
2050
2051 // Parse a ternary conditional (`?:`) operator.
2052
2053 pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) {
2054 var startPos = this.start, startLoc = this.startLoc;
2055 var expr = this.parseExprOps(noIn, refDestructuringErrors);
2056 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2057 if (this.eat(types.question)) {
2058 var node = this.startNodeAt(startPos, startLoc);
2059 node.test = expr;
2060 node.consequent = this.parseMaybeAssign();
2061 this.expect(types.colon);
2062 node.alternate = this.parseMaybeAssign(noIn);
2063 return this.finishNode(node, "ConditionalExpression")
2064 }
2065 return expr
2066 };
2067
2068 // Start the precedence parser.
2069
2070 pp$3.parseExprOps = function(noIn, refDestructuringErrors) {
2071 var startPos = this.start, startLoc = this.startLoc;
2072 var expr = this.parseMaybeUnary(refDestructuringErrors, false);
2073 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2074 return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn)
2075 };
2076
2077 // Parse binary operators with the operator precedence parsing
2078 // algorithm. `left` is the left-hand side of the operator.
2079 // `minPrec` provides context that allows the function to stop and
2080 // defer further parser to one of its callers when it encounters an
2081 // operator that has a lower precedence than the set it is parsing.
2082
2083 pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
2084 var prec = this.type.binop;
2085 if (prec != null && (!noIn || this.type !== types._in)) {
2086 if (prec > minPrec) {
2087 var logical = this.type === types.logicalOR || this.type === types.logicalAND;
2088 var op = this.value;
2089 this.next();
2090 var startPos = this.start, startLoc = this.startLoc;
2091 var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
2092 var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical);
2093 return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
2094 }
2095 }
2096 return left
2097 };
2098
2099 pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) {
2100 var node = this.startNodeAt(startPos, startLoc);
2101 node.left = left;
2102 node.operator = op;
2103 node.right = right;
2104 return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
2105 };
2106
2107 // Parse unary operators, both prefix and postfix.
2108
2109 pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
2110 var startPos = this.start, startLoc = this.startLoc, expr;
2111 if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) {
2112 expr = this.parseAwait();
2113 sawUnary = true;
2114 } else if (this.type.prefix) {
2115 var node = this.startNode(), update = this.type === types.incDec;
2116 node.operator = this.value;
2117 node.prefix = true;
2118 this.next();
2119 node.argument = this.parseMaybeUnary(null, true);
2120 this.checkExpressionErrors(refDestructuringErrors, true);
2121 if (update) { this.checkLVal(node.argument); }
2122 else if (this.strict && node.operator === "delete" &&
2123 node.argument.type === "Identifier")
2124 { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
2125 else { sawUnary = true; }
2126 expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
2127 } else {
2128 expr = this.parseExprSubscripts(refDestructuringErrors);
2129 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2130 while (this.type.postfix && !this.canInsertSemicolon()) {
2131 var node$1 = this.startNodeAt(startPos, startLoc);
2132 node$1.operator = this.value;
2133 node$1.prefix = false;
2134 node$1.argument = expr;
2135 this.checkLVal(expr);
2136 this.next();
2137 expr = this.finishNode(node$1, "UpdateExpression");
2138 }
2139 }
2140
2141 if (!sawUnary && this.eat(types.starstar))
2142 { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) }
2143 else
2144 { return expr }
2145 };
2146
2147 // Parse call, dot, and `[]`-subscript expressions.
2148
2149 pp$3.parseExprSubscripts = function(refDestructuringErrors) {
2150 var startPos = this.start, startLoc = this.startLoc;
2151 var expr = this.parseExprAtom(refDestructuringErrors);
2152 if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")")
2153 { return expr }
2154 var result = this.parseSubscripts(expr, startPos, startLoc);
2155 if (refDestructuringErrors && result.type === "MemberExpression") {
2156 if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
2157 if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
2158 }
2159 return result
2160 };
2161
2162 pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) {
2163 var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
2164 this.lastTokEnd === base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async";
2165 while (true) {
2166 var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow);
2167 if (element === base || element.type === "ArrowFunctionExpression") { return element }
2168 base = element;
2169 }
2170 };
2171
2172 pp$3.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow) {
2173 var computed = this.eat(types.bracketL);
2174 if (computed || this.eat(types.dot)) {
2175 var node = this.startNodeAt(startPos, startLoc);
2176 node.object = base;
2177 node.property = computed ? this.parseExpression() : this.parseIdent(this.options.allowReserved !== "never");
2178 node.computed = !!computed;
2179 if (computed) { this.expect(types.bracketR); }
2180 base = this.finishNode(node, "MemberExpression");
2181 } else if (!noCalls && this.eat(types.parenL)) {
2182 var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2183 this.yieldPos = 0;
2184 this.awaitPos = 0;
2185 this.awaitIdentPos = 0;
2186 var exprList = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors);
2187 if (maybeAsyncArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
2188 this.checkPatternErrors(refDestructuringErrors, false);
2189 this.checkYieldAwaitInDefaultParams();
2190 if (this.awaitIdentPos > 0)
2191 { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); }
2192 this.yieldPos = oldYieldPos;
2193 this.awaitPos = oldAwaitPos;
2194 this.awaitIdentPos = oldAwaitIdentPos;
2195 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true)
2196 }
2197 this.checkExpressionErrors(refDestructuringErrors, true);
2198 this.yieldPos = oldYieldPos || this.yieldPos;
2199 this.awaitPos = oldAwaitPos || this.awaitPos;
2200 this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos;
2201 var node$1 = this.startNodeAt(startPos, startLoc);
2202 node$1.callee = base;
2203 node$1.arguments = exprList;
2204 base = this.finishNode(node$1, "CallExpression");
2205 } else if (this.type === types.backQuote) {
2206 var node$2 = this.startNodeAt(startPos, startLoc);
2207 node$2.tag = base;
2208 node$2.quasi = this.parseTemplate({isTagged: true});
2209 base = this.finishNode(node$2, "TaggedTemplateExpression");
2210 }
2211 return base
2212 };
2213
2214 // Parse an atomic expression — either a single token that is an
2215 // expression, an expression started by a keyword like `function` or
2216 // `new`, or an expression wrapped in punctuation like `()`, `[]`,
2217 // or `{}`.
2218
2219 pp$3.parseExprAtom = function(refDestructuringErrors) {
2220 // If a division operator appears in an expression position, the
2221 // tokenizer got confused, and we force it to read a regexp instead.
2222 if (this.type === types.slash) { this.readRegexp(); }
2223
2224 var node, canBeArrow = this.potentialArrowAt === this.start;
2225 switch (this.type) {
2226 case types._super:
2227 if (!this.allowSuper)
2228 { this.raise(this.start, "'super' keyword outside a method"); }
2229 node = this.startNode();
2230 this.next();
2231 if (this.type === types.parenL && !this.allowDirectSuper)
2232 { this.raise(node.start, "super() call outside constructor of a subclass"); }
2233 // The `super` keyword can appear at below:
2234 // SuperProperty:
2235 // super [ Expression ]
2236 // super . IdentifierName
2237 // SuperCall:
2238 // super ( Arguments )
2239 if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
2240 { this.unexpected(); }
2241 return this.finishNode(node, "Super")
2242
2243 case types._this:
2244 node = this.startNode();
2245 this.next();
2246 return this.finishNode(node, "ThisExpression")
2247
2248 case types.name:
2249 var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
2250 var id = this.parseIdent(false);
2251 if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function))
2252 { return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) }
2253 if (canBeArrow && !this.canInsertSemicolon()) {
2254 if (this.eat(types.arrow))
2255 { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) }
2256 if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) {
2257 id = this.parseIdent(false);
2258 if (this.canInsertSemicolon() || !this.eat(types.arrow))
2259 { this.unexpected(); }
2260 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
2261 }
2262 }
2263 return id
2264
2265 case types.regexp:
2266 var value = this.value;
2267 node = this.parseLiteral(value.value);
2268 node.regex = {pattern: value.pattern, flags: value.flags};
2269 return node
2270
2271 case types.num: case types.string:
2272 return this.parseLiteral(this.value)
2273
2274 case types._null: case types._true: case types._false:
2275 node = this.startNode();
2276 node.value = this.type === types._null ? null : this.type === types._true;
2277 node.raw = this.type.keyword;
2278 this.next();
2279 return this.finishNode(node, "Literal")
2280
2281 case types.parenL:
2282 var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow);
2283 if (refDestructuringErrors) {
2284 if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
2285 { refDestructuringErrors.parenthesizedAssign = start; }
2286 if (refDestructuringErrors.parenthesizedBind < 0)
2287 { refDestructuringErrors.parenthesizedBind = start; }
2288 }
2289 return expr
2290
2291 case types.bracketL:
2292 node = this.startNode();
2293 this.next();
2294 node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors);
2295 return this.finishNode(node, "ArrayExpression")
2296
2297 case types.braceL:
2298 return this.parseObj(false, refDestructuringErrors)
2299
2300 case types._function:
2301 node = this.startNode();
2302 this.next();
2303 return this.parseFunction(node, 0)
2304
2305 case types._class:
2306 return this.parseClass(this.startNode(), false)
2307
2308 case types._new:
2309 return this.parseNew()
2310
2311 case types.backQuote:
2312 return this.parseTemplate()
2313
2314 case types._import:
2315 if (this.options.ecmaVersion >= 11) {
2316 return this.parseExprImport()
2317 } else {
2318 return this.unexpected()
2319 }
2320
2321 default:
2322 this.unexpected();
2323 }
2324 };
2325
2326 pp$3.parseExprImport = function() {
2327 var node = this.startNode();
2328 this.next(); // skip `import`
2329 switch (this.type) {
2330 case types.parenL:
2331 return this.parseDynamicImport(node)
2332 default:
2333 this.unexpected();
2334 }
2335 };
2336
2337 pp$3.parseDynamicImport = function(node) {
2338 this.next(); // skip `(`
2339
2340 // Parse node.source.
2341 node.source = this.parseMaybeAssign();
2342
2343 // Verify ending.
2344 if (!this.eat(types.parenR)) {
2345 var errorPos = this.start;
2346 if (this.eat(types.comma) && this.eat(types.parenR)) {
2347 this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()");
2348 } else {
2349 this.unexpected(errorPos);
2350 }
2351 }
2352
2353 return this.finishNode(node, "ImportExpression")
2354 };
2355
2356 pp$3.parseLiteral = function(value) {
2357 var node = this.startNode();
2358 node.value = value;
2359 node.raw = this.input.slice(this.start, this.end);
2360 if (node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1); }
2361 this.next();
2362 return this.finishNode(node, "Literal")
2363 };
2364
2365 pp$3.parseParenExpression = function() {
2366 this.expect(types.parenL);
2367 var val = this.parseExpression();
2368 this.expect(types.parenR);
2369 return val
2370 };
2371
2372 pp$3.parseParenAndDistinguishExpression = function(canBeArrow) {
2373 var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
2374 if (this.options.ecmaVersion >= 6) {
2375 this.next();
2376
2377 var innerStartPos = this.start, innerStartLoc = this.startLoc;
2378 var exprList = [], first = true, lastIsComma = false;
2379 var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
2380 this.yieldPos = 0;
2381 this.awaitPos = 0;
2382 // Do not save awaitIdentPos to allow checking awaits nested in parameters
2383 while (this.type !== types.parenR) {
2384 first ? first = false : this.expect(types.comma);
2385 if (allowTrailingComma && this.afterTrailingComma(types.parenR, true)) {
2386 lastIsComma = true;
2387 break
2388 } else if (this.type === types.ellipsis) {
2389 spreadStart = this.start;
2390 exprList.push(this.parseParenItem(this.parseRestBinding()));
2391 if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); }
2392 break
2393 } else {
2394 exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem));
2395 }
2396 }
2397 var innerEndPos = this.start, innerEndLoc = this.startLoc;
2398 this.expect(types.parenR);
2399
2400 if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
2401 this.checkPatternErrors(refDestructuringErrors, false);
2402 this.checkYieldAwaitInDefaultParams();
2403 this.yieldPos = oldYieldPos;
2404 this.awaitPos = oldAwaitPos;
2405 return this.parseParenArrowList(startPos, startLoc, exprList)
2406 }
2407
2408 if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
2409 if (spreadStart) { this.unexpected(spreadStart); }
2410 this.checkExpressionErrors(refDestructuringErrors, true);
2411 this.yieldPos = oldYieldPos || this.yieldPos;
2412 this.awaitPos = oldAwaitPos || this.awaitPos;
2413
2414 if (exprList.length > 1) {
2415 val = this.startNodeAt(innerStartPos, innerStartLoc);
2416 val.expressions = exprList;
2417 this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
2418 } else {
2419 val = exprList[0];
2420 }
2421 } else {
2422 val = this.parseParenExpression();
2423 }
2424
2425 if (this.options.preserveParens) {
2426 var par = this.startNodeAt(startPos, startLoc);
2427 par.expression = val;
2428 return this.finishNode(par, "ParenthesizedExpression")
2429 } else {
2430 return val
2431 }
2432 };
2433
2434 pp$3.parseParenItem = function(item) {
2435 return item
2436 };
2437
2438 pp$3.parseParenArrowList = function(startPos, startLoc, exprList) {
2439 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)
2440 };
2441
2442 // New's precedence is slightly tricky. It must allow its argument to
2443 // be a `[]` or dot subscript expression, but not a call — at least,
2444 // not without wrapping it in parentheses. Thus, it uses the noCalls
2445 // argument to parseSubscripts to prevent it from consuming the
2446 // argument list.
2447
2448 var empty$1 = [];
2449
2450 pp$3.parseNew = function() {
2451 if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); }
2452 var node = this.startNode();
2453 var meta = this.parseIdent(true);
2454 if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) {
2455 node.meta = meta;
2456 var containsEsc = this.containsEsc;
2457 node.property = this.parseIdent(true);
2458 if (node.property.name !== "target" || containsEsc)
2459 { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); }
2460 if (!this.inNonArrowFunction())
2461 { this.raiseRecoverable(node.start, "new.target can only be used in functions"); }
2462 return this.finishNode(node, "MetaProperty")
2463 }
2464 var startPos = this.start, startLoc = this.startLoc, isImport = this.type === types._import;
2465 node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
2466 if (isImport && node.callee.type === "ImportExpression") {
2467 this.raise(startPos, "Cannot use new with import()");
2468 }
2469 if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); }
2470 else { node.arguments = empty$1; }
2471 return this.finishNode(node, "NewExpression")
2472 };
2473
2474 // Parse template expression.
2475
2476 pp$3.parseTemplateElement = function(ref) {
2477 var isTagged = ref.isTagged;
2478
2479 var elem = this.startNode();
2480 if (this.type === types.invalidTemplate) {
2481 if (!isTagged) {
2482 this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
2483 }
2484 elem.value = {
2485 raw: this.value,
2486 cooked: null
2487 };
2488 } else {
2489 elem.value = {
2490 raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
2491 cooked: this.value
2492 };
2493 }
2494 this.next();
2495 elem.tail = this.type === types.backQuote;
2496 return this.finishNode(elem, "TemplateElement")
2497 };
2498
2499 pp$3.parseTemplate = function(ref) {
2500 if ( ref === void 0 ) ref = {};
2501 var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;
2502
2503 var node = this.startNode();
2504 this.next();
2505 node.expressions = [];
2506 var curElt = this.parseTemplateElement({isTagged: isTagged});
2507 node.quasis = [curElt];
2508 while (!curElt.tail) {
2509 if (this.type === types.eof) { this.raise(this.pos, "Unterminated template literal"); }
2510 this.expect(types.dollarBraceL);
2511 node.expressions.push(this.parseExpression());
2512 this.expect(types.braceR);
2513 node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged}));
2514 }
2515 this.next();
2516 return this.finishNode(node, "TemplateLiteral")
2517 };
2518
2519 pp$3.isAsyncProp = function(prop) {
2520 return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
2521 (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)) &&
2522 !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
2523 };
2524
2525 // Parse an object literal or binding pattern.
2526
2527 pp$3.parseObj = function(isPattern, refDestructuringErrors) {
2528 var node = this.startNode(), first = true, propHash = {};
2529 node.properties = [];
2530 this.next();
2531 while (!this.eat(types.braceR)) {
2532 if (!first) {
2533 this.expect(types.comma);
2534 if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types.braceR)) { break }
2535 } else { first = false; }
2536
2537 var prop = this.parseProperty(isPattern, refDestructuringErrors);
2538 if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); }
2539 node.properties.push(prop);
2540 }
2541 return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
2542 };
2543
2544 pp$3.parseProperty = function(isPattern, refDestructuringErrors) {
2545 var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
2546 if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) {
2547 if (isPattern) {
2548 prop.argument = this.parseIdent(false);
2549 if (this.type === types.comma) {
2550 this.raise(this.start, "Comma is not permitted after the rest element");
2551 }
2552 return this.finishNode(prop, "RestElement")
2553 }
2554 // To disallow parenthesized identifier via `this.toAssignable()`.
2555 if (this.type === types.parenL && refDestructuringErrors) {
2556 if (refDestructuringErrors.parenthesizedAssign < 0) {
2557 refDestructuringErrors.parenthesizedAssign = this.start;
2558 }
2559 if (refDestructuringErrors.parenthesizedBind < 0) {
2560 refDestructuringErrors.parenthesizedBind = this.start;
2561 }
2562 }
2563 // Parse argument.
2564 prop.argument = this.parseMaybeAssign(false, refDestructuringErrors);
2565 // To disallow trailing comma via `this.toAssignable()`.
2566 if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
2567 refDestructuringErrors.trailingComma = this.start;
2568 }
2569 // Finish
2570 return this.finishNode(prop, "SpreadElement")
2571 }
2572 if (this.options.ecmaVersion >= 6) {
2573 prop.method = false;
2574 prop.shorthand = false;
2575 if (isPattern || refDestructuringErrors) {
2576 startPos = this.start;
2577 startLoc = this.startLoc;
2578 }
2579 if (!isPattern)
2580 { isGenerator = this.eat(types.star); }
2581 }
2582 var containsEsc = this.containsEsc;
2583 this.parsePropertyName(prop);
2584 if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
2585 isAsync = true;
2586 isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
2587 this.parsePropertyName(prop, refDestructuringErrors);
2588 } else {
2589 isAsync = false;
2590 }
2591 this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
2592 return this.finishNode(prop, "Property")
2593 };
2594
2595 pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
2596 if ((isGenerator || isAsync) && this.type === types.colon)
2597 { this.unexpected(); }
2598
2599 if (this.eat(types.colon)) {
2600 prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
2601 prop.kind = "init";
2602 } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) {
2603 if (isPattern) { this.unexpected(); }
2604 prop.kind = "init";
2605 prop.method = true;
2606 prop.value = this.parseMethod(isGenerator, isAsync);
2607 } else if (!isPattern && !containsEsc &&
2608 this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
2609 (prop.key.name === "get" || prop.key.name === "set") &&
2610 (this.type !== types.comma && this.type !== types.braceR)) {
2611 if (isGenerator || isAsync) { this.unexpected(); }
2612 prop.kind = prop.key.name;
2613 this.parsePropertyName(prop);
2614 prop.value = this.parseMethod(false);
2615 var paramCount = prop.kind === "get" ? 0 : 1;
2616 if (prop.value.params.length !== paramCount) {
2617 var start = prop.value.start;
2618 if (prop.kind === "get")
2619 { this.raiseRecoverable(start, "getter should have no params"); }
2620 else
2621 { this.raiseRecoverable(start, "setter should have exactly one param"); }
2622 } else {
2623 if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
2624 { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
2625 }
2626 } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
2627 if (isGenerator || isAsync) { this.unexpected(); }
2628 this.checkUnreserved(prop.key);
2629 if (prop.key.name === "await" && !this.awaitIdentPos)
2630 { this.awaitIdentPos = startPos; }
2631 prop.kind = "init";
2632 if (isPattern) {
2633 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
2634 } else if (this.type === types.eq && refDestructuringErrors) {
2635 if (refDestructuringErrors.shorthandAssign < 0)
2636 { refDestructuringErrors.shorthandAssign = this.start; }
2637 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
2638 } else {
2639 prop.value = prop.key;
2640 }
2641 prop.shorthand = true;
2642 } else { this.unexpected(); }
2643 };
2644
2645 pp$3.parsePropertyName = function(prop) {
2646 if (this.options.ecmaVersion >= 6) {
2647 if (this.eat(types.bracketL)) {
2648 prop.computed = true;
2649 prop.key = this.parseMaybeAssign();
2650 this.expect(types.bracketR);
2651 return prop.key
2652 } else {
2653 prop.computed = false;
2654 }
2655 }
2656 return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never")
2657 };
2658
2659 // Initialize empty function node.
2660
2661 pp$3.initFunction = function(node) {
2662 node.id = null;
2663 if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; }
2664 if (this.options.ecmaVersion >= 8) { node.async = false; }
2665 };
2666
2667 // Parse object or class method.
2668
2669 pp$3.parseMethod = function(isGenerator, isAsync, allowDirectSuper) {
2670 var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2671
2672 this.initFunction(node);
2673 if (this.options.ecmaVersion >= 6)
2674 { node.generator = isGenerator; }
2675 if (this.options.ecmaVersion >= 8)
2676 { node.async = !!isAsync; }
2677
2678 this.yieldPos = 0;
2679 this.awaitPos = 0;
2680 this.awaitIdentPos = 0;
2681 this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0));
2682
2683 this.expect(types.parenL);
2684 node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
2685 this.checkYieldAwaitInDefaultParams();
2686 this.parseFunctionBody(node, false, true);
2687
2688 this.yieldPos = oldYieldPos;
2689 this.awaitPos = oldAwaitPos;
2690 this.awaitIdentPos = oldAwaitIdentPos;
2691 return this.finishNode(node, "FunctionExpression")
2692 };
2693
2694 // Parse arrow function expression with given parameters.
2695
2696 pp$3.parseArrowExpression = function(node, params, isAsync) {
2697 var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2698
2699 this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW);
2700 this.initFunction(node);
2701 if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; }
2702
2703 this.yieldPos = 0;
2704 this.awaitPos = 0;
2705 this.awaitIdentPos = 0;
2706
2707 node.params = this.toAssignableList(params, true);
2708 this.parseFunctionBody(node, true, false);
2709
2710 this.yieldPos = oldYieldPos;
2711 this.awaitPos = oldAwaitPos;
2712 this.awaitIdentPos = oldAwaitIdentPos;
2713 return this.finishNode(node, "ArrowFunctionExpression")
2714 };
2715
2716 // Parse function body and check parameters.
2717
2718 pp$3.parseFunctionBody = function(node, isArrowFunction, isMethod) {
2719 var isExpression = isArrowFunction && this.type !== types.braceL;
2720 var oldStrict = this.strict, useStrict = false;
2721
2722 if (isExpression) {
2723 node.body = this.parseMaybeAssign();
2724 node.expression = true;
2725 this.checkParams(node, false);
2726 } else {
2727 var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
2728 if (!oldStrict || nonSimple) {
2729 useStrict = this.strictDirective(this.end);
2730 // If this is a strict mode function, verify that argument names
2731 // are not repeated, and it does not try to bind the words `eval`
2732 // or `arguments`.
2733 if (useStrict && nonSimple)
2734 { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
2735 }
2736 // Start a new scope with regard to labels and the `inFunction`
2737 // flag (restore them to their old value afterwards).
2738 var oldLabels = this.labels;
2739 this.labels = [];
2740 if (useStrict) { this.strict = true; }
2741
2742 // Add the params to varDeclaredNames to ensure that an error is thrown
2743 // if a let/const declaration in the function clashes with one of the params.
2744 this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params));
2745 node.body = this.parseBlock(false);
2746 node.expression = false;
2747 this.adaptDirectivePrologue(node.body.body);
2748 this.labels = oldLabels;
2749 }
2750 this.exitScope();
2751
2752 // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
2753 if (this.strict && node.id) { this.checkLVal(node.id, BIND_OUTSIDE); }
2754 this.strict = oldStrict;
2755 };
2756
2757 pp$3.isSimpleParamList = function(params) {
2758 for (var i = 0, list = params; i < list.length; i += 1)
2759 {
2760 var param = list[i];
2761
2762 if (param.type !== "Identifier") { return false
2763 } }
2764 return true
2765 };
2766
2767 // Checks function params for various disallowed patterns such as using "eval"
2768 // or "arguments" and duplicate parameters.
2769
2770 pp$3.checkParams = function(node, allowDuplicates) {
2771 var nameHash = {};
2772 for (var i = 0, list = node.params; i < list.length; i += 1)
2773 {
2774 var param = list[i];
2775
2776 this.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash);
2777 }
2778 };
2779
2780 // Parses a comma-separated list of expressions, and returns them as
2781 // an array. `close` is the token type that ends the list, and
2782 // `allowEmpty` can be turned on to allow subsequent commas with
2783 // nothing in between them to be parsed as `null` (which is needed
2784 // for array literals).
2785
2786 pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
2787 var elts = [], first = true;
2788 while (!this.eat(close)) {
2789 if (!first) {
2790 this.expect(types.comma);
2791 if (allowTrailingComma && this.afterTrailingComma(close)) { break }
2792 } else { first = false; }
2793
2794 var elt = (void 0);
2795 if (allowEmpty && this.type === types.comma)
2796 { elt = null; }
2797 else if (this.type === types.ellipsis) {
2798 elt = this.parseSpread(refDestructuringErrors);
2799 if (refDestructuringErrors && this.type === types.comma && refDestructuringErrors.trailingComma < 0)
2800 { refDestructuringErrors.trailingComma = this.start; }
2801 } else {
2802 elt = this.parseMaybeAssign(false, refDestructuringErrors);
2803 }
2804 elts.push(elt);
2805 }
2806 return elts
2807 };
2808
2809 pp$3.checkUnreserved = function(ref) {
2810 var start = ref.start;
2811 var end = ref.end;
2812 var name = ref.name;
2813
2814 if (this.inGenerator && name === "yield")
2815 { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); }
2816 if (this.inAsync && name === "await")
2817 { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); }
2818 if (this.keywords.test(name))
2819 { this.raise(start, ("Unexpected keyword '" + name + "'")); }
2820 if (this.options.ecmaVersion < 6 &&
2821 this.input.slice(start, end).indexOf("\\") !== -1) { return }
2822 var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
2823 if (re.test(name)) {
2824 if (!this.inAsync && name === "await")
2825 { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); }
2826 this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved"));
2827 }
2828 };
2829
2830 // Parse the next token as an identifier. If `liberal` is true (used
2831 // when parsing properties), it will also convert keywords into
2832 // identifiers.
2833
2834 pp$3.parseIdent = function(liberal, isBinding) {
2835 var node = this.startNode();
2836 if (this.type === types.name) {
2837 node.name = this.value;
2838 } else if (this.type.keyword) {
2839 node.name = this.type.keyword;
2840
2841 // To fix https://github.com/acornjs/acorn/issues/575
2842 // `class` and `function` keywords push new context into this.context.
2843 // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
2844 // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
2845 if ((node.name === "class" || node.name === "function") &&
2846 (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
2847 this.context.pop();
2848 }
2849 } else {
2850 this.unexpected();
2851 }
2852 this.next(!!liberal);
2853 this.finishNode(node, "Identifier");
2854 if (!liberal) {
2855 this.checkUnreserved(node);
2856 if (node.name === "await" && !this.awaitIdentPos)
2857 { this.awaitIdentPos = node.start; }
2858 }
2859 return node
2860 };
2861
2862 // Parses yield expression inside generator.
2863
2864 pp$3.parseYield = function(noIn) {
2865 if (!this.yieldPos) { this.yieldPos = this.start; }
2866
2867 var node = this.startNode();
2868 this.next();
2869 if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) {
2870 node.delegate = false;
2871 node.argument = null;
2872 } else {
2873 node.delegate = this.eat(types.star);
2874 node.argument = this.parseMaybeAssign(noIn);
2875 }
2876 return this.finishNode(node, "YieldExpression")
2877 };
2878
2879 pp$3.parseAwait = function() {
2880 if (!this.awaitPos) { this.awaitPos = this.start; }
2881
2882 var node = this.startNode();
2883 this.next();
2884 node.argument = this.parseMaybeUnary(null, false);
2885 return this.finishNode(node, "AwaitExpression")
2886 };
2887
2888 var pp$4 = Parser.prototype;
2889
2890 // This function is used to raise exceptions on parse errors. It
2891 // takes an offset integer (into the current `input`) to indicate
2892 // the location of the error, attaches the position to the end
2893 // of the error message, and then raises a `SyntaxError` with that
2894 // message.
2895
2896 pp$4.raise = function(pos, message) {
2897 var loc = getLineInfo(this.input, pos);
2898 message += " (" + loc.line + ":" + loc.column + ")";
2899 var err = new SyntaxError(message);
2900 err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
2901 throw err
2902 };
2903
2904 pp$4.raiseRecoverable = pp$4.raise;
2905
2906 pp$4.curPosition = function() {
2907 if (this.options.locations) {
2908 return new Position(this.curLine, this.pos - this.lineStart)
2909 }
2910 };
2911
2912 var pp$5 = Parser.prototype;
2913
2914 var Scope = function Scope(flags) {
2915 this.flags = flags;
2916 // A list of var-declared names in the current lexical scope
2917 this.var = [];
2918 // A list of lexically-declared names in the current lexical scope
2919 this.lexical = [];
2920 // A list of lexically-declared FunctionDeclaration names in the current lexical scope
2921 this.functions = [];
2922 };
2923
2924 // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.
2925
2926 pp$5.enterScope = function(flags) {
2927 this.scopeStack.push(new Scope(flags));
2928 };
2929
2930 pp$5.exitScope = function() {
2931 this.scopeStack.pop();
2932 };
2933
2934 // The spec says:
2935 // > At the top level of a function, or script, function declarations are
2936 // > treated like var declarations rather than like lexical declarations.
2937 pp$5.treatFunctionsAsVarInScope = function(scope) {
2938 return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP)
2939 };
2940
2941 pp$5.declareName = function(name, bindingType, pos) {
2942 var redeclared = false;
2943 if (bindingType === BIND_LEXICAL) {
2944 var scope = this.currentScope();
2945 redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
2946 scope.lexical.push(name);
2947 if (this.inModule && (scope.flags & SCOPE_TOP))
2948 { delete this.undefinedExports[name]; }
2949 } else if (bindingType === BIND_SIMPLE_CATCH) {
2950 var scope$1 = this.currentScope();
2951 scope$1.lexical.push(name);
2952 } else if (bindingType === BIND_FUNCTION) {
2953 var scope$2 = this.currentScope();
2954 if (this.treatFunctionsAsVar)
2955 { redeclared = scope$2.lexical.indexOf(name) > -1; }
2956 else
2957 { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; }
2958 scope$2.functions.push(name);
2959 } else {
2960 for (var i = this.scopeStack.length - 1; i >= 0; --i) {
2961 var scope$3 = this.scopeStack[i];
2962 if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) ||
2963 !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) {
2964 redeclared = true;
2965 break
2966 }
2967 scope$3.var.push(name);
2968 if (this.inModule && (scope$3.flags & SCOPE_TOP))
2969 { delete this.undefinedExports[name]; }
2970 if (scope$3.flags & SCOPE_VAR) { break }
2971 }
2972 }
2973 if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); }
2974 };
2975
2976 pp$5.checkLocalExport = function(id) {
2977 // scope.functions must be empty as Module code is always strict.
2978 if (this.scopeStack[0].lexical.indexOf(id.name) === -1 &&
2979 this.scopeStack[0].var.indexOf(id.name) === -1) {
2980 this.undefinedExports[id.name] = id;
2981 }
2982 };
2983
2984 pp$5.currentScope = function() {
2985 return this.scopeStack[this.scopeStack.length - 1]
2986 };
2987
2988 pp$5.currentVarScope = function() {
2989 for (var i = this.scopeStack.length - 1;; i--) {
2990 var scope = this.scopeStack[i];
2991 if (scope.flags & SCOPE_VAR) { return scope }
2992 }
2993 };
2994
2995 // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
2996 pp$5.currentThisScope = function() {
2997 for (var i = this.scopeStack.length - 1;; i--) {
2998 var scope = this.scopeStack[i];
2999 if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) { return scope }
3000 }
3001 };
3002
3003 var Node = function Node(parser, pos, loc) {
3004 this.type = "";
3005 this.start = pos;
3006 this.end = 0;
3007 if (parser.options.locations)
3008 { this.loc = new SourceLocation(parser, loc); }
3009 if (parser.options.directSourceFile)
3010 { this.sourceFile = parser.options.directSourceFile; }
3011 if (parser.options.ranges)
3012 { this.range = [pos, 0]; }
3013 };
3014
3015 // Start an AST node, attaching a start offset.
3016
3017 var pp$6 = Parser.prototype;
3018
3019 pp$6.startNode = function() {
3020 return new Node(this, this.start, this.startLoc)
3021 };
3022
3023 pp$6.startNodeAt = function(pos, loc) {
3024 return new Node(this, pos, loc)
3025 };
3026
3027 // Finish an AST node, adding `type` and `end` properties.
3028
3029 function finishNodeAt(node, type, pos, loc) {
3030 node.type = type;
3031 node.end = pos;
3032 if (this.options.locations)
3033 { node.loc.end = loc; }
3034 if (this.options.ranges)
3035 { node.range[1] = pos; }
3036 return node
3037 }
3038
3039 pp$6.finishNode = function(node, type) {
3040 return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
3041 };
3042
3043 // Finish node at given position
3044
3045 pp$6.finishNodeAt = function(node, type, pos, loc) {
3046 return finishNodeAt.call(this, node, type, pos, loc)
3047 };
3048
3049 // The algorithm used to determine whether a regexp can appear at a
3050
3051 var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
3052 this.token = token;
3053 this.isExpr = !!isExpr;
3054 this.preserveSpace = !!preserveSpace;
3055 this.override = override;
3056 this.generator = !!generator;
3057 };
3058
3059 var types$1 = {
3060 b_stat: new TokContext("{", false),
3061 b_expr: new TokContext("{", true),
3062 b_tmpl: new TokContext("${", false),
3063 p_stat: new TokContext("(", false),
3064 p_expr: new TokContext("(", true),
3065 q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
3066 f_stat: new TokContext("function", false),
3067 f_expr: new TokContext("function", true),
3068 f_expr_gen: new TokContext("function", true, false, null, true),
3069 f_gen: new TokContext("function", false, false, null, true)
3070 };
3071
3072 var pp$7 = Parser.prototype;
3073
3074 pp$7.initialContext = function() {
3075 return [types$1.b_stat]
3076 };
3077
3078 pp$7.braceIsBlock = function(prevType) {
3079 var parent = this.curContext();
3080 if (parent === types$1.f_expr || parent === types$1.f_stat)
3081 { return true }
3082 if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr))
3083 { return !parent.isExpr }
3084
3085 // The check for `tt.name && exprAllowed` detects whether we are
3086 // after a `yield` or `of` construct. See the `updateContext` for
3087 // `tt.name`.
3088 if (prevType === types._return || prevType === types.name && this.exprAllowed)
3089 { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
3090 if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow)
3091 { return true }
3092 if (prevType === types.braceL)
3093 { return parent === types$1.b_stat }
3094 if (prevType === types._var || prevType === types._const || prevType === types.name)
3095 { return false }
3096 return !this.exprAllowed
3097 };
3098
3099 pp$7.inGeneratorContext = function() {
3100 for (var i = this.context.length - 1; i >= 1; i--) {
3101 var context = this.context[i];
3102 if (context.token === "function")
3103 { return context.generator }
3104 }
3105 return false
3106 };
3107
3108 pp$7.updateContext = function(prevType) {
3109 var update, type = this.type;
3110 if (type.keyword && prevType === types.dot)
3111 { this.exprAllowed = false; }
3112 else if (update = type.updateContext)
3113 { update.call(this, prevType); }
3114 else
3115 { this.exprAllowed = type.beforeExpr; }
3116 };
3117
3118 // Token-specific context update code
3119
3120 types.parenR.updateContext = types.braceR.updateContext = function() {
3121 if (this.context.length === 1) {
3122 this.exprAllowed = true;
3123 return
3124 }
3125 var out = this.context.pop();
3126 if (out === types$1.b_stat && this.curContext().token === "function") {
3127 out = this.context.pop();
3128 }
3129 this.exprAllowed = !out.isExpr;
3130 };
3131
3132 types.braceL.updateContext = function(prevType) {
3133 this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr);
3134 this.exprAllowed = true;
3135 };
3136
3137 types.dollarBraceL.updateContext = function() {
3138 this.context.push(types$1.b_tmpl);
3139 this.exprAllowed = true;
3140 };
3141
3142 types.parenL.updateContext = function(prevType) {
3143 var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while;
3144 this.context.push(statementParens ? types$1.p_stat : types$1.p_expr);
3145 this.exprAllowed = true;
3146 };
3147
3148 types.incDec.updateContext = function() {
3149 // tokExprAllowed stays unchanged
3150 };
3151
3152 types._function.updateContext = types._class.updateContext = function(prevType) {
3153 if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else &&
3154 !(prevType === types._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) &&
3155 !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat))
3156 { this.context.push(types$1.f_expr); }
3157 else
3158 { this.context.push(types$1.f_stat); }
3159 this.exprAllowed = false;
3160 };
3161
3162 types.backQuote.updateContext = function() {
3163 if (this.curContext() === types$1.q_tmpl)
3164 { this.context.pop(); }
3165 else
3166 { this.context.push(types$1.q_tmpl); }
3167 this.exprAllowed = false;
3168 };
3169
3170 types.star.updateContext = function(prevType) {
3171 if (prevType === types._function) {
3172 var index = this.context.length - 1;
3173 if (this.context[index] === types$1.f_expr)
3174 { this.context[index] = types$1.f_expr_gen; }
3175 else
3176 { this.context[index] = types$1.f_gen; }
3177 }
3178 this.exprAllowed = true;
3179 };
3180
3181 types.name.updateContext = function(prevType) {
3182 var allowed = false;
3183 if (this.options.ecmaVersion >= 6 && prevType !== types.dot) {
3184 if (this.value === "of" && !this.exprAllowed ||
3185 this.value === "yield" && this.inGeneratorContext())
3186 { allowed = true; }
3187 }
3188 this.exprAllowed = allowed;
3189 };
3190
3191 // This file contains Unicode properties extracted from the ECMAScript
3192 // specification. The lists are extracted like so:
3193 // $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText)
3194
3195 // #table-binary-unicode-properties
3196 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";
3197 var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic";
3198 var ecma11BinaryProperties = ecma10BinaryProperties;
3199 var unicodeBinaryProperties = {
3200 9: ecma9BinaryProperties,
3201 10: ecma10BinaryProperties,
3202 11: ecma11BinaryProperties
3203 };
3204
3205 // #table-unicode-general-category-values
3206 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";
3207
3208 // #table-unicode-script-values
3209 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";
3210 var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd";
3211 var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho";
3212 var unicodeScriptValues = {
3213 9: ecma9ScriptValues,
3214 10: ecma10ScriptValues,
3215 11: ecma11ScriptValues
3216 };
3217
3218 var data = {};
3219 function buildUnicodeData(ecmaVersion) {
3220 var d = data[ecmaVersion] = {
3221 binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues),
3222 nonBinary: {
3223 General_Category: wordsRegexp(unicodeGeneralCategoryValues),
3224 Script: wordsRegexp(unicodeScriptValues[ecmaVersion])
3225 }
3226 };
3227 d.nonBinary.Script_Extensions = d.nonBinary.Script;
3228
3229 d.nonBinary.gc = d.nonBinary.General_Category;
3230 d.nonBinary.sc = d.nonBinary.Script;
3231 d.nonBinary.scx = d.nonBinary.Script_Extensions;
3232 }
3233 buildUnicodeData(9);
3234 buildUnicodeData(10);
3235 buildUnicodeData(11);
3236
3237 var pp$8 = Parser.prototype;
3238
3239 var RegExpValidationState = function RegExpValidationState(parser) {
3240 this.parser = parser;
3241 this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "");
3242 this.unicodeProperties = data[parser.options.ecmaVersion >= 11 ? 11 : parser.options.ecmaVersion];
3243 this.source = "";
3244 this.flags = "";
3245 this.start = 0;
3246 this.switchU = false;
3247 this.switchN = false;
3248 this.pos = 0;
3249 this.lastIntValue = 0;
3250 this.lastStringValue = "";
3251 this.lastAssertionIsQuantifiable = false;
3252 this.numCapturingParens = 0;
3253 this.maxBackReference = 0;
3254 this.groupNames = [];
3255 this.backReferenceNames = [];
3256 };
3257
3258 RegExpValidationState.prototype.reset = function reset (start, pattern, flags) {
3259 var unicode = flags.indexOf("u") !== -1;
3260 this.start = start | 0;
3261 this.source = pattern + "";
3262 this.flags = flags;
3263 this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
3264 this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
3265 };
3266
3267 RegExpValidationState.prototype.raise = function raise (message) {
3268 this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message));
3269 };
3270
3271 // If u flag is given, this returns the code point at the index (it combines a surrogate pair).
3272 // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
3273 RegExpValidationState.prototype.at = function at (i) {
3274 var s = this.source;
3275 var l = s.length;
3276 if (i >= l) {
3277 return -1
3278 }
3279 var c = s.charCodeAt(i);
3280 if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
3281 return c
3282 }
3283 var next = s.charCodeAt(i + 1);
3284 return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c
3285 };
3286
3287 RegExpValidationState.prototype.nextIndex = function nextIndex (i) {
3288 var s = this.source;
3289 var l = s.length;
3290 if (i >= l) {
3291 return l
3292 }
3293 var c = s.charCodeAt(i), next;
3294 if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l ||
3295 (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) {
3296 return i + 1
3297 }
3298 return i + 2
3299 };
3300
3301 RegExpValidationState.prototype.current = function current () {
3302 return this.at(this.pos)
3303 };
3304
3305 RegExpValidationState.prototype.lookahead = function lookahead () {
3306 return this.at(this.nextIndex(this.pos))
3307 };
3308
3309 RegExpValidationState.prototype.advance = function advance () {
3310 this.pos = this.nextIndex(this.pos);
3311 };
3312
3313 RegExpValidationState.prototype.eat = function eat (ch) {
3314 if (this.current() === ch) {
3315 this.advance();
3316 return true
3317 }
3318 return false
3319 };
3320
3321 function codePointToString(ch) {
3322 if (ch <= 0xFFFF) { return String.fromCharCode(ch) }
3323 ch -= 0x10000;
3324 return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00)
3325 }
3326
3327 /**
3328 * Validate the flags part of a given RegExpLiteral.
3329 *
3330 * @param {RegExpValidationState} state The state to validate RegExp.
3331 * @returns {void}
3332 */
3333 pp$8.validateRegExpFlags = function(state) {
3334 var validFlags = state.validFlags;
3335 var flags = state.flags;
3336
3337 for (var i = 0; i < flags.length; i++) {
3338 var flag = flags.charAt(i);
3339 if (validFlags.indexOf(flag) === -1) {
3340 this.raise(state.start, "Invalid regular expression flag");
3341 }
3342 if (flags.indexOf(flag, i + 1) > -1) {
3343 this.raise(state.start, "Duplicate regular expression flag");
3344 }
3345 }
3346 };
3347
3348 /**
3349 * Validate the pattern part of a given RegExpLiteral.
3350 *
3351 * @param {RegExpValidationState} state The state to validate RegExp.
3352 * @returns {void}
3353 */
3354 pp$8.validateRegExpPattern = function(state) {
3355 this.regexp_pattern(state);
3356
3357 // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
3358 // parsing contains a |GroupName|, reparse with the goal symbol
3359 // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
3360 // exception if _P_ did not conform to the grammar, if any elements of _P_
3361 // were not matched by the parse, or if any Early Error conditions exist.
3362 if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) {
3363 state.switchN = true;
3364 this.regexp_pattern(state);
3365 }
3366 };
3367
3368 // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
3369 pp$8.regexp_pattern = function(state) {
3370 state.pos = 0;
3371 state.lastIntValue = 0;
3372 state.lastStringValue = "";
3373 state.lastAssertionIsQuantifiable = false;
3374 state.numCapturingParens = 0;
3375 state.maxBackReference = 0;
3376 state.groupNames.length = 0;
3377 state.backReferenceNames.length = 0;
3378
3379 this.regexp_disjunction(state);
3380
3381 if (state.pos !== state.source.length) {
3382 // Make the same messages as V8.
3383 if (state.eat(0x29 /* ) */)) {
3384 state.raise("Unmatched ')'");
3385 }
3386 if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) {
3387 state.raise("Lone quantifier brackets");
3388 }
3389 }
3390 if (state.maxBackReference > state.numCapturingParens) {
3391 state.raise("Invalid escape");
3392 }
3393 for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) {
3394 var name = list[i];
3395
3396 if (state.groupNames.indexOf(name) === -1) {
3397 state.raise("Invalid named capture referenced");
3398 }
3399 }
3400 };
3401
3402 // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
3403 pp$8.regexp_disjunction = function(state) {
3404 this.regexp_alternative(state);
3405 while (state.eat(0x7C /* | */)) {
3406 this.regexp_alternative(state);
3407 }
3408
3409 // Make the same message as V8.
3410 if (this.regexp_eatQuantifier(state, true)) {
3411 state.raise("Nothing to repeat");
3412 }
3413 if (state.eat(0x7B /* { */)) {
3414 state.raise("Lone quantifier brackets");
3415 }
3416 };
3417
3418 // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
3419 pp$8.regexp_alternative = function(state) {
3420 while (state.pos < state.source.length && this.regexp_eatTerm(state))
3421 { }
3422 };
3423
3424 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
3425 pp$8.regexp_eatTerm = function(state) {
3426 if (this.regexp_eatAssertion(state)) {
3427 // Handle `QuantifiableAssertion Quantifier` alternative.
3428 // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
3429 // is a QuantifiableAssertion.
3430 if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
3431 // Make the same message as V8.
3432 if (state.switchU) {
3433 state.raise("Invalid quantifier");
3434 }
3435 }
3436 return true
3437 }
3438
3439 if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
3440 this.regexp_eatQuantifier(state);
3441 return true
3442 }
3443
3444 return false
3445 };
3446
3447 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
3448 pp$8.regexp_eatAssertion = function(state) {
3449 var start = state.pos;
3450 state.lastAssertionIsQuantifiable = false;
3451
3452 // ^, $
3453 if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) {
3454 return true
3455 }
3456
3457 // \b \B
3458 if (state.eat(0x5C /* \ */)) {
3459 if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) {
3460 return true
3461 }
3462 state.pos = start;
3463 }
3464
3465 // Lookahead / Lookbehind
3466 if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) {
3467 var lookbehind = false;
3468 if (this.options.ecmaVersion >= 9) {
3469 lookbehind = state.eat(0x3C /* < */);
3470 }
3471 if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) {
3472 this.regexp_disjunction(state);
3473 if (!state.eat(0x29 /* ) */)) {
3474 state.raise("Unterminated group");
3475 }
3476 state.lastAssertionIsQuantifiable = !lookbehind;
3477 return true
3478 }
3479 }
3480
3481 state.pos = start;
3482 return false
3483 };
3484
3485 // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
3486 pp$8.regexp_eatQuantifier = function(state, noError) {
3487 if ( noError === void 0 ) noError = false;
3488
3489 if (this.regexp_eatQuantifierPrefix(state, noError)) {
3490 state.eat(0x3F /* ? */);
3491 return true
3492 }
3493 return false
3494 };
3495
3496 // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
3497 pp$8.regexp_eatQuantifierPrefix = function(state, noError) {
3498 return (
3499 state.eat(0x2A /* * */) ||
3500 state.eat(0x2B /* + */) ||
3501 state.eat(0x3F /* ? */) ||
3502 this.regexp_eatBracedQuantifier(state, noError)
3503 )
3504 };
3505 pp$8.regexp_eatBracedQuantifier = function(state, noError) {
3506 var start = state.pos;
3507 if (state.eat(0x7B /* { */)) {
3508 var min = 0, max = -1;
3509 if (this.regexp_eatDecimalDigits(state)) {
3510 min = state.lastIntValue;
3511 if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) {
3512 max = state.lastIntValue;
3513 }
3514 if (state.eat(0x7D /* } */)) {
3515 // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
3516 if (max !== -1 && max < min && !noError) {
3517 state.raise("numbers out of order in {} quantifier");
3518 }
3519 return true
3520 }
3521 }
3522 if (state.switchU && !noError) {
3523 state.raise("Incomplete quantifier");
3524 }
3525 state.pos = start;
3526 }
3527 return false
3528 };
3529
3530 // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
3531 pp$8.regexp_eatAtom = function(state) {
3532 return (
3533 this.regexp_eatPatternCharacters(state) ||
3534 state.eat(0x2E /* . */) ||
3535 this.regexp_eatReverseSolidusAtomEscape(state) ||
3536 this.regexp_eatCharacterClass(state) ||
3537 this.regexp_eatUncapturingGroup(state) ||
3538 this.regexp_eatCapturingGroup(state)
3539 )
3540 };
3541 pp$8.regexp_eatReverseSolidusAtomEscape = function(state) {
3542 var start = state.pos;
3543 if (state.eat(0x5C /* \ */)) {
3544 if (this.regexp_eatAtomEscape(state)) {
3545 return true
3546 }
3547 state.pos = start;
3548 }
3549 return false
3550 };
3551 pp$8.regexp_eatUncapturingGroup = function(state) {
3552 var start = state.pos;
3553 if (state.eat(0x28 /* ( */)) {
3554 if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) {
3555 this.regexp_disjunction(state);
3556 if (state.eat(0x29 /* ) */)) {
3557 return true
3558 }
3559 state.raise("Unterminated group");
3560 }
3561 state.pos = start;
3562 }
3563 return false
3564 };
3565 pp$8.regexp_eatCapturingGroup = function(state) {
3566 if (state.eat(0x28 /* ( */)) {
3567 if (this.options.ecmaVersion >= 9) {
3568 this.regexp_groupSpecifier(state);
3569 } else if (state.current() === 0x3F /* ? */) {
3570 state.raise("Invalid group");
3571 }
3572 this.regexp_disjunction(state);
3573 if (state.eat(0x29 /* ) */)) {
3574 state.numCapturingParens += 1;
3575 return true
3576 }
3577 state.raise("Unterminated group");
3578 }
3579 return false
3580 };
3581
3582 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
3583 pp$8.regexp_eatExtendedAtom = function(state) {
3584 return (
3585 state.eat(0x2E /* . */) ||
3586 this.regexp_eatReverseSolidusAtomEscape(state) ||
3587 this.regexp_eatCharacterClass(state) ||
3588 this.regexp_eatUncapturingGroup(state) ||
3589 this.regexp_eatCapturingGroup(state) ||
3590 this.regexp_eatInvalidBracedQuantifier(state) ||
3591 this.regexp_eatExtendedPatternCharacter(state)
3592 )
3593 };
3594
3595 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
3596 pp$8.regexp_eatInvalidBracedQuantifier = function(state) {
3597 if (this.regexp_eatBracedQuantifier(state, true)) {
3598 state.raise("Nothing to repeat");
3599 }
3600 return false
3601 };
3602
3603 // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
3604 pp$8.regexp_eatSyntaxCharacter = function(state) {
3605 var ch = state.current();
3606 if (isSyntaxCharacter(ch)) {
3607 state.lastIntValue = ch;
3608 state.advance();
3609 return true
3610 }
3611 return false
3612 };
3613 function isSyntaxCharacter(ch) {
3614 return (
3615 ch === 0x24 /* $ */ ||
3616 ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ ||
3617 ch === 0x2E /* . */ ||
3618 ch === 0x3F /* ? */ ||
3619 ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ ||
3620 ch >= 0x7B /* { */ && ch <= 0x7D /* } */
3621 )
3622 }
3623
3624 // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
3625 // But eat eager.
3626 pp$8.regexp_eatPatternCharacters = function(state) {
3627 var start = state.pos;
3628 var ch = 0;
3629 while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
3630 state.advance();
3631 }
3632 return state.pos !== start
3633 };
3634
3635 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
3636 pp$8.regexp_eatExtendedPatternCharacter = function(state) {
3637 var ch = state.current();
3638 if (
3639 ch !== -1 &&
3640 ch !== 0x24 /* $ */ &&
3641 !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) &&
3642 ch !== 0x2E /* . */ &&
3643 ch !== 0x3F /* ? */ &&
3644 ch !== 0x5B /* [ */ &&
3645 ch !== 0x5E /* ^ */ &&
3646 ch !== 0x7C /* | */
3647 ) {
3648 state.advance();
3649 return true
3650 }
3651 return false
3652 };
3653
3654 // GroupSpecifier[U] ::
3655 // [empty]
3656 // `?` GroupName[?U]
3657 pp$8.regexp_groupSpecifier = function(state) {
3658 if (state.eat(0x3F /* ? */)) {
3659 if (this.regexp_eatGroupName(state)) {
3660 if (state.groupNames.indexOf(state.lastStringValue) !== -1) {
3661 state.raise("Duplicate capture group name");
3662 }
3663 state.groupNames.push(state.lastStringValue);
3664 return
3665 }
3666 state.raise("Invalid group");
3667 }
3668 };
3669
3670 // GroupName[U] ::
3671 // `<` RegExpIdentifierName[?U] `>`
3672 // Note: this updates `state.lastStringValue` property with the eaten name.
3673 pp$8.regexp_eatGroupName = function(state) {
3674 state.lastStringValue = "";
3675 if (state.eat(0x3C /* < */)) {
3676 if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) {
3677 return true
3678 }
3679 state.raise("Invalid capture group name");
3680 }
3681 return false
3682 };
3683
3684 // RegExpIdentifierName[U] ::
3685 // RegExpIdentifierStart[?U]
3686 // RegExpIdentifierName[?U] RegExpIdentifierPart[?U]
3687 // Note: this updates `state.lastStringValue` property with the eaten name.
3688 pp$8.regexp_eatRegExpIdentifierName = function(state) {
3689 state.lastStringValue = "";
3690 if (this.regexp_eatRegExpIdentifierStart(state)) {
3691 state.lastStringValue += codePointToString(state.lastIntValue);
3692 while (this.regexp_eatRegExpIdentifierPart(state)) {
3693 state.lastStringValue += codePointToString(state.lastIntValue);
3694 }
3695 return true
3696 }
3697 return false
3698 };
3699
3700 // RegExpIdentifierStart[U] ::
3701 // UnicodeIDStart
3702 // `$`
3703 // `_`
3704 // `\` RegExpUnicodeEscapeSequence[?U]
3705 pp$8.regexp_eatRegExpIdentifierStart = function(state) {
3706 var start = state.pos;
3707 var ch = state.current();
3708 state.advance();
3709
3710 if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
3711 ch = state.lastIntValue;
3712 }
3713 if (isRegExpIdentifierStart(ch)) {
3714 state.lastIntValue = ch;
3715 return true
3716 }
3717
3718 state.pos = start;
3719 return false
3720 };
3721 function isRegExpIdentifierStart(ch) {
3722 return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */
3723 }
3724
3725 // RegExpIdentifierPart[U] ::
3726 // UnicodeIDContinue
3727 // `$`
3728 // `_`
3729 // `\` RegExpUnicodeEscapeSequence[?U]
3730 // <ZWNJ>
3731 // <ZWJ>
3732 pp$8.regexp_eatRegExpIdentifierPart = function(state) {
3733 var start = state.pos;
3734 var ch = state.current();
3735 state.advance();
3736
3737 if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
3738 ch = state.lastIntValue;
3739 }
3740 if (isRegExpIdentifierPart(ch)) {
3741 state.lastIntValue = ch;
3742 return true
3743 }
3744
3745 state.pos = start;
3746 return false
3747 };
3748 function isRegExpIdentifierPart(ch) {
3749 return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */
3750 }
3751
3752 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
3753 pp$8.regexp_eatAtomEscape = function(state) {
3754 if (
3755 this.regexp_eatBackReference(state) ||
3756 this.regexp_eatCharacterClassEscape(state) ||
3757 this.regexp_eatCharacterEscape(state) ||
3758 (state.switchN && this.regexp_eatKGroupName(state))
3759 ) {
3760 return true
3761 }
3762 if (state.switchU) {
3763 // Make the same message as V8.
3764 if (state.current() === 0x63 /* c */) {
3765 state.raise("Invalid unicode escape");
3766 }
3767 state.raise("Invalid escape");
3768 }
3769 return false
3770 };
3771 pp$8.regexp_eatBackReference = function(state) {
3772 var start = state.pos;
3773 if (this.regexp_eatDecimalEscape(state)) {
3774 var n = state.lastIntValue;
3775 if (state.switchU) {
3776 // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
3777 if (n > state.maxBackReference) {
3778 state.maxBackReference = n;
3779 }
3780 return true
3781 }
3782 if (n <= state.numCapturingParens) {
3783 return true
3784 }
3785 state.pos = start;
3786 }
3787 return false
3788 };
3789 pp$8.regexp_eatKGroupName = function(state) {
3790 if (state.eat(0x6B /* k */)) {
3791 if (this.regexp_eatGroupName(state)) {
3792 state.backReferenceNames.push(state.lastStringValue);
3793 return true
3794 }
3795 state.raise("Invalid named reference");
3796 }
3797 return false
3798 };
3799
3800 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
3801 pp$8.regexp_eatCharacterEscape = function(state) {
3802 return (
3803 this.regexp_eatControlEscape(state) ||
3804 this.regexp_eatCControlLetter(state) ||
3805 this.regexp_eatZero(state) ||
3806 this.regexp_eatHexEscapeSequence(state) ||
3807 this.regexp_eatRegExpUnicodeEscapeSequence(state) ||
3808 (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) ||
3809 this.regexp_eatIdentityEscape(state)
3810 )
3811 };
3812 pp$8.regexp_eatCControlLetter = function(state) {
3813 var start = state.pos;
3814 if (state.eat(0x63 /* c */)) {
3815 if (this.regexp_eatControlLetter(state)) {
3816 return true
3817 }
3818 state.pos = start;
3819 }
3820 return false
3821 };
3822 pp$8.regexp_eatZero = function(state) {
3823 if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) {
3824 state.lastIntValue = 0;
3825 state.advance();
3826 return true
3827 }
3828 return false
3829 };
3830
3831 // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
3832 pp$8.regexp_eatControlEscape = function(state) {
3833 var ch = state.current();
3834 if (ch === 0x74 /* t */) {
3835 state.lastIntValue = 0x09; /* \t */
3836 state.advance();
3837 return true
3838 }
3839 if (ch === 0x6E /* n */) {
3840 state.lastIntValue = 0x0A; /* \n */
3841 state.advance();
3842 return true
3843 }
3844 if (ch === 0x76 /* v */) {
3845 state.lastIntValue = 0x0B; /* \v */
3846 state.advance();
3847 return true
3848 }
3849 if (ch === 0x66 /* f */) {
3850 state.lastIntValue = 0x0C; /* \f */
3851 state.advance();
3852 return true
3853 }
3854 if (ch === 0x72 /* r */) {
3855 state.lastIntValue = 0x0D; /* \r */
3856 state.advance();
3857 return true
3858 }
3859 return false
3860 };
3861
3862 // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
3863 pp$8.regexp_eatControlLetter = function(state) {
3864 var ch = state.current();
3865 if (isControlLetter(ch)) {
3866 state.lastIntValue = ch % 0x20;
3867 state.advance();
3868 return true
3869 }
3870 return false
3871 };
3872 function isControlLetter(ch) {
3873 return (
3874 (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) ||
3875 (ch >= 0x61 /* a */ && ch <= 0x7A /* z */)
3876 )
3877 }
3878
3879 // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
3880 pp$8.regexp_eatRegExpUnicodeEscapeSequence = function(state) {
3881 var start = state.pos;
3882
3883 if (state.eat(0x75 /* u */)) {
3884 if (this.regexp_eatFixedHexDigits(state, 4)) {
3885 var lead = state.lastIntValue;
3886 if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) {
3887 var leadSurrogateEnd = state.pos;
3888 if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) {
3889 var trail = state.lastIntValue;
3890 if (trail >= 0xDC00 && trail <= 0xDFFF) {
3891 state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
3892 return true
3893 }
3894 }
3895 state.pos = leadSurrogateEnd;
3896 state.lastIntValue = lead;
3897 }
3898 return true
3899 }
3900 if (
3901 state.switchU &&
3902 state.eat(0x7B /* { */) &&
3903 this.regexp_eatHexDigits(state) &&
3904 state.eat(0x7D /* } */) &&
3905 isValidUnicode(state.lastIntValue)
3906 ) {
3907 return true
3908 }
3909 if (state.switchU) {
3910 state.raise("Invalid unicode escape");
3911 }
3912 state.pos = start;
3913 }
3914
3915 return false
3916 };
3917 function isValidUnicode(ch) {
3918 return ch >= 0 && ch <= 0x10FFFF
3919 }
3920
3921 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
3922 pp$8.regexp_eatIdentityEscape = function(state) {
3923 if (state.switchU) {
3924 if (this.regexp_eatSyntaxCharacter(state)) {
3925 return true
3926 }
3927 if (state.eat(0x2F /* / */)) {
3928 state.lastIntValue = 0x2F; /* / */
3929 return true
3930 }
3931 return false
3932 }
3933
3934 var ch = state.current();
3935 if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) {
3936 state.lastIntValue = ch;
3937 state.advance();
3938 return true
3939 }
3940
3941 return false
3942 };
3943
3944 // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
3945 pp$8.regexp_eatDecimalEscape = function(state) {
3946 state.lastIntValue = 0;
3947 var ch = state.current();
3948 if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) {
3949 do {
3950 state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
3951 state.advance();
3952 } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */)
3953 return true
3954 }
3955 return false
3956 };
3957
3958 // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
3959 pp$8.regexp_eatCharacterClassEscape = function(state) {
3960 var ch = state.current();
3961
3962 if (isCharacterClassEscape(ch)) {
3963 state.lastIntValue = -1;
3964 state.advance();
3965 return true
3966 }
3967
3968 if (
3969 state.switchU &&
3970 this.options.ecmaVersion >= 9 &&
3971 (ch === 0x50 /* P */ || ch === 0x70 /* p */)
3972 ) {
3973 state.lastIntValue = -1;
3974 state.advance();
3975 if (
3976 state.eat(0x7B /* { */) &&
3977 this.regexp_eatUnicodePropertyValueExpression(state) &&
3978 state.eat(0x7D /* } */)
3979 ) {
3980 return true
3981 }
3982 state.raise("Invalid property name");
3983 }
3984
3985 return false
3986 };
3987 function isCharacterClassEscape(ch) {
3988 return (
3989 ch === 0x64 /* d */ ||
3990 ch === 0x44 /* D */ ||
3991 ch === 0x73 /* s */ ||
3992 ch === 0x53 /* S */ ||
3993 ch === 0x77 /* w */ ||
3994 ch === 0x57 /* W */
3995 )
3996 }
3997
3998 // UnicodePropertyValueExpression ::
3999 // UnicodePropertyName `=` UnicodePropertyValue
4000 // LoneUnicodePropertyNameOrValue
4001 pp$8.regexp_eatUnicodePropertyValueExpression = function(state) {
4002 var start = state.pos;
4003
4004 // UnicodePropertyName `=` UnicodePropertyValue
4005 if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) {
4006 var name = state.lastStringValue;
4007 if (this.regexp_eatUnicodePropertyValue(state)) {
4008 var value = state.lastStringValue;
4009 this.regexp_validateUnicodePropertyNameAndValue(state, name, value);
4010 return true
4011 }
4012 }
4013 state.pos = start;
4014
4015 // LoneUnicodePropertyNameOrValue
4016 if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
4017 var nameOrValue = state.lastStringValue;
4018 this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue);
4019 return true
4020 }
4021 return false
4022 };
4023 pp$8.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
4024 if (!has(state.unicodeProperties.nonBinary, name))
4025 { state.raise("Invalid property name"); }
4026 if (!state.unicodeProperties.nonBinary[name].test(value))
4027 { state.raise("Invalid property value"); }
4028 };
4029 pp$8.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
4030 if (!state.unicodeProperties.binary.test(nameOrValue))
4031 { state.raise("Invalid property name"); }
4032 };
4033
4034 // UnicodePropertyName ::
4035 // UnicodePropertyNameCharacters
4036 pp$8.regexp_eatUnicodePropertyName = function(state) {
4037 var ch = 0;
4038 state.lastStringValue = "";
4039 while (isUnicodePropertyNameCharacter(ch = state.current())) {
4040 state.lastStringValue += codePointToString(ch);
4041 state.advance();
4042 }
4043 return state.lastStringValue !== ""
4044 };
4045 function isUnicodePropertyNameCharacter(ch) {
4046 return isControlLetter(ch) || ch === 0x5F /* _ */
4047 }
4048
4049 // UnicodePropertyValue ::
4050 // UnicodePropertyValueCharacters
4051 pp$8.regexp_eatUnicodePropertyValue = function(state) {
4052 var ch = 0;
4053 state.lastStringValue = "";
4054 while (isUnicodePropertyValueCharacter(ch = state.current())) {
4055 state.lastStringValue += codePointToString(ch);
4056 state.advance();
4057 }
4058 return state.lastStringValue !== ""
4059 };
4060 function isUnicodePropertyValueCharacter(ch) {
4061 return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch)
4062 }
4063
4064 // LoneUnicodePropertyNameOrValue ::
4065 // UnicodePropertyValueCharacters
4066 pp$8.regexp_eatLoneUnicodePropertyNameOrValue = function(state) {
4067 return this.regexp_eatUnicodePropertyValue(state)
4068 };
4069
4070 // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
4071 pp$8.regexp_eatCharacterClass = function(state) {
4072 if (state.eat(0x5B /* [ */)) {
4073 state.eat(0x5E /* ^ */);
4074 this.regexp_classRanges(state);
4075 if (state.eat(0x5D /* ] */)) {
4076 return true
4077 }
4078 // Unreachable since it threw "unterminated regular expression" error before.
4079 state.raise("Unterminated character class");
4080 }
4081 return false
4082 };
4083
4084 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
4085 // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
4086 // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
4087 pp$8.regexp_classRanges = function(state) {
4088 while (this.regexp_eatClassAtom(state)) {
4089 var left = state.lastIntValue;
4090 if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) {
4091 var right = state.lastIntValue;
4092 if (state.switchU && (left === -1 || right === -1)) {
4093 state.raise("Invalid character class");
4094 }
4095 if (left !== -1 && right !== -1 && left > right) {
4096 state.raise("Range out of order in character class");
4097 }
4098 }
4099 }
4100 };
4101
4102 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
4103 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
4104 pp$8.regexp_eatClassAtom = function(state) {
4105 var start = state.pos;
4106
4107 if (state.eat(0x5C /* \ */)) {
4108 if (this.regexp_eatClassEscape(state)) {
4109 return true
4110 }
4111 if (state.switchU) {
4112 // Make the same message as V8.
4113 var ch$1 = state.current();
4114 if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
4115 state.raise("Invalid class escape");
4116 }
4117 state.raise("Invalid escape");
4118 }
4119 state.pos = start;
4120 }
4121
4122 var ch = state.current();
4123 if (ch !== 0x5D /* ] */) {
4124 state.lastIntValue = ch;
4125 state.advance();
4126 return true
4127 }
4128
4129 return false
4130 };
4131
4132 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
4133 pp$8.regexp_eatClassEscape = function(state) {
4134 var start = state.pos;
4135
4136 if (state.eat(0x62 /* b */)) {
4137 state.lastIntValue = 0x08; /* <BS> */
4138 return true
4139 }
4140
4141 if (state.switchU && state.eat(0x2D /* - */)) {
4142 state.lastIntValue = 0x2D; /* - */
4143 return true
4144 }
4145
4146 if (!state.switchU && state.eat(0x63 /* c */)) {
4147 if (this.regexp_eatClassControlLetter(state)) {
4148 return true
4149 }
4150 state.pos = start;
4151 }
4152
4153 return (
4154 this.regexp_eatCharacterClassEscape(state) ||
4155 this.regexp_eatCharacterEscape(state)
4156 )
4157 };
4158
4159 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
4160 pp$8.regexp_eatClassControlLetter = function(state) {
4161 var ch = state.current();
4162 if (isDecimalDigit(ch) || ch === 0x5F /* _ */) {
4163 state.lastIntValue = ch % 0x20;
4164 state.advance();
4165 return true
4166 }
4167 return false
4168 };
4169
4170 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
4171 pp$8.regexp_eatHexEscapeSequence = function(state) {
4172 var start = state.pos;
4173 if (state.eat(0x78 /* x */)) {
4174 if (this.regexp_eatFixedHexDigits(state, 2)) {
4175 return true
4176 }
4177 if (state.switchU) {
4178 state.raise("Invalid escape");
4179 }
4180 state.pos = start;
4181 }
4182 return false
4183 };
4184
4185 // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
4186 pp$8.regexp_eatDecimalDigits = function(state) {
4187 var start = state.pos;
4188 var ch = 0;
4189 state.lastIntValue = 0;
4190 while (isDecimalDigit(ch = state.current())) {
4191 state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
4192 state.advance();
4193 }
4194 return state.pos !== start
4195 };
4196 function isDecimalDigit(ch) {
4197 return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */
4198 }
4199
4200 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
4201 pp$8.regexp_eatHexDigits = function(state) {
4202 var start = state.pos;
4203 var ch = 0;
4204 state.lastIntValue = 0;
4205 while (isHexDigit(ch = state.current())) {
4206 state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
4207 state.advance();
4208 }
4209 return state.pos !== start
4210 };
4211 function isHexDigit(ch) {
4212 return (
4213 (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) ||
4214 (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) ||
4215 (ch >= 0x61 /* a */ && ch <= 0x66 /* f */)
4216 )
4217 }
4218 function hexToInt(ch) {
4219 if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) {
4220 return 10 + (ch - 0x41 /* A */)
4221 }
4222 if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) {
4223 return 10 + (ch - 0x61 /* a */)
4224 }
4225 return ch - 0x30 /* 0 */
4226 }
4227
4228 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
4229 // Allows only 0-377(octal) i.e. 0-255(decimal).
4230 pp$8.regexp_eatLegacyOctalEscapeSequence = function(state) {
4231 if (this.regexp_eatOctalDigit(state)) {
4232 var n1 = state.lastIntValue;
4233 if (this.regexp_eatOctalDigit(state)) {
4234 var n2 = state.lastIntValue;
4235 if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
4236 state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
4237 } else {
4238 state.lastIntValue = n1 * 8 + n2;
4239 }
4240 } else {
4241 state.lastIntValue = n1;
4242 }
4243 return true
4244 }
4245 return false
4246 };
4247
4248 // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
4249 pp$8.regexp_eatOctalDigit = function(state) {
4250 var ch = state.current();
4251 if (isOctalDigit(ch)) {
4252 state.lastIntValue = ch - 0x30; /* 0 */
4253 state.advance();
4254 return true
4255 }
4256 state.lastIntValue = 0;
4257 return false
4258 };
4259 function isOctalDigit(ch) {
4260 return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */
4261 }
4262
4263 // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
4264 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
4265 // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
4266 pp$8.regexp_eatFixedHexDigits = function(state, length) {
4267 var start = state.pos;
4268 state.lastIntValue = 0;
4269 for (var i = 0; i < length; ++i) {
4270 var ch = state.current();
4271 if (!isHexDigit(ch)) {
4272 state.pos = start;
4273 return false
4274 }
4275 state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
4276 state.advance();
4277 }
4278 return true
4279 };
4280
4281 // Object type used to represent tokens. Note that normally, tokens
4282 // simply exist as properties on the parser object. This is only
4283 // used for the onToken callback and the external tokenizer.
4284
4285 var Token = function Token(p) {
4286 this.type = p.type;
4287 this.value = p.value;
4288 this.start = p.start;
4289 this.end = p.end;
4290 if (p.options.locations)
4291 { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
4292 if (p.options.ranges)
4293 { this.range = [p.start, p.end]; }
4294 };
4295
4296 // ## Tokenizer
4297
4298 var pp$9 = Parser.prototype;
4299
4300 // Move to the next token
4301
4302 pp$9.next = function(ignoreEscapeSequenceInKeyword) {
4303 if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc)
4304 { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); }
4305 if (this.options.onToken)
4306 { this.options.onToken(new Token(this)); }
4307
4308 this.lastTokEnd = this.end;
4309 this.lastTokStart = this.start;
4310 this.lastTokEndLoc = this.endLoc;
4311 this.lastTokStartLoc = this.startLoc;
4312 this.nextToken();
4313 };
4314
4315 pp$9.getToken = function() {
4316 this.next();
4317 return new Token(this)
4318 };
4319
4320 // If we're in an ES6 environment, make parsers iterable
4321 if (typeof Symbol !== "undefined")
4322 { pp$9[Symbol.iterator] = function() {
4323 var this$1 = this;
4324
4325 return {
4326 next: function () {
4327 var token = this$1.getToken();
4328 return {
4329 done: token.type === types.eof,
4330 value: token
4331 }
4332 }
4333 }
4334 }; }
4335
4336 // Toggle strict mode. Re-reads the next number or string to please
4337 // pedantic tests (`"use strict"; 010;` should fail).
4338
4339 pp$9.curContext = function() {
4340 return this.context[this.context.length - 1]
4341 };
4342
4343 // Read a single token, updating the parser object's token-related
4344 // properties.
4345
4346 pp$9.nextToken = function() {
4347 var curContext = this.curContext();
4348 if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }
4349
4350 this.start = this.pos;
4351 if (this.options.locations) { this.startLoc = this.curPosition(); }
4352 if (this.pos >= this.input.length) { return this.finishToken(types.eof) }
4353
4354 if (curContext.override) { return curContext.override(this) }
4355 else { this.readToken(this.fullCharCodeAtPos()); }
4356 };
4357
4358 pp$9.readToken = function(code) {
4359 // Identifier or keyword. '\uXXXX' sequences are allowed in
4360 // identifiers, so '\' also dispatches to that.
4361 if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
4362 { return this.readWord() }
4363
4364 return this.getTokenFromCode(code)
4365 };
4366
4367 pp$9.fullCharCodeAtPos = function() {
4368 var code = this.input.charCodeAt(this.pos);
4369 if (code <= 0xd7ff || code >= 0xe000) { return code }
4370 var next = this.input.charCodeAt(this.pos + 1);
4371 return (code << 10) + next - 0x35fdc00
4372 };
4373
4374 pp$9.skipBlockComment = function() {
4375 var startLoc = this.options.onComment && this.curPosition();
4376 var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
4377 if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
4378 this.pos = end + 2;
4379 if (this.options.locations) {
4380 lineBreakG.lastIndex = start;
4381 var match;
4382 while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
4383 ++this.curLine;
4384 this.lineStart = match.index + match[0].length;
4385 }
4386 }
4387 if (this.options.onComment)
4388 { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
4389 startLoc, this.curPosition()); }
4390 };
4391
4392 pp$9.skipLineComment = function(startSkip) {
4393 var start = this.pos;
4394 var startLoc = this.options.onComment && this.curPosition();
4395 var ch = this.input.charCodeAt(this.pos += startSkip);
4396 while (this.pos < this.input.length && !isNewLine(ch)) {
4397 ch = this.input.charCodeAt(++this.pos);
4398 }
4399 if (this.options.onComment)
4400 { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
4401 startLoc, this.curPosition()); }
4402 };
4403
4404 // Called at the start of the parse and after every token. Skips
4405 // whitespace and comments, and.
4406
4407 pp$9.skipSpace = function() {
4408 loop: while (this.pos < this.input.length) {
4409 var ch = this.input.charCodeAt(this.pos);
4410 switch (ch) {
4411 case 32: case 160: // ' '
4412 ++this.pos;
4413 break
4414 case 13:
4415 if (this.input.charCodeAt(this.pos + 1) === 10) {
4416 ++this.pos;
4417 }
4418 case 10: case 8232: case 8233:
4419 ++this.pos;
4420 if (this.options.locations) {
4421 ++this.curLine;
4422 this.lineStart = this.pos;
4423 }
4424 break
4425 case 47: // '/'
4426 switch (this.input.charCodeAt(this.pos + 1)) {
4427 case 42: // '*'
4428 this.skipBlockComment();
4429 break
4430 case 47:
4431 this.skipLineComment(2);
4432 break
4433 default:
4434 break loop
4435 }
4436 break
4437 default:
4438 if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
4439 ++this.pos;
4440 } else {
4441 break loop
4442 }
4443 }
4444 }
4445 };
4446
4447 // Called at the end of every token. Sets `end`, `val`, and
4448 // maintains `context` and `exprAllowed`, and skips the space after
4449 // the token, so that the next one's `start` will point at the
4450 // right position.
4451
4452 pp$9.finishToken = function(type, val) {
4453 this.end = this.pos;
4454 if (this.options.locations) { this.endLoc = this.curPosition(); }
4455 var prevType = this.type;
4456 this.type = type;
4457 this.value = val;
4458
4459 this.updateContext(prevType);
4460 };
4461
4462 // ### Token reading
4463
4464 // This is the function that is called to fetch the next token. It
4465 // is somewhat obscure, because it works in character codes rather
4466 // than characters, and because operator parsing has been inlined
4467 // into it.
4468 //
4469 // All in the name of speed.
4470 //
4471 pp$9.readToken_dot = function() {
4472 var next = this.input.charCodeAt(this.pos + 1);
4473 if (next >= 48 && next <= 57) { return this.readNumber(true) }
4474 var next2 = this.input.charCodeAt(this.pos + 2);
4475 if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
4476 this.pos += 3;
4477 return this.finishToken(types.ellipsis)
4478 } else {
4479 ++this.pos;
4480 return this.finishToken(types.dot)
4481 }
4482 };
4483
4484 pp$9.readToken_slash = function() { // '/'
4485 var next = this.input.charCodeAt(this.pos + 1);
4486 if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
4487 if (next === 61) { return this.finishOp(types.assign, 2) }
4488 return this.finishOp(types.slash, 1)
4489 };
4490
4491 pp$9.readToken_mult_modulo_exp = function(code) { // '%*'
4492 var next = this.input.charCodeAt(this.pos + 1);
4493 var size = 1;
4494 var tokentype = code === 42 ? types.star : types.modulo;
4495
4496 // exponentiation operator ** and **=
4497 if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
4498 ++size;
4499 tokentype = types.starstar;
4500 next = this.input.charCodeAt(this.pos + 2);
4501 }
4502
4503 if (next === 61) { return this.finishOp(types.assign, size + 1) }
4504 return this.finishOp(tokentype, size)
4505 };
4506
4507 pp$9.readToken_pipe_amp = function(code) { // '|&'
4508 var next = this.input.charCodeAt(this.pos + 1);
4509 if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) }
4510 if (next === 61) { return this.finishOp(types.assign, 2) }
4511 return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1)
4512 };
4513
4514 pp$9.readToken_caret = function() { // '^'
4515 var next = this.input.charCodeAt(this.pos + 1);
4516 if (next === 61) { return this.finishOp(types.assign, 2) }
4517 return this.finishOp(types.bitwiseXOR, 1)
4518 };
4519
4520 pp$9.readToken_plus_min = function(code) { // '+-'
4521 var next = this.input.charCodeAt(this.pos + 1);
4522 if (next === code) {
4523 if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 &&
4524 (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
4525 // A `-->` line comment
4526 this.skipLineComment(3);
4527 this.skipSpace();
4528 return this.nextToken()
4529 }
4530 return this.finishOp(types.incDec, 2)
4531 }
4532 if (next === 61) { return this.finishOp(types.assign, 2) }
4533 return this.finishOp(types.plusMin, 1)
4534 };
4535
4536 pp$9.readToken_lt_gt = function(code) { // '<>'
4537 var next = this.input.charCodeAt(this.pos + 1);
4538 var size = 1;
4539 if (next === code) {
4540 size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
4541 if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) }
4542 return this.finishOp(types.bitShift, size)
4543 }
4544 if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 &&
4545 this.input.charCodeAt(this.pos + 3) === 45) {
4546 // `<!--`, an XML-style comment that should be interpreted as a line comment
4547 this.skipLineComment(4);
4548 this.skipSpace();
4549 return this.nextToken()
4550 }
4551 if (next === 61) { size = 2; }
4552 return this.finishOp(types.relational, size)
4553 };
4554
4555 pp$9.readToken_eq_excl = function(code) { // '=!'
4556 var next = this.input.charCodeAt(this.pos + 1);
4557 if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
4558 if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
4559 this.pos += 2;
4560 return this.finishToken(types.arrow)
4561 }
4562 return this.finishOp(code === 61 ? types.eq : types.prefix, 1)
4563 };
4564
4565 pp$9.getTokenFromCode = function(code) {
4566 switch (code) {
4567 // The interpretation of a dot depends on whether it is followed
4568 // by a digit or another two dots.
4569 case 46: // '.'
4570 return this.readToken_dot()
4571
4572 // Punctuation tokens.
4573 case 40: ++this.pos; return this.finishToken(types.parenL)
4574 case 41: ++this.pos; return this.finishToken(types.parenR)
4575 case 59: ++this.pos; return this.finishToken(types.semi)
4576 case 44: ++this.pos; return this.finishToken(types.comma)
4577 case 91: ++this.pos; return this.finishToken(types.bracketL)
4578 case 93: ++this.pos; return this.finishToken(types.bracketR)
4579 case 123: ++this.pos; return this.finishToken(types.braceL)
4580 case 125: ++this.pos; return this.finishToken(types.braceR)
4581 case 58: ++this.pos; return this.finishToken(types.colon)
4582 case 63: ++this.pos; return this.finishToken(types.question)
4583
4584 case 96: // '`'
4585 if (this.options.ecmaVersion < 6) { break }
4586 ++this.pos;
4587 return this.finishToken(types.backQuote)
4588
4589 case 48: // '0'
4590 var next = this.input.charCodeAt(this.pos + 1);
4591 if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number
4592 if (this.options.ecmaVersion >= 6) {
4593 if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number
4594 if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number
4595 }
4596
4597 // Anything else beginning with a digit is an integer, octal
4598 // number, or float.
4599 case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
4600 return this.readNumber(false)
4601
4602 // Quotes produce strings.
4603 case 34: case 39: // '"', "'"
4604 return this.readString(code)
4605
4606 // Operators are parsed inline in tiny state machines. '=' (61) is
4607 // often referred to. `finishOp` simply skips the amount of
4608 // characters it is given as second argument, and returns a token
4609 // of the type given by its first argument.
4610
4611 case 47: // '/'
4612 return this.readToken_slash()
4613
4614 case 37: case 42: // '%*'
4615 return this.readToken_mult_modulo_exp(code)
4616
4617 case 124: case 38: // '|&'
4618 return this.readToken_pipe_amp(code)
4619
4620 case 94: // '^'
4621 return this.readToken_caret()
4622
4623 case 43: case 45: // '+-'
4624 return this.readToken_plus_min(code)
4625
4626 case 60: case 62: // '<>'
4627 return this.readToken_lt_gt(code)
4628
4629 case 61: case 33: // '=!'
4630 return this.readToken_eq_excl(code)
4631
4632 case 126: // '~'
4633 return this.finishOp(types.prefix, 1)
4634 }
4635
4636 this.raise(this.pos, "Unexpected character '" + codePointToString$1(code) + "'");
4637 };
4638
4639 pp$9.finishOp = function(type, size) {
4640 var str = this.input.slice(this.pos, this.pos + size);
4641 this.pos += size;
4642 return this.finishToken(type, str)
4643 };
4644
4645 pp$9.readRegexp = function() {
4646 var escaped, inClass, start = this.pos;
4647 for (;;) {
4648 if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); }
4649 var ch = this.input.charAt(this.pos);
4650 if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); }
4651 if (!escaped) {
4652 if (ch === "[") { inClass = true; }
4653 else if (ch === "]" && inClass) { inClass = false; }
4654 else if (ch === "/" && !inClass) { break }
4655 escaped = ch === "\\";
4656 } else { escaped = false; }
4657 ++this.pos;
4658 }
4659 var pattern = this.input.slice(start, this.pos);
4660 ++this.pos;
4661 var flagsStart = this.pos;
4662 var flags = this.readWord1();
4663 if (this.containsEsc) { this.unexpected(flagsStart); }
4664
4665 // Validate pattern
4666 var state = this.regexpState || (this.regexpState = new RegExpValidationState(this));
4667 state.reset(start, pattern, flags);
4668 this.validateRegExpFlags(state);
4669 this.validateRegExpPattern(state);
4670
4671 // Create Literal#value property value.
4672 var value = null;
4673 try {
4674 value = new RegExp(pattern, flags);
4675 } catch (e) {
4676 // ESTree requires null if it failed to instantiate RegExp object.
4677 // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral
4678 }
4679
4680 return this.finishToken(types.regexp, {pattern: pattern, flags: flags, value: value})
4681 };
4682
4683 // Read an integer in the given radix. Return null if zero digits
4684 // were read, the integer value otherwise. When `len` is given, this
4685 // will return `null` unless the integer has exactly `len` digits.
4686
4687 pp$9.readInt = function(radix, len) {
4688 var start = this.pos, total = 0;
4689 for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
4690 var code = this.input.charCodeAt(this.pos), val = (void 0);
4691 if (code >= 97) { val = code - 97 + 10; } // a
4692 else if (code >= 65) { val = code - 65 + 10; } // A
4693 else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
4694 else { val = Infinity; }
4695 if (val >= radix) { break }
4696 ++this.pos;
4697 total = total * radix + val;
4698 }
4699 if (this.pos === start || len != null && this.pos - start !== len) { return null }
4700
4701 return total
4702 };
4703
4704 pp$9.readRadixNumber = function(radix) {
4705 var start = this.pos;
4706 this.pos += 2; // 0x
4707 var val = this.readInt(radix);
4708 if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
4709 if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
4710 val = typeof BigInt !== "undefined" ? BigInt(this.input.slice(start, this.pos)) : null;
4711 ++this.pos;
4712 } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4713 return this.finishToken(types.num, val)
4714 };
4715
4716 // Read an integer, octal integer, or floating-point number.
4717
4718 pp$9.readNumber = function(startsWithDot) {
4719 var start = this.pos;
4720 if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number"); }
4721 var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48;
4722 if (octal && this.strict) { this.raise(start, "Invalid number"); }
4723 var next = this.input.charCodeAt(this.pos);
4724 if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
4725 var str$1 = this.input.slice(start, this.pos);
4726 var val$1 = typeof BigInt !== "undefined" ? BigInt(str$1) : null;
4727 ++this.pos;
4728 if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4729 return this.finishToken(types.num, val$1)
4730 }
4731 if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; }
4732 if (next === 46 && !octal) { // '.'
4733 ++this.pos;
4734 this.readInt(10);
4735 next = this.input.charCodeAt(this.pos);
4736 }
4737 if ((next === 69 || next === 101) && !octal) { // 'eE'
4738 next = this.input.charCodeAt(++this.pos);
4739 if (next === 43 || next === 45) { ++this.pos; } // '+-'
4740 if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
4741 }
4742 if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4743
4744 var str = this.input.slice(start, this.pos);
4745 var val = octal ? parseInt(str, 8) : parseFloat(str);
4746 return this.finishToken(types.num, val)
4747 };
4748
4749 // Read a string value, interpreting backslash-escapes.
4750
4751 pp$9.readCodePoint = function() {
4752 var ch = this.input.charCodeAt(this.pos), code;
4753
4754 if (ch === 123) { // '{'
4755 if (this.options.ecmaVersion < 6) { this.unexpected(); }
4756 var codePos = ++this.pos;
4757 code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
4758 ++this.pos;
4759 if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
4760 } else {
4761 code = this.readHexChar(4);
4762 }
4763 return code
4764 };
4765
4766 function codePointToString$1(code) {
4767 // UTF-16 Decoding
4768 if (code <= 0xFFFF) { return String.fromCharCode(code) }
4769 code -= 0x10000;
4770 return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
4771 }
4772
4773 pp$9.readString = function(quote) {
4774 var out = "", chunkStart = ++this.pos;
4775 for (;;) {
4776 if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); }
4777 var ch = this.input.charCodeAt(this.pos);
4778 if (ch === quote) { break }
4779 if (ch === 92) { // '\'
4780 out += this.input.slice(chunkStart, this.pos);
4781 out += this.readEscapedChar(false);
4782 chunkStart = this.pos;
4783 } else {
4784 if (isNewLine(ch, this.options.ecmaVersion >= 10)) { this.raise(this.start, "Unterminated string constant"); }
4785 ++this.pos;
4786 }
4787 }
4788 out += this.input.slice(chunkStart, this.pos++);
4789 return this.finishToken(types.string, out)
4790 };
4791
4792 // Reads template string tokens.
4793
4794 var INVALID_TEMPLATE_ESCAPE_ERROR = {};
4795
4796 pp$9.tryReadTemplateToken = function() {
4797 this.inTemplateElement = true;
4798 try {
4799 this.readTmplToken();
4800 } catch (err) {
4801 if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
4802 this.readInvalidTemplateToken();
4803 } else {
4804 throw err
4805 }
4806 }
4807
4808 this.inTemplateElement = false;
4809 };
4810
4811 pp$9.invalidStringToken = function(position, message) {
4812 if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
4813 throw INVALID_TEMPLATE_ESCAPE_ERROR
4814 } else {
4815 this.raise(position, message);
4816 }
4817 };
4818
4819 pp$9.readTmplToken = function() {
4820 var out = "", chunkStart = this.pos;
4821 for (;;) {
4822 if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); }
4823 var ch = this.input.charCodeAt(this.pos);
4824 if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${'
4825 if (this.pos === this.start && (this.type === types.template || this.type === types.invalidTemplate)) {
4826 if (ch === 36) {
4827 this.pos += 2;
4828 return this.finishToken(types.dollarBraceL)
4829 } else {
4830 ++this.pos;
4831 return this.finishToken(types.backQuote)
4832 }
4833 }
4834 out += this.input.slice(chunkStart, this.pos);
4835 return this.finishToken(types.template, out)
4836 }
4837 if (ch === 92) { // '\'
4838 out += this.input.slice(chunkStart, this.pos);
4839 out += this.readEscapedChar(true);
4840 chunkStart = this.pos;
4841 } else if (isNewLine(ch)) {
4842 out += this.input.slice(chunkStart, this.pos);
4843 ++this.pos;
4844 switch (ch) {
4845 case 13:
4846 if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; }
4847 case 10:
4848 out += "\n";
4849 break
4850 default:
4851 out += String.fromCharCode(ch);
4852 break
4853 }
4854 if (this.options.locations) {
4855 ++this.curLine;
4856 this.lineStart = this.pos;
4857 }
4858 chunkStart = this.pos;
4859 } else {
4860 ++this.pos;
4861 }
4862 }
4863 };
4864
4865 // Reads a template token to search for the end, without validating any escape sequences
4866 pp$9.readInvalidTemplateToken = function() {
4867 for (; this.pos < this.input.length; this.pos++) {
4868 switch (this.input[this.pos]) {
4869 case "\\":
4870 ++this.pos;
4871 break
4872
4873 case "$":
4874 if (this.input[this.pos + 1] !== "{") {
4875 break
4876 }
4877 // falls through
4878
4879 case "`":
4880 return this.finishToken(types.invalidTemplate, this.input.slice(this.start, this.pos))
4881
4882 // no default
4883 }
4884 }
4885 this.raise(this.start, "Unterminated template");
4886 };
4887
4888 // Used to read escaped characters
4889
4890 pp$9.readEscapedChar = function(inTemplate) {
4891 var ch = this.input.charCodeAt(++this.pos);
4892 ++this.pos;
4893 switch (ch) {
4894 case 110: return "\n" // 'n' -> '\n'
4895 case 114: return "\r" // 'r' -> '\r'
4896 case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
4897 case 117: return codePointToString$1(this.readCodePoint()) // 'u'
4898 case 116: return "\t" // 't' -> '\t'
4899 case 98: return "\b" // 'b' -> '\b'
4900 case 118: return "\u000b" // 'v' -> '\u000b'
4901 case 102: return "\f" // 'f' -> '\f'
4902 case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
4903 case 10: // ' \n'
4904 if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
4905 return ""
4906 case 56:
4907 case 57:
4908 if (inTemplate) {
4909 var codePos = this.pos - 1;
4910
4911 this.invalidStringToken(
4912 codePos,
4913 "Invalid escape sequence in template string"
4914 );
4915
4916 return null
4917 }
4918 default:
4919 if (ch >= 48 && ch <= 55) {
4920 var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
4921 var octal = parseInt(octalStr, 8);
4922 if (octal > 255) {
4923 octalStr = octalStr.slice(0, -1);
4924 octal = parseInt(octalStr, 8);
4925 }
4926 this.pos += octalStr.length - 1;
4927 ch = this.input.charCodeAt(this.pos);
4928 if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
4929 this.invalidStringToken(
4930 this.pos - 1 - octalStr.length,
4931 inTemplate
4932 ? "Octal literal in template string"
4933 : "Octal literal in strict mode"
4934 );
4935 }
4936 return String.fromCharCode(octal)
4937 }
4938 if (isNewLine(ch)) {
4939 // Unicode new line characters after \ get removed from output in both
4940 // template literals and strings
4941 return ""
4942 }
4943 return String.fromCharCode(ch)
4944 }
4945 };
4946
4947 // Used to read character escape sequences ('\x', '\u', '\U').
4948
4949 pp$9.readHexChar = function(len) {
4950 var codePos = this.pos;
4951 var n = this.readInt(16, len);
4952 if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
4953 return n
4954 };
4955
4956 // Read an identifier, and return it as a string. Sets `this.containsEsc`
4957 // to whether the word contained a '\u' escape.
4958 //
4959 // Incrementally adds only escaped chars, adding other chunks as-is
4960 // as a micro-optimization.
4961
4962 pp$9.readWord1 = function() {
4963 this.containsEsc = false;
4964 var word = "", first = true, chunkStart = this.pos;
4965 var astral = this.options.ecmaVersion >= 6;
4966 while (this.pos < this.input.length) {
4967 var ch = this.fullCharCodeAtPos();
4968 if (isIdentifierChar(ch, astral)) {
4969 this.pos += ch <= 0xffff ? 1 : 2;
4970 } else if (ch === 92) { // "\"
4971 this.containsEsc = true;
4972 word += this.input.slice(chunkStart, this.pos);
4973 var escStart = this.pos;
4974 if (this.input.charCodeAt(++this.pos) !== 117) // "u"
4975 { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); }
4976 ++this.pos;
4977 var esc = this.readCodePoint();
4978 if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
4979 { this.invalidStringToken(escStart, "Invalid Unicode escape"); }
4980 word += codePointToString$1(esc);
4981 chunkStart = this.pos;
4982 } else {
4983 break
4984 }
4985 first = false;
4986 }
4987 return word + this.input.slice(chunkStart, this.pos)
4988 };
4989
4990 // Read an identifier or keyword token. Will check for reserved
4991 // words when necessary.
4992
4993 pp$9.readWord = function() {
4994 var word = this.readWord1();
4995 var type = types.name;
4996 if (this.keywords.test(word)) {
4997 type = keywords$1[word];
4998 }
4999 return this.finishToken(type, word)
5000 };
5001
5002 // Acorn is a tiny, fast JavaScript parser written in JavaScript.
5003
5004 var version = "7.1.0";
5005
5006 Parser.acorn = {
5007 Parser: Parser,
5008 version: version,
5009 defaultOptions: defaultOptions,
5010 Position: Position,
5011 SourceLocation: SourceLocation,
5012 getLineInfo: getLineInfo,
5013 Node: Node,
5014 TokenType: TokenType,
5015 tokTypes: types,
5016 keywordTypes: keywords$1,
5017 TokContext: TokContext,
5018 tokContexts: types$1,
5019 isIdentifierChar: isIdentifierChar,
5020 isIdentifierStart: isIdentifierStart,
5021 Token: Token,
5022 isNewLine: isNewLine,
5023 lineBreak: lineBreak,
5024 lineBreakG: lineBreakG,
5025 nonASCIIwhitespace: nonASCIIwhitespace
5026 };
5027
5028 // The main exported interface (under `self.acorn` when in the
5029 // browser) is a `parse` function that takes a code string and
5030 // returns an abstract syntax tree as specified by [Mozilla parser
5031 // API][api].
5032 //
5033 // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
5034
5035 function parse(input, options) {
5036 return Parser.parse(input, options)
5037 }
5038
5039 // This function tries to parse a single expression at a given
5040 // offset in a string. Useful for parsing mixed-language formats
5041 // that embed JavaScript expressions.
5042
5043 function parseExpressionAt(input, pos, options) {
5044 return Parser.parseExpressionAt(input, pos, options)
5045 }
5046
5047 function walk(ast, { enter, leave }) {
5048 return visit(ast, null, enter, leave);
5049 }
5050
5051 let should_skip = false;
5052 let should_remove = false;
5053 let replacement = null;
5054 const context = {
5055 skip: () => should_skip = true,
5056 remove: () => should_remove = true,
5057 replace: (node) => replacement = node
5058 };
5059
5060 function replace(parent, prop, index, node) {
5061 if (parent) {
5062 if (index !== null) {
5063 parent[prop][index] = node;
5064 } else {
5065 parent[prop] = node;
5066 }
5067 }
5068 }
5069
5070 function remove(parent, prop, index) {
5071 if (parent) {
5072 if (index !== null) {
5073 parent[prop].splice(index, 1);
5074 } else {
5075 delete parent[prop];
5076 }
5077 }
5078 }
5079
5080 function visit(
5081 node,
5082 parent,
5083 enter,
5084 leave,
5085 prop,
5086 index
5087 ) {
5088 if (node) {
5089 if (enter) {
5090 const _should_skip = should_skip;
5091 const _should_remove = should_remove;
5092 const _replacement = replacement;
5093 should_skip = false;
5094 should_remove = false;
5095 replacement = null;
5096
5097 enter.call(context, node, parent, prop, index);
5098
5099 if (replacement) {
5100 node = replacement;
5101 replace(parent, prop, index, node);
5102 }
5103
5104 if (should_remove) {
5105 remove(parent, prop, index);
5106 }
5107
5108 const skipped = should_skip;
5109 const removed = should_remove;
5110
5111 should_skip = _should_skip;
5112 should_remove = _should_remove;
5113 replacement = _replacement;
5114
5115 if (skipped) return node;
5116 if (removed) return null;
5117 }
5118
5119 for (const key in node) {
5120 const value = (node )[key];
5121
5122 if (typeof value !== 'object') {
5123 continue;
5124 }
5125
5126 else if (Array.isArray(value)) {
5127 for (let j = 0, k = 0; j < value.length; j += 1, k += 1) {
5128 if (value[j] !== null && typeof value[j].type === 'string') {
5129 if (!visit(value[j], node, enter, leave, key, k)) {
5130 // removed
5131 j--;
5132 }
5133 }
5134 }
5135 }
5136
5137 else if (value !== null && typeof value.type === 'string') {
5138 visit(value, node, enter, leave, key, null);
5139 }
5140 }
5141
5142 if (leave) {
5143 const _replacement = replacement;
5144 const _should_remove = should_remove;
5145 replacement = null;
5146 should_remove = false;
5147
5148 leave.call(context, node, parent, prop, index);
5149
5150 if (replacement) {
5151 node = replacement;
5152 replace(parent, prop, index, node);
5153 }
5154
5155 if (should_remove) {
5156 remove(parent, prop, index);
5157 }
5158
5159 const removed = should_remove;
5160
5161 replacement = _replacement;
5162 should_remove = _should_remove;
5163
5164 if (removed) return null;
5165 }
5166 }
5167
5168 return node;
5169 }
5170
5171 function isReference(node, parent) {
5172 if (node.type === 'MemberExpression') {
5173 return !node.computed && isReference(node.object, node);
5174 }
5175 if (node.type === 'Identifier') {
5176 if (!parent)
5177 return true;
5178 switch (parent.type) {
5179 // disregard `bar` in `foo.bar`
5180 case 'MemberExpression': return parent.computed || node === parent.object;
5181 // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
5182 case 'MethodDefinition': return parent.computed;
5183 // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
5184 case 'Property': return parent.computed || node === parent.value;
5185 // disregard the `bar` in `export { foo as bar }` or
5186 // the foo in `import { foo as bar }`
5187 case 'ExportSpecifier':
5188 case 'ImportSpecifier': return node === parent.local;
5189 // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
5190 case 'LabeledStatement':
5191 case 'BreakStatement':
5192 case 'ContinueStatement': return false;
5193 default: return true;
5194 }
5195 }
5196 return false;
5197 }
5198
5199 function analyze(expression) {
5200 const map = new WeakMap();
5201
5202 let scope = new Scope$1(null, false);
5203
5204 walk(expression, {
5205 enter(node, parent) {
5206 if (node.type === 'ImportDeclaration') {
5207 node.specifiers.forEach((specifier) => {
5208 scope.declarations.set(specifier.local.name, specifier);
5209 });
5210 } else if (/(Function(Declaration|Expression)|ArrowFunctionExpression)/.test(node.type)) {
5211 if (node.type === 'FunctionDeclaration') {
5212 scope.declarations.set(node.id.name, node);
5213 map.set(node, scope = new Scope$1(scope, false));
5214 } else {
5215 map.set(node, scope = new Scope$1(scope, false));
5216 if (node.type === 'FunctionExpression' && node.id) scope.declarations.set(node.id.name, node);
5217 }
5218
5219 node.params.forEach((param) => {
5220 extract_names(param).forEach(name => {
5221 scope.declarations.set(name, node);
5222 });
5223 });
5224 } else if (/For(?:In|Of)?Statement/.test(node.type)) {
5225 map.set(node, scope = new Scope$1(scope, true));
5226 } else if (node.type === 'BlockStatement') {
5227 map.set(node, scope = new Scope$1(scope, true));
5228 } else if (/(Class|Variable)Declaration/.test(node.type)) {
5229 scope.add_declaration(node);
5230 } else if (node.type === 'CatchClause') {
5231 map.set(node, scope = new Scope$1(scope, true));
5232
5233 if (node.param) {
5234 extract_names(node.param).forEach(name => {
5235 scope.declarations.set(name, node.param);
5236 });
5237 }
5238 }
5239 },
5240
5241 leave(node) {
5242 if (map.has(node)) {
5243 scope = scope.parent;
5244 }
5245 }
5246 });
5247
5248 const globals = new Map();
5249
5250 walk(expression, {
5251 enter(node, parent) {
5252 if (map.has(node)) scope = map.get(node);
5253
5254 if (node.type === 'Identifier' && isReference(node, parent)) {
5255 const owner = scope.find_owner(node.name);
5256 if (!owner) globals.set(node.name, node);
5257
5258 add_reference(scope, node.name);
5259 }
5260 },
5261 leave(node) {
5262 if (map.has(node)) {
5263 scope = scope.parent;
5264 }
5265 }
5266 });
5267
5268 return { map, scope, globals };
5269 }
5270
5271 function add_reference(scope, name) {
5272 scope.references.add(name);
5273 if (scope.parent) add_reference(scope.parent, name);
5274 }
5275
5276 class Scope$1 {
5277
5278
5279 __init() {this.declarations = new Map();}
5280 __init2() {this.initialised_declarations = new Set();}
5281 __init3() {this.references = new Set();}
5282
5283 constructor(parent, block) {Scope$1.prototype.__init.call(this);Scope$1.prototype.__init2.call(this);Scope$1.prototype.__init3.call(this);
5284 this.parent = parent;
5285 this.block = block;
5286 }
5287
5288
5289 add_declaration(node) {
5290 if (node.type === 'VariableDeclaration') {
5291 if (node.kind === 'var' && this.block && this.parent) {
5292 this.parent.add_declaration(node);
5293 } else if (node.type === 'VariableDeclaration') {
5294 node.declarations.forEach((declarator) => {
5295 extract_names(declarator.id).forEach(name => {
5296 this.declarations.set(name, node);
5297 if (declarator.init) this.initialised_declarations.add(name);
5298 });
5299 });
5300 }
5301 } else {
5302 this.declarations.set(node.id.name, node);
5303 }
5304 }
5305
5306 find_owner(name) {
5307 if (this.declarations.has(name)) return this;
5308 return this.parent && this.parent.find_owner(name);
5309 }
5310
5311 has(name) {
5312 return (
5313 this.declarations.has(name) || (this.parent && this.parent.has(name))
5314 );
5315 }
5316 }
5317
5318 function extract_names(param) {
5319 return extract_identifiers(param).map(node => node.name);
5320 }
5321
5322 function extract_identifiers(param) {
5323 const nodes = [];
5324 extractors[param.type] && extractors[param.type](nodes, param);
5325 return nodes;
5326 }
5327
5328 const extractors = {
5329 Identifier(nodes, param) {
5330 nodes.push(param);
5331 },
5332
5333 MemberExpression(nodes, param) {
5334 let object = param;
5335 while (object.type === 'MemberExpression') object = object.object;
5336 nodes.push(object);
5337 },
5338
5339 ObjectPattern(nodes, param) {
5340 param.properties.forEach((prop) => {
5341 if (prop.type === 'RestElement') {
5342 nodes.push(prop.argument);
5343 } else {
5344 extractors[prop.value.type](nodes, prop.value);
5345 }
5346 });
5347 },
5348
5349 ArrayPattern(nodes, param) {
5350 param.elements.forEach((element) => {
5351 if (element) extractors[element.type](nodes, element);
5352 });
5353 },
5354
5355 RestElement(nodes, param) {
5356 extractors[param.argument.type](nodes, param.argument);
5357 },
5358
5359 AssignmentPattern(nodes, param) {
5360 extractors[param.left.type](nodes, param.left);
5361 }
5362 };
5363
5364 var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
5365 function encode(decoded) {
5366 var sourceFileIndex = 0; // second field
5367 var sourceCodeLine = 0; // third field
5368 var sourceCodeColumn = 0; // fourth field
5369 var nameIndex = 0; // fifth field
5370 var mappings = '';
5371 for (var i = 0; i < decoded.length; i++) {
5372 var line = decoded[i];
5373 if (i > 0)
5374 mappings += ';';
5375 if (line.length === 0)
5376 continue;
5377 var generatedCodeColumn = 0; // first field
5378 var lineMappings = [];
5379 for (var _i = 0, line_1 = line; _i < line_1.length; _i++) {
5380 var segment = line_1[_i];
5381 var segmentMappings = encodeInteger(segment[0] - generatedCodeColumn);
5382 generatedCodeColumn = segment[0];
5383 if (segment.length > 1) {
5384 segmentMappings +=
5385 encodeInteger(segment[1] - sourceFileIndex) +
5386 encodeInteger(segment[2] - sourceCodeLine) +
5387 encodeInteger(segment[3] - sourceCodeColumn);
5388 sourceFileIndex = segment[1];
5389 sourceCodeLine = segment[2];
5390 sourceCodeColumn = segment[3];
5391 }
5392 if (segment.length === 5) {
5393 segmentMappings += encodeInteger(segment[4] - nameIndex);
5394 nameIndex = segment[4];
5395 }
5396 lineMappings.push(segmentMappings);
5397 }
5398 mappings += lineMappings.join(',');
5399 }
5400 return mappings;
5401 }
5402 function encodeInteger(num) {
5403 var result = '';
5404 num = num < 0 ? (-num << 1) | 1 : num << 1;
5405 do {
5406 var clamped = num & 31;
5407 num >>>= 5;
5408 if (num > 0) {
5409 clamped |= 32;
5410 }
5411 result += chars[clamped];
5412 } while (num > 0);
5413 return result;
5414 }
5415
5416 // generate an ID that is, to all intents and purposes, unique
5417 const id = (Math.round(Math.random() * 1e20)).toString(36);
5418 const re = new RegExp(`_${id}_(?:(\\d+)|(AT)|(HASH))_(\\w+)?`, 'g');
5419
5420 const get_comment_handlers = (comments, raw) => ({
5421
5422 // pass to acorn options
5423 onComment: (block, value, start, end) => {
5424 if (block && /\n/.test(value)) {
5425 let a = start;
5426 while (a > 0 && raw[a - 1] !== '\n') a -= 1;
5427
5428 let b = a;
5429 while (/[ \t]/.test(raw[b])) b += 1;
5430
5431 const indentation = raw.slice(a, b);
5432 value = value.replace(new RegExp(`^${indentation}`, 'gm'), '');
5433 }
5434
5435 comments.push({ type: block ? 'Block' : 'Line', value, start, end });
5436 },
5437
5438 // pass to estree-walker options
5439 enter(node) {
5440 let comment;
5441
5442 while (comments[0] && comments[0].start < (node ).start) {
5443 comment = comments.shift();
5444
5445 comment.value = comment.value.replace(re, (match, id, at, hash, value) => {
5446 if (hash) return `#${value}`;
5447 if (at) return `@${value}`;
5448
5449 return match;
5450 });
5451
5452 const next = comments[0] || node;
5453 (comment ).has_trailing_newline = (
5454 comment.type === 'Line' ||
5455 /\n/.test(raw.slice(comment.end, (next ).start))
5456 );
5457
5458 (node.leadingComments || (node.leadingComments = [])).push(comment);
5459 }
5460 },
5461 leave(node) {
5462 if (comments[0]) {
5463 const slice = raw.slice((node ).end, comments[0].start);
5464
5465 if (/^[,) \t]*$/.test(slice)) {
5466 node.trailingComments = [comments.shift()];
5467 }
5468 }
5469 }
5470
5471 });
5472
5473 function handle(node, state) {
5474 const handler = handlers[node.type];
5475
5476 if (!handler) {
5477 throw new Error(`Not implemented ${node.type}`);
5478 }
5479
5480 const result = handler(node, state);
5481
5482 if (node.leadingComments) {
5483 result.unshift(c(node.leadingComments.map(comment => comment.type === 'Block'
5484 ? `/*${comment.value}*/${(comment ).has_trailing_newline ? `\n${state.indent}` : ` `}`
5485 : `//${comment.value}${(comment ).has_trailing_newline ? `\n${state.indent}` : ` `}`).join(``)));
5486 }
5487
5488 if (node.trailingComments) {
5489 state.comments.push(node.trailingComments[0]); // there is only ever one
5490 }
5491
5492 return result;
5493 }
5494
5495 function c(content, node) {
5496 return {
5497 content,
5498 loc: node && node.loc,
5499 has_newline: /\n/.test(content)
5500 };
5501 }
5502
5503 const OPERATOR_PRECEDENCE = {
5504 '||': 3,
5505 '&&': 4,
5506 '|': 5,
5507 '^': 6,
5508 '&': 7,
5509 '==': 8,
5510 '!=': 8,
5511 '===': 8,
5512 '!==': 8,
5513 '<': 9,
5514 '>': 9,
5515 '<=': 9,
5516 '>=': 9,
5517 in: 9,
5518 instanceof: 9,
5519 '<<': 10,
5520 '>>': 10,
5521 '>>>': 10,
5522 '+': 11,
5523 '-': 11,
5524 '*': 12,
5525 '%': 12,
5526 '/': 12,
5527 '**': 13,
5528 };
5529
5530 const EXPRESSIONS_PRECEDENCE = {
5531 ArrayExpression: 20,
5532 TaggedTemplateExpression: 20,
5533 ThisExpression: 20,
5534 Identifier: 20,
5535 Literal: 18,
5536 TemplateLiteral: 20,
5537 Super: 20,
5538 SequenceExpression: 20,
5539 MemberExpression: 19,
5540 CallExpression: 19,
5541 NewExpression: 19,
5542 AwaitExpression: 17,
5543 ClassExpression: 17,
5544 FunctionExpression: 17,
5545 ObjectExpression: 17,
5546 UpdateExpression: 16,
5547 UnaryExpression: 15,
5548 BinaryExpression: 14,
5549 LogicalExpression: 13,
5550 ConditionalExpression: 4,
5551 ArrowFunctionExpression: 3,
5552 AssignmentExpression: 3,
5553 YieldExpression: 2,
5554 RestElement: 1
5555 };
5556
5557 function needs_parens(node, parent, is_right) {
5558 const precedence = EXPRESSIONS_PRECEDENCE[node.type];
5559 const parent_precedence = EXPRESSIONS_PRECEDENCE[parent.type];
5560
5561 if (precedence !== parent_precedence) {
5562 // Different node types
5563 return (
5564 (!is_right &&
5565 precedence === 15 &&
5566 parent_precedence === 14 &&
5567 parent.operator === '**') ||
5568 precedence < parent_precedence
5569 );
5570 }
5571
5572 if (precedence !== 13 && precedence !== 14) {
5573 // Not a `LogicalExpression` or `BinaryExpression`
5574 return false;
5575 }
5576
5577 if ((node ).operator === '**' && parent.operator === '**') {
5578 // Exponentiation operator has right-to-left associativity
5579 return !is_right;
5580 }
5581
5582 if (is_right) {
5583 // Parenthesis are used if both operators have the same precedence
5584 return (
5585 OPERATOR_PRECEDENCE[(node ).operator] <=
5586 OPERATOR_PRECEDENCE[parent.operator]
5587 );
5588 }
5589
5590 return (
5591 OPERATOR_PRECEDENCE[(node ).operator] <
5592 OPERATOR_PRECEDENCE[parent.operator]
5593 );
5594 }
5595
5596 function has_call_expression(node) {
5597 while (node) {
5598 if (node.type[0] === 'CallExpression') {
5599 return true;
5600 } else if (node.type === 'MemberExpression') {
5601 node = node.object;
5602 } else {
5603 return false;
5604 }
5605 }
5606 }
5607
5608 const has_newline = (chunks) => {
5609 for (let i = 0; i < chunks.length; i += 1) {
5610 if (chunks[i].has_newline) return true;
5611 }
5612 return false;
5613 };
5614
5615 const get_length = (chunks) => {
5616 let total = 0;
5617 for (let i = 0; i < chunks.length; i += 1) {
5618 total += chunks[i].content.length;
5619 }
5620 return total;
5621 };
5622
5623 const sum = (a, b) => a + b;
5624
5625 const join = (nodes, separator) => {
5626 if (nodes.length === 0) return [];
5627 const joined = [...nodes[0]];
5628 for (let i = 1; i < nodes.length; i += 1) {
5629 joined.push(separator, ...nodes[i] );
5630 }
5631 return joined;
5632 };
5633
5634 const scoped = (fn) => {
5635 return (node, state) => {
5636 return fn(node, {
5637 ...state,
5638 scope: state.scope_map.get(node)
5639 });
5640 };
5641 };
5642
5643 const deconflict = (name, names) => {
5644 const original = name;
5645 let i = 1;
5646
5647 while (names.has(name)) {
5648 name = `${original}$${i++}`;
5649 }
5650
5651 return name;
5652 };
5653
5654 const handle_body = (nodes, state) => {
5655 const chunks = [];
5656
5657 const body = nodes.map(statement => {
5658 const chunks = handle(statement, {
5659 ...state,
5660 indent: state.indent
5661 });
5662
5663 let add_newline = false;
5664
5665 while (state.comments.length) {
5666 const comment = state.comments.shift();
5667 const prefix = add_newline ? `\n${state.indent}` : ` `;
5668
5669 chunks.push(c(comment.type === 'Block'
5670 ? `${prefix}/*${comment.value}*/`
5671 : `${prefix}//${comment.value}`));
5672
5673 add_newline = (comment.type === 'Line');
5674 }
5675
5676 return chunks;
5677 });
5678
5679 let needed_padding = false;
5680
5681 for (let i = 0; i < body.length; i += 1) {
5682 const needs_padding = has_newline(body[i]);
5683
5684 if (i > 0) {
5685 chunks.push(
5686 c(needs_padding || needed_padding ? `\n\n${state.indent}` : `\n${state.indent}`)
5687 );
5688 }
5689
5690 chunks.push(
5691 ...body[i]
5692 );
5693
5694 needed_padding = needs_padding;
5695 }
5696
5697 return chunks;
5698 };
5699
5700 const handle_var_declaration = (node, state) => {
5701 const chunks = [c(`${node.kind} `)];
5702
5703 const declarators = node.declarations.map(d => handle(d, {
5704 ...state,
5705 indent: state.indent + (node.declarations.length === 1 ? '' : '\t')
5706 }));
5707
5708 const multiple_lines = (
5709 declarators.some(has_newline) ||
5710 (declarators.map(get_length).reduce(sum, 0) + (state.indent.length + declarators.length - 1) * 2) > 80
5711 );
5712
5713 const separator = c(multiple_lines ? `,\n${state.indent}\t` : ', ');
5714
5715 if (multiple_lines) {
5716 chunks.push(...join(declarators, separator));
5717 } else {
5718 chunks.push(
5719 ...join(declarators, separator)
5720 );
5721 }
5722
5723 return chunks;
5724 };
5725
5726 const handlers = {
5727 Program(node, state) {
5728 return handle_body(node.body, state);
5729 },
5730
5731 BlockStatement: scoped((node, state) => {
5732 return [
5733 c(`{\n${state.indent}\t`),
5734 ...handle_body(node.body, { ...state, indent: state.indent + '\t' }),
5735 c(`\n${state.indent}}`)
5736 ];
5737 }),
5738
5739 EmptyStatement(node, state) {
5740 return [];
5741 },
5742
5743 ParenthesizedExpression(node, state) {
5744 return handle(node.expression, state);
5745 },
5746
5747 ExpressionStatement(node, state) {
5748 const precedence = EXPRESSIONS_PRECEDENCE[node.expression.type];
5749 if (
5750 precedence === 3 && (node.expression ).left.type === 'ObjectPattern'
5751 ) {
5752 // is an AssignmentExpression to an ObjectPattern
5753 return [
5754 c('('),
5755 ...handle(node.expression, state),
5756 c(');')
5757 ];
5758 }
5759
5760 return [
5761 ...handle(node.expression, state),
5762 c(';')
5763 ];
5764 },
5765
5766 IfStatement(node, state) {
5767 const chunks = [
5768 c('if ('),
5769 ...handle(node.test, state),
5770 c(') '),
5771 ...handle(node.consequent, state)
5772 ];
5773
5774 if (node.alternate) {
5775 chunks.push(
5776 c(' else '),
5777 ...handle(node.alternate, state)
5778 );
5779 }
5780
5781 return chunks;
5782 },
5783
5784 LabeledStatement(node, state) {
5785 return [
5786 ...handle(node.label, state),
5787 c(': '),
5788 ...handle(node.body, state)
5789 ];
5790 },
5791
5792 BreakStatement(node, state) {
5793 return node.label
5794 ? [c('break '), ...handle(node.label, state), c(';')]
5795 : [c('break;')];
5796 },
5797
5798 ContinueStatement(node, state) {
5799 return node.label
5800 ? [c('continue '), ...handle(node.label, state), c(';')]
5801 : [c('continue;')];
5802 },
5803
5804 WithStatement(node, state) {
5805 return [
5806 c('with ('),
5807 ...handle(node.object, state),
5808 c(') '),
5809 ...handle(node.body, state)
5810 ];
5811 },
5812
5813 SwitchStatement(node, state) {
5814 const chunks = [
5815 c('switch ('),
5816 ...handle(node.discriminant, state),
5817 c(') {')
5818 ];
5819
5820 node.cases.forEach(block => {
5821 if (block.test) {
5822 chunks.push(
5823 c(`\n${state.indent}\tcase `),
5824 ...handle(block.test, { ...state, indent: `${state.indent}\t` }),
5825 c(':')
5826 );
5827 } else {
5828 chunks.push(c(`\n${state.indent}\tdefault:`));
5829 }
5830
5831 block.consequent.forEach(statement => {
5832 chunks.push(
5833 c(`\n${state.indent}\t\t`),
5834 ...handle(statement, { ...state, indent: `${state.indent}\t\t` })
5835 );
5836 });
5837 });
5838
5839 chunks.push(c(`\n${state.indent}}`));
5840
5841 return chunks;
5842 },
5843
5844 ReturnStatement(node, state) {
5845 if (node.argument) {
5846 return [
5847 c('return '),
5848 ...handle(node.argument, state),
5849 c(';')
5850 ];
5851 } else {
5852 return [c('return;')];
5853 }
5854 },
5855
5856 ThrowStatement(node, state) {
5857 return [
5858 c('throw '),
5859 ...handle(node.argument, state),
5860 c(';')
5861 ];
5862 },
5863
5864 TryStatement(node, state) {
5865 const chunks = [
5866 c('try '),
5867 ...handle(node.block, state)
5868 ];
5869
5870 if (node.handler) {
5871 if (node.handler.param) {
5872 chunks.push(
5873 c(' catch('),
5874 ...handle(node.handler.param, state),
5875 c(') ')
5876 );
5877 } else {
5878 chunks.push(c(' catch '));
5879 }
5880
5881 chunks.push(...handle(node.handler.body, state));
5882 }
5883
5884 if (node.finalizer) {
5885 chunks.push(c(' finally '), ...handle(node.finalizer, state));
5886 }
5887
5888 return chunks;
5889 },
5890
5891 WhileStatement(node, state) {
5892 return [
5893 c('while ('),
5894 ...handle(node.test, state),
5895 c(') '),
5896 ...handle(node.body, state)
5897 ];
5898 },
5899
5900 DoWhileStatement(node, state) {
5901 return [
5902 c('do '),
5903 ...handle(node.body, state),
5904 c(' while ('),
5905 ...handle(node.test, state),
5906 c(');')
5907 ];
5908 },
5909
5910 ForStatement: scoped((node, state) => {
5911 const chunks = [c('for (')];
5912
5913 if (node.init) {
5914 if ((node.init ).type === 'VariableDeclaration') {
5915 chunks.push(...handle_var_declaration(node.init , state));
5916 } else {
5917 chunks.push(...handle(node.init, state));
5918 }
5919 }
5920
5921 chunks.push(c('; '));
5922 if (node.test) chunks.push(...handle(node.test, state));
5923 chunks.push(c('; '));
5924 if (node.update) chunks.push(...handle(node.update, state));
5925
5926 chunks.push(
5927 c(') '),
5928 ...handle(node.body, state)
5929 );
5930
5931 return chunks;
5932 }),
5933
5934 ForInStatement: scoped((node, state) => {
5935 const chunks = [
5936 c(`for ${(node ).await ? 'await ' : ''}(`)
5937 ];
5938
5939 if ((node.left ).type === 'VariableDeclaration') {
5940 chunks.push(...handle_var_declaration(node.left , state));
5941 } else {
5942 chunks.push(...handle(node.left, state));
5943 }
5944
5945 chunks.push(
5946 c(node.type === 'ForInStatement' ? ` in ` : ` of `),
5947 ...handle(node.right, state),
5948 c(') '),
5949 ...handle(node.body, state)
5950 );
5951
5952 return chunks;
5953 }),
5954
5955 DebuggerStatement(node, state) {
5956 return [c('debugger', node), c(';')];
5957 },
5958
5959 FunctionDeclaration: scoped((node, state) => {
5960 const chunks = [];
5961
5962 if (node.async) chunks.push(c('async '));
5963 chunks.push(c(node.generator ? 'function* ' : 'function '));
5964 if (node.id) chunks.push(...handle(node.id, state));
5965 chunks.push(c('('));
5966
5967 const params = node.params.map(p => handle(p, {
5968 ...state,
5969 indent: state.indent + '\t'
5970 }));
5971
5972 const multiple_lines = (
5973 params.some(has_newline) ||
5974 (params.map(get_length).reduce(sum, 0) + (state.indent.length + params.length - 1) * 2) > 80
5975 );
5976
5977 const separator = c(multiple_lines ? `,\n${state.indent}` : ', ');
5978
5979 if (multiple_lines) {
5980 chunks.push(
5981 c(`\n${state.indent}\t`),
5982 ...join(params, separator),
5983 c(`\n${state.indent}`)
5984 );
5985 } else {
5986 chunks.push(
5987 ...join(params, separator)
5988 );
5989 }
5990
5991 chunks.push(
5992 c(') '),
5993 ...handle(node.body, state)
5994 );
5995
5996 return chunks;
5997 }),
5998
5999 VariableDeclaration(node, state) {
6000 return handle_var_declaration(node, state).concat(c(';'));
6001 },
6002
6003 VariableDeclarator(node, state) {
6004 if (node.init) {
6005 return [
6006 ...handle(node.id, state),
6007 c(' = '),
6008 ...handle(node.init, state)
6009 ];
6010 } else {
6011 return handle(node.id, state);
6012 }
6013 },
6014
6015 ClassDeclaration(node, state) {
6016 const chunks = [c('class ')];
6017
6018 if (node.id) chunks.push(...handle(node.id, state), c(' '));
6019
6020 if (node.superClass) {
6021 chunks.push(
6022 c('extends '),
6023 ...handle(node.superClass, state),
6024 c(' ')
6025 );
6026 }
6027
6028 chunks.push(...handle(node.body, state));
6029
6030 return chunks;
6031 },
6032
6033 ImportDeclaration(node, state) {
6034 const chunks = [c('import ')];
6035
6036 const { length } = node.specifiers;
6037 const source = handle(node.source, state);
6038
6039 if (length > 0) {
6040 let i = 0;
6041
6042 while (i < length) {
6043 if (i > 0) {
6044 chunks.push(c(', '));
6045 }
6046
6047 const specifier = node.specifiers[i];
6048
6049 if (specifier.type === 'ImportDefaultSpecifier') {
6050 chunks.push(c(specifier.local.name, specifier));
6051 i += 1;
6052 } else if (specifier.type === 'ImportNamespaceSpecifier') {
6053 chunks.push(c('* as ' + specifier.local.name, specifier));
6054 i += 1;
6055 } else {
6056 break;
6057 }
6058 }
6059
6060 if (i < length) {
6061 // we have named specifiers
6062 const specifiers = node.specifiers.slice(i).map((specifier) => {
6063 const name = handle(specifier.imported, state)[0];
6064 const as = handle(specifier.local, state)[0];
6065
6066 if (name.content === as.content) {
6067 return [as];
6068 }
6069
6070 return [name, c(' as '), as];
6071 });
6072
6073 const width = get_length(chunks) + specifiers.map(get_length).reduce(sum, 0) + (2 * specifiers.length) + 6 + get_length(source);
6074
6075 if (width > 80) {
6076 chunks.push(
6077 c(`{\n\t`),
6078 ...join(specifiers, c(',\n\t')),
6079 c('\n}')
6080 );
6081 } else {
6082 chunks.push(
6083 c(`{ `),
6084 ...join(specifiers, c(', ')),
6085 c(' }')
6086 );
6087 }
6088 }
6089
6090 chunks.push(c(' from '));
6091 }
6092
6093 chunks.push(
6094 ...source,
6095 c(';')
6096 );
6097
6098 return chunks;
6099 },
6100
6101 ImportExpression(node, state) {
6102 return [c('import('), ...handle(node.source, state), c(')')];
6103 },
6104
6105 ExportDefaultDeclaration(node, state) {
6106 const chunks = [
6107 c(`export default `),
6108 ...handle(node.declaration, state)
6109 ];
6110
6111 if (node.declaration.type !== 'FunctionDeclaration') {
6112 chunks.push(c(';'));
6113 }
6114
6115 return chunks;
6116 },
6117
6118 ExportNamedDeclaration(node, state) {
6119 const chunks = [c('export ')];
6120
6121 if (node.declaration) {
6122 chunks.push(...handle(node.declaration, state));
6123 } else {
6124 const specifiers = node.specifiers.map(specifier => {
6125 const name = handle(specifier.local, state)[0];
6126 const as = handle(specifier.exported, state)[0];
6127
6128 if (name.content === as.content) {
6129 return [name];
6130 }
6131
6132 return [name, c(' as '), as];
6133 });
6134
6135 const width = 7 + specifiers.map(get_length).reduce(sum, 0) + 2 * specifiers.length;
6136
6137 if (width > 80) {
6138 chunks.push(
6139 c('{\n\t'),
6140 ...join(specifiers, c(',\n\t')),
6141 c('\n}')
6142 );
6143 } else {
6144 chunks.push(
6145 c('{ '),
6146 ...join(specifiers, c(', ')),
6147 c(' }')
6148 );
6149 }
6150
6151 if (node.source) {
6152 chunks.push(
6153 c(' from '),
6154 ...handle(node.source, state)
6155 );
6156 }
6157 }
6158
6159 chunks.push(c(';'));
6160
6161 return chunks;
6162 },
6163
6164 ExportAllDeclaration(node, state) {
6165 return [
6166 c(`export * from `),
6167 ...handle(node.source, state),
6168 c(`;`)
6169 ];
6170 },
6171
6172 MethodDefinition(node, state) {
6173 const chunks = [];
6174
6175 if (node.static) {
6176 chunks.push(c('static '));
6177 }
6178
6179 if (node.kind === 'get' || node.kind === 'set') {
6180 // Getter or setter
6181 chunks.push(c(node.kind + ' '));
6182 }
6183
6184 if (node.value.async) {
6185 chunks.push(c('async '));
6186 }
6187
6188 if (node.value.generator) {
6189 chunks.push(c('*'));
6190 }
6191
6192 if (node.computed) {
6193 chunks.push(
6194 c('['),
6195 ...handle(node.key, state),
6196 c(']')
6197 );
6198 } else {
6199 chunks.push(...handle(node.key, state));
6200 }
6201
6202 chunks.push(c('('));
6203
6204 const { params } = node.value;
6205 for (let i = 0; i < params.length; i += 1) {
6206 chunks.push(...handle(params[i], state));
6207 if (i < params.length - 1) chunks.push(c(', '));
6208 }
6209
6210 chunks.push(
6211 c(') '),
6212 ...handle(node.value.body, state)
6213 );
6214
6215 return chunks;
6216 },
6217
6218 ArrowFunctionExpression: scoped((node, state) => {
6219 const chunks = [];
6220
6221 if (node.async) chunks.push(c('async '));
6222
6223 if (node.params.length === 1 && node.params[0].type === 'Identifier') {
6224 chunks.push(...handle(node.params[0], state));
6225 } else {
6226 const params = node.params.map(param => handle(param, {
6227 ...state,
6228 indent: state.indent + '\t'
6229 }));
6230
6231 chunks.push(
6232 c('('),
6233 ...join(params, c(', ')),
6234 c(')')
6235 );
6236 }
6237
6238 chunks.push(c(' => '));
6239
6240 if (node.body.type === 'ObjectExpression') {
6241 chunks.push(
6242 c('('),
6243 ...handle(node.body, state),
6244 c(')')
6245 );
6246 } else {
6247 chunks.push(...handle(node.body, state));
6248 }
6249
6250 return chunks;
6251 }),
6252
6253 ThisExpression(node, state) {
6254 return [c('this', node)];
6255 },
6256
6257 Super(node, state) {
6258 return [c('super', node)];
6259 },
6260
6261 RestElement(node, state) {
6262 return [c('...'), ...handle(node.argument, state)];
6263 },
6264
6265 YieldExpression(node, state) {
6266 if (node.argument) {
6267 return [c(node.delegate ? `yield* ` : `yield `), ...handle(node.argument, state)];
6268 }
6269
6270 return [c(node.delegate ? `yield*` : `yield`)];
6271 },
6272
6273 AwaitExpression(node, state) {
6274 if (node.argument) {
6275 const precedence = EXPRESSIONS_PRECEDENCE[node.argument.type];
6276
6277 if (precedence && (precedence < EXPRESSIONS_PRECEDENCE.AwaitExpression)) {
6278 return [c('await ('), ...handle(node.argument, state), c(')')];
6279 } else {
6280 return [c('await '), ...handle(node.argument, state)];
6281 }
6282 }
6283
6284 return [c('await')];
6285 },
6286
6287 TemplateLiteral(node, state) {
6288 const chunks = [c('`')];
6289
6290 const { quasis, expressions } = node;
6291
6292 for (let i = 0; i < expressions.length; i++) {
6293 chunks.push(
6294 c(quasis[i].value.raw),
6295 c('${'),
6296 ...handle(expressions[i], state),
6297 c('}')
6298 );
6299 }
6300
6301 chunks.push(
6302 c(quasis[quasis.length - 1].value.raw),
6303 c('`')
6304 );
6305
6306 return chunks;
6307 },
6308
6309 TaggedTemplateExpression(node, state) {
6310 return handle(node.tag, state).concat(handle(node.quasi, state));
6311 },
6312
6313 ArrayExpression(node, state) {
6314 const chunks = [c('[')];
6315
6316 const elements = [];
6317 let sparse_commas = [];
6318
6319 for (let i = 0; i < node.elements.length; i += 1) {
6320 // can't use map/forEach because of sparse arrays
6321 const element = node.elements[i];
6322 if (element) {
6323 elements.push([...sparse_commas, ...handle(element, {
6324 ...state,
6325 indent: state.indent + '\t'
6326 })]);
6327 sparse_commas = [];
6328 } else {
6329 sparse_commas.push(c(','));
6330 }
6331 }
6332
6333 const multiple_lines = (
6334 elements.some(has_newline) ||
6335 (elements.map(get_length).reduce(sum, 0) + (state.indent.length + elements.length - 1) * 2) > 80
6336 );
6337
6338 if (multiple_lines) {
6339 chunks.push(
6340 c(`\n${state.indent}\t`),
6341 ...join(elements, c(`,\n${state.indent}\t`)),
6342 c(`\n${state.indent}`),
6343 ...sparse_commas
6344 );
6345 } else {
6346 chunks.push(...join(elements, c(', ')), ...sparse_commas);
6347 }
6348
6349 chunks.push(c(']'));
6350
6351 return chunks;
6352 },
6353
6354 ObjectExpression(node, state) {
6355 if (node.properties.length === 0) {
6356 return [c('{}')];
6357 }
6358
6359 let has_inline_comment = false;
6360
6361 const chunks = [];
6362 const separator = c(', ');
6363
6364 node.properties.forEach((p, i) => {
6365 chunks.push(...handle(p, {
6366 ...state,
6367 indent: state.indent + '\t'
6368 }));
6369
6370 if (state.comments.length) {
6371 // TODO generalise this, so it works with ArrayExpressions and other things.
6372 // At present, stuff will just get appended to the closest statement/declaration
6373 chunks.push(c(', '));
6374
6375 while (state.comments.length) {
6376 const comment = state.comments.shift();
6377
6378 chunks.push(c(comment.type === 'Block'
6379 ? `/*${comment.value}*/\n${state.indent}\t`
6380 : `//${comment.value}\n${state.indent}\t`));
6381
6382 if (comment.type === 'Line') {
6383 has_inline_comment = true;
6384 }
6385 }
6386 } else {
6387 if (i < node.properties.length - 1) {
6388 chunks.push(separator);
6389 }
6390 }
6391 });
6392
6393 const multiple_lines = (
6394 has_inline_comment ||
6395 has_newline(chunks) ||
6396 get_length(chunks) > 40
6397 );
6398
6399 if (multiple_lines) {
6400 separator.content = `,\n${state.indent}\t`;
6401 }
6402
6403 return [
6404 c(multiple_lines ? `{\n${state.indent}\t` : `{ `),
6405 ...chunks,
6406 c(multiple_lines ? `\n${state.indent}}` : ` }`)
6407 ];
6408 },
6409
6410 Property(node, state) {
6411 const value = handle(node.value, state);
6412
6413 if (node.key === node.value) {
6414 return value;
6415 }
6416
6417 // special case
6418 if (
6419 !node.computed &&
6420 node.value.type === 'AssignmentPattern' &&
6421 node.value.left.type === 'Identifier' &&
6422 node.value.left.name === (node.key ).name
6423 ) {
6424 return value;
6425 }
6426
6427 if (node.value.type === 'Identifier' && (
6428 (node.key.type === 'Identifier' && node.key.name === value[0].content) ||
6429 (node.key.type === 'Literal' && node.key.value === value[0].content)
6430 )) {
6431 return value;
6432 }
6433
6434 const key = handle(node.key, state);
6435
6436 if (node.value.type === 'FunctionExpression' && !node.value.id) {
6437 state = {
6438 ...state,
6439 scope: state.scope_map.get(node.value)
6440 };
6441
6442 const chunks = node.kind !== 'init'
6443 ? [c(`${node.kind} `)]
6444 : [];
6445
6446 if (node.value.async) {
6447 chunks.push(c('async '));
6448 }
6449 if (node.value.generator) {
6450 chunks.push(c('*'));
6451 }
6452
6453 chunks.push(
6454 ...(node.computed ? [c('['), ...key, c(']')] : key),
6455 c('('),
6456 ...join((node.value ).params.map(param => handle(param, state)), c(', ')),
6457 c(') '),
6458 ...handle((node.value ).body, state)
6459 );
6460
6461 return chunks;
6462 }
6463
6464 if (node.computed) {
6465 return [
6466 c('['),
6467 ...key,
6468 c(']: '),
6469 ...value
6470 ];
6471 }
6472
6473 return [
6474 ...key,
6475 c(': '),
6476 ...value
6477 ];
6478 },
6479
6480 ObjectPattern(node, state) {
6481 const chunks = [c('{ ')];
6482
6483 for (let i = 0; i < node.properties.length; i += 1) {
6484 chunks.push(...handle(node.properties[i], state));
6485 if (i < node.properties.length - 1) chunks.push(c(', '));
6486 }
6487
6488 chunks.push(c(' }'));
6489
6490 return chunks;
6491 },
6492
6493 SequenceExpression(node, state) {
6494 const expressions = node.expressions.map(e => handle(e, state));
6495
6496 return [
6497 c('('),
6498 ...join(expressions, c(', ')),
6499 c(')')
6500 ];
6501 },
6502
6503 UnaryExpression(node, state) {
6504 const chunks = [c(node.operator)];
6505
6506 if (node.operator.length > 1) {
6507 chunks.push(c(' '));
6508 }
6509
6510 if (
6511 EXPRESSIONS_PRECEDENCE[node.argument.type] <
6512 EXPRESSIONS_PRECEDENCE.UnaryExpression
6513 ) {
6514 chunks.push(
6515 c('('),
6516 ...handle(node.argument, state),
6517 c(')')
6518 );
6519 } else {
6520 chunks.push(...handle(node.argument, state));
6521 }
6522
6523 return chunks;
6524 },
6525
6526 UpdateExpression(node, state) {
6527 return node.prefix
6528 ? [c(node.operator), ...handle(node.argument, state)]
6529 : [...handle(node.argument, state), c(node.operator)];
6530 },
6531
6532 AssignmentExpression(node, state) {
6533 return [
6534 ...handle(node.left, state),
6535 c(` ${node.operator || '='} `),
6536 ...handle(node.right, state)
6537 ];
6538 },
6539
6540 BinaryExpression(node, state) {
6541 const chunks = [];
6542
6543 // TODO
6544 // const is_in = node.operator === 'in';
6545 // if (is_in) {
6546 // // Avoids confusion in `for` loops initializers
6547 // chunks.push(c('('));
6548 // }
6549
6550 if (needs_parens(node.left, node, false)) {
6551 chunks.push(
6552 c('('),
6553 ...handle(node.left, state),
6554 c(')')
6555 );
6556 } else {
6557 chunks.push(...handle(node.left, state));
6558 }
6559
6560 chunks.push(c(` ${node.operator} `));
6561
6562 if (needs_parens(node.right, node, true)) {
6563 chunks.push(
6564 c('('),
6565 ...handle(node.right, state),
6566 c(')')
6567 );
6568 } else {
6569 chunks.push(...handle(node.right, state));
6570 }
6571
6572 return chunks;
6573 },
6574
6575 ConditionalExpression(node, state) {
6576 const chunks = [];
6577
6578 if (
6579 EXPRESSIONS_PRECEDENCE[node.test.type] >
6580 EXPRESSIONS_PRECEDENCE.ConditionalExpression
6581 ) {
6582 chunks.push(...handle(node.test, state));
6583 } else {
6584 chunks.push(
6585 c('('),
6586 ...handle(node.test, state),
6587 c(')')
6588 );
6589 }
6590
6591 const child_state = { ...state, indent: state.indent + '\t' };
6592
6593 const consequent = handle(node.consequent, child_state);
6594 const alternate = handle(node.alternate, child_state);
6595
6596 const multiple_lines = (
6597 has_newline(consequent) || has_newline(alternate) ||
6598 get_length(chunks) + get_length(consequent) + get_length(alternate) > 50
6599 );
6600
6601 if (multiple_lines) {
6602 chunks.push(
6603 c(`\n${state.indent}? `),
6604 ...consequent,
6605 c(`\n${state.indent}: `),
6606 ...alternate
6607 );
6608 } else {
6609 chunks.push(
6610 c(` ? `),
6611 ...consequent,
6612 c(` : `),
6613 ...alternate
6614 );
6615 }
6616
6617 return chunks;
6618 },
6619
6620 NewExpression(node, state) {
6621 const chunks = [c('new ')];
6622
6623 if (
6624 EXPRESSIONS_PRECEDENCE[node.callee.type] <
6625 EXPRESSIONS_PRECEDENCE.CallExpression || has_call_expression(node.callee)
6626 ) {
6627 chunks.push(
6628 c('('),
6629 ...handle(node.callee, state),
6630 c(')')
6631 );
6632 } else {
6633 chunks.push(...handle(node.callee, state));
6634 }
6635
6636 // TODO this is copied from CallExpression — DRY it out
6637 const args = node.arguments.map(arg => handle(arg, {
6638 ...state,
6639 indent: state.indent + '\t'
6640 }));
6641
6642 const separator = args.some(has_newline) // TODO or length exceeds 80
6643 ? c(',\n' + state.indent)
6644 : c(', ');
6645
6646 chunks.push(
6647 c('('),
6648 ...join(args, separator) ,
6649 c(')')
6650 );
6651
6652 return chunks;
6653 },
6654
6655 CallExpression(node, state) {
6656 const chunks = [];
6657
6658 if (
6659 EXPRESSIONS_PRECEDENCE[node.callee.type] <
6660 EXPRESSIONS_PRECEDENCE.CallExpression
6661 ) {
6662 chunks.push(
6663 c('('),
6664 ...handle(node.callee, state),
6665 c(')')
6666 );
6667 } else {
6668 chunks.push(...handle(node.callee, state));
6669 }
6670
6671 const args = node.arguments.map(arg => handle(arg, state));
6672
6673 const multiple_lines = args.slice(0, -1).some(has_newline); // TODO or length exceeds 80
6674
6675 if (multiple_lines) {
6676 // need to handle args again. TODO find alternative approach?
6677 const args = node.arguments.map(arg => handle(arg, {
6678 ...state,
6679 indent: `${state.indent}\t`
6680 }));
6681
6682 chunks.push(
6683 c(`(\n${state.indent}\t`),
6684 ...join(args, c(`,\n${state.indent}\t`)),
6685 c(`\n${state.indent})`)
6686 );
6687 } else {
6688 chunks.push(
6689 c('('),
6690 ...join(args, c(', ')),
6691 c(')')
6692 );
6693 }
6694
6695 return chunks;
6696 },
6697
6698 MemberExpression(node, state) {
6699 const chunks = [];
6700
6701 if (EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression) {
6702 chunks.push(
6703 c('('),
6704 ...handle(node.object, state),
6705 c(')')
6706 );
6707 } else {
6708 chunks.push(...handle(node.object, state));
6709 }
6710
6711 if (node.computed) {
6712 chunks.push(
6713 c('['),
6714 ...handle(node.property, state),
6715 c(']')
6716 );
6717 } else {
6718 chunks.push(
6719 c('.'),
6720 ...handle(node.property, state)
6721 );
6722 }
6723
6724 return chunks;
6725 },
6726
6727 MetaProperty(node, state) {
6728 return [...handle(node.meta, state), c('.'), ...handle(node.property, state)];
6729 },
6730
6731 Identifier(node, state) {
6732 let name = node.name;
6733
6734 if (name[0] === '@') {
6735 name = state.getName(name.slice(1));
6736 } else if (node.name[0] === '#') {
6737 const owner = state.scope.find_owner(node.name);
6738
6739 if (!owner) {
6740 throw new Error(`Could not find owner for node`);
6741 }
6742
6743 if (!state.deconflicted.has(owner)) {
6744 state.deconflicted.set(owner, new Map());
6745 }
6746
6747 const deconflict_map = state.deconflicted.get(owner);
6748
6749 if (!deconflict_map.has(node.name)) {
6750 deconflict_map.set(node.name, deconflict(node.name.slice(1), owner.references));
6751 }
6752
6753 name = deconflict_map.get(node.name);
6754 }
6755
6756 return [c(name, node)];
6757 },
6758
6759 Literal(node, state) {
6760 if (typeof node.value === 'string') {
6761 return [
6762 // TODO do we need to handle weird unicode characters somehow?
6763 // str.replace(/\\u(\d{4})/g, (m, n) => String.fromCharCode(+n))
6764 c(JSON.stringify(node.value).replace(re, (_m, _i, at, hash, name) => {
6765 if (at) return '@' + name;
6766 if (hash) return '#' + name;
6767 throw new Error(`this shouldn't happen`);
6768 }), node)
6769 ];
6770 }
6771
6772 const { regex } = node ; // TODO is this right?
6773 if (regex) {
6774 return [c(`/${regex.pattern}/${regex.flags}`, node)];
6775 }
6776
6777 return [c(String(node.value), node)];
6778 }
6779 };
6780
6781 handlers.ForOfStatement = handlers.ForInStatement;
6782 handlers.FunctionExpression = handlers.FunctionDeclaration;
6783 handlers.ClassExpression = handlers.ClassDeclaration;
6784 handlers.ClassBody = handlers.BlockStatement;
6785 handlers.SpreadElement = handlers.RestElement;
6786 handlers.ArrayPattern = handlers.ArrayExpression;
6787 handlers.LogicalExpression = handlers.BinaryExpression;
6788 handlers.AssignmentPattern = handlers.AssignmentExpression;
6789
6790 let btoa = () => {
6791 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
6792 };
6793 if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
6794 btoa = (str) => window.btoa(unescape(encodeURIComponent(str)));
6795 } else if (typeof Buffer === 'function') {
6796 btoa = (str) => Buffer.from(str, 'utf-8').toString('base64');
6797 }
6798
6799
6800
6801
6802
6803
6804
6805
6806 function print(node, opts = {}) {
6807 if (Array.isArray(node)) {
6808 return print({
6809 type: 'Program',
6810 body: node
6811 } , opts);
6812 }
6813
6814 const {
6815 getName = (x) => {
6816 throw new Error(`Unhandled sigil @${x}`);
6817 }
6818 } = opts;
6819
6820 let { map: scope_map, scope } = analyze(node);
6821 const deconflicted = new WeakMap();
6822
6823 const chunks = handle(node, {
6824 indent: '',
6825 getName,
6826 scope,
6827 scope_map,
6828 deconflicted,
6829 comments: []
6830 });
6831
6832
6833
6834 let code = '';
6835 let mappings = [];
6836 let current_line = [];
6837 let current_column = 0;
6838
6839 for (let i = 0; i < chunks.length; i += 1) {
6840 const chunk = chunks[i];
6841
6842 code += chunk.content;
6843
6844 if (chunk.loc) {
6845 current_line.push([
6846 current_column,
6847 0, // source index is always zero
6848 chunk.loc.start.line - 1,
6849 chunk.loc.start.column,
6850 ]);
6851 }
6852
6853 for (let i = 0; i < chunk.content.length; i += 1) {
6854 if (chunk.content[i] === '\n') {
6855 mappings.push(current_line);
6856 current_line = [];
6857 current_column = 0;
6858 } else {
6859 current_column += 1;
6860 }
6861 }
6862
6863 if (chunk.loc) {
6864 current_line.push([
6865 current_column,
6866 0, // source index is always zero
6867 chunk.loc.end.line - 1,
6868 chunk.loc.end.column,
6869 ]);
6870 }
6871 }
6872
6873 mappings.push(current_line);
6874
6875 const map = {
6876 version: 3,
6877 names: [] ,
6878 sources: [opts.sourceMapSource || null],
6879 sourcesContent: [opts.sourceMapContent || null],
6880 mappings: encode(mappings)
6881 };
6882
6883 Object.defineProperties(map, {
6884 toString: {
6885 enumerable: false,
6886 value: function toString() {
6887 return JSON.stringify(this);
6888 }
6889 },
6890 toUrl: {
6891 enumerable: false,
6892 value: function toUrl() {
6893 return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString());
6894 }
6895 }
6896 });
6897
6898 return {
6899 code,
6900 map
6901 };
6902 }
6903
6904 const sigils = {
6905 '@': 'AT',
6906 '#': 'HASH'
6907 };
6908
6909 const join$1 = (strings) => {
6910 let str = strings[0];
6911 for (let i = 1; i < strings.length; i += 1) {
6912 str += `_${id}_${i - 1}_${strings[i]}`;
6913 }
6914 return str.replace(/([@#])(\w+)/g, (_m, sigil, name) => `_${id}_${sigils[sigil]}_${name}`);
6915 };
6916
6917 const flatten_body = (array, target) => {
6918 for (let i = 0; i < array.length; i += 1) {
6919 const statement = array[i];
6920 if (Array.isArray(statement)) {
6921 flatten_body(statement, target);
6922 continue;
6923 }
6924
6925 if (statement.type === 'ExpressionStatement') {
6926 if (statement.expression === EMPTY) continue;
6927
6928 if (Array.isArray(statement.expression)) {
6929 // TODO this is hacktacular
6930 let node = statement.expression[0];
6931 while (Array.isArray(node)) node = node[0];
6932 if (node) node.leadingComments = statement.leadingComments;
6933
6934 flatten_body(statement.expression, target);
6935 continue;
6936 }
6937
6938 if (/(Expression|Literal)$/.test(statement.expression.type)) {
6939 target.push(statement);
6940 continue;
6941 }
6942
6943 if (statement.leadingComments) statement.expression.leadingComments = statement.leadingComments;
6944 if (statement.trailingComments) statement.expression.trailingComments = statement.trailingComments;
6945
6946 target.push(statement.expression);
6947 continue;
6948 }
6949
6950 target.push(statement);
6951 }
6952
6953 return target;
6954 };
6955
6956 const flatten_properties = (array, target) => {
6957 for (let i = 0; i < array.length; i += 1) {
6958 const property = array[i];
6959
6960 if (property.value === EMPTY) continue;
6961
6962 if (property.key === property.value && Array.isArray(property.key)) {
6963 flatten_properties(property.key, target);
6964 continue;
6965 }
6966
6967 target.push(property);
6968 }
6969
6970 return target;
6971 };
6972
6973 const flatten = (nodes, target) => {
6974 for (let i = 0; i < nodes.length; i += 1) {
6975 const node = nodes[i];
6976
6977 if (node === EMPTY) continue;
6978
6979 if (Array.isArray(node)) {
6980 flatten(node, target);
6981 continue;
6982 }
6983
6984 target.push(node);
6985 }
6986
6987 return target;
6988 };
6989
6990 const EMPTY = { type: 'Empty' };
6991
6992 const acorn_opts = (comments, raw) => {
6993 const { onComment } = get_comment_handlers(comments, raw);
6994 return {
6995 ecmaVersion: 11,
6996 sourceType: 'module',
6997 allowAwaitOutsideFunction: true,
6998 allowImportExportEverywhere: true,
6999 allowReturnOutsideFunction: true,
7000 onComment
7001 } ;
7002 };
7003
7004 const inject = (raw, node, values, comments) => {
7005 comments.forEach(comment => {
7006 comment.value = comment.value.replace(re, (m, i) => +i in values ? values[+i] : m);
7007 });
7008
7009 const { enter, leave } = get_comment_handlers(comments, raw);
7010
7011 walk(node, {
7012 enter,
7013
7014 leave(node, parent, key, index) {
7015 if (node.type === 'Identifier') {
7016 re.lastIndex = 0;
7017 const match = re.exec(node.name);
7018
7019 if (match) {
7020 if (match[1]) {
7021 if (+match[1] in values) {
7022 let value = values[+match[1]];
7023
7024 if (typeof value === 'string') {
7025 value = { type: 'Identifier', name: value, leadingComments: node.leadingComments, trailingComments: node.trailingComments };
7026 } else if (typeof value === 'number') {
7027 value = { type: 'Literal', value, leadingComments: node.leadingComments, trailingComments: node.trailingComments };
7028 }
7029
7030 this.replace(value || EMPTY);
7031 }
7032 } else {
7033 node.name = `${match[2] ? `@` : `#`}${match[4]}`;
7034 }
7035 }
7036 }
7037
7038 if (node.type === 'Literal') {
7039 if (typeof node.value === 'string') {
7040 re.lastIndex = 0;
7041 node.value = node.value.replace(re, (m, i) => +i in values ? values[+i] : m);
7042 }
7043 }
7044
7045 if (node.type === 'TemplateElement') {
7046 re.lastIndex = 0;
7047 node.value.raw = (node.value.raw ).replace(re, (m, i) => +i in values ? values[+i] : m);
7048 }
7049
7050 if (node.type === 'Program' || node.type === 'BlockStatement') {
7051 node.body = flatten_body(node.body, []);
7052 }
7053
7054 if (node.type === 'ObjectExpression' || node.type === 'ObjectPattern') {
7055 node.properties = flatten_properties(node.properties, []);
7056 }
7057
7058 if (node.type === 'ArrayExpression' || node.type === 'ArrayPattern') {
7059 node.elements = flatten(node.elements, []);
7060 }
7061
7062 if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') {
7063 node.params = flatten(node.params, []);
7064 }
7065
7066 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
7067 node.arguments = flatten(node.arguments, []);
7068 }
7069
7070 if (node.type === 'ImportDeclaration' || node.type === 'ExportNamedDeclaration') {
7071 node.specifiers = flatten(node.specifiers, []);
7072 }
7073
7074 if (node.type === 'ForStatement') {
7075 node.init = node.init === EMPTY ? null : node.init;
7076 node.test = node.test === EMPTY ? null : node.test;
7077 node.update = node.update === EMPTY ? null : node.update;
7078 }
7079
7080 leave(node);
7081 }
7082 });
7083 };
7084
7085 function b(strings, ...values) {
7086 const str = join$1(strings);
7087 const comments = [];
7088
7089 try {
7090 const ast = parse(str, acorn_opts(comments, str));
7091
7092 inject(str, ast, values, comments);
7093
7094 return ast.body;
7095 } catch (err) {
7096 handle_error(str, err);
7097 }
7098 }
7099
7100 function x(strings, ...values) {
7101 const str = join$1(strings);
7102 const comments = [];
7103
7104 try {
7105 const expression = parseExpressionAt(str, 0, acorn_opts(comments, str)) ;
7106 const match = /\S+/.exec(str.slice((expression ).end));
7107 if (match) {
7108 throw new Error(`Unexpected token '${match[0]}'`);
7109 }
7110
7111 inject(str, expression, values, comments);
7112
7113 return expression;
7114 } catch (err) {
7115 handle_error(str, err);
7116 }
7117 }
7118
7119 function p(strings, ...values) {
7120 const str = `{${join$1(strings)}}`;
7121 const comments = [];
7122
7123 try {
7124 const expression = parseExpressionAt(str, 0, acorn_opts(comments, str)) ;
7125
7126 inject(str, expression, values, comments);
7127
7128 return expression.properties[0];
7129 } catch (err) {
7130 handle_error(str, err);
7131 }
7132 }
7133
7134 function handle_error(str, err) {
7135 // TODO location/code frame
7136
7137 re.lastIndex = 0;
7138
7139 str = str.replace(re, (m, i, at, hash, name) => {
7140 if (at) return `@${name}`;
7141 if (hash) return `#${name}`;
7142
7143 return '${...}';
7144 });
7145
7146 console.log(`failed to parse:\n${str}`);
7147 throw err;
7148 }
7149
7150 const parse$1 = (source, opts) => {
7151 const comments = [];
7152 const { onComment, enter, leave } = get_comment_handlers(comments, source);
7153 const ast = parse(source, { onComment, ...opts });
7154 walk(ast , { enter, leave });
7155 return ast;
7156 };
7157
7158 const parseExpressionAt$1 = (source, index, opts) => {
7159 const comments = [];
7160 const { onComment, enter, leave } = get_comment_handlers(comments, source);
7161 const ast = parseExpressionAt(source, index, { onComment, ...opts });
7162 walk(ast , { enter, leave });
7163 return ast;
7164 };
7165
7166 const parse$2 = (source) => parse$1(source, {
7167 sourceType: 'module',
7168 ecmaVersion: 11,
7169 locations: true
7170 });
7171 const parse_expression_at = (source, index) => parseExpressionAt$1(source, index, {
7172 ecmaVersion: 11,
7173 locations: true
7174 });
7175
7176 const whitespace = /[ \t\r\n]/;
7177 const dimensions = /^(?:offset|client)(?:Width|Height)$/;
7178
7179 function read_expression(parser) {
7180 try {
7181 const node = parse_expression_at(parser.template, parser.index);
7182 let num_parens = 0;
7183 for (let i = parser.index; i < node.start; i += 1) {
7184 if (parser.template[i] === '(')
7185 num_parens += 1;
7186 }
7187 let index = node.end;
7188 while (num_parens > 0) {
7189 const char = parser.template[index];
7190 if (char === ')') {
7191 num_parens -= 1;
7192 }
7193 else if (!whitespace.test(char)) {
7194 parser.error({
7195 code: 'unexpected-token',
7196 message: 'Expected )'
7197 }, index);
7198 }
7199 index += 1;
7200 }
7201 parser.index = index;
7202 return node;
7203 }
7204 catch (err) {
7205 parser.acorn_error(err);
7206 }
7207 }
7208
7209 const script_closing_tag = '</script>';
7210 function get_context(parser, attributes, start) {
7211 const context = attributes.find(attribute => attribute.name === 'context');
7212 if (!context)
7213 return 'default';
7214 if (context.value.length !== 1 || context.value[0].type !== 'Text') {
7215 parser.error({
7216 code: 'invalid-script',
7217 message: `context attribute must be static`
7218 }, start);
7219 }
7220 const value = context.value[0].data;
7221 if (value !== 'module') {
7222 parser.error({
7223 code: `invalid-script`,
7224 message: `If the context attribute is supplied, its value must be "module"`
7225 }, context.start);
7226 }
7227 return value;
7228 }
7229 function read_script(parser, start, attributes) {
7230 const script_start = parser.index;
7231 const script_end = parser.template.indexOf(script_closing_tag, script_start);
7232 if (script_end === -1)
7233 parser.error({
7234 code: `unclosed-script`,
7235 message: `<script> must have a closing tag`
7236 });
7237 const source = parser.template.slice(0, script_start).replace(/[^\n]/g, ' ') +
7238 parser.template.slice(script_start, script_end);
7239 parser.index = script_end + script_closing_tag.length;
7240 let ast;
7241 try {
7242 ast = parse$2(source);
7243 }
7244 catch (err) {
7245 parser.acorn_error(err);
7246 }
7247 // TODO is this necessary?
7248 ast.start = script_start;
7249 return {
7250 type: 'Script',
7251 start,
7252 end: parser.index,
7253 context: get_context(parser, attributes, start),
7254 content: ast,
7255 };
7256 }
7257
7258 var MAX_LINE_LENGTH = 100;
7259 var OFFSET_CORRECTION = 60;
7260 var TAB_REPLACEMENT = ' ';
7261
7262 function sourceFragment(error, extraLines) {
7263 function processLines(start, end) {
7264 return lines.slice(start, end).map(function(line, idx) {
7265 var num = String(start + idx + 1);
7266
7267 while (num.length < maxNumLength) {
7268 num = ' ' + num;
7269 }
7270
7271 return num + ' |' + line;
7272 }).join('\n');
7273 }
7274
7275 var lines = error.source.split(/\n|\r\n?|\f/);
7276 var line = error.line;
7277 var column = error.column;
7278 var startLine = Math.max(1, line - extraLines) - 1;
7279 var endLine = Math.min(line + extraLines, lines.length + 1);
7280 var maxNumLength = Math.max(4, String(endLine).length) + 1;
7281 var cutLeft = 0;
7282
7283 // correct column according to replaced tab before column
7284 column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;
7285
7286 if (column > MAX_LINE_LENGTH) {
7287 cutLeft = column - OFFSET_CORRECTION + 3;
7288 column = OFFSET_CORRECTION - 2;
7289 }
7290
7291 for (var i = startLine; i <= endLine; i++) {
7292 if (i >= 0 && i < lines.length) {
7293 lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT);
7294 lines[i] =
7295 (cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
7296 lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
7297 (lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
7298 }
7299 }
7300
7301 return [
7302 processLines(startLine, line),
7303 new Array(column + maxNumLength + 2).join('-') + '^',
7304 processLines(line, endLine)
7305 ].join('\n');
7306 }
7307
7308 var CssSyntaxError = function(message, source, offset, line, column) {
7309 // some VMs prevent setting line/column otherwise (iOS Safari 10 even throw an exception)
7310 var error = Object.create(SyntaxError.prototype);
7311
7312 error.name = 'CssSyntaxError';
7313 error.message = message;
7314 error.stack = (new Error().stack || '').replace(/^.+\n/, error.name + ': ' + error.message + '\n');
7315 error.source = source;
7316 error.offset = offset;
7317 error.line = line;
7318 error.column = column;
7319
7320 error.sourceFragment = function(extraLines) {
7321 return sourceFragment(error, isNaN(extraLines) ? 0 : extraLines);
7322 };
7323 Object.defineProperty(error, 'formattedMessage', {
7324 get: function() {
7325 return (
7326 'Parse error: ' + error.message + '\n' +
7327 sourceFragment(error, 2)
7328 );
7329 }
7330 });
7331
7332 // for backward capability
7333 error.parseError = {
7334 offset: offset,
7335 line: line,
7336 column: column
7337 };
7338
7339 return error;
7340 };
7341
7342 var error = CssSyntaxError;
7343
7344 // token types (note: value shouldn't intersect with used char codes)
7345 var WHITESPACE = 1;
7346 var IDENTIFIER = 2;
7347 var NUMBER = 3;
7348 var STRING = 4;
7349 var COMMENT = 5;
7350 var PUNCTUATOR = 6;
7351 var CDO = 7;
7352 var CDC = 8;
7353 var ATRULE = 14;
7354 var FUNCTION = 15;
7355 var URL = 16;
7356 var RAW = 17;
7357
7358 var TAB = 9;
7359 var N = 10;
7360 var F = 12;
7361 var R = 13;
7362 var SPACE = 32;
7363
7364 var TYPE = {
7365 WhiteSpace: WHITESPACE,
7366 Identifier: IDENTIFIER,
7367 Number: NUMBER,
7368 String: STRING,
7369 Comment: COMMENT,
7370 Punctuator: PUNCTUATOR,
7371 CDO: CDO,
7372 CDC: CDC,
7373 Atrule: ATRULE,
7374 Function: FUNCTION,
7375 Url: URL,
7376 Raw: RAW,
7377
7378 ExclamationMark: 33, // !
7379 QuotationMark: 34, // "
7380 NumberSign: 35, // #
7381 DollarSign: 36, // $
7382 PercentSign: 37, // %
7383 Ampersand: 38, // &
7384 Apostrophe: 39, // '
7385 LeftParenthesis: 40, // (
7386 RightParenthesis: 41, // )
7387 Asterisk: 42, // *
7388 PlusSign: 43, // +
7389 Comma: 44, // ,
7390 HyphenMinus: 45, // -
7391 FullStop: 46, // .
7392 Solidus: 47, // /
7393 Colon: 58, // :
7394 Semicolon: 59, // ;
7395 LessThanSign: 60, // <
7396 EqualsSign: 61, // =
7397 GreaterThanSign: 62, // >
7398 QuestionMark: 63, // ?
7399 CommercialAt: 64, // @
7400 LeftSquareBracket: 91, // [
7401 Backslash: 92, // \
7402 RightSquareBracket: 93, // ]
7403 CircumflexAccent: 94, // ^
7404 LowLine: 95, // _
7405 GraveAccent: 96, // `
7406 LeftCurlyBracket: 123, // {
7407 VerticalLine: 124, // |
7408 RightCurlyBracket: 125, // }
7409 Tilde: 126 // ~
7410 };
7411
7412 var NAME = Object.keys(TYPE).reduce(function(result, key) {
7413 result[TYPE[key]] = key;
7414 return result;
7415 }, {});
7416
7417 // https://drafts.csswg.org/css-syntax/#tokenizer-definitions
7418 // > non-ASCII code point
7419 // > A code point with a value equal to or greater than U+0080 <control>
7420 // > name-start code point
7421 // > A letter, a non-ASCII code point, or U+005F LOW LINE (_).
7422 // > name code point
7423 // > A name-start code point, a digit, or U+002D HYPHEN-MINUS (-)
7424 // That means only ASCII code points has a special meaning and we a maps for 0..127 codes only
7425 var SafeUint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
7426 var SYMBOL_TYPE = new SafeUint32Array(0x80);
7427 var PUNCTUATION = new SafeUint32Array(0x80);
7428 var STOP_URL_RAW = new SafeUint32Array(0x80);
7429
7430 for (var i = 0; i < SYMBOL_TYPE.length; i++) {
7431 SYMBOL_TYPE[i] = IDENTIFIER;
7432 }
7433
7434 // fill categories
7435 [
7436 TYPE.ExclamationMark, // !
7437 TYPE.QuotationMark, // "
7438 TYPE.NumberSign, // #
7439 TYPE.DollarSign, // $
7440 TYPE.PercentSign, // %
7441 TYPE.Ampersand, // &
7442 TYPE.Apostrophe, // '
7443 TYPE.LeftParenthesis, // (
7444 TYPE.RightParenthesis, // )
7445 TYPE.Asterisk, // *
7446 TYPE.PlusSign, // +
7447 TYPE.Comma, // ,
7448 TYPE.HyphenMinus, // -
7449 TYPE.FullStop, // .
7450 TYPE.Solidus, // /
7451 TYPE.Colon, // :
7452 TYPE.Semicolon, // ;
7453 TYPE.LessThanSign, // <
7454 TYPE.EqualsSign, // =
7455 TYPE.GreaterThanSign, // >
7456 TYPE.QuestionMark, // ?
7457 TYPE.CommercialAt, // @
7458 TYPE.LeftSquareBracket, // [
7459 // TYPE.Backslash, // \
7460 TYPE.RightSquareBracket, // ]
7461 TYPE.CircumflexAccent, // ^
7462 // TYPE.LowLine, // _
7463 TYPE.GraveAccent, // `
7464 TYPE.LeftCurlyBracket, // {
7465 TYPE.VerticalLine, // |
7466 TYPE.RightCurlyBracket, // }
7467 TYPE.Tilde // ~
7468 ].forEach(function(key) {
7469 SYMBOL_TYPE[Number(key)] = PUNCTUATOR;
7470 PUNCTUATION[Number(key)] = PUNCTUATOR;
7471 });
7472
7473 for (var i = 48; i <= 57; i++) {
7474 SYMBOL_TYPE[i] = NUMBER;
7475 }
7476
7477 SYMBOL_TYPE[SPACE] = WHITESPACE;
7478 SYMBOL_TYPE[TAB] = WHITESPACE;
7479 SYMBOL_TYPE[N] = WHITESPACE;
7480 SYMBOL_TYPE[R] = WHITESPACE;
7481 SYMBOL_TYPE[F] = WHITESPACE;
7482
7483 SYMBOL_TYPE[TYPE.Apostrophe] = STRING;
7484 SYMBOL_TYPE[TYPE.QuotationMark] = STRING;
7485
7486 STOP_URL_RAW[SPACE] = 1;
7487 STOP_URL_RAW[TAB] = 1;
7488 STOP_URL_RAW[N] = 1;
7489 STOP_URL_RAW[R] = 1;
7490 STOP_URL_RAW[F] = 1;
7491 STOP_URL_RAW[TYPE.Apostrophe] = 1;
7492 STOP_URL_RAW[TYPE.QuotationMark] = 1;
7493 STOP_URL_RAW[TYPE.LeftParenthesis] = 1;
7494 STOP_URL_RAW[TYPE.RightParenthesis] = 1;
7495
7496 // whitespace is punctuation ...
7497 PUNCTUATION[SPACE] = PUNCTUATOR;
7498 PUNCTUATION[TAB] = PUNCTUATOR;
7499 PUNCTUATION[N] = PUNCTUATOR;
7500 PUNCTUATION[R] = PUNCTUATOR;
7501 PUNCTUATION[F] = PUNCTUATOR;
7502 // ... hyper minus is not
7503 PUNCTUATION[TYPE.HyphenMinus] = 0;
7504
7505 var _const = {
7506 TYPE: TYPE,
7507 NAME: NAME,
7508
7509 SYMBOL_TYPE: SYMBOL_TYPE,
7510 PUNCTUATION: PUNCTUATION,
7511 STOP_URL_RAW: STOP_URL_RAW
7512 };
7513
7514 var PUNCTUATION$1 = _const.PUNCTUATION;
7515 var STOP_URL_RAW$1 = _const.STOP_URL_RAW;
7516 var TYPE$1 = _const.TYPE;
7517 var FULLSTOP = TYPE$1.FullStop;
7518 var PLUSSIGN = TYPE$1.PlusSign;
7519 var HYPHENMINUS = TYPE$1.HyphenMinus;
7520 var PUNCTUATOR$1 = TYPE$1.Punctuator;
7521 var TAB$1 = 9;
7522 var N$1 = 10;
7523 var F$1 = 12;
7524 var R$1 = 13;
7525 var SPACE$1 = 32;
7526 var BACK_SLASH = 92;
7527 var E = 101; // 'e'.charCodeAt(0)
7528
7529 function firstCharOffset(source) {
7530 // detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
7531 if (source.charCodeAt(0) === 0xFEFF || // UTF-16BE
7532 source.charCodeAt(0) === 0xFFFE) { // UTF-16LE
7533 return 1;
7534 }
7535
7536 return 0;
7537 }
7538
7539 function isHex(code) {
7540 return (code >= 48 && code <= 57) || // 0 .. 9
7541 (code >= 65 && code <= 70) || // A .. F
7542 (code >= 97 && code <= 102); // a .. f
7543 }
7544
7545 function isNumber(code) {
7546 return code >= 48 && code <= 57;
7547 }
7548
7549 function isNewline(source, offset, code) {
7550 if (code === N$1 || code === F$1 || code === R$1) {
7551 if (code === R$1 && offset + 1 < source.length && source.charCodeAt(offset + 1) === N$1) {
7552 return 2;
7553 }
7554
7555 return 1;
7556 }
7557
7558 return 0;
7559 }
7560
7561 function cmpChar(testStr, offset, referenceCode) {
7562 var code = testStr.charCodeAt(offset);
7563
7564 // code.toLowerCase()
7565 if (code >= 65 && code <= 90) {
7566 code = code | 32;
7567 }
7568
7569 return code === referenceCode;
7570 }
7571
7572 function cmpStr(testStr, start, end, referenceStr) {
7573 if (end - start !== referenceStr.length) {
7574 return false;
7575 }
7576
7577 if (start < 0 || end > testStr.length) {
7578 return false;
7579 }
7580
7581 for (var i = start; i < end; i++) {
7582 var testCode = testStr.charCodeAt(i);
7583 var refCode = referenceStr.charCodeAt(i - start);
7584
7585 // testStr[i].toLowerCase()
7586 if (testCode >= 65 && testCode <= 90) {
7587 testCode = testCode | 32;
7588 }
7589
7590 if (testCode !== refCode) {
7591 return false;
7592 }
7593 }
7594
7595 return true;
7596 }
7597
7598 function endsWith(testStr, referenceStr) {
7599 return cmpStr(testStr, testStr.length - referenceStr.length, testStr.length, referenceStr);
7600 }
7601
7602 function findLastNonSpaceLocation(scanner) {
7603 for (var i = scanner.source.length - 1; i >= 0; i--) {
7604 var code = scanner.source.charCodeAt(i);
7605
7606 if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
7607 break;
7608 }
7609 }
7610
7611 return scanner.getLocation(i + 1);
7612 }
7613
7614 function findWhiteSpaceEnd(source, offset) {
7615 for (; offset < source.length; offset++) {
7616 var code = source.charCodeAt(offset);
7617
7618 if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
7619 break;
7620 }
7621 }
7622
7623 return offset;
7624 }
7625
7626 function findCommentEnd(source, offset) {
7627 var commentEnd = source.indexOf('*/', offset);
7628
7629 if (commentEnd === -1) {
7630 return source.length;
7631 }
7632
7633 return commentEnd + 2;
7634 }
7635
7636 function findStringEnd(source, offset, quote) {
7637 for (; offset < source.length; offset++) {
7638 var code = source.charCodeAt(offset);
7639
7640 // TODO: bad string
7641 if (code === BACK_SLASH) {
7642 offset++;
7643 } else if (code === quote) {
7644 offset++;
7645 break;
7646 }
7647 }
7648
7649 return offset;
7650 }
7651
7652 function findDecimalNumberEnd(source, offset) {
7653 for (; offset < source.length; offset++) {
7654 var code = source.charCodeAt(offset);
7655
7656 if (code < 48 || code > 57) { // not a 0 .. 9
7657 break;
7658 }
7659 }
7660
7661 return offset;
7662 }
7663
7664 function findNumberEnd(source, offset, allowFraction) {
7665 var code;
7666
7667 offset = findDecimalNumberEnd(source, offset);
7668
7669 // fraction: .\d+
7670 if (allowFraction && offset + 1 < source.length && source.charCodeAt(offset) === FULLSTOP) {
7671 code = source.charCodeAt(offset + 1);
7672
7673 if (isNumber(code)) {
7674 offset = findDecimalNumberEnd(source, offset + 1);
7675 }
7676 }
7677
7678 // exponent: e[+-]\d+
7679 if (offset + 1 < source.length) {
7680 if ((source.charCodeAt(offset) | 32) === E) { // case insensitive check for `e`
7681 code = source.charCodeAt(offset + 1);
7682
7683 if (code === PLUSSIGN || code === HYPHENMINUS) {
7684 if (offset + 2 < source.length) {
7685 code = source.charCodeAt(offset + 2);
7686 }
7687 }
7688
7689 if (isNumber(code)) {
7690 offset = findDecimalNumberEnd(source, offset + 2);
7691 }
7692 }
7693 }
7694
7695 return offset;
7696 }
7697
7698 // skip escaped unicode sequence that can ends with space
7699 // [0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
7700 function findEscaseEnd(source, offset) {
7701 for (var i = 0; i < 7 && offset + i < source.length; i++) {
7702 var code = source.charCodeAt(offset + i);
7703
7704 if (i !== 6 && isHex(code)) {
7705 continue;
7706 }
7707
7708 if (i > 0) {
7709 offset += i - 1 + isNewline(source, offset + i, code);
7710 if (code === SPACE$1 || code === TAB$1) {
7711 offset++;
7712 }
7713 }
7714
7715 break;
7716 }
7717
7718 return offset;
7719 }
7720
7721 function findIdentifierEnd(source, offset) {
7722 for (; offset < source.length; offset++) {
7723 var code = source.charCodeAt(offset);
7724
7725 if (code === BACK_SLASH) {
7726 offset = findEscaseEnd(source, offset + 1);
7727 } else if (code < 0x80 && PUNCTUATION$1[code] === PUNCTUATOR$1) {
7728 break;
7729 }
7730 }
7731
7732 return offset;
7733 }
7734
7735 function findUrlRawEnd(source, offset) {
7736 for (; offset < source.length; offset++) {
7737 var code = source.charCodeAt(offset);
7738
7739 if (code === BACK_SLASH) {
7740 offset = findEscaseEnd(source, offset + 1);
7741 } else if (code < 0x80 && STOP_URL_RAW$1[code] === 1) {
7742 break;
7743 }
7744 }
7745
7746 return offset;
7747 }
7748
7749 var utils = {
7750 firstCharOffset: firstCharOffset,
7751
7752 isHex: isHex,
7753 isNumber: isNumber,
7754 isNewline: isNewline,
7755
7756 cmpChar: cmpChar,
7757 cmpStr: cmpStr,
7758 endsWith: endsWith,
7759
7760 findLastNonSpaceLocation: findLastNonSpaceLocation,
7761 findWhiteSpaceEnd: findWhiteSpaceEnd,
7762 findCommentEnd: findCommentEnd,
7763 findStringEnd: findStringEnd,
7764 findDecimalNumberEnd: findDecimalNumberEnd,
7765 findNumberEnd: findNumberEnd,
7766 findEscaseEnd: findEscaseEnd,
7767 findIdentifierEnd: findIdentifierEnd,
7768 findUrlRawEnd: findUrlRawEnd
7769 };
7770
7771 var TYPE$2 = _const.TYPE;
7772 var NAME$1 = _const.NAME;
7773 var SYMBOL_TYPE$1 = _const.SYMBOL_TYPE;
7774
7775
7776 var firstCharOffset$1 = utils.firstCharOffset;
7777 var cmpStr$1 = utils.cmpStr;
7778 var isNumber$1 = utils.isNumber;
7779 var findLastNonSpaceLocation$1 = utils.findLastNonSpaceLocation;
7780 var findWhiteSpaceEnd$1 = utils.findWhiteSpaceEnd;
7781 var findCommentEnd$1 = utils.findCommentEnd;
7782 var findStringEnd$1 = utils.findStringEnd;
7783 var findNumberEnd$1 = utils.findNumberEnd;
7784 var findIdentifierEnd$1 = utils.findIdentifierEnd;
7785 var findUrlRawEnd$1 = utils.findUrlRawEnd;
7786
7787 var NULL = 0;
7788 var WHITESPACE$1 = TYPE$2.WhiteSpace;
7789 var IDENTIFIER$1 = TYPE$2.Identifier;
7790 var NUMBER$1 = TYPE$2.Number;
7791 var STRING$1 = TYPE$2.String;
7792 var COMMENT$1 = TYPE$2.Comment;
7793 var PUNCTUATOR$2 = TYPE$2.Punctuator;
7794 var CDO$1 = TYPE$2.CDO;
7795 var CDC$1 = TYPE$2.CDC;
7796 var ATRULE$1 = TYPE$2.Atrule;
7797 var FUNCTION$1 = TYPE$2.Function;
7798 var URL$1 = TYPE$2.Url;
7799 var RAW$1 = TYPE$2.Raw;
7800
7801 var N$2 = 10;
7802 var F$2 = 12;
7803 var R$2 = 13;
7804 var STAR = TYPE$2.Asterisk;
7805 var SLASH = TYPE$2.Solidus;
7806 var FULLSTOP$1 = TYPE$2.FullStop;
7807 var PLUSSIGN$1 = TYPE$2.PlusSign;
7808 var HYPHENMINUS$1 = TYPE$2.HyphenMinus;
7809 var GREATERTHANSIGN = TYPE$2.GreaterThanSign;
7810 var LESSTHANSIGN = TYPE$2.LessThanSign;
7811 var EXCLAMATIONMARK = TYPE$2.ExclamationMark;
7812 var COMMERCIALAT = TYPE$2.CommercialAt;
7813 var QUOTATIONMARK = TYPE$2.QuotationMark;
7814 var APOSTROPHE = TYPE$2.Apostrophe;
7815 var LEFTPARENTHESIS = TYPE$2.LeftParenthesis;
7816 var RIGHTPARENTHESIS = TYPE$2.RightParenthesis;
7817 var LEFTCURLYBRACKET = TYPE$2.LeftCurlyBracket;
7818 var RIGHTCURLYBRACKET = TYPE$2.RightCurlyBracket;
7819 var LEFTSQUAREBRACKET = TYPE$2.LeftSquareBracket;
7820 var RIGHTSQUAREBRACKET = TYPE$2.RightSquareBracket;
7821
7822 var MIN_BUFFER_SIZE = 16 * 1024;
7823 var OFFSET_MASK = 0x00FFFFFF;
7824 var TYPE_SHIFT = 24;
7825 var SafeUint32Array$1 = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
7826
7827 function computeLinesAndColumns(tokenizer, source) {
7828 var sourceLength = source.length;
7829 var start = firstCharOffset$1(source);
7830 var lines = tokenizer.lines;
7831 var line = tokenizer.startLine;
7832 var columns = tokenizer.columns;
7833 var column = tokenizer.startColumn;
7834
7835 if (lines === null || lines.length < sourceLength + 1) {
7836 lines = new SafeUint32Array$1(Math.max(sourceLength + 1024, MIN_BUFFER_SIZE));
7837 columns = new SafeUint32Array$1(lines.length);
7838 }
7839
7840 for (var i = start; i < sourceLength; i++) {
7841 var code = source.charCodeAt(i);
7842
7843 lines[i] = line;
7844 columns[i] = column++;
7845
7846 if (code === N$2 || code === R$2 || code === F$2) {
7847 if (code === R$2 && i + 1 < sourceLength && source.charCodeAt(i + 1) === N$2) {
7848 i++;
7849 lines[i] = line;
7850 columns[i] = column;
7851 }
7852
7853 line++;
7854 column = 1;
7855 }
7856 }
7857
7858 lines[i] = line;
7859 columns[i] = column;
7860
7861 tokenizer.linesAnsColumnsComputed = true;
7862 tokenizer.lines = lines;
7863 tokenizer.columns = columns;
7864 }
7865
7866 function tokenLayout(tokenizer, source, startPos) {
7867 var sourceLength = source.length;
7868 var offsetAndType = tokenizer.offsetAndType;
7869 var balance = tokenizer.balance;
7870 var tokenCount = 0;
7871 var prevType = 0;
7872 var offset = startPos;
7873 var anchor = 0;
7874 var balanceCloseCode = 0;
7875 var balanceStart = 0;
7876 var balancePrev = 0;
7877
7878 if (offsetAndType === null || offsetAndType.length < sourceLength + 1) {
7879 offsetAndType = new SafeUint32Array$1(sourceLength + 1024);
7880 balance = new SafeUint32Array$1(sourceLength + 1024);
7881 }
7882
7883 while (offset < sourceLength) {
7884 var code = source.charCodeAt(offset);
7885 var type = code < 0x80 ? SYMBOL_TYPE$1[code] : IDENTIFIER$1;
7886
7887 balance[tokenCount] = sourceLength;
7888
7889 switch (type) {
7890 case WHITESPACE$1:
7891 offset = findWhiteSpaceEnd$1(source, offset + 1);
7892 break;
7893
7894 case PUNCTUATOR$2:
7895 switch (code) {
7896 case balanceCloseCode:
7897 balancePrev = balanceStart & OFFSET_MASK;
7898 balanceStart = balance[balancePrev];
7899 balanceCloseCode = balanceStart >> TYPE_SHIFT;
7900 balance[tokenCount] = balancePrev;
7901 balance[balancePrev++] = tokenCount;
7902 for (; balancePrev < tokenCount; balancePrev++) {
7903 if (balance[balancePrev] === sourceLength) {
7904 balance[balancePrev] = tokenCount;
7905 }
7906 }
7907 break;
7908
7909 case LEFTSQUAREBRACKET:
7910 balance[tokenCount] = balanceStart;
7911 balanceCloseCode = RIGHTSQUAREBRACKET;
7912 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
7913 break;
7914
7915 case LEFTCURLYBRACKET:
7916 balance[tokenCount] = balanceStart;
7917 balanceCloseCode = RIGHTCURLYBRACKET;
7918 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
7919 break;
7920
7921 case LEFTPARENTHESIS:
7922 balance[tokenCount] = balanceStart;
7923 balanceCloseCode = RIGHTPARENTHESIS;
7924 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
7925 break;
7926 }
7927
7928 // /*
7929 if (code === STAR && prevType === SLASH) {
7930 type = COMMENT$1;
7931 offset = findCommentEnd$1(source, offset + 1);
7932 tokenCount--; // rewrite prev token
7933 break;
7934 }
7935
7936 // edge case for -.123 and +.123
7937 if (code === FULLSTOP$1 && (prevType === PLUSSIGN$1 || prevType === HYPHENMINUS$1)) {
7938 if (offset + 1 < sourceLength && isNumber$1(source.charCodeAt(offset + 1))) {
7939 type = NUMBER$1;
7940 offset = findNumberEnd$1(source, offset + 2, false);
7941 tokenCount--; // rewrite prev token
7942 break;
7943 }
7944 }
7945
7946 // <!--
7947 if (code === EXCLAMATIONMARK && prevType === LESSTHANSIGN) {
7948 if (offset + 2 < sourceLength &&
7949 source.charCodeAt(offset + 1) === HYPHENMINUS$1 &&
7950 source.charCodeAt(offset + 2) === HYPHENMINUS$1) {
7951 type = CDO$1;
7952 offset = offset + 3;
7953 tokenCount--; // rewrite prev token
7954 break;
7955 }
7956 }
7957
7958 // -->
7959 if (code === HYPHENMINUS$1 && prevType === HYPHENMINUS$1) {
7960 if (offset + 1 < sourceLength && source.charCodeAt(offset + 1) === GREATERTHANSIGN) {
7961 type = CDC$1;
7962 offset = offset + 2;
7963 tokenCount--; // rewrite prev token
7964 break;
7965 }
7966 }
7967
7968 // ident(
7969 if (code === LEFTPARENTHESIS && prevType === IDENTIFIER$1) {
7970 offset = offset + 1;
7971 tokenCount--; // rewrite prev token
7972 balance[tokenCount] = balance[tokenCount + 1];
7973 balanceStart--;
7974
7975 // 4 char length identifier and equal to `url(` (case insensitive)
7976 if (offset - anchor === 4 && cmpStr$1(source, anchor, offset, 'url(')) {
7977 // special case for url() because it can contain any symbols sequence with few exceptions
7978 anchor = findWhiteSpaceEnd$1(source, offset);
7979 code = source.charCodeAt(anchor);
7980 if (code !== LEFTPARENTHESIS &&
7981 code !== RIGHTPARENTHESIS &&
7982 code !== QUOTATIONMARK &&
7983 code !== APOSTROPHE) {
7984 // url(
7985 offsetAndType[tokenCount++] = (URL$1 << TYPE_SHIFT) | offset;
7986 balance[tokenCount] = sourceLength;
7987
7988 // ws*
7989 if (anchor !== offset) {
7990 offsetAndType[tokenCount++] = (WHITESPACE$1 << TYPE_SHIFT) | anchor;
7991 balance[tokenCount] = sourceLength;
7992 }
7993
7994 // raw
7995 type = RAW$1;
7996 offset = findUrlRawEnd$1(source, anchor);
7997 } else {
7998 type = URL$1;
7999 }
8000 } else {
8001 type = FUNCTION$1;
8002 }
8003 break;
8004 }
8005
8006 type = code;
8007 offset = offset + 1;
8008 break;
8009
8010 case NUMBER$1:
8011 offset = findNumberEnd$1(source, offset + 1, prevType !== FULLSTOP$1);
8012
8013 // merge number with a preceding dot, dash or plus
8014 if (prevType === FULLSTOP$1 ||
8015 prevType === HYPHENMINUS$1 ||
8016 prevType === PLUSSIGN$1) {
8017 tokenCount--; // rewrite prev token
8018 }
8019
8020 break;
8021
8022 case STRING$1:
8023 offset = findStringEnd$1(source, offset + 1, code);
8024 break;
8025
8026 default:
8027 anchor = offset;
8028 offset = findIdentifierEnd$1(source, offset);
8029
8030 // merge identifier with a preceding dash
8031 if (prevType === HYPHENMINUS$1) {
8032 // rewrite prev token
8033 tokenCount--;
8034 // restore prev prev token type
8035 // for case @-prefix-ident
8036 prevType = tokenCount === 0 ? 0 : offsetAndType[tokenCount - 1] >> TYPE_SHIFT;
8037 }
8038
8039 if (prevType === COMMERCIALAT) {
8040 // rewrite prev token and change type to <at-keyword-token>
8041 tokenCount--;
8042 type = ATRULE$1;
8043 }
8044 }
8045
8046 offsetAndType[tokenCount++] = (type << TYPE_SHIFT) | offset;
8047 prevType = type;
8048 }
8049
8050 // finalize arrays
8051 offsetAndType[tokenCount] = offset;
8052 balance[tokenCount] = sourceLength;
8053 while (balanceStart !== 0) {
8054 balancePrev = balanceStart & OFFSET_MASK;
8055 balanceStart = balance[balancePrev];
8056 balance[balancePrev] = sourceLength;
8057 }
8058
8059 tokenizer.offsetAndType = offsetAndType;
8060 tokenizer.tokenCount = tokenCount;
8061 tokenizer.balance = balance;
8062 }
8063
8064 //
8065 // tokenizer
8066 //
8067
8068 var Tokenizer = function(source, startOffset, startLine, startColumn) {
8069 this.offsetAndType = null;
8070 this.balance = null;
8071 this.lines = null;
8072 this.columns = null;
8073
8074 this.setSource(source, startOffset, startLine, startColumn);
8075 };
8076
8077 Tokenizer.prototype = {
8078 setSource: function(source, startOffset, startLine, startColumn) {
8079 var safeSource = String(source || '');
8080 var start = firstCharOffset$1(safeSource);
8081
8082 this.source = safeSource;
8083 this.firstCharOffset = start;
8084 this.startOffset = typeof startOffset === 'undefined' ? 0 : startOffset;
8085 this.startLine = typeof startLine === 'undefined' ? 1 : startLine;
8086 this.startColumn = typeof startColumn === 'undefined' ? 1 : startColumn;
8087 this.linesAnsColumnsComputed = false;
8088
8089 this.eof = false;
8090 this.currentToken = -1;
8091 this.tokenType = 0;
8092 this.tokenStart = start;
8093 this.tokenEnd = start;
8094
8095 tokenLayout(this, safeSource, start);
8096 this.next();
8097 },
8098
8099 lookupType: function(offset) {
8100 offset += this.currentToken;
8101
8102 if (offset < this.tokenCount) {
8103 return this.offsetAndType[offset] >> TYPE_SHIFT;
8104 }
8105
8106 return NULL;
8107 },
8108 lookupNonWSType: function(offset) {
8109 offset += this.currentToken;
8110
8111 for (var type; offset < this.tokenCount; offset++) {
8112 type = this.offsetAndType[offset] >> TYPE_SHIFT;
8113
8114 if (type !== WHITESPACE$1) {
8115 return type;
8116 }
8117 }
8118
8119 return NULL;
8120 },
8121 lookupValue: function(offset, referenceStr) {
8122 offset += this.currentToken;
8123
8124 if (offset < this.tokenCount) {
8125 return cmpStr$1(
8126 this.source,
8127 this.offsetAndType[offset - 1] & OFFSET_MASK,
8128 this.offsetAndType[offset] & OFFSET_MASK,
8129 referenceStr
8130 );
8131 }
8132
8133 return false;
8134 },
8135 getTokenStart: function(tokenNum) {
8136 if (tokenNum === this.currentToken) {
8137 return this.tokenStart;
8138 }
8139
8140 if (tokenNum > 0) {
8141 return tokenNum < this.tokenCount
8142 ? this.offsetAndType[tokenNum - 1] & OFFSET_MASK
8143 : this.offsetAndType[this.tokenCount] & OFFSET_MASK;
8144 }
8145
8146 return this.firstCharOffset;
8147 },
8148 getOffsetExcludeWS: function() {
8149 if (this.currentToken > 0) {
8150 if ((this.offsetAndType[this.currentToken - 1] >> TYPE_SHIFT) === WHITESPACE$1) {
8151 return this.currentToken > 1
8152 ? this.offsetAndType[this.currentToken - 2] & OFFSET_MASK
8153 : this.firstCharOffset;
8154 }
8155 }
8156 return this.tokenStart;
8157 },
8158 getRawLength: function(startToken, endTokenType1, endTokenType2, includeTokenType2) {
8159 var cursor = startToken;
8160 var balanceEnd;
8161
8162 loop:
8163 for (; cursor < this.tokenCount; cursor++) {
8164 balanceEnd = this.balance[cursor];
8165
8166 // belance end points to offset before start
8167 if (balanceEnd < startToken) {
8168 break loop;
8169 }
8170
8171 // check token is stop type
8172 switch (this.offsetAndType[cursor] >> TYPE_SHIFT) {
8173 case endTokenType1:
8174 break loop;
8175
8176 case endTokenType2:
8177 if (includeTokenType2) {
8178 cursor++;
8179 }
8180 break loop;
8181
8182 default:
8183 // fast forward to the end of balanced block
8184 if (this.balance[balanceEnd] === cursor) {
8185 cursor = balanceEnd;
8186 }
8187 }
8188
8189 }
8190
8191 return cursor - this.currentToken;
8192 },
8193
8194 getTokenValue: function() {
8195 return this.source.substring(this.tokenStart, this.tokenEnd);
8196 },
8197 substrToCursor: function(start) {
8198 return this.source.substring(start, this.tokenStart);
8199 },
8200
8201 skipWS: function() {
8202 for (var i = this.currentToken, skipTokenCount = 0; i < this.tokenCount; i++, skipTokenCount++) {
8203 if ((this.offsetAndType[i] >> TYPE_SHIFT) !== WHITESPACE$1) {
8204 break;
8205 }
8206 }
8207
8208 if (skipTokenCount > 0) {
8209 this.skip(skipTokenCount);
8210 }
8211 },
8212 skipSC: function() {
8213 while (this.tokenType === WHITESPACE$1 || this.tokenType === COMMENT$1) {
8214 this.next();
8215 }
8216 },
8217 skip: function(tokenCount) {
8218 var next = this.currentToken + tokenCount;
8219
8220 if (next < this.tokenCount) {
8221 this.currentToken = next;
8222 this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
8223 next = this.offsetAndType[next];
8224 this.tokenType = next >> TYPE_SHIFT;
8225 this.tokenEnd = next & OFFSET_MASK;
8226 } else {
8227 this.currentToken = this.tokenCount;
8228 this.next();
8229 }
8230 },
8231 next: function() {
8232 var next = this.currentToken + 1;
8233
8234 if (next < this.tokenCount) {
8235 this.currentToken = next;
8236 this.tokenStart = this.tokenEnd;
8237 next = this.offsetAndType[next];
8238 this.tokenType = next >> TYPE_SHIFT;
8239 this.tokenEnd = next & OFFSET_MASK;
8240 } else {
8241 this.currentToken = this.tokenCount;
8242 this.eof = true;
8243 this.tokenType = NULL;
8244 this.tokenStart = this.tokenEnd = this.source.length;
8245 }
8246 },
8247
8248 eat: function(tokenType) {
8249 if (this.tokenType !== tokenType) {
8250 var offset = this.tokenStart;
8251 var message = NAME$1[tokenType] + ' is expected';
8252
8253 // tweak message and offset
8254 if (tokenType === IDENTIFIER$1) {
8255 // when identifier is expected but there is a function or url
8256 if (this.tokenType === FUNCTION$1 || this.tokenType === URL$1) {
8257 offset = this.tokenEnd - 1;
8258 message += ' but function found';
8259 }
8260 } else {
8261 // when test type is part of another token show error for current position + 1
8262 // e.g. eat(HYPHENMINUS) will fail on "-foo", but pointing on "-" is odd
8263 if (this.source.charCodeAt(this.tokenStart) === tokenType) {
8264 offset = offset + 1;
8265 }
8266 }
8267
8268 this.error(message, offset);
8269 }
8270
8271 this.next();
8272 },
8273 eatNonWS: function(tokenType) {
8274 this.skipWS();
8275 this.eat(tokenType);
8276 },
8277
8278 consume: function(tokenType) {
8279 var value = this.getTokenValue();
8280
8281 this.eat(tokenType);
8282
8283 return value;
8284 },
8285 consumeFunctionName: function() {
8286 var name = this.source.substring(this.tokenStart, this.tokenEnd - 1);
8287
8288 this.eat(FUNCTION$1);
8289
8290 return name;
8291 },
8292 consumeNonWS: function(tokenType) {
8293 this.skipWS();
8294
8295 return this.consume(tokenType);
8296 },
8297
8298 expectIdentifier: function(name) {
8299 if (this.tokenType !== IDENTIFIER$1 || cmpStr$1(this.source, this.tokenStart, this.tokenEnd, name) === false) {
8300 this.error('Identifier `' + name + '` is expected');
8301 }
8302
8303 this.next();
8304 },
8305
8306 getLocation: function(offset, filename) {
8307 if (!this.linesAnsColumnsComputed) {
8308 computeLinesAndColumns(this, this.source);
8309 }
8310
8311 return {
8312 source: filename,
8313 offset: this.startOffset + offset,
8314 line: this.lines[offset],
8315 column: this.columns[offset]
8316 };
8317 },
8318
8319 getLocationRange: function(start, end, filename) {
8320 if (!this.linesAnsColumnsComputed) {
8321 computeLinesAndColumns(this, this.source);
8322 }
8323
8324 return {
8325 source: filename,
8326 start: {
8327 offset: this.startOffset + start,
8328 line: this.lines[start],
8329 column: this.columns[start]
8330 },
8331 end: {
8332 offset: this.startOffset + end,
8333 line: this.lines[end],
8334 column: this.columns[end]
8335 }
8336 };
8337 },
8338
8339 error: function(message, offset) {
8340 var location = typeof offset !== 'undefined' && offset < this.source.length
8341 ? this.getLocation(offset)
8342 : this.eof
8343 ? findLastNonSpaceLocation$1(this)
8344 : this.getLocation(this.tokenStart);
8345
8346 throw new error(
8347 message || 'Unexpected input',
8348 this.source,
8349 location.offset,
8350 location.line,
8351 location.column
8352 );
8353 },
8354
8355 dump: function() {
8356 var offset = 0;
8357
8358 return Array.prototype.slice.call(this.offsetAndType, 0, this.tokenCount).map(function(item, idx) {
8359 var start = offset;
8360 var end = item & OFFSET_MASK;
8361
8362 offset = end;
8363
8364 return {
8365 idx: idx,
8366 type: NAME$1[item >> TYPE_SHIFT],
8367 chunk: this.source.substring(start, end),
8368 balance: this.balance[idx]
8369 };
8370 }, this);
8371 }
8372 };
8373
8374 // extend with error class
8375 Tokenizer.CssSyntaxError = error;
8376
8377 // extend tokenizer with constants
8378 Object.keys(_const).forEach(function(key) {
8379 Tokenizer[key] = _const[key];
8380 });
8381
8382 // extend tokenizer with static methods from utils
8383 Object.keys(utils).forEach(function(key) {
8384 Tokenizer[key] = utils[key];
8385 });
8386
8387 // warm up tokenizer to elimitate code branches that never execute
8388 // fix soft deoptimizations (insufficient type feedback)
8389 new Tokenizer('\n\r\r\n\f<!---->//""\'\'/*\r\n\f*/1a;.\\31\t\+2{url(a);func();+1.2e3 -.4e-5 .6e+7}').getLocation();
8390
8391 var Tokenizer_1 = Tokenizer;
8392
8393 var tokenizer = Tokenizer_1;
8394
8395 //
8396 // item item item item
8397 // /------\ /------\ /------\ /------\
8398 // | data | | data | | data | | data |
8399 // null <--+-prev |<---+-prev |<---+-prev |<---+-prev |
8400 // | next-+--->| next-+--->| next-+--->| next-+--> null
8401 // \------/ \------/ \------/ \------/
8402 // ^ ^
8403 // | list |
8404 // | /------\ |
8405 // \--------------+-head | |
8406 // | tail-+--------------/
8407 // \------/
8408 //
8409
8410 function createItem(data) {
8411 return {
8412 prev: null,
8413 next: null,
8414 data: data
8415 };
8416 }
8417
8418 var cursors = null;
8419 var List = function() {
8420 this.cursor = null;
8421 this.head = null;
8422 this.tail = null;
8423 };
8424
8425 List.createItem = createItem;
8426 List.prototype.createItem = createItem;
8427
8428 List.prototype.getSize = function() {
8429 var size = 0;
8430 var cursor = this.head;
8431
8432 while (cursor) {
8433 size++;
8434 cursor = cursor.next;
8435 }
8436
8437 return size;
8438 };
8439
8440 List.prototype.fromArray = function(array) {
8441 var cursor = null;
8442
8443 this.head = null;
8444
8445 for (var i = 0; i < array.length; i++) {
8446 var item = createItem(array[i]);
8447
8448 if (cursor !== null) {
8449 cursor.next = item;
8450 } else {
8451 this.head = item;
8452 }
8453
8454 item.prev = cursor;
8455 cursor = item;
8456 }
8457
8458 this.tail = cursor;
8459
8460 return this;
8461 };
8462
8463 List.prototype.toArray = function() {
8464 var cursor = this.head;
8465 var result = [];
8466
8467 while (cursor) {
8468 result.push(cursor.data);
8469 cursor = cursor.next;
8470 }
8471
8472 return result;
8473 };
8474
8475 List.prototype.toJSON = List.prototype.toArray;
8476
8477 List.prototype.isEmpty = function() {
8478 return this.head === null;
8479 };
8480
8481 List.prototype.first = function() {
8482 return this.head && this.head.data;
8483 };
8484
8485 List.prototype.last = function() {
8486 return this.tail && this.tail.data;
8487 };
8488
8489 function allocateCursor(node, prev, next) {
8490 var cursor;
8491
8492 if (cursors !== null) {
8493 cursor = cursors;
8494 cursors = cursors.cursor;
8495 cursor.prev = prev;
8496 cursor.next = next;
8497 cursor.cursor = node.cursor;
8498 } else {
8499 cursor = {
8500 prev: prev,
8501 next: next,
8502 cursor: node.cursor
8503 };
8504 }
8505
8506 node.cursor = cursor;
8507
8508 return cursor;
8509 }
8510
8511 function releaseCursor(node) {
8512 var cursor = node.cursor;
8513
8514 node.cursor = cursor.cursor;
8515 cursor.prev = null;
8516 cursor.next = null;
8517 cursor.cursor = cursors;
8518 cursors = cursor;
8519 }
8520
8521 List.prototype.each = function(fn, context) {
8522 var item;
8523
8524 if (context === undefined) {
8525 context = this;
8526 }
8527
8528 // push cursor
8529 var cursor = allocateCursor(this, null, this.head);
8530
8531 while (cursor.next !== null) {
8532 item = cursor.next;
8533 cursor.next = item.next;
8534
8535 fn.call(context, item.data, item, this);
8536 }
8537
8538 // pop cursor
8539 releaseCursor(this);
8540 };
8541
8542 List.prototype.eachRight = function(fn, context) {
8543 var item;
8544
8545 if (context === undefined) {
8546 context = this;
8547 }
8548
8549 // push cursor
8550 var cursor = allocateCursor(this, this.tail, null);
8551
8552 while (cursor.prev !== null) {
8553 item = cursor.prev;
8554 cursor.prev = item.prev;
8555
8556 fn.call(context, item.data, item, this);
8557 }
8558
8559 // pop cursor
8560 releaseCursor(this);
8561 };
8562
8563 List.prototype.nextUntil = function(start, fn, context) {
8564 if (start === null) {
8565 return;
8566 }
8567
8568 var item;
8569
8570 if (context === undefined) {
8571 context = this;
8572 }
8573
8574 // push cursor
8575 var cursor = allocateCursor(this, null, start);
8576
8577 while (cursor.next !== null) {
8578 item = cursor.next;
8579 cursor.next = item.next;
8580
8581 if (fn.call(context, item.data, item, this)) {
8582 break;
8583 }
8584 }
8585
8586 // pop cursor
8587 releaseCursor(this);
8588 };
8589
8590 List.prototype.prevUntil = function(start, fn, context) {
8591 if (start === null) {
8592 return;
8593 }
8594
8595 var item;
8596
8597 if (context === undefined) {
8598 context = this;
8599 }
8600
8601 // push cursor
8602 var cursor = allocateCursor(this, start, null);
8603
8604 while (cursor.prev !== null) {
8605 item = cursor.prev;
8606 cursor.prev = item.prev;
8607
8608 if (fn.call(context, item.data, item, this)) {
8609 break;
8610 }
8611 }
8612
8613 // pop cursor
8614 releaseCursor(this);
8615 };
8616
8617 List.prototype.some = function(fn, context) {
8618 var cursor = this.head;
8619
8620 if (context === undefined) {
8621 context = this;
8622 }
8623
8624 while (cursor !== null) {
8625 if (fn.call(context, cursor.data, cursor, this)) {
8626 return true;
8627 }
8628
8629 cursor = cursor.next;
8630 }
8631
8632 return false;
8633 };
8634
8635 List.prototype.map = function(fn, context) {
8636 var result = [];
8637 var cursor = this.head;
8638
8639 if (context === undefined) {
8640 context = this;
8641 }
8642
8643 while (cursor !== null) {
8644 result.push(fn.call(context, cursor.data, cursor, this));
8645 cursor = cursor.next;
8646 }
8647
8648 return result;
8649 };
8650
8651 List.prototype.clear = function() {
8652 this.head = null;
8653 this.tail = null;
8654 };
8655
8656 List.prototype.copy = function() {
8657 var result = new List();
8658 var cursor = this.head;
8659
8660 while (cursor !== null) {
8661 result.insert(createItem(cursor.data));
8662 cursor = cursor.next;
8663 }
8664
8665 return result;
8666 };
8667
8668 List.prototype.updateCursors = function(prevOld, prevNew, nextOld, nextNew) {
8669 var cursor = this.cursor;
8670
8671 while (cursor !== null) {
8672 if (cursor.prev === prevOld) {
8673 cursor.prev = prevNew;
8674 }
8675
8676 if (cursor.next === nextOld) {
8677 cursor.next = nextNew;
8678 }
8679
8680 cursor = cursor.cursor;
8681 }
8682 };
8683
8684 List.prototype.prepend = function(item) {
8685 // head
8686 // ^
8687 // item
8688 this.updateCursors(null, item, this.head, item);
8689
8690 // insert to the beginning of the list
8691 if (this.head !== null) {
8692 // new item <- first item
8693 this.head.prev = item;
8694
8695 // new item -> first item
8696 item.next = this.head;
8697 } else {
8698 // if list has no head, then it also has no tail
8699 // in this case tail points to the new item
8700 this.tail = item;
8701 }
8702
8703 // head always points to new item
8704 this.head = item;
8705
8706 return this;
8707 };
8708
8709 List.prototype.prependData = function(data) {
8710 return this.prepend(createItem(data));
8711 };
8712
8713 List.prototype.append = function(item) {
8714 // tail
8715 // ^
8716 // item
8717 this.updateCursors(this.tail, item, null, item);
8718
8719 // insert to the ending of the list
8720 if (this.tail !== null) {
8721 // last item -> new item
8722 this.tail.next = item;
8723
8724 // last item <- new item
8725 item.prev = this.tail;
8726 } else {
8727 // if list has no tail, then it also has no head
8728 // in this case head points to new item
8729 this.head = item;
8730 }
8731
8732 // tail always points to new item
8733 this.tail = item;
8734
8735 return this;
8736 };
8737
8738 List.prototype.appendData = function(data) {
8739 return this.append(createItem(data));
8740 };
8741
8742 List.prototype.insert = function(item, before) {
8743 if (before !== undefined && before !== null) {
8744 // prev before
8745 // ^
8746 // item
8747 this.updateCursors(before.prev, item, before, item);
8748
8749 if (before.prev === null) {
8750 // insert to the beginning of list
8751 if (this.head !== before) {
8752 throw new Error('before doesn\'t belong to list');
8753 }
8754
8755 // since head points to before therefore list doesn't empty
8756 // no need to check tail
8757 this.head = item;
8758 before.prev = item;
8759 item.next = before;
8760
8761 this.updateCursors(null, item);
8762 } else {
8763
8764 // insert between two items
8765 before.prev.next = item;
8766 item.prev = before.prev;
8767
8768 before.prev = item;
8769 item.next = before;
8770 }
8771 } else {
8772 this.append(item);
8773 }
8774 };
8775
8776 List.prototype.insertData = function(data, before) {
8777 this.insert(createItem(data), before);
8778 };
8779
8780 List.prototype.remove = function(item) {
8781 // item
8782 // ^
8783 // prev next
8784 this.updateCursors(item, item.prev, item, item.next);
8785
8786 if (item.prev !== null) {
8787 item.prev.next = item.next;
8788 } else {
8789 if (this.head !== item) {
8790 throw new Error('item doesn\'t belong to list');
8791 }
8792
8793 this.head = item.next;
8794 }
8795
8796 if (item.next !== null) {
8797 item.next.prev = item.prev;
8798 } else {
8799 if (this.tail !== item) {
8800 throw new Error('item doesn\'t belong to list');
8801 }
8802
8803 this.tail = item.prev;
8804 }
8805
8806 item.prev = null;
8807 item.next = null;
8808
8809 return item;
8810 };
8811
8812 List.prototype.appendList = function(list) {
8813 // ignore empty lists
8814 if (list.head === null) {
8815 return;
8816 }
8817
8818 this.updateCursors(this.tail, list.tail, null, list.head);
8819
8820 // insert to end of the list
8821 if (this.tail !== null) {
8822 // if destination list has a tail, then it also has a head,
8823 // but head doesn't change
8824
8825 // dest tail -> source head
8826 this.tail.next = list.head;
8827
8828 // dest tail <- source head
8829 list.head.prev = this.tail;
8830 } else {
8831 // if list has no a tail, then it also has no a head
8832 // in this case points head to new item
8833 this.head = list.head;
8834 }
8835
8836 // tail always start point to new item
8837 this.tail = list.tail;
8838
8839 list.head = null;
8840 list.tail = null;
8841 };
8842
8843 List.prototype.insertList = function(list, before) {
8844 if (before !== undefined && before !== null) {
8845 // ignore empty lists
8846 if (list.head === null) {
8847 return;
8848 }
8849
8850 this.updateCursors(before.prev, list.tail, before, list.head);
8851
8852 // insert in the middle of dist list
8853 if (before.prev !== null) {
8854 // before.prev <-> list.head
8855 before.prev.next = list.head;
8856 list.head.prev = before.prev;
8857 } else {
8858 this.head = list.head;
8859 }
8860
8861 before.prev = list.tail;
8862 list.tail.next = before;
8863
8864 list.head = null;
8865 list.tail = null;
8866 } else {
8867 this.appendList(list);
8868 }
8869 };
8870
8871 List.prototype.replace = function(oldItem, newItemOrList) {
8872 if ('head' in newItemOrList) {
8873 this.insertList(newItemOrList, oldItem);
8874 } else {
8875 this.insert(newItemOrList, oldItem);
8876 }
8877 this.remove(oldItem);
8878 };
8879
8880 var list = List;
8881
8882 var TYPE$3 = tokenizer.TYPE;
8883 var WHITESPACE$2 = TYPE$3.WhiteSpace;
8884 var COMMENT$2 = TYPE$3.Comment;
8885
8886 var sequence = function readSequence(recognizer) {
8887 var children = new list();
8888 var child = null;
8889 var context = {
8890 recognizer: recognizer,
8891 space: null,
8892 ignoreWS: false,
8893 ignoreWSAfter: false
8894 };
8895
8896 this.scanner.skipSC();
8897
8898 while (!this.scanner.eof) {
8899 switch (this.scanner.tokenType) {
8900 case COMMENT$2:
8901 this.scanner.next();
8902 continue;
8903
8904 case WHITESPACE$2:
8905 if (context.ignoreWS) {
8906 this.scanner.next();
8907 } else {
8908 context.space = this.WhiteSpace();
8909 }
8910 continue;
8911 }
8912
8913 child = recognizer.getNode.call(this, context);
8914
8915 if (child === undefined) {
8916 break;
8917 }
8918
8919 if (context.space !== null) {
8920 children.appendData(context.space);
8921 context.space = null;
8922 }
8923
8924 children.appendData(child);
8925
8926 if (context.ignoreWSAfter) {
8927 context.ignoreWSAfter = false;
8928 context.ignoreWS = true;
8929 } else {
8930 context.ignoreWS = false;
8931 }
8932 }
8933
8934 return children;
8935 };
8936
8937 var noop = function() {};
8938
8939 function createParseContext(name) {
8940 return function() {
8941 return this[name]();
8942 };
8943 }
8944
8945 function processConfig(config) {
8946 var parserConfig = {
8947 context: {},
8948 scope: {},
8949 atrule: {},
8950 pseudo: {}
8951 };
8952
8953 if (config.parseContext) {
8954 for (var name in config.parseContext) {
8955 switch (typeof config.parseContext[name]) {
8956 case 'function':
8957 parserConfig.context[name] = config.parseContext[name];
8958 break;
8959
8960 case 'string':
8961 parserConfig.context[name] = createParseContext(config.parseContext[name]);
8962 break;
8963 }
8964 }
8965 }
8966
8967 if (config.scope) {
8968 for (var name in config.scope) {
8969 parserConfig.scope[name] = config.scope[name];
8970 }
8971 }
8972
8973 if (config.atrule) {
8974 for (var name in config.atrule) {
8975 var atrule = config.atrule[name];
8976
8977 if (atrule.parse) {
8978 parserConfig.atrule[name] = atrule.parse;
8979 }
8980 }
8981 }
8982
8983 if (config.pseudo) {
8984 for (var name in config.pseudo) {
8985 var pseudo = config.pseudo[name];
8986
8987 if (pseudo.parse) {
8988 parserConfig.pseudo[name] = pseudo.parse;
8989 }
8990 }
8991 }
8992
8993 if (config.node) {
8994 for (var name in config.node) {
8995 parserConfig[name] = config.node[name].parse;
8996 }
8997 }
8998
8999 return parserConfig;
9000 }
9001
9002 var create = function createParser(config) {
9003 var parser = {
9004 scanner: new tokenizer(),
9005 filename: '<unknown>',
9006 needPositions: false,
9007 tolerant: false,
9008 onParseError: noop,
9009 parseAtruleExpression: true,
9010 parseSelector: true,
9011 parseValue: true,
9012 parseCustomProperty: false,
9013
9014 readSequence: sequence,
9015
9016 tolerantParse: function(consumer, fallback) {
9017 if (this.tolerant) {
9018 var start = this.scanner.currentToken;
9019
9020 try {
9021 return consumer.call(this);
9022 } catch (e) {
9023 this.onParseError(e);
9024 return fallback.call(this, start);
9025 }
9026 } else {
9027 return consumer.call(this);
9028 }
9029 },
9030
9031 getLocation: function(start, end) {
9032 if (this.needPositions) {
9033 return this.scanner.getLocationRange(
9034 start,
9035 end,
9036 this.filename
9037 );
9038 }
9039
9040 return null;
9041 },
9042 getLocationFromList: function(list) {
9043 if (this.needPositions) {
9044 return this.scanner.getLocationRange(
9045 list.head !== null ? list.first().loc.start.offset - this.scanner.startOffset : this.scanner.tokenStart,
9046 list.head !== null ? list.last().loc.end.offset - this.scanner.startOffset : this.scanner.tokenStart,
9047 this.filename
9048 );
9049 }
9050
9051 return null;
9052 }
9053 };
9054
9055 config = processConfig(config || {});
9056 for (var key in config) {
9057 parser[key] = config[key];
9058 }
9059
9060 return function(source, options) {
9061 options = options || {};
9062
9063 var context = options.context || 'default';
9064 var ast;
9065
9066 parser.scanner.setSource(source, options.offset, options.line, options.column);
9067 parser.filename = options.filename || '<unknown>';
9068 parser.needPositions = Boolean(options.positions);
9069 parser.tolerant = Boolean(options.tolerant);
9070 parser.onParseError = typeof options.onParseError === 'function' ? options.onParseError : noop;
9071 parser.parseAtruleExpression = 'parseAtruleExpression' in options ? Boolean(options.parseAtruleExpression) : true;
9072 parser.parseSelector = 'parseSelector' in options ? Boolean(options.parseSelector) : true;
9073 parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
9074 parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;
9075
9076 if (!parser.context.hasOwnProperty(context)) {
9077 throw new Error('Unknown context `' + context + '`');
9078 }
9079
9080 ast = parser.context[context].call(parser, options);
9081
9082 if (!parser.scanner.eof) {
9083 parser.scanner.error();
9084 }
9085
9086 // console.log(JSON.stringify(ast, null, 4));
9087 return ast;
9088 };
9089 };
9090
9091 var cmpChar$1 = tokenizer.cmpChar;
9092 var TYPE$4 = tokenizer.TYPE;
9093
9094 var IDENTIFIER$2 = TYPE$4.Identifier;
9095 var STRING$2 = TYPE$4.String;
9096 var NUMBER$2 = TYPE$4.Number;
9097 var FUNCTION$2 = TYPE$4.Function;
9098 var URL$2 = TYPE$4.Url;
9099 var NUMBERSIGN = TYPE$4.NumberSign;
9100 var LEFTPARENTHESIS$1 = TYPE$4.LeftParenthesis;
9101 var LEFTSQUAREBRACKET$1 = TYPE$4.LeftSquareBracket;
9102 var PLUSSIGN$2 = TYPE$4.PlusSign;
9103 var HYPHENMINUS$2 = TYPE$4.HyphenMinus;
9104 var COMMA = TYPE$4.Comma;
9105 var SOLIDUS = TYPE$4.Solidus;
9106 var ASTERISK = TYPE$4.Asterisk;
9107 var PERCENTSIGN = TYPE$4.PercentSign;
9108 var BACKSLASH = TYPE$4.Backslash;
9109 var U = 117; // 'u'.charCodeAt(0)
9110
9111 var _default = function defaultRecognizer(context) {
9112 switch (this.scanner.tokenType) {
9113 case NUMBERSIGN:
9114 return this.HexColor();
9115
9116 case COMMA:
9117 context.space = null;
9118 context.ignoreWSAfter = true;
9119 return this.Operator();
9120
9121 case SOLIDUS:
9122 case ASTERISK:
9123 case PLUSSIGN$2:
9124 case HYPHENMINUS$2:
9125 return this.Operator();
9126
9127 case LEFTPARENTHESIS$1:
9128 return this.Parentheses(this.readSequence, context.recognizer);
9129
9130 case LEFTSQUAREBRACKET$1:
9131 return this.Brackets(this.readSequence, context.recognizer);
9132
9133 case STRING$2:
9134 return this.String();
9135
9136 case NUMBER$2:
9137 switch (this.scanner.lookupType(1)) {
9138 case PERCENTSIGN:
9139 return this.Percentage();
9140
9141 case IDENTIFIER$2:
9142 // edge case: number with folowing \0 and \9 hack shouldn't to be a Dimension
9143 if (cmpChar$1(this.scanner.source, this.scanner.tokenEnd, BACKSLASH)) {
9144 return this.Number();
9145 } else {
9146 return this.Dimension();
9147 }
9148
9149 default:
9150 return this.Number();
9151 }
9152
9153 case FUNCTION$2:
9154 return this.Function(this.readSequence, context.recognizer);
9155
9156 case URL$2:
9157 return this.Url();
9158
9159 case IDENTIFIER$2:
9160 // check for unicode range, it should start with u+ or U+
9161 if (cmpChar$1(this.scanner.source, this.scanner.tokenStart, U) &&
9162 cmpChar$1(this.scanner.source, this.scanner.tokenStart + 1, PLUSSIGN$2)) {
9163 return this.UnicodeRange();
9164 } else {
9165 return this.Identifier();
9166 }
9167 }
9168 };
9169
9170 var atruleExpression = {
9171 getNode: _default
9172 };
9173
9174 var TYPE$5 = tokenizer.TYPE;
9175
9176 var IDENTIFIER$3 = TYPE$5.Identifier;
9177 var NUMBER$3 = TYPE$5.Number;
9178 var NUMBERSIGN$1 = TYPE$5.NumberSign;
9179 var LEFTSQUAREBRACKET$2 = TYPE$5.LeftSquareBracket;
9180 var PLUSSIGN$3 = TYPE$5.PlusSign;
9181 var SOLIDUS$1 = TYPE$5.Solidus;
9182 var ASTERISK$1 = TYPE$5.Asterisk;
9183 var FULLSTOP$2 = TYPE$5.FullStop;
9184 var COLON = TYPE$5.Colon;
9185 var GREATERTHANSIGN$1 = TYPE$5.GreaterThanSign;
9186 var VERTICALLINE = TYPE$5.VerticalLine;
9187 var TILDE = TYPE$5.Tilde;
9188
9189 function getNode(context) {
9190 switch (this.scanner.tokenType) {
9191 case PLUSSIGN$3:
9192 case GREATERTHANSIGN$1:
9193 case TILDE:
9194 context.space = null;
9195 context.ignoreWSAfter = true;
9196 return this.Combinator();
9197
9198 case SOLIDUS$1: // /deep/
9199 return this.Combinator();
9200
9201 case FULLSTOP$2:
9202 return this.ClassSelector();
9203
9204 case LEFTSQUAREBRACKET$2:
9205 return this.AttributeSelector();
9206
9207 case NUMBERSIGN$1:
9208 return this.IdSelector();
9209
9210 case COLON:
9211 if (this.scanner.lookupType(1) === COLON) {
9212 return this.PseudoElementSelector();
9213 } else {
9214 return this.PseudoClassSelector();
9215 }
9216
9217 case IDENTIFIER$3:
9218 case ASTERISK$1:
9219 case VERTICALLINE:
9220 return this.TypeSelector();
9221
9222 case NUMBER$3:
9223 return this.Percentage();
9224 }
9225 }
9226 var selector = {
9227 getNode: getNode
9228 };
9229
9230 // https://drafts.csswg.org/css-images-4/#element-notation
9231 // https://developer.mozilla.org/en-US/docs/Web/CSS/element
9232 var element = function() {
9233 this.scanner.skipSC();
9234
9235 var id = this.IdSelector();
9236
9237 this.scanner.skipSC();
9238
9239 return new list().appendData(
9240 id
9241 );
9242 };
9243
9244 // legacy IE function
9245 // expression '(' raw ')'
9246 var expression = function() {
9247 return new list().appendData(
9248 this.Raw(this.scanner.currentToken, 0, 0, false, false)
9249 );
9250 };
9251
9252 var TYPE$6 = tokenizer.TYPE;
9253
9254 var IDENTIFIER$4 = TYPE$6.Identifier;
9255 var COMMA$1 = TYPE$6.Comma;
9256 var SEMICOLON = TYPE$6.Semicolon;
9257 var HYPHENMINUS$3 = TYPE$6.HyphenMinus;
9258 var EXCLAMATIONMARK$1 = TYPE$6.ExclamationMark;
9259
9260 // var '(' ident (',' <value>? )? ')'
9261 var _var = function() {
9262 var children = new list();
9263
9264 this.scanner.skipSC();
9265
9266 var identStart = this.scanner.tokenStart;
9267
9268 this.scanner.eat(HYPHENMINUS$3);
9269 if (this.scanner.source.charCodeAt(this.scanner.tokenStart) !== HYPHENMINUS$3) {
9270 this.scanner.error('HyphenMinus is expected');
9271 }
9272 this.scanner.eat(IDENTIFIER$4);
9273
9274 children.appendData({
9275 type: 'Identifier',
9276 loc: this.getLocation(identStart, this.scanner.tokenStart),
9277 name: this.scanner.substrToCursor(identStart)
9278 });
9279
9280 this.scanner.skipSC();
9281
9282 if (this.scanner.tokenType === COMMA$1) {
9283 children.appendData(this.Operator());
9284 children.appendData(this.parseCustomProperty
9285 ? this.Value(null)
9286 : this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$1, SEMICOLON, false, false)
9287 );
9288 }
9289
9290 return children;
9291 };
9292
9293 var value = {
9294 getNode: _default,
9295 '-moz-element': element,
9296 'element': element,
9297 'expression': expression,
9298 'var': _var
9299 };
9300
9301 var scope = {
9302 AtruleExpression: atruleExpression,
9303 Selector: selector,
9304 Value: value
9305 };
9306
9307 var fontFace = {
9308 parse: {
9309 expression: null,
9310 block: function() {
9311 return this.Block(this.Declaration);
9312 }
9313 }
9314 };
9315
9316 var TYPE$7 = tokenizer.TYPE;
9317
9318 var STRING$3 = TYPE$7.String;
9319 var IDENTIFIER$5 = TYPE$7.Identifier;
9320 var URL$3 = TYPE$7.Url;
9321 var LEFTPARENTHESIS$2 = TYPE$7.LeftParenthesis;
9322
9323 var _import = {
9324 parse: {
9325 expression: function() {
9326 var children = new list();
9327
9328 this.scanner.skipSC();
9329
9330 switch (this.scanner.tokenType) {
9331 case STRING$3:
9332 children.appendData(this.String());
9333 break;
9334
9335 case URL$3:
9336 children.appendData(this.Url());
9337 break;
9338
9339 default:
9340 this.scanner.error('String or url() is expected');
9341 }
9342
9343 if (this.scanner.lookupNonWSType(0) === IDENTIFIER$5 ||
9344 this.scanner.lookupNonWSType(0) === LEFTPARENTHESIS$2) {
9345 children.appendData(this.WhiteSpace());
9346 children.appendData(this.MediaQueryList());
9347 }
9348
9349 return children;
9350 },
9351 block: null
9352 }
9353 };
9354
9355 var media = {
9356 parse: {
9357 expression: function() {
9358 return new list().appendData(
9359 this.MediaQueryList()
9360 );
9361 },
9362 block: function() {
9363 return this.Block(this.Rule);
9364 }
9365 }
9366 };
9367
9368 var TYPE$8 = tokenizer.TYPE;
9369 var LEFTCURLYBRACKET$1 = TYPE$8.LeftCurlyBracket;
9370
9371 var page = {
9372 parse: {
9373 expression: function() {
9374 if (this.scanner.lookupNonWSType(0) === LEFTCURLYBRACKET$1) {
9375 return null;
9376 }
9377
9378 return new list().appendData(
9379 this.SelectorList()
9380 );
9381 },
9382 block: function() {
9383 return this.Block(this.Declaration);
9384 }
9385 }
9386 };
9387
9388 var TYPE$9 = tokenizer.TYPE;
9389
9390 var WHITESPACE$3 = TYPE$9.WhiteSpace;
9391 var COMMENT$3 = TYPE$9.Comment;
9392 var IDENTIFIER$6 = TYPE$9.Identifier;
9393 var FUNCTION$3 = TYPE$9.Function;
9394 var LEFTPARENTHESIS$3 = TYPE$9.LeftParenthesis;
9395 var HYPHENMINUS$4 = TYPE$9.HyphenMinus;
9396 var COLON$1 = TYPE$9.Colon;
9397
9398 function consumeRaw() {
9399 return new list().appendData(
9400 this.Raw(this.scanner.currentToken, 0, 0, false, false)
9401 );
9402 }
9403
9404 function parentheses() {
9405 var index = 0;
9406
9407 this.scanner.skipSC();
9408
9409 // TODO: make it simplier
9410 if (this.scanner.tokenType === IDENTIFIER$6) {
9411 index = 1;
9412 } else if (this.scanner.tokenType === HYPHENMINUS$4 &&
9413 this.scanner.lookupType(1) === IDENTIFIER$6) {
9414 index = 2;
9415 }
9416
9417 if (index !== 0 && this.scanner.lookupNonWSType(index) === COLON$1) {
9418 return new list().appendData(
9419 this.Declaration()
9420 );
9421 }
9422
9423 return readSequence.call(this);
9424 }
9425
9426 function readSequence() {
9427 var children = new list();
9428 var space = null;
9429 var child;
9430
9431 this.scanner.skipSC();
9432
9433 scan:
9434 while (!this.scanner.eof) {
9435 switch (this.scanner.tokenType) {
9436 case WHITESPACE$3:
9437 space = this.WhiteSpace();
9438 continue;
9439
9440 case COMMENT$3:
9441 this.scanner.next();
9442 continue;
9443
9444 case FUNCTION$3:
9445 child = this.Function(consumeRaw, this.scope.AtruleExpression);
9446 break;
9447
9448 case IDENTIFIER$6:
9449 child = this.Identifier();
9450 break;
9451
9452 case LEFTPARENTHESIS$3:
9453 child = this.Parentheses(parentheses, this.scope.AtruleExpression);
9454 break;
9455
9456 default:
9457 break scan;
9458 }
9459
9460 if (space !== null) {
9461 children.appendData(space);
9462 space = null;
9463 }
9464
9465 children.appendData(child);
9466 }
9467
9468 return children;
9469 }
9470
9471 var supports = {
9472 parse: {
9473 expression: function() {
9474 var children = readSequence.call(this);
9475
9476 if (children.isEmpty()) {
9477 this.scanner.error('Condition is expected');
9478 }
9479
9480 return children;
9481 },
9482 block: function() {
9483 return this.Block(this.Rule);
9484 }
9485 }
9486 };
9487
9488 var atrule = {
9489 'font-face': fontFace,
9490 'import': _import,
9491 'media': media,
9492 'page': page,
9493 'supports': supports
9494 };
9495
9496 var dir = {
9497 parse: function() {
9498 return new list().appendData(
9499 this.Identifier()
9500 );
9501 }
9502 };
9503
9504 var has$1 = {
9505 parse: function() {
9506 return new list().appendData(
9507 this.SelectorList()
9508 );
9509 }
9510 };
9511
9512 var lang = {
9513 parse: function() {
9514 return new list().appendData(
9515 this.Identifier()
9516 );
9517 }
9518 };
9519
9520 var selectorList = {
9521 parse: function selectorList() {
9522 return new list().appendData(
9523 this.SelectorList()
9524 );
9525 }
9526 };
9527
9528 var matches = selectorList;
9529
9530 var not = selectorList;
9531
9532 var ALLOW_OF_CLAUSE = true;
9533
9534 var nthWithOfClause = {
9535 parse: function() {
9536 return new list().appendData(
9537 this.Nth(ALLOW_OF_CLAUSE)
9538 );
9539 }
9540 };
9541
9542 var nthChild = nthWithOfClause;
9543
9544 var nthLastChild = nthWithOfClause;
9545
9546 var DISALLOW_OF_CLAUSE = false;
9547
9548 var nth = {
9549 parse: function nth() {
9550 return new list().appendData(
9551 this.Nth(DISALLOW_OF_CLAUSE)
9552 );
9553 }
9554 };
9555
9556 var nthLastOfType = nth;
9557
9558 var nthOfType = nth;
9559
9560 var slotted = {
9561 parse: function compoundSelector() {
9562 return new list().appendData(
9563 this.Selector()
9564 );
9565 }
9566 };
9567
9568 var pseudo = {
9569 'dir': dir,
9570 'has': has$1,
9571 'lang': lang,
9572 'matches': matches,
9573 'not': not,
9574 'nth-child': nthChild,
9575 'nth-last-child': nthLastChild,
9576 'nth-last-of-type': nthLastOfType,
9577 'nth-of-type': nthOfType,
9578 'slotted': slotted
9579 };
9580
9581 var cmpChar$2 = tokenizer.cmpChar;
9582 var isNumber$2 = tokenizer.isNumber;
9583 var TYPE$a = tokenizer.TYPE;
9584
9585 var IDENTIFIER$7 = TYPE$a.Identifier;
9586 var NUMBER$4 = TYPE$a.Number;
9587 var PLUSSIGN$4 = TYPE$a.PlusSign;
9588 var HYPHENMINUS$5 = TYPE$a.HyphenMinus;
9589 var N$3 = 110; // 'n'.charCodeAt(0)
9590 var DISALLOW_SIGN = true;
9591 var ALLOW_SIGN = false;
9592
9593 function checkTokenIsInteger(scanner, disallowSign) {
9594 var pos = scanner.tokenStart;
9595
9596 if (scanner.source.charCodeAt(pos) === PLUSSIGN$4 ||
9597 scanner.source.charCodeAt(pos) === HYPHENMINUS$5) {
9598 if (disallowSign) {
9599 scanner.error();
9600 }
9601 pos++;
9602 }
9603
9604 for (; pos < scanner.tokenEnd; pos++) {
9605 if (!isNumber$2(scanner.source.charCodeAt(pos))) {
9606 scanner.error('Unexpected input', pos);
9607 }
9608 }
9609 }
9610
9611 // An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
9612 var AnPlusB = {
9613 name: 'AnPlusB',
9614 structure: {
9615 a: [String, null],
9616 b: [String, null]
9617 },
9618 parse: function() {
9619 var start = this.scanner.tokenStart;
9620 var end = start;
9621 var prefix = '';
9622 var a = null;
9623 var b = null;
9624
9625 if (this.scanner.tokenType === NUMBER$4 ||
9626 this.scanner.tokenType === PLUSSIGN$4) {
9627 checkTokenIsInteger(this.scanner, ALLOW_SIGN);
9628 prefix = this.scanner.getTokenValue();
9629 this.scanner.next();
9630 end = this.scanner.tokenStart;
9631 }
9632
9633 if (this.scanner.tokenType === IDENTIFIER$7) {
9634 var bStart = this.scanner.tokenStart;
9635
9636 if (cmpChar$2(this.scanner.source, bStart, HYPHENMINUS$5)) {
9637 if (prefix === '') {
9638 prefix = '-';
9639 bStart++;
9640 } else {
9641 this.scanner.error('Unexpected hyphen minus');
9642 }
9643 }
9644
9645 if (!cmpChar$2(this.scanner.source, bStart, N$3)) {
9646 this.scanner.error();
9647 }
9648
9649 a = prefix === '' ? '1' :
9650 prefix === '+' ? '+1' :
9651 prefix === '-' ? '-1' :
9652 prefix;
9653
9654 var len = this.scanner.tokenEnd - bStart;
9655 if (len > 1) {
9656 // ..n-..
9657 if (this.scanner.source.charCodeAt(bStart + 1) !== HYPHENMINUS$5) {
9658 this.scanner.error('Unexpected input', bStart + 1);
9659 }
9660
9661 if (len > 2) {
9662 // ..n-{number}..
9663 this.scanner.tokenStart = bStart + 2;
9664 } else {
9665 // ..n- {number}
9666 this.scanner.next();
9667 this.scanner.skipSC();
9668 }
9669
9670 checkTokenIsInteger(this.scanner, DISALLOW_SIGN);
9671 b = '-' + this.scanner.getTokenValue();
9672 this.scanner.next();
9673 end = this.scanner.tokenStart;
9674 } else {
9675 prefix = '';
9676 this.scanner.next();
9677 end = this.scanner.tokenStart;
9678 this.scanner.skipSC();
9679
9680 if (this.scanner.tokenType === HYPHENMINUS$5 ||
9681 this.scanner.tokenType === PLUSSIGN$4) {
9682 prefix = this.scanner.getTokenValue();
9683 this.scanner.next();
9684 this.scanner.skipSC();
9685 }
9686
9687 if (this.scanner.tokenType === NUMBER$4) {
9688 checkTokenIsInteger(this.scanner, prefix !== '');
9689
9690 if (!isNumber$2(this.scanner.source.charCodeAt(this.scanner.tokenStart))) {
9691 prefix = this.scanner.source.charAt(this.scanner.tokenStart);
9692 this.scanner.tokenStart++;
9693 }
9694
9695 if (prefix === '') {
9696 // should be an operator before number
9697 this.scanner.error();
9698 } else if (prefix === '+') {
9699 // plus is using by default
9700 prefix = '';
9701 }
9702
9703 b = prefix + this.scanner.getTokenValue();
9704
9705 this.scanner.next();
9706 end = this.scanner.tokenStart;
9707 } else {
9708 if (prefix) {
9709 this.scanner.eat(NUMBER$4);
9710 }
9711 }
9712 }
9713 } else {
9714 if (prefix === '' || prefix === '+') { // no number
9715 this.scanner.error(
9716 'Number or identifier is expected',
9717 this.scanner.tokenStart + (
9718 this.scanner.tokenType === PLUSSIGN$4 ||
9719 this.scanner.tokenType === HYPHENMINUS$5
9720 )
9721 );
9722 }
9723
9724 b = prefix;
9725 }
9726
9727 return {
9728 type: 'AnPlusB',
9729 loc: this.getLocation(start, end),
9730 a: a,
9731 b: b
9732 };
9733 },
9734 generate: function(processChunk, node) {
9735 var a = node.a !== null && node.a !== undefined;
9736 var b = node.b !== null && node.b !== undefined;
9737
9738 if (a) {
9739 processChunk(
9740 node.a === '+1' ? '+n' :
9741 node.a === '1' ? 'n' :
9742 node.a === '-1' ? '-n' :
9743 node.a + 'n'
9744 );
9745
9746 if (b) {
9747 b = String(node.b);
9748 if (b.charAt(0) === '-' || b.charAt(0) === '+') {
9749 processChunk(b.charAt(0));
9750 processChunk(b.substr(1));
9751 } else {
9752 processChunk('+');
9753 processChunk(b);
9754 }
9755 }
9756 } else {
9757 processChunk(String(node.b));
9758 }
9759 }
9760 };
9761
9762 var TYPE$b = tokenizer.TYPE;
9763
9764 var ATRULE$2 = TYPE$b.Atrule;
9765 var SEMICOLON$1 = TYPE$b.Semicolon;
9766 var LEFTCURLYBRACKET$2 = TYPE$b.LeftCurlyBracket;
9767 var RIGHTCURLYBRACKET$1 = TYPE$b.RightCurlyBracket;
9768
9769 function isBlockAtrule() {
9770 for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) {
9771 if (type === RIGHTCURLYBRACKET$1) {
9772 return true;
9773 }
9774
9775 if (type === LEFTCURLYBRACKET$2 ||
9776 type === ATRULE$2) {
9777 return false;
9778 }
9779 }
9780
9781 this.scanner.skip(offset);
9782 this.scanner.eat(RIGHTCURLYBRACKET$1);
9783 }
9784
9785 var Atrule = {
9786 name: 'Atrule',
9787 structure: {
9788 name: String,
9789 expression: ['AtruleExpression', null],
9790 block: ['Block', null]
9791 },
9792 parse: function() {
9793 var start = this.scanner.tokenStart;
9794 var name;
9795 var nameLowerCase;
9796 var expression = null;
9797 var block = null;
9798
9799 this.scanner.eat(ATRULE$2);
9800
9801 name = this.scanner.substrToCursor(start + 1);
9802 nameLowerCase = name.toLowerCase();
9803 this.scanner.skipSC();
9804
9805 expression = this.AtruleExpression(name);
9806
9807 // turn empty AtruleExpression into null
9808 if (expression.children.head === null) {
9809 expression = null;
9810 }
9811
9812 this.scanner.skipSC();
9813
9814 if (this.atrule.hasOwnProperty(nameLowerCase)) {
9815 if (typeof this.atrule[nameLowerCase].block === 'function') {
9816 if (this.scanner.tokenType !== LEFTCURLYBRACKET$2) {
9817 // FIXME: make tolerant
9818 this.scanner.error('Curly bracket is expected');
9819 }
9820
9821 block = this.atrule[nameLowerCase].block.call(this);
9822 } else {
9823 if (!this.tolerant || !this.scanner.eof) {
9824 this.scanner.eat(SEMICOLON$1);
9825 }
9826 }
9827 } else {
9828 switch (this.scanner.tokenType) {
9829 case SEMICOLON$1:
9830 this.scanner.next();
9831 break;
9832
9833 case LEFTCURLYBRACKET$2:
9834 // TODO: should consume block content as Raw?
9835 block = this.Block(isBlockAtrule.call(this) ? this.Declaration : this.Rule);
9836 break;
9837
9838 default:
9839 if (!this.tolerant) {
9840 this.scanner.error('Semicolon or block is expected');
9841 }
9842 }
9843 }
9844
9845 return {
9846 type: 'Atrule',
9847 loc: this.getLocation(start, this.scanner.tokenStart),
9848 name: name,
9849 expression: expression,
9850 block: block
9851 };
9852 },
9853 generate: function(processChunk, node) {
9854 processChunk('@');
9855 processChunk(node.name);
9856
9857 if (node.expression !== null) {
9858 processChunk(' ');
9859 this.generate(processChunk, node.expression);
9860 }
9861
9862 if (node.block) {
9863 this.generate(processChunk, node.block);
9864 } else {
9865 processChunk(';');
9866 }
9867 },
9868 walkContext: 'atrule'
9869 };
9870
9871 var TYPE$c = tokenizer.TYPE;
9872 var SEMICOLON$2 = TYPE$c.Semicolon;
9873 var LEFTCURLYBRACKET$3 = TYPE$c.LeftCurlyBracket;
9874
9875 function consumeRaw$1(startToken) {
9876 return new list().appendData(
9877 this.Raw(startToken, SEMICOLON$2, LEFTCURLYBRACKET$3, false, true)
9878 );
9879 }
9880
9881 function consumeDefaultSequence() {
9882 return this.readSequence(this.scope.AtruleExpression);
9883 }
9884
9885 var AtruleExpression = {
9886 name: 'AtruleExpression',
9887 structure: {
9888 children: [[]]
9889 },
9890 parse: function(name) {
9891 var children = null;
9892 var startToken = this.scanner.currentToken;
9893
9894 if (name !== null) {
9895 name = name.toLowerCase();
9896 }
9897
9898 if (this.parseAtruleExpression) {
9899 // custom consumer
9900 if (this.atrule.hasOwnProperty(name)) {
9901 if (typeof this.atrule[name].expression === 'function') {
9902 children = this.tolerantParse(this.atrule[name].expression, consumeRaw$1);
9903 }
9904 } else {
9905 // default consumer
9906 this.scanner.skipSC();
9907 children = this.tolerantParse(consumeDefaultSequence, consumeRaw$1);
9908 }
9909
9910 if (this.tolerant) {
9911 if (this.scanner.eof || (this.scanner.tokenType !== SEMICOLON$2 && this.scanner.tokenType !== LEFTCURLYBRACKET$3)) {
9912 children = consumeRaw$1.call(this, startToken);
9913 }
9914 }
9915 } else {
9916 children = consumeRaw$1.call(this, startToken);
9917 }
9918
9919 if (children === null) {
9920 children = new list();
9921 }
9922
9923 return {
9924 type: 'AtruleExpression',
9925 loc: this.getLocationFromList(children),
9926 children: children
9927 };
9928 },
9929 generate: function(processChunk, node) {
9930 this.each(processChunk, node);
9931 },
9932 walkContext: 'atruleExpression'
9933 };
9934
9935 var TYPE$d = tokenizer.TYPE;
9936
9937 var IDENTIFIER$8 = TYPE$d.Identifier;
9938 var STRING$4 = TYPE$d.String;
9939 var DOLLARSIGN = TYPE$d.DollarSign;
9940 var ASTERISK$2 = TYPE$d.Asterisk;
9941 var COLON$2 = TYPE$d.Colon;
9942 var EQUALSSIGN = TYPE$d.EqualsSign;
9943 var LEFTSQUAREBRACKET$3 = TYPE$d.LeftSquareBracket;
9944 var RIGHTSQUAREBRACKET$1 = TYPE$d.RightSquareBracket;
9945 var CIRCUMFLEXACCENT = TYPE$d.CircumflexAccent;
9946 var VERTICALLINE$1 = TYPE$d.VerticalLine;
9947 var TILDE$1 = TYPE$d.Tilde;
9948
9949 function getAttributeName() {
9950 if (this.scanner.eof) {
9951 this.scanner.error('Unexpected end of input');
9952 }
9953
9954 var start = this.scanner.tokenStart;
9955 var expectIdentifier = false;
9956 var checkColon = true;
9957
9958 if (this.scanner.tokenType === ASTERISK$2) {
9959 expectIdentifier = true;
9960 checkColon = false;
9961 this.scanner.next();
9962 } else if (this.scanner.tokenType !== VERTICALLINE$1) {
9963 this.scanner.eat(IDENTIFIER$8);
9964 }
9965
9966 if (this.scanner.tokenType === VERTICALLINE$1) {
9967 if (this.scanner.lookupType(1) !== EQUALSSIGN) {
9968 this.scanner.next();
9969 this.scanner.eat(IDENTIFIER$8);
9970 } else if (expectIdentifier) {
9971 this.scanner.error('Identifier is expected', this.scanner.tokenEnd);
9972 }
9973 } else if (expectIdentifier) {
9974 this.scanner.error('Vertical line is expected');
9975 }
9976
9977 if (checkColon && this.scanner.tokenType === COLON$2) {
9978 this.scanner.next();
9979 this.scanner.eat(IDENTIFIER$8);
9980 }
9981
9982 return {
9983 type: 'Identifier',
9984 loc: this.getLocation(start, this.scanner.tokenStart),
9985 name: this.scanner.substrToCursor(start)
9986 };
9987 }
9988
9989 function getOperator() {
9990 var start = this.scanner.tokenStart;
9991 var tokenType = this.scanner.tokenType;
9992
9993 if (tokenType !== EQUALSSIGN && // =
9994 tokenType !== TILDE$1 && // ~=
9995 tokenType !== CIRCUMFLEXACCENT && // ^=
9996 tokenType !== DOLLARSIGN && // $=
9997 tokenType !== ASTERISK$2 && // *=
9998 tokenType !== VERTICALLINE$1 // |=
9999 ) {
10000 this.scanner.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
10001 }
10002
10003 if (tokenType === EQUALSSIGN) {
10004 this.scanner.next();
10005 } else {
10006 this.scanner.next();
10007 this.scanner.eat(EQUALSSIGN);
10008 }
10009
10010 return this.scanner.substrToCursor(start);
10011 }
10012
10013 // '[' S* attrib_name ']'
10014 // '[' S* attrib_name S* attrib_matcher S* [ IDENT | STRING ] S* attrib_flags? S* ']'
10015 var AttributeSelector = {
10016 name: 'AttributeSelector',
10017 structure: {
10018 name: 'Identifier',
10019 matcher: [String, null],
10020 value: ['String', 'Identifier', null],
10021 flags: [String, null]
10022 },
10023 parse: function() {
10024 var start = this.scanner.tokenStart;
10025 var name;
10026 var matcher = null;
10027 var value = null;
10028 var flags = null;
10029
10030 this.scanner.eat(LEFTSQUAREBRACKET$3);
10031 this.scanner.skipSC();
10032
10033 name = getAttributeName.call(this);
10034 this.scanner.skipSC();
10035
10036 if (this.scanner.tokenType !== RIGHTSQUAREBRACKET$1) {
10037 // avoid case `[name i]`
10038 if (this.scanner.tokenType !== IDENTIFIER$8) {
10039 matcher = getOperator.call(this);
10040
10041 this.scanner.skipSC();
10042
10043 value = this.scanner.tokenType === STRING$4
10044 ? this.String()
10045 : this.Identifier();
10046
10047 this.scanner.skipSC();
10048 }
10049
10050 // attribute flags
10051 if (this.scanner.tokenType === IDENTIFIER$8) {
10052 flags = this.scanner.getTokenValue();
10053 this.scanner.next();
10054
10055 this.scanner.skipSC();
10056 }
10057 }
10058
10059 this.scanner.eat(RIGHTSQUAREBRACKET$1);
10060
10061 return {
10062 type: 'AttributeSelector',
10063 loc: this.getLocation(start, this.scanner.tokenStart),
10064 name: name,
10065 matcher: matcher,
10066 value: value,
10067 flags: flags
10068 };
10069 },
10070 generate: function(processChunk, node) {
10071 var flagsPrefix = ' ';
10072
10073 processChunk('[');
10074 this.generate(processChunk, node.name);
10075
10076 if (node.matcher !== null) {
10077 processChunk(node.matcher);
10078
10079 if (node.value !== null) {
10080 this.generate(processChunk, node.value);
10081
10082 // space between string and flags is not required
10083 if (node.value.type === 'String') {
10084 flagsPrefix = '';
10085 }
10086 }
10087 }
10088
10089 if (node.flags !== null) {
10090 processChunk(flagsPrefix);
10091 processChunk(node.flags);
10092 }
10093
10094 processChunk(']');
10095 }
10096 };
10097
10098 var TYPE$e = tokenizer.TYPE;
10099
10100 var WHITESPACE$4 = TYPE$e.WhiteSpace;
10101 var COMMENT$4 = TYPE$e.Comment;
10102 var SEMICOLON$3 = TYPE$e.Semicolon;
10103 var ATRULE$3 = TYPE$e.Atrule;
10104 var LEFTCURLYBRACKET$4 = TYPE$e.LeftCurlyBracket;
10105 var RIGHTCURLYBRACKET$2 = TYPE$e.RightCurlyBracket;
10106
10107 function consumeRaw$2(startToken) {
10108 return this.Raw(startToken, 0, SEMICOLON$3, true, true);
10109 }
10110
10111 var Block = {
10112 name: 'Block',
10113 structure: {
10114 children: [['Atrule', 'Rule', 'Declaration']]
10115 },
10116 parse: function(defaultConsumer) {
10117 if (!defaultConsumer) {
10118 defaultConsumer = this.Declaration;
10119 }
10120
10121 var start = this.scanner.tokenStart;
10122 var children = new list();
10123
10124 this.scanner.eat(LEFTCURLYBRACKET$4);
10125
10126 scan:
10127 while (!this.scanner.eof) {
10128 switch (this.scanner.tokenType) {
10129 case RIGHTCURLYBRACKET$2:
10130 break scan;
10131
10132 case WHITESPACE$4:
10133 case COMMENT$4:
10134 case SEMICOLON$3:
10135 this.scanner.next();
10136 break;
10137
10138 case ATRULE$3:
10139 children.appendData(this.tolerantParse(this.Atrule, consumeRaw$2));
10140 break;
10141
10142 default:
10143 children.appendData(this.tolerantParse(defaultConsumer, consumeRaw$2));
10144 }
10145 }
10146
10147 if (!this.tolerant || !this.scanner.eof) {
10148 this.scanner.eat(RIGHTCURLYBRACKET$2);
10149 }
10150
10151 return {
10152 type: 'Block',
10153 loc: this.getLocation(start, this.scanner.tokenStart),
10154 children: children
10155 };
10156 },
10157 generate: function(processChunk, node) {
10158 processChunk('{');
10159 this.each(processChunk, node);
10160 processChunk('}');
10161 },
10162 walkContext: 'block'
10163 };
10164
10165 var TYPE$f = tokenizer.TYPE;
10166 var LEFTSQUAREBRACKET$4 = TYPE$f.LeftSquareBracket;
10167 var RIGHTSQUAREBRACKET$2 = TYPE$f.RightSquareBracket;
10168
10169 // currently only Grid Layout uses square brackets, but left it universal
10170 // https://drafts.csswg.org/css-grid/#track-sizing
10171 // [ ident* ]
10172 var Brackets = {
10173 name: 'Brackets',
10174 structure: {
10175 children: [[]]
10176 },
10177 parse: function(readSequence, recognizer) {
10178 var start = this.scanner.tokenStart;
10179 var children = null;
10180
10181 this.scanner.eat(LEFTSQUAREBRACKET$4);
10182 children = readSequence.call(this, recognizer);
10183 this.scanner.eat(RIGHTSQUAREBRACKET$2);
10184
10185 return {
10186 type: 'Brackets',
10187 loc: this.getLocation(start, this.scanner.tokenStart),
10188 children: children
10189 };
10190 },
10191 generate: function(processChunk, node) {
10192 processChunk('[');
10193 this.each(processChunk, node);
10194 processChunk(']');
10195 }
10196 };
10197
10198 var CDC$2 = tokenizer.TYPE.CDC;
10199
10200 var CDC_1 = {
10201 name: 'CDC',
10202 structure: [],
10203 parse: function() {
10204 var start = this.scanner.tokenStart;
10205
10206 this.scanner.eat(CDC$2); // -->
10207
10208 return {
10209 type: 'CDC',
10210 loc: this.getLocation(start, this.scanner.tokenStart)
10211 };
10212 },
10213 generate: function(processChunk) {
10214 processChunk('-->');
10215 }
10216 };
10217
10218 var CDO$2 = tokenizer.TYPE.CDO;
10219
10220 var CDO_1 = {
10221 name: 'CDO',
10222 structure: [],
10223 parse: function() {
10224 var start = this.scanner.tokenStart;
10225
10226 this.scanner.eat(CDO$2); // <!--
10227
10228 return {
10229 type: 'CDO',
10230 loc: this.getLocation(start, this.scanner.tokenStart)
10231 };
10232 },
10233 generate: function(processChunk) {
10234 processChunk('<!--');
10235 }
10236 };
10237
10238 var TYPE$g = tokenizer.TYPE;
10239 var IDENTIFIER$9 = TYPE$g.Identifier;
10240 var FULLSTOP$3 = TYPE$g.FullStop;
10241
10242 // '.' ident
10243 var ClassSelector = {
10244 name: 'ClassSelector',
10245 structure: {
10246 name: String
10247 },
10248 parse: function() {
10249 this.scanner.eat(FULLSTOP$3);
10250
10251 return {
10252 type: 'ClassSelector',
10253 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10254 name: this.scanner.consume(IDENTIFIER$9)
10255 };
10256 },
10257 generate: function(processChunk, node) {
10258 processChunk('.');
10259 processChunk(node.name);
10260 }
10261 };
10262
10263 var TYPE$h = tokenizer.TYPE;
10264
10265 var PLUSSIGN$5 = TYPE$h.PlusSign;
10266 var SOLIDUS$2 = TYPE$h.Solidus;
10267 var GREATERTHANSIGN$2 = TYPE$h.GreaterThanSign;
10268 var TILDE$2 = TYPE$h.Tilde;
10269
10270 // + | > | ~ | /deep/
10271 var Combinator = {
10272 name: 'Combinator',
10273 structure: {
10274 name: String
10275 },
10276 parse: function() {
10277 var start = this.scanner.tokenStart;
10278
10279 switch (this.scanner.tokenType) {
10280 case GREATERTHANSIGN$2:
10281 case PLUSSIGN$5:
10282 case TILDE$2:
10283 this.scanner.next();
10284 break;
10285
10286 case SOLIDUS$2:
10287 this.scanner.next();
10288 this.scanner.expectIdentifier('deep');
10289 this.scanner.eat(SOLIDUS$2);
10290 break;
10291
10292 default:
10293 this.scanner.error('Combinator is expected');
10294 }
10295
10296 return {
10297 type: 'Combinator',
10298 loc: this.getLocation(start, this.scanner.tokenStart),
10299 name: this.scanner.substrToCursor(start)
10300 };
10301 },
10302 generate: function(processChunk, node) {
10303 processChunk(node.name);
10304 }
10305 };
10306
10307 var TYPE$i = tokenizer.TYPE;
10308
10309 var ASTERISK$3 = TYPE$i.Asterisk;
10310 var SOLIDUS$3 = TYPE$i.Solidus;
10311
10312 // '/*' .* '*/'
10313 var Comment = {
10314 name: 'Comment',
10315 structure: {
10316 value: String
10317 },
10318 parse: function() {
10319 var start = this.scanner.tokenStart;
10320 var end = this.scanner.tokenEnd;
10321
10322 if ((end - start + 2) >= 2 &&
10323 this.scanner.source.charCodeAt(end - 2) === ASTERISK$3 &&
10324 this.scanner.source.charCodeAt(end - 1) === SOLIDUS$3) {
10325 end -= 2;
10326 }
10327
10328 this.scanner.next();
10329
10330 return {
10331 type: 'Comment',
10332 loc: this.getLocation(start, this.scanner.tokenStart),
10333 value: this.scanner.source.substring(start + 2, end)
10334 };
10335 },
10336 generate: function(processChunk, node) {
10337 processChunk('/*');
10338 processChunk(node.value);
10339 processChunk('*/');
10340 }
10341 };
10342
10343 var TYPE$j = tokenizer.TYPE;
10344
10345 var IDENTIFIER$a = TYPE$j.Identifier;
10346 var COLON$3 = TYPE$j.Colon;
10347 var EXCLAMATIONMARK$2 = TYPE$j.ExclamationMark;
10348 var SOLIDUS$4 = TYPE$j.Solidus;
10349 var ASTERISK$4 = TYPE$j.Asterisk;
10350 var DOLLARSIGN$1 = TYPE$j.DollarSign;
10351 var HYPHENMINUS$6 = TYPE$j.HyphenMinus;
10352 var SEMICOLON$4 = TYPE$j.Semicolon;
10353 var RIGHTCURLYBRACKET$3 = TYPE$j.RightCurlyBracket;
10354 var RIGHTPARENTHESIS$1 = TYPE$j.RightParenthesis;
10355 var PLUSSIGN$6 = TYPE$j.PlusSign;
10356 var NUMBERSIGN$2 = TYPE$j.NumberSign;
10357
10358 var Declaration = {
10359 name: 'Declaration',
10360 structure: {
10361 important: [Boolean, String],
10362 property: String,
10363 value: ['Value', 'Raw']
10364 },
10365 parse: function() {
10366 var start = this.scanner.tokenStart;
10367 var property = readProperty.call(this);
10368 var important = false;
10369 var value;
10370
10371 this.scanner.skipSC();
10372 this.scanner.eat(COLON$3);
10373
10374 if (isCustomProperty(property) ? this.parseCustomProperty : this.parseValue) {
10375 value = this.Value(property);
10376 } else {
10377 value = this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$2, SEMICOLON$4, false, false);
10378 }
10379
10380 if (this.scanner.tokenType === EXCLAMATIONMARK$2) {
10381 important = getImportant(this.scanner);
10382 this.scanner.skipSC();
10383 }
10384
10385 // TODO: include or not to include semicolon to range?
10386 // if (this.scanner.tokenType === SEMICOLON) {
10387 // this.scanner.next();
10388 // }
10389
10390 if (!this.scanner.eof &&
10391 this.scanner.tokenType !== SEMICOLON$4 &&
10392 this.scanner.tokenType !== RIGHTPARENTHESIS$1 &&
10393 this.scanner.tokenType !== RIGHTCURLYBRACKET$3) {
10394 this.scanner.error();
10395 }
10396
10397 return {
10398 type: 'Declaration',
10399 loc: this.getLocation(start, this.scanner.tokenStart),
10400 important: important,
10401 property: property,
10402 value: value
10403 };
10404 },
10405 generate: function(processChunk, node, item) {
10406 processChunk(node.property);
10407 processChunk(':');
10408 this.generate(processChunk, node.value);
10409
10410 if (node.important) {
10411 processChunk(node.important === true ? '!important' : '!' + node.important);
10412 }
10413
10414 if (item && item.next) {
10415 processChunk(';');
10416 }
10417 },
10418 walkContext: 'declaration'
10419 };
10420
10421 function isCustomProperty(name) {
10422 return name.length >= 2 &&
10423 name.charCodeAt(0) === HYPHENMINUS$6 &&
10424 name.charCodeAt(1) === HYPHENMINUS$6;
10425 }
10426
10427 function readProperty() {
10428 var start = this.scanner.tokenStart;
10429 var prefix = 0;
10430
10431 // hacks
10432 switch (this.scanner.tokenType) {
10433 case ASTERISK$4:
10434 case DOLLARSIGN$1:
10435 case PLUSSIGN$6:
10436 case NUMBERSIGN$2:
10437 prefix = 1;
10438 break;
10439
10440 // TODO: not sure we should support this hack
10441 case SOLIDUS$4:
10442 prefix = this.scanner.lookupType(1) === SOLIDUS$4 ? 2 : 1;
10443 break;
10444 }
10445
10446 if (this.scanner.lookupType(prefix) === HYPHENMINUS$6) {
10447 prefix++;
10448 }
10449
10450 if (prefix) {
10451 this.scanner.skip(prefix);
10452 }
10453
10454 this.scanner.eat(IDENTIFIER$a);
10455
10456 return this.scanner.substrToCursor(start);
10457 }
10458
10459 // ! ws* important
10460 function getImportant(scanner) {
10461 scanner.eat(EXCLAMATIONMARK$2);
10462 scanner.skipSC();
10463
10464 var important = scanner.consume(IDENTIFIER$a);
10465
10466 // store original value in case it differ from `important`
10467 // for better original source restoring and hacks like `!ie` support
10468 return important === 'important' ? true : important;
10469 }
10470
10471 var TYPE$k = tokenizer.TYPE;
10472
10473 var WHITESPACE$5 = TYPE$k.WhiteSpace;
10474 var COMMENT$5 = TYPE$k.Comment;
10475 var SEMICOLON$5 = TYPE$k.Semicolon;
10476
10477 function consumeRaw$3(startToken) {
10478 return this.Raw(startToken, 0, SEMICOLON$5, true, true);
10479 }
10480
10481 var DeclarationList = {
10482 name: 'DeclarationList',
10483 structure: {
10484 children: [['Declaration']]
10485 },
10486 parse: function() {
10487 var children = new list();
10488
10489
10490 while (!this.scanner.eof) {
10491 switch (this.scanner.tokenType) {
10492 case WHITESPACE$5:
10493 case COMMENT$5:
10494 case SEMICOLON$5:
10495 this.scanner.next();
10496 break;
10497
10498 default:
10499 children.appendData(this.tolerantParse(this.Declaration, consumeRaw$3));
10500 }
10501 }
10502
10503 return {
10504 type: 'DeclarationList',
10505 loc: this.getLocationFromList(children),
10506 children: children
10507 };
10508 },
10509 generate: function(processChunk, node) {
10510 this.each(processChunk, node);
10511 }
10512 };
10513
10514 var NUMBER$5 = tokenizer.TYPE.Number;
10515
10516 // special reader for units to avoid adjoined IE hacks (i.e. '1px\9')
10517 function readUnit(scanner) {
10518 var unit = scanner.getTokenValue();
10519 var backSlashPos = unit.indexOf('\\');
10520
10521 if (backSlashPos > 0) {
10522 // patch token offset
10523 scanner.tokenStart += backSlashPos;
10524
10525 // return part before backslash
10526 return unit.substring(0, backSlashPos);
10527 }
10528
10529 // no backslash in unit name
10530 scanner.next();
10531
10532 return unit;
10533 }
10534
10535 // number ident
10536 var Dimension = {
10537 name: 'Dimension',
10538 structure: {
10539 value: String,
10540 unit: String
10541 },
10542 parse: function() {
10543 var start = this.scanner.tokenStart;
10544 var value = this.scanner.consume(NUMBER$5);
10545 var unit = readUnit(this.scanner);
10546
10547 return {
10548 type: 'Dimension',
10549 loc: this.getLocation(start, this.scanner.tokenStart),
10550 value: value,
10551 unit: unit
10552 };
10553 },
10554 generate: function(processChunk, node) {
10555 processChunk(node.value);
10556 processChunk(node.unit);
10557 }
10558 };
10559
10560 var TYPE$l = tokenizer.TYPE;
10561 var RIGHTPARENTHESIS$2 = TYPE$l.RightParenthesis;
10562
10563 // <function-token> <sequence> ')'
10564 var _Function = {
10565 name: 'Function',
10566 structure: {
10567 name: String,
10568 children: [[]]
10569 },
10570 parse: function(readSequence, recognizer) {
10571 var start = this.scanner.tokenStart;
10572 var name = this.scanner.consumeFunctionName();
10573 var nameLowerCase = name.toLowerCase();
10574 var children;
10575
10576 children = recognizer.hasOwnProperty(nameLowerCase)
10577 ? recognizer[nameLowerCase].call(this, recognizer)
10578 : readSequence.call(this, recognizer);
10579
10580 this.scanner.eat(RIGHTPARENTHESIS$2);
10581
10582 return {
10583 type: 'Function',
10584 loc: this.getLocation(start, this.scanner.tokenStart),
10585 name: name,
10586 children: children
10587 };
10588 },
10589 generate: function(processChunk, node) {
10590 processChunk(node.name);
10591 processChunk('(');
10592 this.each(processChunk, node);
10593 processChunk(')');
10594 },
10595 walkContext: 'function'
10596 };
10597
10598 var isHex$1 = tokenizer.isHex;
10599 var TYPE$m = tokenizer.TYPE;
10600
10601 var IDENTIFIER$b = TYPE$m.Identifier;
10602 var NUMBER$6 = TYPE$m.Number;
10603 var NUMBERSIGN$3 = TYPE$m.NumberSign;
10604
10605 function consumeHexSequence(scanner, required) {
10606 if (!isHex$1(scanner.source.charCodeAt(scanner.tokenStart))) {
10607 if (required) {
10608 scanner.error('Unexpected input', scanner.tokenStart);
10609 } else {
10610 return;
10611 }
10612 }
10613
10614 for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
10615 var code = scanner.source.charCodeAt(pos);
10616
10617 // break on non-hex char
10618 if (!isHex$1(code)) {
10619 // break token, exclude symbol
10620 scanner.tokenStart = pos;
10621 return;
10622 }
10623 }
10624
10625 // token is full hex sequence, go to next token
10626 scanner.next();
10627 }
10628
10629 // # ident
10630 var HexColor = {
10631 name: 'HexColor',
10632 structure: {
10633 value: String
10634 },
10635 parse: function() {
10636 var start = this.scanner.tokenStart;
10637
10638 this.scanner.eat(NUMBERSIGN$3);
10639
10640
10641 switch (this.scanner.tokenType) {
10642 case NUMBER$6:
10643 consumeHexSequence(this.scanner, true);
10644
10645 // if token is identifier then number consists of hex only,
10646 // try to add identifier to result
10647 if (this.scanner.tokenType === IDENTIFIER$b) {
10648 consumeHexSequence(this.scanner, false);
10649 }
10650
10651 break;
10652
10653 case IDENTIFIER$b:
10654 consumeHexSequence(this.scanner, true);
10655 break;
10656
10657 default:
10658 this.scanner.error('Number or identifier is expected');
10659 }
10660
10661 return {
10662 type: 'HexColor',
10663 loc: this.getLocation(start, this.scanner.tokenStart),
10664 value: this.scanner.substrToCursor(start + 1) // skip #
10665 };
10666 },
10667 generate: function(processChunk, node) {
10668 processChunk('#');
10669 processChunk(node.value);
10670 }
10671 };
10672
10673 var TYPE$n = tokenizer.TYPE;
10674 var IDENTIFIER$c = TYPE$n.Identifier;
10675
10676 var Identifier = {
10677 name: 'Identifier',
10678 structure: {
10679 name: String
10680 },
10681 parse: function() {
10682 return {
10683 type: 'Identifier',
10684 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
10685 name: this.scanner.consume(IDENTIFIER$c)
10686 };
10687 },
10688 generate: function(processChunk, node) {
10689 processChunk(node.name);
10690 }
10691 };
10692
10693 var TYPE$o = tokenizer.TYPE;
10694 var IDENTIFIER$d = TYPE$o.Identifier;
10695 var NUMBERSIGN$4 = TYPE$o.NumberSign;
10696
10697 // '#' ident
10698 var IdSelector = {
10699 name: 'IdSelector',
10700 structure: {
10701 name: String
10702 },
10703 parse: function() {
10704 this.scanner.eat(NUMBERSIGN$4);
10705
10706 return {
10707 type: 'IdSelector',
10708 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10709 name: this.scanner.consume(IDENTIFIER$d)
10710 };
10711 },
10712 generate: function(processChunk, node) {
10713 processChunk('#');
10714 processChunk(node.name);
10715 }
10716 };
10717
10718 var TYPE$p = tokenizer.TYPE;
10719
10720 var IDENTIFIER$e = TYPE$p.Identifier;
10721 var NUMBER$7 = TYPE$p.Number;
10722 var LEFTPARENTHESIS$4 = TYPE$p.LeftParenthesis;
10723 var RIGHTPARENTHESIS$3 = TYPE$p.RightParenthesis;
10724 var COLON$4 = TYPE$p.Colon;
10725 var SOLIDUS$5 = TYPE$p.Solidus;
10726
10727 var MediaFeature = {
10728 name: 'MediaFeature',
10729 structure: {
10730 name: String,
10731 value: ['Identifier', 'Number', 'Dimension', 'Ratio', null]
10732 },
10733 parse: function() {
10734 var start = this.scanner.tokenStart;
10735 var name;
10736 var value = null;
10737
10738 this.scanner.eat(LEFTPARENTHESIS$4);
10739 this.scanner.skipSC();
10740
10741 name = this.scanner.consume(IDENTIFIER$e);
10742 this.scanner.skipSC();
10743
10744 if (this.scanner.tokenType !== RIGHTPARENTHESIS$3) {
10745 this.scanner.eat(COLON$4);
10746 this.scanner.skipSC();
10747
10748 switch (this.scanner.tokenType) {
10749 case NUMBER$7:
10750 if (this.scanner.lookupType(1) === IDENTIFIER$e) {
10751 value = this.Dimension();
10752 } else if (this.scanner.lookupNonWSType(1) === SOLIDUS$5) {
10753 value = this.Ratio();
10754 } else {
10755 value = this.Number();
10756 }
10757
10758 break;
10759
10760 case IDENTIFIER$e:
10761 value = this.Identifier();
10762
10763 break;
10764
10765 default:
10766 this.scanner.error('Number, dimension, ratio or identifier is expected');
10767 }
10768
10769 this.scanner.skipSC();
10770 }
10771
10772 this.scanner.eat(RIGHTPARENTHESIS$3);
10773
10774 return {
10775 type: 'MediaFeature',
10776 loc: this.getLocation(start, this.scanner.tokenStart),
10777 name: name,
10778 value: value
10779 };
10780 },
10781 generate: function(processChunk, node) {
10782 processChunk('(');
10783 processChunk(node.name);
10784 if (node.value !== null) {
10785 processChunk(':');
10786 this.generate(processChunk, node.value);
10787 }
10788 processChunk(')');
10789 }
10790 };
10791
10792 var TYPE$q = tokenizer.TYPE;
10793
10794 var WHITESPACE$6 = TYPE$q.WhiteSpace;
10795 var COMMENT$6 = TYPE$q.Comment;
10796 var IDENTIFIER$f = TYPE$q.Identifier;
10797 var LEFTPARENTHESIS$5 = TYPE$q.LeftParenthesis;
10798
10799 var MediaQuery = {
10800 name: 'MediaQuery',
10801 structure: {
10802 children: [['Identifier', 'MediaFeature', 'WhiteSpace']]
10803 },
10804 parse: function() {
10805 this.scanner.skipSC();
10806
10807 var children = new list();
10808 var child = null;
10809 var space = null;
10810
10811 scan:
10812 while (!this.scanner.eof) {
10813 switch (this.scanner.tokenType) {
10814 case COMMENT$6:
10815 this.scanner.next();
10816 continue;
10817
10818 case WHITESPACE$6:
10819 space = this.WhiteSpace();
10820 continue;
10821
10822 case IDENTIFIER$f:
10823 child = this.Identifier();
10824 break;
10825
10826 case LEFTPARENTHESIS$5:
10827 child = this.MediaFeature();
10828 break;
10829
10830 default:
10831 break scan;
10832 }
10833
10834 if (space !== null) {
10835 children.appendData(space);
10836 space = null;
10837 }
10838
10839 children.appendData(child);
10840 }
10841
10842 if (child === null) {
10843 this.scanner.error('Identifier or parenthesis is expected');
10844 }
10845
10846 return {
10847 type: 'MediaQuery',
10848 loc: this.getLocationFromList(children),
10849 children: children
10850 };
10851 },
10852 generate: function(processChunk, node) {
10853 this.each(processChunk, node);
10854 }
10855 };
10856
10857 var COMMA$2 = tokenizer.TYPE.Comma;
10858
10859 var MediaQueryList = {
10860 name: 'MediaQueryList',
10861 structure: {
10862 children: [['MediaQuery']]
10863 },
10864 parse: function(relative) {
10865 var children = new list();
10866
10867 this.scanner.skipSC();
10868
10869 while (!this.scanner.eof) {
10870 children.appendData(this.MediaQuery(relative));
10871
10872 if (this.scanner.tokenType !== COMMA$2) {
10873 break;
10874 }
10875
10876 this.scanner.next();
10877 }
10878
10879 return {
10880 type: 'MediaQueryList',
10881 loc: this.getLocationFromList(children),
10882 children: children
10883 };
10884 },
10885 generate: function(processChunk, node) {
10886 this.eachComma(processChunk, node);
10887 }
10888 };
10889
10890 // https://drafts.csswg.org/css-syntax-3/#the-anb-type
10891 var Nth = {
10892 name: 'Nth',
10893 structure: {
10894 nth: ['AnPlusB', 'Identifier'],
10895 selector: ['SelectorList', null]
10896 },
10897 parse: function(allowOfClause) {
10898 this.scanner.skipSC();
10899
10900 var start = this.scanner.tokenStart;
10901 var end = start;
10902 var selector = null;
10903 var query;
10904
10905 if (this.scanner.lookupValue(0, 'odd') || this.scanner.lookupValue(0, 'even')) {
10906 query = this.Identifier();
10907 } else {
10908 query = this.AnPlusB();
10909 }
10910
10911 this.scanner.skipSC();
10912
10913 if (allowOfClause && this.scanner.lookupValue(0, 'of')) {
10914 this.scanner.next();
10915
10916 selector = this.SelectorList();
10917
10918 if (this.needPositions) {
10919 end = selector.children.last().loc.end.offset;
10920 }
10921 } else {
10922 if (this.needPositions) {
10923 end = query.loc.end.offset;
10924 }
10925 }
10926
10927 return {
10928 type: 'Nth',
10929 loc: this.getLocation(start, end),
10930 nth: query,
10931 selector: selector
10932 };
10933 },
10934 generate: function(processChunk, node) {
10935 this.generate(processChunk, node.nth);
10936 if (node.selector !== null) {
10937 processChunk(' of ');
10938 this.generate(processChunk, node.selector);
10939 }
10940 }
10941 };
10942
10943 var NUMBER$8 = tokenizer.TYPE.Number;
10944
10945 var _Number = {
10946 name: 'Number',
10947 structure: {
10948 value: String
10949 },
10950 parse: function() {
10951 return {
10952 type: 'Number',
10953 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
10954 value: this.scanner.consume(NUMBER$8)
10955 };
10956 },
10957 generate: function(processChunk, node) {
10958 processChunk(node.value);
10959 }
10960 };
10961
10962 // '/' | '*' | ',' | ':' | '+' | '-'
10963 var Operator = {
10964 name: 'Operator',
10965 structure: {
10966 value: String
10967 },
10968 parse: function() {
10969 var start = this.scanner.tokenStart;
10970
10971 this.scanner.next();
10972
10973 return {
10974 type: 'Operator',
10975 loc: this.getLocation(start, this.scanner.tokenStart),
10976 value: this.scanner.substrToCursor(start)
10977 };
10978 },
10979 generate: function(processChunk, node) {
10980 processChunk(node.value);
10981 }
10982 };
10983
10984 var TYPE$r = tokenizer.TYPE;
10985 var LEFTPARENTHESIS$6 = TYPE$r.LeftParenthesis;
10986 var RIGHTPARENTHESIS$4 = TYPE$r.RightParenthesis;
10987
10988 var Parentheses = {
10989 name: 'Parentheses',
10990 structure: {
10991 children: [[]]
10992 },
10993 parse: function(readSequence, recognizer) {
10994 var start = this.scanner.tokenStart;
10995 var children = null;
10996
10997 this.scanner.eat(LEFTPARENTHESIS$6);
10998 children = readSequence.call(this, recognizer);
10999 this.scanner.eat(RIGHTPARENTHESIS$4);
11000
11001 return {
11002 type: 'Parentheses',
11003 loc: this.getLocation(start, this.scanner.tokenStart),
11004 children: children
11005 };
11006 },
11007 generate: function(processChunk, node) {
11008 processChunk('(');
11009 this.each(processChunk, node);
11010 processChunk(')');
11011 }
11012 };
11013
11014 var TYPE$s = tokenizer.TYPE;
11015
11016 var NUMBER$9 = TYPE$s.Number;
11017 var PERCENTSIGN$1 = TYPE$s.PercentSign;
11018
11019 var Percentage = {
11020 name: 'Percentage',
11021 structure: {
11022 value: String
11023 },
11024 parse: function() {
11025 var start = this.scanner.tokenStart;
11026 var number = this.scanner.consume(NUMBER$9);
11027
11028 this.scanner.eat(PERCENTSIGN$1);
11029
11030 return {
11031 type: 'Percentage',
11032 loc: this.getLocation(start, this.scanner.tokenStart),
11033 value: number
11034 };
11035 },
11036 generate: function(processChunk, node) {
11037 processChunk(node.value);
11038 processChunk('%');
11039 }
11040 };
11041
11042 var TYPE$t = tokenizer.TYPE;
11043
11044 var IDENTIFIER$g = TYPE$t.Identifier;
11045 var FUNCTION$4 = TYPE$t.Function;
11046 var COLON$5 = TYPE$t.Colon;
11047 var RIGHTPARENTHESIS$5 = TYPE$t.RightParenthesis;
11048
11049 // : ident [ '(' .. ')' ]?
11050 var PseudoClassSelector = {
11051 name: 'PseudoClassSelector',
11052 structure: {
11053 name: String,
11054 children: [['Raw'], null]
11055 },
11056 parse: function() {
11057 var start = this.scanner.tokenStart;
11058 var children = null;
11059 var name;
11060 var nameLowerCase;
11061
11062 this.scanner.eat(COLON$5);
11063
11064 if (this.scanner.tokenType === FUNCTION$4) {
11065 name = this.scanner.consumeFunctionName();
11066 nameLowerCase = name.toLowerCase();
11067
11068 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11069 this.scanner.skipSC();
11070 children = this.pseudo[nameLowerCase].call(this);
11071 this.scanner.skipSC();
11072 } else {
11073 children = new list().appendData(
11074 this.Raw(this.scanner.currentToken, 0, 0, false, false)
11075 );
11076 }
11077
11078 this.scanner.eat(RIGHTPARENTHESIS$5);
11079 } else {
11080 name = this.scanner.consume(IDENTIFIER$g);
11081 }
11082
11083 return {
11084 type: 'PseudoClassSelector',
11085 loc: this.getLocation(start, this.scanner.tokenStart),
11086 name: name,
11087 children: children
11088 };
11089 },
11090 generate: function(processChunk, node) {
11091 processChunk(':');
11092 processChunk(node.name);
11093
11094 if (node.children !== null) {
11095 processChunk('(');
11096 this.each(processChunk, node);
11097 processChunk(')');
11098 }
11099 },
11100 walkContext: 'function'
11101 };
11102
11103 var TYPE$u = tokenizer.TYPE;
11104
11105 var IDENTIFIER$h = TYPE$u.Identifier;
11106 var FUNCTION$5 = TYPE$u.Function;
11107 var COLON$6 = TYPE$u.Colon;
11108 var RIGHTPARENTHESIS$6 = TYPE$u.RightParenthesis;
11109
11110 // :: ident [ '(' .. ')' ]?
11111 var PseudoElementSelector = {
11112 name: 'PseudoElementSelector',
11113 structure: {
11114 name: String,
11115 children: [['Raw'], null]
11116 },
11117 parse: function() {
11118 var start = this.scanner.tokenStart;
11119 var children = null;
11120 var name;
11121 var nameLowerCase;
11122
11123 this.scanner.eat(COLON$6);
11124 this.scanner.eat(COLON$6);
11125
11126 if (this.scanner.tokenType === FUNCTION$5) {
11127 name = this.scanner.consumeFunctionName();
11128 nameLowerCase = name.toLowerCase();
11129
11130 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11131 this.scanner.skipSC();
11132 children = this.pseudo[nameLowerCase].call(this);
11133 this.scanner.skipSC();
11134 } else {
11135 children = new list().appendData(
11136 this.Raw(this.scanner.currentToken, 0, 0, false, false)
11137 );
11138 }
11139
11140 this.scanner.eat(RIGHTPARENTHESIS$6);
11141 } else {
11142 name = this.scanner.consume(IDENTIFIER$h);
11143 }
11144
11145 return {
11146 type: 'PseudoElementSelector',
11147 loc: this.getLocation(start, this.scanner.tokenStart),
11148 name: name,
11149 children: children
11150 };
11151 },
11152 generate: function(processChunk, node) {
11153 processChunk('::');
11154 processChunk(node.name);
11155
11156 if (node.children !== null) {
11157 processChunk('(');
11158 this.each(processChunk, node);
11159 processChunk(')');
11160 }
11161 },
11162 walkContext: 'function'
11163 };
11164
11165 var isNumber$3 = tokenizer.isNumber;
11166 var TYPE$v = tokenizer.TYPE;
11167 var NUMBER$a = TYPE$v.Number;
11168 var SOLIDUS$6 = TYPE$v.Solidus;
11169 var FULLSTOP$4 = TYPE$v.FullStop;
11170
11171 // Terms of <ratio> should to be a positive number (not zero or negative)
11172 // (see https://drafts.csswg.org/mediaqueries-3/#values)
11173 // However, -o-min-device-pixel-ratio takes fractional values as a ratio's term
11174 // and this is using by various sites. Therefore we relax checking on parse
11175 // to test a term is unsigned number without exponent part.
11176 // Additional checks may to be applied on lexer validation.
11177 function consumeNumber(scanner) {
11178 var value = scanner.consumeNonWS(NUMBER$a);
11179
11180 for (var i = 0; i < value.length; i++) {
11181 var code = value.charCodeAt(i);
11182 if (!isNumber$3(code) && code !== FULLSTOP$4) {
11183 scanner.error('Unsigned number is expected', scanner.tokenStart - value.length + i);
11184 }
11185 }
11186
11187 if (Number(value) === 0) {
11188 scanner.error('Zero number is not allowed', scanner.tokenStart - value.length);
11189 }
11190
11191 return value;
11192 }
11193
11194 // <positive-integer> S* '/' S* <positive-integer>
11195 var Ratio = {
11196 name: 'Ratio',
11197 structure: {
11198 left: String,
11199 right: String
11200 },
11201 parse: function() {
11202 var start = this.scanner.tokenStart;
11203 var left = consumeNumber(this.scanner);
11204 var right;
11205
11206 this.scanner.eatNonWS(SOLIDUS$6);
11207 right = consumeNumber(this.scanner);
11208
11209 return {
11210 type: 'Ratio',
11211 loc: this.getLocation(start, this.scanner.tokenStart),
11212 left: left,
11213 right: right
11214 };
11215 },
11216 generate: function(processChunk, node) {
11217 processChunk(node.left);
11218 processChunk('/');
11219 processChunk(node.right);
11220 }
11221 };
11222
11223 var Raw = {
11224 name: 'Raw',
11225 structure: {
11226 value: String
11227 },
11228 parse: function(startToken, endTokenType1, endTokenType2, includeTokenType2, excludeWhiteSpace) {
11229 var startOffset = this.scanner.getTokenStart(startToken);
11230 var endOffset;
11231
11232 this.scanner.skip(
11233 this.scanner.getRawLength(
11234 startToken,
11235 endTokenType1,
11236 endTokenType2,
11237 includeTokenType2
11238 )
11239 );
11240
11241 if (excludeWhiteSpace && this.scanner.tokenStart > startOffset) {
11242 endOffset = this.scanner.getOffsetExcludeWS();
11243 } else {
11244 endOffset = this.scanner.tokenStart;
11245 }
11246
11247 return {
11248 type: 'Raw',
11249 loc: this.getLocation(startOffset, endOffset),
11250 value: this.scanner.source.substring(startOffset, endOffset)
11251 };
11252 },
11253 generate: function(processChunk, node) {
11254 processChunk(node.value);
11255 }
11256 };
11257
11258 var TYPE$w = tokenizer.TYPE;
11259
11260 var LEFTCURLYBRACKET$5 = TYPE$w.LeftCurlyBracket;
11261
11262 function consumeRaw$4(startToken) {
11263 return this.Raw(startToken, LEFTCURLYBRACKET$5, 0, false, true);
11264 }
11265
11266 var Rule = {
11267 name: 'Rule',
11268 structure: {
11269 selector: ['SelectorList', 'Raw'],
11270 block: ['Block']
11271 },
11272 parse: function() {
11273 var startToken = this.scanner.currentToken;
11274 var startOffset = this.scanner.tokenStart;
11275 var selector = this.parseSelector
11276 ? this.tolerantParse(this.SelectorList, consumeRaw$4)
11277 : consumeRaw$4.call(this, startToken);
11278 var block = this.Block(this.Declaration);
11279
11280 return {
11281 type: 'Rule',
11282 loc: this.getLocation(startOffset, this.scanner.tokenStart),
11283 selector: selector,
11284 block: block
11285 };
11286 },
11287 generate: function(processChunk, node) {
11288 this.generate(processChunk, node.selector);
11289 this.generate(processChunk, node.block);
11290 },
11291 walkContext: 'rule'
11292 };
11293
11294 var Selector = {
11295 name: 'Selector',
11296 structure: {
11297 children: [[
11298 'TypeSelector',
11299 'IdSelector',
11300 'ClassSelector',
11301 'AttributeSelector',
11302 'PseudoClassSelector',
11303 'PseudoElementSelector',
11304 'Combinator',
11305 'WhiteSpace'
11306 ]]
11307 },
11308 parse: function() {
11309 var children = this.readSequence(this.scope.Selector);
11310
11311 // nothing were consumed
11312 if (children.isEmpty()) {
11313 this.scanner.error('Selector is expected');
11314 }
11315
11316 return {
11317 type: 'Selector',
11318 loc: this.getLocationFromList(children),
11319 children: children
11320 };
11321 },
11322 generate: function(processChunk, node) {
11323 this.each(processChunk, node);
11324 }
11325 };
11326
11327 var TYPE$x = tokenizer.TYPE;
11328
11329 var COMMA$3 = TYPE$x.Comma;
11330 var LEFTCURLYBRACKET$6 = TYPE$x.LeftCurlyBracket;
11331
11332 var SelectorList = {
11333 name: 'SelectorList',
11334 structure: {
11335 children: [['Selector', 'Raw']]
11336 },
11337 parse: function() {
11338 var children = new list();
11339
11340 while (!this.scanner.eof) {
11341 children.appendData(this.parseSelector
11342 ? this.Selector()
11343 : this.Raw(this.scanner.currentToken, COMMA$3, LEFTCURLYBRACKET$6, false, false)
11344 );
11345
11346 if (this.scanner.tokenType === COMMA$3) {
11347 this.scanner.next();
11348 continue;
11349 }
11350
11351 break;
11352 }
11353
11354 return {
11355 type: 'SelectorList',
11356 loc: this.getLocationFromList(children),
11357 children: children
11358 };
11359 },
11360 generate: function(processChunk, node) {
11361 this.eachComma(processChunk, node);
11362 },
11363 walkContext: 'selector'
11364 };
11365
11366 var STRING$5 = tokenizer.TYPE.String;
11367
11368 var _String = {
11369 name: 'String',
11370 structure: {
11371 value: String
11372 },
11373 parse: function() {
11374 return {
11375 type: 'String',
11376 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11377 value: this.scanner.consume(STRING$5)
11378 };
11379 },
11380 generate: function(processChunk, node) {
11381 processChunk(node.value);
11382 }
11383 };
11384
11385 var TYPE$y = tokenizer.TYPE;
11386
11387 var WHITESPACE$7 = TYPE$y.WhiteSpace;
11388 var COMMENT$7 = TYPE$y.Comment;
11389 var EXCLAMATIONMARK$3 = TYPE$y.ExclamationMark;
11390 var ATRULE$4 = TYPE$y.Atrule;
11391 var CDO$3 = TYPE$y.CDO;
11392 var CDC$3 = TYPE$y.CDC;
11393
11394 function consumeRaw$5(startToken) {
11395 return this.Raw(startToken, 0, 0, false, false);
11396 }
11397
11398 var StyleSheet = {
11399 name: 'StyleSheet',
11400 structure: {
11401 children: [['Comment', 'Atrule', 'Rule', 'Raw']]
11402 },
11403 parse: function() {
11404 var start = this.scanner.tokenStart;
11405 var children = new list();
11406 var child;
11407
11408
11409 while (!this.scanner.eof) {
11410 switch (this.scanner.tokenType) {
11411 case WHITESPACE$7:
11412 this.scanner.next();
11413 continue;
11414
11415 case COMMENT$7:
11416 // ignore comments except exclamation comments (i.e. /*! .. */) on top level
11417 if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 2) !== EXCLAMATIONMARK$3) {
11418 this.scanner.next();
11419 continue;
11420 }
11421
11422 child = this.Comment();
11423 break;
11424
11425 case CDO$3: // <!--
11426 child = this.CDO();
11427 break;
11428
11429 case CDC$3: // -->
11430 child = this.CDC();
11431 break;
11432
11433 // CSS Syntax Module Level 3
11434 // §2.2 Error handling
11435 // At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule.
11436 case ATRULE$4:
11437 child = this.Atrule();
11438 break;
11439
11440 // Anything else starts a qualified rule ...
11441 default:
11442 child = this.tolerantParse(this.Rule, consumeRaw$5);
11443 }
11444
11445 children.appendData(child);
11446 }
11447
11448 return {
11449 type: 'StyleSheet',
11450 loc: this.getLocation(start, this.scanner.tokenStart),
11451 children: children
11452 };
11453 },
11454 generate: function(processChunk, node) {
11455 this.each(processChunk, node);
11456 },
11457 walkContext: 'stylesheet'
11458 };
11459
11460 var TYPE$z = tokenizer.TYPE;
11461
11462 var IDENTIFIER$i = TYPE$z.Identifier;
11463 var ASTERISK$5 = TYPE$z.Asterisk;
11464 var VERTICALLINE$2 = TYPE$z.VerticalLine;
11465
11466 function eatIdentifierOrAsterisk() {
11467 if (this.scanner.tokenType !== IDENTIFIER$i &&
11468 this.scanner.tokenType !== ASTERISK$5) {
11469 this.scanner.error('Identifier or asterisk is expected');
11470 }
11471
11472 this.scanner.next();
11473 }
11474
11475 // ident
11476 // ident|ident
11477 // ident|*
11478 // *
11479 // *|ident
11480 // *|*
11481 // |ident
11482 // |*
11483 var TypeSelector = {
11484 name: 'TypeSelector',
11485 structure: {
11486 name: String
11487 },
11488 parse: function() {
11489 var start = this.scanner.tokenStart;
11490
11491 if (this.scanner.tokenType === VERTICALLINE$2) {
11492 this.scanner.next();
11493 eatIdentifierOrAsterisk.call(this);
11494 } else {
11495 eatIdentifierOrAsterisk.call(this);
11496
11497 if (this.scanner.tokenType === VERTICALLINE$2) {
11498 this.scanner.next();
11499 eatIdentifierOrAsterisk.call(this);
11500 }
11501 }
11502
11503 return {
11504 type: 'TypeSelector',
11505 loc: this.getLocation(start, this.scanner.tokenStart),
11506 name: this.scanner.substrToCursor(start)
11507 };
11508 },
11509 generate: function(processChunk, node) {
11510 processChunk(node.name);
11511 }
11512 };
11513
11514 var isHex$2 = tokenizer.isHex;
11515 var TYPE$A = tokenizer.TYPE;
11516
11517 var IDENTIFIER$j = TYPE$A.Identifier;
11518 var NUMBER$b = TYPE$A.Number;
11519 var PLUSSIGN$7 = TYPE$A.PlusSign;
11520 var HYPHENMINUS$7 = TYPE$A.HyphenMinus;
11521 var FULLSTOP$5 = TYPE$A.FullStop;
11522 var QUESTIONMARK = TYPE$A.QuestionMark;
11523
11524 function scanUnicodeNumber(scanner) {
11525 for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
11526 var code = scanner.source.charCodeAt(pos);
11527
11528 // break on fullstop or hyperminus/plussign after exponent
11529 if (code === FULLSTOP$5 || code === PLUSSIGN$7) {
11530 // break token, exclude symbol
11531 scanner.tokenStart = pos;
11532 return false;
11533 }
11534 }
11535
11536 return true;
11537 }
11538
11539 // https://drafts.csswg.org/css-syntax-3/#urange
11540 function scanUnicodeRange(scanner) {
11541 var hexStart = scanner.tokenStart + 1; // skip +
11542 var hexLength = 0;
11543
11544 scan: {
11545 if (scanner.tokenType === NUMBER$b) {
11546 if (scanner.source.charCodeAt(scanner.tokenStart) !== FULLSTOP$5 && scanUnicodeNumber(scanner)) {
11547 scanner.next();
11548 } else if (scanner.source.charCodeAt(scanner.tokenStart) !== HYPHENMINUS$7) {
11549 break scan;
11550 }
11551 } else {
11552 scanner.next(); // PLUSSIGN
11553 }
11554
11555 if (scanner.tokenType === HYPHENMINUS$7) {
11556 scanner.next();
11557 }
11558
11559 if (scanner.tokenType === NUMBER$b) {
11560 scanner.next();
11561 }
11562
11563 if (scanner.tokenType === IDENTIFIER$j) {
11564 scanner.next();
11565 }
11566
11567 if (scanner.tokenStart === hexStart) {
11568 scanner.error('Unexpected input', hexStart);
11569 }
11570 }
11571
11572 // validate for U+x{1,6} or U+x{1,6}-x{1,6}
11573 // where x is [0-9a-fA-F]
11574 for (var i = hexStart, wasHyphenMinus = false; i < scanner.tokenStart; i++) {
11575 var code = scanner.source.charCodeAt(i);
11576
11577 if (isHex$2(code) === false && (code !== HYPHENMINUS$7 || wasHyphenMinus)) {
11578 scanner.error('Unexpected input', i);
11579 }
11580
11581 if (code === HYPHENMINUS$7) {
11582 // hex sequence shouldn't be an empty
11583 if (hexLength === 0) {
11584 scanner.error('Unexpected input', i);
11585 }
11586
11587 wasHyphenMinus = true;
11588 hexLength = 0;
11589 } else {
11590 hexLength++;
11591
11592 // too long hex sequence
11593 if (hexLength > 6) {
11594 scanner.error('Too long hex sequence', i);
11595 }
11596 }
11597
11598 }
11599
11600 // check we have a non-zero sequence
11601 if (hexLength === 0) {
11602 scanner.error('Unexpected input', i - 1);
11603 }
11604
11605 // U+abc???
11606 if (!wasHyphenMinus) {
11607 // consume as many U+003F QUESTION MARK (?) code points as possible
11608 for (; hexLength < 6 && !scanner.eof; scanner.next()) {
11609 if (scanner.tokenType !== QUESTIONMARK) {
11610 break;
11611 }
11612
11613 hexLength++;
11614 }
11615 }
11616 }
11617
11618 var UnicodeRange = {
11619 name: 'UnicodeRange',
11620 structure: {
11621 value: String
11622 },
11623 parse: function() {
11624 var start = this.scanner.tokenStart;
11625
11626 this.scanner.next(); // U or u
11627 scanUnicodeRange(this.scanner);
11628
11629 return {
11630 type: 'UnicodeRange',
11631 loc: this.getLocation(start, this.scanner.tokenStart),
11632 value: this.scanner.substrToCursor(start)
11633 };
11634 },
11635 generate: function(processChunk, node) {
11636 processChunk(node.value);
11637 }
11638 };
11639
11640 var TYPE$B = tokenizer.TYPE;
11641
11642 var STRING$6 = TYPE$B.String;
11643 var URL$4 = TYPE$B.Url;
11644 var RAW$2 = TYPE$B.Raw;
11645 var RIGHTPARENTHESIS$7 = TYPE$B.RightParenthesis;
11646
11647 // url '(' S* (string | raw) S* ')'
11648 var Url = {
11649 name: 'Url',
11650 structure: {
11651 value: ['String', 'Raw']
11652 },
11653 parse: function() {
11654 var start = this.scanner.tokenStart;
11655 var value;
11656
11657 this.scanner.eat(URL$4);
11658 this.scanner.skipSC();
11659
11660 switch (this.scanner.tokenType) {
11661 case STRING$6:
11662 value = this.String();
11663 break;
11664
11665 case RAW$2:
11666 value = this.Raw(this.scanner.currentToken, 0, RAW$2, true, false);
11667 break;
11668
11669 default:
11670 this.scanner.error('String or Raw is expected');
11671 }
11672
11673 this.scanner.skipSC();
11674 this.scanner.eat(RIGHTPARENTHESIS$7);
11675
11676 return {
11677 type: 'Url',
11678 loc: this.getLocation(start, this.scanner.tokenStart),
11679 value: value
11680 };
11681 },
11682 generate: function(processChunk, node) {
11683 processChunk('url');
11684 processChunk('(');
11685 this.generate(processChunk, node.value);
11686 processChunk(')');
11687 }
11688 };
11689
11690 var endsWith$1 = tokenizer.endsWith;
11691 var TYPE$C = tokenizer.TYPE;
11692
11693 var WHITESPACE$8 = TYPE$C.WhiteSpace;
11694 var COMMENT$8 = TYPE$C.Comment;
11695 var FUNCTION$6 = TYPE$C.Function;
11696 var COLON$7 = TYPE$C.Colon;
11697 var SEMICOLON$6 = TYPE$C.Semicolon;
11698 var EXCLAMATIONMARK$4 = TYPE$C.ExclamationMark;
11699
11700 // 'progid:' ws* 'DXImageTransform.Microsoft.' ident ws* '(' .* ')'
11701 function checkProgid(scanner) {
11702 var offset = 0;
11703
11704 for (var type; type = scanner.lookupType(offset); offset++) {
11705 if (type !== WHITESPACE$8 && type !== COMMENT$8) {
11706 break;
11707 }
11708 }
11709
11710 if (scanner.lookupValue(offset, 'alpha(') ||
11711 scanner.lookupValue(offset, 'chroma(') ||
11712 scanner.lookupValue(offset, 'dropshadow(')) {
11713 if (scanner.lookupType(offset) !== FUNCTION$6) {
11714 return false;
11715 }
11716 } else {
11717 if (scanner.lookupValue(offset, 'progid') === false ||
11718 scanner.lookupType(offset + 1) !== COLON$7) {
11719 return false;
11720 }
11721 }
11722
11723 return true;
11724 }
11725
11726 var Value = {
11727 name: 'Value',
11728 structure: {
11729 children: [[]]
11730 },
11731 parse: function(property) {
11732 // special parser for filter property since it can contains non-standart syntax for old IE
11733 if (property !== null && endsWith$1(property, 'filter') && checkProgid(this.scanner)) {
11734 this.scanner.skipSC();
11735 return this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$4, SEMICOLON$6, false, false);
11736 }
11737
11738 var start = this.scanner.tokenStart;
11739 var children = this.readSequence(this.scope.Value);
11740
11741 return {
11742 type: 'Value',
11743 loc: this.getLocation(start, this.scanner.tokenStart),
11744 children: children
11745 };
11746 },
11747 generate: function(processChunk, node) {
11748 this.each(processChunk, node);
11749 }
11750 };
11751
11752 var WHITESPACE$9 = tokenizer.TYPE.WhiteSpace;
11753 var SPACE$2 = Object.freeze({
11754 type: 'WhiteSpace',
11755 loc: null,
11756 value: ' '
11757 });
11758
11759 var WhiteSpace = {
11760 name: 'WhiteSpace',
11761 structure: {
11762 value: String
11763 },
11764 parse: function() {
11765 this.scanner.eat(WHITESPACE$9);
11766 return SPACE$2;
11767
11768 // return {
11769 // type: 'WhiteSpace',
11770 // loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11771 // value: this.scanner.consume(WHITESPACE)
11772 // };
11773 },
11774 generate: function(processChunk, node) {
11775 processChunk(node.value);
11776 }
11777 };
11778
11779 var node = {
11780 AnPlusB: AnPlusB,
11781 Atrule: Atrule,
11782 AtruleExpression: AtruleExpression,
11783 AttributeSelector: AttributeSelector,
11784 Block: Block,
11785 Brackets: Brackets,
11786 CDC: CDC_1,
11787 CDO: CDO_1,
11788 ClassSelector: ClassSelector,
11789 Combinator: Combinator,
11790 Comment: Comment,
11791 Declaration: Declaration,
11792 DeclarationList: DeclarationList,
11793 Dimension: Dimension,
11794 Function: _Function,
11795 HexColor: HexColor,
11796 Identifier: Identifier,
11797 IdSelector: IdSelector,
11798 MediaFeature: MediaFeature,
11799 MediaQuery: MediaQuery,
11800 MediaQueryList: MediaQueryList,
11801 Nth: Nth,
11802 Number: _Number,
11803 Operator: Operator,
11804 Parentheses: Parentheses,
11805 Percentage: Percentage,
11806 PseudoClassSelector: PseudoClassSelector,
11807 PseudoElementSelector: PseudoElementSelector,
11808 Ratio: Ratio,
11809 Raw: Raw,
11810 Rule: Rule,
11811 Selector: Selector,
11812 SelectorList: SelectorList,
11813 String: _String,
11814 StyleSheet: StyleSheet,
11815 TypeSelector: TypeSelector,
11816 UnicodeRange: UnicodeRange,
11817 Url: Url,
11818 Value: Value,
11819 WhiteSpace: WhiteSpace
11820 };
11821
11822 var parser = {
11823 parseContext: {
11824 default: 'StyleSheet',
11825 stylesheet: 'StyleSheet',
11826 atrule: 'Atrule',
11827 atruleExpression: function(options) {
11828 return this.AtruleExpression(options.atrule ? String(options.atrule) : null);
11829 },
11830 mediaQueryList: 'MediaQueryList',
11831 mediaQuery: 'MediaQuery',
11832 rule: 'Rule',
11833 selectorList: 'SelectorList',
11834 selector: 'Selector',
11835 block: function() {
11836 return this.Block(this.Declaration);
11837 },
11838 declarationList: 'DeclarationList',
11839 declaration: 'Declaration',
11840 value: function(options) {
11841 return this.Value(options.property ? String(options.property) : null);
11842 }
11843 },
11844 scope: scope,
11845 atrule: atrule,
11846 pseudo: pseudo,
11847 node: node
11848 };
11849
11850 var parser$1 = create(parser);
11851
11852 function read_style(parser, start, attributes) {
11853 const content_start = parser.index;
11854 const styles = parser.read_until(/<\/style>/);
11855 const content_end = parser.index;
11856 let ast;
11857 try {
11858 ast = parser$1(styles, {
11859 positions: true,
11860 offset: content_start,
11861 });
11862 }
11863 catch (err) {
11864 if (err.name === 'CssSyntaxError') {
11865 parser.error({
11866 code: `css-syntax-error`,
11867 message: err.message
11868 }, err.offset);
11869 }
11870 else {
11871 throw err;
11872 }
11873 }
11874 ast = JSON.parse(JSON.stringify(ast));
11875 // tidy up AST
11876 walk(ast, {
11877 enter: (node) => {
11878 // replace `ref:a` nodes
11879 if (node.type === 'Selector') {
11880 for (let i = 0; i < node.children.length; i += 1) {
11881 const a = node.children[i];
11882 const b = node.children[i + 1];
11883 if (is_ref_selector(a, b)) {
11884 parser.error({
11885 code: `invalid-ref-selector`,
11886 message: 'ref selectors are no longer supported'
11887 }, a.loc.start.offset);
11888 }
11889 }
11890 }
11891 if (node.type === 'Declaration' && node.value.type === 'Value' && node.value.children.length === 0) {
11892 parser.error({
11893 code: `invalid-declaration`,
11894 message: `Declaration cannot be empty`
11895 }, node.start);
11896 }
11897 if (node.type === 'PseudoClassSelector' && node.name === 'global' && node.children === null) {
11898 parser.error({
11899 code: `css-syntax-error`,
11900 message: `:global() must contain a selector`
11901 }, node.loc.start.offset);
11902 }
11903 if (node.loc) {
11904 node.start = node.loc.start.offset;
11905 node.end = node.loc.end.offset;
11906 delete node.loc;
11907 }
11908 }
11909 });
11910 parser.eat('</style>', true);
11911 const end = parser.index;
11912 return {
11913 type: 'Style',
11914 start,
11915 end,
11916 attributes,
11917 children: ast.children,
11918 content: {
11919 start: content_start,
11920 end: content_end,
11921 styles
11922 }
11923 };
11924 }
11925 function is_ref_selector(a, b) {
11926 if (!b)
11927 return false;
11928 return (a.type === 'TypeSelector' &&
11929 a.name === 'ref' &&
11930 b.type === 'PseudoClassSelector');
11931 }
11932
11933 // https://dev.w3.org/html5/html-author/charref
11934 var entities = {
11935 CounterClockwiseContourIntegral: 8755,
11936 ClockwiseContourIntegral: 8754,
11937 DoubleLongLeftRightArrow: 10234,
11938 DiacriticalDoubleAcute: 733,
11939 NotSquareSupersetEqual: 8931,
11940 CloseCurlyDoubleQuote: 8221,
11941 DoubleContourIntegral: 8751,
11942 FilledVerySmallSquare: 9642,
11943 NegativeVeryThinSpace: 8203,
11944 NotPrecedesSlantEqual: 8928,
11945 NotRightTriangleEqual: 8941,
11946 NotSucceedsSlantEqual: 8929,
11947 CapitalDifferentialD: 8517,
11948 DoubleLeftRightArrow: 8660,
11949 DoubleLongRightArrow: 10233,
11950 EmptyVerySmallSquare: 9643,
11951 NestedGreaterGreater: 8811,
11952 NotDoubleVerticalBar: 8742,
11953 NotLeftTriangleEqual: 8940,
11954 NotSquareSubsetEqual: 8930,
11955 OpenCurlyDoubleQuote: 8220,
11956 ReverseUpEquilibrium: 10607,
11957 DoubleLongLeftArrow: 10232,
11958 DownLeftRightVector: 10576,
11959 LeftArrowRightArrow: 8646,
11960 NegativeMediumSpace: 8203,
11961 RightArrowLeftArrow: 8644,
11962 SquareSupersetEqual: 8850,
11963 leftrightsquigarrow: 8621,
11964 DownRightTeeVector: 10591,
11965 DownRightVectorBar: 10583,
11966 LongLeftRightArrow: 10231,
11967 Longleftrightarrow: 10234,
11968 NegativeThickSpace: 8203,
11969 PrecedesSlantEqual: 8828,
11970 ReverseEquilibrium: 8651,
11971 RightDoubleBracket: 10215,
11972 RightDownTeeVector: 10589,
11973 RightDownVectorBar: 10581,
11974 RightTriangleEqual: 8885,
11975 SquareIntersection: 8851,
11976 SucceedsSlantEqual: 8829,
11977 blacktriangleright: 9656,
11978 longleftrightarrow: 10231,
11979 DoubleUpDownArrow: 8661,
11980 DoubleVerticalBar: 8741,
11981 DownLeftTeeVector: 10590,
11982 DownLeftVectorBar: 10582,
11983 FilledSmallSquare: 9724,
11984 GreaterSlantEqual: 10878,
11985 LeftDoubleBracket: 10214,
11986 LeftDownTeeVector: 10593,
11987 LeftDownVectorBar: 10585,
11988 LeftTriangleEqual: 8884,
11989 NegativeThinSpace: 8203,
11990 NotReverseElement: 8716,
11991 NotTildeFullEqual: 8775,
11992 RightAngleBracket: 10217,
11993 RightUpDownVector: 10575,
11994 SquareSubsetEqual: 8849,
11995 VerticalSeparator: 10072,
11996 blacktriangledown: 9662,
11997 blacktriangleleft: 9666,
11998 leftrightharpoons: 8651,
11999 rightleftharpoons: 8652,
12000 twoheadrightarrow: 8608,
12001 DiacriticalAcute: 180,
12002 DiacriticalGrave: 96,
12003 DiacriticalTilde: 732,
12004 DoubleRightArrow: 8658,
12005 DownArrowUpArrow: 8693,
12006 EmptySmallSquare: 9723,
12007 GreaterEqualLess: 8923,
12008 GreaterFullEqual: 8807,
12009 LeftAngleBracket: 10216,
12010 LeftUpDownVector: 10577,
12011 LessEqualGreater: 8922,
12012 NonBreakingSpace: 160,
12013 NotRightTriangle: 8939,
12014 NotSupersetEqual: 8841,
12015 RightTriangleBar: 10704,
12016 RightUpTeeVector: 10588,
12017 RightUpVectorBar: 10580,
12018 UnderParenthesis: 9181,
12019 UpArrowDownArrow: 8645,
12020 circlearrowright: 8635,
12021 downharpoonright: 8642,
12022 ntrianglerighteq: 8941,
12023 rightharpoondown: 8641,
12024 rightrightarrows: 8649,
12025 twoheadleftarrow: 8606,
12026 vartriangleright: 8883,
12027 CloseCurlyQuote: 8217,
12028 ContourIntegral: 8750,
12029 DoubleDownArrow: 8659,
12030 DoubleLeftArrow: 8656,
12031 DownRightVector: 8641,
12032 LeftRightVector: 10574,
12033 LeftTriangleBar: 10703,
12034 LeftUpTeeVector: 10592,
12035 LeftUpVectorBar: 10584,
12036 LowerRightArrow: 8600,
12037 NotGreaterEqual: 8817,
12038 NotGreaterTilde: 8821,
12039 NotLeftTriangle: 8938,
12040 OverParenthesis: 9180,
12041 RightDownVector: 8642,
12042 ShortRightArrow: 8594,
12043 UpperRightArrow: 8599,
12044 bigtriangledown: 9661,
12045 circlearrowleft: 8634,
12046 curvearrowright: 8631,
12047 downharpoonleft: 8643,
12048 leftharpoondown: 8637,
12049 leftrightarrows: 8646,
12050 nLeftrightarrow: 8654,
12051 nleftrightarrow: 8622,
12052 ntrianglelefteq: 8940,
12053 rightleftarrows: 8644,
12054 rightsquigarrow: 8605,
12055 rightthreetimes: 8908,
12056 straightepsilon: 1013,
12057 trianglerighteq: 8885,
12058 vartriangleleft: 8882,
12059 DiacriticalDot: 729,
12060 DoubleRightTee: 8872,
12061 DownLeftVector: 8637,
12062 GreaterGreater: 10914,
12063 HorizontalLine: 9472,
12064 InvisibleComma: 8291,
12065 InvisibleTimes: 8290,
12066 LeftDownVector: 8643,
12067 LeftRightArrow: 8596,
12068 Leftrightarrow: 8660,
12069 LessSlantEqual: 10877,
12070 LongRightArrow: 10230,
12071 Longrightarrow: 10233,
12072 LowerLeftArrow: 8601,
12073 NestedLessLess: 8810,
12074 NotGreaterLess: 8825,
12075 NotLessGreater: 8824,
12076 NotSubsetEqual: 8840,
12077 NotVerticalBar: 8740,
12078 OpenCurlyQuote: 8216,
12079 ReverseElement: 8715,
12080 RightTeeVector: 10587,
12081 RightVectorBar: 10579,
12082 ShortDownArrow: 8595,
12083 ShortLeftArrow: 8592,
12084 SquareSuperset: 8848,
12085 TildeFullEqual: 8773,
12086 UpperLeftArrow: 8598,
12087 ZeroWidthSpace: 8203,
12088 curvearrowleft: 8630,
12089 doublebarwedge: 8966,
12090 downdownarrows: 8650,
12091 hookrightarrow: 8618,
12092 leftleftarrows: 8647,
12093 leftrightarrow: 8596,
12094 leftthreetimes: 8907,
12095 longrightarrow: 10230,
12096 looparrowright: 8620,
12097 nshortparallel: 8742,
12098 ntriangleright: 8939,
12099 rightarrowtail: 8611,
12100 rightharpoonup: 8640,
12101 trianglelefteq: 8884,
12102 upharpoonright: 8638,
12103 ApplyFunction: 8289,
12104 DifferentialD: 8518,
12105 DoubleLeftTee: 10980,
12106 DoubleUpArrow: 8657,
12107 LeftTeeVector: 10586,
12108 LeftVectorBar: 10578,
12109 LessFullEqual: 8806,
12110 LongLeftArrow: 10229,
12111 Longleftarrow: 10232,
12112 NotTildeEqual: 8772,
12113 NotTildeTilde: 8777,
12114 Poincareplane: 8460,
12115 PrecedesEqual: 10927,
12116 PrecedesTilde: 8830,
12117 RightArrowBar: 8677,
12118 RightTeeArrow: 8614,
12119 RightTriangle: 8883,
12120 RightUpVector: 8638,
12121 SucceedsEqual: 10928,
12122 SucceedsTilde: 8831,
12123 SupersetEqual: 8839,
12124 UpEquilibrium: 10606,
12125 VerticalTilde: 8768,
12126 VeryThinSpace: 8202,
12127 bigtriangleup: 9651,
12128 blacktriangle: 9652,
12129 divideontimes: 8903,
12130 fallingdotseq: 8786,
12131 hookleftarrow: 8617,
12132 leftarrowtail: 8610,
12133 leftharpoonup: 8636,
12134 longleftarrow: 10229,
12135 looparrowleft: 8619,
12136 measuredangle: 8737,
12137 ntriangleleft: 8938,
12138 shortparallel: 8741,
12139 smallsetminus: 8726,
12140 triangleright: 9657,
12141 upharpoonleft: 8639,
12142 DownArrowBar: 10515,
12143 DownTeeArrow: 8615,
12144 ExponentialE: 8519,
12145 GreaterEqual: 8805,
12146 GreaterTilde: 8819,
12147 HilbertSpace: 8459,
12148 HumpDownHump: 8782,
12149 Intersection: 8898,
12150 LeftArrowBar: 8676,
12151 LeftTeeArrow: 8612,
12152 LeftTriangle: 8882,
12153 LeftUpVector: 8639,
12154 NotCongruent: 8802,
12155 NotLessEqual: 8816,
12156 NotLessTilde: 8820,
12157 Proportional: 8733,
12158 RightCeiling: 8969,
12159 RoundImplies: 10608,
12160 ShortUpArrow: 8593,
12161 SquareSubset: 8847,
12162 UnderBracket: 9141,
12163 VerticalLine: 124,
12164 blacklozenge: 10731,
12165 exponentiale: 8519,
12166 risingdotseq: 8787,
12167 triangledown: 9663,
12168 triangleleft: 9667,
12169 CircleMinus: 8854,
12170 CircleTimes: 8855,
12171 Equilibrium: 8652,
12172 GreaterLess: 8823,
12173 LeftCeiling: 8968,
12174 LessGreater: 8822,
12175 MediumSpace: 8287,
12176 NotPrecedes: 8832,
12177 NotSucceeds: 8833,
12178 OverBracket: 9140,
12179 RightVector: 8640,
12180 Rrightarrow: 8667,
12181 RuleDelayed: 10740,
12182 SmallCircle: 8728,
12183 SquareUnion: 8852,
12184 SubsetEqual: 8838,
12185 UpDownArrow: 8597,
12186 Updownarrow: 8661,
12187 VerticalBar: 8739,
12188 backepsilon: 1014,
12189 blacksquare: 9642,
12190 circledcirc: 8858,
12191 circleddash: 8861,
12192 curlyeqprec: 8926,
12193 curlyeqsucc: 8927,
12194 diamondsuit: 9830,
12195 eqslantless: 10901,
12196 expectation: 8496,
12197 nRightarrow: 8655,
12198 nrightarrow: 8603,
12199 preccurlyeq: 8828,
12200 precnapprox: 10937,
12201 quaternions: 8461,
12202 straightphi: 981,
12203 succcurlyeq: 8829,
12204 succnapprox: 10938,
12205 thickapprox: 8776,
12206 updownarrow: 8597,
12207 Bernoullis: 8492,
12208 CirclePlus: 8853,
12209 EqualTilde: 8770,
12210 Fouriertrf: 8497,
12211 ImaginaryI: 8520,
12212 Laplacetrf: 8466,
12213 LeftVector: 8636,
12214 Lleftarrow: 8666,
12215 NotElement: 8713,
12216 NotGreater: 8815,
12217 Proportion: 8759,
12218 RightArrow: 8594,
12219 RightFloor: 8971,
12220 Rightarrow: 8658,
12221 TildeEqual: 8771,
12222 TildeTilde: 8776,
12223 UnderBrace: 9183,
12224 UpArrowBar: 10514,
12225 UpTeeArrow: 8613,
12226 circledast: 8859,
12227 complement: 8705,
12228 curlywedge: 8911,
12229 eqslantgtr: 10902,
12230 gtreqqless: 10892,
12231 lessapprox: 10885,
12232 lesseqqgtr: 10891,
12233 lmoustache: 9136,
12234 longmapsto: 10236,
12235 mapstodown: 8615,
12236 mapstoleft: 8612,
12237 nLeftarrow: 8653,
12238 nleftarrow: 8602,
12239 precapprox: 10935,
12240 rightarrow: 8594,
12241 rmoustache: 9137,
12242 sqsubseteq: 8849,
12243 sqsupseteq: 8850,
12244 subsetneqq: 10955,
12245 succapprox: 10936,
12246 supsetneqq: 10956,
12247 upuparrows: 8648,
12248 varepsilon: 949,
12249 varnothing: 8709,
12250 Backslash: 8726,
12251 CenterDot: 183,
12252 CircleDot: 8857,
12253 Congruent: 8801,
12254 Coproduct: 8720,
12255 DoubleDot: 168,
12256 DownArrow: 8595,
12257 DownBreve: 785,
12258 Downarrow: 8659,
12259 HumpEqual: 8783,
12260 LeftArrow: 8592,
12261 LeftFloor: 8970,
12262 Leftarrow: 8656,
12263 LessTilde: 8818,
12264 Mellintrf: 8499,
12265 MinusPlus: 8723,
12266 NotCupCap: 8813,
12267 NotExists: 8708,
12268 OverBrace: 9182,
12269 PlusMinus: 177,
12270 Therefore: 8756,
12271 ThinSpace: 8201,
12272 TripleDot: 8411,
12273 UnionPlus: 8846,
12274 backprime: 8245,
12275 backsimeq: 8909,
12276 bigotimes: 10754,
12277 centerdot: 183,
12278 checkmark: 10003,
12279 complexes: 8450,
12280 dotsquare: 8865,
12281 downarrow: 8595,
12282 gtrapprox: 10886,
12283 gtreqless: 8923,
12284 heartsuit: 9829,
12285 leftarrow: 8592,
12286 lesseqgtr: 8922,
12287 nparallel: 8742,
12288 nshortmid: 8740,
12289 nsubseteq: 8840,
12290 nsupseteq: 8841,
12291 pitchfork: 8916,
12292 rationals: 8474,
12293 spadesuit: 9824,
12294 subseteqq: 10949,
12295 subsetneq: 8842,
12296 supseteqq: 10950,
12297 supsetneq: 8843,
12298 therefore: 8756,
12299 triangleq: 8796,
12300 varpropto: 8733,
12301 DDotrahd: 10513,
12302 DotEqual: 8784,
12303 Integral: 8747,
12304 LessLess: 10913,
12305 NotEqual: 8800,
12306 NotTilde: 8769,
12307 PartialD: 8706,
12308 Precedes: 8826,
12309 RightTee: 8866,
12310 Succeeds: 8827,
12311 SuchThat: 8715,
12312 Superset: 8835,
12313 Uarrocir: 10569,
12314 UnderBar: 818,
12315 andslope: 10840,
12316 angmsdaa: 10664,
12317 angmsdab: 10665,
12318 angmsdac: 10666,
12319 angmsdad: 10667,
12320 angmsdae: 10668,
12321 angmsdaf: 10669,
12322 angmsdag: 10670,
12323 angmsdah: 10671,
12324 angrtvbd: 10653,
12325 approxeq: 8778,
12326 awconint: 8755,
12327 backcong: 8780,
12328 barwedge: 8965,
12329 bbrktbrk: 9142,
12330 bigoplus: 10753,
12331 bigsqcup: 10758,
12332 biguplus: 10756,
12333 bigwedge: 8896,
12334 boxminus: 8863,
12335 boxtimes: 8864,
12336 capbrcup: 10825,
12337 circledR: 174,
12338 circledS: 9416,
12339 cirfnint: 10768,
12340 clubsuit: 9827,
12341 cupbrcap: 10824,
12342 curlyvee: 8910,
12343 cwconint: 8754,
12344 doteqdot: 8785,
12345 dotminus: 8760,
12346 drbkarow: 10512,
12347 dzigrarr: 10239,
12348 elinters: 9191,
12349 emptyset: 8709,
12350 eqvparsl: 10725,
12351 fpartint: 10765,
12352 geqslant: 10878,
12353 gesdotol: 10884,
12354 gnapprox: 10890,
12355 hksearow: 10533,
12356 hkswarow: 10534,
12357 imagline: 8464,
12358 imagpart: 8465,
12359 infintie: 10717,
12360 integers: 8484,
12361 intercal: 8890,
12362 intlarhk: 10775,
12363 laemptyv: 10676,
12364 ldrushar: 10571,
12365 leqslant: 10877,
12366 lesdotor: 10883,
12367 llcorner: 8990,
12368 lnapprox: 10889,
12369 lrcorner: 8991,
12370 lurdshar: 10570,
12371 mapstoup: 8613,
12372 multimap: 8888,
12373 naturals: 8469,
12374 otimesas: 10806,
12375 parallel: 8741,
12376 plusacir: 10787,
12377 pointint: 10773,
12378 precneqq: 10933,
12379 precnsim: 8936,
12380 profalar: 9006,
12381 profline: 8978,
12382 profsurf: 8979,
12383 raemptyv: 10675,
12384 realpart: 8476,
12385 rppolint: 10770,
12386 rtriltri: 10702,
12387 scpolint: 10771,
12388 setminus: 8726,
12389 shortmid: 8739,
12390 smeparsl: 10724,
12391 sqsubset: 8847,
12392 sqsupset: 8848,
12393 subseteq: 8838,
12394 succneqq: 10934,
12395 succnsim: 8937,
12396 supseteq: 8839,
12397 thetasym: 977,
12398 thicksim: 8764,
12399 timesbar: 10801,
12400 triangle: 9653,
12401 triminus: 10810,
12402 trpezium: 9186,
12403 ulcorner: 8988,
12404 urcorner: 8989,
12405 varkappa: 1008,
12406 varsigma: 962,
12407 vartheta: 977,
12408 Because: 8757,
12409 Cayleys: 8493,
12410 Cconint: 8752,
12411 Cedilla: 184,
12412 Diamond: 8900,
12413 DownTee: 8868,
12414 Element: 8712,
12415 Epsilon: 917,
12416 Implies: 8658,
12417 LeftTee: 8867,
12418 NewLine: 10,
12419 NoBreak: 8288,
12420 NotLess: 8814,
12421 Omicron: 927,
12422 OverBar: 175,
12423 Product: 8719,
12424 UpArrow: 8593,
12425 Uparrow: 8657,
12426 Upsilon: 933,
12427 alefsym: 8501,
12428 angrtvb: 8894,
12429 angzarr: 9084,
12430 asympeq: 8781,
12431 backsim: 8765,
12432 because: 8757,
12433 bemptyv: 10672,
12434 between: 8812,
12435 bigcirc: 9711,
12436 bigodot: 10752,
12437 bigstar: 9733,
12438 boxplus: 8862,
12439 ccupssm: 10832,
12440 cemptyv: 10674,
12441 cirscir: 10690,
12442 coloneq: 8788,
12443 congdot: 10861,
12444 cudarrl: 10552,
12445 cudarrr: 10549,
12446 cularrp: 10557,
12447 curarrm: 10556,
12448 dbkarow: 10511,
12449 ddagger: 8225,
12450 ddotseq: 10871,
12451 demptyv: 10673,
12452 diamond: 8900,
12453 digamma: 989,
12454 dotplus: 8724,
12455 dwangle: 10662,
12456 epsilon: 949,
12457 eqcolon: 8789,
12458 equivDD: 10872,
12459 gesdoto: 10882,
12460 gtquest: 10876,
12461 gtrless: 8823,
12462 harrcir: 10568,
12463 intprod: 10812,
12464 isindot: 8949,
12465 larrbfs: 10527,
12466 larrsim: 10611,
12467 lbrksld: 10639,
12468 lbrkslu: 10637,
12469 ldrdhar: 10599,
12470 lesdoto: 10881,
12471 lessdot: 8918,
12472 lessgtr: 8822,
12473 lesssim: 8818,
12474 lotimes: 10804,
12475 lozenge: 9674,
12476 ltquest: 10875,
12477 luruhar: 10598,
12478 maltese: 10016,
12479 minusdu: 10794,
12480 napprox: 8777,
12481 natural: 9838,
12482 nearrow: 8599,
12483 nexists: 8708,
12484 notinva: 8713,
12485 notinvb: 8951,
12486 notinvc: 8950,
12487 notniva: 8716,
12488 notnivb: 8958,
12489 notnivc: 8957,
12490 npolint: 10772,
12491 nsqsube: 8930,
12492 nsqsupe: 8931,
12493 nvinfin: 10718,
12494 nwarrow: 8598,
12495 olcross: 10683,
12496 omicron: 959,
12497 orderof: 8500,
12498 orslope: 10839,
12499 pertenk: 8241,
12500 planckh: 8462,
12501 pluscir: 10786,
12502 plussim: 10790,
12503 plustwo: 10791,
12504 precsim: 8830,
12505 quatint: 10774,
12506 questeq: 8799,
12507 rarrbfs: 10528,
12508 rarrsim: 10612,
12509 rbrksld: 10638,
12510 rbrkslu: 10640,
12511 rdldhar: 10601,
12512 realine: 8475,
12513 rotimes: 10805,
12514 ruluhar: 10600,
12515 searrow: 8600,
12516 simplus: 10788,
12517 simrarr: 10610,
12518 subedot: 10947,
12519 submult: 10945,
12520 subplus: 10943,
12521 subrarr: 10617,
12522 succsim: 8831,
12523 supdsub: 10968,
12524 supedot: 10948,
12525 suphsub: 10967,
12526 suplarr: 10619,
12527 supmult: 10946,
12528 supplus: 10944,
12529 swarrow: 8601,
12530 topfork: 10970,
12531 triplus: 10809,
12532 tritime: 10811,
12533 uparrow: 8593,
12534 upsilon: 965,
12535 uwangle: 10663,
12536 vzigzag: 10650,
12537 zigrarr: 8669,
12538 Aacute: 193,
12539 Abreve: 258,
12540 Agrave: 192,
12541 Assign: 8788,
12542 Atilde: 195,
12543 Barwed: 8966,
12544 Bumpeq: 8782,
12545 Cacute: 262,
12546 Ccaron: 268,
12547 Ccedil: 199,
12548 Colone: 10868,
12549 Conint: 8751,
12550 CupCap: 8781,
12551 Dagger: 8225,
12552 Dcaron: 270,
12553 DotDot: 8412,
12554 Dstrok: 272,
12555 Eacute: 201,
12556 Ecaron: 282,
12557 Egrave: 200,
12558 Exists: 8707,
12559 ForAll: 8704,
12560 Gammad: 988,
12561 Gbreve: 286,
12562 Gcedil: 290,
12563 HARDcy: 1066,
12564 Hstrok: 294,
12565 Iacute: 205,
12566 Igrave: 204,
12567 Itilde: 296,
12568 Jsercy: 1032,
12569 Kcedil: 310,
12570 Lacute: 313,
12571 Lambda: 923,
12572 Lcaron: 317,
12573 Lcedil: 315,
12574 Lmidot: 319,
12575 Lstrok: 321,
12576 Nacute: 323,
12577 Ncaron: 327,
12578 Ncedil: 325,
12579 Ntilde: 209,
12580 Oacute: 211,
12581 Odblac: 336,
12582 Ograve: 210,
12583 Oslash: 216,
12584 Otilde: 213,
12585 Otimes: 10807,
12586 Racute: 340,
12587 Rarrtl: 10518,
12588 Rcaron: 344,
12589 Rcedil: 342,
12590 SHCHcy: 1065,
12591 SOFTcy: 1068,
12592 Sacute: 346,
12593 Scaron: 352,
12594 Scedil: 350,
12595 Square: 9633,
12596 Subset: 8912,
12597 Supset: 8913,
12598 Tcaron: 356,
12599 Tcedil: 354,
12600 Tstrok: 358,
12601 Uacute: 218,
12602 Ubreve: 364,
12603 Udblac: 368,
12604 Ugrave: 217,
12605 Utilde: 360,
12606 Vdashl: 10982,
12607 Verbar: 8214,
12608 Vvdash: 8874,
12609 Yacute: 221,
12610 Zacute: 377,
12611 Zcaron: 381,
12612 aacute: 225,
12613 abreve: 259,
12614 agrave: 224,
12615 andand: 10837,
12616 angmsd: 8737,
12617 angsph: 8738,
12618 apacir: 10863,
12619 approx: 8776,
12620 atilde: 227,
12621 barvee: 8893,
12622 barwed: 8965,
12623 becaus: 8757,
12624 bernou: 8492,
12625 bigcap: 8898,
12626 bigcup: 8899,
12627 bigvee: 8897,
12628 bkarow: 10509,
12629 bottom: 8869,
12630 bowtie: 8904,
12631 boxbox: 10697,
12632 bprime: 8245,
12633 brvbar: 166,
12634 bullet: 8226,
12635 bumpeq: 8783,
12636 cacute: 263,
12637 capand: 10820,
12638 capcap: 10827,
12639 capcup: 10823,
12640 capdot: 10816,
12641 ccaron: 269,
12642 ccedil: 231,
12643 circeq: 8791,
12644 cirmid: 10991,
12645 colone: 8788,
12646 commat: 64,
12647 compfn: 8728,
12648 conint: 8750,
12649 coprod: 8720,
12650 copysr: 8471,
12651 cularr: 8630,
12652 cupcap: 10822,
12653 cupcup: 10826,
12654 cupdot: 8845,
12655 curarr: 8631,
12656 curren: 164,
12657 cylcty: 9005,
12658 dagger: 8224,
12659 daleth: 8504,
12660 dcaron: 271,
12661 dfisht: 10623,
12662 divide: 247,
12663 divonx: 8903,
12664 dlcorn: 8990,
12665 dlcrop: 8973,
12666 dollar: 36,
12667 drcorn: 8991,
12668 drcrop: 8972,
12669 dstrok: 273,
12670 eacute: 233,
12671 easter: 10862,
12672 ecaron: 283,
12673 ecolon: 8789,
12674 egrave: 232,
12675 egsdot: 10904,
12676 elsdot: 10903,
12677 emptyv: 8709,
12678 emsp13: 8196,
12679 emsp14: 8197,
12680 eparsl: 10723,
12681 eqcirc: 8790,
12682 equals: 61,
12683 equest: 8799,
12684 female: 9792,
12685 ffilig: 64259,
12686 ffllig: 64260,
12687 forall: 8704,
12688 frac12: 189,
12689 frac13: 8531,
12690 frac14: 188,
12691 frac15: 8533,
12692 frac16: 8537,
12693 frac18: 8539,
12694 frac23: 8532,
12695 frac25: 8534,
12696 frac34: 190,
12697 frac35: 8535,
12698 frac38: 8540,
12699 frac45: 8536,
12700 frac56: 8538,
12701 frac58: 8541,
12702 frac78: 8542,
12703 gacute: 501,
12704 gammad: 989,
12705 gbreve: 287,
12706 gesdot: 10880,
12707 gesles: 10900,
12708 gtlPar: 10645,
12709 gtrarr: 10616,
12710 gtrdot: 8919,
12711 gtrsim: 8819,
12712 hairsp: 8202,
12713 hamilt: 8459,
12714 hardcy: 1098,
12715 hearts: 9829,
12716 hellip: 8230,
12717 hercon: 8889,
12718 homtht: 8763,
12719 horbar: 8213,
12720 hslash: 8463,
12721 hstrok: 295,
12722 hybull: 8259,
12723 hyphen: 8208,
12724 iacute: 237,
12725 igrave: 236,
12726 iiiint: 10764,
12727 iinfin: 10716,
12728 incare: 8453,
12729 inodot: 305,
12730 intcal: 8890,
12731 iquest: 191,
12732 isinsv: 8947,
12733 itilde: 297,
12734 jsercy: 1112,
12735 kappav: 1008,
12736 kcedil: 311,
12737 kgreen: 312,
12738 lAtail: 10523,
12739 lacute: 314,
12740 lagran: 8466,
12741 lambda: 955,
12742 langle: 10216,
12743 larrfs: 10525,
12744 larrhk: 8617,
12745 larrlp: 8619,
12746 larrpl: 10553,
12747 larrtl: 8610,
12748 latail: 10521,
12749 lbrace: 123,
12750 lbrack: 91,
12751 lcaron: 318,
12752 lcedil: 316,
12753 ldquor: 8222,
12754 lesdot: 10879,
12755 lesges: 10899,
12756 lfisht: 10620,
12757 lfloor: 8970,
12758 lharul: 10602,
12759 llhard: 10603,
12760 lmidot: 320,
12761 lmoust: 9136,
12762 loplus: 10797,
12763 lowast: 8727,
12764 lowbar: 95,
12765 lparlt: 10643,
12766 lrhard: 10605,
12767 lsaquo: 8249,
12768 lsquor: 8218,
12769 lstrok: 322,
12770 lthree: 8907,
12771 ltimes: 8905,
12772 ltlarr: 10614,
12773 ltrPar: 10646,
12774 mapsto: 8614,
12775 marker: 9646,
12776 mcomma: 10793,
12777 midast: 42,
12778 midcir: 10992,
12779 middot: 183,
12780 minusb: 8863,
12781 minusd: 8760,
12782 mnplus: 8723,
12783 models: 8871,
12784 mstpos: 8766,
12785 nVDash: 8879,
12786 nVdash: 8878,
12787 nacute: 324,
12788 ncaron: 328,
12789 ncedil: 326,
12790 nearhk: 10532,
12791 nequiv: 8802,
12792 nesear: 10536,
12793 nexist: 8708,
12794 nltrie: 8940,
12795 nprcue: 8928,
12796 nrtrie: 8941,
12797 nsccue: 8929,
12798 nsimeq: 8772,
12799 ntilde: 241,
12800 numero: 8470,
12801 nvDash: 8877,
12802 nvHarr: 10500,
12803 nvdash: 8876,
12804 nvlArr: 10498,
12805 nvrArr: 10499,
12806 nwarhk: 10531,
12807 nwnear: 10535,
12808 oacute: 243,
12809 odblac: 337,
12810 odsold: 10684,
12811 ograve: 242,
12812 ominus: 8854,
12813 origof: 8886,
12814 oslash: 248,
12815 otilde: 245,
12816 otimes: 8855,
12817 parsim: 10995,
12818 percnt: 37,
12819 period: 46,
12820 permil: 8240,
12821 phmmat: 8499,
12822 planck: 8463,
12823 plankv: 8463,
12824 plusdo: 8724,
12825 plusdu: 10789,
12826 plusmn: 177,
12827 preceq: 10927,
12828 primes: 8473,
12829 prnsim: 8936,
12830 propto: 8733,
12831 prurel: 8880,
12832 puncsp: 8200,
12833 qprime: 8279,
12834 rAtail: 10524,
12835 racute: 341,
12836 rangle: 10217,
12837 rarrap: 10613,
12838 rarrfs: 10526,
12839 rarrhk: 8618,
12840 rarrlp: 8620,
12841 rarrpl: 10565,
12842 rarrtl: 8611,
12843 ratail: 10522,
12844 rbrace: 125,
12845 rbrack: 93,
12846 rcaron: 345,
12847 rcedil: 343,
12848 rdquor: 8221,
12849 rfisht: 10621,
12850 rfloor: 8971,
12851 rharul: 10604,
12852 rmoust: 9137,
12853 roplus: 10798,
12854 rpargt: 10644,
12855 rsaquo: 8250,
12856 rsquor: 8217,
12857 rthree: 8908,
12858 rtimes: 8906,
12859 sacute: 347,
12860 scaron: 353,
12861 scedil: 351,
12862 scnsim: 8937,
12863 searhk: 10533,
12864 seswar: 10537,
12865 sfrown: 8994,
12866 shchcy: 1097,
12867 sigmaf: 962,
12868 sigmav: 962,
12869 simdot: 10858,
12870 smashp: 10803,
12871 softcy: 1100,
12872 solbar: 9023,
12873 spades: 9824,
12874 sqsube: 8849,
12875 sqsupe: 8850,
12876 square: 9633,
12877 squarf: 9642,
12878 ssetmn: 8726,
12879 ssmile: 8995,
12880 sstarf: 8902,
12881 subdot: 10941,
12882 subset: 8834,
12883 subsim: 10951,
12884 subsub: 10965,
12885 subsup: 10963,
12886 succeq: 10928,
12887 supdot: 10942,
12888 supset: 8835,
12889 supsim: 10952,
12890 supsub: 10964,
12891 supsup: 10966,
12892 swarhk: 10534,
12893 swnwar: 10538,
12894 target: 8982,
12895 tcaron: 357,
12896 tcedil: 355,
12897 telrec: 8981,
12898 there4: 8756,
12899 thetav: 977,
12900 thinsp: 8201,
12901 thksim: 8764,
12902 timesb: 8864,
12903 timesd: 10800,
12904 topbot: 9014,
12905 topcir: 10993,
12906 tprime: 8244,
12907 tridot: 9708,
12908 tstrok: 359,
12909 uacute: 250,
12910 ubreve: 365,
12911 udblac: 369,
12912 ufisht: 10622,
12913 ugrave: 249,
12914 ulcorn: 8988,
12915 ulcrop: 8975,
12916 urcorn: 8989,
12917 urcrop: 8974,
12918 utilde: 361,
12919 vangrt: 10652,
12920 varphi: 966,
12921 varrho: 1009,
12922 veebar: 8891,
12923 vellip: 8942,
12924 verbar: 124,
12925 wedbar: 10847,
12926 wedgeq: 8793,
12927 weierp: 8472,
12928 wreath: 8768,
12929 xoplus: 10753,
12930 xotime: 10754,
12931 xsqcup: 10758,
12932 xuplus: 10756,
12933 xwedge: 8896,
12934 yacute: 253,
12935 zacute: 378,
12936 zcaron: 382,
12937 zeetrf: 8488,
12938 AElig: 198,
12939 Acirc: 194,
12940 Alpha: 913,
12941 Amacr: 256,
12942 Aogon: 260,
12943 Aring: 197,
12944 Breve: 728,
12945 Ccirc: 264,
12946 Colon: 8759,
12947 Cross: 10799,
12948 Dashv: 10980,
12949 Delta: 916,
12950 Ecirc: 202,
12951 Emacr: 274,
12952 Eogon: 280,
12953 Equal: 10869,
12954 Gamma: 915,
12955 Gcirc: 284,
12956 Hacek: 711,
12957 Hcirc: 292,
12958 IJlig: 306,
12959 Icirc: 206,
12960 Imacr: 298,
12961 Iogon: 302,
12962 Iukcy: 1030,
12963 Jcirc: 308,
12964 Jukcy: 1028,
12965 Kappa: 922,
12966 OElig: 338,
12967 Ocirc: 212,
12968 Omacr: 332,
12969 Omega: 937,
12970 Prime: 8243,
12971 RBarr: 10512,
12972 Scirc: 348,
12973 Sigma: 931,
12974 THORN: 222,
12975 TRADE: 8482,
12976 TSHcy: 1035,
12977 Theta: 920,
12978 Tilde: 8764,
12979 Ubrcy: 1038,
12980 Ucirc: 219,
12981 Umacr: 362,
12982 Union: 8899,
12983 Uogon: 370,
12984 UpTee: 8869,
12985 Uring: 366,
12986 VDash: 8875,
12987 Vdash: 8873,
12988 Wcirc: 372,
12989 Wedge: 8896,
12990 Ycirc: 374,
12991 acirc: 226,
12992 acute: 180,
12993 aelig: 230,
12994 aleph: 8501,
12995 alpha: 945,
12996 amacr: 257,
12997 amalg: 10815,
12998 angle: 8736,
12999 angrt: 8735,
13000 angst: 8491,
13001 aogon: 261,
13002 aring: 229,
13003 asymp: 8776,
13004 awint: 10769,
13005 bcong: 8780,
13006 bdquo: 8222,
13007 bepsi: 1014,
13008 blank: 9251,
13009 blk12: 9618,
13010 blk14: 9617,
13011 blk34: 9619,
13012 block: 9608,
13013 boxDL: 9559,
13014 boxDR: 9556,
13015 boxDl: 9558,
13016 boxDr: 9555,
13017 boxHD: 9574,
13018 boxHU: 9577,
13019 boxHd: 9572,
13020 boxHu: 9575,
13021 boxUL: 9565,
13022 boxUR: 9562,
13023 boxUl: 9564,
13024 boxUr: 9561,
13025 boxVH: 9580,
13026 boxVL: 9571,
13027 boxVR: 9568,
13028 boxVh: 9579,
13029 boxVl: 9570,
13030 boxVr: 9567,
13031 boxdL: 9557,
13032 boxdR: 9554,
13033 boxdl: 9488,
13034 boxdr: 9484,
13035 boxhD: 9573,
13036 boxhU: 9576,
13037 boxhd: 9516,
13038 boxhu: 9524,
13039 boxuL: 9563,
13040 boxuR: 9560,
13041 boxul: 9496,
13042 boxur: 9492,
13043 boxvH: 9578,
13044 boxvL: 9569,
13045 boxvR: 9566,
13046 boxvh: 9532,
13047 boxvl: 9508,
13048 boxvr: 9500,
13049 breve: 728,
13050 bsemi: 8271,
13051 bsime: 8909,
13052 bsolb: 10693,
13053 bumpE: 10926,
13054 bumpe: 8783,
13055 caret: 8257,
13056 caron: 711,
13057 ccaps: 10829,
13058 ccirc: 265,
13059 ccups: 10828,
13060 cedil: 184,
13061 check: 10003,
13062 clubs: 9827,
13063 colon: 58,
13064 comma: 44,
13065 crarr: 8629,
13066 cross: 10007,
13067 csube: 10961,
13068 csupe: 10962,
13069 ctdot: 8943,
13070 cuepr: 8926,
13071 cuesc: 8927,
13072 cupor: 10821,
13073 cuvee: 8910,
13074 cuwed: 8911,
13075 cwint: 8753,
13076 dashv: 8867,
13077 dblac: 733,
13078 ddarr: 8650,
13079 delta: 948,
13080 dharl: 8643,
13081 dharr: 8642,
13082 diams: 9830,
13083 disin: 8946,
13084 doteq: 8784,
13085 dtdot: 8945,
13086 dtrif: 9662,
13087 duarr: 8693,
13088 duhar: 10607,
13089 eDDot: 10871,
13090 ecirc: 234,
13091 efDot: 8786,
13092 emacr: 275,
13093 empty: 8709,
13094 eogon: 281,
13095 eplus: 10865,
13096 epsiv: 949,
13097 eqsim: 8770,
13098 equiv: 8801,
13099 erDot: 8787,
13100 erarr: 10609,
13101 esdot: 8784,
13102 exist: 8707,
13103 fflig: 64256,
13104 filig: 64257,
13105 fllig: 64258,
13106 fltns: 9649,
13107 forkv: 10969,
13108 frasl: 8260,
13109 frown: 8994,
13110 gamma: 947,
13111 gcirc: 285,
13112 gescc: 10921,
13113 gimel: 8503,
13114 gneqq: 8809,
13115 gnsim: 8935,
13116 grave: 96,
13117 gsime: 10894,
13118 gsiml: 10896,
13119 gtcir: 10874,
13120 gtdot: 8919,
13121 harrw: 8621,
13122 hcirc: 293,
13123 hoarr: 8703,
13124 icirc: 238,
13125 iexcl: 161,
13126 iiint: 8749,
13127 iiota: 8489,
13128 ijlig: 307,
13129 imacr: 299,
13130 image: 8465,
13131 imath: 305,
13132 imped: 437,
13133 infin: 8734,
13134 iogon: 303,
13135 iprod: 10812,
13136 isinE: 8953,
13137 isins: 8948,
13138 isinv: 8712,
13139 iukcy: 1110,
13140 jcirc: 309,
13141 jmath: 567,
13142 jukcy: 1108,
13143 kappa: 954,
13144 lAarr: 8666,
13145 lBarr: 10510,
13146 langd: 10641,
13147 laquo: 171,
13148 larrb: 8676,
13149 lbarr: 10508,
13150 lbbrk: 10098,
13151 lbrke: 10635,
13152 lceil: 8968,
13153 ldquo: 8220,
13154 lescc: 10920,
13155 lhard: 8637,
13156 lharu: 8636,
13157 lhblk: 9604,
13158 llarr: 8647,
13159 lltri: 9722,
13160 lneqq: 8808,
13161 lnsim: 8934,
13162 loang: 10220,
13163 loarr: 8701,
13164 lobrk: 10214,
13165 lopar: 10629,
13166 lrarr: 8646,
13167 lrhar: 8651,
13168 lrtri: 8895,
13169 lsime: 10893,
13170 lsimg: 10895,
13171 lsquo: 8216,
13172 ltcir: 10873,
13173 ltdot: 8918,
13174 ltrie: 8884,
13175 ltrif: 9666,
13176 mDDot: 8762,
13177 mdash: 8212,
13178 micro: 181,
13179 minus: 8722,
13180 mumap: 8888,
13181 nabla: 8711,
13182 napos: 329,
13183 natur: 9838,
13184 ncong: 8775,
13185 ndash: 8211,
13186 neArr: 8663,
13187 nearr: 8599,
13188 ngsim: 8821,
13189 nhArr: 8654,
13190 nharr: 8622,
13191 nhpar: 10994,
13192 nlArr: 8653,
13193 nlarr: 8602,
13194 nless: 8814,
13195 nlsim: 8820,
13196 nltri: 8938,
13197 notin: 8713,
13198 notni: 8716,
13199 nprec: 8832,
13200 nrArr: 8655,
13201 nrarr: 8603,
13202 nrtri: 8939,
13203 nsime: 8772,
13204 nsmid: 8740,
13205 nspar: 8742,
13206 nsube: 8840,
13207 nsucc: 8833,
13208 nsupe: 8841,
13209 numsp: 8199,
13210 nwArr: 8662,
13211 nwarr: 8598,
13212 ocirc: 244,
13213 odash: 8861,
13214 oelig: 339,
13215 ofcir: 10687,
13216 ohbar: 10677,
13217 olarr: 8634,
13218 olcir: 10686,
13219 oline: 8254,
13220 omacr: 333,
13221 omega: 969,
13222 operp: 10681,
13223 oplus: 8853,
13224 orarr: 8635,
13225 order: 8500,
13226 ovbar: 9021,
13227 parsl: 11005,
13228 phone: 9742,
13229 plusb: 8862,
13230 pluse: 10866,
13231 pound: 163,
13232 prcue: 8828,
13233 prime: 8242,
13234 prnap: 10937,
13235 prsim: 8830,
13236 quest: 63,
13237 rAarr: 8667,
13238 rBarr: 10511,
13239 radic: 8730,
13240 rangd: 10642,
13241 range: 10661,
13242 raquo: 187,
13243 rarrb: 8677,
13244 rarrc: 10547,
13245 rarrw: 8605,
13246 ratio: 8758,
13247 rbarr: 10509,
13248 rbbrk: 10099,
13249 rbrke: 10636,
13250 rceil: 8969,
13251 rdquo: 8221,
13252 reals: 8477,
13253 rhard: 8641,
13254 rharu: 8640,
13255 rlarr: 8644,
13256 rlhar: 8652,
13257 rnmid: 10990,
13258 roang: 10221,
13259 roarr: 8702,
13260 robrk: 10215,
13261 ropar: 10630,
13262 rrarr: 8649,
13263 rsquo: 8217,
13264 rtrie: 8885,
13265 rtrif: 9656,
13266 sbquo: 8218,
13267 sccue: 8829,
13268 scirc: 349,
13269 scnap: 10938,
13270 scsim: 8831,
13271 sdotb: 8865,
13272 sdote: 10854,
13273 seArr: 8664,
13274 searr: 8600,
13275 setmn: 8726,
13276 sharp: 9839,
13277 sigma: 963,
13278 simeq: 8771,
13279 simgE: 10912,
13280 simlE: 10911,
13281 simne: 8774,
13282 slarr: 8592,
13283 smile: 8995,
13284 sqcap: 8851,
13285 sqcup: 8852,
13286 sqsub: 8847,
13287 sqsup: 8848,
13288 srarr: 8594,
13289 starf: 9733,
13290 strns: 175,
13291 subnE: 10955,
13292 subne: 8842,
13293 supnE: 10956,
13294 supne: 8843,
13295 swArr: 8665,
13296 swarr: 8601,
13297 szlig: 223,
13298 theta: 952,
13299 thkap: 8776,
13300 thorn: 254,
13301 tilde: 732,
13302 times: 215,
13303 trade: 8482,
13304 trisb: 10701,
13305 tshcy: 1115,
13306 twixt: 8812,
13307 ubrcy: 1118,
13308 ucirc: 251,
13309 udarr: 8645,
13310 udhar: 10606,
13311 uharl: 8639,
13312 uharr: 8638,
13313 uhblk: 9600,
13314 ultri: 9720,
13315 umacr: 363,
13316 uogon: 371,
13317 uplus: 8846,
13318 upsih: 978,
13319 uring: 367,
13320 urtri: 9721,
13321 utdot: 8944,
13322 utrif: 9652,
13323 uuarr: 8648,
13324 vBarv: 10985,
13325 vDash: 8872,
13326 varpi: 982,
13327 vdash: 8866,
13328 veeeq: 8794,
13329 vltri: 8882,
13330 vprop: 8733,
13331 vrtri: 8883,
13332 wcirc: 373,
13333 wedge: 8743,
13334 xcirc: 9711,
13335 xdtri: 9661,
13336 xhArr: 10234,
13337 xharr: 10231,
13338 xlArr: 10232,
13339 xlarr: 10229,
13340 xodot: 10752,
13341 xrArr: 10233,
13342 xrarr: 10230,
13343 xutri: 9651,
13344 ycirc: 375,
13345 Aopf: 120120,
13346 Ascr: 119964,
13347 Auml: 196,
13348 Barv: 10983,
13349 Beta: 914,
13350 Bopf: 120121,
13351 Bscr: 8492,
13352 CHcy: 1063,
13353 COPY: 169,
13354 Cdot: 266,
13355 Copf: 8450,
13356 Cscr: 119966,
13357 DJcy: 1026,
13358 DScy: 1029,
13359 DZcy: 1039,
13360 Darr: 8609,
13361 Dopf: 120123,
13362 Dscr: 119967,
13363 Edot: 278,
13364 Eopf: 120124,
13365 Escr: 8496,
13366 Esim: 10867,
13367 Euml: 203,
13368 Fopf: 120125,
13369 Fscr: 8497,
13370 GJcy: 1027,
13371 Gdot: 288,
13372 Gopf: 120126,
13373 Gscr: 119970,
13374 Hopf: 8461,
13375 Hscr: 8459,
13376 IEcy: 1045,
13377 IOcy: 1025,
13378 Idot: 304,
13379 Iopf: 120128,
13380 Iota: 921,
13381 Iscr: 8464,
13382 Iuml: 207,
13383 Jopf: 120129,
13384 Jscr: 119973,
13385 KHcy: 1061,
13386 KJcy: 1036,
13387 Kopf: 120130,
13388 Kscr: 119974,
13389 LJcy: 1033,
13390 Lang: 10218,
13391 Larr: 8606,
13392 Lopf: 120131,
13393 Lscr: 8466,
13394 Mopf: 120132,
13395 Mscr: 8499,
13396 NJcy: 1034,
13397 Nopf: 8469,
13398 Nscr: 119977,
13399 Oopf: 120134,
13400 Oscr: 119978,
13401 Ouml: 214,
13402 Popf: 8473,
13403 Pscr: 119979,
13404 QUOT: 34,
13405 Qopf: 8474,
13406 Qscr: 119980,
13407 Rang: 10219,
13408 Rarr: 8608,
13409 Ropf: 8477,
13410 Rscr: 8475,
13411 SHcy: 1064,
13412 Sopf: 120138,
13413 Sqrt: 8730,
13414 Sscr: 119982,
13415 Star: 8902,
13416 TScy: 1062,
13417 Topf: 120139,
13418 Tscr: 119983,
13419 Uarr: 8607,
13420 Uopf: 120140,
13421 Upsi: 978,
13422 Uscr: 119984,
13423 Uuml: 220,
13424 Vbar: 10987,
13425 Vert: 8214,
13426 Vopf: 120141,
13427 Vscr: 119985,
13428 Wopf: 120142,
13429 Wscr: 119986,
13430 Xopf: 120143,
13431 Xscr: 119987,
13432 YAcy: 1071,
13433 YIcy: 1031,
13434 YUcy: 1070,
13435 Yopf: 120144,
13436 Yscr: 119988,
13437 Yuml: 376,
13438 ZHcy: 1046,
13439 Zdot: 379,
13440 Zeta: 918,
13441 Zopf: 8484,
13442 Zscr: 119989,
13443 andd: 10844,
13444 andv: 10842,
13445 ange: 10660,
13446 aopf: 120146,
13447 apid: 8779,
13448 apos: 39,
13449 ascr: 119990,
13450 auml: 228,
13451 bNot: 10989,
13452 bbrk: 9141,
13453 beta: 946,
13454 beth: 8502,
13455 bnot: 8976,
13456 bopf: 120147,
13457 boxH: 9552,
13458 boxV: 9553,
13459 boxh: 9472,
13460 boxv: 9474,
13461 bscr: 119991,
13462 bsim: 8765,
13463 bsol: 92,
13464 bull: 8226,
13465 bump: 8782,
13466 cdot: 267,
13467 cent: 162,
13468 chcy: 1095,
13469 cirE: 10691,
13470 circ: 710,
13471 cire: 8791,
13472 comp: 8705,
13473 cong: 8773,
13474 copf: 120148,
13475 copy: 169,
13476 cscr: 119992,
13477 csub: 10959,
13478 csup: 10960,
13479 dArr: 8659,
13480 dHar: 10597,
13481 darr: 8595,
13482 dash: 8208,
13483 diam: 8900,
13484 djcy: 1106,
13485 dopf: 120149,
13486 dscr: 119993,
13487 dscy: 1109,
13488 dsol: 10742,
13489 dtri: 9663,
13490 dzcy: 1119,
13491 eDot: 8785,
13492 ecir: 8790,
13493 edot: 279,
13494 emsp: 8195,
13495 ensp: 8194,
13496 eopf: 120150,
13497 epar: 8917,
13498 epsi: 1013,
13499 escr: 8495,
13500 esim: 8770,
13501 euml: 235,
13502 euro: 8364,
13503 excl: 33,
13504 flat: 9837,
13505 fnof: 402,
13506 fopf: 120151,
13507 fork: 8916,
13508 fscr: 119995,
13509 gdot: 289,
13510 geqq: 8807,
13511 gjcy: 1107,
13512 gnap: 10890,
13513 gneq: 10888,
13514 gopf: 120152,
13515 gscr: 8458,
13516 gsim: 8819,
13517 gtcc: 10919,
13518 hArr: 8660,
13519 half: 189,
13520 harr: 8596,
13521 hbar: 8463,
13522 hopf: 120153,
13523 hscr: 119997,
13524 iecy: 1077,
13525 imof: 8887,
13526 iocy: 1105,
13527 iopf: 120154,
13528 iota: 953,
13529 iscr: 119998,
13530 isin: 8712,
13531 iuml: 239,
13532 jopf: 120155,
13533 jscr: 119999,
13534 khcy: 1093,
13535 kjcy: 1116,
13536 kopf: 120156,
13537 kscr: 120000,
13538 lArr: 8656,
13539 lHar: 10594,
13540 lang: 10216,
13541 larr: 8592,
13542 late: 10925,
13543 lcub: 123,
13544 ldca: 10550,
13545 ldsh: 8626,
13546 leqq: 8806,
13547 ljcy: 1113,
13548 lnap: 10889,
13549 lneq: 10887,
13550 lopf: 120157,
13551 lozf: 10731,
13552 lpar: 40,
13553 lscr: 120001,
13554 lsim: 8818,
13555 lsqb: 91,
13556 ltcc: 10918,
13557 ltri: 9667,
13558 macr: 175,
13559 male: 9794,
13560 malt: 10016,
13561 mlcp: 10971,
13562 mldr: 8230,
13563 mopf: 120158,
13564 mscr: 120002,
13565 nbsp: 160,
13566 ncap: 10819,
13567 ncup: 10818,
13568 ngeq: 8817,
13569 ngtr: 8815,
13570 nisd: 8954,
13571 njcy: 1114,
13572 nldr: 8229,
13573 nleq: 8816,
13574 nmid: 8740,
13575 nopf: 120159,
13576 npar: 8742,
13577 nscr: 120003,
13578 nsim: 8769,
13579 nsub: 8836,
13580 nsup: 8837,
13581 ntgl: 8825,
13582 ntlg: 8824,
13583 oast: 8859,
13584 ocir: 8858,
13585 odiv: 10808,
13586 odot: 8857,
13587 ogon: 731,
13588 oint: 8750,
13589 omid: 10678,
13590 oopf: 120160,
13591 opar: 10679,
13592 ordf: 170,
13593 ordm: 186,
13594 oror: 10838,
13595 oscr: 8500,
13596 osol: 8856,
13597 ouml: 246,
13598 para: 182,
13599 part: 8706,
13600 perp: 8869,
13601 phiv: 966,
13602 plus: 43,
13603 popf: 120161,
13604 prap: 10935,
13605 prec: 8826,
13606 prnE: 10933,
13607 prod: 8719,
13608 prop: 8733,
13609 pscr: 120005,
13610 qint: 10764,
13611 qopf: 120162,
13612 qscr: 120006,
13613 quot: 34,
13614 rArr: 8658,
13615 rHar: 10596,
13616 race: 10714,
13617 rang: 10217,
13618 rarr: 8594,
13619 rcub: 125,
13620 rdca: 10551,
13621 rdsh: 8627,
13622 real: 8476,
13623 rect: 9645,
13624 rhov: 1009,
13625 ring: 730,
13626 ropf: 120163,
13627 rpar: 41,
13628 rscr: 120007,
13629 rsqb: 93,
13630 rtri: 9657,
13631 scap: 10936,
13632 scnE: 10934,
13633 sdot: 8901,
13634 sect: 167,
13635 semi: 59,
13636 sext: 10038,
13637 shcy: 1096,
13638 sime: 8771,
13639 simg: 10910,
13640 siml: 10909,
13641 smid: 8739,
13642 smte: 10924,
13643 solb: 10692,
13644 sopf: 120164,
13645 spar: 8741,
13646 squf: 9642,
13647 sscr: 120008,
13648 star: 9734,
13649 subE: 10949,
13650 sube: 8838,
13651 succ: 8827,
13652 sung: 9834,
13653 sup1: 185,
13654 sup2: 178,
13655 sup3: 179,
13656 supE: 10950,
13657 supe: 8839,
13658 tbrk: 9140,
13659 tdot: 8411,
13660 tint: 8749,
13661 toea: 10536,
13662 topf: 120165,
13663 tosa: 10537,
13664 trie: 8796,
13665 tscr: 120009,
13666 tscy: 1094,
13667 uArr: 8657,
13668 uHar: 10595,
13669 uarr: 8593,
13670 uopf: 120166,
13671 upsi: 965,
13672 uscr: 120010,
13673 utri: 9653,
13674 uuml: 252,
13675 vArr: 8661,
13676 vBar: 10984,
13677 varr: 8597,
13678 vert: 124,
13679 vopf: 120167,
13680 vscr: 120011,
13681 wopf: 120168,
13682 wscr: 120012,
13683 xcap: 8898,
13684 xcup: 8899,
13685 xmap: 10236,
13686 xnis: 8955,
13687 xopf: 120169,
13688 xscr: 120013,
13689 xvee: 8897,
13690 yacy: 1103,
13691 yicy: 1111,
13692 yopf: 120170,
13693 yscr: 120014,
13694 yucy: 1102,
13695 yuml: 255,
13696 zdot: 380,
13697 zeta: 950,
13698 zhcy: 1078,
13699 zopf: 120171,
13700 zscr: 120015,
13701 zwnj: 8204,
13702 AMP: 38,
13703 Acy: 1040,
13704 Afr: 120068,
13705 And: 10835,
13706 Bcy: 1041,
13707 Bfr: 120069,
13708 Cap: 8914,
13709 Cfr: 8493,
13710 Chi: 935,
13711 Cup: 8915,
13712 Dcy: 1044,
13713 Del: 8711,
13714 Dfr: 120071,
13715 Dot: 168,
13716 ENG: 330,
13717 ETH: 208,
13718 Ecy: 1069,
13719 Efr: 120072,
13720 Eta: 919,
13721 Fcy: 1060,
13722 Ffr: 120073,
13723 Gcy: 1043,
13724 Gfr: 120074,
13725 Hat: 94,
13726 Hfr: 8460,
13727 Icy: 1048,
13728 Ifr: 8465,
13729 Int: 8748,
13730 Jcy: 1049,
13731 Jfr: 120077,
13732 Kcy: 1050,
13733 Kfr: 120078,
13734 Lcy: 1051,
13735 Lfr: 120079,
13736 Lsh: 8624,
13737 Map: 10501,
13738 Mcy: 1052,
13739 Mfr: 120080,
13740 Ncy: 1053,
13741 Nfr: 120081,
13742 Not: 10988,
13743 Ocy: 1054,
13744 Ofr: 120082,
13745 Pcy: 1055,
13746 Pfr: 120083,
13747 Phi: 934,
13748 Psi: 936,
13749 Qfr: 120084,
13750 REG: 174,
13751 Rcy: 1056,
13752 Rfr: 8476,
13753 Rho: 929,
13754 Rsh: 8625,
13755 Scy: 1057,
13756 Sfr: 120086,
13757 Sub: 8912,
13758 Sum: 8721,
13759 Sup: 8913,
13760 Tab: 9,
13761 Tau: 932,
13762 Tcy: 1058,
13763 Tfr: 120087,
13764 Ucy: 1059,
13765 Ufr: 120088,
13766 Vcy: 1042,
13767 Vee: 8897,
13768 Vfr: 120089,
13769 Wfr: 120090,
13770 Xfr: 120091,
13771 Ycy: 1067,
13772 Yfr: 120092,
13773 Zcy: 1047,
13774 Zfr: 8488,
13775 acd: 8767,
13776 acy: 1072,
13777 afr: 120094,
13778 amp: 38,
13779 and: 8743,
13780 ang: 8736,
13781 apE: 10864,
13782 ape: 8778,
13783 ast: 42,
13784 bcy: 1073,
13785 bfr: 120095,
13786 bot: 8869,
13787 cap: 8745,
13788 cfr: 120096,
13789 chi: 967,
13790 cir: 9675,
13791 cup: 8746,
13792 dcy: 1076,
13793 deg: 176,
13794 dfr: 120097,
13795 die: 168,
13796 div: 247,
13797 dot: 729,
13798 ecy: 1101,
13799 efr: 120098,
13800 egs: 10902,
13801 ell: 8467,
13802 els: 10901,
13803 eng: 331,
13804 eta: 951,
13805 eth: 240,
13806 fcy: 1092,
13807 ffr: 120099,
13808 gEl: 10892,
13809 gap: 10886,
13810 gcy: 1075,
13811 gel: 8923,
13812 geq: 8805,
13813 ges: 10878,
13814 gfr: 120100,
13815 ggg: 8921,
13816 glE: 10898,
13817 gla: 10917,
13818 glj: 10916,
13819 gnE: 8809,
13820 gne: 10888,
13821 hfr: 120101,
13822 icy: 1080,
13823 iff: 8660,
13824 ifr: 120102,
13825 int: 8747,
13826 jcy: 1081,
13827 jfr: 120103,
13828 kcy: 1082,
13829 kfr: 120104,
13830 lEg: 10891,
13831 lap: 10885,
13832 lat: 10923,
13833 lcy: 1083,
13834 leg: 8922,
13835 leq: 8804,
13836 les: 10877,
13837 lfr: 120105,
13838 lgE: 10897,
13839 lnE: 8808,
13840 lne: 10887,
13841 loz: 9674,
13842 lrm: 8206,
13843 lsh: 8624,
13844 map: 8614,
13845 mcy: 1084,
13846 mfr: 120106,
13847 mho: 8487,
13848 mid: 8739,
13849 nap: 8777,
13850 ncy: 1085,
13851 nfr: 120107,
13852 nge: 8817,
13853 ngt: 8815,
13854 nis: 8956,
13855 niv: 8715,
13856 nle: 8816,
13857 nlt: 8814,
13858 not: 172,
13859 npr: 8832,
13860 nsc: 8833,
13861 num: 35,
13862 ocy: 1086,
13863 ofr: 120108,
13864 ogt: 10689,
13865 ohm: 8486,
13866 olt: 10688,
13867 ord: 10845,
13868 orv: 10843,
13869 par: 8741,
13870 pcy: 1087,
13871 pfr: 120109,
13872 phi: 966,
13873 piv: 982,
13874 prE: 10931,
13875 pre: 10927,
13876 psi: 968,
13877 qfr: 120110,
13878 rcy: 1088,
13879 reg: 174,
13880 rfr: 120111,
13881 rho: 961,
13882 rlm: 8207,
13883 rsh: 8625,
13884 scE: 10932,
13885 sce: 10928,
13886 scy: 1089,
13887 sfr: 120112,
13888 shy: 173,
13889 sim: 8764,
13890 smt: 10922,
13891 sol: 47,
13892 squ: 9633,
13893 sub: 8834,
13894 sum: 8721,
13895 sup: 8835,
13896 tau: 964,
13897 tcy: 1090,
13898 tfr: 120113,
13899 top: 8868,
13900 ucy: 1091,
13901 ufr: 120114,
13902 uml: 168,
13903 vcy: 1074,
13904 vee: 8744,
13905 vfr: 120115,
13906 wfr: 120116,
13907 xfr: 120117,
13908 ycy: 1099,
13909 yen: 165,
13910 yfr: 120118,
13911 zcy: 1079,
13912 zfr: 120119,
13913 zwj: 8205,
13914 DD: 8517,
13915 GT: 62,
13916 Gg: 8921,
13917 Gt: 8811,
13918 Im: 8465,
13919 LT: 60,
13920 Ll: 8920,
13921 Lt: 8810,
13922 Mu: 924,
13923 Nu: 925,
13924 Or: 10836,
13925 Pi: 928,
13926 Pr: 10939,
13927 Re: 8476,
13928 Sc: 10940,
13929 Xi: 926,
13930 ac: 8766,
13931 af: 8289,
13932 ap: 8776,
13933 dd: 8518,
13934 ee: 8519,
13935 eg: 10906,
13936 el: 10905,
13937 gE: 8807,
13938 ge: 8805,
13939 gg: 8811,
13940 gl: 8823,
13941 gt: 62,
13942 ic: 8291,
13943 ii: 8520,
13944 in: 8712,
13945 it: 8290,
13946 lE: 8806,
13947 le: 8804,
13948 lg: 8822,
13949 ll: 8810,
13950 lt: 60,
13951 mp: 8723,
13952 mu: 956,
13953 ne: 8800,
13954 ni: 8715,
13955 nu: 957,
13956 oS: 9416,
13957 or: 8744,
13958 pi: 960,
13959 pm: 177,
13960 pr: 8826,
13961 rx: 8478,
13962 sc: 8827,
13963 wp: 8472,
13964 wr: 8768,
13965 xi: 958,
13966 };
13967
13968 const windows_1252 = [
13969 8364,
13970 129,
13971 8218,
13972 402,
13973 8222,
13974 8230,
13975 8224,
13976 8225,
13977 710,
13978 8240,
13979 352,
13980 8249,
13981 338,
13982 141,
13983 381,
13984 143,
13985 144,
13986 8216,
13987 8217,
13988 8220,
13989 8221,
13990 8226,
13991 8211,
13992 8212,
13993 732,
13994 8482,
13995 353,
13996 8250,
13997 339,
13998 157,
13999 382,
14000 376,
14001 ];
14002 const entity_pattern = new RegExp(`&(#?(?:x[\\w\\d]+|\\d+|${Object.keys(entities).join('|')}))(?:;|\\b)`, 'g');
14003 function decode_character_references(html) {
14004 return html.replace(entity_pattern, (match, entity) => {
14005 let code;
14006 // Handle named entities
14007 if (entity[0] !== '#') {
14008 code = entities[entity];
14009 }
14010 else if (entity[1] === 'x') {
14011 code = parseInt(entity.substring(2), 16);
14012 }
14013 else {
14014 code = parseInt(entity.substring(1), 10);
14015 }
14016 if (!code) {
14017 return match;
14018 }
14019 return String.fromCodePoint(validate_code(code));
14020 });
14021 }
14022 const NUL = 0;
14023 // some code points are verboten. If we were inserting HTML, the browser would replace the illegal
14024 // code points with alternatives in some cases - since we're bypassing that mechanism, we need
14025 // to replace them ourselves
14026 //
14027 // Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
14028 function validate_code(code) {
14029 // line feed becomes generic whitespace
14030 if (code === 10) {
14031 return 32;
14032 }
14033 // ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
14034 if (code < 128) {
14035 return code;
14036 }
14037 // code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
14038 // to correct the mistake or we'll end up with missing € signs and so on
14039 if (code <= 159) {
14040 return windows_1252[code - 128];
14041 }
14042 // basic multilingual plane
14043 if (code < 55296) {
14044 return code;
14045 }
14046 // UTF-16 surrogate halves
14047 if (code <= 57343) {
14048 return NUL;
14049 }
14050 // rest of the basic multilingual plane
14051 if (code <= 65535) {
14052 return code;
14053 }
14054 // supplementary multilingual plane 0x10000 - 0x1ffff
14055 if (code >= 65536 && code <= 131071) {
14056 return code;
14057 }
14058 // supplementary ideographic plane 0x20000 - 0x2ffff
14059 if (code >= 131072 && code <= 196607) {
14060 return code;
14061 }
14062 return NUL;
14063 }
14064 // based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
14065 const disallowed_contents = new Map([
14066 ['li', new Set(['li'])],
14067 ['dt', new Set(['dt', 'dd'])],
14068 ['dd', new Set(['dt', 'dd'])],
14069 [
14070 'p',
14071 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(' ')),
14072 ],
14073 ['rt', new Set(['rt', 'rp'])],
14074 ['rp', new Set(['rt', 'rp'])],
14075 ['optgroup', new Set(['optgroup'])],
14076 ['option', new Set(['option', 'optgroup'])],
14077 ['thead', new Set(['tbody', 'tfoot'])],
14078 ['tbody', new Set(['tbody', 'tfoot'])],
14079 ['tfoot', new Set(['tbody'])],
14080 ['tr', new Set(['tr', 'tbody'])],
14081 ['td', new Set(['td', 'th', 'tr'])],
14082 ['th', new Set(['td', 'th', 'tr'])],
14083 ]);
14084 // can this be a child of the parent element, or does it implicitly
14085 // close it, like `<li>one<li>two`?
14086 function closing_tag_omitted(current, next) {
14087 if (disallowed_contents.has(current)) {
14088 if (!next || disallowed_contents.get(current).has(next)) {
14089 return true;
14090 }
14091 }
14092 return false;
14093 }
14094
14095 // Adapted from https://github.com/acornjs/acorn/blob/6584815dca7440e00de841d1dad152302fdd7ca5/src/tokenize.js
14096 // Reproduced under MIT License https://github.com/acornjs/acorn/blob/master/LICENSE
14097 function full_char_code_at(str, i) {
14098 const code = str.charCodeAt(i);
14099 if (code <= 0xd7ff || code >= 0xe000)
14100 return code;
14101 const next = str.charCodeAt(i + 1);
14102 return (code << 10) + next - 0x35fdc00;
14103 }
14104
14105 const globals = new Set([
14106 'alert',
14107 'Array',
14108 'Boolean',
14109 'clearInterval',
14110 'clearTimeout',
14111 'confirm',
14112 'console',
14113 'Date',
14114 'decodeURI',
14115 'decodeURIComponent',
14116 'document',
14117 'encodeURI',
14118 'encodeURIComponent',
14119 'Error',
14120 'EvalError',
14121 'Event',
14122 'fetch',
14123 'global',
14124 'globalThis',
14125 'history',
14126 'Infinity',
14127 'InternalError',
14128 'Intl',
14129 'isFinite',
14130 'isNaN',
14131 'JSON',
14132 'localStorage',
14133 'location',
14134 'Map',
14135 'Math',
14136 'NaN',
14137 'navigator',
14138 'Number',
14139 'Object',
14140 'parseFloat',
14141 'parseInt',
14142 'process',
14143 'Promise',
14144 'prompt',
14145 'RangeError',
14146 'ReferenceError',
14147 'RegExp',
14148 'sessionStorage',
14149 'Set',
14150 'setInterval',
14151 'setTimeout',
14152 'String',
14153 'SyntaxError',
14154 'TypeError',
14155 'undefined',
14156 'URIError',
14157 'URL',
14158 'window'
14159 ]);
14160 const reserved = new Set([
14161 'arguments',
14162 'await',
14163 'break',
14164 'case',
14165 'catch',
14166 'class',
14167 'const',
14168 'continue',
14169 'debugger',
14170 'default',
14171 'delete',
14172 'do',
14173 'else',
14174 'enum',
14175 'eval',
14176 'export',
14177 'extends',
14178 'false',
14179 'finally',
14180 'for',
14181 'function',
14182 'if',
14183 'implements',
14184 'import',
14185 'in',
14186 'instanceof',
14187 'interface',
14188 'let',
14189 'new',
14190 'null',
14191 'package',
14192 'private',
14193 'protected',
14194 'public',
14195 'return',
14196 'static',
14197 'super',
14198 'switch',
14199 'this',
14200 'throw',
14201 'true',
14202 'try',
14203 'typeof',
14204 'var',
14205 'void',
14206 'while',
14207 'with',
14208 'yield',
14209 ]);
14210 const void_element_names = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
14211 function is_void(name) {
14212 return void_element_names.test(name) || name.toLowerCase() === '!doctype';
14213 }
14214 function is_valid(str) {
14215 let i = 0;
14216 while (i < str.length) {
14217 const code = full_char_code_at(str, i);
14218 if (!(i === 0 ? isIdentifierStart : isIdentifierChar)(code, true))
14219 return false;
14220 i += code <= 0xffff ? 1 : 2;
14221 }
14222 return true;
14223 }
14224 function sanitize(name) {
14225 return name
14226 .replace(/[^a-zA-Z0-9_]+/g, '_')
14227 .replace(/^_/, '')
14228 .replace(/_$/, '')
14229 .replace(/^[0-9]/, '_$&');
14230 }
14231
14232 function fuzzymatch(name, names) {
14233 const set = new FuzzySet(names);
14234 const matches = set.get(name);
14235 return matches && matches[0] && matches[0][0] > 0.7 ? matches[0][1] : null;
14236 }
14237 // adapted from https://github.com/Glench/fuzzyset.js/blob/master/lib/fuzzyset.js
14238 // BSD Licensed
14239 const GRAM_SIZE_LOWER = 2;
14240 const GRAM_SIZE_UPPER = 3;
14241 // return an edit distance from 0 to 1
14242 function _distance(str1, str2) {
14243 if (str1 === null && str2 === null)
14244 throw 'Trying to compare two null values';
14245 if (str1 === null || str2 === null)
14246 return 0;
14247 str1 = String(str1);
14248 str2 = String(str2);
14249 const distance = levenshtein(str1, str2);
14250 if (str1.length > str2.length) {
14251 return 1 - distance / str1.length;
14252 }
14253 else {
14254 return 1 - distance / str2.length;
14255 }
14256 }
14257 // helper functions
14258 function levenshtein(str1, str2) {
14259 const current = [];
14260 let prev;
14261 let value;
14262 for (let i = 0; i <= str2.length; i++) {
14263 for (let j = 0; j <= str1.length; j++) {
14264 if (i && j) {
14265 if (str1.charAt(j - 1) === str2.charAt(i - 1)) {
14266 value = prev;
14267 }
14268 else {
14269 value = Math.min(current[j], current[j - 1], prev) + 1;
14270 }
14271 }
14272 else {
14273 value = i + j;
14274 }
14275 prev = current[j];
14276 current[j] = value;
14277 }
14278 }
14279 return current.pop();
14280 }
14281 const non_word_regex = /[^\w, ]+/;
14282 function iterate_grams(value, gram_size = 2) {
14283 const simplified = '-' + value.toLowerCase().replace(non_word_regex, '') + '-';
14284 const len_diff = gram_size - simplified.length;
14285 const results = [];
14286 if (len_diff > 0) {
14287 for (let i = 0; i < len_diff; ++i) {
14288 value += '-';
14289 }
14290 }
14291 for (let i = 0; i < simplified.length - gram_size + 1; ++i) {
14292 results.push(simplified.slice(i, i + gram_size));
14293 }
14294 return results;
14295 }
14296 function gram_counter(value, gram_size = 2) {
14297 // return an object where key=gram, value=number of occurrences
14298 const result = {};
14299 const grams = iterate_grams(value, gram_size);
14300 let i = 0;
14301 for (i; i < grams.length; ++i) {
14302 if (grams[i] in result) {
14303 result[grams[i]] += 1;
14304 }
14305 else {
14306 result[grams[i]] = 1;
14307 }
14308 }
14309 return result;
14310 }
14311 function sort_descending(a, b) {
14312 return b[0] - a[0];
14313 }
14314 class FuzzySet {
14315 constructor(arr) {
14316 this.exact_set = {};
14317 this.match_dict = {};
14318 this.items = {};
14319 // initialization
14320 for (let i = GRAM_SIZE_LOWER; i < GRAM_SIZE_UPPER + 1; ++i) {
14321 this.items[i] = [];
14322 }
14323 // add all the items to the set
14324 for (let i = 0; i < arr.length; ++i) {
14325 this.add(arr[i]);
14326 }
14327 }
14328 add(value) {
14329 const normalized_value = value.toLowerCase();
14330 if (normalized_value in this.exact_set) {
14331 return false;
14332 }
14333 let i = GRAM_SIZE_LOWER;
14334 for (i; i < GRAM_SIZE_UPPER + 1; ++i) {
14335 this._add(value, i);
14336 }
14337 }
14338 _add(value, gram_size) {
14339 const normalized_value = value.toLowerCase();
14340 const items = this.items[gram_size] || [];
14341 const index = items.length;
14342 items.push(0);
14343 const gram_counts = gram_counter(normalized_value, gram_size);
14344 let sum_of_square_gram_counts = 0;
14345 let gram;
14346 let gram_count;
14347 for (gram in gram_counts) {
14348 gram_count = gram_counts[gram];
14349 sum_of_square_gram_counts += Math.pow(gram_count, 2);
14350 if (gram in this.match_dict) {
14351 this.match_dict[gram].push([index, gram_count]);
14352 }
14353 else {
14354 this.match_dict[gram] = [[index, gram_count]];
14355 }
14356 }
14357 const vector_normal = Math.sqrt(sum_of_square_gram_counts);
14358 items[index] = [vector_normal, normalized_value];
14359 this.items[gram_size] = items;
14360 this.exact_set[normalized_value] = value;
14361 }
14362 get(value) {
14363 const normalized_value = value.toLowerCase();
14364 const result = this.exact_set[normalized_value];
14365 if (result) {
14366 return [[1, result]];
14367 }
14368 let results = [];
14369 // start with high gram size and if there are no results, go to lower gram sizes
14370 for (let gram_size = GRAM_SIZE_UPPER; gram_size >= GRAM_SIZE_LOWER; --gram_size) {
14371 results = this.__get(value, gram_size);
14372 if (results) {
14373 return results;
14374 }
14375 }
14376 return null;
14377 }
14378 __get(value, gram_size) {
14379 const normalized_value = value.toLowerCase();
14380 const matches = {};
14381 const gram_counts = gram_counter(normalized_value, gram_size);
14382 const items = this.items[gram_size];
14383 let sum_of_square_gram_counts = 0;
14384 let gram;
14385 let gram_count;
14386 let i;
14387 let index;
14388 let other_gram_count;
14389 for (gram in gram_counts) {
14390 gram_count = gram_counts[gram];
14391 sum_of_square_gram_counts += Math.pow(gram_count, 2);
14392 if (gram in this.match_dict) {
14393 for (i = 0; i < this.match_dict[gram].length; ++i) {
14394 index = this.match_dict[gram][i][0];
14395 other_gram_count = this.match_dict[gram][i][1];
14396 if (index in matches) {
14397 matches[index] += gram_count * other_gram_count;
14398 }
14399 else {
14400 matches[index] = gram_count * other_gram_count;
14401 }
14402 }
14403 }
14404 }
14405 const vector_normal = Math.sqrt(sum_of_square_gram_counts);
14406 let results = [];
14407 let match_score;
14408 // build a results list of [score, str]
14409 for (const match_index in matches) {
14410 match_score = matches[match_index];
14411 results.push([
14412 match_score / (vector_normal * items[match_index][0]),
14413 items[match_index][1],
14414 ]);
14415 }
14416 results.sort(sort_descending);
14417 let new_results = [];
14418 const end_index = Math.min(50, results.length);
14419 // truncate somewhat arbitrarily to 50
14420 for (let i = 0; i < end_index; ++i) {
14421 new_results.push([
14422 _distance(results[i][1], normalized_value),
14423 results[i][1],
14424 ]);
14425 }
14426 results = new_results;
14427 results.sort(sort_descending);
14428 new_results = [];
14429 for (let i = 0; i < results.length; ++i) {
14430 if (results[i][0] == results[0][0]) {
14431 new_results.push([results[i][0], this.exact_set[results[i][1]]]);
14432 }
14433 }
14434 return new_results;
14435 }
14436 }
14437
14438 function list$1(items, conjunction = 'or') {
14439 if (items.length === 1)
14440 return items[0];
14441 return `${items.slice(0, -1).join(', ')} ${conjunction} ${items[items.length - 1]}`;
14442 }
14443
14444 // eslint-disable-next-line no-useless-escape
14445 const valid_tag_name = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
14446 const meta_tags = new Map([
14447 ['svelte:head', 'Head'],
14448 ['svelte:options', 'Options'],
14449 ['svelte:window', 'Window'],
14450 ['svelte:body', 'Body']
14451 ]);
14452 const valid_meta_tags = Array.from(meta_tags.keys()).concat('svelte:self', 'svelte:component');
14453 const specials = new Map([
14454 [
14455 'script',
14456 {
14457 read: read_script,
14458 property: 'js',
14459 },
14460 ],
14461 [
14462 'style',
14463 {
14464 read: read_style,
14465 property: 'css',
14466 },
14467 ],
14468 ]);
14469 const SELF = /^svelte:self(?=[\s/>])/;
14470 const COMPONENT = /^svelte:component(?=[\s/>])/;
14471 function parent_is_head(stack) {
14472 let i = stack.length;
14473 while (i--) {
14474 const { type } = stack[i];
14475 if (type === 'Head')
14476 return true;
14477 if (type === 'Element' || type === 'InlineComponent')
14478 return false;
14479 }
14480 return false;
14481 }
14482 function tag(parser) {
14483 const start = parser.index++;
14484 let parent = parser.current();
14485 if (parser.eat('!--')) {
14486 const data = parser.read_until(/-->/);
14487 parser.eat('-->', true, 'comment was left open, expected -->');
14488 parser.current().children.push({
14489 start,
14490 end: parser.index,
14491 type: 'Comment',
14492 data,
14493 });
14494 return;
14495 }
14496 const is_closing_tag = parser.eat('/');
14497 const name = read_tag_name(parser);
14498 if (meta_tags.has(name)) {
14499 const slug = meta_tags.get(name).toLowerCase();
14500 if (is_closing_tag) {
14501 if ((name === 'svelte:window' || name === 'svelte:body') &&
14502 parser.current().children.length) {
14503 parser.error({
14504 code: `invalid-${slug}-content`,
14505 message: `<${name}> cannot have children`
14506 }, parser.current().children[0].start);
14507 }
14508 }
14509 else {
14510 if (name in parser.meta_tags) {
14511 parser.error({
14512 code: `duplicate-${slug}`,
14513 message: `A component can only have one <${name}> tag`
14514 }, start);
14515 }
14516 if (parser.stack.length > 1) {
14517 parser.error({
14518 code: `invalid-${slug}-placement`,
14519 message: `<${name}> tags cannot be inside elements or blocks`
14520 }, start);
14521 }
14522 parser.meta_tags[name] = true;
14523 }
14524 }
14525 const type = meta_tags.has(name)
14526 ? meta_tags.get(name)
14527 : (/[A-Z]/.test(name[0]) || name === 'svelte:self' || name === 'svelte:component') ? 'InlineComponent'
14528 : name === 'title' && parent_is_head(parser.stack) ? 'Title'
14529 : name === 'slot' && !parser.customElement ? 'Slot' : 'Element';
14530 const element = {
14531 start,
14532 end: null,
14533 type,
14534 name,
14535 attributes: [],
14536 children: [],
14537 };
14538 parser.allow_whitespace();
14539 if (is_closing_tag) {
14540 if (is_void(name)) {
14541 parser.error({
14542 code: `invalid-void-content`,
14543 message: `<${name}> is a void element and cannot have children, or a closing tag`
14544 }, start);
14545 }
14546 parser.eat('>', true);
14547 // close any elements that don't have their own closing tags, e.g. <div><p></div>
14548 while (parent.name !== name) {
14549 if (parent.type !== 'Element')
14550 parser.error({
14551 code: `invalid-closing-tag`,
14552 message: `</${name}> attempted to close an element that was not open`
14553 }, start);
14554 parent.end = start;
14555 parser.stack.pop();
14556 parent = parser.current();
14557 }
14558 parent.end = parser.index;
14559 parser.stack.pop();
14560 return;
14561 }
14562 else if (closing_tag_omitted(parent.name, name)) {
14563 parent.end = start;
14564 parser.stack.pop();
14565 }
14566 const unique_names = new Set();
14567 let attribute;
14568 while ((attribute = read_attribute(parser, unique_names))) {
14569 element.attributes.push(attribute);
14570 parser.allow_whitespace();
14571 }
14572 if (name === 'svelte:component') {
14573 const index = element.attributes.findIndex(attr => attr.type === 'Attribute' && attr.name === 'this');
14574 if (!~index) {
14575 parser.error({
14576 code: `missing-component-definition`,
14577 message: `<svelte:component> must have a 'this' attribute`
14578 }, start);
14579 }
14580 const definition = element.attributes.splice(index, 1)[0];
14581 if (definition.value === true || definition.value.length !== 1 || definition.value[0].type === 'Text') {
14582 parser.error({
14583 code: `invalid-component-definition`,
14584 message: `invalid component definition`
14585 }, definition.start);
14586 }
14587 element.expression = definition.value[0].expression;
14588 }
14589 // special cases – top-level <script> and <style>
14590 if (specials.has(name) && parser.stack.length === 1) {
14591 const special = specials.get(name);
14592 parser.eat('>', true);
14593 const content = special.read(parser, start, element.attributes);
14594 if (content)
14595 parser[special.property].push(content);
14596 return;
14597 }
14598 parser.current().children.push(element);
14599 const self_closing = parser.eat('/') || is_void(name);
14600 parser.eat('>', true);
14601 if (self_closing) {
14602 // don't push self-closing elements onto the stack
14603 element.end = parser.index;
14604 }
14605 else if (name === 'textarea') {
14606 // special case
14607 element.children = read_sequence(parser, () => parser.template.slice(parser.index, parser.index + 11) === '</textarea>');
14608 parser.read(/<\/textarea>/);
14609 element.end = parser.index;
14610 }
14611 else if (name === 'script') {
14612 // special case
14613 const start = parser.index;
14614 const data = parser.read_until(/<\/script>/);
14615 const end = parser.index;
14616 element.children.push({ start, end, type: 'Text', data });
14617 parser.eat('</script>', true);
14618 element.end = parser.index;
14619 }
14620 else if (name === 'style') {
14621 // special case
14622 const start = parser.index;
14623 const data = parser.read_until(/<\/style>/);
14624 const end = parser.index;
14625 element.children.push({ start, end, type: 'Text', data });
14626 parser.eat('</style>', true);
14627 }
14628 else {
14629 parser.stack.push(element);
14630 }
14631 }
14632 function read_tag_name(parser) {
14633 const start = parser.index;
14634 if (parser.read(SELF)) {
14635 // check we're inside a block, otherwise this
14636 // will cause infinite recursion
14637 let i = parser.stack.length;
14638 let legal = false;
14639 while (i--) {
14640 const fragment = parser.stack[i];
14641 if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock' || fragment.type === 'InlineComponent') {
14642 legal = true;
14643 break;
14644 }
14645 }
14646 if (!legal) {
14647 parser.error({
14648 code: `invalid-self-placement`,
14649 message: `<svelte:self> components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components`
14650 }, start);
14651 }
14652 return 'svelte:self';
14653 }
14654 if (parser.read(COMPONENT))
14655 return 'svelte:component';
14656 const name = parser.read_until(/(\s|\/|>)/);
14657 if (meta_tags.has(name))
14658 return name;
14659 if (name.startsWith('svelte:')) {
14660 const match = fuzzymatch(name.slice(7), valid_meta_tags);
14661 let message = `Valid <svelte:...> tag names are ${list$1(valid_meta_tags)}`;
14662 if (match)
14663 message += ` (did you mean '${match}'?)`;
14664 parser.error({
14665 code: 'invalid-tag-name',
14666 message
14667 }, start);
14668 }
14669 if (!valid_tag_name.test(name)) {
14670 parser.error({
14671 code: `invalid-tag-name`,
14672 message: `Expected valid tag name`
14673 }, start);
14674 }
14675 return name;
14676 }
14677 function read_attribute(parser, unique_names) {
14678 const start = parser.index;
14679 function check_unique(name) {
14680 if (unique_names.has(name)) {
14681 parser.error({
14682 code: `duplicate-attribute`,
14683 message: 'Attributes need to be unique'
14684 }, start);
14685 }
14686 unique_names.add(name);
14687 }
14688 if (parser.eat('{')) {
14689 parser.allow_whitespace();
14690 if (parser.eat('...')) {
14691 const expression = read_expression(parser);
14692 parser.allow_whitespace();
14693 parser.eat('}', true);
14694 return {
14695 start,
14696 end: parser.index,
14697 type: 'Spread',
14698 expression
14699 };
14700 }
14701 else {
14702 const value_start = parser.index;
14703 const name = parser.read_identifier();
14704 parser.allow_whitespace();
14705 parser.eat('}', true);
14706 check_unique(name);
14707 return {
14708 start,
14709 end: parser.index,
14710 type: 'Attribute',
14711 name,
14712 value: [{
14713 start: value_start,
14714 end: value_start + name.length,
14715 type: 'AttributeShorthand',
14716 expression: {
14717 start: value_start,
14718 end: value_start + name.length,
14719 type: 'Identifier',
14720 name
14721 }
14722 }]
14723 };
14724 }
14725 }
14726 // eslint-disable-next-line no-useless-escape
14727 const name = parser.read_until(/[\s=\/>"']/);
14728 if (!name)
14729 return null;
14730 let end = parser.index;
14731 parser.allow_whitespace();
14732 const colon_index = name.indexOf(':');
14733 const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index));
14734 let value = true;
14735 if (parser.eat('=')) {
14736 parser.allow_whitespace();
14737 value = read_attribute_value(parser);
14738 end = parser.index;
14739 }
14740 else if (parser.match_regex(/["']/)) {
14741 parser.error({
14742 code: `unexpected-token`,
14743 message: `Expected =`
14744 }, parser.index);
14745 }
14746 if (type) {
14747 const [directive_name, ...modifiers] = name.slice(colon_index + 1).split('|');
14748 if (type === 'Binding' && directive_name !== 'this') {
14749 check_unique(directive_name);
14750 }
14751 else if (type !== 'EventHandler') {
14752 check_unique(name);
14753 }
14754 if (type === 'Ref') {
14755 parser.error({
14756 code: `invalid-ref-directive`,
14757 message: `The ref directive is no longer supported — use \`bind:this={${directive_name}}\` instead`
14758 }, start);
14759 }
14760 if (value[0]) {
14761 if (value.length > 1 || value[0].type === 'Text') {
14762 parser.error({
14763 code: `invalid-directive-value`,
14764 message: `Directive value must be a JavaScript expression enclosed in curly braces`
14765 }, value[0].start);
14766 }
14767 }
14768 const directive = {
14769 start,
14770 end,
14771 type,
14772 name: directive_name,
14773 modifiers,
14774 expression: (value[0] && value[0].expression) || null
14775 };
14776 if (type === 'Transition') {
14777 const direction = name.slice(0, colon_index);
14778 directive.intro = direction === 'in' || direction === 'transition';
14779 directive.outro = direction === 'out' || direction === 'transition';
14780 }
14781 if (!directive.expression && (type === 'Binding' || type === 'Class')) {
14782 directive.expression = {
14783 start: directive.start + colon_index + 1,
14784 end: directive.end,
14785 type: 'Identifier',
14786 name: directive.name
14787 };
14788 }
14789 return directive;
14790 }
14791 check_unique(name);
14792 return {
14793 start,
14794 end,
14795 type: 'Attribute',
14796 name,
14797 value,
14798 };
14799 }
14800 function get_directive_type(name) {
14801 if (name === 'use')
14802 return 'Action';
14803 if (name === 'animate')
14804 return 'Animation';
14805 if (name === 'bind')
14806 return 'Binding';
14807 if (name === 'class')
14808 return 'Class';
14809 if (name === 'on')
14810 return 'EventHandler';
14811 if (name === 'let')
14812 return 'Let';
14813 if (name === 'ref')
14814 return 'Ref';
14815 if (name === 'in' || name === 'out' || name === 'transition')
14816 return 'Transition';
14817 }
14818 function read_attribute_value(parser) {
14819 const quote_mark = parser.eat(`'`) ? `'` : parser.eat(`"`) ? `"` : null;
14820 const regex = (quote_mark === `'` ? /'/ :
14821 quote_mark === `"` ? /"/ :
14822 /(\/>|[\s"'=<>`])/);
14823 const value = read_sequence(parser, () => !!parser.match_regex(regex));
14824 if (quote_mark)
14825 parser.index += 1;
14826 return value;
14827 }
14828 function read_sequence(parser, done) {
14829 let current_chunk = {
14830 start: parser.index,
14831 end: null,
14832 type: 'Text',
14833 raw: '',
14834 data: null
14835 };
14836 function flush() {
14837 if (current_chunk.raw) {
14838 current_chunk.data = decode_character_references(current_chunk.raw);
14839 current_chunk.end = parser.index;
14840 chunks.push(current_chunk);
14841 }
14842 }
14843 const chunks = [];
14844 while (parser.index < parser.template.length) {
14845 const index = parser.index;
14846 if (done()) {
14847 flush();
14848 return chunks;
14849 }
14850 else if (parser.eat('{')) {
14851 flush();
14852 parser.allow_whitespace();
14853 const expression = read_expression(parser);
14854 parser.allow_whitespace();
14855 parser.eat('}', true);
14856 chunks.push({
14857 start: index,
14858 end: parser.index,
14859 type: 'MustacheTag',
14860 expression,
14861 });
14862 current_chunk = {
14863 start: parser.index,
14864 end: null,
14865 type: 'Text',
14866 raw: '',
14867 data: null
14868 };
14869 }
14870 else {
14871 current_chunk.raw += parser.template[parser.index++];
14872 }
14873 }
14874 parser.error({
14875 code: `unexpected-eof`,
14876 message: `Unexpected end of input`
14877 });
14878 }
14879
14880 const SQUARE_BRACKET_OPEN = "[".charCodeAt(0);
14881 const SQUARE_BRACKET_CLOSE = "]".charCodeAt(0);
14882 const CURLY_BRACKET_OPEN = "{".charCodeAt(0);
14883 const CURLY_BRACKET_CLOSE = "}".charCodeAt(0);
14884 function is_bracket_open(code) {
14885 return code === SQUARE_BRACKET_OPEN || code === CURLY_BRACKET_OPEN;
14886 }
14887 function is_bracket_close(code) {
14888 return code === SQUARE_BRACKET_CLOSE || code === CURLY_BRACKET_CLOSE;
14889 }
14890 function is_bracket_pair(open, close) {
14891 return ((open === SQUARE_BRACKET_OPEN && close === SQUARE_BRACKET_CLOSE) ||
14892 (open === CURLY_BRACKET_OPEN && close === CURLY_BRACKET_CLOSE));
14893 }
14894 function get_bracket_close(open) {
14895 if (open === SQUARE_BRACKET_OPEN) {
14896 return SQUARE_BRACKET_CLOSE;
14897 }
14898 if (open === CURLY_BRACKET_OPEN) {
14899 return CURLY_BRACKET_CLOSE;
14900 }
14901 }
14902
14903 function read_context(parser) {
14904 const start = parser.index;
14905 let i = parser.index;
14906 const code = full_char_code_at(parser.template, i);
14907 if (isIdentifierStart(code, true)) {
14908 return {
14909 type: "Identifier",
14910 name: parser.read_identifier(),
14911 start,
14912 end: parser.index
14913 };
14914 }
14915 if (!is_bracket_open(code)) {
14916 parser.error({
14917 code: "unexpected-token",
14918 message: "Expected identifier or destructure pattern"
14919 });
14920 }
14921 const bracket_stack = [code];
14922 i += code <= 0xffff ? 1 : 2;
14923 while (i < parser.template.length) {
14924 const code = full_char_code_at(parser.template, i);
14925 if (is_bracket_open(code)) {
14926 bracket_stack.push(code);
14927 }
14928 else if (is_bracket_close(code)) {
14929 if (!is_bracket_pair(bracket_stack[bracket_stack.length - 1], code)) {
14930 parser.error({
14931 code: "unexpected-token",
14932 message: `Expected ${String.fromCharCode(get_bracket_close(bracket_stack[bracket_stack.length - 1]))}`
14933 });
14934 }
14935 bracket_stack.pop();
14936 if (bracket_stack.length === 0) {
14937 i += code <= 0xffff ? 1 : 2;
14938 break;
14939 }
14940 }
14941 i += code <= 0xffff ? 1 : 2;
14942 }
14943 parser.index = i;
14944 const pattern_string = parser.template.slice(start, i);
14945 try {
14946 // the length of the `space_with_newline` has to be start - 1
14947 // because we added a `(` in front of the pattern_string,
14948 // which shifted the entire string to right by 1
14949 // so we offset it by removing 1 character in the `space_with_newline`
14950 // to achieve that, we remove the 1st space encountered,
14951 // so it will not affect the `column` of the node
14952 let space_with_newline = parser.template.slice(0, start).replace(/[^\n]/g, ' ');
14953 const first_space = space_with_newline.indexOf(' ');
14954 space_with_newline = space_with_newline.slice(0, first_space) + space_with_newline.slice(first_space + 1);
14955 return parse_expression_at(`${space_with_newline}(${pattern_string} = 1)`, start - 1).left;
14956 }
14957 catch (error) {
14958 parser.acorn_error(error);
14959 }
14960 }
14961
14962 function trim_start(str) {
14963 let i = 0;
14964 while (whitespace.test(str[i]))
14965 i += 1;
14966 return str.slice(i);
14967 }
14968 function trim_end(str) {
14969 let i = str.length;
14970 while (whitespace.test(str[i - 1]))
14971 i -= 1;
14972 return str.slice(0, i);
14973 }
14974
14975 function to_string(node) {
14976 switch (node.type) {
14977 case 'IfBlock':
14978 return '{#if} block';
14979 case 'ThenBlock':
14980 return '{:then} block';
14981 case 'ElseBlock':
14982 return '{:else} block';
14983 case 'PendingBlock':
14984 case 'AwaitBlock':
14985 return '{#await} block';
14986 case 'CatchBlock':
14987 return '{:catch} block';
14988 case 'EachBlock':
14989 return '{#each} block';
14990 case 'RawMustacheTag':
14991 return '{@html} block';
14992 case 'DebugTag':
14993 return '{@debug} block';
14994 case 'Element':
14995 case 'InlineComponent':
14996 case 'Slot':
14997 case 'Title':
14998 return `<${node.name}> tag`;
14999 default:
15000 return node.type;
15001 }
15002 }
15003
15004 function trim_whitespace(block, trim_before, trim_after) {
15005 if (!block.children || block.children.length === 0)
15006 return; // AwaitBlock
15007 const first_child = block.children[0];
15008 const last_child = block.children[block.children.length - 1];
15009 if (first_child.type === 'Text' && trim_before) {
15010 first_child.data = trim_start(first_child.data);
15011 if (!first_child.data)
15012 block.children.shift();
15013 }
15014 if (last_child.type === 'Text' && trim_after) {
15015 last_child.data = trim_end(last_child.data);
15016 if (!last_child.data)
15017 block.children.pop();
15018 }
15019 if (block.else) {
15020 trim_whitespace(block.else, trim_before, trim_after);
15021 }
15022 if (first_child.elseif) {
15023 trim_whitespace(first_child, trim_before, trim_after);
15024 }
15025 }
15026 function mustache(parser) {
15027 const start = parser.index;
15028 parser.index += 1;
15029 parser.allow_whitespace();
15030 // {/if}, {/each} or {/await}
15031 if (parser.eat('/')) {
15032 let block = parser.current();
15033 let expected;
15034 if (closing_tag_omitted(block.name)) {
15035 block.end = start;
15036 parser.stack.pop();
15037 block = parser.current();
15038 }
15039 if (block.type === 'ElseBlock' || block.type === 'PendingBlock' || block.type === 'ThenBlock' || block.type === 'CatchBlock') {
15040 block.end = start;
15041 parser.stack.pop();
15042 block = parser.current();
15043 expected = 'await';
15044 }
15045 if (block.type === 'IfBlock') {
15046 expected = 'if';
15047 }
15048 else if (block.type === 'EachBlock') {
15049 expected = 'each';
15050 }
15051 else if (block.type === 'AwaitBlock') {
15052 expected = 'await';
15053 }
15054 else {
15055 parser.error({
15056 code: `unexpected-block-close`,
15057 message: `Unexpected block closing tag`
15058 });
15059 }
15060 parser.eat(expected, true);
15061 parser.allow_whitespace();
15062 parser.eat('}', true);
15063 while (block.elseif) {
15064 block.end = parser.index;
15065 parser.stack.pop();
15066 block = parser.current();
15067 if (block.else) {
15068 block.else.end = start;
15069 }
15070 }
15071 // strip leading/trailing whitespace as necessary
15072 const char_before = parser.template[block.start - 1];
15073 const char_after = parser.template[parser.index];
15074 const trim_before = !char_before || whitespace.test(char_before);
15075 const trim_after = !char_after || whitespace.test(char_after);
15076 trim_whitespace(block, trim_before, trim_after);
15077 block.end = parser.index;
15078 parser.stack.pop();
15079 }
15080 else if (parser.eat(':else')) {
15081 if (parser.eat('if')) {
15082 parser.error({
15083 code: 'invalid-elseif',
15084 message: `'elseif' should be 'else if'`
15085 });
15086 }
15087 parser.allow_whitespace();
15088 // :else if
15089 if (parser.eat('if')) {
15090 const block = parser.current();
15091 if (block.type !== 'IfBlock') {
15092 parser.error({
15093 code: `invalid-elseif-placement`,
15094 message: parser.stack.some(block => block.type === 'IfBlock')
15095 ? `Expected to close ${to_string(block)} before seeing {:else if ...} block`
15096 : `Cannot have an {:else if ...} block outside an {#if ...} block`
15097 });
15098 }
15099 parser.require_whitespace();
15100 const expression = read_expression(parser);
15101 parser.allow_whitespace();
15102 parser.eat('}', true);
15103 block.else = {
15104 start: parser.index,
15105 end: null,
15106 type: 'ElseBlock',
15107 children: [
15108 {
15109 start: parser.index,
15110 end: null,
15111 type: 'IfBlock',
15112 elseif: true,
15113 expression,
15114 children: [],
15115 },
15116 ],
15117 };
15118 parser.stack.push(block.else.children[0]);
15119 }
15120 // :else
15121 else {
15122 const block = parser.current();
15123 if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
15124 parser.error({
15125 code: `invalid-else-placement`,
15126 message: parser.stack.some(block => block.type === 'IfBlock' || block.type === 'EachBlock')
15127 ? `Expected to close ${to_string(block)} before seeing {:else} block`
15128 : `Cannot have an {:else} block outside an {#if ...} or {#each ...} block`
15129 });
15130 }
15131 parser.allow_whitespace();
15132 parser.eat('}', true);
15133 block.else = {
15134 start: parser.index,
15135 end: null,
15136 type: 'ElseBlock',
15137 children: [],
15138 };
15139 parser.stack.push(block.else);
15140 }
15141 }
15142 else if (parser.match(':then') || parser.match(':catch')) {
15143 const block = parser.current();
15144 const is_then = parser.eat(':then') || !parser.eat(':catch');
15145 if (is_then) {
15146 if (block.type !== 'PendingBlock') {
15147 parser.error({
15148 code: `invalid-then-placement`,
15149 message: parser.stack.some(block => block.type === 'PendingBlock')
15150 ? `Expected to close ${to_string(block)} before seeing {:then} block`
15151 : `Cannot have an {:then} block outside an {#await ...} block`
15152 });
15153 }
15154 }
15155 else {
15156 if (block.type !== 'ThenBlock' && block.type !== 'PendingBlock') {
15157 parser.error({
15158 code: `invalid-catch-placement`,
15159 message: parser.stack.some(block => block.type === 'ThenBlock' || block.type === 'PendingBlock')
15160 ? `Expected to close ${to_string(block)} before seeing {:catch} block`
15161 : `Cannot have an {:catch} block outside an {#await ...} block`
15162 });
15163 }
15164 }
15165 block.end = start;
15166 parser.stack.pop();
15167 const await_block = parser.current();
15168 if (!parser.eat('}')) {
15169 parser.require_whitespace();
15170 await_block[is_then ? 'value' : 'error'] = read_context(parser);
15171 parser.allow_whitespace();
15172 parser.eat('}', true);
15173 }
15174 const new_block = {
15175 start,
15176 end: null,
15177 type: is_then ? 'ThenBlock' : 'CatchBlock',
15178 children: [],
15179 skip: false
15180 };
15181 await_block[is_then ? 'then' : 'catch'] = new_block;
15182 parser.stack.push(new_block);
15183 }
15184 else if (parser.eat('#')) {
15185 // {#if foo}, {#each foo} or {#await foo}
15186 let type;
15187 if (parser.eat('if')) {
15188 type = 'IfBlock';
15189 }
15190 else if (parser.eat('each')) {
15191 type = 'EachBlock';
15192 }
15193 else if (parser.eat('await')) {
15194 type = 'AwaitBlock';
15195 }
15196 else {
15197 parser.error({
15198 code: `expected-block-type`,
15199 message: `Expected if, each or await`
15200 });
15201 }
15202 parser.require_whitespace();
15203 const expression = read_expression(parser);
15204 const block = type === 'AwaitBlock' ?
15205 {
15206 start,
15207 end: null,
15208 type,
15209 expression,
15210 value: null,
15211 error: null,
15212 pending: {
15213 start: null,
15214 end: null,
15215 type: 'PendingBlock',
15216 children: [],
15217 skip: true
15218 },
15219 then: {
15220 start: null,
15221 end: null,
15222 type: 'ThenBlock',
15223 children: [],
15224 skip: true
15225 },
15226 catch: {
15227 start: null,
15228 end: null,
15229 type: 'CatchBlock',
15230 children: [],
15231 skip: true
15232 },
15233 } :
15234 {
15235 start,
15236 end: null,
15237 type,
15238 expression,
15239 children: [],
15240 };
15241 parser.allow_whitespace();
15242 // {#each} blocks must declare a context – {#each list as item}
15243 if (type === 'EachBlock') {
15244 parser.eat('as', true);
15245 parser.require_whitespace();
15246 block.context = read_context(parser);
15247 parser.allow_whitespace();
15248 if (parser.eat(',')) {
15249 parser.allow_whitespace();
15250 block.index = parser.read_identifier();
15251 if (!block.index)
15252 parser.error({
15253 code: `expected-name`,
15254 message: `Expected name`
15255 });
15256 parser.allow_whitespace();
15257 }
15258 if (parser.eat('(')) {
15259 parser.allow_whitespace();
15260 block.key = read_expression(parser);
15261 parser.allow_whitespace();
15262 parser.eat(')', true);
15263 parser.allow_whitespace();
15264 }
15265 }
15266 const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then');
15267 if (await_block_shorthand) {
15268 parser.require_whitespace();
15269 block.value = read_context(parser);
15270 parser.allow_whitespace();
15271 }
15272 const await_block_catch_shorthand = !await_block_shorthand && type === 'AwaitBlock' && parser.eat('catch');
15273 if (await_block_catch_shorthand) {
15274 parser.require_whitespace();
15275 block.error = read_context(parser);
15276 parser.allow_whitespace();
15277 }
15278 parser.eat('}', true);
15279 parser.current().children.push(block);
15280 parser.stack.push(block);
15281 if (type === 'AwaitBlock') {
15282 let child_block;
15283 if (await_block_shorthand) {
15284 block.then.skip = false;
15285 child_block = block.then;
15286 }
15287 else if (await_block_catch_shorthand) {
15288 block.catch.skip = false;
15289 child_block = block.catch;
15290 }
15291 else {
15292 block.pending.skip = false;
15293 child_block = block.pending;
15294 }
15295 child_block.start = parser.index;
15296 parser.stack.push(child_block);
15297 }
15298 }
15299 else if (parser.eat('@html')) {
15300 // {@html content} tag
15301 parser.require_whitespace();
15302 const expression = read_expression(parser);
15303 parser.allow_whitespace();
15304 parser.eat('}', true);
15305 parser.current().children.push({
15306 start,
15307 end: parser.index,
15308 type: 'RawMustacheTag',
15309 expression,
15310 });
15311 }
15312 else if (parser.eat('@debug')) {
15313 let identifiers;
15314 // Implies {@debug} which indicates "debug all"
15315 if (parser.read(/\s*}/)) {
15316 identifiers = [];
15317 }
15318 else {
15319 const expression = read_expression(parser);
15320 identifiers = expression.type === 'SequenceExpression'
15321 ? expression.expressions
15322 : [expression];
15323 identifiers.forEach(node => {
15324 if (node.type !== 'Identifier') {
15325 parser.error({
15326 code: 'invalid-debug-args',
15327 message: '{@debug ...} arguments must be identifiers, not arbitrary expressions'
15328 }, node.start);
15329 }
15330 });
15331 parser.allow_whitespace();
15332 parser.eat('}', true);
15333 }
15334 parser.current().children.push({
15335 start,
15336 end: parser.index,
15337 type: 'DebugTag',
15338 identifiers
15339 });
15340 }
15341 else {
15342 const expression = read_expression(parser);
15343 parser.allow_whitespace();
15344 parser.eat('}', true);
15345 parser.current().children.push({
15346 start,
15347 end: parser.index,
15348 type: 'MustacheTag',
15349 expression,
15350 });
15351 }
15352 }
15353
15354 function text(parser) {
15355 const start = parser.index;
15356 let data = '';
15357 while (parser.index < parser.template.length &&
15358 !parser.match('<') &&
15359 !parser.match('{')) {
15360 data += parser.template[parser.index++];
15361 }
15362 const node = {
15363 start,
15364 end: parser.index,
15365 type: 'Text',
15366 raw: data,
15367 data: decode_character_references(data),
15368 };
15369 parser.current().children.push(node);
15370 }
15371
15372 function fragment(parser) {
15373 if (parser.match('<')) {
15374 return tag;
15375 }
15376 if (parser.match('{')) {
15377 return mustache;
15378 }
15379 return text;
15380 }
15381
15382 function getLocator(source, options) {
15383 if (options === void 0) { options = {}; }
15384 var offsetLine = options.offsetLine || 0;
15385 var offsetColumn = options.offsetColumn || 0;
15386 var originalLines = source.split('\n');
15387 var start = 0;
15388 var lineRanges = originalLines.map(function (line, i) {
15389 var end = start + line.length + 1;
15390 var range = { start: start, end: end, line: i };
15391 start = end;
15392 return range;
15393 });
15394 var i = 0;
15395 function rangeContains(range, index) {
15396 return range.start <= index && index < range.end;
15397 }
15398 function getLocation(range, index) {
15399 return { line: offsetLine + range.line, column: offsetColumn + index - range.start, character: index };
15400 }
15401 function locate(search, startIndex) {
15402 if (typeof search === 'string') {
15403 search = source.indexOf(search, startIndex || 0);
15404 }
15405 var range = lineRanges[i];
15406 var d = search >= range.end ? 1 : -1;
15407 while (range) {
15408 if (rangeContains(range, search))
15409 return getLocation(range, search);
15410 i += d;
15411 range = lineRanges[i];
15412 }
15413 }
15414 return locate;
15415 }
15416 function locate(source, search, options) {
15417 if (typeof options === 'number') {
15418 throw new Error('locate takes a { startIndex, offsetLine, offsetColumn } object as the third argument');
15419 }
15420 return getLocator(source, options)(search, options && options.startIndex);
15421 }
15422
15423 function tabs_to_spaces(str) {
15424 return str.replace(/^\t+/, match => match.split('\t').join(' '));
15425 }
15426 function get_code_frame(source, line, column) {
15427 const lines = source.split('\n');
15428 const frame_start = Math.max(0, line - 2);
15429 const frame_end = Math.min(line + 3, lines.length);
15430 const digits = String(frame_end + 1).length;
15431 return lines
15432 .slice(frame_start, frame_end)
15433 .map((str, i) => {
15434 const isErrorLine = frame_start + i === line;
15435 const line_num = String(i + frame_start + 1).padStart(digits, ' ');
15436 if (isErrorLine) {
15437 const indicator = ' '.repeat(digits + 2 + tabs_to_spaces(str.slice(0, column)).length) + '^';
15438 return `${line_num}: ${tabs_to_spaces(str)}\n${indicator}`;
15439 }
15440 return `${line_num}: ${tabs_to_spaces(str)}`;
15441 })
15442 .join('\n');
15443 }
15444
15445 class CompileError extends Error {
15446 toString() {
15447 return `${this.message} (${this.start.line}:${this.start.column})\n${this.frame}`;
15448 }
15449 }
15450 function error$1(message, props) {
15451 const error = new CompileError(message);
15452 error.name = props.name;
15453 const start = locate(props.source, props.start, { offsetLine: 1 });
15454 const end = locate(props.source, props.end || props.start, { offsetLine: 1 });
15455 error.code = props.code;
15456 error.start = start;
15457 error.end = end;
15458 error.pos = props.start;
15459 error.filename = props.filename;
15460 error.frame = get_code_frame(props.source, start.line - 1, start.column);
15461 throw error;
15462 }
15463
15464 class Parser$1 {
15465 constructor(template, options) {
15466 this.index = 0;
15467 this.stack = [];
15468 this.css = [];
15469 this.js = [];
15470 this.meta_tags = {};
15471 if (typeof template !== 'string') {
15472 throw new TypeError('Template must be a string');
15473 }
15474 this.template = template.replace(/\s+$/, '');
15475 this.filename = options.filename;
15476 this.customElement = options.customElement;
15477 this.html = {
15478 start: null,
15479 end: null,
15480 type: 'Fragment',
15481 children: [],
15482 };
15483 this.stack.push(this.html);
15484 let state = fragment;
15485 while (this.index < this.template.length) {
15486 state = state(this) || fragment;
15487 }
15488 if (this.stack.length > 1) {
15489 const current = this.current();
15490 const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
15491 const slug = current.type === 'Element' ? 'element' : 'block';
15492 this.error({
15493 code: `unclosed-${slug}`,
15494 message: `${type} was left open`
15495 }, current.start);
15496 }
15497 if (state !== fragment) {
15498 this.error({
15499 code: `unexpected-eof`,
15500 message: 'Unexpected end of input'
15501 });
15502 }
15503 if (this.html.children.length) {
15504 let start = this.html.children[0].start;
15505 while (whitespace.test(template[start]))
15506 start += 1;
15507 let end = this.html.children[this.html.children.length - 1].end;
15508 while (whitespace.test(template[end - 1]))
15509 end -= 1;
15510 this.html.start = start;
15511 this.html.end = end;
15512 }
15513 else {
15514 this.html.start = this.html.end = null;
15515 }
15516 }
15517 current() {
15518 return this.stack[this.stack.length - 1];
15519 }
15520 acorn_error(err) {
15521 this.error({
15522 code: `parse-error`,
15523 message: err.message.replace(/ \(\d+:\d+\)$/, '')
15524 }, err.pos);
15525 }
15526 error({ code, message }, index = this.index) {
15527 error$1(message, {
15528 name: 'ParseError',
15529 code,
15530 source: this.template,
15531 start: index,
15532 filename: this.filename
15533 });
15534 }
15535 eat(str, required, message) {
15536 if (this.match(str)) {
15537 this.index += str.length;
15538 return true;
15539 }
15540 if (required) {
15541 this.error({
15542 code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`,
15543 message: message || `Expected ${str}`
15544 });
15545 }
15546 return false;
15547 }
15548 match(str) {
15549 return this.template.slice(this.index, this.index + str.length) === str;
15550 }
15551 match_regex(pattern) {
15552 const match = pattern.exec(this.template.slice(this.index));
15553 if (!match || match.index !== 0)
15554 return null;
15555 return match[0];
15556 }
15557 allow_whitespace() {
15558 while (this.index < this.template.length &&
15559 whitespace.test(this.template[this.index])) {
15560 this.index++;
15561 }
15562 }
15563 read(pattern) {
15564 const result = this.match_regex(pattern);
15565 if (result)
15566 this.index += result.length;
15567 return result;
15568 }
15569 read_identifier(allow_reserved = false) {
15570 const start = this.index;
15571 let i = this.index;
15572 const code = full_char_code_at(this.template, i);
15573 if (!isIdentifierStart(code, true))
15574 return null;
15575 i += code <= 0xffff ? 1 : 2;
15576 while (i < this.template.length) {
15577 const code = full_char_code_at(this.template, i);
15578 if (!isIdentifierChar(code, true))
15579 break;
15580 i += code <= 0xffff ? 1 : 2;
15581 }
15582 const identifier = this.template.slice(this.index, this.index = i);
15583 if (!allow_reserved && reserved.has(identifier)) {
15584 this.error({
15585 code: `unexpected-reserved-word`,
15586 message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`
15587 }, start);
15588 }
15589 return identifier;
15590 }
15591 read_until(pattern) {
15592 if (this.index >= this.template.length)
15593 this.error({
15594 code: `unexpected-eof`,
15595 message: 'Unexpected end of input'
15596 });
15597 const start = this.index;
15598 const match = pattern.exec(this.template.slice(start));
15599 if (match) {
15600 this.index = start + match.index;
15601 return this.template.slice(start, this.index);
15602 }
15603 this.index = this.template.length;
15604 return this.template.slice(start);
15605 }
15606 require_whitespace() {
15607 if (!whitespace.test(this.template[this.index])) {
15608 this.error({
15609 code: `missing-whitespace`,
15610 message: `Expected whitespace`
15611 });
15612 }
15613 this.allow_whitespace();
15614 }
15615 }
15616 function parse$3(template, options = {}) {
15617 const parser = new Parser$1(template, options);
15618 // TODO we may want to allow multiple <style> tags —
15619 // one scoped, one global. for now, only allow one
15620 if (parser.css.length > 1) {
15621 parser.error({
15622 code: 'duplicate-style',
15623 message: 'You can only have one top-level <style> tag per component'
15624 }, parser.css[1].start);
15625 }
15626 const instance_scripts = parser.js.filter(script => script.context === 'default');
15627 const module_scripts = parser.js.filter(script => script.context === 'module');
15628 if (instance_scripts.length > 1) {
15629 parser.error({
15630 code: `invalid-script`,
15631 message: `A component can only have one instance-level <script> element`
15632 }, instance_scripts[1].start);
15633 }
15634 if (module_scripts.length > 1) {
15635 parser.error({
15636 code: `invalid-script`,
15637 message: `A component can only have one <script context="module"> element`
15638 }, module_scripts[1].start);
15639 }
15640 return {
15641 html: parser.html,
15642 css: parser.css[0],
15643 instance: instance_scripts[0],
15644 module: module_scripts[0]
15645 };
15646 }
15647
15648 function is_head(node) {
15649 return node && node.type === 'MemberExpression' && node.object.name === '@_document' && node.property.name === 'head';
15650 }
15651
15652 class Block$1 {
15653 constructor(options) {
15654 this.dependencies = new Set();
15655 this.event_listeners = [];
15656 this.variables = new Map();
15657 this.has_update_method = false;
15658 this.parent = options.parent;
15659 this.renderer = options.renderer;
15660 this.name = options.name;
15661 this.type = options.type;
15662 this.comment = options.comment;
15663 this.wrappers = [];
15664 // for keyed each blocks
15665 this.key = options.key;
15666 this.first = null;
15667 this.bindings = options.bindings;
15668 this.chunks = {
15669 declarations: [],
15670 init: [],
15671 create: [],
15672 claim: [],
15673 hydrate: [],
15674 mount: [],
15675 measure: [],
15676 fix: [],
15677 animate: [],
15678 intro: [],
15679 update: [],
15680 outro: [],
15681 destroy: [],
15682 };
15683 this.has_animation = false;
15684 this.has_intro_method = false; // a block could have an intro method but not intro transitions, e.g. if a sibling block has intros
15685 this.has_outro_method = false;
15686 this.outros = 0;
15687 this.get_unique_name = this.renderer.component.get_unique_name_maker();
15688 this.aliases = new Map();
15689 if (this.key)
15690 this.aliases.set('key', this.get_unique_name('key'));
15691 }
15692 assign_variable_names() {
15693 const seen = new Set();
15694 const dupes = new Set();
15695 let i = this.wrappers.length;
15696 while (i--) {
15697 const wrapper = this.wrappers[i];
15698 if (!wrapper.var)
15699 continue;
15700 if (seen.has(wrapper.var.name)) {
15701 dupes.add(wrapper.var.name);
15702 }
15703 seen.add(wrapper.var.name);
15704 }
15705 const counts = new Map();
15706 i = this.wrappers.length;
15707 while (i--) {
15708 const wrapper = this.wrappers[i];
15709 if (!wrapper.var)
15710 continue;
15711 let suffix = '';
15712 if (dupes.has(wrapper.var.name)) {
15713 const i = counts.get(wrapper.var.name) || 0;
15714 counts.set(wrapper.var.name, i + 1);
15715 suffix = i;
15716 }
15717 wrapper.var.name = this.get_unique_name(wrapper.var.name + suffix).name;
15718 }
15719 }
15720 add_dependencies(dependencies) {
15721 dependencies.forEach(dependency => {
15722 this.dependencies.add(dependency);
15723 });
15724 this.has_update_method = true;
15725 if (this.parent) {
15726 this.parent.add_dependencies(dependencies);
15727 }
15728 }
15729 add_element(id, render_statement, claim_statement, parent_node, no_detach) {
15730 this.add_variable(id);
15731 this.chunks.create.push(b `${id} = ${render_statement};`);
15732 if (this.renderer.options.hydratable) {
15733 this.chunks.claim.push(b `${id} = ${claim_statement || render_statement};`);
15734 }
15735 if (parent_node) {
15736 this.chunks.mount.push(b `@append(${parent_node}, ${id});`);
15737 if (is_head(parent_node) && !no_detach)
15738 this.chunks.destroy.push(b `@detach(${id});`);
15739 }
15740 else {
15741 this.chunks.mount.push(b `@insert(#target, ${id}, #anchor);`);
15742 if (!no_detach)
15743 this.chunks.destroy.push(b `if (detaching) @detach(${id});`);
15744 }
15745 }
15746 add_intro(local) {
15747 this.has_intros = this.has_intro_method = true;
15748 if (!local && this.parent)
15749 this.parent.add_intro();
15750 }
15751 add_outro(local) {
15752 this.has_outros = this.has_outro_method = true;
15753 this.outros += 1;
15754 if (!local && this.parent)
15755 this.parent.add_outro();
15756 }
15757 add_animation() {
15758 this.has_animation = true;
15759 }
15760 add_variable(id, init) {
15761 if (this.variables.has(id.name)) {
15762 throw new Error(`Variable '${id.name}' already initialised with a different value`);
15763 }
15764 this.variables.set(id.name, { id, init });
15765 }
15766 alias(name) {
15767 if (!this.aliases.has(name)) {
15768 this.aliases.set(name, this.get_unique_name(name));
15769 }
15770 return this.aliases.get(name);
15771 }
15772 child(options) {
15773 return new Block$1(Object.assign({}, this, { key: null }, options, { parent: this }));
15774 }
15775 get_contents(key) {
15776 const { dev } = this.renderer.options;
15777 if (this.has_outros) {
15778 this.add_variable({ type: 'Identifier', name: '#current' });
15779 if (this.chunks.intro.length > 0) {
15780 this.chunks.intro.push(b `#current = true;`);
15781 this.chunks.mount.push(b `#current = true;`);
15782 }
15783 if (this.chunks.outro.length > 0) {
15784 this.chunks.outro.push(b `#current = false;`);
15785 }
15786 }
15787 if (this.autofocus) {
15788 this.chunks.mount.push(b `${this.autofocus}.focus();`);
15789 }
15790 this.render_listeners();
15791 const properties = {};
15792 const noop = x `@noop`;
15793 properties.key = key;
15794 if (this.first) {
15795 properties.first = x `null`;
15796 this.chunks.hydrate.push(b `this.first = ${this.first};`);
15797 }
15798 if (this.chunks.create.length === 0 && this.chunks.hydrate.length === 0) {
15799 properties.create = noop;
15800 }
15801 else {
15802 const hydrate = this.chunks.hydrate.length > 0 && (this.renderer.options.hydratable
15803 ? b `this.h();`
15804 : this.chunks.hydrate);
15805 properties.create = x `function #create() {
15806 ${this.chunks.create}
15807 ${hydrate}
15808 }`;
15809 }
15810 if (this.renderer.options.hydratable || this.chunks.claim.length > 0) {
15811 if (this.chunks.claim.length === 0 && this.chunks.hydrate.length === 0) {
15812 properties.claim = noop;
15813 }
15814 else {
15815 properties.claim = x `function #claim(#nodes) {
15816 ${this.chunks.claim}
15817 ${this.renderer.options.hydratable && this.chunks.hydrate.length > 0 && b `this.h();`}
15818 }`;
15819 }
15820 }
15821 if (this.renderer.options.hydratable && this.chunks.hydrate.length > 0) {
15822 properties.hydrate = x `function #hydrate() {
15823 ${this.chunks.hydrate}
15824 }`;
15825 }
15826 if (this.chunks.mount.length === 0) {
15827 properties.mount = noop;
15828 }
15829 else if (this.event_listeners.length === 0) {
15830 properties.mount = x `function #mount(#target, #anchor) {
15831 ${this.chunks.mount}
15832 }`;
15833 }
15834 else {
15835 properties.mount = x `function #mount(#target, #anchor) {
15836 ${this.chunks.mount}
15837 }`;
15838 }
15839 if (this.has_update_method || this.maintain_context) {
15840 if (this.chunks.update.length === 0 && !this.maintain_context) {
15841 properties.update = noop;
15842 }
15843 else {
15844 const ctx = this.maintain_context ? x `#new_ctx` : x `#ctx`;
15845 let dirty = { type: 'Identifier', name: '#dirty' };
15846 if (!this.renderer.context_overflow && !this.parent) {
15847 dirty = { type: 'ArrayPattern', elements: [dirty] };
15848 }
15849 properties.update = x `function #update(${ctx}, ${dirty}) {
15850 ${this.maintain_context && b `#ctx = ${ctx};`}
15851 ${this.chunks.update}
15852 }`;
15853 }
15854 }
15855 if (this.has_animation) {
15856 properties.measure = x `function #measure() {
15857 ${this.chunks.measure}
15858 }`;
15859 properties.fix = x `function #fix() {
15860 ${this.chunks.fix}
15861 }`;
15862 properties.animate = x `function #animate() {
15863 ${this.chunks.animate}
15864 }`;
15865 }
15866 if (this.has_intro_method || this.has_outro_method) {
15867 if (this.chunks.intro.length === 0) {
15868 properties.intro = noop;
15869 }
15870 else {
15871 properties.intro = x `function #intro(#local) {
15872 ${this.has_outros && b `if (#current) return;`}
15873 ${this.chunks.intro}
15874 }`;
15875 }
15876 if (this.chunks.outro.length === 0) {
15877 properties.outro = noop;
15878 }
15879 else {
15880 properties.outro = x `function #outro(#local) {
15881 ${this.chunks.outro}
15882 }`;
15883 }
15884 }
15885 if (this.chunks.destroy.length === 0) {
15886 properties.destroy = noop;
15887 }
15888 else {
15889 properties.destroy = x `function #destroy(detaching) {
15890 ${this.chunks.destroy}
15891 }`;
15892 }
15893 if (!this.renderer.component.compile_options.dev) {
15894 // allow shorthand names
15895 for (const name in properties) {
15896 const property = properties[name];
15897 if (property)
15898 property.id = null;
15899 }
15900 }
15901 const return_value = x `{
15902 key: ${properties.key},
15903 first: ${properties.first},
15904 c: ${properties.create},
15905 l: ${properties.claim},
15906 h: ${properties.hydrate},
15907 m: ${properties.mount},
15908 p: ${properties.update},
15909 r: ${properties.measure},
15910 f: ${properties.fix},
15911 a: ${properties.animate},
15912 i: ${properties.intro},
15913 o: ${properties.outro},
15914 d: ${properties.destroy}
15915 }`;
15916 const block = dev && this.get_unique_name('block');
15917 const body = b `
15918 ${this.chunks.declarations}
15919
15920 ${Array.from(this.variables.values()).map(({ id, init }) => {
15921 return init
15922 ? b `let ${id} = ${init}`
15923 : b `let ${id}`;
15924 })}
15925
15926 ${this.chunks.init}
15927
15928 ${dev
15929 ? b `
15930 const ${block} = ${return_value};
15931 @dispatch_dev("SvelteRegisterBlock", {
15932 block: ${block},
15933 id: ${this.name || 'create_fragment'}.name,
15934 type: "${this.type}",
15935 source: "${this.comment ? this.comment.replace(/"/g, '\\"') : ''}",
15936 ctx: #ctx
15937 });
15938 return ${block};`
15939 : b `
15940 return ${return_value};`}
15941 `;
15942 return body;
15943 }
15944 has_content() {
15945 return !!this.first ||
15946 this.event_listeners.length > 0 ||
15947 this.chunks.intro.length > 0 ||
15948 this.chunks.outro.length > 0 ||
15949 this.chunks.create.length > 0 ||
15950 this.chunks.hydrate.length > 0 ||
15951 this.chunks.claim.length > 0 ||
15952 this.chunks.mount.length > 0 ||
15953 this.chunks.update.length > 0 ||
15954 this.chunks.destroy.length > 0 ||
15955 this.has_animation;
15956 }
15957 render() {
15958 const key = this.key && this.get_unique_name('key');
15959 const args = [x `#ctx`];
15960 if (key)
15961 args.unshift(key);
15962 const fn = b `function ${this.name}(${args}) {
15963 ${this.get_contents(key)}
15964 }`;
15965 return this.comment
15966 ? b `
15967 // ${this.comment}
15968 ${fn}`
15969 : fn;
15970 }
15971 render_listeners(chunk = '') {
15972 if (this.event_listeners.length > 0) {
15973 this.add_variable({ type: 'Identifier', name: '#mounted' });
15974 this.chunks.destroy.push(b `#mounted = false`);
15975 const dispose = {
15976 type: 'Identifier',
15977 name: `#dispose${chunk}`
15978 };
15979 this.add_variable(dispose);
15980 if (this.event_listeners.length === 1) {
15981 this.chunks.mount.push(b `
15982 if (!#mounted) {
15983 ${dispose} = ${this.event_listeners[0]};
15984 #mounted = true;
15985 }
15986 `);
15987 this.chunks.destroy.push(b `${dispose}();`);
15988 }
15989 else {
15990 this.chunks.mount.push(b `
15991 if (!#mounted) {
15992 ${dispose} = [
15993 ${this.event_listeners}
15994 ];
15995 #mounted = true;
15996 }
15997 `);
15998 this.chunks.destroy.push(b `@run_all(${dispose});`);
15999 }
16000 }
16001 }
16002 }
16003
16004 class Wrapper {
16005 constructor(renderer, block, parent, node) {
16006 this.node = node;
16007 // make these non-enumerable so that they can be logged sensibly
16008 // (TODO in dev only?)
16009 Object.defineProperties(this, {
16010 renderer: {
16011 value: renderer
16012 },
16013 parent: {
16014 value: parent
16015 }
16016 });
16017 this.can_use_innerhtml = !renderer.options.hydratable;
16018 this.is_static_content = !renderer.options.hydratable;
16019 block.wrappers.push(this);
16020 }
16021 cannot_use_innerhtml() {
16022 this.can_use_innerhtml = false;
16023 if (this.parent)
16024 this.parent.cannot_use_innerhtml();
16025 }
16026 not_static_content() {
16027 this.is_static_content = false;
16028 if (this.parent)
16029 this.parent.not_static_content();
16030 }
16031 get_or_create_anchor(block, parent_node, parent_nodes) {
16032 // TODO use this in EachBlock and IfBlock — tricky because
16033 // children need to be created first
16034 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
16035 const anchor = needs_anchor
16036 ? block.get_unique_name(`${this.var.name}_anchor`)
16037 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16038 if (needs_anchor) {
16039 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16040 }
16041 return anchor;
16042 }
16043 get_update_mount_node(anchor) {
16044 return ((this.parent && this.parent.is_dom_node())
16045 ? this.parent.var
16046 : x `${anchor}.parentNode`);
16047 }
16048 is_dom_node() {
16049 return (this.node.type === 'Element' ||
16050 this.node.type === 'Text' ||
16051 this.node.type === 'MustacheTag');
16052 }
16053 render(_block, _parent_node, _parent_nodes) {
16054 throw Error('Wrapper class is not renderable');
16055 }
16056 }
16057
16058 function create_debugging_comment(node, component) {
16059 const { locate, source } = component;
16060 let c = node.start;
16061 if (node.type === 'ElseBlock') {
16062 while (source[c - 1] !== '{')
16063 c -= 1;
16064 while (source[c - 1] === '{')
16065 c -= 1;
16066 }
16067 let d;
16068 if (node.type === 'InlineComponent' || node.type === 'Element') {
16069 if (node.children.length) {
16070 d = node.children[0].start;
16071 while (source[d - 1] !== '>')
16072 d -= 1;
16073 }
16074 else {
16075 d = node.start;
16076 while (source[d] !== '>')
16077 d += 1;
16078 d += 1;
16079 }
16080 }
16081 else if (node.type === 'Text' || node.type === 'Comment') {
16082 d = node.end;
16083 }
16084 else {
16085 // @ts-ignore
16086 d = node.expression ? node.expression.node.end : c;
16087 while (source[d] !== '}')
16088 d += 1;
16089 while (source[d] === '}')
16090 d += 1;
16091 }
16092 const start = locate(c);
16093 const loc = `(${start.line}:${start.column})`;
16094 return `${loc} ${source.slice(c, d)}`.replace(/\s/g, ' ');
16095 }
16096
16097 class AwaitBlockBranch extends Wrapper {
16098 constructor(status, renderer, block, parent, node, strip_whitespace, next_sibling) {
16099 super(renderer, block, parent, node);
16100 this.var = null;
16101 this.status = status;
16102 this.block = block.child({
16103 comment: create_debugging_comment(node, this.renderer.component),
16104 name: this.renderer.component.get_unique_name(`create_${status}_block`),
16105 type: status
16106 });
16107 this.add_context(parent.node[status + '_node'], parent.node[status + '_contexts']);
16108 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16109 this.is_dynamic = this.block.dependencies.size > 0;
16110 }
16111 add_context(node, contexts) {
16112 if (!node)
16113 return;
16114 if (node.type === 'Identifier') {
16115 this.value = node.name;
16116 this.renderer.add_to_context(this.value, true);
16117 }
16118 else {
16119 contexts.forEach(context => {
16120 this.renderer.add_to_context(context.key.name, true);
16121 });
16122 this.value = this.block.parent.get_unique_name('value').name;
16123 this.value_contexts = contexts;
16124 this.renderer.add_to_context(this.value, true);
16125 this.is_destructured = true;
16126 }
16127 this.value_index = this.renderer.context_lookup.get(this.value).index;
16128 }
16129 render(block, parent_node, parent_nodes) {
16130 this.fragment.render(block, parent_node, parent_nodes);
16131 if (this.is_destructured) {
16132 this.render_destructure();
16133 }
16134 }
16135 render_destructure() {
16136 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}]`)};`);
16137 const get_context = this.block.renderer.component.get_unique_name(`get_${this.status}_context`);
16138 this.block.renderer.blocks.push(b `
16139 function ${get_context}(#ctx) {
16140 ${props}
16141 }
16142 `);
16143 this.block.chunks.declarations.push(b `${get_context}(#ctx)`);
16144 if (this.block.has_update_method) {
16145 this.block.chunks.update.push(b `${get_context}(#ctx)`);
16146 }
16147 }
16148 }
16149 class AwaitBlockWrapper extends Wrapper {
16150 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16151 super(renderer, block, parent, node);
16152 this.var = { type: 'Identifier', name: 'await_block' };
16153 this.cannot_use_innerhtml();
16154 this.not_static_content();
16155 block.add_dependencies(this.node.expression.dependencies);
16156 let is_dynamic = false;
16157 let has_intros = false;
16158 let has_outros = false;
16159 ['pending', 'then', 'catch'].forEach((status) => {
16160 const child = this.node[status];
16161 const branch = new AwaitBlockBranch(status, renderer, block, this, child, strip_whitespace, next_sibling);
16162 renderer.blocks.push(branch.block);
16163 if (branch.is_dynamic) {
16164 is_dynamic = true;
16165 // TODO should blocks update their own parents?
16166 block.add_dependencies(branch.block.dependencies);
16167 }
16168 if (branch.block.has_intros)
16169 has_intros = true;
16170 if (branch.block.has_outros)
16171 has_outros = true;
16172 this[status] = branch;
16173 });
16174 ['pending', 'then', 'catch'].forEach(status => {
16175 this[status].block.has_update_method = is_dynamic;
16176 this[status].block.has_intro_method = has_intros;
16177 this[status].block.has_outro_method = has_outros;
16178 });
16179 if (has_outros) {
16180 block.add_outro();
16181 }
16182 }
16183 render(block, parent_node, parent_nodes) {
16184 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
16185 const update_mount_node = this.get_update_mount_node(anchor);
16186 const snippet = this.node.expression.manipulate(block);
16187 const info = block.get_unique_name(`info`);
16188 const promise = block.get_unique_name(`promise`);
16189 block.add_variable(promise);
16190 block.maintain_context = true;
16191 const info_props = x `{
16192 ctx: #ctx,
16193 current: null,
16194 token: null,
16195 pending: ${this.pending.block.name},
16196 then: ${this.then.block.name},
16197 catch: ${this.catch.block.name},
16198 value: ${this.then.value_index},
16199 error: ${this.catch.value_index},
16200 blocks: ${this.pending.block.has_outro_method && x `[,,,]`}
16201 }`;
16202 block.chunks.init.push(b `
16203 let ${info} = ${info_props};
16204 `);
16205 block.chunks.init.push(b `
16206 @handle_promise(${promise} = ${snippet}, ${info});
16207 `);
16208 block.chunks.create.push(b `
16209 ${info}.block.c();
16210 `);
16211 if (parent_nodes && this.renderer.options.hydratable) {
16212 block.chunks.claim.push(b `
16213 ${info}.block.l(${parent_nodes});
16214 `);
16215 }
16216 const initial_mount_node = parent_node || '#target';
16217 const anchor_node = parent_node ? 'null' : '#anchor';
16218 const has_transitions = this.pending.block.has_intro_method || this.pending.block.has_outro_method;
16219 block.chunks.mount.push(b `
16220 ${info}.block.m(${initial_mount_node}, ${info}.anchor = ${anchor_node});
16221 ${info}.mount = () => ${update_mount_node};
16222 ${info}.anchor = ${anchor};
16223 `);
16224 if (has_transitions) {
16225 block.chunks.intro.push(b `@transition_in(${info}.block);`);
16226 }
16227 const dependencies = this.node.expression.dynamic_dependencies();
16228 if (dependencies.length > 0) {
16229 const condition = x `
16230 ${block.renderer.dirty(dependencies)} &&
16231 ${promise} !== (${promise} = ${snippet}) &&
16232 @handle_promise(${promise}, ${info})`;
16233 block.chunks.update.push(b `${info}.ctx = #ctx;`);
16234 if (this.pending.block.has_update_method) {
16235 block.chunks.update.push(b `
16236 if (${condition}) {
16237
16238 } else {
16239 const #child_ctx = #ctx.slice();
16240 ${this.then.value && b `#child_ctx[${this.then.value_index}] = ${info}.resolved;`}
16241 ${info}.block.p(#child_ctx, #dirty);
16242 }
16243 `);
16244 }
16245 else {
16246 block.chunks.update.push(b `
16247 ${condition}
16248 `);
16249 }
16250 }
16251 else {
16252 if (this.pending.block.has_update_method) {
16253 block.chunks.update.push(b `
16254 {
16255 const #child_ctx = #ctx.slice();
16256 ${this.then.value && b `#child_ctx[${this.then.value_index}] = ${info}.resolved;`}
16257 ${info}.block.p(#child_ctx, #dirty);
16258 }
16259 `);
16260 }
16261 }
16262 if (this.pending.block.has_outro_method) {
16263 block.chunks.outro.push(b `
16264 for (let #i = 0; #i < 3; #i += 1) {
16265 const block = ${info}.blocks[#i];
16266 @transition_out(block);
16267 }
16268 `);
16269 }
16270 block.chunks.destroy.push(b `
16271 ${info}.block.d(${parent_node ? null : 'detaching'});
16272 ${info}.token = null;
16273 ${info} = null;
16274 `);
16275 [this.pending, this.then, this.catch].forEach(branch => {
16276 branch.render(branch.block, null, x `#nodes`);
16277 });
16278 }
16279 }
16280
16281 const TRUE = x `true`;
16282 const FALSE = x `false`;
16283 class EventHandlerWrapper {
16284 constructor(node, parent) {
16285 this.node = node;
16286 this.parent = parent;
16287 if (!node.expression) {
16288 this.parent.renderer.add_to_context(node.handler_name.name);
16289 this.parent.renderer.component.partly_hoisted.push(b `
16290 function ${node.handler_name.name}(event) {
16291 @bubble($$self, event);
16292 }
16293 `);
16294 }
16295 }
16296 get_snippet(block) {
16297 const snippet = this.node.expression ? this.node.expression.manipulate(block) : block.renderer.reference(this.node.handler_name);
16298 if (this.node.reassigned) {
16299 block.maintain_context = true;
16300 return x `function () { if (@is_function(${snippet})) ${snippet}.apply(this, arguments); }`;
16301 }
16302 return snippet;
16303 }
16304 render(block, target) {
16305 let snippet = this.get_snippet(block);
16306 if (this.node.modifiers.has('preventDefault'))
16307 snippet = x `@prevent_default(${snippet})`;
16308 if (this.node.modifiers.has('stopPropagation'))
16309 snippet = x `@stop_propagation(${snippet})`;
16310 if (this.node.modifiers.has('self'))
16311 snippet = x `@self(${snippet})`;
16312 const args = [];
16313 const opts = ['passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod));
16314 if (opts.length) {
16315 args.push((opts.length === 1 && opts[0] === 'capture')
16316 ? TRUE
16317 : x `{ ${opts.map(opt => p `${opt}: true`)} }`);
16318 }
16319 else if (block.renderer.options.dev) {
16320 args.push(FALSE);
16321 }
16322 if (block.renderer.options.dev) {
16323 args.push(this.node.modifiers.has('preventDefault') ? TRUE : FALSE);
16324 args.push(this.node.modifiers.has('stopPropagation') ? TRUE : FALSE);
16325 }
16326 block.event_listeners.push(x `@listen(${target}, "${this.node.name}", ${snippet}, ${args})`);
16327 }
16328 }
16329
16330 function add_event_handlers(block, target, handlers) {
16331 handlers.forEach(handler => add_event_handler(block, target, handler));
16332 }
16333 function add_event_handler(block, target, handler) {
16334 handler.render(block, target);
16335 }
16336
16337 class BodyWrapper extends Wrapper {
16338 constructor(renderer, block, parent, node) {
16339 super(renderer, block, parent, node);
16340 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
16341 }
16342 render(block, _parent_node, _parent_nodes) {
16343 add_event_handlers(block, x `@_document.body`, this.handlers);
16344 }
16345 }
16346
16347 function add_to_set(a, b) {
16348 // @ts-ignore
16349 b.forEach(item => {
16350 a.add(item);
16351 });
16352 }
16353
16354 class DebugTagWrapper extends Wrapper {
16355 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
16356 super(renderer, block, parent, node);
16357 }
16358 render(block, _parent_node, _parent_nodes) {
16359 const { renderer } = this;
16360 const { component } = renderer;
16361 if (!renderer.options.dev)
16362 return;
16363 const { var_lookup } = component;
16364 const start = component.locate(this.node.start + 1);
16365 const end = { line: start.line, column: start.column + 6 };
16366 const loc = { start, end };
16367 const debug = {
16368 type: 'DebuggerStatement',
16369 loc
16370 };
16371 if (this.node.expressions.length === 0) {
16372 // Debug all
16373 block.chunks.create.push(debug);
16374 block.chunks.update.push(debug);
16375 }
16376 else {
16377 const log = {
16378 type: 'Identifier',
16379 name: 'log',
16380 loc
16381 };
16382 const dependencies = new Set();
16383 this.node.expressions.forEach(expression => {
16384 add_to_set(dependencies, expression.dependencies);
16385 });
16386 const contextual_identifiers = this.node.expressions
16387 .filter(e => {
16388 const variable = var_lookup.get(e.node.name);
16389 return !(variable && variable.hoistable);
16390 })
16391 .map(e => e.node.name);
16392 const logged_identifiers = this.node.expressions.map(e => p `${e.node.name}`);
16393 const debug_statements = b `
16394 ${contextual_identifiers.map(name => b `const ${name} = ${renderer.reference(name)};`)}
16395 @_console.${log}({ ${logged_identifiers} });
16396 debugger;`;
16397 if (dependencies.size) {
16398 const condition = renderer.dirty(Array.from(dependencies));
16399 block.chunks.update.push(b `
16400 if (${condition}) {
16401 ${debug_statements}
16402 }
16403 `);
16404 }
16405 block.chunks.create.push(b `{
16406 ${debug_statements}
16407 }`);
16408 }
16409 }
16410 }
16411
16412 class ElseBlockWrapper extends Wrapper {
16413 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16414 super(renderer, block, parent, node);
16415 this.var = null;
16416 this.block = block.child({
16417 comment: create_debugging_comment(node, this.renderer.component),
16418 name: this.renderer.component.get_unique_name(`create_else_block`),
16419 type: 'else'
16420 });
16421 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16422 this.is_dynamic = this.block.dependencies.size > 0;
16423 }
16424 }
16425 class EachBlockWrapper extends Wrapper {
16426 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16427 super(renderer, block, parent, node);
16428 this.updates = [];
16429 this.var = { type: 'Identifier', name: 'each' };
16430 this.cannot_use_innerhtml();
16431 this.not_static_content();
16432 const { dependencies } = node.expression;
16433 block.add_dependencies(dependencies);
16434 this.node.contexts.forEach(context => {
16435 renderer.add_to_context(context.key.name, true);
16436 });
16437 this.block = block.child({
16438 comment: create_debugging_comment(this.node, this.renderer.component),
16439 name: renderer.component.get_unique_name('create_each_block'),
16440 type: 'each',
16441 // @ts-ignore todo: probably error
16442 key: node.key,
16443 bindings: new Map(block.bindings)
16444 });
16445 // TODO this seems messy
16446 this.block.has_animation = this.node.has_animation;
16447 this.index_name = this.node.index
16448 ? { type: 'Identifier', name: this.node.index }
16449 : renderer.component.get_unique_name(`${this.node.context}_index`);
16450 const fixed_length = node.expression.node.type === 'ArrayExpression' &&
16451 node.expression.node.elements.every(element => element.type !== 'SpreadElement')
16452 ? node.expression.node.elements.length
16453 : null;
16454 // hack the sourcemap, so that if data is missing the bug
16455 // is easy to find
16456 let c = this.node.start + 2;
16457 while (renderer.component.source[c] !== 'e')
16458 c += 1;
16459 const start = renderer.component.locate(c);
16460 const end = { line: start.line, column: start.column + 4 };
16461 const length = {
16462 type: 'Identifier',
16463 name: 'length',
16464 loc: { start, end }
16465 };
16466 const each_block_value = renderer.component.get_unique_name(`${this.var.name}_value`);
16467 const iterations = block.get_unique_name(`${this.var.name}_blocks`);
16468 renderer.add_to_context(each_block_value.name, true);
16469 renderer.add_to_context(this.index_name.name, true);
16470 this.vars = {
16471 create_each_block: this.block.name,
16472 each_block_value,
16473 get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`),
16474 iterations,
16475 // optimisation for array literal
16476 fixed_length,
16477 data_length: fixed_length === null ? x `${each_block_value}.${length}` : fixed_length,
16478 view_length: fixed_length === null ? x `${iterations}.length` : fixed_length
16479 };
16480 const store = node.expression.node.type === 'Identifier' &&
16481 node.expression.node.name[0] === '$'
16482 ? node.expression.node.name.slice(1)
16483 : null;
16484 node.contexts.forEach(prop => {
16485 this.block.bindings.set(prop.key.name, {
16486 object: this.vars.each_block_value,
16487 property: this.index_name,
16488 modifier: prop.modifier,
16489 snippet: prop.modifier(x `${this.vars.each_block_value}[${this.index_name}]`),
16490 store,
16491 tail: prop.modifier(x `[${this.index_name}]`)
16492 });
16493 });
16494 if (this.node.index) {
16495 this.block.get_unique_name(this.node.index); // this prevents name collisions (#1254)
16496 }
16497 renderer.blocks.push(this.block);
16498 this.fragment = new FragmentWrapper(renderer, this.block, node.children, this, strip_whitespace, next_sibling);
16499 if (this.node.else) {
16500 this.else = new ElseBlockWrapper(renderer, block, this, this.node.else, strip_whitespace, next_sibling);
16501 renderer.blocks.push(this.else.block);
16502 if (this.else.is_dynamic) {
16503 this.block.add_dependencies(this.else.block.dependencies);
16504 }
16505 }
16506 block.add_dependencies(this.block.dependencies);
16507 if (this.block.has_outros || (this.else && this.else.block.has_outros)) {
16508 block.add_outro();
16509 }
16510 }
16511 render(block, parent_node, parent_nodes) {
16512 if (this.fragment.nodes.length === 0)
16513 return;
16514 const { renderer } = this;
16515 const { component } = renderer;
16516 const needs_anchor = this.next
16517 ? !this.next.is_dom_node() :
16518 !parent_node || !this.parent.is_dom_node();
16519 this.context_props = this.node.contexts.map(prop => b `child_ctx[${renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x `list[i]`)};`);
16520 if (this.node.has_binding)
16521 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`);
16522 if (this.node.has_binding || this.node.index)
16523 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`);
16524 const snippet = this.node.expression.manipulate(block);
16525 block.chunks.init.push(b `let ${this.vars.each_block_value} = ${snippet};`);
16526 if (this.renderer.options.dev) {
16527 block.chunks.init.push(b `@validate_each_argument(${this.vars.each_block_value});`);
16528 }
16529 // TODO which is better — Object.create(array) or array.slice()?
16530 renderer.blocks.push(b `
16531 function ${this.vars.get_each_context}(#ctx, list, i) {
16532 const child_ctx = #ctx.slice();
16533 ${this.context_props}
16534 return child_ctx;
16535 }
16536 `);
16537 const initial_anchor_node = { type: 'Identifier', name: parent_node ? 'null' : '#anchor' };
16538 const initial_mount_node = parent_node || { type: 'Identifier', name: '#target' };
16539 const update_anchor_node = needs_anchor
16540 ? block.get_unique_name(`${this.var.name}_anchor`)
16541 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16542 const update_mount_node = this.get_update_mount_node(update_anchor_node);
16543 const args = {
16544 block,
16545 parent_node,
16546 parent_nodes,
16547 snippet,
16548 initial_anchor_node,
16549 initial_mount_node,
16550 update_anchor_node,
16551 update_mount_node
16552 };
16553 const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
16554 this.node.expression.dynamic_dependencies().forEach((dependency) => {
16555 all_dependencies.add(dependency);
16556 });
16557 this.dependencies = all_dependencies;
16558 if (this.node.key) {
16559 this.render_keyed(args);
16560 }
16561 else {
16562 this.render_unkeyed(args);
16563 }
16564 if (this.block.has_intro_method || this.block.has_outro_method) {
16565 block.chunks.intro.push(b `
16566 for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) {
16567 @transition_in(${this.vars.iterations}[#i]);
16568 }
16569 `);
16570 }
16571 if (needs_anchor) {
16572 block.add_element(update_anchor_node, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16573 }
16574 if (this.else) {
16575 const each_block_else = component.get_unique_name(`${this.var.name}_else`);
16576 block.chunks.init.push(b `let ${each_block_else} = null;`);
16577 // TODO neaten this up... will end up with an empty line in the block
16578 block.chunks.init.push(b `
16579 if (!${this.vars.data_length}) {
16580 ${each_block_else} = ${this.else.block.name}(#ctx);
16581 }
16582 `);
16583 block.chunks.create.push(b `
16584 if (${each_block_else}) {
16585 ${each_block_else}.c();
16586 }
16587 `);
16588 if (this.renderer.options.hydratable) {
16589 block.chunks.claim.push(b `
16590 if (${each_block_else}) {
16591 ${each_block_else}.l(${parent_nodes});
16592 }
16593 `);
16594 }
16595 block.chunks.mount.push(b `
16596 if (${each_block_else}) {
16597 ${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node});
16598 }
16599 `);
16600 if (this.else.block.has_update_method) {
16601 this.updates.push(b `
16602 if (!${this.vars.data_length} && ${each_block_else}) {
16603 ${each_block_else}.p(#ctx, #dirty);
16604 } else if (!${this.vars.data_length}) {
16605 ${each_block_else} = ${this.else.block.name}(#ctx);
16606 ${each_block_else}.c();
16607 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16608 } else if (${each_block_else}) {
16609 ${each_block_else}.d(1);
16610 ${each_block_else} = null;
16611 }
16612 `);
16613 }
16614 else {
16615 this.updates.push(b `
16616 if (${this.vars.data_length}) {
16617 if (${each_block_else}) {
16618 ${each_block_else}.d(1);
16619 ${each_block_else} = null;
16620 }
16621 } else if (!${each_block_else}) {
16622 ${each_block_else} = ${this.else.block.name}(#ctx);
16623 ${each_block_else}.c();
16624 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16625 }
16626 `);
16627 }
16628 block.chunks.destroy.push(b `
16629 if (${each_block_else}) ${each_block_else}.d(${parent_node ? '' : 'detaching'});
16630 `);
16631 }
16632 if (this.updates.length) {
16633 block.chunks.update.push(b `
16634 if (${block.renderer.dirty(Array.from(all_dependencies))}) {
16635 ${this.updates}
16636 }
16637 `);
16638 }
16639 this.fragment.render(this.block, null, x `#nodes`);
16640 if (this.else) {
16641 this.else.fragment.render(this.else.block, null, x `#nodes`);
16642 }
16643 }
16644 render_keyed({ block, parent_node, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
16645 const { create_each_block, iterations, data_length, view_length } = this.vars;
16646 const get_key = block.get_unique_name('get_key');
16647 const lookup = block.get_unique_name(`${this.var.name}_lookup`);
16648 block.add_variable(iterations, x `[]`);
16649 block.add_variable(lookup, x `new @_Map()`);
16650 if (this.fragment.nodes[0].is_dom_node()) {
16651 this.block.first = this.fragment.nodes[0].var;
16652 }
16653 else {
16654 this.block.first = this.block.get_unique_name('first');
16655 this.block.add_element(this.block.first, x `@empty()`, parent_nodes && x `@empty()`, null);
16656 }
16657 block.chunks.init.push(b `
16658 const ${get_key} = #ctx => ${this.node.key.manipulate(block)};
16659
16660 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
16661 for (let #i = 0; #i < ${data_length}; #i += 1) {
16662 let child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
16663 let key = ${get_key}(child_ctx);
16664 ${lookup}.set(key, ${iterations}[#i] = ${create_each_block}(key, child_ctx));
16665 }
16666 `);
16667 block.chunks.create.push(b `
16668 for (let #i = 0; #i < ${view_length}; #i += 1) {
16669 ${iterations}[#i].c();
16670 }
16671 `);
16672 if (parent_nodes && this.renderer.options.hydratable) {
16673 block.chunks.claim.push(b `
16674 for (let #i = 0; #i < ${view_length}; #i += 1) {
16675 ${iterations}[#i].l(${parent_nodes});
16676 }
16677 `);
16678 }
16679 block.chunks.mount.push(b `
16680 for (let #i = 0; #i < ${view_length}; #i += 1) {
16681 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
16682 }
16683 `);
16684 const dynamic = this.block.has_update_method;
16685 const destroy = this.node.has_animation
16686 ? (this.block.has_outros
16687 ? `@fix_and_outro_and_destroy_block`
16688 : `@fix_and_destroy_block`)
16689 : this.block.has_outros
16690 ? `@outro_and_destroy_block`
16691 : `@destroy_block`;
16692 if (this.dependencies.size) {
16693 this.updates.push(b `
16694 const ${this.vars.each_block_value} = ${snippet};
16695 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
16696
16697 ${this.block.has_outros && b `@group_outros();`}
16698 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`}
16699 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
16700 ${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});
16701 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
16702 ${this.block.has_outros && b `@check_outros();`}
16703 `);
16704 }
16705 if (this.block.has_outros) {
16706 block.chunks.outro.push(b `
16707 for (let #i = 0; #i < ${view_length}; #i += 1) {
16708 @transition_out(${iterations}[#i]);
16709 }
16710 `);
16711 }
16712 block.chunks.destroy.push(b `
16713 for (let #i = 0; #i < ${view_length}; #i += 1) {
16714 ${iterations}[#i].d(${parent_node ? null : 'detaching'});
16715 }
16716 `);
16717 }
16718 render_unkeyed({ block, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
16719 const { create_each_block, iterations, fixed_length, data_length, view_length } = this.vars;
16720 block.chunks.init.push(b `
16721 let ${iterations} = [];
16722
16723 for (let #i = 0; #i < ${data_length}; #i += 1) {
16724 ${iterations}[#i] = ${create_each_block}(${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i));
16725 }
16726 `);
16727 block.chunks.create.push(b `
16728 for (let #i = 0; #i < ${view_length}; #i += 1) {
16729 ${iterations}[#i].c();
16730 }
16731 `);
16732 if (parent_nodes && this.renderer.options.hydratable) {
16733 block.chunks.claim.push(b `
16734 for (let #i = 0; #i < ${view_length}; #i += 1) {
16735 ${iterations}[#i].l(${parent_nodes});
16736 }
16737 `);
16738 }
16739 block.chunks.mount.push(b `
16740 for (let #i = 0; #i < ${view_length}; #i += 1) {
16741 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
16742 }
16743 `);
16744 if (this.dependencies.size) {
16745 const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
16746 const for_loop_body = this.block.has_update_method
16747 ? b `
16748 if (${iterations}[#i]) {
16749 ${iterations}[#i].p(child_ctx, #dirty);
16750 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
16751 } else {
16752 ${iterations}[#i] = ${create_each_block}(child_ctx);
16753 ${iterations}[#i].c();
16754 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
16755 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16756 }
16757 `
16758 : has_transitions
16759 ? b `
16760 if (${iterations}[#i]) {
16761 @transition_in(${this.vars.iterations}[#i], 1);
16762 } else {
16763 ${iterations}[#i] = ${create_each_block}(child_ctx);
16764 ${iterations}[#i].c();
16765 @transition_in(${this.vars.iterations}[#i], 1);
16766 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16767 }
16768 `
16769 : b `
16770 if (!${iterations}[#i]) {
16771 ${iterations}[#i] = ${create_each_block}(child_ctx);
16772 ${iterations}[#i].c();
16773 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
16774 }
16775 `;
16776 const start = this.block.has_update_method ? 0 : `#old_length`;
16777 let remove_old_blocks;
16778 if (this.block.has_outros) {
16779 const out = block.get_unique_name('out');
16780 block.chunks.init.push(b `
16781 const ${out} = i => @transition_out(${iterations}[i], 1, 1, () => {
16782 ${iterations}[i] = null;
16783 });
16784 `);
16785 remove_old_blocks = b `
16786 @group_outros();
16787 for (#i = ${data_length}; #i < ${view_length}; #i += 1) {
16788 ${out}(#i);
16789 }
16790 @check_outros();
16791 `;
16792 }
16793 else {
16794 remove_old_blocks = b `
16795 for (${this.block.has_update_method ? null : x `#i = ${data_length}`}; #i < ${this.block.has_update_method ? view_length : '#old_length'}; #i += 1) {
16796 ${iterations}[#i].d(1);
16797 }
16798 ${!fixed_length && b `${view_length} = ${data_length};`}
16799 `;
16800 }
16801 // We declare `i` as block scoped here, as the `remove_old_blocks` code
16802 // may rely on continuing where this iteration stopped.
16803 const update = b `
16804 ${!this.block.has_update_method && b `const #old_length = ${this.vars.each_block_value}.length;`}
16805 ${this.vars.each_block_value} = ${snippet};
16806 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
16807
16808 let #i;
16809 for (#i = ${start}; #i < ${data_length}; #i += 1) {
16810 const child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
16811
16812 ${for_loop_body}
16813 }
16814
16815 ${remove_old_blocks}
16816 `;
16817 this.updates.push(update);
16818 }
16819 if (this.block.has_outros) {
16820 block.chunks.outro.push(b `
16821 ${iterations} = ${iterations}.filter(@_Boolean);
16822 for (let #i = 0; #i < ${view_length}; #i += 1) {
16823 @transition_out(${iterations}[#i]);
16824 }
16825 `);
16826 }
16827 block.chunks.destroy.push(b `@destroy_each(${iterations}, detaching);`);
16828 }
16829 }
16830
16831 function string_literal(data) {
16832 return {
16833 type: 'Literal',
16834 value: data
16835 };
16836 }
16837 const escaped = {
16838 '"': '&quot;',
16839 "'": '&#39;',
16840 '&': '&amp;',
16841 '<': '&lt;',
16842 '>': '&gt;',
16843 };
16844 function escape_html(html) {
16845 return String(html).replace(/["'&<>]/g, match => escaped[match]);
16846 }
16847 function escape_template(str) {
16848 return str.replace(/(\${|`|\\)/g, '\\$1');
16849 }
16850
16851 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(' ');
16852 const svg_attribute_lookup = new Map();
16853 svg_attributes.forEach(name => {
16854 svg_attribute_lookup.set(name.toLowerCase(), name);
16855 });
16856 function fix_attribute_casing(name) {
16857 name = name.toLowerCase();
16858 return svg_attribute_lookup.get(name) || name;
16859 }
16860
16861 const html = 'http://www.w3.org/1999/xhtml';
16862 const mathml = 'http://www.w3.org/1998/Math/MathML';
16863 const svg = 'http://www.w3.org/2000/svg';
16864 const xlink = 'http://www.w3.org/1999/xlink';
16865 const xml = 'http://www.w3.org/XML/1998/namespace';
16866 const xmlns = 'http://www.w3.org/2000/xmlns';
16867 const valid_namespaces = [
16868 'html',
16869 'mathml',
16870 'svg',
16871 'xlink',
16872 'xml',
16873 'xmlns',
16874 html,
16875 mathml,
16876 svg,
16877 xlink,
16878 xml,
16879 xmlns,
16880 ];
16881 const namespaces = { html, mathml, svg, xlink, xml, xmlns };
16882
16883 class AttributeWrapper {
16884 constructor(parent, block, node) {
16885 this.node = node;
16886 this.parent = parent;
16887 if (node.dependencies.size > 0) {
16888 parent.cannot_use_innerhtml();
16889 parent.not_static_content();
16890 block.add_dependencies(node.dependencies);
16891 // special case — <option value={foo}> — see below
16892 if (this.parent.node.name === 'option' && node.name === 'value') {
16893 let select = this.parent;
16894 while (select && (select.node.type !== 'Element' || select.node.name !== 'select'))
16895 // @ts-ignore todo: doublecheck this, but looks to be correct
16896 select = select.parent;
16897 if (select && select.select_binding_dependencies) {
16898 select.select_binding_dependencies.forEach(prop => {
16899 this.node.dependencies.forEach((dependency) => {
16900 this.parent.renderer.component.indirect_dependencies.get(prop).add(dependency);
16901 });
16902 });
16903 }
16904 }
16905 }
16906 }
16907 is_indirectly_bound_value() {
16908 const element = this.parent;
16909 const name = fix_attribute_casing(this.node.name);
16910 return name === 'value' &&
16911 (element.node.name === 'option' || // TODO check it's actually bound
16912 (element.node.name === 'input' &&
16913 element.node.bindings.some((binding) => /checked|group/.test(binding.name))));
16914 }
16915 render(block) {
16916 const element = this.parent;
16917 const name = fix_attribute_casing(this.node.name);
16918 const metadata = this.get_metadata();
16919 const is_indirectly_bound_value = this.is_indirectly_bound_value();
16920 const property_name = is_indirectly_bound_value
16921 ? '__value'
16922 : metadata && metadata.property_name;
16923 // xlink is a special case... we could maybe extend this to generic
16924 // namespaced attributes but I'm not sure that's applicable in
16925 // HTML5?
16926 const method = /-/.test(element.node.name)
16927 ? '@set_custom_element_data'
16928 : name.slice(0, 6) === 'xlink:'
16929 ? '@xlink_attr'
16930 : '@attr';
16931 const is_legacy_input_type = element.renderer.component.compile_options.legacy && name === 'type' && this.parent.node.name === 'input';
16932 const dependencies = this.node.get_dependencies();
16933 const value = this.get_value(block);
16934 const is_src = this.node.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
16935 const is_select_value_attribute = name === 'value' && element.node.name === 'select';
16936 const is_input_value = name === 'value' && element.node.name === 'input';
16937 const should_cache = is_src || this.node.should_cache() || is_select_value_attribute; // TODO is this necessary?
16938 const last = should_cache && block.get_unique_name(`${element.var.name}_${name.replace(/[^a-zA-Z_$]/g, '_')}_value`);
16939 if (should_cache)
16940 block.add_variable(last);
16941 let updater;
16942 const init = should_cache ? x `${last} = ${value}` : value;
16943 if (is_legacy_input_type) {
16944 block.chunks.hydrate.push(b `@set_input_type(${element.var}, ${init});`);
16945 updater = b `@set_input_type(${element.var}, ${should_cache ? last : value});`;
16946 }
16947 else if (is_select_value_attribute) {
16948 // annoying special case
16949 const is_multiple_select = element.node.get_static_attribute_value('multiple');
16950 if (is_multiple_select) {
16951 updater = b `@select_options(${element.var}, ${last});`;
16952 }
16953 else {
16954 updater = b `@select_option(${element.var}, ${last});`;
16955 }
16956 block.chunks.mount.push(b `
16957 ${last} = ${value};
16958 ${updater}
16959 `);
16960 }
16961 else if (is_src) {
16962 block.chunks.hydrate.push(b `if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${last});`);
16963 updater = b `${method}(${element.var}, "${name}", ${should_cache ? last : value});`;
16964 }
16965 else if (property_name) {
16966 block.chunks.hydrate.push(b `${element.var}.${property_name} = ${init};`);
16967 updater = block.renderer.options.dev
16968 ? b `@prop_dev(${element.var}, "${property_name}", ${should_cache ? last : value});`
16969 : b `${element.var}.${property_name} = ${should_cache ? last : value};`;
16970 }
16971 else {
16972 block.chunks.hydrate.push(b `${method}(${element.var}, "${name}", ${init});`);
16973 updater = b `${method}(${element.var}, "${name}", ${should_cache ? last : value});`;
16974 }
16975 if (dependencies.length > 0) {
16976 let condition = block.renderer.dirty(dependencies);
16977 if (should_cache) {
16978 condition = is_src
16979 ? x `${condition} && (${element.var}.src !== (${last} = ${value}))`
16980 : x `${condition} && (${last} !== (${last} = ${value}))`;
16981 }
16982 if (is_input_value) {
16983 const type = element.node.get_static_attribute_value('type');
16984 if (type === null || type === "" || type === "text" || type === "email" || type === "password") {
16985 condition = x `${condition} && ${element.var}.${property_name} !== ${should_cache ? last : value}`;
16986 }
16987 }
16988 if (block.has_outros) {
16989 condition = x `!#current || ${condition}`;
16990 }
16991 block.chunks.update.push(b `
16992 if (${condition}) {
16993 ${updater}
16994 }`);
16995 }
16996 // special case – autofocus. has to be handled in a bit of a weird way
16997 if (this.node.is_true && name === 'autofocus') {
16998 block.autofocus = element.var;
16999 }
17000 if (is_indirectly_bound_value) {
17001 const update_value = b `${element.var}.value = ${element.var}.__value;`;
17002 block.chunks.hydrate.push(update_value);
17003 if (this.node.get_dependencies().length > 0)
17004 block.chunks.update.push(update_value);
17005 }
17006 }
17007 get_metadata() {
17008 if (this.parent.node.namespace)
17009 return null;
17010 const metadata = attribute_lookup[fix_attribute_casing(this.node.name)];
17011 if (metadata && metadata.applies_to && !metadata.applies_to.includes(this.parent.node.name))
17012 return null;
17013 return metadata;
17014 }
17015 get_value(block) {
17016 if (this.node.is_true) {
17017 const metadata = this.get_metadata();
17018 if (metadata && boolean_attribute.has(metadata.property_name.toLowerCase())) {
17019 return x `true`;
17020 }
17021 return x `""`;
17022 }
17023 if (this.node.chunks.length === 0)
17024 return x `""`;
17025 // TODO some of this code is repeated in Tag.ts — would be good to
17026 // DRY it out if that's possible without introducing crazy indirection
17027 if (this.node.chunks.length === 1) {
17028 return this.node.chunks[0].type === 'Text'
17029 ? string_literal(this.node.chunks[0].data)
17030 : this.node.chunks[0].manipulate(block);
17031 }
17032 let value = this.node.name === 'class'
17033 ? this.get_class_name_text(block)
17034 : this.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17035 // '{foo} {bar}' — treat as string concatenation
17036 if (this.node.chunks[0].type !== 'Text') {
17037 value = x `"" + ${value}`;
17038 }
17039 return value;
17040 }
17041 get_class_name_text(block) {
17042 const scoped_css = this.node.chunks.some((chunk) => chunk.synthetic);
17043 const rendered = this.render_chunks(block);
17044 if (scoped_css && rendered.length === 2) {
17045 // we have a situation like class={possiblyUndefined}
17046 rendered[0] = x `@null_to_empty(${rendered[0]})`;
17047 }
17048 return rendered.reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17049 }
17050 render_chunks(block) {
17051 return this.node.chunks.map((chunk) => {
17052 if (chunk.type === 'Text') {
17053 return string_literal(chunk.data);
17054 }
17055 return chunk.manipulate(block);
17056 });
17057 }
17058 stringify() {
17059 if (this.node.is_true)
17060 return '';
17061 const value = this.node.chunks;
17062 if (value.length === 0)
17063 return `=""`;
17064 return `="${value.map(chunk => {
17065 return chunk.type === 'Text'
17066 ? chunk.data.replace(/"/g, '\\"')
17067 : `\${${chunk.manipulate()}}`;
17068 }).join('')}"`;
17069 }
17070 }
17071 // source: https://html.spec.whatwg.org/multipage/indices.html
17072 const attribute_lookup = {
17073 allowfullscreen: { property_name: 'allowFullscreen', applies_to: ['iframe'] },
17074 allowpaymentrequest: { property_name: 'allowPaymentRequest', applies_to: ['iframe'] },
17075 async: { applies_to: ['script'] },
17076 autofocus: { applies_to: ['button', 'input', 'keygen', 'select', 'textarea'] },
17077 autoplay: { applies_to: ['audio', 'video'] },
17078 checked: { applies_to: ['input'] },
17079 controls: { applies_to: ['audio', 'video'] },
17080 default: { applies_to: ['track'] },
17081 defer: { applies_to: ['script'] },
17082 disabled: {
17083 applies_to: [
17084 'button',
17085 'fieldset',
17086 'input',
17087 'keygen',
17088 'optgroup',
17089 'option',
17090 'select',
17091 'textarea',
17092 ],
17093 },
17094 formnovalidate: { property_name: 'formNoValidate', applies_to: ['button', 'input'] },
17095 hidden: {},
17096 indeterminate: { applies_to: ['input'] },
17097 ismap: { property_name: 'isMap', applies_to: ['img'] },
17098 loop: { applies_to: ['audio', 'bgsound', 'video'] },
17099 multiple: { applies_to: ['input', 'select'] },
17100 muted: { applies_to: ['audio', 'video'] },
17101 nomodule: { property_name: 'noModule', applies_to: ['script'] },
17102 novalidate: { property_name: 'noValidate', applies_to: ['form'] },
17103 open: { applies_to: ['details', 'dialog'] },
17104 playsinline: { property_name: 'playsInline', applies_to: ['video'] },
17105 readonly: { property_name: 'readOnly', applies_to: ['input', 'textarea'] },
17106 required: { applies_to: ['input', 'select', 'textarea'] },
17107 reversed: { applies_to: ['ol'] },
17108 selected: { applies_to: ['option'] },
17109 value: {
17110 applies_to: [
17111 'button',
17112 'option',
17113 'input',
17114 'li',
17115 'meter',
17116 'progress',
17117 'param',
17118 'select',
17119 'textarea',
17120 ],
17121 },
17122 };
17123 Object.keys(attribute_lookup).forEach(name => {
17124 const metadata = attribute_lookup[name];
17125 if (!metadata.property_name)
17126 metadata.property_name = name;
17127 });
17128 // source: https://html.spec.whatwg.org/multipage/indices.html
17129 const boolean_attribute = new Set([
17130 'allowfullscreen',
17131 'allowpaymentrequest',
17132 'async',
17133 'autofocus',
17134 'autoplay',
17135 'checked',
17136 'controls',
17137 'default',
17138 'defer',
17139 'disabled',
17140 'formnovalidate',
17141 'hidden',
17142 'ismap',
17143 'itemscope',
17144 'loop',
17145 'multiple',
17146 'muted',
17147 'nomodule',
17148 'novalidate',
17149 'open',
17150 'playsinline',
17151 'readonly',
17152 'required',
17153 'reversed',
17154 'selected'
17155 ]);
17156
17157 class StyleAttributeWrapper extends AttributeWrapper {
17158 render(block) {
17159 const style_props = optimize_style(this.node.chunks);
17160 if (!style_props)
17161 return super.render(block);
17162 style_props.forEach((prop) => {
17163 let value;
17164 if (is_dynamic(prop.value)) {
17165 const prop_dependencies = new Set();
17166 value = prop.value
17167 .map(chunk => {
17168 if (chunk.type === 'Text') {
17169 return string_literal(chunk.data);
17170 }
17171 else {
17172 add_to_set(prop_dependencies, chunk.dynamic_dependencies());
17173 return chunk.manipulate(block);
17174 }
17175 })
17176 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17177 // TODO is this necessary? style.setProperty always treats value as string, no?
17178 // if (prop.value.length === 1 || prop.value[0].type !== 'Text') {
17179 // value = x`"" + ${value}`;
17180 // }
17181 if (prop_dependencies.size) {
17182 let condition = block.renderer.dirty(Array.from(prop_dependencies));
17183 if (block.has_outros) {
17184 condition = x `!#current || ${condition}`;
17185 }
17186 const update = b `
17187 if (${condition}) {
17188 @set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});
17189 }`;
17190 block.chunks.update.push(update);
17191 }
17192 }
17193 else {
17194 value = string_literal(prop.value[0].data);
17195 }
17196 block.chunks.hydrate.push(b `@set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});`);
17197 });
17198 }
17199 }
17200 function optimize_style(value) {
17201 const props = [];
17202 let chunks = value.slice();
17203 while (chunks.length) {
17204 const chunk = chunks[0];
17205 if (chunk.type !== 'Text')
17206 return null;
17207 const key_match = /^\s*([\w-]+):\s*/.exec(chunk.data);
17208 if (!key_match)
17209 return null;
17210 const key = key_match[1];
17211 const offset = key_match.index + key_match[0].length;
17212 const remaining_data = chunk.data.slice(offset);
17213 if (remaining_data) {
17214 chunks[0] = {
17215 start: chunk.start + offset,
17216 end: chunk.end,
17217 type: 'Text',
17218 data: remaining_data
17219 };
17220 }
17221 else {
17222 chunks.shift();
17223 }
17224 const result = get_style_value(chunks);
17225 props.push({ key, value: result.value, important: result.important });
17226 chunks = result.chunks;
17227 }
17228 return props;
17229 }
17230 function get_style_value(chunks) {
17231 const value = [];
17232 let in_url = false;
17233 let quote_mark = null;
17234 let escaped = false;
17235 let closed = false;
17236 while (chunks.length && !closed) {
17237 const chunk = chunks.shift();
17238 if (chunk.type === 'Text') {
17239 let c = 0;
17240 while (c < chunk.data.length) {
17241 const char = chunk.data[c];
17242 if (escaped) {
17243 escaped = false;
17244 }
17245 else if (char === '\\') {
17246 escaped = true;
17247 }
17248 else if (char === quote_mark) {
17249 quote_mark = null;
17250 }
17251 else if (char === '"' || char === "'") {
17252 quote_mark = char;
17253 }
17254 else if (char === ')' && in_url) {
17255 in_url = false;
17256 }
17257 else if (char === 'u' && chunk.data.slice(c, c + 4) === 'url(') {
17258 in_url = true;
17259 }
17260 else if (char === ';' && !in_url && !quote_mark) {
17261 closed = true;
17262 break;
17263 }
17264 c += 1;
17265 }
17266 if (c > 0) {
17267 value.push({
17268 type: 'Text',
17269 start: chunk.start,
17270 end: chunk.start + c,
17271 data: chunk.data.slice(0, c)
17272 });
17273 }
17274 while (/[;\s]/.test(chunk.data[c]))
17275 c += 1;
17276 const remaining_data = chunk.data.slice(c);
17277 if (remaining_data) {
17278 chunks.unshift({
17279 start: chunk.start + c,
17280 end: chunk.end,
17281 type: 'Text',
17282 data: remaining_data
17283 });
17284 break;
17285 }
17286 }
17287 else {
17288 value.push(chunk);
17289 }
17290 }
17291 let important = false;
17292 const last_chunk = value[value.length - 1];
17293 if (last_chunk && last_chunk.type === 'Text' && /\s*!important\s*$/.test(last_chunk.data)) {
17294 important = true;
17295 last_chunk.data = last_chunk.data.replace(/\s*!important\s*$/, '');
17296 if (!last_chunk.data)
17297 value.pop();
17298 }
17299 return {
17300 chunks,
17301 value,
17302 important
17303 };
17304 }
17305 function is_dynamic(value) {
17306 return value.length > 1 || value[0].type !== 'Text';
17307 }
17308
17309 function get_object(node) {
17310 while (node.type === 'MemberExpression')
17311 node = node.object;
17312 return node;
17313 }
17314
17315 function replace_object(node, replacement) {
17316 if (node.type === 'Identifier')
17317 return replacement;
17318 const ancestor = node;
17319 let parent;
17320 while (node.type === 'MemberExpression') {
17321 parent = node;
17322 node = node.object;
17323 }
17324 parent.object = replacement;
17325 return ancestor;
17326 }
17327
17328 function flatten_reference(node) {
17329 const nodes = [];
17330 const parts = [];
17331 while (node.type === 'MemberExpression') {
17332 nodes.unshift(node.property);
17333 if (!node.computed) {
17334 parts.unshift(node.property.name);
17335 }
17336 node = node.object;
17337 }
17338 const name = node.type === 'Identifier'
17339 ? node.name
17340 : node.type === 'ThisExpression' ? 'this' : null;
17341 nodes.unshift(node);
17342 if (!node.computed) {
17343 parts.unshift(name);
17344 }
17345 return { name, nodes, parts };
17346 }
17347
17348 class BindingWrapper {
17349 constructor(block, node, parent) {
17350 this.node = node;
17351 this.parent = parent;
17352 const { dependencies } = this.node.expression;
17353 block.add_dependencies(dependencies);
17354 // TODO does this also apply to e.g. `<input type='checkbox' bind:group='foo'>`?
17355 if (parent.node.name === 'select') {
17356 parent.select_binding_dependencies = dependencies;
17357 dependencies.forEach((prop) => {
17358 parent.renderer.component.indirect_dependencies.set(prop, new Set());
17359 });
17360 }
17361 if (node.is_contextual) {
17362 // we need to ensure that the each block creates a context including
17363 // the list and the index, if they're not otherwise referenced
17364 const { name } = get_object(this.node.expression.node);
17365 const each_block = this.parent.node.scope.get_owner(name);
17366 each_block.has_binding = true;
17367 }
17368 this.object = get_object(this.node.expression.node).name;
17369 // view to model
17370 this.handler = get_event_handler(this, parent.renderer, block, this.object, this.node.raw_expression);
17371 this.snippet = this.node.expression.manipulate(block);
17372 this.is_readonly = this.node.is_readonly;
17373 this.needs_lock = this.node.name === 'currentTime'; // TODO others?
17374 }
17375 get_dependencies() {
17376 const dependencies = new Set(this.node.expression.dependencies);
17377 this.node.expression.dependencies.forEach((prop) => {
17378 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17379 if (indirect_dependencies) {
17380 indirect_dependencies.forEach(indirect_dependency => {
17381 dependencies.add(indirect_dependency);
17382 });
17383 }
17384 });
17385 return dependencies;
17386 }
17387 is_readonly_media_attribute() {
17388 return this.node.is_readonly_media_attribute();
17389 }
17390 render(block, lock) {
17391 if (this.is_readonly)
17392 return;
17393 const { parent } = this;
17394 const update_conditions = this.needs_lock ? [x `!${lock}`] : [];
17395 const mount_conditions = [];
17396 const dependency_array = Array.from(this.get_dependencies());
17397 if (dependency_array.length > 0) {
17398 update_conditions.push(block.renderer.dirty(dependency_array));
17399 }
17400 if (parent.node.name === "input") {
17401 const type = parent.node.get_static_attribute_value("type");
17402 if (type === null ||
17403 type === "" ||
17404 type === "text" ||
17405 type === "email" ||
17406 type === "password") {
17407 update_conditions.push(x `${parent.var}.${this.node.name} !== ${this.snippet}`);
17408 }
17409 else if (type === "number") {
17410 update_conditions.push(x `@to_number(${parent.var}.${this.node.name}) !== ${this.snippet}`);
17411 }
17412 }
17413 // model to view
17414 let update_dom = get_dom_updater(parent, this);
17415 let mount_dom = update_dom;
17416 // special cases
17417 switch (this.node.name) {
17418 case 'group':
17419 {
17420 const binding_group = get_binding_group(parent.renderer, this.node.expression.node);
17421 block.renderer.add_to_context(`$$binding_groups`);
17422 const reference = block.renderer.reference(`$$binding_groups`);
17423 block.chunks.hydrate.push(b `${reference}[${binding_group}].push(${parent.var});`);
17424 block.chunks.destroy.push(b `${reference}[${binding_group}].splice(${reference}[${binding_group}].indexOf(${parent.var}), 1);`);
17425 break;
17426 }
17427 case 'textContent':
17428 update_conditions.push(x `${this.snippet} !== ${parent.var}.textContent`);
17429 mount_conditions.push(x `${this.snippet} !== void 0`);
17430 break;
17431 case 'innerHTML':
17432 update_conditions.push(x `${this.snippet} !== ${parent.var}.innerHTML`);
17433 mount_conditions.push(x `${this.snippet} !== void 0`);
17434 break;
17435 case 'currentTime':
17436 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17437 mount_dom = null;
17438 break;
17439 case 'playbackRate':
17440 case 'volume':
17441 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17442 mount_conditions.push(x `!@_isNaN(${this.snippet})`);
17443 break;
17444 case 'paused':
17445 {
17446 // this is necessary to prevent audio restarting by itself
17447 const last = block.get_unique_name(`${parent.var.name}_is_paused`);
17448 block.add_variable(last, x `true`);
17449 update_conditions.push(x `${last} !== (${last} = ${this.snippet})`);
17450 update_dom = b `${parent.var}[${last} ? "pause" : "play"]();`;
17451 mount_dom = null;
17452 break;
17453 }
17454 case 'value':
17455 if (parent.node.get_static_attribute_value('type') === 'file') {
17456 update_dom = null;
17457 mount_dom = null;
17458 }
17459 }
17460 if (update_dom) {
17461 if (update_conditions.length > 0) {
17462 const condition = update_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17463 block.chunks.update.push(b `
17464 if (${condition}) {
17465 ${update_dom}
17466 }
17467 `);
17468 }
17469 else {
17470 block.chunks.update.push(update_dom);
17471 }
17472 }
17473 if (mount_dom) {
17474 if (mount_conditions.length > 0) {
17475 const condition = mount_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17476 block.chunks.mount.push(b `
17477 if (${condition}) {
17478 ${mount_dom}
17479 }
17480 `);
17481 }
17482 else {
17483 block.chunks.mount.push(mount_dom);
17484 }
17485 }
17486 }
17487 }
17488 function get_dom_updater(element, binding) {
17489 const { node } = element;
17490 if (binding.is_readonly_media_attribute()) {
17491 return null;
17492 }
17493 if (binding.node.name === 'this') {
17494 return null;
17495 }
17496 if (node.name === 'select') {
17497 return node.get_static_attribute_value('multiple') === true ?
17498 b `@select_options(${element.var}, ${binding.snippet})` :
17499 b `@select_option(${element.var}, ${binding.snippet})`;
17500 }
17501 if (binding.node.name === 'group') {
17502 const type = node.get_static_attribute_value('type');
17503 const condition = type === 'checkbox'
17504 ? x `~${binding.snippet}.indexOf(${element.var}.__value)`
17505 : x `${element.var}.__value === ${binding.snippet}`;
17506 return b `${element.var}.checked = ${condition};`;
17507 }
17508 if (binding.node.name === 'value') {
17509 return b `@set_input_value(${element.var}, ${binding.snippet});`;
17510 }
17511 return b `${element.var}.${binding.node.name} = ${binding.snippet};`;
17512 }
17513 function get_binding_group(renderer, value) {
17514 const { parts } = flatten_reference(value); // TODO handle cases involving computed member expressions
17515 const keypath = parts.join('.');
17516 // TODO handle contextual bindings — `keypath` should include unique ID of
17517 // each block that provides context
17518 let index = renderer.binding_groups.indexOf(keypath);
17519 if (index === -1) {
17520 index = renderer.binding_groups.length;
17521 renderer.binding_groups.push(keypath);
17522 }
17523 return index;
17524 }
17525 function get_event_handler(binding, renderer, block, name, lhs) {
17526 const contextual_dependencies = new Set(binding.node.expression.contextual_dependencies);
17527 const context = block.bindings.get(name);
17528 let set_store;
17529 if (context) {
17530 const { object, property, store, snippet } = context;
17531 lhs = replace_object(lhs, snippet);
17532 contextual_dependencies.add(object.name);
17533 contextual_dependencies.add(property.name);
17534 contextual_dependencies.delete(name);
17535 if (store) {
17536 set_store = b `${store}.set(${`$${store}`});`;
17537 }
17538 }
17539 else {
17540 const object = get_object(lhs);
17541 if (object.name[0] === '$') {
17542 const store = object.name.slice(1);
17543 set_store = b `${store}.set(${object.name});`;
17544 }
17545 }
17546 const value = get_value_from_dom(renderer, binding.parent, binding);
17547 const mutation = b `
17548 ${lhs} = ${value};
17549 ${set_store}
17550 `;
17551 return {
17552 uses_context: binding.node.is_contextual || binding.node.expression.uses_context,
17553 mutation,
17554 contextual_dependencies,
17555 lhs,
17556 };
17557 }
17558 function get_value_from_dom(renderer, element, binding) {
17559 const { node } = element;
17560 const { name } = binding.node;
17561 if (name === 'this') {
17562 return x `$$value`;
17563 }
17564 // <select bind:value='selected>
17565 if (node.name === 'select') {
17566 return node.get_static_attribute_value('multiple') === true ?
17567 x `@select_multiple_value(this)` :
17568 x `@select_value(this)`;
17569 }
17570 const type = node.get_static_attribute_value('type');
17571 // <input type='checkbox' bind:group='foo'>
17572 if (name === 'group') {
17573 const binding_group = get_binding_group(renderer, binding.node.expression.node);
17574 if (type === 'checkbox') {
17575 return x `@get_binding_group_value($$binding_groups[${binding_group}], this.__value, this.checked)`;
17576 }
17577 return x `this.__value`;
17578 }
17579 // <input type='range|number' bind:value>
17580 if (type === 'range' || type === 'number') {
17581 return x `@to_number(this.${name})`;
17582 }
17583 if ((name === 'buffered' || name === 'seekable' || name === 'played')) {
17584 return x `@time_ranges_to_array(this.${name})`;
17585 }
17586 // everything else
17587 return x `this.${name}`;
17588 }
17589
17590 function add_actions(block, target, actions) {
17591 actions.forEach(action => add_action(block, target, action));
17592 }
17593 function add_action(block, target, action) {
17594 const { expression } = action;
17595 let snippet;
17596 let dependencies;
17597 if (expression) {
17598 snippet = expression.manipulate(block);
17599 dependencies = expression.dynamic_dependencies();
17600 }
17601 const id = block.get_unique_name(`${action.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action`);
17602 block.add_variable(id);
17603 const fn = block.renderer.reference(action.name);
17604 block.event_listeners.push(x `@action_destroyer(${id} = ${fn}.call(null, ${target}, ${snippet}))`);
17605 if (dependencies && dependencies.length > 0) {
17606 let condition = x `${id} && @is_function(${id}.update)`;
17607 if (dependencies.length > 0) {
17608 condition = x `${condition} && ${block.renderer.dirty(dependencies)}`;
17609 }
17610 block.chunks.update.push(b `if (${condition}) ${id}.update.call(null, ${snippet});`);
17611 }
17612 }
17613
17614 function get_slot_definition(block, scope, lets) {
17615 if (lets.length === 0)
17616 return { block, scope };
17617 const context_input = {
17618 type: 'ObjectPattern',
17619 properties: lets.map(l => ({
17620 type: 'Property',
17621 kind: 'init',
17622 key: l.name,
17623 value: l.value || l.name
17624 }))
17625 };
17626 const properties = [];
17627 const value_map = new Map();
17628 lets.forEach(l => {
17629 let value;
17630 if (l.names.length > 1) {
17631 // more than one, probably destructuring
17632 const unique_name = block.get_unique_name(l.names.join('_')).name;
17633 value_map.set(l.value, unique_name);
17634 value = { type: 'Identifier', name: unique_name };
17635 }
17636 else {
17637 value = l.value || l.name;
17638 }
17639 properties.push({
17640 type: 'Property',
17641 kind: 'init',
17642 key: l.name,
17643 value,
17644 });
17645 });
17646 const changes_input = {
17647 type: 'ObjectPattern',
17648 properties,
17649 };
17650 const names = new Set();
17651 const names_lookup = new Map();
17652 lets.forEach(l => {
17653 l.names.forEach(name => {
17654 names.add(name);
17655 if (value_map.has(l.value)) {
17656 names_lookup.set(name, value_map.get(l.value));
17657 }
17658 });
17659 });
17660 const context = {
17661 type: 'ObjectExpression',
17662 properties: Array.from(names).map(name => p `${block.renderer.context_lookup.get(name).index}: ${name}`)
17663 };
17664 const { context_lookup } = block.renderer;
17665 // i am well aware that this code is gross
17666 // TODO: context-overflow make it less gross
17667 const changes = {
17668 type: 'ParenthesizedExpression',
17669 get expression() {
17670 if (block.renderer.context_overflow) {
17671 const grouped = [];
17672 Array.from(names).forEach(name => {
17673 const i = context_lookup.get(name).index.value;
17674 const g = Math.floor(i / 31);
17675 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
17676 if (!grouped[g])
17677 grouped[g] = [];
17678 grouped[g].push({ name: lookup_name, n: i % 31 });
17679 });
17680 const elements = [];
17681 for (let g = 0; g < grouped.length; g += 1) {
17682 elements[g] = grouped[g]
17683 ? grouped[g]
17684 .map(({ name, n }) => x `${name} ? ${1 << n} : 0`)
17685 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`)
17686 : x `0`;
17687 }
17688 return {
17689 type: 'ArrayExpression',
17690 elements
17691 };
17692 }
17693 return Array.from(names)
17694 .map(name => {
17695 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
17696 const i = context_lookup.get(name).index.value;
17697 return x `${lookup_name} ? ${1 << i} : 0`;
17698 })
17699 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
17700 }
17701 };
17702 return {
17703 block,
17704 scope,
17705 get_context: x `${context_input} => ${context}`,
17706 get_changes: x `${changes_input} => ${changes}`
17707 };
17708 }
17709
17710 function bind_this(component, block, binding, variable) {
17711 const fn = component.get_unique_name(`${variable.name}_binding`);
17712 block.renderer.add_to_context(fn.name);
17713 const callee = block.renderer.reference(fn.name);
17714 const { contextual_dependencies, mutation, lhs } = binding.handler;
17715 const dependencies = binding.get_dependencies();
17716 const body = b `
17717 ${mutation}
17718 ${Array.from(dependencies)
17719 .filter(dep => dep[0] !== '$')
17720 .filter(dep => !contextual_dependencies.has(dep))
17721 .map(dep => b `${block.renderer.invalidate(dep)};`)}
17722 `;
17723 if (contextual_dependencies.size) {
17724 const params = Array.from(contextual_dependencies).map(name => ({
17725 type: 'Identifier',
17726 name
17727 }));
17728 component.partly_hoisted.push(b `
17729 function ${fn}($$value, ${params}) {
17730 if (${lhs} === $$value) return;
17731 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
17732 ${body}
17733 });
17734 }
17735 `);
17736 const args = [];
17737 for (const id of params) {
17738 args.push(id);
17739 if (block.variables.has(id.name)) {
17740 if (block.renderer.context_lookup.get(id.name).is_contextual)
17741 continue;
17742 }
17743 block.add_variable(id, block.renderer.reference(id.name));
17744 }
17745 const assign = block.get_unique_name(`assign_${variable.name}`);
17746 const unassign = block.get_unique_name(`unassign_${variable.name}`);
17747 block.chunks.init.push(b `
17748 const ${assign} = () => ${callee}(${variable}, ${args});
17749 const ${unassign} = () => ${callee}(null, ${args});
17750 `);
17751 const condition = Array.from(params)
17752 .map(name => x `${name} !== ${block.renderer.reference(name.name)}`)
17753 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
17754 // we push unassign and unshift assign so that references are
17755 // nulled out before they're created, to avoid glitches
17756 // with shifting indices
17757 block.chunks.update.push(b `
17758 if (${condition}) {
17759 ${unassign}();
17760 ${args.map(a => b `${a} = ${block.renderer.reference(a.name)}`)};
17761 ${assign}();
17762 }`);
17763 block.chunks.destroy.push(b `${unassign}();`);
17764 return b `${assign}();`;
17765 }
17766 component.partly_hoisted.push(b `
17767 function ${fn}($$value) {
17768 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
17769 ${body}
17770 });
17771 }
17772 `);
17773 block.chunks.destroy.push(b `${callee}(null);`);
17774 return b `${callee}(${variable});`;
17775 }
17776
17777 class Node$1 {
17778 constructor(component, parent, _scope, info) {
17779 this.start = info.start;
17780 this.end = info.end;
17781 this.type = info.type;
17782 // this makes properties non-enumerable, which makes logging
17783 // bearable. might have a performance cost. TODO remove in prod?
17784 Object.defineProperties(this, {
17785 component: {
17786 value: component
17787 },
17788 parent: {
17789 value: parent
17790 }
17791 });
17792 }
17793 cannot_use_innerhtml() {
17794 if (this.can_use_innerhtml !== false) {
17795 this.can_use_innerhtml = false;
17796 if (this.parent)
17797 this.parent.cannot_use_innerhtml();
17798 }
17799 }
17800 find_nearest(selector) {
17801 if (selector.test(this.type))
17802 return this;
17803 if (this.parent)
17804 return this.parent.find_nearest(selector);
17805 }
17806 get_static_attribute_value(name) {
17807 const attribute = this.attributes && this.attributes.find((attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === name);
17808 if (!attribute)
17809 return null;
17810 if (attribute.is_true)
17811 return true;
17812 if (attribute.chunks.length === 0)
17813 return '';
17814 if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
17815 return attribute.chunks[0].data;
17816 }
17817 return null;
17818 }
17819 has_ancestor(type) {
17820 return this.parent ?
17821 this.parent.type === type || this.parent.has_ancestor(type) :
17822 false;
17823 }
17824 }
17825
17826 function create_scopes(expression) {
17827 return analyze(expression);
17828 }
17829
17830 function is_dynamic$1(variable) {
17831 if (variable) {
17832 if (variable.mutated || variable.reassigned)
17833 return true; // dynamic internal state
17834 if (!variable.module && variable.writable && variable.export_name)
17835 return true; // writable props
17836 }
17837 return false;
17838 }
17839
17840 function nodes_match(a, b) {
17841 if (!!a !== !!b)
17842 return false;
17843 if (Array.isArray(a) !== Array.isArray(b))
17844 return false;
17845 if (a && typeof a === 'object') {
17846 if (Array.isArray(a)) {
17847 if (a.length !== b.length)
17848 return false;
17849 return a.every((child, i) => nodes_match(child, b[i]));
17850 }
17851 const a_keys = Object.keys(a).sort();
17852 const b_keys = Object.keys(b).sort();
17853 if (a_keys.length !== b_keys.length)
17854 return false;
17855 let i = a_keys.length;
17856 while (i--) {
17857 const key = a_keys[i];
17858 if (b_keys[i] !== key)
17859 return false;
17860 if (key === 'start' || key === 'end')
17861 continue;
17862 if (!nodes_match(a[key], b[key])) {
17863 return false;
17864 }
17865 }
17866 return true;
17867 }
17868 return a === b;
17869 }
17870
17871 function invalidate(renderer, scope, node, names, main_execution_context = false) {
17872 const { component } = renderer;
17873 const [head, ...tail] = Array.from(names)
17874 .filter(name => {
17875 const owner = scope.find_owner(name);
17876 return !owner || owner === component.instance_scope;
17877 })
17878 .map(name => component.var_lookup.get(name))
17879 .filter(variable => {
17880 return variable && (!variable.hoistable &&
17881 !variable.global &&
17882 !variable.module &&
17883 (variable.referenced ||
17884 variable.subscribable ||
17885 variable.is_reactive_dependency ||
17886 variable.export_name ||
17887 variable.name[0] === '$'));
17888 });
17889 function get_invalidated(variable, node) {
17890 if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') {
17891 return node || x `${variable.name}`;
17892 }
17893 return renderer.invalidate(variable.name);
17894 }
17895 if (head) {
17896 component.has_reactive_assignments = true;
17897 if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) {
17898 return get_invalidated(head, node);
17899 }
17900 else {
17901 const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
17902 const extra_args = tail.map(variable => get_invalidated(variable));
17903 const pass_value = (extra_args.length > 0 ||
17904 (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
17905 (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier')));
17906 if (pass_value) {
17907 extra_args.unshift({
17908 type: 'Identifier',
17909 name: head.name
17910 });
17911 }
17912 let invalidate = is_store_value
17913 ? x `@set_store_value(${head.name.slice(1)}, ${node}, ${extra_args})`
17914 : !main_execution_context
17915 ? x `$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`
17916 : node;
17917 if (head.subscribable && head.reassigned) {
17918 const subscribe = `$$subscribe_${head.name}`;
17919 invalidate = x `${subscribe}(${invalidate})`;
17920 }
17921 return invalidate;
17922 }
17923 }
17924 return node;
17925 }
17926
17927 const reserved_keywords = new Set(["$$props", "$$restProps"]);
17928 function is_reserved_keyword(name) {
17929 return reserved_keywords.has(name);
17930 }
17931
17932 class Expression {
17933 // todo: owner type
17934 constructor(component, owner, template_scope, info, lazy) {
17935 this.type = 'Expression';
17936 this.dependencies = new Set();
17937 this.contextual_dependencies = new Set();
17938 this.declarations = [];
17939 this.uses_context = false;
17940 // TODO revert to direct property access in prod?
17941 Object.defineProperties(this, {
17942 component: {
17943 value: component
17944 }
17945 });
17946 this.node = info;
17947 this.template_scope = template_scope;
17948 this.owner = owner;
17949 const { dependencies, contextual_dependencies } = this;
17950 let { map, scope } = create_scopes(info);
17951 this.scope = scope;
17952 this.scope_map = map;
17953 const expression = this;
17954 let function_expression;
17955 // discover dependencies, but don't change the code yet
17956 walk(info, {
17957 enter(node, parent, key) {
17958 // don't manipulate shorthand props twice
17959 if (key === 'value' && parent.shorthand)
17960 return;
17961 if (map.has(node)) {
17962 scope = map.get(node);
17963 }
17964 if (!function_expression && /FunctionExpression/.test(node.type)) {
17965 function_expression = node;
17966 }
17967 if (isReference(node, parent)) {
17968 const { name, nodes } = flatten_reference(node);
17969 if (scope.has(name))
17970 return;
17971 if (name[0] === '$' && template_scope.names.has(name.slice(1))) {
17972 component.error(node, {
17973 code: `contextual-store`,
17974 message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
17975 });
17976 }
17977 if (template_scope.is_let(name)) {
17978 if (!function_expression) { // TODO should this be `!lazy` ?
17979 contextual_dependencies.add(name);
17980 dependencies.add(name);
17981 }
17982 }
17983 else if (template_scope.names.has(name)) {
17984 expression.uses_context = true;
17985 contextual_dependencies.add(name);
17986 const owner = template_scope.get_owner(name);
17987 const is_index = owner.type === 'EachBlock' && owner.key && name === owner.index;
17988 if (!lazy || is_index) {
17989 template_scope.dependencies_for_name.get(name).forEach(name => dependencies.add(name));
17990 }
17991 }
17992 else {
17993 if (!lazy) {
17994 dependencies.add(name);
17995 }
17996 component.add_reference(name);
17997 component.warn_if_undefined(name, nodes[0], template_scope);
17998 }
17999 this.skip();
18000 }
18001 // track any assignments from template expressions as mutable
18002 let names;
18003 let deep = false;
18004 if (function_expression) {
18005 if (node.type === 'AssignmentExpression') {
18006 deep = node.left.type === 'MemberExpression';
18007 names = deep
18008 ? [get_object(node.left).name]
18009 : extract_names(node.left);
18010 }
18011 else if (node.type === 'UpdateExpression') {
18012 const { name } = get_object(node.argument);
18013 names = [name];
18014 }
18015 }
18016 if (names) {
18017 names.forEach(name => {
18018 if (template_scope.names.has(name)) {
18019 template_scope.dependencies_for_name.get(name).forEach(name => {
18020 const variable = component.var_lookup.get(name);
18021 if (variable)
18022 variable[deep ? 'mutated' : 'reassigned'] = true;
18023 });
18024 const each_block = template_scope.get_owner(name);
18025 each_block.has_binding = true;
18026 }
18027 else {
18028 component.add_reference(name);
18029 const variable = component.var_lookup.get(name);
18030 if (variable)
18031 variable[deep ? 'mutated' : 'reassigned'] = true;
18032 }
18033 });
18034 }
18035 },
18036 leave(node) {
18037 if (map.has(node)) {
18038 scope = scope.parent;
18039 }
18040 if (node === function_expression) {
18041 function_expression = null;
18042 }
18043 }
18044 });
18045 }
18046 dynamic_dependencies() {
18047 return Array.from(this.dependencies).filter(name => {
18048 if (this.template_scope.is_let(name))
18049 return true;
18050 if (is_reserved_keyword(name))
18051 return true;
18052 const variable = this.component.var_lookup.get(name);
18053 return is_dynamic$1(variable);
18054 });
18055 }
18056 // TODO move this into a render-dom wrapper?
18057 manipulate(block) {
18058 // TODO ideally we wouldn't end up calling this method
18059 // multiple times
18060 if (this.manipulated)
18061 return this.manipulated;
18062 const { component, declarations, scope_map: map, template_scope, owner } = this;
18063 let scope = this.scope;
18064 let function_expression;
18065 let dependencies;
18066 let contextual_dependencies;
18067 const node = walk(this.node, {
18068 enter(node, parent) {
18069 if (node.type === 'Property' && node.shorthand) {
18070 node.value = JSON.parse(JSON.stringify(node.value));
18071 node.shorthand = false;
18072 }
18073 if (map.has(node)) {
18074 scope = map.get(node);
18075 }
18076 if (isReference(node, parent)) {
18077 const { name } = flatten_reference(node);
18078 if (scope.has(name))
18079 return;
18080 if (function_expression) {
18081 if (template_scope.names.has(name)) {
18082 contextual_dependencies.add(name);
18083 template_scope.dependencies_for_name.get(name).forEach(dependency => {
18084 dependencies.add(dependency);
18085 });
18086 }
18087 else {
18088 dependencies.add(name);
18089 component.add_reference(name); // TODO is this redundant/misplaced?
18090 }
18091 }
18092 else if (is_contextual(component, template_scope, name)) {
18093 const reference = block.renderer.reference(node);
18094 this.replace(reference);
18095 }
18096 this.skip();
18097 }
18098 if (!function_expression) {
18099 if (node.type === 'AssignmentExpression') ;
18100 if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
18101 function_expression = node;
18102 dependencies = new Set();
18103 contextual_dependencies = new Set();
18104 }
18105 }
18106 },
18107 leave(node, parent) {
18108 if (map.has(node))
18109 scope = scope.parent;
18110 if (node === function_expression) {
18111 const id = component.get_unique_name(sanitize(get_function_name(node, owner)));
18112 const declaration = b `const ${id} = ${node}`;
18113 if (dependencies.size === 0 && contextual_dependencies.size === 0) {
18114 // we can hoist this out of the component completely
18115 component.fully_hoisted.push(declaration);
18116 this.replace(id);
18117 component.add_var({
18118 name: id.name,
18119 internal: true,
18120 hoistable: true,
18121 referenced: true
18122 });
18123 }
18124 else if (contextual_dependencies.size === 0) {
18125 // function can be hoisted inside the component init
18126 component.partly_hoisted.push(declaration);
18127 block.renderer.add_to_context(id.name);
18128 this.replace(block.renderer.reference(id));
18129 }
18130 else {
18131 // we need a combo block/init recipe
18132 const deps = Array.from(contextual_dependencies);
18133 node.params = [
18134 ...deps.map(name => ({ type: 'Identifier', name })),
18135 ...node.params
18136 ];
18137 const context_args = deps.map(name => block.renderer.reference(name));
18138 component.partly_hoisted.push(declaration);
18139 block.renderer.add_to_context(id.name);
18140 const callee = block.renderer.reference(id);
18141 this.replace(id);
18142 if (node.params.length > 0) {
18143 declarations.push(b `
18144 function ${id}(...args) {
18145 return ${callee}(${context_args}, ...args);
18146 }
18147 `);
18148 }
18149 else {
18150 declarations.push(b `
18151 function ${id}() {
18152 return ${callee}(${context_args});
18153 }
18154 `);
18155 }
18156 }
18157 function_expression = null;
18158 dependencies = null;
18159 contextual_dependencies = null;
18160 if (parent && parent.type === 'Property') {
18161 parent.method = false;
18162 }
18163 }
18164 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
18165 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
18166 const object_name = get_object(assignee).name;
18167 if (scope.has(object_name))
18168 return;
18169 // normally (`a = 1`, `b.c = 2`), there'll be a single name
18170 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
18171 // may be more, in which case we need to tack the extra ones
18172 // onto the initial function call
18173 const names = new Set(extract_names(assignee));
18174 const traced = new Set();
18175 names.forEach(name => {
18176 const dependencies = template_scope.dependencies_for_name.get(name);
18177 if (dependencies) {
18178 dependencies.forEach(name => traced.add(name));
18179 }
18180 else {
18181 traced.add(name);
18182 }
18183 });
18184 const context = block.bindings.get(object_name);
18185 if (context) {
18186 // for `{#each array as item}`
18187 // replace `item = 1` to `each_array[each_index] = 1`, this allow us to mutate the array
18188 // rather than mutating the local `item` variable
18189 const { snippet, object, property } = context;
18190 const replaced = replace_object(assignee, snippet);
18191 if (node.type === 'AssignmentExpression') {
18192 node.left = replaced;
18193 }
18194 else {
18195 node.argument = replaced;
18196 }
18197 contextual_dependencies.add(object.name);
18198 contextual_dependencies.add(property.name);
18199 }
18200 this.replace(invalidate(block.renderer, scope, node, traced));
18201 }
18202 }
18203 });
18204 if (declarations.length > 0) {
18205 block.maintain_context = true;
18206 declarations.forEach(declaration => {
18207 block.chunks.init.push(declaration);
18208 });
18209 }
18210 return (this.manipulated = node);
18211 }
18212 }
18213 function get_function_name(_node, parent) {
18214 if (parent.type === 'EventHandler') {
18215 return `${parent.name}_handler`;
18216 }
18217 if (parent.type === 'Action') {
18218 return `${parent.name}_function`;
18219 }
18220 return 'func';
18221 }
18222 function is_contextual(component, scope, name) {
18223 if (is_reserved_keyword(name))
18224 return true;
18225 // if it's a name below root scope, it's contextual
18226 if (!scope.is_top_level(name))
18227 return true;
18228 const variable = component.var_lookup.get(name);
18229 // hoistables, module declarations, and imports are non-contextual
18230 if (!variable || variable.hoistable)
18231 return false;
18232 // assume contextual
18233 return true;
18234 }
18235
18236 class Action extends Node$1 {
18237 constructor(component, parent, scope, info) {
18238 super(component, parent, scope, info);
18239 component.warn_if_undefined(info.name, info, scope);
18240 this.name = info.name;
18241 component.add_reference(info.name.split('.')[0]);
18242 this.expression = info.expression
18243 ? new Expression(component, this, scope, info.expression)
18244 : null;
18245 this.uses_context = this.expression && this.expression.uses_context;
18246 }
18247 }
18248
18249 const events = [
18250 {
18251 event_names: ['input'],
18252 filter: (node, _name) => node.name === 'textarea' ||
18253 node.name === 'input' && !/radio|checkbox|range|file/.test(node.get_static_attribute_value('type'))
18254 },
18255 {
18256 event_names: ['input'],
18257 filter: (node, name) => (name === 'textContent' || name === 'innerHTML') &&
18258 node.attributes.some(attribute => attribute.name === 'contenteditable')
18259 },
18260 {
18261 event_names: ['change'],
18262 filter: (node, _name) => node.name === 'select' ||
18263 node.name === 'input' && /radio|checkbox|file/.test(node.get_static_attribute_value('type'))
18264 },
18265 {
18266 event_names: ['change', 'input'],
18267 filter: (node, _name) => node.name === 'input' && node.get_static_attribute_value('type') === 'range'
18268 },
18269 {
18270 event_names: ['elementresize'],
18271 filter: (_node, name) => dimensions.test(name)
18272 },
18273 // media events
18274 {
18275 event_names: ['timeupdate'],
18276 filter: (node, name) => node.is_media_node() &&
18277 (name === 'currentTime' || name === 'played' || name === 'ended')
18278 },
18279 {
18280 event_names: ['durationchange'],
18281 filter: (node, name) => node.is_media_node() &&
18282 name === 'duration'
18283 },
18284 {
18285 event_names: ['play', 'pause'],
18286 filter: (node, name) => node.is_media_node() &&
18287 name === 'paused'
18288 },
18289 {
18290 event_names: ['progress'],
18291 filter: (node, name) => node.is_media_node() &&
18292 name === 'buffered'
18293 },
18294 {
18295 event_names: ['loadedmetadata'],
18296 filter: (node, name) => node.is_media_node() &&
18297 (name === 'buffered' || name === 'seekable')
18298 },
18299 {
18300 event_names: ['volumechange'],
18301 filter: (node, name) => node.is_media_node() &&
18302 (name === 'volume' || name === 'muted')
18303 },
18304 {
18305 event_names: ['ratechange'],
18306 filter: (node, name) => node.is_media_node() &&
18307 name === 'playbackRate'
18308 },
18309 {
18310 event_names: ['seeking', 'seeked'],
18311 filter: (node, name) => node.is_media_node() &&
18312 (name === 'seeking')
18313 },
18314 {
18315 event_names: ['ended'],
18316 filter: (node, name) => node.is_media_node() &&
18317 name === 'ended'
18318 },
18319 {
18320 event_names: ['resize'],
18321 filter: (node, name) => node.is_media_node() &&
18322 (name === 'videoHeight' || name === 'videoWidth')
18323 },
18324 // details event
18325 {
18326 event_names: ['toggle'],
18327 filter: (node, _name) => node.name === 'details'
18328 },
18329 ];
18330 class ElementWrapper extends Wrapper {
18331 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
18332 super(renderer, block, parent, node);
18333 this.var = {
18334 type: 'Identifier',
18335 name: node.name.replace(/[^a-zA-Z0-9_$]/g, '_')
18336 };
18337 this.void = is_void(node.name);
18338 this.class_dependencies = [];
18339 if (this.node.children.length) {
18340 this.node.lets.forEach(l => {
18341 extract_names(l.value || l.name).forEach(name => {
18342 renderer.add_to_context(name, true);
18343 });
18344 });
18345 }
18346 this.attributes = this.node.attributes.map(attribute => {
18347 if (attribute.name === 'slot') {
18348 // TODO make separate subclass for this?
18349 let owner = this.parent;
18350 while (owner) {
18351 if (owner.node.type === 'InlineComponent') {
18352 break;
18353 }
18354 if (owner.node.type === 'Element' && /-/.test(owner.node.name)) {
18355 break;
18356 }
18357 owner = owner.parent;
18358 }
18359 if (owner && owner.node.type === 'InlineComponent') {
18360 const name = attribute.get_static_value();
18361 if (!owner.slots.has(name)) {
18362 const child_block = block.child({
18363 comment: create_debugging_comment(node, this.renderer.component),
18364 name: this.renderer.component.get_unique_name(`create_${sanitize(name)}_slot`),
18365 type: 'slot'
18366 });
18367 const { scope, lets } = this.node;
18368 const seen = new Set(lets.map(l => l.name.name));
18369 owner.node.lets.forEach(l => {
18370 if (!seen.has(l.name.name))
18371 lets.push(l);
18372 });
18373 owner.slots.set(name, get_slot_definition(child_block, scope, lets));
18374 this.renderer.blocks.push(child_block);
18375 }
18376 this.slot_block = owner.slots.get(name).block;
18377 block = this.slot_block;
18378 }
18379 }
18380 if (attribute.name === 'style') {
18381 return new StyleAttributeWrapper(this, block, attribute);
18382 }
18383 return new AttributeWrapper(this, block, attribute);
18384 });
18385 // ordinarily, there'll only be one... but we need to handle
18386 // the rare case where an element can have multiple bindings,
18387 // e.g. <audio bind:paused bind:currentTime>
18388 this.bindings = this.node.bindings.map(binding => new BindingWrapper(block, binding, this));
18389 this.event_handlers = this.node.handlers.map(event_handler => new EventHandlerWrapper(event_handler, this));
18390 if (node.intro || node.outro) {
18391 if (node.intro)
18392 block.add_intro(node.intro.is_local);
18393 if (node.outro)
18394 block.add_outro(node.outro.is_local);
18395 }
18396 if (node.animation) {
18397 block.add_animation();
18398 }
18399 // add directive and handler dependencies
18400 [node.animation, node.outro, ...node.actions, ...node.classes].forEach(directive => {
18401 if (directive && directive.expression) {
18402 block.add_dependencies(directive.expression.dependencies);
18403 }
18404 });
18405 node.handlers.forEach(handler => {
18406 if (handler.expression) {
18407 block.add_dependencies(handler.expression.dependencies);
18408 }
18409 });
18410 if (this.parent) {
18411 if (node.actions.length > 0 ||
18412 node.animation ||
18413 node.bindings.length > 0 ||
18414 node.classes.length > 0 ||
18415 node.intro || node.outro ||
18416 node.handlers.length > 0 ||
18417 this.node.name === 'option' ||
18418 renderer.options.dev) {
18419 this.parent.cannot_use_innerhtml(); // need to use add_location
18420 this.parent.not_static_content();
18421 }
18422 }
18423 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
18424 if (this.slot_block) {
18425 block.parent.add_dependencies(block.dependencies);
18426 // appalling hack
18427 const index = block.parent.wrappers.indexOf(this);
18428 block.parent.wrappers.splice(index, 1);
18429 block.wrappers.push(this);
18430 }
18431 }
18432 render(block, parent_node, parent_nodes) {
18433 const { renderer } = this;
18434 if (this.node.name === 'noscript')
18435 return;
18436 if (this.slot_block) {
18437 block = this.slot_block;
18438 }
18439 const node = this.var;
18440 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
18441 const children = x `@children(${this.node.name === 'template' ? x `${node}.content` : node})`;
18442 block.add_variable(node);
18443 const render_statement = this.get_render_statement(block);
18444 block.chunks.create.push(b `${node} = ${render_statement};`);
18445 if (renderer.options.hydratable) {
18446 if (parent_nodes) {
18447 block.chunks.claim.push(b `
18448 ${node} = ${this.get_claim_statement(parent_nodes)};
18449 `);
18450 if (!this.void && this.node.children.length > 0) {
18451 block.chunks.claim.push(b `
18452 var ${nodes} = ${children};
18453 `);
18454 }
18455 }
18456 else {
18457 block.chunks.claim.push(b `${node} = ${render_statement};`);
18458 }
18459 }
18460 if (parent_node) {
18461 block.chunks.mount.push(b `@append(${parent_node}, ${node});`);
18462 if (is_head(parent_node)) {
18463 block.chunks.destroy.push(b `@detach(${node});`);
18464 }
18465 }
18466 else {
18467 block.chunks.mount.push(b `@insert(#target, ${node}, #anchor);`);
18468 // TODO we eventually need to consider what happens to elements
18469 // that belong to the same outgroup as an outroing element...
18470 block.chunks.destroy.push(b `if (detaching) @detach(${node});`);
18471 }
18472 // insert static children with textContent or innerHTML
18473 const can_use_textcontent = this.can_use_textcontent();
18474 if (!this.node.namespace && (this.can_use_innerhtml || can_use_textcontent) && this.fragment.nodes.length > 0) {
18475 if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
18476 block.chunks.create.push(
18477 // @ts-ignore todo: should it be this.fragment.nodes[0].node.data instead?
18478 b `${node}.textContent = ${string_literal(this.fragment.nodes[0].data)};`);
18479 }
18480 else {
18481 const state = {
18482 quasi: {
18483 type: 'TemplateElement',
18484 value: { raw: '' }
18485 }
18486 };
18487 const literal = {
18488 type: 'TemplateLiteral',
18489 expressions: [],
18490 quasis: []
18491 };
18492 const can_use_raw_text = !this.can_use_innerhtml && can_use_textcontent;
18493 to_html(this.fragment.nodes, block, literal, state, can_use_raw_text);
18494 literal.quasis.push(state.quasi);
18495 block.chunks.create.push(b `${node}.${this.can_use_innerhtml ? 'innerHTML' : 'textContent'} = ${literal};`);
18496 }
18497 }
18498 else {
18499 this.fragment.nodes.forEach((child) => {
18500 child.render(block, this.node.name === 'template' ? x `${node}.content` : node, nodes);
18501 });
18502 }
18503 const event_handler_or_binding_uses_context = (this.bindings.some(binding => binding.handler.uses_context) ||
18504 this.node.handlers.some(handler => handler.uses_context) ||
18505 this.node.actions.some(action => action.uses_context));
18506 if (event_handler_or_binding_uses_context) {
18507 block.maintain_context = true;
18508 }
18509 this.add_attributes(block);
18510 this.add_directives_in_order(block);
18511 this.add_transitions(block);
18512 this.add_animation(block);
18513 this.add_classes(block);
18514 this.add_manual_style_scoping(block);
18515 if (nodes && this.renderer.options.hydratable && !this.void) {
18516 block.chunks.claim.push(b `${this.node.children.length > 0 ? nodes : children}.forEach(@detach);`);
18517 }
18518 if (renderer.options.dev) {
18519 const loc = renderer.locate(this.node.start);
18520 block.chunks.hydrate.push(b `@add_location(${this.var}, ${renderer.file_var}, ${loc.line - 1}, ${loc.column}, ${this.node.start});`);
18521 }
18522 }
18523 can_use_textcontent() {
18524 return this.is_static_content && this.fragment.nodes.every(node => node.node.type === 'Text' || node.node.type === 'MustacheTag');
18525 }
18526 get_render_statement(block) {
18527 const { name, namespace } = this.node;
18528 if (namespace === namespaces.svg) {
18529 return x `@svg_element("${name}")`;
18530 }
18531 if (namespace) {
18532 return x `@_document.createElementNS("${namespace}", "${name}")`;
18533 }
18534 const is = this.attributes.find(attr => attr.node.name === 'is');
18535 if (is) {
18536 return x `@element_is("${name}", ${is.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`)})`;
18537 }
18538 return x `@element("${name}")`;
18539 }
18540 get_claim_statement(nodes) {
18541 const attributes = this.node.attributes
18542 .filter((attr) => attr.type === 'Attribute')
18543 .map((attr) => p `${attr.name}: true`);
18544 const name = this.node.namespace
18545 ? this.node.name
18546 : this.node.name.toUpperCase();
18547 const svg = this.node.namespace === namespaces.svg ? 1 : null;
18548 return x `@claim_element(${nodes}, "${name}", { ${attributes} }, ${svg})`;
18549 }
18550 add_directives_in_order(block) {
18551 const binding_groups = events
18552 .map(event => ({
18553 events: event.event_names,
18554 bindings: this.bindings
18555 .filter(binding => binding.node.name !== 'this')
18556 .filter(binding => event.filter(this.node, binding.node.name))
18557 }))
18558 .filter(group => group.bindings.length);
18559 const this_binding = this.bindings.find(b => b.node.name === 'this');
18560 function getOrder(item) {
18561 if (item instanceof EventHandlerWrapper) {
18562 return item.node.start;
18563 }
18564 else if (item instanceof BindingWrapper) {
18565 return item.node.start;
18566 }
18567 else if (item instanceof Action) {
18568 return item.start;
18569 }
18570 else {
18571 return item.bindings[0].node.start;
18572 }
18573 }
18574 [
18575 ...binding_groups,
18576 ...this.event_handlers,
18577 this_binding,
18578 ...this.node.actions
18579 ]
18580 .filter(Boolean)
18581 .sort((a, b) => getOrder(a) - getOrder(b))
18582 .forEach(item => {
18583 if (item instanceof EventHandlerWrapper) {
18584 add_event_handler(block, this.var, item);
18585 }
18586 else if (item instanceof BindingWrapper) {
18587 this.add_this_binding(block, item);
18588 }
18589 else if (item instanceof Action) {
18590 add_action(block, this.var, item);
18591 }
18592 else {
18593 this.add_bindings(block, item);
18594 }
18595 });
18596 }
18597 add_bindings(block, binding_group) {
18598 const { renderer } = this;
18599 if (binding_group.bindings.length === 0)
18600 return;
18601 renderer.component.has_reactive_assignments = true;
18602 const lock = binding_group.bindings.some(binding => binding.needs_lock) ?
18603 block.get_unique_name(`${this.var.name}_updating`) :
18604 null;
18605 if (lock)
18606 block.add_variable(lock, x `false`);
18607 const handler = renderer.component.get_unique_name(`${this.var.name}_${binding_group.events.join('_')}_handler`);
18608 renderer.add_to_context(handler.name);
18609 // TODO figure out how to handle locks
18610 const needs_lock = binding_group.bindings.some(binding => binding.needs_lock);
18611 const dependencies = new Set();
18612 const contextual_dependencies = new Set();
18613 binding_group.bindings.forEach(binding => {
18614 // TODO this is a mess
18615 add_to_set(dependencies, binding.get_dependencies());
18616 add_to_set(contextual_dependencies, binding.handler.contextual_dependencies);
18617 binding.render(block, lock);
18618 });
18619 // media bindings — awkward special case. The native timeupdate events
18620 // fire too infrequently, so we need to take matters into our
18621 // own hands
18622 let animation_frame;
18623 if (binding_group.events[0] === 'timeupdate') {
18624 animation_frame = block.get_unique_name(`${this.var.name}_animationframe`);
18625 block.add_variable(animation_frame);
18626 }
18627 const has_local_function = contextual_dependencies.size > 0 || needs_lock || animation_frame;
18628 let callee = renderer.reference(handler);
18629 // TODO dry this out — similar code for event handlers and component bindings
18630 if (has_local_function) {
18631 const args = Array.from(contextual_dependencies).map(name => renderer.reference(name));
18632 // need to create a block-local function that calls an instance-level function
18633 if (animation_frame) {
18634 block.chunks.init.push(b `
18635 function ${handler}() {
18636 @_cancelAnimationFrame(${animation_frame});
18637 if (!${this.var}.paused) {
18638 ${animation_frame} = @raf(${handler});
18639 ${needs_lock && b `${lock} = true;`}
18640 }
18641 ${callee}.call(${this.var}, ${args});
18642 }
18643 `);
18644 }
18645 else {
18646 block.chunks.init.push(b `
18647 function ${handler}() {
18648 ${needs_lock && b `${lock} = true;`}
18649 ${callee}.call(${this.var}, ${args});
18650 }
18651 `);
18652 }
18653 callee = handler;
18654 }
18655 const params = Array.from(contextual_dependencies).map(name => ({
18656 type: 'Identifier',
18657 name
18658 }));
18659 this.renderer.component.partly_hoisted.push(b `
18660 function ${handler}(${params}) {
18661 ${binding_group.bindings.map(b => b.handler.mutation)}
18662 ${Array.from(dependencies)
18663 .filter(dep => dep[0] !== '$')
18664 .filter(dep => !contextual_dependencies.has(dep))
18665 .map(dep => b `${this.renderer.invalidate(dep)};`)}
18666 }
18667 `);
18668 binding_group.events.forEach(name => {
18669 if (name === 'elementresize') {
18670 // special case
18671 const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`);
18672 block.add_variable(resize_listener);
18673 block.chunks.mount.push(b `${resize_listener} = @add_resize_listener(${this.var}, ${callee}.bind(${this.var}));`);
18674 block.chunks.destroy.push(b `${resize_listener}();`);
18675 }
18676 else {
18677 block.event_listeners.push(x `@listen(${this.var}, "${name}", ${callee})`);
18678 }
18679 });
18680 const some_initial_state_is_undefined = binding_group.bindings
18681 .map(binding => x `${binding.snippet} === void 0`)
18682 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
18683 const should_initialise = (this.node.name === 'select' ||
18684 binding_group.bindings.find(binding => {
18685 return (binding.node.name === 'indeterminate' ||
18686 binding.node.name === 'textContent' ||
18687 binding.node.name === 'innerHTML' ||
18688 binding.is_readonly_media_attribute());
18689 }));
18690 if (should_initialise) {
18691 const callback = has_local_function ? handler : x `() => ${callee}.call(${this.var})`;
18692 block.chunks.hydrate.push(b `if (${some_initial_state_is_undefined}) @add_render_callback(${callback});`);
18693 }
18694 if (binding_group.events[0] === 'elementresize') {
18695 block.chunks.hydrate.push(b `@add_render_callback(() => ${callee}.call(${this.var}));`);
18696 }
18697 if (lock) {
18698 block.chunks.update.push(b `${lock} = false;`);
18699 }
18700 }
18701 add_this_binding(block, this_binding) {
18702 const { renderer } = this;
18703 renderer.component.has_reactive_assignments = true;
18704 const binding_callback = bind_this(renderer.component, block, this_binding, this.var);
18705 block.chunks.mount.push(binding_callback);
18706 }
18707 add_attributes(block) {
18708 // Get all the class dependencies first
18709 this.attributes.forEach((attribute) => {
18710 if (attribute.node.name === 'class') {
18711 const dependencies = attribute.node.get_dependencies();
18712 this.class_dependencies.push(...dependencies);
18713 }
18714 });
18715 if (this.node.attributes.some(attr => attr.is_spread)) {
18716 this.add_spread_attributes(block);
18717 return;
18718 }
18719 this.attributes.forEach((attribute) => {
18720 attribute.render(block);
18721 });
18722 }
18723 add_spread_attributes(block) {
18724 const levels = block.get_unique_name(`${this.var.name}_levels`);
18725 const data = block.get_unique_name(`${this.var.name}_data`);
18726 const initial_props = [];
18727 const updates = [];
18728 this.attributes
18729 .forEach(attr => {
18730 const condition = attr.node.dependencies.size > 0
18731 ? block.renderer.dirty(Array.from(attr.node.dependencies))
18732 : null;
18733 if (attr.node.is_spread) {
18734 const snippet = attr.node.expression.manipulate(block);
18735 initial_props.push(snippet);
18736 updates.push(condition ? x `${condition} && ${snippet}` : snippet);
18737 }
18738 else {
18739 const metadata = attr.get_metadata();
18740 const name = attr.is_indirectly_bound_value()
18741 ? '__value'
18742 : (metadata && metadata.property_name) || fix_attribute_casing(attr.node.name);
18743 const snippet = x `{ ${name}: ${attr.get_value(block)} }`;
18744 initial_props.push(snippet);
18745 updates.push(condition ? x `${condition} && ${snippet}` : snippet);
18746 }
18747 });
18748 block.chunks.init.push(b `
18749 let ${levels} = [${initial_props}];
18750
18751 let ${data} = {};
18752 for (let #i = 0; #i < ${levels}.length; #i += 1) {
18753 ${data} = @assign(${data}, ${levels}[#i]);
18754 }
18755 `);
18756 const fn = this.node.namespace === namespaces.svg ? x `@set_svg_attributes` : x `@set_attributes`;
18757 block.chunks.hydrate.push(b `${fn}(${this.var}, ${data});`);
18758 block.chunks.update.push(b `
18759 ${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
18760 ${updates}
18761 ]));
18762 `);
18763 // handle edge cases for elements
18764 if (this.node.name === 'select') {
18765 const dependencies = new Set();
18766 for (const attr of this.attributes) {
18767 for (const dep of attr.node.dependencies) {
18768 dependencies.add(dep);
18769 }
18770 }
18771 block.chunks.mount.push(b `
18772 if (${data}.multiple) @select_options(${this.var}, ${data}.value);
18773 `);
18774 block.chunks.update.push(b `
18775 if (${block.renderer.dirty(Array.from(dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value);
18776 `);
18777 }
18778 }
18779 add_transitions(block) {
18780 const { intro, outro } = this.node;
18781 if (!intro && !outro)
18782 return;
18783 if (intro === outro) {
18784 // bidirectional transition
18785 const name = block.get_unique_name(`${this.var.name}_transition`);
18786 const snippet = intro.expression
18787 ? intro.expression.manipulate(block)
18788 : x `{}`;
18789 block.add_variable(name);
18790 const fn = this.renderer.reference(intro.name);
18791 const intro_block = b `
18792 @add_render_callback(() => {
18793 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, true);
18794 ${name}.run(1);
18795 });
18796 `;
18797 const outro_block = b `
18798 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, false);
18799 ${name}.run(0);
18800 `;
18801 if (intro.is_local) {
18802 block.chunks.intro.push(b `
18803 if (#local) {
18804 ${intro_block}
18805 }
18806 `);
18807 block.chunks.outro.push(b `
18808 if (#local) {
18809 ${outro_block}
18810 }
18811 `);
18812 }
18813 else {
18814 block.chunks.intro.push(intro_block);
18815 block.chunks.outro.push(outro_block);
18816 }
18817 block.chunks.destroy.push(b `if (detaching && ${name}) ${name}.end();`);
18818 }
18819 else {
18820 const intro_name = intro && block.get_unique_name(`${this.var.name}_intro`);
18821 const outro_name = outro && block.get_unique_name(`${this.var.name}_outro`);
18822 if (intro) {
18823 block.add_variable(intro_name);
18824 const snippet = intro.expression
18825 ? intro.expression.manipulate(block)
18826 : x `{}`;
18827 const fn = this.renderer.reference(intro.name);
18828 let intro_block;
18829 if (outro) {
18830 intro_block = b `
18831 @add_render_callback(() => {
18832 if (${outro_name}) ${outro_name}.end(1);
18833 if (!${intro_name}) ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
18834 ${intro_name}.start();
18835 });
18836 `;
18837 block.chunks.outro.push(b `if (${intro_name}) ${intro_name}.invalidate();`);
18838 }
18839 else {
18840 intro_block = b `
18841 if (!${intro_name}) {
18842 @add_render_callback(() => {
18843 ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
18844 ${intro_name}.start();
18845 });
18846 }
18847 `;
18848 }
18849 if (intro.is_local) {
18850 intro_block = b `
18851 if (#local) {
18852 ${intro_block}
18853 }
18854 `;
18855 }
18856 block.chunks.intro.push(intro_block);
18857 }
18858 if (outro) {
18859 block.add_variable(outro_name);
18860 const snippet = outro.expression
18861 ? outro.expression.manipulate(block)
18862 : x `{}`;
18863 const fn = this.renderer.reference(outro.name);
18864 if (!intro) {
18865 block.chunks.intro.push(b `
18866 if (${outro_name}) ${outro_name}.end(1);
18867 `);
18868 }
18869 // TODO hide elements that have outro'd (unless they belong to a still-outroing
18870 // group) prior to their removal from the DOM
18871 let outro_block = b `
18872 ${outro_name} = @create_out_transition(${this.var}, ${fn}, ${snippet});
18873 `;
18874 if (outro.is_local) {
18875 outro_block = b `
18876 if (#local) {
18877 ${outro_block}
18878 }
18879 `;
18880 }
18881 block.chunks.outro.push(outro_block);
18882 block.chunks.destroy.push(b `if (detaching && ${outro_name}) ${outro_name}.end();`);
18883 }
18884 }
18885 }
18886 add_animation(block) {
18887 if (!this.node.animation)
18888 return;
18889 const { outro } = this.node;
18890 const rect = block.get_unique_name('rect');
18891 const stop_animation = block.get_unique_name('stop_animation');
18892 block.add_variable(rect);
18893 block.add_variable(stop_animation, x `@noop`);
18894 block.chunks.measure.push(b `
18895 ${rect} = ${this.var}.getBoundingClientRect();
18896 `);
18897 block.chunks.fix.push(b `
18898 @fix_position(${this.var});
18899 ${stop_animation}();
18900 ${outro && b `@add_transform(${this.var}, ${rect});`}
18901 `);
18902 const params = this.node.animation.expression ? this.node.animation.expression.manipulate(block) : x `{}`;
18903 const name = this.renderer.reference(this.node.animation.name);
18904 block.chunks.animate.push(b `
18905 ${stop_animation}();
18906 ${stop_animation} = @create_animation(${this.var}, ${rect}, ${name}, ${params});
18907 `);
18908 }
18909 add_classes(block) {
18910 const has_spread = this.node.attributes.some(attr => attr.is_spread);
18911 this.node.classes.forEach(class_directive => {
18912 const { expression, name } = class_directive;
18913 let snippet;
18914 let dependencies;
18915 if (expression) {
18916 snippet = expression.manipulate(block);
18917 dependencies = expression.dependencies;
18918 }
18919 else {
18920 snippet = name;
18921 dependencies = new Set([name]);
18922 }
18923 const updater = b `@toggle_class(${this.var}, "${name}", ${snippet});`;
18924 block.chunks.hydrate.push(updater);
18925 if (has_spread) {
18926 block.chunks.update.push(updater);
18927 }
18928 else if ((dependencies && dependencies.size > 0) || this.class_dependencies.length) {
18929 const all_dependencies = this.class_dependencies.concat(...dependencies);
18930 const condition = block.renderer.dirty(all_dependencies);
18931 block.chunks.update.push(b `
18932 if (${condition}) {
18933 ${updater}
18934 }`);
18935 }
18936 });
18937 }
18938 add_manual_style_scoping(block) {
18939 if (this.node.needs_manual_style_scoping) {
18940 const updater = b `@toggle_class(${this.var}, "${this.node.component.stylesheet.id}", true);`;
18941 block.chunks.hydrate.push(updater);
18942 block.chunks.update.push(updater);
18943 }
18944 }
18945 }
18946 function to_html(wrappers, block, literal, state, can_use_raw_text) {
18947 wrappers.forEach(wrapper => {
18948 if (wrapper.node.type === 'Text') {
18949 if (wrapper.use_space())
18950 state.quasi.value.raw += ' ';
18951 const parent = wrapper.node.parent;
18952 const raw = parent && (parent.name === 'script' ||
18953 parent.name === 'style' ||
18954 can_use_raw_text);
18955 state.quasi.value.raw += (raw ? wrapper.node.data : escape_html(wrapper.node.data))
18956 .replace(/\\/g, '\\\\')
18957 .replace(/`/g, '\\`')
18958 .replace(/\$/g, '\\$');
18959 }
18960 else if (wrapper.node.type === 'MustacheTag' || wrapper.node.type === 'RawMustacheTag') {
18961 literal.quasis.push(state.quasi);
18962 literal.expressions.push(wrapper.node.expression.manipulate(block));
18963 state.quasi = {
18964 type: 'TemplateElement',
18965 value: { raw: '' }
18966 };
18967 }
18968 else if (wrapper.node.name === 'noscript') ;
18969 else {
18970 // element
18971 state.quasi.value.raw += `<${wrapper.node.name}`;
18972 wrapper.attributes.forEach((attr) => {
18973 state.quasi.value.raw += ` ${fix_attribute_casing(attr.node.name)}="`;
18974 attr.node.chunks.forEach(chunk => {
18975 if (chunk.type === 'Text') {
18976 state.quasi.value.raw += escape_html(chunk.data);
18977 }
18978 else {
18979 literal.quasis.push(state.quasi);
18980 literal.expressions.push(chunk.manipulate(block));
18981 state.quasi = {
18982 type: 'TemplateElement',
18983 value: { raw: '' }
18984 };
18985 }
18986 });
18987 state.quasi.value.raw += `"`;
18988 });
18989 state.quasi.value.raw += '>';
18990 if (!wrapper.void) {
18991 to_html(wrapper.fragment.nodes, block, literal, state);
18992 state.quasi.value.raw += `</${wrapper.node.name}>`;
18993 }
18994 }
18995 });
18996 }
18997
18998 class HeadWrapper extends Wrapper {
18999 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19000 super(renderer, block, parent, node);
19001 this.can_use_innerhtml = false;
19002 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
19003 }
19004 render(block, _parent_node, _parent_nodes) {
19005 let nodes;
19006 if (this.renderer.options.hydratable && this.fragment.nodes.length) {
19007 nodes = block.get_unique_name('head_nodes');
19008 block.chunks.claim.push(b `const ${nodes} = @query_selector_all('[data-svelte="${this.node.id}"]', @_document.head);`);
19009 }
19010 this.fragment.render(block, x `@_document.head`, nodes);
19011 if (nodes && this.renderer.options.hydratable) {
19012 block.chunks.claim.push(b `${nodes}.forEach(@detach);`);
19013 }
19014 }
19015 }
19016
19017 function is_else_if(node) {
19018 return (node && node.children.length === 1 && node.children[0].type === 'IfBlock');
19019 }
19020 class IfBlockBranch extends Wrapper {
19021 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19022 super(renderer, block, parent, node);
19023 this.var = null;
19024 const { expression } = node;
19025 const is_else = !expression;
19026 if (expression) {
19027 this.dependencies = expression.dynamic_dependencies();
19028 // TODO is this the right rule? or should any non-reference count?
19029 // const should_cache = !is_reference(expression.node, null) && dependencies.length > 0;
19030 let should_cache = false;
19031 walk(expression.node, {
19032 enter(node) {
19033 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
19034 should_cache = true;
19035 }
19036 }
19037 });
19038 if (should_cache) {
19039 this.condition = block.get_unique_name(`show_if`);
19040 this.snippet = expression.manipulate(block);
19041 }
19042 else {
19043 this.condition = expression.manipulate(block);
19044 }
19045 }
19046 this.block = block.child({
19047 comment: create_debugging_comment(node, parent.renderer.component),
19048 name: parent.renderer.component.get_unique_name(is_else ? `create_else_block` : `create_if_block`),
19049 type: node.expression ? 'if' : 'else'
19050 });
19051 this.fragment = new FragmentWrapper(renderer, this.block, node.children, parent, strip_whitespace, next_sibling);
19052 this.is_dynamic = this.block.dependencies.size > 0;
19053 }
19054 }
19055 class IfBlockWrapper extends Wrapper {
19056 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19057 super(renderer, block, parent, node);
19058 this.needs_update = false;
19059 this.var = { type: 'Identifier', name: 'if_block' };
19060 this.cannot_use_innerhtml();
19061 this.not_static_content();
19062 this.branches = [];
19063 const blocks = [];
19064 let is_dynamic = false;
19065 let has_intros = false;
19066 let has_outros = false;
19067 const create_branches = (node) => {
19068 const branch = new IfBlockBranch(renderer, block, this, node, strip_whitespace, next_sibling);
19069 this.branches.push(branch);
19070 blocks.push(branch.block);
19071 block.add_dependencies(node.expression.dependencies);
19072 if (branch.block.dependencies.size > 0) {
19073 // the condition, or its contents, is dynamic
19074 is_dynamic = true;
19075 block.add_dependencies(branch.block.dependencies);
19076 }
19077 if (branch.dependencies && branch.dependencies.length > 0) {
19078 // the condition itself is dynamic
19079 this.needs_update = true;
19080 }
19081 if (branch.block.has_intros)
19082 has_intros = true;
19083 if (branch.block.has_outros)
19084 has_outros = true;
19085 if (is_else_if(node.else)) {
19086 create_branches(node.else.children[0]);
19087 }
19088 else if (node.else) {
19089 const branch = new IfBlockBranch(renderer, block, this, node.else, strip_whitespace, next_sibling);
19090 this.branches.push(branch);
19091 blocks.push(branch.block);
19092 if (branch.block.dependencies.size > 0) {
19093 is_dynamic = true;
19094 block.add_dependencies(branch.block.dependencies);
19095 }
19096 if (branch.block.has_intros)
19097 has_intros = true;
19098 if (branch.block.has_outros)
19099 has_outros = true;
19100 }
19101 };
19102 create_branches(this.node);
19103 blocks.forEach(block => {
19104 block.has_update_method = is_dynamic;
19105 block.has_intro_method = has_intros;
19106 block.has_outro_method = has_outros;
19107 });
19108 renderer.blocks.push(...blocks);
19109 }
19110 render(block, parent_node, parent_nodes) {
19111 const name = this.var;
19112 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
19113 const anchor = needs_anchor
19114 ? block.get_unique_name(`${this.var.name}_anchor`)
19115 : (this.next && this.next.var) || 'null';
19116 const has_else = !(this.branches[this.branches.length - 1].condition);
19117 const if_exists_condition = has_else ? null : name;
19118 const dynamic = this.branches[0].block.has_update_method; // can use [0] as proxy for all, since they necessarily have the same value
19119 const has_intros = this.branches[0].block.has_intro_method;
19120 const has_outros = this.branches[0].block.has_outro_method;
19121 const has_transitions = has_intros || has_outros;
19122 const vars = { name, anchor, if_exists_condition, has_else, has_transitions };
19123 const detaching = parent_node && !is_head(parent_node) ? null : 'detaching';
19124 if (this.node.else) {
19125 this.branches.forEach(branch => {
19126 if (branch.snippet)
19127 block.add_variable(branch.condition);
19128 });
19129 if (has_outros) {
19130 this.render_compound_with_outros(block, parent_node, parent_nodes, dynamic, vars, detaching);
19131 block.chunks.outro.push(b `@transition_out(${name});`);
19132 }
19133 else {
19134 this.render_compound(block, parent_node, parent_nodes, dynamic, vars, detaching);
19135 }
19136 }
19137 else {
19138 this.render_simple(block, parent_node, parent_nodes, dynamic, vars, detaching);
19139 if (has_outros) {
19140 block.chunks.outro.push(b `@transition_out(${name});`);
19141 }
19142 }
19143 if (if_exists_condition) {
19144 block.chunks.create.push(b `if (${if_exists_condition}) ${name}.c();`);
19145 }
19146 else {
19147 block.chunks.create.push(b `${name}.c();`);
19148 }
19149 if (parent_nodes && this.renderer.options.hydratable) {
19150 if (if_exists_condition) {
19151 block.chunks.claim.push(b `if (${if_exists_condition}) ${name}.l(${parent_nodes});`);
19152 }
19153 else {
19154 block.chunks.claim.push(b `${name}.l(${parent_nodes});`);
19155 }
19156 }
19157 if (has_intros || has_outros) {
19158 block.chunks.intro.push(b `@transition_in(${name});`);
19159 }
19160 if (needs_anchor) {
19161 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
19162 }
19163 this.branches.forEach(branch => {
19164 branch.fragment.render(branch.block, null, x `#nodes`);
19165 });
19166 }
19167 render_compound(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, if_exists_condition, has_transitions }, detaching) {
19168 const select_block_type = this.renderer.component.get_unique_name(`select_block_type`);
19169 const current_block_type = block.get_unique_name(`current_block_type`);
19170 const get_block = has_else
19171 ? x `${current_block_type}(#ctx)`
19172 : x `${current_block_type} && ${current_block_type}(#ctx)`;
19173 if (this.needs_update) {
19174 block.chunks.init.push(b `
19175 function ${select_block_type}(#ctx, #dirty) {
19176 ${this.branches.map(({ dependencies, condition, snippet, block }) => condition
19177 ? b `
19178 ${snippet && (dependencies.length > 0
19179 ? b `if (${condition} == null || ${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
19180 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
19181 if (${condition}) return ${block.name};`
19182 : b `return ${block.name};`)}
19183 }
19184 `);
19185 }
19186 else {
19187 block.chunks.init.push(b `
19188 function ${select_block_type}(#ctx, #dirty) {
19189 ${this.branches.map(({ condition, snippet, block }) => condition
19190 ? b `if (${snippet || condition}) return ${block.name};`
19191 : b `return ${block.name};`)}
19192 }
19193 `);
19194 }
19195 block.chunks.init.push(b `
19196 let ${current_block_type} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
19197 let ${name} = ${get_block};
19198 `);
19199 const initial_mount_node = parent_node || '#target';
19200 const anchor_node = parent_node ? 'null' : '#anchor';
19201 if (if_exists_condition) {
19202 block.chunks.mount.push(b `if (${if_exists_condition}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
19203 }
19204 else {
19205 block.chunks.mount.push(b `${name}.m(${initial_mount_node}, ${anchor_node});`);
19206 }
19207 if (this.needs_update) {
19208 const update_mount_node = this.get_update_mount_node(anchor);
19209 const change_block = b `
19210 ${if_exists_condition ? b `if (${if_exists_condition}) ${name}.d(1)` : b `${name}.d(1)`};
19211 ${name} = ${get_block};
19212 if (${name}) {
19213 ${name}.c();
19214 ${has_transitions && b `@transition_in(${name}, 1);`}
19215 ${name}.m(${update_mount_node}, ${anchor});
19216 }
19217 `;
19218 if (dynamic) {
19219 block.chunks.update.push(b `
19220 if (${current_block_type} === (${current_block_type} = ${select_block_type}(#ctx, #dirty)) && ${name}) {
19221 ${name}.p(#ctx, #dirty);
19222 } else {
19223 ${change_block}
19224 }
19225 `);
19226 }
19227 else {
19228 block.chunks.update.push(b `
19229 if (${current_block_type} !== (${current_block_type} = ${select_block_type}(#ctx, #dirty))) {
19230 ${change_block}
19231 }
19232 `);
19233 }
19234 }
19235 else if (dynamic) {
19236 if (if_exists_condition) {
19237 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
19238 }
19239 else {
19240 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
19241 }
19242 }
19243 if (if_exists_condition) {
19244 block.chunks.destroy.push(b `
19245 if (${if_exists_condition}) {
19246 ${name}.d(${detaching});
19247 }
19248 `);
19249 }
19250 else {
19251 block.chunks.destroy.push(b `
19252 ${name}.d(${detaching});
19253 `);
19254 }
19255 }
19256 // if any of the siblings have outros, we need to keep references to the blocks
19257 // (TODO does this only apply to bidi transitions?)
19258 render_compound_with_outros(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, has_transitions, if_exists_condition }, detaching) {
19259 const select_block_type = this.renderer.component.get_unique_name(`select_block_type`);
19260 const current_block_type_index = block.get_unique_name(`current_block_type_index`);
19261 const previous_block_index = block.get_unique_name(`previous_block_index`);
19262 const if_block_creators = block.get_unique_name(`if_block_creators`);
19263 const if_blocks = block.get_unique_name(`if_blocks`);
19264 const if_current_block_type_index = has_else
19265 ? nodes => nodes
19266 : nodes => b `if (~${current_block_type_index}) { ${nodes} }`;
19267 block.add_variable(current_block_type_index);
19268 block.add_variable(name);
19269 block.chunks.init.push(b `
19270 const ${if_block_creators} = [
19271 ${this.branches.map(branch => branch.block.name)}
19272 ];
19273
19274 const ${if_blocks} = [];
19275
19276 ${this.needs_update
19277 ? b `
19278 function ${select_block_type}(#ctx, #dirty) {
19279 ${this.branches.map(({ dependencies, condition, snippet }, i) => condition
19280 ? b `
19281 ${snippet && (dependencies.length > 0
19282 ? b `if (${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
19283 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
19284 if (${condition}) return ${i};`
19285 : b `return ${i};`)}
19286 ${!has_else && b `return -1;`}
19287 }
19288 `
19289 : b `
19290 function ${select_block_type}(#ctx, #dirty) {
19291 ${this.branches.map(({ condition, snippet }, i) => condition
19292 ? b `if (${snippet || condition}) return ${i};`
19293 : b `return ${i};`)}
19294 ${!has_else && b `return -1;`}
19295 }
19296 `}
19297 `);
19298 if (has_else) {
19299 block.chunks.init.push(b `
19300 ${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
19301 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19302 `);
19303 }
19304 else {
19305 block.chunks.init.push(b `
19306 if (~(${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}))) {
19307 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19308 }
19309 `);
19310 }
19311 const initial_mount_node = parent_node || '#target';
19312 const anchor_node = parent_node ? 'null' : '#anchor';
19313 block.chunks.mount.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].m(${initial_mount_node}, ${anchor_node});`));
19314 if (this.needs_update) {
19315 const update_mount_node = this.get_update_mount_node(anchor);
19316 const destroy_old_block = b `
19317 @group_outros();
19318 @transition_out(${if_blocks}[${previous_block_index}], 1, 1, () => {
19319 ${if_blocks}[${previous_block_index}] = null;
19320 });
19321 @check_outros();
19322 `;
19323 const create_new_block = b `
19324 ${name} = ${if_blocks}[${current_block_type_index}];
19325 if (!${name}) {
19326 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
19327 ${name}.c();
19328 }
19329 ${has_transitions && b `@transition_in(${name}, 1);`}
19330 ${name}.m(${update_mount_node}, ${anchor});
19331 `;
19332 const change_block = has_else
19333 ? b `
19334 ${destroy_old_block}
19335
19336 ${create_new_block}
19337 `
19338 : b `
19339 if (${name}) {
19340 ${destroy_old_block}
19341 }
19342
19343 if (~${current_block_type_index}) {
19344 ${create_new_block}
19345 } else {
19346 ${name} = null;
19347 }
19348 `;
19349 if (dynamic) {
19350 block.chunks.update.push(b `
19351 let ${previous_block_index} = ${current_block_type_index};
19352 ${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
19353 if (${current_block_type_index} === ${previous_block_index}) {
19354 ${if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].p(#ctx, #dirty);`)}
19355 } else {
19356 ${change_block}
19357 }
19358 `);
19359 }
19360 else {
19361 block.chunks.update.push(b `
19362 let ${previous_block_index} = ${current_block_type_index};
19363 ${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
19364 if (${current_block_type_index} !== ${previous_block_index}) {
19365 ${change_block}
19366 }
19367 `);
19368 }
19369 }
19370 else if (dynamic) {
19371 if (if_exists_condition) {
19372 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
19373 }
19374 else {
19375 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
19376 }
19377 }
19378 block.chunks.destroy.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].d(${detaching});`));
19379 }
19380 render_simple(block, parent_node, _parent_nodes, dynamic, { name, anchor, if_exists_condition, has_transitions }, detaching) {
19381 const branch = this.branches[0];
19382 if (branch.snippet)
19383 block.add_variable(branch.condition, branch.snippet);
19384 block.chunks.init.push(b `
19385 let ${name} = ${branch.condition} && ${branch.block.name}(#ctx);
19386 `);
19387 const initial_mount_node = parent_node || '#target';
19388 const anchor_node = parent_node ? 'null' : '#anchor';
19389 block.chunks.mount.push(b `if (${name}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
19390 if (branch.dependencies.length > 0) {
19391 const update_mount_node = this.get_update_mount_node(anchor);
19392 const enter = b `
19393 if (${name}) {
19394 ${dynamic && b `${name}.p(#ctx, #dirty);`}
19395 ${has_transitions &&
19396 b `if (${block.renderer.dirty(branch.dependencies)}) {
19397 @transition_in(${name}, 1);
19398 }`}
19399 } else {
19400 ${name} = ${branch.block.name}(#ctx);
19401 ${name}.c();
19402 ${has_transitions && b `@transition_in(${name}, 1);`}
19403 ${name}.m(${update_mount_node}, ${anchor});
19404 }
19405 `;
19406 if (branch.snippet) {
19407 block.chunks.update.push(b `if (${block.renderer.dirty(branch.dependencies)}) ${branch.condition} = ${branch.snippet}`);
19408 }
19409 // no `p()` here — we don't want to update outroing nodes,
19410 // as that will typically result in glitching
19411 if (branch.block.has_outro_method) {
19412 block.chunks.update.push(b `
19413 if (${branch.condition}) {
19414 ${enter}
19415 } else if (${name}) {
19416 @group_outros();
19417 @transition_out(${name}, 1, 1, () => {
19418 ${name} = null;
19419 });
19420 @check_outros();
19421 }
19422 `);
19423 }
19424 else {
19425 block.chunks.update.push(b `
19426 if (${branch.condition}) {
19427 ${enter}
19428 } else if (${name}) {
19429 ${name}.d(1);
19430 ${name} = null;
19431 }
19432 `);
19433 }
19434 }
19435 else if (dynamic) {
19436 block.chunks.update.push(b `
19437 if (${branch.condition}) ${name}.p(#ctx, #dirty);
19438 `);
19439 }
19440 if (if_exists_condition) {
19441 block.chunks.destroy.push(b `
19442 if (${if_exists_condition}) ${name}.d(${detaching});
19443 `);
19444 }
19445 else {
19446 block.chunks.destroy.push(b `
19447 ${name}.d(${detaching});
19448 `);
19449 }
19450 }
19451 get_initial_dirty_bit() {
19452 const _this = this;
19453 // TODO: context-overflow make it less gross
19454 const val = x `-1`;
19455 return {
19456 get type() {
19457 return _this.renderer.context_overflow ? 'ArrayExpression' : 'UnaryExpression';
19458 },
19459 // as [-1]
19460 elements: [val],
19461 // as -1
19462 operator: val.operator,
19463 prefix: val.prefix,
19464 argument: val.argument,
19465 };
19466 }
19467 }
19468
19469 class InlineComponentWrapper extends Wrapper {
19470 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19471 super(renderer, block, parent, node);
19472 this.slots = new Map();
19473 this.cannot_use_innerhtml();
19474 this.not_static_content();
19475 if (this.node.expression) {
19476 block.add_dependencies(this.node.expression.dependencies);
19477 }
19478 this.node.attributes.forEach(attr => {
19479 block.add_dependencies(attr.dependencies);
19480 });
19481 this.node.bindings.forEach(binding => {
19482 if (binding.is_contextual) {
19483 // we need to ensure that the each block creates a context including
19484 // the list and the index, if they're not otherwise referenced
19485 const { name } = get_object(binding.expression.node);
19486 const each_block = this.node.scope.get_owner(name);
19487 each_block.has_binding = true;
19488 }
19489 block.add_dependencies(binding.expression.dependencies);
19490 });
19491 this.node.handlers.forEach(handler => {
19492 if (handler.expression) {
19493 block.add_dependencies(handler.expression.dependencies);
19494 }
19495 });
19496 this.var = {
19497 type: 'Identifier',
19498 name: (this.node.name === 'svelte:self' ? renderer.component.name.name :
19499 this.node.name === 'svelte:component' ? 'switch_instance' :
19500 sanitize(this.node.name)).toLowerCase()
19501 };
19502 if (this.node.children.length) {
19503 this.node.lets.forEach(l => {
19504 extract_names(l.value || l.name).forEach(name => {
19505 renderer.add_to_context(name, true);
19506 });
19507 });
19508 const default_slot = block.child({
19509 comment: create_debugging_comment(node, renderer.component),
19510 name: renderer.component.get_unique_name(`create_default_slot`),
19511 type: 'slot'
19512 });
19513 this.renderer.blocks.push(default_slot);
19514 this.slots.set('default', get_slot_definition(default_slot, this.node.scope, this.node.lets));
19515 this.fragment = new FragmentWrapper(renderer, default_slot, node.children, this, strip_whitespace, next_sibling);
19516 const dependencies = new Set();
19517 // TODO is this filtering necessary? (I *think* so)
19518 default_slot.dependencies.forEach(name => {
19519 if (!this.node.scope.is_let(name)) {
19520 dependencies.add(name);
19521 }
19522 });
19523 block.add_dependencies(dependencies);
19524 }
19525 block.add_outro();
19526 }
19527 warn_if_reactive() {
19528 const { name } = this.node;
19529 const variable = this.renderer.component.var_lookup.get(name);
19530 if (!variable) {
19531 return;
19532 }
19533 if (variable.reassigned || variable.export_name || variable.is_reactive_dependency) {
19534 this.renderer.component.warn(this.node, {
19535 code: 'reactive-component',
19536 message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`,
19537 });
19538 }
19539 }
19540 render(block, parent_node, parent_nodes) {
19541 this.warn_if_reactive();
19542 const { renderer } = this;
19543 const { component } = renderer;
19544 const name = this.var;
19545 const component_opts = x `{}`;
19546 const statements = [];
19547 const updates = [];
19548 if (this.fragment) {
19549 this.renderer.add_to_context('$$scope', true);
19550 const default_slot = this.slots.get('default');
19551 this.fragment.nodes.forEach((child) => {
19552 child.render(default_slot.block, null, x `#nodes`);
19553 });
19554 }
19555 let props;
19556 const name_changes = block.get_unique_name(`${name.name}_changes`);
19557 const uses_spread = !!this.node.attributes.find(a => a.is_spread);
19558 // removing empty slot
19559 for (const slot of this.slots.keys()) {
19560 if (!this.slots.get(slot).block.has_content()) {
19561 this.renderer.remove_block(this.slots.get(slot).block);
19562 this.slots.delete(slot);
19563 }
19564 }
19565 const initial_props = this.slots.size > 0
19566 ? [
19567 p `$$slots: {
19568 ${Array.from(this.slots).map(([name, slot]) => {
19569 return p `${name}: [${slot.block.name}, ${slot.get_context || null}, ${slot.get_changes || null}]`;
19570 })}
19571 }`,
19572 p `$$scope: {
19573 ctx: #ctx
19574 }`
19575 ]
19576 : [];
19577 const attribute_object = uses_spread
19578 ? x `{ ${initial_props} }`
19579 : x `{
19580 ${this.node.attributes.map(attr => p `${attr.name}: ${attr.get_value(block)}`)},
19581 ${initial_props}
19582 }`;
19583 if (this.node.attributes.length || this.node.bindings.length || initial_props.length) {
19584 if (!uses_spread && this.node.bindings.length === 0) {
19585 component_opts.properties.push(p `props: ${attribute_object}`);
19586 }
19587 else {
19588 props = block.get_unique_name(`${name.name}_props`);
19589 component_opts.properties.push(p `props: ${props}`);
19590 }
19591 }
19592 if (component.compile_options.dev) {
19593 // TODO this is a terrible hack, but without it the component
19594 // will complain that options.target is missing. This would
19595 // work better if components had separate public and private
19596 // APIs
19597 component_opts.properties.push(p `$$inline: true`);
19598 }
19599 const fragment_dependencies = new Set(this.fragment ? ['$$scope'] : []);
19600 this.slots.forEach(slot => {
19601 slot.block.dependencies.forEach(name => {
19602 const is_let = slot.scope.is_let(name);
19603 const variable = renderer.component.var_lookup.get(name);
19604 if (is_let || is_dynamic$1(variable))
19605 fragment_dependencies.add(name);
19606 });
19607 });
19608 const dynamic_attributes = this.node.attributes.filter(a => a.get_dependencies().length > 0);
19609 if (!uses_spread && (dynamic_attributes.length > 0 || this.node.bindings.length > 0 || fragment_dependencies.size > 0)) {
19610 updates.push(b `const ${name_changes} = {};`);
19611 }
19612 if (this.node.attributes.length) {
19613 if (uses_spread) {
19614 const levels = block.get_unique_name(`${this.var.name}_spread_levels`);
19615 const initial_props = [];
19616 const changes = [];
19617 const all_dependencies = new Set();
19618 this.node.attributes.forEach(attr => {
19619 add_to_set(all_dependencies, attr.dependencies);
19620 });
19621 this.node.attributes.forEach((attr, i) => {
19622 const { name, dependencies } = attr;
19623 const condition = dependencies.size > 0 && (dependencies.size !== all_dependencies.size)
19624 ? renderer.dirty(Array.from(dependencies))
19625 : null;
19626 const unchanged = dependencies.size === 0;
19627 let change_object;
19628 if (attr.is_spread) {
19629 const value = attr.expression.manipulate(block);
19630 initial_props.push(value);
19631 let value_object = value;
19632 if (attr.expression.node.type !== 'ObjectExpression') {
19633 value_object = x `@get_spread_object(${value})`;
19634 }
19635 change_object = value_object;
19636 }
19637 else {
19638 const obj = x `{ ${name}: ${attr.get_value(block)} }`;
19639 initial_props.push(obj);
19640 change_object = obj;
19641 }
19642 changes.push(unchanged
19643 ? x `${levels}[${i}]`
19644 : condition
19645 ? x `${condition} && ${change_object}`
19646 : change_object);
19647 });
19648 block.chunks.init.push(b `
19649 const ${levels} = [
19650 ${initial_props}
19651 ];
19652 `);
19653 statements.push(b `
19654 for (let #i = 0; #i < ${levels}.length; #i += 1) {
19655 ${props} = @assign(${props}, ${levels}[#i]);
19656 }
19657 `);
19658 if (all_dependencies.size) {
19659 const condition = renderer.dirty(Array.from(all_dependencies));
19660 updates.push(b `
19661 const ${name_changes} = ${condition} ? @get_spread_update(${levels}, [
19662 ${changes}
19663 ]) : {}
19664 `);
19665 }
19666 else {
19667 updates.push(b `
19668 const ${name_changes} = {};
19669 `);
19670 }
19671 }
19672 else {
19673 dynamic_attributes.forEach((attribute) => {
19674 const dependencies = attribute.get_dependencies();
19675 if (dependencies.length > 0) {
19676 const condition = renderer.dirty(dependencies);
19677 updates.push(b `
19678 if (${condition}) ${name_changes}.${attribute.name} = ${attribute.get_value(block)};
19679 `);
19680 }
19681 });
19682 }
19683 }
19684 if (fragment_dependencies.size > 0) {
19685 updates.push(b `
19686 if (${renderer.dirty(Array.from(fragment_dependencies))}) {
19687 ${name_changes}.$$scope = { dirty: #dirty, ctx: #ctx };
19688 }`);
19689 }
19690 const munged_bindings = this.node.bindings.map(binding => {
19691 component.has_reactive_assignments = true;
19692 if (binding.name === 'this') {
19693 return bind_this(component, block, new BindingWrapper(block, binding, this), this.var);
19694 }
19695 const id = component.get_unique_name(`${this.var.name}_${binding.name}_binding`);
19696 renderer.add_to_context(id.name);
19697 const callee = renderer.reference(id);
19698 const updating = block.get_unique_name(`updating_${binding.name}`);
19699 block.add_variable(updating);
19700 const snippet = binding.expression.manipulate(block);
19701 statements.push(b `
19702 if (${snippet} !== void 0) {
19703 ${props}.${binding.name} = ${snippet};
19704 }`);
19705 updates.push(b `
19706 if (!${updating} && ${renderer.dirty(Array.from(binding.expression.dependencies))}) {
19707 ${updating} = true;
19708 ${name_changes}.${binding.name} = ${snippet};
19709 @add_flush_callback(() => ${updating} = false);
19710 }
19711 `);
19712 const contextual_dependencies = Array.from(binding.expression.contextual_dependencies);
19713 const dependencies = Array.from(binding.expression.dependencies);
19714 let lhs = binding.raw_expression;
19715 if (binding.is_contextual && binding.expression.node.type === 'Identifier') {
19716 // bind:x={y} — we can't just do `y = x`, we need to
19717 // to `array[index] = x;
19718 const { name } = binding.expression.node;
19719 const { object, property, snippet } = block.bindings.get(name);
19720 lhs = snippet;
19721 contextual_dependencies.push(object.name, property.name);
19722 }
19723 const params = [x `#value`];
19724 if (contextual_dependencies.length > 0) {
19725 const args = [];
19726 contextual_dependencies.forEach(name => {
19727 params.push({
19728 type: 'Identifier',
19729 name
19730 });
19731 renderer.add_to_context(name, true);
19732 args.push(renderer.reference(name));
19733 });
19734 block.chunks.init.push(b `
19735 function ${id}(#value) {
19736 ${callee}.call(null, #value, ${args});
19737 }
19738 `);
19739 block.maintain_context = true; // TODO put this somewhere more logical
19740 }
19741 else {
19742 block.chunks.init.push(b `
19743 function ${id}(#value) {
19744 ${callee}.call(null, #value);
19745 }
19746 `);
19747 }
19748 const body = b `
19749 function ${id}(${params}) {
19750 ${lhs} = #value;
19751 ${renderer.invalidate(dependencies[0])};
19752 }
19753 `;
19754 component.partly_hoisted.push(body);
19755 return b `@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
19756 });
19757 const munged_handlers = this.node.handlers.map(handler => {
19758 const event_handler = new EventHandlerWrapper(handler, this);
19759 let snippet = event_handler.get_snippet(block);
19760 if (handler.modifiers.has('once'))
19761 snippet = x `@once(${snippet})`;
19762 return b `${name}.$on("${handler.name}", ${snippet});`;
19763 });
19764 if (this.node.name === 'svelte:component') {
19765 const switch_value = block.get_unique_name('switch_value');
19766 const switch_props = block.get_unique_name('switch_props');
19767 const snippet = this.node.expression.manipulate(block);
19768 block.chunks.init.push(b `
19769 var ${switch_value} = ${snippet};
19770
19771 function ${switch_props}(#ctx) {
19772 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
19773 ${props && b `let ${props} = ${attribute_object};`}`}
19774 ${statements}
19775 return ${component_opts};
19776 }
19777
19778 if (${switch_value}) {
19779 var ${name} = new ${switch_value}(${switch_props}(#ctx));
19780
19781 ${munged_bindings}
19782 ${munged_handlers}
19783 }
19784 `);
19785 block.chunks.create.push(b `if (${name}) @create_component(${name}.$$.fragment);`);
19786 if (parent_nodes && this.renderer.options.hydratable) {
19787 block.chunks.claim.push(b `if (${name}) @claim_component(${name}.$$.fragment, ${parent_nodes});`);
19788 }
19789 block.chunks.mount.push(b `
19790 if (${name}) {
19791 @mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
19792 }
19793 `);
19794 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
19795 const update_mount_node = this.get_update_mount_node(anchor);
19796 if (updates.length) {
19797 block.chunks.update.push(b `
19798 ${updates}
19799 `);
19800 }
19801 block.chunks.update.push(b `
19802 if (${switch_value} !== (${switch_value} = ${snippet})) {
19803 if (${name}) {
19804 @group_outros();
19805 const old_component = ${name};
19806 @transition_out(old_component.$$.fragment, 1, 0, () => {
19807 @destroy_component(old_component, 1);
19808 });
19809 @check_outros();
19810 }
19811
19812 if (${switch_value}) {
19813 ${name} = new ${switch_value}(${switch_props}(#ctx));
19814
19815 ${munged_bindings}
19816 ${munged_handlers}
19817
19818 @create_component(${name}.$$.fragment);
19819 @transition_in(${name}.$$.fragment, 1);
19820 @mount_component(${name}, ${update_mount_node}, ${anchor});
19821 } else {
19822 ${name} = null;
19823 }
19824 } else if (${switch_value}) {
19825 ${updates.length && b `${name}.$set(${name_changes});`}
19826 }
19827 `);
19828 block.chunks.intro.push(b `
19829 if (${name}) @transition_in(${name}.$$.fragment, #local);
19830 `);
19831 block.chunks.outro.push(b `if (${name}) @transition_out(${name}.$$.fragment, #local);`);
19832 block.chunks.destroy.push(b `if (${name}) @destroy_component(${name}, ${parent_node ? null : 'detaching'});`);
19833 }
19834 else {
19835 const expression = this.node.name === 'svelte:self'
19836 ? component.name
19837 : this.renderer.reference(this.node.name);
19838 block.chunks.init.push(b `
19839 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
19840 ${props && b `let ${props} = ${attribute_object};`}`}
19841 ${statements}
19842 const ${name} = new ${expression}(${component_opts});
19843
19844 ${munged_bindings}
19845 ${munged_handlers}
19846 `);
19847 block.chunks.create.push(b `@create_component(${name}.$$.fragment);`);
19848 if (parent_nodes && this.renderer.options.hydratable) {
19849 block.chunks.claim.push(b `@claim_component(${name}.$$.fragment, ${parent_nodes});`);
19850 }
19851 block.chunks.mount.push(b `@mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});`);
19852 block.chunks.intro.push(b `
19853 @transition_in(${name}.$$.fragment, #local);
19854 `);
19855 if (updates.length) {
19856 block.chunks.update.push(b `
19857 ${updates}
19858 ${name}.$set(${name_changes});
19859 `);
19860 }
19861 block.chunks.destroy.push(b `
19862 @destroy_component(${name}, ${parent_node ? null : 'detaching'});
19863 `);
19864 block.chunks.outro.push(b `@transition_out(${name}.$$.fragment, #local);`);
19865 }
19866 }
19867 }
19868
19869 class Tag extends Wrapper {
19870 constructor(renderer, block, parent, node) {
19871 super(renderer, block, parent, node);
19872 this.cannot_use_innerhtml();
19873 if (!this.is_dependencies_static()) {
19874 this.not_static_content();
19875 }
19876 block.add_dependencies(node.expression.dependencies);
19877 }
19878 is_dependencies_static() {
19879 return this.node.expression.contextual_dependencies.size === 0 && this.node.expression.dynamic_dependencies().length === 0;
19880 }
19881 rename_this_method(block, update) {
19882 const dependencies = this.node.expression.dynamic_dependencies();
19883 let snippet = this.node.expression.manipulate(block);
19884 const value = this.node.should_cache && block.get_unique_name(`${this.var.name}_value`);
19885 const content = this.node.should_cache ? value : snippet;
19886 snippet = x `${snippet} + ""`;
19887 if (this.node.should_cache)
19888 block.add_variable(value, snippet); // TODO may need to coerce snippet to string
19889 if (dependencies.length > 0) {
19890 let condition = block.renderer.dirty(dependencies);
19891 if (block.has_outros) {
19892 condition = x `!#current || ${condition}`;
19893 }
19894 const update_cached_value = x `${value} !== (${value} = ${snippet})`;
19895 if (this.node.should_cache) {
19896 condition = x `${condition} && ${update_cached_value}`;
19897 }
19898 block.chunks.update.push(b `if (${condition}) ${update(content)}`);
19899 }
19900 return { init: content };
19901 }
19902 }
19903
19904 class MustacheTagWrapper extends Tag {
19905 constructor(renderer, block, parent, node) {
19906 super(renderer, block, parent, node);
19907 this.var = { type: 'Identifier', name: 't' };
19908 }
19909 render(block, parent_node, parent_nodes) {
19910 const { init } = this.rename_this_method(block, value => x `@set_data(${this.var}, ${value})`);
19911 block.add_element(this.var, x `@text(${init})`, parent_nodes && x `@claim_text(${parent_nodes}, ${init})`, parent_node);
19912 }
19913 }
19914
19915 class RawMustacheTagWrapper extends Tag {
19916 constructor(renderer, block, parent, node) {
19917 super(renderer, block, parent, node);
19918 this.var = { type: 'Identifier', name: 'raw' };
19919 this.cannot_use_innerhtml();
19920 this.not_static_content();
19921 }
19922 render(block, parent_node, _parent_nodes) {
19923 const in_head = is_head(parent_node);
19924 const can_use_innerhtml = !in_head && parent_node && !this.prev && !this.next;
19925 if (can_use_innerhtml) {
19926 const insert = content => b `${parent_node}.innerHTML = ${content};`[0];
19927 const { init } = this.rename_this_method(block, content => insert(content));
19928 block.chunks.mount.push(insert(init));
19929 }
19930 else {
19931 const needs_anchor = in_head || (this.next && !this.next.is_dom_node());
19932 const html_tag = block.get_unique_name('html_tag');
19933 const html_anchor = needs_anchor && block.get_unique_name('html_anchor');
19934 block.add_variable(html_tag);
19935 const { init } = this.rename_this_method(block, content => x `${html_tag}.p(${content})`);
19936 const update_anchor = in_head ? 'null' : needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
19937 block.chunks.hydrate.push(b `${html_tag} = new @HtmlTag(${update_anchor});`);
19938 block.chunks.mount.push(b `${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`);
19939 if (needs_anchor) {
19940 block.add_element(html_anchor, x `@empty()`, x `@empty()`, parent_node);
19941 }
19942 if (!parent_node || in_head) {
19943 block.chunks.destroy.push(b `if (detaching) ${html_tag}.d();`);
19944 }
19945 }
19946 }
19947 }
19948
19949 function get_slot_data(values, block = null) {
19950 return {
19951 type: 'ObjectExpression',
19952 properties: Array.from(values.values())
19953 .filter(attribute => attribute.name !== 'name')
19954 .map(attribute => {
19955 const value = get_value(block, attribute);
19956 return p `${attribute.name}: ${value}`;
19957 })
19958 };
19959 }
19960 function get_value(block, attribute) {
19961 if (attribute.is_true)
19962 return x `true`;
19963 if (attribute.chunks.length === 0)
19964 return x `""`;
19965 let value = attribute.chunks
19966 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : (block ? chunk.manipulate(block) : chunk.node))
19967 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
19968 if (attribute.chunks.length > 1 && attribute.chunks[0].type !== 'Text') {
19969 value = x `"" + ${value}`;
19970 }
19971 return value;
19972 }
19973
19974 class SlotWrapper extends Wrapper {
19975 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19976 super(renderer, block, parent, node);
19977 this.fallback = null;
19978 this.var = { type: 'Identifier', name: 'slot' };
19979 this.dependencies = new Set(['$$scope']);
19980 this.cannot_use_innerhtml();
19981 this.not_static_content();
19982 if (this.node.children.length) {
19983 this.fallback = block.child({
19984 comment: create_debugging_comment(this.node.children[0], this.renderer.component),
19985 name: this.renderer.component.get_unique_name(`fallback_block`),
19986 type: 'fallback'
19987 });
19988 renderer.blocks.push(this.fallback);
19989 }
19990 this.fragment = new FragmentWrapper(renderer, this.fallback, node.children, this, strip_whitespace, next_sibling);
19991 this.node.values.forEach(attribute => {
19992 add_to_set(this.dependencies, attribute.dependencies);
19993 });
19994 block.add_dependencies(this.dependencies);
19995 // we have to do this, just in case
19996 block.add_intro();
19997 block.add_outro();
19998 }
19999 render(block, parent_node, parent_nodes) {
20000 const { renderer } = this;
20001 const { slot_name } = this.node;
20002 let get_slot_changes_fn;
20003 let get_slot_context_fn;
20004 if (this.node.values.size > 0) {
20005 get_slot_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_changes`);
20006 get_slot_context_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_context`);
20007 const changes = x `{}`;
20008 const dependencies = new Set();
20009 this.node.values.forEach(attribute => {
20010 attribute.chunks.forEach(chunk => {
20011 if (chunk.dependencies) {
20012 add_to_set(dependencies, chunk.contextual_dependencies);
20013 // add_to_set(dependencies, (chunk as Expression).dependencies);
20014 chunk.dependencies.forEach(name => {
20015 const variable = renderer.component.var_lookup.get(name);
20016 if (variable && !variable.hoistable)
20017 dependencies.add(name);
20018 });
20019 }
20020 });
20021 const dynamic_dependencies = Array.from(attribute.dependencies).filter(name => {
20022 if (this.node.scope.is_let(name))
20023 return true;
20024 const variable = renderer.component.var_lookup.get(name);
20025 return is_dynamic$1(variable);
20026 });
20027 if (dynamic_dependencies.length > 0) {
20028 changes.properties.push(p `${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`);
20029 }
20030 });
20031 renderer.blocks.push(b `
20032 const ${get_slot_changes_fn} = #dirty => ${changes};
20033 const ${get_slot_context_fn} = #ctx => ${get_slot_data(this.node.values, block)};
20034 `);
20035 }
20036 else {
20037 get_slot_changes_fn = 'null';
20038 get_slot_context_fn = 'null';
20039 }
20040 let has_fallback = !!this.fallback;
20041 if (this.fallback) {
20042 this.fragment.render(this.fallback, null, x `#nodes`);
20043 has_fallback = this.fallback.has_content();
20044 if (!has_fallback) {
20045 renderer.remove_block(this.fallback);
20046 }
20047 }
20048 const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`);
20049 const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
20050 const slot_or_fallback = has_fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot;
20051 block.chunks.init.push(b `
20052 const ${slot_definition} = ${renderer.reference('$$slots')}.${slot_name};
20053 const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn});
20054 ${has_fallback ? b `const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
20055 `);
20056 block.chunks.create.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.c();`);
20057 if (renderer.options.hydratable) {
20058 block.chunks.claim.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});`);
20059 }
20060 block.chunks.mount.push(b `
20061 if (${slot_or_fallback}) {
20062 ${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20063 }
20064 `);
20065 block.chunks.intro.push(b `@transition_in(${slot_or_fallback}, #local);`);
20066 block.chunks.outro.push(b `@transition_out(${slot_or_fallback}, #local);`);
20067 const is_dependency_dynamic = name => {
20068 if (name === '$$scope')
20069 return true;
20070 if (this.node.scope.is_let(name))
20071 return true;
20072 const variable = renderer.component.var_lookup.get(name);
20073 return is_dynamic$1(variable);
20074 };
20075 const dynamic_dependencies = Array.from(this.dependencies).filter(is_dependency_dynamic);
20076 const fallback_dynamic_dependencies = has_fallback
20077 ? Array.from(this.fallback.dependencies).filter(is_dependency_dynamic)
20078 : [];
20079 const slot_update = b `
20080 if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
20081 @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn});
20082 }
20083 `;
20084 const fallback_update = has_fallback && fallback_dynamic_dependencies.length > 0 && b `
20085 if (${slot_or_fallback} && ${slot_or_fallback}.p && ${renderer.dirty(fallback_dynamic_dependencies)}) {
20086 ${slot_or_fallback}.p(#ctx, #dirty);
20087 }
20088 `;
20089 if (fallback_update) {
20090 block.chunks.update.push(b `
20091 if (${slot}) {
20092 ${slot_update}
20093 } else {
20094 ${fallback_update}
20095 }
20096 `);
20097 }
20098 else {
20099 block.chunks.update.push(b `
20100 if (${slot}) {
20101 ${slot_update}
20102 }
20103 `);
20104 }
20105 block.chunks.destroy.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`);
20106 }
20107 }
20108
20109 class TextWrapper extends Wrapper {
20110 constructor(renderer, block, parent, node, data) {
20111 super(renderer, block, parent, node);
20112 this.skip = this.node.should_skip();
20113 this.data = data;
20114 this.var = (this.skip ? null : x `t`);
20115 }
20116 use_space() {
20117 if (this.renderer.component.component_options.preserveWhitespace)
20118 return false;
20119 if (/[\S\u00A0]/.test(this.data))
20120 return false;
20121 let node = this.parent && this.parent.node;
20122 while (node) {
20123 if (node.type === 'Element' && node.name === 'pre') {
20124 return false;
20125 }
20126 node = node.parent;
20127 }
20128 return true;
20129 }
20130 render(block, parent_node, parent_nodes) {
20131 if (this.skip)
20132 return;
20133 const use_space = this.use_space();
20134 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);
20135 }
20136 }
20137
20138 class TitleWrapper extends Wrapper {
20139 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
20140 super(renderer, block, parent, node);
20141 }
20142 render(block, _parent_node, _parent_nodes) {
20143 const is_dynamic = !!this.node.children.find(node => node.type !== 'Text');
20144 if (is_dynamic) {
20145 let value;
20146 const all_dependencies = new Set();
20147 // TODO some of this code is repeated in Tag.ts — would be good to
20148 // DRY it out if that's possible without introducing crazy indirection
20149 if (this.node.children.length === 1) {
20150 // single {tag} — may be a non-string
20151 // @ts-ignore todo: check this
20152 const { expression } = this.node.children[0];
20153 value = expression.manipulate(block);
20154 add_to_set(all_dependencies, expression.dependencies);
20155 }
20156 else {
20157 // '{foo} {bar}' — treat as string concatenation
20158 value = this.node.children
20159 .map(chunk => {
20160 if (chunk.type === 'Text')
20161 return string_literal(chunk.data);
20162 chunk.expression.dependencies.forEach(d => {
20163 all_dependencies.add(d);
20164 });
20165 return chunk.expression.manipulate(block);
20166 })
20167 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20168 if (this.node.children[0].type !== 'Text') {
20169 value = x `"" + ${value}`;
20170 }
20171 }
20172 const last = this.node.should_cache && block.get_unique_name(`title_value`);
20173 if (this.node.should_cache)
20174 block.add_variable(last);
20175 const init = this.node.should_cache ? x `${last} = ${value}` : value;
20176 block.chunks.init.push(b `@_document.title = ${init};`);
20177 const updater = b `@_document.title = ${this.node.should_cache ? last : value};`;
20178 if (all_dependencies.size) {
20179 const dependencies = Array.from(all_dependencies);
20180 let condition = block.renderer.dirty(dependencies);
20181 if (block.has_outros) {
20182 condition = x `!#current || ${condition}`;
20183 }
20184 if (this.node.should_cache) {
20185 condition = x `${condition} && (${last} !== (${last} = ${value}))`;
20186 }
20187 block.chunks.update.push(b `
20188 if (${condition}) {
20189 ${updater}
20190 }`);
20191 }
20192 }
20193 else {
20194 const value = this.node.children.length > 0
20195 ? string_literal(this.node.children[0].data)
20196 : x `""`;
20197 block.chunks.hydrate.push(b `@_document.title = ${value};`);
20198 }
20199 }
20200 }
20201
20202 const associated_events = {
20203 innerWidth: 'resize',
20204 innerHeight: 'resize',
20205 outerWidth: 'resize',
20206 outerHeight: 'resize',
20207 scrollX: 'scroll',
20208 scrollY: 'scroll',
20209 };
20210 const properties = {
20211 scrollX: 'pageXOffset',
20212 scrollY: 'pageYOffset'
20213 };
20214 const readonly = new Set([
20215 'innerWidth',
20216 'innerHeight',
20217 'outerWidth',
20218 'outerHeight',
20219 'online',
20220 ]);
20221 class WindowWrapper extends Wrapper {
20222 constructor(renderer, block, parent, node) {
20223 super(renderer, block, parent, node);
20224 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
20225 }
20226 render(block, _parent_node, _parent_nodes) {
20227 const { renderer } = this;
20228 const { component } = renderer;
20229 const events = {};
20230 const bindings = {};
20231 add_actions(block, '@_window', this.node.actions);
20232 add_event_handlers(block, '@_window', this.handlers);
20233 this.node.bindings.forEach(binding => {
20234 // in dev mode, throw if read-only values are written to
20235 if (readonly.has(binding.name)) {
20236 renderer.readonly.add(binding.expression.node.name);
20237 }
20238 bindings[binding.name] = binding.expression.node.name;
20239 // bind:online is a special case, we need to listen for two separate events
20240 if (binding.name === 'online')
20241 return;
20242 const associated_event = associated_events[binding.name];
20243 const property = properties[binding.name] || binding.name;
20244 if (!events[associated_event])
20245 events[associated_event] = [];
20246 events[associated_event].push({
20247 name: binding.expression.node.name,
20248 value: property
20249 });
20250 });
20251 const scrolling = block.get_unique_name(`scrolling`);
20252 const clear_scrolling = block.get_unique_name(`clear_scrolling`);
20253 const scrolling_timeout = block.get_unique_name(`scrolling_timeout`);
20254 Object.keys(events).forEach(event => {
20255 const id = block.get_unique_name(`onwindow${event}`);
20256 const props = events[event];
20257 renderer.add_to_context(id.name);
20258 const fn = renderer.reference(id.name);
20259 if (event === 'scroll') {
20260 // TODO other bidirectional bindings...
20261 block.add_variable(scrolling, x `false`);
20262 block.add_variable(clear_scrolling, x `() => { ${scrolling} = false }`);
20263 block.add_variable(scrolling_timeout);
20264 const condition = bindings.scrollX && bindings.scrollY
20265 ? x `"${bindings.scrollX}" in this._state || "${bindings.scrollY}" in this._state`
20266 : x `"${bindings.scrollX || bindings.scrollY}" in this._state`;
20267 const scrollX = bindings.scrollX && x `this._state.${bindings.scrollX}`;
20268 const scrollY = bindings.scrollY && x `this._state.${bindings.scrollY}`;
20269 renderer.meta_bindings.push(b `
20270 if (${condition}) {
20271 @_scrollTo(${scrollX || '@_window.pageXOffset'}, ${scrollY || '@_window.pageYOffset'});
20272 }
20273 ${scrollX && `${scrollX} = @_window.pageXOffset;`}
20274 ${scrollY && `${scrollY} = @_window.pageYOffset;`}
20275 `);
20276 block.event_listeners.push(x `
20277 @listen(@_window, "${event}", () => {
20278 ${scrolling} = true;
20279 @_clearTimeout(${scrolling_timeout});
20280 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
20281 ${fn}();
20282 })
20283 `);
20284 }
20285 else {
20286 props.forEach(prop => {
20287 renderer.meta_bindings.push(b `this._state.${prop.name} = @_window.${prop.value};`);
20288 });
20289 block.event_listeners.push(x `
20290 @listen(@_window, "${event}", ${fn})
20291 `);
20292 }
20293 component.partly_hoisted.push(b `
20294 function ${id}() {
20295 ${props.map(prop => renderer.invalidate(prop.name, x `${prop.name} = @_window.${prop.value}`))}
20296 }
20297 `);
20298 block.chunks.init.push(b `
20299 @add_render_callback(${fn});
20300 `);
20301 component.has_reactive_assignments = true;
20302 });
20303 // special case... might need to abstract this out if we add more special cases
20304 if (bindings.scrollX || bindings.scrollY) {
20305 const condition = renderer.dirty([bindings.scrollX, bindings.scrollY].filter(Boolean));
20306 const scrollX = bindings.scrollX ? renderer.reference(bindings.scrollX) : x `@_window.pageXOffset`;
20307 const scrollY = bindings.scrollY ? renderer.reference(bindings.scrollY) : x `@_window.pageYOffset`;
20308 block.chunks.update.push(b `
20309 if (${condition} && !${scrolling}) {
20310 ${scrolling} = true;
20311 @_clearTimeout(${scrolling_timeout});
20312 @_scrollTo(${scrollX}, ${scrollY});
20313 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
20314 }
20315 `);
20316 }
20317 // another special case. (I'm starting to think these are all special cases.)
20318 if (bindings.online) {
20319 const id = block.get_unique_name(`onlinestatuschanged`);
20320 const name = bindings.online;
20321 renderer.add_to_context(id.name);
20322 const reference = renderer.reference(id.name);
20323 component.partly_hoisted.push(b `
20324 function ${id}() {
20325 ${renderer.invalidate(name, x `${name} = @_navigator.onLine`)}
20326 }
20327 `);
20328 block.chunks.init.push(b `
20329 @add_render_callback(${reference});
20330 `);
20331 block.event_listeners.push(x `@listen(@_window, "online", ${reference})`, x `@listen(@_window, "offline", ${reference})`);
20332 component.has_reactive_assignments = true;
20333 }
20334 }
20335 }
20336
20337 function link(next, prev) {
20338 prev.next = next;
20339 if (next)
20340 next.prev = prev;
20341 }
20342
20343 const wrappers = {
20344 AwaitBlock: AwaitBlockWrapper,
20345 Body: BodyWrapper,
20346 Comment: null,
20347 DebugTag: DebugTagWrapper,
20348 EachBlock: EachBlockWrapper,
20349 Element: ElementWrapper,
20350 Head: HeadWrapper,
20351 IfBlock: IfBlockWrapper,
20352 InlineComponent: InlineComponentWrapper,
20353 MustacheTag: MustacheTagWrapper,
20354 Options: null,
20355 RawMustacheTag: RawMustacheTagWrapper,
20356 Slot: SlotWrapper,
20357 Text: TextWrapper,
20358 Title: TitleWrapper,
20359 Window: WindowWrapper
20360 };
20361 function trimmable_at(child, next_sibling) {
20362 // Whitespace is trimmable if one of the following is true:
20363 // The child and its sibling share a common nearest each block (not at an each block boundary)
20364 // The next sibling's previous node is an each block
20365 return (next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/)) || next_sibling.node.prev.type === 'EachBlock';
20366 }
20367 class FragmentWrapper {
20368 constructor(renderer, block, nodes, parent, strip_whitespace, next_sibling) {
20369 this.nodes = [];
20370 let last_child;
20371 let window_wrapper;
20372 let i = nodes.length;
20373 while (i--) {
20374 const child = nodes[i];
20375 if (!child.type) {
20376 throw new Error(`missing type`);
20377 }
20378 if (!(child.type in wrappers)) {
20379 throw new Error(`TODO implement ${child.type}`);
20380 }
20381 // special case — this is an easy way to remove whitespace surrounding
20382 // <svelte:window/>. lil hacky but it works
20383 if (child.type === 'Window') {
20384 window_wrapper = new WindowWrapper(renderer, block, parent, child);
20385 continue;
20386 }
20387 if (child.type === 'Text') {
20388 let { data } = child;
20389 // We want to remove trailing whitespace inside an element/component/block,
20390 // *unless* there is no whitespace between this node and its next sibling
20391 if (this.nodes.length === 0) {
20392 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'));
20393 if (should_trim) {
20394 data = trim_end(data);
20395 if (!data)
20396 continue;
20397 }
20398 }
20399 // glue text nodes (which could e.g. be separated by comments) together
20400 if (last_child && last_child.node.type === 'Text') {
20401 last_child.data = data + last_child.data;
20402 continue;
20403 }
20404 const wrapper = new TextWrapper(renderer, block, parent, child, data);
20405 if (wrapper.skip)
20406 continue;
20407 this.nodes.unshift(wrapper);
20408 link(last_child, last_child = wrapper);
20409 }
20410 else {
20411 const Wrapper = wrappers[child.type];
20412 if (!Wrapper)
20413 continue;
20414 const wrapper = new Wrapper(renderer, block, parent, child, strip_whitespace, last_child || next_sibling);
20415 this.nodes.unshift(wrapper);
20416 link(last_child, last_child = wrapper);
20417 }
20418 }
20419 if (strip_whitespace) {
20420 const first = this.nodes[0];
20421 if (first && first.node.type === 'Text') {
20422 first.data = trim_start(first.data);
20423 if (!first.data) {
20424 first.var = null;
20425 this.nodes.shift();
20426 if (this.nodes[0]) {
20427 this.nodes[0].prev = null;
20428 }
20429 }
20430 }
20431 }
20432 if (window_wrapper) {
20433 this.nodes.unshift(window_wrapper);
20434 link(last_child, window_wrapper);
20435 }
20436 }
20437 render(block, parent_node, parent_nodes) {
20438 for (let i = 0; i < this.nodes.length; i += 1) {
20439 this.nodes[i].render(block, parent_node, parent_nodes);
20440 }
20441 }
20442 }
20443
20444 class Renderer {
20445 constructor(component, options) {
20446 this.context = [];
20447 this.initial_context = [];
20448 this.context_lookup = new Map();
20449 this.blocks = [];
20450 this.readonly = new Set();
20451 this.meta_bindings = []; // initial values for e.g. window.innerWidth, if there's a <svelte:window> meta tag
20452 this.binding_groups = [];
20453 this.component = component;
20454 this.options = options;
20455 this.locate = component.locate; // TODO messy
20456 this.file_var = options.dev && this.component.get_unique_name('file');
20457 component.vars.filter(v => !v.hoistable || (v.export_name && !v.module)).forEach(v => this.add_to_context(v.name));
20458 // ensure store values are included in context
20459 component.vars.filter(v => v.subscribable).forEach(v => this.add_to_context(`$${v.name}`));
20460 reserved_keywords.forEach(keyword => {
20461 if (component.var_lookup.has(keyword)) {
20462 this.add_to_context(keyword);
20463 }
20464 });
20465 if (component.slots.size > 0) {
20466 this.add_to_context('$$scope');
20467 this.add_to_context('$$slots');
20468 }
20469 if (this.binding_groups.length > 0) {
20470 this.add_to_context('$$binding_groups');
20471 }
20472 // main block
20473 this.block = new Block$1({
20474 renderer: this,
20475 name: null,
20476 type: 'component',
20477 key: null,
20478 bindings: new Map(),
20479 dependencies: new Set(),
20480 });
20481 this.block.has_update_method = true;
20482 this.fragment = new FragmentWrapper(this, this.block, component.fragment.children, null, true, null);
20483 // TODO messy
20484 this.blocks.forEach(block => {
20485 if (block instanceof Block$1) {
20486 block.assign_variable_names();
20487 }
20488 });
20489 this.block.assign_variable_names();
20490 this.fragment.render(this.block, null, x `#nodes`);
20491 this.context_overflow = this.context.length > 31;
20492 this.context.forEach(member => {
20493 const { variable } = member;
20494 if (variable) {
20495 member.priority += 2;
20496 if (variable.mutated || variable.reassigned)
20497 member.priority += 4;
20498 // these determine whether variable is included in initial context
20499 // array, so must have the highest priority
20500 if (variable.export_name)
20501 member.priority += 16;
20502 if (variable.referenced)
20503 member.priority += 32;
20504 }
20505 else if (member.is_non_contextual) {
20506 // determine whether variable is included in initial context
20507 // array, so must have the highest priority
20508 member.priority += 8;
20509 }
20510 if (!member.is_contextual) {
20511 member.priority += 1;
20512 }
20513 });
20514 this.context.sort((a, b) => (b.priority - a.priority) || (a.index.value - b.index.value));
20515 this.context.forEach((member, i) => member.index.value = i);
20516 let i = this.context.length;
20517 while (i--) {
20518 const member = this.context[i];
20519 if (member.variable) {
20520 if (member.variable.referenced || member.variable.export_name)
20521 break;
20522 }
20523 else if (member.is_non_contextual) {
20524 break;
20525 }
20526 }
20527 this.initial_context = this.context.slice(0, i + 1);
20528 }
20529 add_to_context(name, contextual = false) {
20530 if (!this.context_lookup.has(name)) {
20531 const member = {
20532 name,
20533 index: { type: 'Literal', value: this.context.length },
20534 is_contextual: false,
20535 is_non_contextual: false,
20536 variable: null,
20537 priority: 0
20538 };
20539 this.context_lookup.set(name, member);
20540 this.context.push(member);
20541 }
20542 const member = this.context_lookup.get(name);
20543 if (contextual) {
20544 member.is_contextual = true;
20545 }
20546 else {
20547 member.is_non_contextual = true;
20548 const variable = this.component.var_lookup.get(name);
20549 member.variable = variable;
20550 }
20551 return member;
20552 }
20553 invalidate(name, value) {
20554 const variable = this.component.var_lookup.get(name);
20555 const member = this.context_lookup.get(name);
20556 if (variable && (variable.subscribable && (variable.reassigned || variable.export_name))) {
20557 return x `${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
20558 }
20559 if (name[0] === '$' && name[1] !== '$') {
20560 return x `${name.slice(1)}.set(${value || name})`;
20561 }
20562 if (variable && (variable.module || (!variable.referenced &&
20563 !variable.is_reactive_dependency &&
20564 !variable.export_name &&
20565 !name.startsWith('$$')))) {
20566 return value || name;
20567 }
20568 if (value) {
20569 return x `$$invalidate(${member.index}, ${value})`;
20570 }
20571 // if this is a reactive declaration, invalidate dependencies recursively
20572 const deps = new Set([name]);
20573 deps.forEach(name => {
20574 const reactive_declarations = this.component.reactive_declarations.filter(x => x.assignees.has(name));
20575 reactive_declarations.forEach(declaration => {
20576 declaration.dependencies.forEach(name => {
20577 deps.add(name);
20578 });
20579 });
20580 });
20581 // TODO ideally globals etc wouldn't be here in the first place
20582 const filtered = Array.from(deps).filter(n => this.context_lookup.has(n));
20583 if (!filtered.length)
20584 return null;
20585 return filtered
20586 .map(n => x `$$invalidate(${this.context_lookup.get(n).index}, ${n})`)
20587 .reduce((lhs, rhs) => x `${lhs}, ${rhs}`);
20588 }
20589 dirty(names, is_reactive_declaration = false) {
20590 const renderer = this;
20591 const dirty = (is_reactive_declaration
20592 ? x `$$self.$$.dirty`
20593 : x `#dirty`);
20594 const get_bitmask = () => {
20595 const bitmask = [];
20596 names.forEach((name) => {
20597 const member = renderer.context_lookup.get(name);
20598 if (!member)
20599 return;
20600 if (member.index.value === -1) {
20601 throw new Error(`unset index`);
20602 }
20603 const value = member.index.value;
20604 const i = (value / 31) | 0;
20605 const n = 1 << (value % 31);
20606 if (!bitmask[i])
20607 bitmask[i] = { n: 0, names: [] };
20608 bitmask[i].n |= n;
20609 bitmask[i].names.push(name);
20610 });
20611 return bitmask;
20612 };
20613 // TODO: context-overflow make it less gross
20614 return {
20615 // Using a ParenthesizedExpression allows us to create
20616 // the expression lazily. TODO would be better if
20617 // context was determined before rendering, so that
20618 // this indirection was unnecessary
20619 type: 'ParenthesizedExpression',
20620 get expression() {
20621 const bitmask = get_bitmask();
20622 if (!bitmask.length) {
20623 return x `${dirty} & /*${names.join(', ')}*/ 0`;
20624 }
20625 if (renderer.context_overflow) {
20626 return bitmask
20627 .map((b, i) => ({ b, i }))
20628 .filter(({ b }) => b)
20629 .map(({ b, i }) => x `${dirty}[${i}] & /*${b.names.join(', ')}*/ ${b.n}`)
20630 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
20631 }
20632 return x `${dirty} & /*${names.join(', ')}*/ ${bitmask[0].n}`;
20633 }
20634 };
20635 }
20636 reference(node) {
20637 if (typeof node === 'string') {
20638 node = { type: 'Identifier', name: node };
20639 }
20640 const { name, nodes } = flatten_reference(node);
20641 const member = this.context_lookup.get(name);
20642 // TODO is this correct?
20643 if (this.component.var_lookup.get(name)) {
20644 this.component.add_reference(name);
20645 }
20646 if (member !== undefined) {
20647 const replacement = x `/*${member.name}*/ #ctx[${member.index}]`;
20648 if (nodes[0].loc)
20649 replacement.object.loc = nodes[0].loc;
20650 nodes[0] = replacement;
20651 return nodes.reduce((lhs, rhs) => x `${lhs}.${rhs}`);
20652 }
20653 return node;
20654 }
20655 remove_block(block) {
20656 this.blocks.splice(this.blocks.indexOf(block), 1);
20657 }
20658 }
20659
20660 function dom(component, options) {
20661 const { name } = component;
20662 const renderer = new Renderer(component, options);
20663 const { block } = renderer;
20664 block.has_outro_method = true;
20665 // prevent fragment being created twice (#1063)
20666 if (options.customElement)
20667 block.chunks.create.push(b `this.c = @noop;`);
20668 const body = [];
20669 if (renderer.file_var) {
20670 const file = component.file ? x `"${component.file}"` : x `undefined`;
20671 body.push(b `const ${renderer.file_var} = ${file};`);
20672 }
20673 const css = component.stylesheet.render(options.filename, !options.customElement);
20674 const styles = component.stylesheet.has_styles && options.dev
20675 ? `${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */`
20676 : css.code;
20677 const add_css = component.get_unique_name('add_css');
20678 const should_add_css = (!options.customElement &&
20679 !!styles &&
20680 options.css !== false);
20681 if (should_add_css) {
20682 body.push(b `
20683 function ${add_css}() {
20684 var style = @element("style");
20685 style.id = "${component.stylesheet.id}-style";
20686 style.textContent = "${styles}";
20687 @append(@_document.head, style);
20688 }
20689 `);
20690 }
20691 // fix order
20692 // TODO the deconflicted names of blocks are reversed... should set them here
20693 const blocks = renderer.blocks.slice().reverse();
20694 body.push(...blocks.map(block => {
20695 // TODO this is a horrible mess — renderer.blocks
20696 // contains a mixture of Blocks and Nodes
20697 if (block.render)
20698 return block.render();
20699 return block;
20700 }));
20701 if (options.dev && !options.hydratable) {
20702 block.chunks.claim.push(b `throw new @_Error("options.hydrate only works if the component was compiled with the \`hydratable: true\` option");`);
20703 }
20704 const uses_props = component.var_lookup.has('$$props');
20705 const uses_rest = component.var_lookup.has('$$restProps');
20706 const $$props = uses_props || uses_rest ? `$$new_props` : `$$props`;
20707 const props = component.vars.filter(variable => !variable.module && variable.export_name);
20708 const writable_props = props.filter(variable => variable.writable);
20709 const omit_props_names = component.get_unique_name('omit_props_names');
20710 const compute_rest = x `@compute_rest_props($$props, ${omit_props_names.name})`;
20711 const rest = uses_rest ? b `
20712 const ${omit_props_names.name} = [${props.map(prop => `"${prop.export_name}"`).join(',')}];
20713 let $$restProps = ${compute_rest};
20714 ` : null;
20715 const set = (uses_props || uses_rest || writable_props.length > 0 || component.slots.size > 0)
20716 ? x `
20717 ${$$props} => {
20718 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`)}
20719 ${uses_rest && !uses_props && x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`}
20720 ${uses_rest && renderer.invalidate('$$restProps', x `$$restProps = ${compute_rest}`)}
20721 ${writable_props.map(prop => b `if ('${prop.export_name}' in ${$$props}) ${renderer.invalidate(prop.name, x `${prop.name} = ${$$props}.${prop.export_name}`)};`)}
20722 ${component.slots.size > 0 &&
20723 b `if ('$$scope' in ${$$props}) ${renderer.invalidate('$$scope', x `$$scope = ${$$props}.$$scope`)};`}
20724 }
20725 `
20726 : null;
20727 const accessors = [];
20728 const not_equal = component.component_options.immutable ? x `@not_equal` : x `@safe_not_equal`;
20729 let dev_props_check;
20730 let inject_state;
20731 let capture_state;
20732 let props_inject;
20733 props.forEach(prop => {
20734 const variable = component.var_lookup.get(prop.name);
20735 if (!variable.writable || component.component_options.accessors) {
20736 accessors.push({
20737 type: 'MethodDefinition',
20738 kind: 'get',
20739 key: { type: 'Identifier', name: prop.export_name },
20740 value: x `function() {
20741 return ${prop.hoistable ? prop.name : x `this.$$.ctx[${renderer.context_lookup.get(prop.name).index}]`}
20742 }`
20743 });
20744 }
20745 else if (component.compile_options.dev) {
20746 accessors.push({
20747 type: 'MethodDefinition',
20748 kind: 'get',
20749 key: { type: 'Identifier', name: prop.export_name },
20750 value: x `function() {
20751 throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
20752 }`
20753 });
20754 }
20755 if (component.component_options.accessors) {
20756 if (variable.writable && !renderer.readonly.has(prop.name)) {
20757 accessors.push({
20758 type: 'MethodDefinition',
20759 kind: 'set',
20760 key: { type: 'Identifier', name: prop.export_name },
20761 value: x `function(${prop.name}) {
20762 this.$set({ ${prop.export_name}: ${prop.name} });
20763 @flush();
20764 }`
20765 });
20766 }
20767 else if (component.compile_options.dev) {
20768 accessors.push({
20769 type: 'MethodDefinition',
20770 kind: 'set',
20771 key: { type: 'Identifier', name: prop.export_name },
20772 value: x `function(value) {
20773 throw new @_Error("<${component.tag}>: Cannot set read-only property '${prop.export_name}'");
20774 }`
20775 });
20776 }
20777 }
20778 else if (component.compile_options.dev) {
20779 accessors.push({
20780 type: 'MethodDefinition',
20781 kind: 'set',
20782 key: { type: 'Identifier', name: prop.export_name },
20783 value: x `function(value) {
20784 throw new @_Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
20785 }`
20786 });
20787 }
20788 });
20789 if (component.compile_options.dev) {
20790 // checking that expected ones were passed
20791 const expected = props.filter(prop => prop.writable && !prop.initialised);
20792 if (expected.length) {
20793 dev_props_check = b `
20794 const { ctx: #ctx } = this.$$;
20795 const props = ${options.customElement ? x `this.attributes` : x `options.props || {}`};
20796 ${expected.map(prop => b `
20797 if (${renderer.reference(prop.name)} === undefined && !('${prop.export_name}' in props)) {
20798 @_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'");
20799 }`)}
20800 `;
20801 }
20802 const capturable_vars = component.vars.filter(v => !v.internal && !v.global && !v.name.startsWith('$$'));
20803 if (capturable_vars.length > 0) {
20804 capture_state = x `() => ({ ${capturable_vars.map(prop => p `${prop.name}`)} })`;
20805 }
20806 const injectable_vars = capturable_vars.filter(v => !v.module && v.writable && v.name[0] !== '$');
20807 if (uses_props || injectable_vars.length > 0) {
20808 inject_state = x `
20809 ${$$props} => {
20810 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), $$new_props)`)}
20811 ${injectable_vars.map(v => b `if ('${v.name}' in $$props) ${renderer.invalidate(v.name, x `${v.name} = ${$$props}.${v.name}`)};`)}
20812 }
20813 `;
20814 props_inject = b `
20815 if ($$props && "$$inject" in $$props) {
20816 $$self.$inject_state($$props.$$inject);
20817 }
20818 `;
20819 }
20820 }
20821 // instrument assignments
20822 if (component.ast.instance) {
20823 let scope = component.instance_scope;
20824 const map = component.instance_scope_map;
20825 let execution_context = null;
20826 walk(component.ast.instance.content, {
20827 enter(node) {
20828 if (map.has(node)) {
20829 scope = map.get(node);
20830 if (!execution_context && !scope.block) {
20831 execution_context = node;
20832 }
20833 }
20834 else if (!execution_context && node.type === 'LabeledStatement' && node.label.name === '$') {
20835 execution_context = node;
20836 }
20837 },
20838 leave(node) {
20839 if (map.has(node)) {
20840 scope = scope.parent;
20841 }
20842 if (execution_context === node) {
20843 execution_context = null;
20844 }
20845 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
20846 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
20847 // normally (`a = 1`, `b.c = 2`), there'll be a single name
20848 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
20849 // may be more, in which case we need to tack the extra ones
20850 // onto the initial function call
20851 const names = new Set(extract_names(assignee));
20852 this.replace(invalidate(renderer, scope, node, names, execution_context === null));
20853 }
20854 }
20855 });
20856 component.rewrite_props(({ name, reassigned, export_name }) => {
20857 const value = `$${name}`;
20858 const i = renderer.context_lookup.get(`$${name}`).index;
20859 const insert = (reassigned || export_name)
20860 ? b `${`$$subscribe_${name}`}()`
20861 : b `@component_subscribe($$self, ${name}, #value => $$invalidate(${i}, ${value} = #value))`;
20862 if (component.compile_options.dev) {
20863 return b `@validate_store(${name}, '${name}'); ${insert}`;
20864 }
20865 return insert;
20866 });
20867 }
20868 const args = [x `$$self`];
20869 const has_invalidate = props.length > 0 ||
20870 component.has_reactive_assignments ||
20871 component.slots.size > 0 ||
20872 capture_state ||
20873 inject_state;
20874 if (has_invalidate) {
20875 args.push(x `$$props`, x `$$invalidate`);
20876 }
20877 else if (component.compile_options.dev) {
20878 // $$props arg is still needed for unknown prop check
20879 args.push(x `$$props`);
20880 }
20881 const has_create_fragment = component.compile_options.dev || block.has_content();
20882 if (has_create_fragment) {
20883 body.push(b `
20884 function create_fragment(#ctx) {
20885 ${block.get_contents()}
20886 }
20887 `);
20888 }
20889 body.push(b `
20890 ${component.extract_javascript(component.ast.module)}
20891
20892 ${component.fully_hoisted}
20893 `);
20894 const filtered_props = props.filter(prop => {
20895 const variable = component.var_lookup.get(prop.name);
20896 if (variable.hoistable)
20897 return false;
20898 if (prop.name[0] === '$')
20899 return false;
20900 return true;
20901 });
20902 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
20903 const instance_javascript = component.extract_javascript(component.ast.instance);
20904 const has_definition = (component.compile_options.dev ||
20905 (instance_javascript && instance_javascript.length > 0) ||
20906 filtered_props.length > 0 ||
20907 uses_props ||
20908 component.partly_hoisted.length > 0 ||
20909 renderer.initial_context.length > 0 ||
20910 component.reactive_declarations.length > 0 ||
20911 capture_state ||
20912 inject_state);
20913 const definition = has_definition
20914 ? component.alias('instance')
20915 : { type: 'Literal', value: null };
20916 const reactive_store_subscriptions = reactive_stores
20917 .filter(store => {
20918 const variable = component.var_lookup.get(store.name.slice(1));
20919 return !variable || variable.hoistable;
20920 })
20921 .map(({ name }) => b `
20922 ${component.compile_options.dev && b `@validate_store(${name.slice(1)}, '${name.slice(1)}');`}
20923 @component_subscribe($$self, ${name.slice(1)}, $$value => $$invalidate(${renderer.context_lookup.get(name).index}, ${name} = $$value));
20924 `);
20925 const resubscribable_reactive_store_unsubscribers = reactive_stores
20926 .filter(store => {
20927 const variable = component.var_lookup.get(store.name.slice(1));
20928 return variable && (variable.reassigned || variable.export_name);
20929 })
20930 .map(({ name }) => b `$$self.$$.on_destroy.push(() => ${`$$unsubscribe_${name.slice(1)}`}());`);
20931 if (has_definition) {
20932 const reactive_declarations = [];
20933 const fixed_reactive_declarations = []; // not really 'reactive' but whatever
20934 component.reactive_declarations.forEach(d => {
20935 const dependencies = Array.from(d.dependencies);
20936 const uses_rest_or_props = !!dependencies.find(n => n === '$$props' || n === '$$restProps');
20937 const writable = dependencies.filter(n => {
20938 const variable = component.var_lookup.get(n);
20939 return variable && (variable.export_name || variable.mutated || variable.reassigned);
20940 });
20941 const condition = !uses_rest_or_props && writable.length > 0 && renderer.dirty(writable, true);
20942 let statement = d.node; // TODO remove label (use d.node.body) if it's not referenced
20943 if (condition)
20944 statement = b `if (${condition}) { ${statement} }`[0];
20945 if (condition || uses_rest_or_props) {
20946 reactive_declarations.push(statement);
20947 }
20948 else {
20949 fixed_reactive_declarations.push(statement);
20950 }
20951 });
20952 const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
20953 const variable = component.var_lookup.get(name);
20954 return variable.injected && variable.name[0] !== '$';
20955 });
20956 const reactive_store_declarations = reactive_stores.map(variable => {
20957 const $name = variable.name;
20958 const name = $name.slice(1);
20959 const store = component.var_lookup.get(name);
20960 if (store && (store.reassigned || store.export_name)) {
20961 const unsubscribe = `$$unsubscribe_${name}`;
20962 const subscribe = `$$subscribe_${name}`;
20963 const i = renderer.context_lookup.get($name).index;
20964 return b `let ${$name}, ${unsubscribe} = @noop, ${subscribe} = () => (${unsubscribe}(), ${unsubscribe} = @subscribe(${name}, $$value => $$invalidate(${i}, ${$name} = $$value)), ${name})`;
20965 }
20966 return b `let ${$name};`;
20967 });
20968 let unknown_props_check;
20969 if (component.compile_options.dev && !(uses_props || uses_rest)) {
20970 unknown_props_check = b `
20971 const writable_props = [${writable_props.map(prop => x `'${prop.export_name}'`)}];
20972 @_Object.keys($$props).forEach(key => {
20973 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$') @_console.warn(\`<${component.tag}> was created with unknown prop '\${key}'\`);
20974 });
20975 `;
20976 }
20977 const return_value = {
20978 type: 'ArrayExpression',
20979 elements: renderer.initial_context.map(member => ({
20980 type: 'Identifier',
20981 name: member.name
20982 }))
20983 };
20984 body.push(b `
20985 function ${definition}(${args}) {
20986 ${rest}
20987
20988 ${reactive_store_declarations}
20989
20990 ${reactive_store_subscriptions}
20991
20992 ${resubscribable_reactive_store_unsubscribers}
20993
20994 ${instance_javascript}
20995
20996 ${unknown_props_check}
20997
20998 ${component.slots.size || component.compile_options.dev ? b `let { $$slots = {}, $$scope } = $$props;` : null}
20999 ${component.compile_options.dev && b `@validate_slots('${component.tag}', $$slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
21000
21001 ${renderer.binding_groups.length > 0 && b `const $$binding_groups = [${renderer.binding_groups.map(_ => x `[]`)}];`}
21002
21003 ${component.partly_hoisted}
21004
21005 ${set && b `$$self.$set = ${set};`}
21006
21007 ${capture_state && b `$$self.$capture_state = ${capture_state};`}
21008
21009 ${inject_state && b `$$self.$inject_state = ${inject_state};`}
21010
21011 ${injected.map(name => b `let ${name};`)}
21012
21013 ${ /* before reactive declarations */props_inject}
21014
21015 ${reactive_declarations.length > 0 && b `
21016 $$self.$$.update = () => {
21017 ${reactive_declarations}
21018 };
21019 `}
21020
21021 ${fixed_reactive_declarations}
21022
21023 ${uses_props && b `$$props = @exclude_internal_props($$props);`}
21024
21025 return ${return_value};
21026 }
21027 `);
21028 }
21029 const prop_indexes = x `{
21030 ${props.filter(v => v.export_name && !v.module).map(v => p `${v.export_name}: ${renderer.context_lookup.get(v.name).index}`)}
21031 }`;
21032 let dirty;
21033 if (renderer.context_overflow) {
21034 dirty = x `[]`;
21035 for (let i = 0; i < renderer.context.length; i += 31) {
21036 dirty.elements.push(x `-1`);
21037 }
21038 }
21039 if (options.customElement) {
21040 const declaration = b `
21041 class ${name} extends @SvelteElement {
21042 constructor(options) {
21043 super();
21044
21045 ${css.code && b `this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
21046
21047 @init(this, { target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
21048
21049 ${dev_props_check}
21050
21051 if (options) {
21052 if (options.target) {
21053 @insert(options.target, this, options.anchor);
21054 }
21055
21056 ${(props.length > 0 || uses_props || uses_rest) && b `
21057 if (options.props) {
21058 this.$set(options.props);
21059 @flush();
21060 }`}
21061 }
21062 }
21063 }
21064 `[0];
21065 if (props.length > 0) {
21066 declaration.body.body.push({
21067 type: 'MethodDefinition',
21068 kind: 'get',
21069 static: true,
21070 computed: false,
21071 key: { type: 'Identifier', name: 'observedAttributes' },
21072 value: x `function() {
21073 return [${props.map(prop => x `"${prop.export_name}"`)}];
21074 }`
21075 });
21076 }
21077 declaration.body.body.push(...accessors);
21078 body.push(declaration);
21079 if (component.tag != null) {
21080 body.push(b `
21081 @_customElements.define("${component.tag}", ${name});
21082 `);
21083 }
21084 }
21085 else {
21086 const superclass = {
21087 type: 'Identifier',
21088 name: options.dev ? '@SvelteComponentDev' : '@SvelteComponent'
21089 };
21090 const declaration = b `
21091 class ${name} extends ${superclass} {
21092 constructor(options) {
21093 super(${options.dev && `options`});
21094 ${should_add_css && b `if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
21095 @init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
21096 ${options.dev && b `@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`}
21097
21098 ${dev_props_check}
21099 }
21100 }
21101 `[0];
21102 declaration.body.body.push(...accessors);
21103 body.push(declaration);
21104 }
21105 return { js: flatten$1(body, []), css };
21106 }
21107 function flatten$1(nodes, target) {
21108 for (let i = 0; i < nodes.length; i += 1) {
21109 const node = nodes[i];
21110 if (Array.isArray(node)) {
21111 flatten$1(node, target);
21112 }
21113 else {
21114 target.push(node);
21115 }
21116 }
21117 return target;
21118 }
21119
21120 function AwaitBlock (node, renderer, options) {
21121 renderer.push();
21122 renderer.render(node.pending.children, options);
21123 const pending = renderer.pop();
21124 renderer.push();
21125 renderer.render(node.then.children, options);
21126 const then = renderer.pop();
21127 renderer.add_expression(x `
21128 function(__value) {
21129 if (@is_promise(__value)) return ${pending};
21130 return (function(${node.then_node ? node.then_node : ''}) { return ${then}; }(__value));
21131 }(${node.expression.node})
21132 `);
21133 }
21134
21135 function Comment$1 (_node, _renderer, _options) {
21136 // TODO preserve comments
21137 // if (options.preserveComments) {
21138 // renderer.append(`<!--${node.data}-->`);
21139 // }
21140 }
21141
21142 function DebugTag (node, renderer, options) {
21143 if (!options.dev)
21144 return;
21145 const filename = options.filename || null;
21146 const { line, column } = options.locate(node.start + 1);
21147 const obj = x `{
21148 ${node.expressions.map(e => p `${e.node.name}`)}
21149 }`;
21150 renderer.add_expression(x `@debug(${filename ? x `"${filename}"` : x `null`}, ${line - 1}, ${column}, ${obj})`);
21151 }
21152
21153 function EachBlock (node, renderer, options) {
21154 const args = [node.context_node];
21155 if (node.index)
21156 args.push({ type: 'Identifier', name: node.index });
21157 renderer.push();
21158 renderer.render(node.children, options);
21159 const result = renderer.pop();
21160 const consequent = x `@each(${node.expression.node}, (${args}) => ${result})`;
21161 if (node.else) {
21162 renderer.push();
21163 renderer.render(node.else.children, options);
21164 const alternate = renderer.pop();
21165 renderer.add_expression(x `${node.expression.node}.length ? ${consequent} : ${alternate}`);
21166 }
21167 else {
21168 renderer.add_expression(consequent);
21169 }
21170 }
21171
21172 function get_class_attribute_value(attribute) {
21173 // handle special case — `class={possiblyUndefined}` with scoped CSS
21174 if (attribute.chunks.length === 2 && attribute.chunks[1].synthetic) {
21175 const value = attribute.chunks[0].node;
21176 return x `@escape(@null_to_empty(${value})) + "${attribute.chunks[1].data}"`;
21177 }
21178 return get_attribute_value(attribute);
21179 }
21180 function get_attribute_value(attribute) {
21181 if (attribute.chunks.length === 0)
21182 return x `""`;
21183 return attribute.chunks
21184 .map((chunk) => {
21185 return chunk.type === 'Text'
21186 ? string_literal(chunk.data.replace(/"/g, '&quot;'))
21187 : x `@escape(${chunk.node})`;
21188 })
21189 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
21190 }
21191
21192 function get_slot_scope(lets) {
21193 if (lets.length === 0)
21194 return null;
21195 return {
21196 type: 'ObjectPattern',
21197 properties: lets.map(l => {
21198 return {
21199 type: 'Property',
21200 kind: 'init',
21201 method: false,
21202 shorthand: false,
21203 computed: false,
21204 key: l.name,
21205 value: l.value || l.name
21206 };
21207 })
21208 };
21209 }
21210
21211 // source: https://html.spec.whatwg.org/multipage/indices.html
21212 const boolean_attributes = new Set([
21213 'allowfullscreen',
21214 'allowpaymentrequest',
21215 'async',
21216 'autofocus',
21217 'autoplay',
21218 'checked',
21219 'controls',
21220 'default',
21221 'defer',
21222 'disabled',
21223 'formnovalidate',
21224 'hidden',
21225 'ismap',
21226 'loop',
21227 'multiple',
21228 'muted',
21229 'nomodule',
21230 'novalidate',
21231 'open',
21232 'playsinline',
21233 'readonly',
21234 'required',
21235 'reversed',
21236 'selected'
21237 ]);
21238
21239 // similar logic from `compile/render_dom/wrappers/Fragment`
21240 // We want to remove trailing whitespace inside an element/component/block,
21241 // *unless* there is no whitespace between this node and its next sibling
21242 function remove_whitespace_children(children, next) {
21243 const nodes = [];
21244 let last_child;
21245 let i = children.length;
21246 while (i--) {
21247 const child = children[i];
21248 if (child.type === 'Text') {
21249 if (child.should_skip()) {
21250 continue;
21251 }
21252 let { data } = child;
21253 if (nodes.length === 0) {
21254 const should_trim = next
21255 ? next.type === 'Text' &&
21256 /^\s/.test(next.data) &&
21257 trimmable_at$1(child, next)
21258 : !child.has_ancestor('EachBlock');
21259 if (should_trim) {
21260 data = trim_end(data);
21261 if (!data)
21262 continue;
21263 }
21264 }
21265 // glue text nodes (which could e.g. be separated by comments) together
21266 if (last_child && last_child.type === 'Text') {
21267 last_child.data = data + last_child.data;
21268 continue;
21269 }
21270 nodes.unshift(child);
21271 link(last_child, last_child = child);
21272 }
21273 else {
21274 nodes.unshift(child);
21275 link(last_child, last_child = child);
21276 }
21277 }
21278 const first = nodes[0];
21279 if (first && first.type === 'Text') {
21280 first.data = trim_start(first.data);
21281 if (!first.data) {
21282 first.var = null;
21283 nodes.shift();
21284 if (nodes[0]) {
21285 nodes[0].prev = null;
21286 }
21287 }
21288 }
21289 return nodes;
21290 }
21291 function trimmable_at$1(child, next_sibling) {
21292 // Whitespace is trimmable if one of the following is true:
21293 // The child and its sibling share a common nearest each block (not at an each block boundary)
21294 // The next sibling's previous node is an each block
21295 return (next_sibling.find_nearest(/EachBlock/) ===
21296 child.find_nearest(/EachBlock/) || next_sibling.prev.type === 'EachBlock');
21297 }
21298
21299 function Element (node, renderer, options) {
21300 const children = remove_whitespace_children(node.children, node.next);
21301 // awkward special case
21302 let node_contents;
21303 const contenteditable = (node.name !== 'textarea' &&
21304 node.name !== 'input' &&
21305 node.attributes.some((attribute) => attribute.name === 'contenteditable'));
21306 const slot = node.get_static_attribute_value('slot');
21307 const nearest_inline_component = node.find_nearest(/InlineComponent/);
21308 if (slot && nearest_inline_component) {
21309 renderer.push();
21310 }
21311 renderer.add_string(`<${node.name}`);
21312 const class_expression_list = node.classes.map(class_directive => {
21313 const { expression, name } = class_directive;
21314 const snippet = expression ? expression.node : x `#ctx.${name}`; // TODO is this right?
21315 return x `${snippet} ? "${name}" : ""`;
21316 });
21317 if (node.needs_manual_style_scoping) {
21318 class_expression_list.push(x `"${node.component.stylesheet.id}"`);
21319 }
21320 const class_expression = class_expression_list.length > 0 &&
21321 class_expression_list.reduce((lhs, rhs) => x `${lhs} + ' ' + ${rhs}`);
21322 if (node.attributes.some(attr => attr.is_spread)) {
21323 // TODO dry this out
21324 const args = [];
21325 node.attributes.forEach(attribute => {
21326 if (attribute.is_spread) {
21327 args.push(attribute.expression.node);
21328 }
21329 else {
21330 const name = attribute.name.toLowerCase();
21331 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
21332 node_contents = get_attribute_value(attribute);
21333 }
21334 else if (attribute.is_true) {
21335 args.push(x `{ ${attribute.name}: true }`);
21336 }
21337 else if (boolean_attributes.has(name) &&
21338 attribute.chunks.length === 1 &&
21339 attribute.chunks[0].type !== 'Text') {
21340 // a boolean attribute with one non-Text chunk
21341 args.push(x `{ ${attribute.name}: ${attribute.chunks[0].node} || null }`);
21342 }
21343 else {
21344 args.push(x `{ ${attribute.name}: ${get_attribute_value(attribute)} }`);
21345 }
21346 }
21347 });
21348 renderer.add_expression(x `@spread([${args}], ${class_expression})`);
21349 }
21350 else {
21351 let add_class_attribute = !!class_expression;
21352 node.attributes.forEach(attribute => {
21353 const name = attribute.name.toLowerCase();
21354 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
21355 node_contents = get_attribute_value(attribute);
21356 }
21357 else if (attribute.is_true) {
21358 renderer.add_string(` ${attribute.name}`);
21359 }
21360 else if (boolean_attributes.has(name) &&
21361 attribute.chunks.length === 1 &&
21362 attribute.chunks[0].type !== 'Text') {
21363 // a boolean attribute with one non-Text chunk
21364 renderer.add_string(` `);
21365 renderer.add_expression(x `${attribute.chunks[0].node} ? "${attribute.name}" : ""`);
21366 }
21367 else if (name === 'class' && class_expression) {
21368 add_class_attribute = false;
21369 renderer.add_string(` ${attribute.name}="`);
21370 renderer.add_expression(x `[${get_class_attribute_value(attribute)}, ${class_expression}].join(' ').trim()`);
21371 renderer.add_string(`"`);
21372 }
21373 else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') {
21374 const snippet = attribute.chunks[0].node;
21375 renderer.add_expression(x `@add_attribute("${attribute.name}", ${snippet}, ${boolean_attributes.has(name) ? 1 : 0})`);
21376 }
21377 else {
21378 renderer.add_string(` ${attribute.name}="`);
21379 renderer.add_expression((name === 'class' ? get_class_attribute_value : get_attribute_value)(attribute));
21380 renderer.add_string(`"`);
21381 }
21382 });
21383 if (add_class_attribute) {
21384 renderer.add_expression(x `@add_classes([${class_expression}].join(' ').trim())`);
21385 }
21386 }
21387 node.bindings.forEach(binding => {
21388 const { name, expression } = binding;
21389 if (binding.is_readonly) {
21390 return;
21391 }
21392 if (name === 'group') ;
21393 else if (contenteditable && (name === 'textContent' || name === 'innerHTML')) {
21394 node_contents = expression.node;
21395 // TODO where was this used?
21396 // value = name === 'textContent' ? x`@escape($$value)` : x`$$value`;
21397 }
21398 else if (binding.name === 'value' && node.name === 'textarea') {
21399 const snippet = expression.node;
21400 node_contents = x `${snippet} || ""`;
21401 }
21402 else {
21403 const snippet = expression.node;
21404 renderer.add_expression(x `@add_attribute("${name}", ${snippet}, 1)`);
21405 }
21406 });
21407 if (options.hydratable && options.head_id) {
21408 renderer.add_string(` data-svelte="${options.head_id}"`);
21409 }
21410 renderer.add_string('>');
21411 if (node_contents !== undefined) {
21412 if (contenteditable) {
21413 renderer.push();
21414 renderer.render(children, options);
21415 const result = renderer.pop();
21416 renderer.add_expression(x `($$value => $$value === void 0 ? ${result} : $$value)(${node_contents})`);
21417 }
21418 else {
21419 renderer.add_expression(node_contents);
21420 }
21421 if (!is_void(node.name)) {
21422 renderer.add_string(`</${node.name}>`);
21423 }
21424 }
21425 else if (slot && nearest_inline_component) {
21426 renderer.render(children, options);
21427 if (!is_void(node.name)) {
21428 renderer.add_string(`</${node.name}>`);
21429 }
21430 const lets = node.lets;
21431 const seen = new Set(lets.map(l => l.name.name));
21432 nearest_inline_component.lets.forEach(l => {
21433 if (!seen.has(l.name.name))
21434 lets.push(l);
21435 });
21436 options.slot_scopes.set(slot, {
21437 input: get_slot_scope(node.lets),
21438 output: renderer.pop()
21439 });
21440 }
21441 else {
21442 renderer.render(children, options);
21443 if (!is_void(node.name)) {
21444 renderer.add_string(`</${node.name}>`);
21445 }
21446 }
21447 }
21448
21449 function Head (node, renderer, options) {
21450 const head_options = Object.assign({}, options, { head_id: node.id });
21451 renderer.push();
21452 renderer.render(node.children, head_options);
21453 const result = renderer.pop();
21454 renderer.add_expression(x `$$result.head += ${result}, ""`);
21455 }
21456
21457 function HtmlTag (node, renderer, _options) {
21458 renderer.add_expression(node.expression.node);
21459 }
21460
21461 function IfBlock (node, renderer, options) {
21462 const condition = node.expression.node;
21463 renderer.push();
21464 renderer.render(node.children, options);
21465 const consequent = renderer.pop();
21466 renderer.push();
21467 if (node.else)
21468 renderer.render(node.else.children, options);
21469 const alternate = renderer.pop();
21470 renderer.add_expression(x `${condition} ? ${consequent} : ${alternate}`);
21471 }
21472
21473 function get_prop_value(attribute) {
21474 if (attribute.is_true)
21475 return x `true`;
21476 if (attribute.chunks.length === 0)
21477 return x `''`;
21478 return attribute.chunks
21479 .map(chunk => {
21480 if (chunk.type === 'Text')
21481 return string_literal(chunk.data);
21482 return chunk.node;
21483 })
21484 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
21485 }
21486 function InlineComponent (node, renderer, options) {
21487 const binding_props = [];
21488 const binding_fns = [];
21489 node.bindings.forEach(binding => {
21490 renderer.has_bindings = true;
21491 // TODO this probably won't work for contextual bindings
21492 const snippet = binding.expression.node;
21493 binding_props.push(p `${binding.name}: ${snippet}`);
21494 binding_fns.push(p `${binding.name}: $$value => { ${snippet} = $$value; $$settled = false }`);
21495 });
21496 const uses_spread = node.attributes.find(attr => attr.is_spread);
21497 let props;
21498 if (uses_spread) {
21499 props = x `@_Object.assign(${node.attributes
21500 .map(attribute => {
21501 if (attribute.is_spread) {
21502 return attribute.expression.node;
21503 }
21504 else {
21505 return x `{ ${attribute.name}: ${get_prop_value(attribute)} }`;
21506 }
21507 })
21508 .concat(binding_props.map(p => x `{ ${p} }`))})`;
21509 }
21510 else {
21511 props = x `{
21512 ${node.attributes.map(attribute => p `${attribute.name}: ${get_prop_value(attribute)}`)},
21513 ${binding_props}
21514 }`;
21515 }
21516 const bindings = x `{
21517 ${binding_fns}
21518 }`;
21519 const expression = (node.name === 'svelte:self'
21520 ? renderer.name
21521 : node.name === 'svelte:component'
21522 ? x `(${node.expression.node}) || @missing_component`
21523 : node.name.split('.').reduce(((lhs, rhs) => x `${lhs}.${rhs}`)));
21524 const slot_fns = [];
21525 const children = remove_whitespace_children(node.children, node.next);
21526 if (children.length) {
21527 const slot_scopes = new Map();
21528 renderer.push();
21529 renderer.render(children, Object.assign({}, options, {
21530 slot_scopes
21531 }));
21532 slot_scopes.set('default', {
21533 input: get_slot_scope(node.lets),
21534 output: renderer.pop()
21535 });
21536 slot_scopes.forEach(({ input, output }, name) => {
21537 if (!is_empty_template_literal(output)) {
21538 slot_fns.push(p `${name}: (${input}) => ${output}`);
21539 }
21540 });
21541 }
21542 const slots = x `{
21543 ${slot_fns}
21544 }`;
21545 renderer.add_expression(x `@validate_component(${expression}, "${node.name}").$$render($$result, ${props}, ${bindings}, ${slots})`);
21546 }
21547 function is_empty_template_literal(template_literal) {
21548 return (template_literal.expressions.length === 0 &&
21549 template_literal.quasis.length === 1 &&
21550 template_literal.quasis[0].value.raw === "");
21551 }
21552
21553 function Slot (node, renderer, options) {
21554 const slot_data = get_slot_data(node.values);
21555 renderer.push();
21556 renderer.render(node.children, options);
21557 const result = renderer.pop();
21558 renderer.add_expression(x `
21559 $$slots.${node.slot_name}
21560 ? $$slots.${node.slot_name}(${slot_data})
21561 : ${result}
21562 `);
21563 }
21564
21565 function Tag$1 (node, renderer, _options) {
21566 const snippet = node.expression.node;
21567 renderer.add_expression(node.parent &&
21568 node.parent.type === 'Element' &&
21569 node.parent.name === 'style'
21570 ? snippet
21571 : x `@escape(${snippet})`);
21572 }
21573
21574 function Text (node, renderer, _options) {
21575 let text = node.data;
21576 if (!node.parent ||
21577 node.parent.type !== 'Element' ||
21578 (node.parent.name !== 'script' && node.parent.name !== 'style')) {
21579 // unless this Text node is inside a <script> or <style> element, escape &,<,>
21580 text = escape_html(text);
21581 }
21582 renderer.add_string(text);
21583 }
21584
21585 function Title (node, renderer, options) {
21586 renderer.push();
21587 renderer.add_string(`<title>`);
21588 renderer.render(node.children, options);
21589 renderer.add_string(`</title>`);
21590 const result = renderer.pop();
21591 renderer.add_expression(x `$$result.title = ${result}, ""`);
21592 }
21593
21594 function noop$1() { }
21595 const handlers$1 = {
21596 AwaitBlock,
21597 Body: noop$1,
21598 Comment: Comment$1,
21599 DebugTag,
21600 EachBlock,
21601 Element,
21602 Head,
21603 IfBlock,
21604 InlineComponent,
21605 MustacheTag: Tag$1,
21606 Options: noop$1,
21607 RawMustacheTag: HtmlTag,
21608 Slot,
21609 Text,
21610 Title,
21611 Window: noop$1
21612 };
21613 class Renderer$1 {
21614 constructor({ name }) {
21615 this.has_bindings = false;
21616 this.stack = [];
21617 this.targets = [];
21618 this.name = name;
21619 this.push();
21620 }
21621 add_string(str) {
21622 this.current.value += escape_template(str);
21623 }
21624 add_expression(node) {
21625 this.literal.quasis.push({
21626 type: 'TemplateElement',
21627 value: { raw: this.current.value, cooked: null },
21628 tail: false
21629 });
21630 this.literal.expressions.push(node);
21631 this.current.value = '';
21632 }
21633 push() {
21634 const current = this.current = { value: '' };
21635 const literal = this.literal = {
21636 type: 'TemplateLiteral',
21637 expressions: [],
21638 quasis: []
21639 };
21640 this.stack.push({ current, literal });
21641 }
21642 pop() {
21643 this.literal.quasis.push({
21644 type: 'TemplateElement',
21645 value: { raw: this.current.value, cooked: null },
21646 tail: true
21647 });
21648 const popped = this.stack.pop();
21649 const last = this.stack[this.stack.length - 1];
21650 if (last) {
21651 this.literal = last.literal;
21652 this.current = last.current;
21653 }
21654 return popped.literal;
21655 }
21656 render(nodes, options) {
21657 nodes.forEach(node => {
21658 const handler = handlers$1[node.type];
21659 if (!handler) {
21660 throw new Error(`No handler for '${node.type}' nodes`);
21661 }
21662 handler(node, this, options);
21663 });
21664 }
21665 }
21666
21667 function ssr(component, options) {
21668 const renderer = new Renderer$1({
21669 name: component.name
21670 });
21671 const { name } = component;
21672 // create $$render function
21673 renderer.render(trim(component.fragment.children), Object.assign({
21674 locate: component.locate
21675 }, options));
21676 // TODO put this inside the Renderer class
21677 const literal = renderer.pop();
21678 // TODO concatenate CSS maps
21679 const css = options.customElement ?
21680 { code: null, map: null } :
21681 component.stylesheet.render(options.filename, true);
21682 const uses_rest = component.var_lookup.has('$$restProps');
21683 const props = component.vars.filter(variable => !variable.module && variable.export_name);
21684 const rest = uses_rest ? b `let $$restProps = @compute_rest_props($$props, [${props.map(prop => `"${prop.export_name}"`).join(',')}]);` : null;
21685 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
21686 const reactive_store_values = reactive_stores
21687 .map(({ name }) => {
21688 const store_name = name.slice(1);
21689 const store = component.var_lookup.get(store_name);
21690 if (store && store.hoistable)
21691 return null;
21692 const assignment = b `${name} = @get_store_value(${store_name});`;
21693 return component.compile_options.dev
21694 ? b `@validate_store(${store_name}, '${store_name}'); ${assignment}`
21695 : assignment;
21696 })
21697 .filter(Boolean);
21698 component.rewrite_props(({ name }) => {
21699 const value = `$${name}`;
21700 let insert = b `${value} = @get_store_value(${name})`;
21701 if (component.compile_options.dev) {
21702 insert = b `@validate_store(${name}, '${name}'); ${insert}`;
21703 }
21704 return insert;
21705 });
21706 const instance_javascript = component.extract_javascript(component.ast.instance);
21707 // TODO only do this for props with a default value
21708 const parent_bindings = instance_javascript
21709 ? component.vars
21710 .filter(variable => !variable.module && variable.export_name)
21711 .map(prop => {
21712 return b `if ($$props.${prop.export_name} === void 0 && $$bindings.${prop.export_name} && ${prop.name} !== void 0) $$bindings.${prop.export_name}(${prop.name});`;
21713 })
21714 : [];
21715 const reactive_declarations = component.reactive_declarations.map(d => {
21716 const body = d.node.body;
21717 let statement = b `${body}`;
21718 if (d.declaration) {
21719 const declared = extract_names(d.declaration);
21720 const injected = declared.filter(name => {
21721 return name[0] !== '$' && component.var_lookup.get(name).injected;
21722 });
21723 const self_dependencies = injected.filter(name => d.dependencies.has(name));
21724 if (injected.length) {
21725 // in some cases we need to do `let foo; [expression]`, in
21726 // others we can do `let [expression]`
21727 const separate = (self_dependencies.length > 0 ||
21728 declared.length > injected.length);
21729 const { left, right } = body.expression;
21730 statement = separate
21731 ? b `
21732 ${injected.map(name => b `let ${name};`)}
21733 ${statement}`
21734 : b `
21735 let ${left} = ${right}`;
21736 }
21737 }
21738 else { // TODO do not add label if it's not referenced
21739 statement = b `$: { ${statement} }`;
21740 }
21741 return statement;
21742 });
21743 const main = renderer.has_bindings
21744 ? b `
21745 let $$settled;
21746 let $$rendered;
21747
21748 do {
21749 $$settled = true;
21750
21751 ${reactive_store_values}
21752
21753 ${reactive_declarations}
21754
21755 $$rendered = ${literal};
21756 } while (!$$settled);
21757
21758 return $$rendered;
21759 `
21760 : b `
21761 ${reactive_store_values}
21762
21763 ${reactive_declarations}
21764
21765 return ${literal};`;
21766 const blocks = [
21767 rest,
21768 ...reactive_stores.map(({ name }) => {
21769 const store_name = name.slice(1);
21770 const store = component.var_lookup.get(store_name);
21771 if (store && store.hoistable) {
21772 return b `let ${name} = @get_store_value(${store_name});`;
21773 }
21774 return b `let ${name};`;
21775 }),
21776 instance_javascript,
21777 ...parent_bindings,
21778 css.code && b `$$result.css.add(#css);`,
21779 main
21780 ].filter(Boolean);
21781 const js = b `
21782 ${css.code ? b `
21783 const #css = {
21784 code: "${css.code}",
21785 map: ${css.map ? string_literal(css.map.toString()) : 'null'}
21786 };` : null}
21787
21788 ${component.extract_javascript(component.ast.module)}
21789
21790 ${component.fully_hoisted}
21791
21792 const ${name} = @create_ssr_component(($$result, $$props, $$bindings, $$slots) => {
21793 ${blocks}
21794 });
21795 `;
21796 return { js, css };
21797 }
21798 function trim(nodes) {
21799 let start = 0;
21800 for (; start < nodes.length; start += 1) {
21801 const node = nodes[start];
21802 if (node.type !== 'Text')
21803 break;
21804 node.data = node.data.replace(/^\s+/, '');
21805 if (node.data)
21806 break;
21807 }
21808 let end = nodes.length;
21809 for (; end > start; end -= 1) {
21810 const node = nodes[end - 1];
21811 if (node.type !== 'Text')
21812 break;
21813 node.data = node.data.replace(/\s+$/, '');
21814 if (node.data)
21815 break;
21816 }
21817 return nodes.slice(start, end);
21818 }
21819
21820 const wrappers$1 = { esm, cjs };
21821 function create_module(program, format, name, banner, sveltePath = 'svelte', helpers, globals, imports, module_exports) {
21822 const internal_path = `${sveltePath}/internal`;
21823 helpers.sort((a, b) => (a.name < b.name) ? -1 : 1);
21824 globals.sort((a, b) => (a.name < b.name) ? -1 : 1);
21825 if (format === 'esm') {
21826 return esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
21827 }
21828 if (format === 'cjs')
21829 return cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
21830 throw new Error(`options.format is invalid (must be ${list$1(Object.keys(wrappers$1))})`);
21831 }
21832 function edit_source(source, sveltePath) {
21833 return source === 'svelte' || source.startsWith('svelte/')
21834 ? source.replace('svelte', sveltePath)
21835 : source;
21836 }
21837 function get_internal_globals(globals, helpers) {
21838 return globals.length > 0 && {
21839 type: 'VariableDeclaration',
21840 kind: 'const',
21841 declarations: [{
21842 type: 'VariableDeclarator',
21843 id: {
21844 type: 'ObjectPattern',
21845 properties: globals.map(g => ({
21846 type: 'Property',
21847 method: false,
21848 shorthand: false,
21849 computed: false,
21850 key: { type: 'Identifier', name: g.name },
21851 value: g.alias,
21852 kind: 'init'
21853 }))
21854 },
21855 init: helpers.find(({ name }) => name === 'globals').alias
21856 }]
21857 };
21858 }
21859 function esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
21860 const import_declaration = {
21861 type: 'ImportDeclaration',
21862 specifiers: helpers.map(h => ({
21863 type: 'ImportSpecifier',
21864 local: h.alias,
21865 imported: { type: 'Identifier', name: h.name }
21866 })),
21867 source: { type: 'Literal', value: internal_path }
21868 };
21869 const internal_globals = get_internal_globals(globals, helpers);
21870 // edit user imports
21871 imports.forEach(node => {
21872 node.source.value = edit_source(node.source.value, sveltePath);
21873 });
21874 const exports = module_exports.length > 0 && {
21875 type: 'ExportNamedDeclaration',
21876 specifiers: module_exports.map(x => ({
21877 type: 'Specifier',
21878 local: { type: 'Identifier', name: x.name },
21879 exported: { type: 'Identifier', name: x.as }
21880 }))
21881 };
21882 program.body = b `
21883 /* ${banner} */
21884
21885 ${import_declaration}
21886 ${internal_globals}
21887 ${imports}
21888
21889 ${program.body}
21890
21891 export default ${name};
21892 ${exports}
21893 `;
21894 }
21895 function cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
21896 const internal_requires = {
21897 type: 'VariableDeclaration',
21898 kind: 'const',
21899 declarations: [{
21900 type: 'VariableDeclarator',
21901 id: {
21902 type: 'ObjectPattern',
21903 properties: helpers.map(h => ({
21904 type: 'Property',
21905 method: false,
21906 shorthand: false,
21907 computed: false,
21908 key: { type: 'Identifier', name: h.name },
21909 value: h.alias,
21910 kind: 'init'
21911 }))
21912 },
21913 init: x `require("${internal_path}")`
21914 }]
21915 };
21916 const internal_globals = get_internal_globals(globals, helpers);
21917 const user_requires = imports.map(node => {
21918 const init = x `require("${edit_source(node.source.value, sveltePath)}")`;
21919 if (node.specifiers.length === 0) {
21920 return b `${init};`;
21921 }
21922 return {
21923 type: 'VariableDeclaration',
21924 kind: 'const',
21925 declarations: [{
21926 type: 'VariableDeclarator',
21927 id: node.specifiers[0].type === 'ImportNamespaceSpecifier'
21928 ? { type: 'Identifier', name: node.specifiers[0].local.name }
21929 : {
21930 type: 'ObjectPattern',
21931 properties: node.specifiers.map(s => ({
21932 type: 'Property',
21933 method: false,
21934 shorthand: false,
21935 computed: false,
21936 key: s.type === 'ImportSpecifier' ? s.imported : { type: 'Identifier', name: 'default' },
21937 value: s.local,
21938 kind: 'init'
21939 }))
21940 },
21941 init
21942 }]
21943 };
21944 });
21945 const exports = module_exports.map(x => b `exports.${{ type: 'Identifier', name: x.as }} = ${{ type: 'Identifier', name: x.name }};`);
21946 program.body = b `
21947 /* ${banner} */
21948
21949 "use strict";
21950 ${internal_requires}
21951 ${internal_globals}
21952 ${user_requires}
21953
21954 ${program.body}
21955
21956 exports.default = ${name};
21957 ${exports}
21958 `;
21959 }
21960
21961 var Chunk = function Chunk(start, end, content) {
21962 this.start = start;
21963 this.end = end;
21964 this.original = content;
21965
21966 this.intro = '';
21967 this.outro = '';
21968
21969 this.content = content;
21970 this.storeName = false;
21971 this.edited = false;
21972
21973 // we make these non-enumerable, for sanity while debugging
21974 Object.defineProperties(this, {
21975 previous: { writable: true, value: null },
21976 next: { writable: true, value: null }
21977 });
21978 };
21979
21980 Chunk.prototype.appendLeft = function appendLeft (content) {
21981 this.outro += content;
21982 };
21983
21984 Chunk.prototype.appendRight = function appendRight (content) {
21985 this.intro = this.intro + content;
21986 };
21987
21988 Chunk.prototype.clone = function clone () {
21989 var chunk = new Chunk(this.start, this.end, this.original);
21990
21991 chunk.intro = this.intro;
21992 chunk.outro = this.outro;
21993 chunk.content = this.content;
21994 chunk.storeName = this.storeName;
21995 chunk.edited = this.edited;
21996
21997 return chunk;
21998 };
21999
22000 Chunk.prototype.contains = function contains (index) {
22001 return this.start < index && index < this.end;
22002 };
22003
22004 Chunk.prototype.eachNext = function eachNext (fn) {
22005 var chunk = this;
22006 while (chunk) {
22007 fn(chunk);
22008 chunk = chunk.next;
22009 }
22010 };
22011
22012 Chunk.prototype.eachPrevious = function eachPrevious (fn) {
22013 var chunk = this;
22014 while (chunk) {
22015 fn(chunk);
22016 chunk = chunk.previous;
22017 }
22018 };
22019
22020 Chunk.prototype.edit = function edit (content, storeName, contentOnly) {
22021 this.content = content;
22022 if (!contentOnly) {
22023 this.intro = '';
22024 this.outro = '';
22025 }
22026 this.storeName = storeName;
22027
22028 this.edited = true;
22029
22030 return this;
22031 };
22032
22033 Chunk.prototype.prependLeft = function prependLeft (content) {
22034 this.outro = content + this.outro;
22035 };
22036
22037 Chunk.prototype.prependRight = function prependRight (content) {
22038 this.intro = content + this.intro;
22039 };
22040
22041 Chunk.prototype.split = function split (index) {
22042 var sliceIndex = index - this.start;
22043
22044 var originalBefore = this.original.slice(0, sliceIndex);
22045 var originalAfter = this.original.slice(sliceIndex);
22046
22047 this.original = originalBefore;
22048
22049 var newChunk = new Chunk(index, this.end, originalAfter);
22050 newChunk.outro = this.outro;
22051 this.outro = '';
22052
22053 this.end = index;
22054
22055 if (this.edited) {
22056 // TODO is this block necessary?...
22057 newChunk.edit('', false);
22058 this.content = '';
22059 } else {
22060 this.content = originalBefore;
22061 }
22062
22063 newChunk.next = this.next;
22064 if (newChunk.next) { newChunk.next.previous = newChunk; }
22065 newChunk.previous = this;
22066 this.next = newChunk;
22067
22068 return newChunk;
22069 };
22070
22071 Chunk.prototype.toString = function toString () {
22072 return this.intro + this.content + this.outro;
22073 };
22074
22075 Chunk.prototype.trimEnd = function trimEnd (rx) {
22076 this.outro = this.outro.replace(rx, '');
22077 if (this.outro.length) { return true; }
22078
22079 var trimmed = this.content.replace(rx, '');
22080
22081 if (trimmed.length) {
22082 if (trimmed !== this.content) {
22083 this.split(this.start + trimmed.length).edit('', undefined, true);
22084 }
22085 return true;
22086
22087 } else {
22088 this.edit('', undefined, true);
22089
22090 this.intro = this.intro.replace(rx, '');
22091 if (this.intro.length) { return true; }
22092 }
22093 };
22094
22095 Chunk.prototype.trimStart = function trimStart (rx) {
22096 this.intro = this.intro.replace(rx, '');
22097 if (this.intro.length) { return true; }
22098
22099 var trimmed = this.content.replace(rx, '');
22100
22101 if (trimmed.length) {
22102 if (trimmed !== this.content) {
22103 this.split(this.end - trimmed.length);
22104 this.edit('', undefined, true);
22105 }
22106 return true;
22107
22108 } else {
22109 this.edit('', undefined, true);
22110
22111 this.outro = this.outro.replace(rx, '');
22112 if (this.outro.length) { return true; }
22113 }
22114 };
22115
22116 var btoa$1 = function () {
22117 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
22118 };
22119 if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
22120 btoa$1 = function (str) { return window.btoa(unescape(encodeURIComponent(str))); };
22121 } else if (typeof Buffer === 'function') {
22122 btoa$1 = function (str) { return Buffer.from(str, 'utf-8').toString('base64'); };
22123 }
22124
22125 var SourceMap = function SourceMap(properties) {
22126 this.version = 3;
22127 this.file = properties.file;
22128 this.sources = properties.sources;
22129 this.sourcesContent = properties.sourcesContent;
22130 this.names = properties.names;
22131 this.mappings = encode(properties.mappings);
22132 };
22133
22134 SourceMap.prototype.toString = function toString () {
22135 return JSON.stringify(this);
22136 };
22137
22138 SourceMap.prototype.toUrl = function toUrl () {
22139 return 'data:application/json;charset=utf-8;base64,' + btoa$1(this.toString());
22140 };
22141
22142 function guessIndent(code) {
22143 var lines = code.split('\n');
22144
22145 var tabbed = lines.filter(function (line) { return /^\t+/.test(line); });
22146 var spaced = lines.filter(function (line) { return /^ {2,}/.test(line); });
22147
22148 if (tabbed.length === 0 && spaced.length === 0) {
22149 return null;
22150 }
22151
22152 // More lines tabbed than spaced? Assume tabs, and
22153 // default to tabs in the case of a tie (or nothing
22154 // to go on)
22155 if (tabbed.length >= spaced.length) {
22156 return '\t';
22157 }
22158
22159 // Otherwise, we need to guess the multiple
22160 var min = spaced.reduce(function (previous, current) {
22161 var numSpaces = /^ +/.exec(current)[0].length;
22162 return Math.min(numSpaces, previous);
22163 }, Infinity);
22164
22165 return new Array(min + 1).join(' ');
22166 }
22167
22168 function getRelativePath(from, to) {
22169 var fromParts = from.split(/[/\\]/);
22170 var toParts = to.split(/[/\\]/);
22171
22172 fromParts.pop(); // get dirname
22173
22174 while (fromParts[0] === toParts[0]) {
22175 fromParts.shift();
22176 toParts.shift();
22177 }
22178
22179 if (fromParts.length) {
22180 var i = fromParts.length;
22181 while (i--) { fromParts[i] = '..'; }
22182 }
22183
22184 return fromParts.concat(toParts).join('/');
22185 }
22186
22187 var toString$1 = Object.prototype.toString;
22188
22189 function isObject(thing) {
22190 return toString$1.call(thing) === '[object Object]';
22191 }
22192
22193 function getLocator$1(source) {
22194 var originalLines = source.split('\n');
22195 var lineOffsets = [];
22196
22197 for (var i = 0, pos = 0; i < originalLines.length; i++) {
22198 lineOffsets.push(pos);
22199 pos += originalLines[i].length + 1;
22200 }
22201
22202 return function locate(index) {
22203 var i = 0;
22204 var j = lineOffsets.length;
22205 while (i < j) {
22206 var m = (i + j) >> 1;
22207 if (index < lineOffsets[m]) {
22208 j = m;
22209 } else {
22210 i = m + 1;
22211 }
22212 }
22213 var line = i - 1;
22214 var column = index - lineOffsets[line];
22215 return { line: line, column: column };
22216 };
22217 }
22218
22219 var Mappings = function Mappings(hires) {
22220 this.hires = hires;
22221 this.generatedCodeLine = 0;
22222 this.generatedCodeColumn = 0;
22223 this.raw = [];
22224 this.rawSegments = this.raw[this.generatedCodeLine] = [];
22225 this.pending = null;
22226 };
22227
22228 Mappings.prototype.addEdit = function addEdit (sourceIndex, content, loc, nameIndex) {
22229 if (content.length) {
22230 var segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
22231 if (nameIndex >= 0) {
22232 segment.push(nameIndex);
22233 }
22234 this.rawSegments.push(segment);
22235 } else if (this.pending) {
22236 this.rawSegments.push(this.pending);
22237 }
22238
22239 this.advance(content);
22240 this.pending = null;
22241 };
22242
22243 Mappings.prototype.addUneditedChunk = function addUneditedChunk (sourceIndex, chunk, original, loc, sourcemapLocations) {
22244 var originalCharIndex = chunk.start;
22245 var first = true;
22246
22247 while (originalCharIndex < chunk.end) {
22248 if (this.hires || first || sourcemapLocations[originalCharIndex]) {
22249 this.rawSegments.push([this.generatedCodeColumn, sourceIndex, loc.line, loc.column]);
22250 }
22251
22252 if (original[originalCharIndex] === '\n') {
22253 loc.line += 1;
22254 loc.column = 0;
22255 this.generatedCodeLine += 1;
22256 this.raw[this.generatedCodeLine] = this.rawSegments = [];
22257 this.generatedCodeColumn = 0;
22258 } else {
22259 loc.column += 1;
22260 this.generatedCodeColumn += 1;
22261 }
22262
22263 originalCharIndex += 1;
22264 first = false;
22265 }
22266
22267 this.pending = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
22268 };
22269
22270 Mappings.prototype.advance = function advance (str) {
22271 if (!str) { return; }
22272
22273 var lines = str.split('\n');
22274
22275 if (lines.length > 1) {
22276 for (var i = 0; i < lines.length - 1; i++) {
22277 this.generatedCodeLine++;
22278 this.raw[this.generatedCodeLine] = this.rawSegments = [];
22279 }
22280 this.generatedCodeColumn = 0;
22281 }
22282
22283 this.generatedCodeColumn += lines[lines.length - 1].length;
22284 };
22285
22286 var n = '\n';
22287
22288 var warned = {
22289 insertLeft: false,
22290 insertRight: false,
22291 storeName: false
22292 };
22293
22294 var MagicString = function MagicString(string, options) {
22295 if ( options === void 0 ) options = {};
22296
22297 var chunk = new Chunk(0, string.length, string);
22298
22299 Object.defineProperties(this, {
22300 original: { writable: true, value: string },
22301 outro: { writable: true, value: '' },
22302 intro: { writable: true, value: '' },
22303 firstChunk: { writable: true, value: chunk },
22304 lastChunk: { writable: true, value: chunk },
22305 lastSearchedChunk: { writable: true, value: chunk },
22306 byStart: { writable: true, value: {} },
22307 byEnd: { writable: true, value: {} },
22308 filename: { writable: true, value: options.filename },
22309 indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
22310 sourcemapLocations: { writable: true, value: {} },
22311 storedNames: { writable: true, value: {} },
22312 indentStr: { writable: true, value: guessIndent(string) }
22313 });
22314
22315 this.byStart[0] = chunk;
22316 this.byEnd[string.length] = chunk;
22317 };
22318
22319 MagicString.prototype.addSourcemapLocation = function addSourcemapLocation (char) {
22320 this.sourcemapLocations[char] = true;
22321 };
22322
22323 MagicString.prototype.append = function append (content) {
22324 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
22325
22326 this.outro += content;
22327 return this;
22328 };
22329
22330 MagicString.prototype.appendLeft = function appendLeft (index, content) {
22331 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22332
22333 this._split(index);
22334
22335 var chunk = this.byEnd[index];
22336
22337 if (chunk) {
22338 chunk.appendLeft(content);
22339 } else {
22340 this.intro += content;
22341 }
22342 return this;
22343 };
22344
22345 MagicString.prototype.appendRight = function appendRight (index, content) {
22346 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22347
22348 this._split(index);
22349
22350 var chunk = this.byStart[index];
22351
22352 if (chunk) {
22353 chunk.appendRight(content);
22354 } else {
22355 this.outro += content;
22356 }
22357 return this;
22358 };
22359
22360 MagicString.prototype.clone = function clone () {
22361 var cloned = new MagicString(this.original, { filename: this.filename });
22362
22363 var originalChunk = this.firstChunk;
22364 var clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());
22365
22366 while (originalChunk) {
22367 cloned.byStart[clonedChunk.start] = clonedChunk;
22368 cloned.byEnd[clonedChunk.end] = clonedChunk;
22369
22370 var nextOriginalChunk = originalChunk.next;
22371 var nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
22372
22373 if (nextClonedChunk) {
22374 clonedChunk.next = nextClonedChunk;
22375 nextClonedChunk.previous = clonedChunk;
22376
22377 clonedChunk = nextClonedChunk;
22378 }
22379
22380 originalChunk = nextOriginalChunk;
22381 }
22382
22383 cloned.lastChunk = clonedChunk;
22384
22385 if (this.indentExclusionRanges) {
22386 cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
22387 }
22388
22389 Object.keys(this.sourcemapLocations).forEach(function (loc) {
22390 cloned.sourcemapLocations[loc] = true;
22391 });
22392
22393 return cloned;
22394 };
22395
22396 MagicString.prototype.generateDecodedMap = function generateDecodedMap (options) {
22397 var this$1 = this;
22398
22399 options = options || {};
22400
22401 var sourceIndex = 0;
22402 var names = Object.keys(this.storedNames);
22403 var mappings = new Mappings(options.hires);
22404
22405 var locate = getLocator$1(this.original);
22406
22407 if (this.intro) {
22408 mappings.advance(this.intro);
22409 }
22410
22411 this.firstChunk.eachNext(function (chunk) {
22412 var loc = locate(chunk.start);
22413
22414 if (chunk.intro.length) { mappings.advance(chunk.intro); }
22415
22416 if (chunk.edited) {
22417 mappings.addEdit(
22418 sourceIndex,
22419 chunk.content,
22420 loc,
22421 chunk.storeName ? names.indexOf(chunk.original) : -1
22422 );
22423 } else {
22424 mappings.addUneditedChunk(sourceIndex, chunk, this$1.original, loc, this$1.sourcemapLocations);
22425 }
22426
22427 if (chunk.outro.length) { mappings.advance(chunk.outro); }
22428 });
22429
22430 return {
22431 file: options.file ? options.file.split(/[/\\]/).pop() : null,
22432 sources: [options.source ? getRelativePath(options.file || '', options.source) : null],
22433 sourcesContent: options.includeContent ? [this.original] : [null],
22434 names: names,
22435 mappings: mappings.raw
22436 };
22437 };
22438
22439 MagicString.prototype.generateMap = function generateMap (options) {
22440 return new SourceMap(this.generateDecodedMap(options));
22441 };
22442
22443 MagicString.prototype.getIndentString = function getIndentString () {
22444 return this.indentStr === null ? '\t' : this.indentStr;
22445 };
22446
22447 MagicString.prototype.indent = function indent (indentStr, options) {
22448 var pattern = /^[^\r\n]/gm;
22449
22450 if (isObject(indentStr)) {
22451 options = indentStr;
22452 indentStr = undefined;
22453 }
22454
22455 indentStr = indentStr !== undefined ? indentStr : this.indentStr || '\t';
22456
22457 if (indentStr === '') { return this; } // noop
22458
22459 options = options || {};
22460
22461 // Process exclusion ranges
22462 var isExcluded = {};
22463
22464 if (options.exclude) {
22465 var exclusions =
22466 typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;
22467 exclusions.forEach(function (exclusion) {
22468 for (var i = exclusion[0]; i < exclusion[1]; i += 1) {
22469 isExcluded[i] = true;
22470 }
22471 });
22472 }
22473
22474 var shouldIndentNextCharacter = options.indentStart !== false;
22475 var replacer = function (match) {
22476 if (shouldIndentNextCharacter) { return ("" + indentStr + match); }
22477 shouldIndentNextCharacter = true;
22478 return match;
22479 };
22480
22481 this.intro = this.intro.replace(pattern, replacer);
22482
22483 var charIndex = 0;
22484 var chunk = this.firstChunk;
22485
22486 while (chunk) {
22487 var end = chunk.end;
22488
22489 if (chunk.edited) {
22490 if (!isExcluded[charIndex]) {
22491 chunk.content = chunk.content.replace(pattern, replacer);
22492
22493 if (chunk.content.length) {
22494 shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';
22495 }
22496 }
22497 } else {
22498 charIndex = chunk.start;
22499
22500 while (charIndex < end) {
22501 if (!isExcluded[charIndex]) {
22502 var char = this.original[charIndex];
22503
22504 if (char === '\n') {
22505 shouldIndentNextCharacter = true;
22506 } else if (char !== '\r' && shouldIndentNextCharacter) {
22507 shouldIndentNextCharacter = false;
22508
22509 if (charIndex === chunk.start) {
22510 chunk.prependRight(indentStr);
22511 } else {
22512 this._splitChunk(chunk, charIndex);
22513 chunk = chunk.next;
22514 chunk.prependRight(indentStr);
22515 }
22516 }
22517 }
22518
22519 charIndex += 1;
22520 }
22521 }
22522
22523 charIndex = chunk.end;
22524 chunk = chunk.next;
22525 }
22526
22527 this.outro = this.outro.replace(pattern, replacer);
22528
22529 return this;
22530 };
22531
22532 MagicString.prototype.insert = function insert () {
22533 throw new Error('magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)');
22534 };
22535
22536 MagicString.prototype.insertLeft = function insertLeft (index, content) {
22537 if (!warned.insertLeft) {
22538 console.warn('magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead'); // eslint-disable-line no-console
22539 warned.insertLeft = true;
22540 }
22541
22542 return this.appendLeft(index, content);
22543 };
22544
22545 MagicString.prototype.insertRight = function insertRight (index, content) {
22546 if (!warned.insertRight) {
22547 console.warn('magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead'); // eslint-disable-line no-console
22548 warned.insertRight = true;
22549 }
22550
22551 return this.prependRight(index, content);
22552 };
22553
22554 MagicString.prototype.move = function move (start, end, index) {
22555 if (index >= start && index <= end) { throw new Error('Cannot move a selection inside itself'); }
22556
22557 this._split(start);
22558 this._split(end);
22559 this._split(index);
22560
22561 var first = this.byStart[start];
22562 var last = this.byEnd[end];
22563
22564 var oldLeft = first.previous;
22565 var oldRight = last.next;
22566
22567 var newRight = this.byStart[index];
22568 if (!newRight && last === this.lastChunk) { return this; }
22569 var newLeft = newRight ? newRight.previous : this.lastChunk;
22570
22571 if (oldLeft) { oldLeft.next = oldRight; }
22572 if (oldRight) { oldRight.previous = oldLeft; }
22573
22574 if (newLeft) { newLeft.next = first; }
22575 if (newRight) { newRight.previous = last; }
22576
22577 if (!first.previous) { this.firstChunk = last.next; }
22578 if (!last.next) {
22579 this.lastChunk = first.previous;
22580 this.lastChunk.next = null;
22581 }
22582
22583 first.previous = newLeft;
22584 last.next = newRight || null;
22585
22586 if (!newLeft) { this.firstChunk = first; }
22587 if (!newRight) { this.lastChunk = last; }
22588 return this;
22589 };
22590
22591 MagicString.prototype.overwrite = function overwrite (start, end, content, options) {
22592 if (typeof content !== 'string') { throw new TypeError('replacement content must be a string'); }
22593
22594 while (start < 0) { start += this.original.length; }
22595 while (end < 0) { end += this.original.length; }
22596
22597 if (end > this.original.length) { throw new Error('end is out of bounds'); }
22598 if (start === end)
22599 { throw new Error('Cannot overwrite a zero-length range – use appendLeft or prependRight instead'); }
22600
22601 this._split(start);
22602 this._split(end);
22603
22604 if (options === true) {
22605 if (!warned.storeName) {
22606 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
22607 warned.storeName = true;
22608 }
22609
22610 options = { storeName: true };
22611 }
22612 var storeName = options !== undefined ? options.storeName : false;
22613 var contentOnly = options !== undefined ? options.contentOnly : false;
22614
22615 if (storeName) {
22616 var original = this.original.slice(start, end);
22617 this.storedNames[original] = true;
22618 }
22619
22620 var first = this.byStart[start];
22621 var last = this.byEnd[end];
22622
22623 if (first) {
22624 if (end > first.end && first.next !== this.byStart[first.end]) {
22625 throw new Error('Cannot overwrite across a split point');
22626 }
22627
22628 first.edit(content, storeName, contentOnly);
22629
22630 if (first !== last) {
22631 var chunk = first.next;
22632 while (chunk !== last) {
22633 chunk.edit('', false);
22634 chunk = chunk.next;
22635 }
22636
22637 chunk.edit('', false);
22638 }
22639 } else {
22640 // must be inserting at the end
22641 var newChunk = new Chunk(start, end, '').edit(content, storeName);
22642
22643 // TODO last chunk in the array may not be the last chunk, if it's moved...
22644 last.next = newChunk;
22645 newChunk.previous = last;
22646 }
22647 return this;
22648 };
22649
22650 MagicString.prototype.prepend = function prepend (content) {
22651 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
22652
22653 this.intro = content + this.intro;
22654 return this;
22655 };
22656
22657 MagicString.prototype.prependLeft = function prependLeft (index, content) {
22658 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22659
22660 this._split(index);
22661
22662 var chunk = this.byEnd[index];
22663
22664 if (chunk) {
22665 chunk.prependLeft(content);
22666 } else {
22667 this.intro = content + this.intro;
22668 }
22669 return this;
22670 };
22671
22672 MagicString.prototype.prependRight = function prependRight (index, content) {
22673 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
22674
22675 this._split(index);
22676
22677 var chunk = this.byStart[index];
22678
22679 if (chunk) {
22680 chunk.prependRight(content);
22681 } else {
22682 this.outro = content + this.outro;
22683 }
22684 return this;
22685 };
22686
22687 MagicString.prototype.remove = function remove (start, end) {
22688 while (start < 0) { start += this.original.length; }
22689 while (end < 0) { end += this.original.length; }
22690
22691 if (start === end) { return this; }
22692
22693 if (start < 0 || end > this.original.length) { throw new Error('Character is out of bounds'); }
22694 if (start > end) { throw new Error('end must be greater than start'); }
22695
22696 this._split(start);
22697 this._split(end);
22698
22699 var chunk = this.byStart[start];
22700
22701 while (chunk) {
22702 chunk.intro = '';
22703 chunk.outro = '';
22704 chunk.edit('');
22705
22706 chunk = end > chunk.end ? this.byStart[chunk.end] : null;
22707 }
22708 return this;
22709 };
22710
22711 MagicString.prototype.lastChar = function lastChar () {
22712 if (this.outro.length)
22713 { return this.outro[this.outro.length - 1]; }
22714 var chunk = this.lastChunk;
22715 do {
22716 if (chunk.outro.length)
22717 { return chunk.outro[chunk.outro.length - 1]; }
22718 if (chunk.content.length)
22719 { return chunk.content[chunk.content.length - 1]; }
22720 if (chunk.intro.length)
22721 { return chunk.intro[chunk.intro.length - 1]; }
22722 } while (chunk = chunk.previous);
22723 if (this.intro.length)
22724 { return this.intro[this.intro.length - 1]; }
22725 return '';
22726 };
22727
22728 MagicString.prototype.lastLine = function lastLine () {
22729 var lineIndex = this.outro.lastIndexOf(n);
22730 if (lineIndex !== -1)
22731 { return this.outro.substr(lineIndex + 1); }
22732 var lineStr = this.outro;
22733 var chunk = this.lastChunk;
22734 do {
22735 if (chunk.outro.length > 0) {
22736 lineIndex = chunk.outro.lastIndexOf(n);
22737 if (lineIndex !== -1)
22738 { return chunk.outro.substr(lineIndex + 1) + lineStr; }
22739 lineStr = chunk.outro + lineStr;
22740 }
22741
22742 if (chunk.content.length > 0) {
22743 lineIndex = chunk.content.lastIndexOf(n);
22744 if (lineIndex !== -1)
22745 { return chunk.content.substr(lineIndex + 1) + lineStr; }
22746 lineStr = chunk.content + lineStr;
22747 }
22748
22749 if (chunk.intro.length > 0) {
22750 lineIndex = chunk.intro.lastIndexOf(n);
22751 if (lineIndex !== -1)
22752 { return chunk.intro.substr(lineIndex + 1) + lineStr; }
22753 lineStr = chunk.intro + lineStr;
22754 }
22755 } while (chunk = chunk.previous);
22756 lineIndex = this.intro.lastIndexOf(n);
22757 if (lineIndex !== -1)
22758 { return this.intro.substr(lineIndex + 1) + lineStr; }
22759 return this.intro + lineStr;
22760 };
22761
22762 MagicString.prototype.slice = function slice (start, end) {
22763 if ( start === void 0 ) start = 0;
22764 if ( end === void 0 ) end = this.original.length;
22765
22766 while (start < 0) { start += this.original.length; }
22767 while (end < 0) { end += this.original.length; }
22768
22769 var result = '';
22770
22771 // find start chunk
22772 var chunk = this.firstChunk;
22773 while (chunk && (chunk.start > start || chunk.end <= start)) {
22774 // found end chunk before start
22775 if (chunk.start < end && chunk.end >= end) {
22776 return result;
22777 }
22778
22779 chunk = chunk.next;
22780 }
22781
22782 if (chunk && chunk.edited && chunk.start !== start)
22783 { throw new Error(("Cannot use replaced character " + start + " as slice start anchor.")); }
22784
22785 var startChunk = chunk;
22786 while (chunk) {
22787 if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
22788 result += chunk.intro;
22789 }
22790
22791 var containsEnd = chunk.start < end && chunk.end >= end;
22792 if (containsEnd && chunk.edited && chunk.end !== end)
22793 { throw new Error(("Cannot use replaced character " + end + " as slice end anchor.")); }
22794
22795 var sliceStart = startChunk === chunk ? start - chunk.start : 0;
22796 var sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
22797
22798 result += chunk.content.slice(sliceStart, sliceEnd);
22799
22800 if (chunk.outro && (!containsEnd || chunk.end === end)) {
22801 result += chunk.outro;
22802 }
22803
22804 if (containsEnd) {
22805 break;
22806 }
22807
22808 chunk = chunk.next;
22809 }
22810
22811 return result;
22812 };
22813
22814 // TODO deprecate this? not really very useful
22815 MagicString.prototype.snip = function snip (start, end) {
22816 var clone = this.clone();
22817 clone.remove(0, start);
22818 clone.remove(end, clone.original.length);
22819
22820 return clone;
22821 };
22822
22823 MagicString.prototype._split = function _split (index) {
22824 if (this.byStart[index] || this.byEnd[index]) { return; }
22825
22826 var chunk = this.lastSearchedChunk;
22827 var searchForward = index > chunk.end;
22828
22829 while (chunk) {
22830 if (chunk.contains(index)) { return this._splitChunk(chunk, index); }
22831
22832 chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
22833 }
22834 };
22835
22836 MagicString.prototype._splitChunk = function _splitChunk (chunk, index) {
22837 if (chunk.edited && chunk.content.length) {
22838 // zero-length edited chunks are a special case (overlapping replacements)
22839 var loc = getLocator$1(this.original)(index);
22840 throw new Error(
22841 ("Cannot split a chunk that has already been edited (" + (loc.line) + ":" + (loc.column) + " – \"" + (chunk.original) + "\")")
22842 );
22843 }
22844
22845 var newChunk = chunk.split(index);
22846
22847 this.byEnd[index] = chunk;
22848 this.byStart[index] = newChunk;
22849 this.byEnd[newChunk.end] = newChunk;
22850
22851 if (chunk === this.lastChunk) { this.lastChunk = newChunk; }
22852
22853 this.lastSearchedChunk = chunk;
22854 return true;
22855 };
22856
22857 MagicString.prototype.toString = function toString () {
22858 var str = this.intro;
22859
22860 var chunk = this.firstChunk;
22861 while (chunk) {
22862 str += chunk.toString();
22863 chunk = chunk.next;
22864 }
22865
22866 return str + this.outro;
22867 };
22868
22869 MagicString.prototype.isEmpty = function isEmpty () {
22870 var chunk = this.firstChunk;
22871 do {
22872 if (chunk.intro.length && chunk.intro.trim() ||
22873 chunk.content.length && chunk.content.trim() ||
22874 chunk.outro.length && chunk.outro.trim())
22875 { return false; }
22876 } while (chunk = chunk.next);
22877 return true;
22878 };
22879
22880 MagicString.prototype.length = function length () {
22881 var chunk = this.firstChunk;
22882 var length = 0;
22883 do {
22884 length += chunk.intro.length + chunk.content.length + chunk.outro.length;
22885 } while (chunk = chunk.next);
22886 return length;
22887 };
22888
22889 MagicString.prototype.trimLines = function trimLines () {
22890 return this.trim('[\\r\\n]');
22891 };
22892
22893 MagicString.prototype.trim = function trim (charType) {
22894 return this.trimStart(charType).trimEnd(charType);
22895 };
22896
22897 MagicString.prototype.trimEndAborted = function trimEndAborted (charType) {
22898 var rx = new RegExp((charType || '\\s') + '+$');
22899
22900 this.outro = this.outro.replace(rx, '');
22901 if (this.outro.length) { return true; }
22902
22903 var chunk = this.lastChunk;
22904
22905 do {
22906 var end = chunk.end;
22907 var aborted = chunk.trimEnd(rx);
22908
22909 // if chunk was trimmed, we have a new lastChunk
22910 if (chunk.end !== end) {
22911 if (this.lastChunk === chunk) {
22912 this.lastChunk = chunk.next;
22913 }
22914
22915 this.byEnd[chunk.end] = chunk;
22916 this.byStart[chunk.next.start] = chunk.next;
22917 this.byEnd[chunk.next.end] = chunk.next;
22918 }
22919
22920 if (aborted) { return true; }
22921 chunk = chunk.previous;
22922 } while (chunk);
22923
22924 return false;
22925 };
22926
22927 MagicString.prototype.trimEnd = function trimEnd (charType) {
22928 this.trimEndAborted(charType);
22929 return this;
22930 };
22931 MagicString.prototype.trimStartAborted = function trimStartAborted (charType) {
22932 var rx = new RegExp('^' + (charType || '\\s') + '+');
22933
22934 this.intro = this.intro.replace(rx, '');
22935 if (this.intro.length) { return true; }
22936
22937 var chunk = this.firstChunk;
22938
22939 do {
22940 var end = chunk.end;
22941 var aborted = chunk.trimStart(rx);
22942
22943 if (chunk.end !== end) {
22944 // special case...
22945 if (chunk === this.lastChunk) { this.lastChunk = chunk.next; }
22946
22947 this.byEnd[chunk.end] = chunk;
22948 this.byStart[chunk.next.start] = chunk.next;
22949 this.byEnd[chunk.next.end] = chunk.next;
22950 }
22951
22952 if (aborted) { return true; }
22953 chunk = chunk.next;
22954 } while (chunk);
22955
22956 return false;
22957 };
22958
22959 MagicString.prototype.trimStart = function trimStart (charType) {
22960 this.trimStartAborted(charType);
22961 return this;
22962 };
22963
22964 const UNKNOWN = {};
22965 function gather_possible_values(node, set) {
22966 if (node.type === 'Literal') {
22967 set.add(node.value);
22968 }
22969 else if (node.type === 'ConditionalExpression') {
22970 gather_possible_values(node.consequent, set);
22971 gather_possible_values(node.alternate, set);
22972 }
22973 else {
22974 set.add(UNKNOWN);
22975 }
22976 }
22977
22978 var BlockAppliesToNode;
22979 (function (BlockAppliesToNode) {
22980 BlockAppliesToNode[BlockAppliesToNode["NotPossible"] = 0] = "NotPossible";
22981 BlockAppliesToNode[BlockAppliesToNode["Possible"] = 1] = "Possible";
22982 BlockAppliesToNode[BlockAppliesToNode["UnknownSelectorType"] = 2] = "UnknownSelectorType";
22983 })(BlockAppliesToNode || (BlockAppliesToNode = {}));
22984 class Selector$1 {
22985 constructor(node, stylesheet) {
22986 this.node = node;
22987 this.stylesheet = stylesheet;
22988 this.blocks = group_selectors(node);
22989 // take trailing :global(...) selectors out of consideration
22990 let i = this.blocks.length;
22991 while (i > 0) {
22992 if (!this.blocks[i - 1].global)
22993 break;
22994 i -= 1;
22995 }
22996 this.local_blocks = this.blocks.slice(0, i);
22997 this.used = this.local_blocks.length === 0;
22998 }
22999 apply(node, stack) {
23000 const to_encapsulate = [];
23001 apply_selector(this.local_blocks.slice(), node, stack.slice(), to_encapsulate);
23002 if (to_encapsulate.length > 0) {
23003 to_encapsulate.forEach(({ node, block }) => {
23004 this.stylesheet.nodes_with_css_class.add(node);
23005 block.should_encapsulate = true;
23006 });
23007 this.used = true;
23008 }
23009 }
23010 minify(code) {
23011 let c = null;
23012 this.blocks.forEach((block, i) => {
23013 if (i > 0) {
23014 if (block.start - c > 1) {
23015 code.overwrite(c, block.start, block.combinator.name || ' ');
23016 }
23017 }
23018 c = block.end;
23019 });
23020 }
23021 transform(code, attr, max_amount_class_specificity_increased) {
23022 const amount_class_specificity_to_increase = max_amount_class_specificity_increased - this.blocks.filter(block => block.should_encapsulate).length;
23023 attr = attr.repeat(amount_class_specificity_to_increase + 1);
23024 function encapsulate_block(block) {
23025 let i = block.selectors.length;
23026 while (i--) {
23027 const selector = block.selectors[i];
23028 if (selector.type === 'PseudoElementSelector' || selector.type === 'PseudoClassSelector') {
23029 if (selector.name !== 'root') {
23030 if (i === 0)
23031 code.prependRight(selector.start, attr);
23032 }
23033 continue;
23034 }
23035 if (selector.type === 'TypeSelector' && selector.name === '*') {
23036 code.overwrite(selector.start, selector.end, attr);
23037 }
23038 else {
23039 code.appendLeft(selector.end, attr);
23040 }
23041 break;
23042 }
23043 }
23044 this.blocks.forEach((block) => {
23045 if (block.global) {
23046 const selector = block.selectors[0];
23047 const first = selector.children[0];
23048 const last = selector.children[selector.children.length - 1];
23049 code.remove(selector.start, first.start).remove(last.end, selector.end);
23050 }
23051 if (block.should_encapsulate)
23052 encapsulate_block(block);
23053 });
23054 }
23055 validate(component) {
23056 this.blocks.forEach((block) => {
23057 let i = block.selectors.length;
23058 while (i-- > 1) {
23059 const selector = block.selectors[i];
23060 if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
23061 component.error(selector, {
23062 code: `css-invalid-global`,
23063 message: `:global(...) must be the first element in a compound selector`
23064 });
23065 }
23066 }
23067 });
23068 let start = 0;
23069 let end = this.blocks.length;
23070 for (; start < end; start += 1) {
23071 if (!this.blocks[start].global)
23072 break;
23073 }
23074 for (; end > start; end -= 1) {
23075 if (!this.blocks[end - 1].global)
23076 break;
23077 }
23078 for (let i = start; i < end; i += 1) {
23079 if (this.blocks[i].global) {
23080 component.error(this.blocks[i].selectors[0], {
23081 code: `css-invalid-global`,
23082 message: `:global(...) can be at the start or end of a selector sequence, but not in the middle`
23083 });
23084 }
23085 }
23086 }
23087 get_amount_class_specificity_increased() {
23088 let count = 0;
23089 for (const block of this.blocks) {
23090 if (block.should_encapsulate) {
23091 count++;
23092 }
23093 }
23094 return count;
23095 }
23096 }
23097 function apply_selector(blocks, node, stack, to_encapsulate) {
23098 const block = blocks.pop();
23099 if (!block)
23100 return false;
23101 if (!node) {
23102 return blocks.every(block => block.global);
23103 }
23104 switch (block_might_apply_to_node(block, node)) {
23105 case BlockAppliesToNode.NotPossible:
23106 return false;
23107 case BlockAppliesToNode.UnknownSelectorType:
23108 // bail. TODO figure out what these could be
23109 to_encapsulate.push({ node, block });
23110 return true;
23111 }
23112 if (block.combinator) {
23113 if (block.combinator.type === 'WhiteSpace') {
23114 for (const ancestor_block of blocks) {
23115 if (ancestor_block.global) {
23116 continue;
23117 }
23118 for (const stack_node of stack) {
23119 if (block_might_apply_to_node(ancestor_block, stack_node) !== BlockAppliesToNode.NotPossible) {
23120 to_encapsulate.push({ node: stack_node, block: ancestor_block });
23121 }
23122 }
23123 if (to_encapsulate.length) {
23124 to_encapsulate.push({ node, block });
23125 return true;
23126 }
23127 }
23128 if (blocks.every(block => block.global)) {
23129 to_encapsulate.push({ node, block });
23130 return true;
23131 }
23132 return false;
23133 }
23134 else if (block.combinator.name === '>') {
23135 if (apply_selector(blocks, stack.pop(), stack, to_encapsulate)) {
23136 to_encapsulate.push({ node, block });
23137 return true;
23138 }
23139 return false;
23140 }
23141 // TODO other combinators
23142 to_encapsulate.push({ node, block });
23143 return true;
23144 }
23145 to_encapsulate.push({ node, block });
23146 return true;
23147 }
23148 function block_might_apply_to_node(block, node) {
23149 let i = block.selectors.length;
23150 while (i--) {
23151 const selector = block.selectors[i];
23152 const name = typeof selector.name === 'string' && selector.name.replace(/\\(.)/g, '$1');
23153 if (selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector') {
23154 continue;
23155 }
23156 if (selector.type === 'PseudoClassSelector' && name === 'global') {
23157 // TODO shouldn't see this here... maybe we should enforce that :global(...)
23158 // cannot be sandwiched between non-global selectors?
23159 return BlockAppliesToNode.NotPossible;
23160 }
23161 if (selector.type === 'ClassSelector') {
23162 if (!attribute_matches(node, 'class', name, '~=', false) && !node.classes.some(c => c.name === name))
23163 return BlockAppliesToNode.NotPossible;
23164 }
23165 else if (selector.type === 'IdSelector') {
23166 if (!attribute_matches(node, 'id', name, '=', false))
23167 return BlockAppliesToNode.NotPossible;
23168 }
23169 else if (selector.type === 'AttributeSelector') {
23170 if (!attribute_matches(node, selector.name.name, selector.value && unquote(selector.value), selector.matcher, selector.flags))
23171 return BlockAppliesToNode.NotPossible;
23172 }
23173 else if (selector.type === 'TypeSelector') {
23174 if (node.name.toLowerCase() !== name.toLowerCase() && name !== '*')
23175 return BlockAppliesToNode.NotPossible;
23176 }
23177 else {
23178 return BlockAppliesToNode.UnknownSelectorType;
23179 }
23180 }
23181 return BlockAppliesToNode.Possible;
23182 }
23183 function test_attribute(operator, expected_value, case_insensitive, value) {
23184 if (case_insensitive) {
23185 expected_value = expected_value.toLowerCase();
23186 value = value.toLowerCase();
23187 }
23188 switch (operator) {
23189 case '=': return value === expected_value;
23190 case '~=': return value.split(/\s/).includes(expected_value);
23191 case '|=': return `${value}-`.startsWith(`${expected_value}-`);
23192 case '^=': return value.startsWith(expected_value);
23193 case '$=': return value.endsWith(expected_value);
23194 case '*=': return value.includes(expected_value);
23195 default: throw new Error(`this shouldn't happen`);
23196 }
23197 }
23198 function attribute_matches(node, name, expected_value, operator, case_insensitive) {
23199 const spread = node.attributes.find(attr => attr.type === 'Spread');
23200 if (spread)
23201 return true;
23202 if (node.bindings.some((binding) => binding.name === name))
23203 return true;
23204 const attr = node.attributes.find((attr) => attr.name === name);
23205 if (!attr)
23206 return false;
23207 if (attr.is_true)
23208 return operator === null;
23209 if (!expected_value)
23210 return true;
23211 if (attr.chunks.length === 1) {
23212 const value = attr.chunks[0];
23213 if (!value)
23214 return false;
23215 if (value.type === 'Text')
23216 return test_attribute(operator, expected_value, case_insensitive, value.data);
23217 }
23218 const possible_values = new Set();
23219 let prev_values = [];
23220 for (const chunk of attr.chunks) {
23221 const current_possible_values = new Set();
23222 if (chunk.type === 'Text') {
23223 current_possible_values.add(chunk.data);
23224 }
23225 else {
23226 gather_possible_values(chunk.node, current_possible_values);
23227 }
23228 // impossible to find out all combinations
23229 if (current_possible_values.has(UNKNOWN))
23230 return true;
23231 if (prev_values.length > 0) {
23232 const start_with_space = [];
23233 const remaining = [];
23234 current_possible_values.forEach((current_possible_value) => {
23235 if (/^\s/.test(current_possible_value)) {
23236 start_with_space.push(current_possible_value);
23237 }
23238 else {
23239 remaining.push(current_possible_value);
23240 }
23241 });
23242 if (remaining.length > 0) {
23243 if (start_with_space.length > 0) {
23244 prev_values.forEach(prev_value => possible_values.add(prev_value));
23245 }
23246 const combined = [];
23247 prev_values.forEach((prev_value) => {
23248 remaining.forEach((value) => {
23249 combined.push(prev_value + value);
23250 });
23251 });
23252 prev_values = combined;
23253 start_with_space.forEach((value) => {
23254 if (/\s$/.test(value)) {
23255 possible_values.add(value);
23256 }
23257 else {
23258 prev_values.push(value);
23259 }
23260 });
23261 continue;
23262 }
23263 else {
23264 prev_values.forEach(prev_value => possible_values.add(prev_value));
23265 prev_values = [];
23266 }
23267 }
23268 current_possible_values.forEach((current_possible_value) => {
23269 if (/\s$/.test(current_possible_value)) {
23270 possible_values.add(current_possible_value);
23271 }
23272 else {
23273 prev_values.push(current_possible_value);
23274 }
23275 });
23276 if (prev_values.length < current_possible_values.size) {
23277 prev_values.push(' ');
23278 }
23279 if (prev_values.length > 20) {
23280 // might grow exponentially, bail out
23281 return true;
23282 }
23283 }
23284 prev_values.forEach(prev_value => possible_values.add(prev_value));
23285 if (possible_values.has(UNKNOWN))
23286 return true;
23287 for (const value of possible_values) {
23288 if (test_attribute(operator, expected_value, case_insensitive, value))
23289 return true;
23290 }
23291 return false;
23292 }
23293 function unquote(value) {
23294 if (value.type === 'Identifier')
23295 return value.name;
23296 const str = value.value;
23297 if (str[0] === str[str.length - 1] && str[0] === "'" || str[0] === '"') {
23298 return str.slice(1, str.length - 1);
23299 }
23300 return str;
23301 }
23302 class Block$2 {
23303 constructor(combinator) {
23304 this.combinator = combinator;
23305 this.global = false;
23306 this.selectors = [];
23307 this.start = null;
23308 this.end = null;
23309 this.should_encapsulate = false;
23310 }
23311 add(selector) {
23312 if (this.selectors.length === 0) {
23313 this.start = selector.start;
23314 this.global = selector.type === 'PseudoClassSelector' && selector.name === 'global';
23315 }
23316 this.selectors.push(selector);
23317 this.end = selector.end;
23318 }
23319 }
23320 function group_selectors(selector) {
23321 let block = new Block$2(null);
23322 const blocks = [block];
23323 selector.children.forEach((child) => {
23324 if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
23325 block = new Block$2(child);
23326 blocks.push(block);
23327 }
23328 else {
23329 block.add(child);
23330 }
23331 });
23332 return blocks;
23333 }
23334
23335 // https://github.com/darkskyapp/string-hash/blob/master/index.js
23336 function hash(str) {
23337 str = str.replace(/\r/g, "");
23338 let hash = 5381;
23339 let i = str.length;
23340 while (i--)
23341 hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
23342 return (hash >>> 0).toString(36);
23343 }
23344
23345 function remove_css_prefix(name) {
23346 return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, '');
23347 }
23348 const is_keyframes_node = (node) => remove_css_prefix(node.name) === 'keyframes';
23349 const at_rule_has_declaration = ({ block }) => block &&
23350 block.children &&
23351 block.children.find((node) => node.type === 'Declaration');
23352 function minify_declarations(code, start, declarations) {
23353 let c = start;
23354 declarations.forEach((declaration, i) => {
23355 const separator = i > 0 ? ';' : '';
23356 if ((declaration.node.start - c) > separator.length) {
23357 code.overwrite(c, declaration.node.start, separator);
23358 }
23359 declaration.minify(code);
23360 c = declaration.node.end;
23361 });
23362 return c;
23363 }
23364 class Rule$1 {
23365 constructor(node, stylesheet, parent) {
23366 this.node = node;
23367 this.parent = parent;
23368 this.selectors = node.selector.children.map((node) => new Selector$1(node, stylesheet));
23369 this.declarations = node.block.children.map((node) => new Declaration$1(node));
23370 }
23371 apply(node, stack) {
23372 this.selectors.forEach(selector => selector.apply(node, stack)); // TODO move the logic in here?
23373 }
23374 is_used(dev) {
23375 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
23376 return true;
23377 if (this.declarations.length === 0)
23378 return dev;
23379 return this.selectors.some(s => s.used);
23380 }
23381 minify(code, _dev) {
23382 let c = this.node.start;
23383 let started = false;
23384 this.selectors.forEach((selector) => {
23385 if (selector.used) {
23386 const separator = started ? ',' : '';
23387 if ((selector.node.start - c) > separator.length) {
23388 code.overwrite(c, selector.node.start, separator);
23389 }
23390 selector.minify(code);
23391 c = selector.node.end;
23392 started = true;
23393 }
23394 });
23395 code.remove(c, this.node.block.start);
23396 c = this.node.block.start + 1;
23397 c = minify_declarations(code, c, this.declarations);
23398 code.remove(c, this.node.block.end - 1);
23399 }
23400 transform(code, id, keyframes, max_amount_class_specificity_increased) {
23401 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
23402 return true;
23403 const attr = `.${id}`;
23404 this.selectors.forEach(selector => selector.transform(code, attr, max_amount_class_specificity_increased));
23405 this.declarations.forEach(declaration => declaration.transform(code, keyframes));
23406 }
23407 validate(component) {
23408 this.selectors.forEach(selector => {
23409 selector.validate(component);
23410 });
23411 }
23412 warn_on_unused_selector(handler) {
23413 this.selectors.forEach(selector => {
23414 if (!selector.used)
23415 handler(selector);
23416 });
23417 }
23418 get_max_amount_class_specificity_increased() {
23419 return Math.max(...this.selectors.map(selector => selector.get_amount_class_specificity_increased()));
23420 }
23421 }
23422 class Declaration$1 {
23423 constructor(node) {
23424 this.node = node;
23425 }
23426 transform(code, keyframes) {
23427 const property = this.node.property && remove_css_prefix(this.node.property.toLowerCase());
23428 if (property === 'animation' || property === 'animation-name') {
23429 this.node.value.children.forEach((block) => {
23430 if (block.type === 'Identifier') {
23431 const name = block.name;
23432 if (keyframes.has(name)) {
23433 code.overwrite(block.start, block.end, keyframes.get(name));
23434 }
23435 }
23436 });
23437 }
23438 }
23439 minify(code) {
23440 if (!this.node.property)
23441 return; // @apply, and possibly other weird cases?
23442 const c = this.node.start + this.node.property.length;
23443 const first = this.node.value.children
23444 ? this.node.value.children[0]
23445 : this.node.value;
23446 let start = first.start;
23447 while (/\s/.test(code.original[start]))
23448 start += 1;
23449 if (start - c > 1) {
23450 code.overwrite(c, start, ':');
23451 }
23452 }
23453 }
23454 class Atrule$1 {
23455 constructor(node) {
23456 this.node = node;
23457 this.children = [];
23458 this.declarations = [];
23459 }
23460 apply(node, stack) {
23461 if (this.node.name === 'media' || this.node.name === 'supports') {
23462 this.children.forEach(child => {
23463 child.apply(node, stack);
23464 });
23465 }
23466 else if (is_keyframes_node(this.node)) {
23467 this.children.forEach((rule) => {
23468 rule.selectors.forEach(selector => {
23469 selector.used = true;
23470 });
23471 });
23472 }
23473 }
23474 is_used(_dev) {
23475 return true; // TODO
23476 }
23477 minify(code, dev) {
23478 if (this.node.name === 'media') {
23479 const expression_char = code.original[this.node.expression.start];
23480 let c = this.node.start + (expression_char === '(' ? 6 : 7);
23481 if (this.node.expression.start > c)
23482 code.remove(c, this.node.expression.start);
23483 this.node.expression.children.forEach((query) => {
23484 // TODO minify queries
23485 c = query.end;
23486 });
23487 code.remove(c, this.node.block.start);
23488 }
23489 else if (this.node.name === 'supports') {
23490 let c = this.node.start + 9;
23491 if (this.node.expression.start - c > 1)
23492 code.overwrite(c, this.node.expression.start, ' ');
23493 this.node.expression.children.forEach((query) => {
23494 // TODO minify queries
23495 c = query.end;
23496 });
23497 code.remove(c, this.node.block.start);
23498 }
23499 else {
23500 let c = this.node.start + this.node.name.length + 1;
23501 if (this.node.expression) {
23502 if (this.node.expression.start - c > 1)
23503 code.overwrite(c, this.node.expression.start, ' ');
23504 c = this.node.expression.end;
23505 }
23506 if (this.node.block && this.node.block.start - c > 0) {
23507 code.remove(c, this.node.block.start);
23508 }
23509 }
23510 // TODO other atrules
23511 if (this.node.block) {
23512 let c = this.node.block.start + 1;
23513 if (this.declarations.length) {
23514 c = minify_declarations(code, c, this.declarations);
23515 // if the atrule has children, leave the last declaration semicolon alone
23516 if (this.children.length)
23517 c++;
23518 }
23519 this.children.forEach(child => {
23520 if (child.is_used(dev)) {
23521 code.remove(c, child.node.start);
23522 child.minify(code, dev);
23523 c = child.node.end;
23524 }
23525 });
23526 code.remove(c, this.node.block.end - 1);
23527 }
23528 }
23529 transform(code, id, keyframes, max_amount_class_specificity_increased) {
23530 if (is_keyframes_node(this.node)) {
23531 this.node.expression.children.forEach(({ type, name, start, end }) => {
23532 if (type === 'Identifier') {
23533 if (name.startsWith('-global-')) {
23534 code.remove(start, start + 8);
23535 this.children.forEach((rule) => {
23536 rule.selectors.forEach(selector => {
23537 selector.used = true;
23538 });
23539 });
23540 }
23541 else {
23542 code.overwrite(start, end, keyframes.get(name));
23543 }
23544 }
23545 });
23546 }
23547 this.children.forEach(child => {
23548 child.transform(code, id, keyframes, max_amount_class_specificity_increased);
23549 });
23550 }
23551 validate(component) {
23552 this.children.forEach(child => {
23553 child.validate(component);
23554 });
23555 }
23556 warn_on_unused_selector(handler) {
23557 if (this.node.name !== 'media')
23558 return;
23559 this.children.forEach(child => {
23560 child.warn_on_unused_selector(handler);
23561 });
23562 }
23563 get_max_amount_class_specificity_increased() {
23564 return Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
23565 }
23566 }
23567 class Stylesheet {
23568 constructor(source, ast, filename, dev) {
23569 this.children = [];
23570 this.keyframes = new Map();
23571 this.nodes_with_css_class = new Set();
23572 this.source = source;
23573 this.ast = ast;
23574 this.filename = filename;
23575 this.dev = dev;
23576 if (ast.css && ast.css.children.length) {
23577 this.id = `svelte-${hash(ast.css.content.styles)}`;
23578 this.has_styles = true;
23579 const stack = [];
23580 let depth = 0;
23581 let current_atrule = null;
23582 walk(ast.css, {
23583 enter: (node) => {
23584 if (node.type === 'Atrule') {
23585 const atrule = new Atrule$1(node);
23586 stack.push(atrule);
23587 if (current_atrule) {
23588 current_atrule.children.push(atrule);
23589 }
23590 else if (depth <= 1) {
23591 this.children.push(atrule);
23592 }
23593 if (is_keyframes_node(node)) {
23594 node.expression.children.forEach((expression) => {
23595 if (expression.type === 'Identifier' && !expression.name.startsWith('-global-')) {
23596 this.keyframes.set(expression.name, `${this.id}-${expression.name}`);
23597 }
23598 });
23599 }
23600 else if (at_rule_has_declaration(node)) {
23601 const at_rule_declarations = node.block.children
23602 .filter(node => node.type === 'Declaration')
23603 .map(node => new Declaration$1(node));
23604 atrule.declarations.push(...at_rule_declarations);
23605 }
23606 current_atrule = atrule;
23607 }
23608 if (node.type === 'Rule') {
23609 const rule = new Rule$1(node, this, current_atrule);
23610 if (current_atrule) {
23611 current_atrule.children.push(rule);
23612 }
23613 else if (depth <= 1) {
23614 this.children.push(rule);
23615 }
23616 }
23617 depth += 1;
23618 },
23619 leave: (node) => {
23620 if (node.type === 'Atrule') {
23621 stack.pop();
23622 current_atrule = stack[stack.length - 1];
23623 }
23624 depth -= 1;
23625 }
23626 });
23627 }
23628 else {
23629 this.has_styles = false;
23630 }
23631 }
23632 apply(node) {
23633 if (!this.has_styles)
23634 return;
23635 const stack = [];
23636 let parent = node;
23637 while (parent = parent.parent) {
23638 if (parent.type === 'Element')
23639 stack.unshift(parent);
23640 }
23641 for (let i = 0; i < this.children.length; i += 1) {
23642 const child = this.children[i];
23643 child.apply(node, stack);
23644 }
23645 }
23646 reify() {
23647 this.nodes_with_css_class.forEach((node) => {
23648 node.add_css_class();
23649 });
23650 }
23651 render(file, should_transform_selectors) {
23652 if (!this.has_styles) {
23653 return { code: null, map: null };
23654 }
23655 const code = new MagicString(this.source);
23656 walk(this.ast.css, {
23657 enter: (node) => {
23658 code.addSourcemapLocation(node.start);
23659 code.addSourcemapLocation(node.end);
23660 }
23661 });
23662 if (should_transform_selectors) {
23663 const max = Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
23664 this.children.forEach((child) => {
23665 child.transform(code, this.id, this.keyframes, max);
23666 });
23667 }
23668 let c = 0;
23669 this.children.forEach(child => {
23670 if (child.is_used(this.dev)) {
23671 code.remove(c, child.node.start);
23672 child.minify(code, this.dev);
23673 c = child.node.end;
23674 }
23675 });
23676 code.remove(c, this.source.length);
23677 return {
23678 code: code.toString(),
23679 map: code.generateMap({
23680 includeContent: true,
23681 source: this.filename,
23682 file
23683 })
23684 };
23685 }
23686 validate(component) {
23687 this.children.forEach(child => {
23688 child.validate(component);
23689 });
23690 }
23691 warn_on_unused_selectors(component) {
23692 this.children.forEach(child => {
23693 child.warn_on_unused_selector((selector) => {
23694 component.warn(selector.node, {
23695 code: `css-unused-selector`,
23696 message: `Unused CSS selector`
23697 });
23698 });
23699 });
23700 }
23701 }
23702
23703 const test = typeof process !== 'undefined' && process.env.TEST;
23704
23705 class AbstractBlock extends Node$1 {
23706 constructor(component, parent, scope, info) {
23707 super(component, parent, scope, info);
23708 }
23709 warn_if_empty_block() {
23710 if (!this.children || this.children.length > 1)
23711 return;
23712 const child = this.children[0];
23713 if (!child || (child.type === 'Text' && !/[^ \r\n\f\v\t]/.test(child.data))) {
23714 this.component.warn(this, {
23715 code: 'empty-block',
23716 message: 'Empty block'
23717 });
23718 }
23719 }
23720 }
23721
23722 class PendingBlock extends AbstractBlock {
23723 constructor(component, parent, scope, info) {
23724 super(component, parent, scope, info);
23725 this.children = map_children(component, parent, scope, info.children);
23726 if (!info.skip) {
23727 this.warn_if_empty_block();
23728 }
23729 }
23730 }
23731
23732 class ThenBlock extends AbstractBlock {
23733 constructor(component, parent, scope, info) {
23734 super(component, parent, scope, info);
23735 this.scope = scope.child();
23736 if (parent.then_node) {
23737 parent.then_contexts.forEach(context => {
23738 this.scope.add(context.key.name, parent.expression.dependencies, this);
23739 });
23740 }
23741 this.children = map_children(component, parent, this.scope, info.children);
23742 if (!info.skip) {
23743 this.warn_if_empty_block();
23744 }
23745 }
23746 }
23747
23748 class CatchBlock extends AbstractBlock {
23749 constructor(component, parent, scope, info) {
23750 super(component, parent, scope, info);
23751 this.scope = scope.child();
23752 if (parent.catch_node) {
23753 parent.catch_contexts.forEach(context => {
23754 this.scope.add(context.key.name, parent.expression.dependencies, this);
23755 });
23756 }
23757 this.children = map_children(component, parent, this.scope, info.children);
23758 if (!info.skip) {
23759 this.warn_if_empty_block();
23760 }
23761 }
23762 }
23763
23764 function unpack_destructuring(contexts, node, modifier) {
23765 if (!node)
23766 return;
23767 if (node.type === 'Identifier') {
23768 contexts.push({
23769 key: node,
23770 modifier
23771 });
23772 }
23773 else if (node.type === 'RestElement') {
23774 contexts.push({
23775 key: node.argument,
23776 modifier
23777 });
23778 }
23779 else if (node.type === 'ArrayPattern') {
23780 node.elements.forEach((element, i) => {
23781 if (element && element.type === 'RestElement') {
23782 unpack_destructuring(contexts, element, node => x `${modifier(node)}.slice(${i})`);
23783 }
23784 else if (element && element.type === 'AssignmentPattern') {
23785 unpack_destructuring(contexts, element.left, node => x `${modifier(node)}[${i}] !== undefined ? ${modifier(node)}[${i}] : ${element.right}`);
23786 }
23787 else {
23788 unpack_destructuring(contexts, element, node => x `${modifier(node)}[${i}]`);
23789 }
23790 });
23791 }
23792 else if (node.type === 'ObjectPattern') {
23793 const used_properties = [];
23794 node.properties.forEach((property) => {
23795 const props = property;
23796 if (props.type === 'RestElement') {
23797 unpack_destructuring(contexts, props.argument, node => x `@object_without_properties(${modifier(node)}, [${used_properties}])`);
23798 }
23799 else {
23800 const key = property.key;
23801 const value = property.value;
23802 used_properties.push(x `"${key.name}"`);
23803 if (value.type === 'AssignmentPattern') {
23804 unpack_destructuring(contexts, value.left, node => x `${modifier(node)}.${key.name} !== undefined ? ${modifier(node)}.${key.name} : ${value.right}`);
23805 }
23806 else {
23807 unpack_destructuring(contexts, value, node => x `${modifier(node)}.${key.name}`);
23808 }
23809 }
23810 });
23811 }
23812 }
23813
23814 class AwaitBlock$1 extends Node$1 {
23815 constructor(component, parent, scope, info) {
23816 super(component, parent, scope, info);
23817 this.expression = new Expression(component, this, scope, info.expression);
23818 this.then_node = info.value;
23819 this.catch_node = info.error;
23820 if (this.then_node) {
23821 this.then_contexts = [];
23822 unpack_destructuring(this.then_contexts, info.value, node => node);
23823 }
23824 if (this.catch_node) {
23825 this.catch_contexts = [];
23826 unpack_destructuring(this.catch_contexts, info.error, node => node);
23827 }
23828 this.pending = new PendingBlock(component, this, scope, info.pending);
23829 this.then = new ThenBlock(component, this, scope, info.then);
23830 this.catch = new CatchBlock(component, this, scope, info.catch);
23831 }
23832 }
23833
23834 class EventHandler extends Node$1 {
23835 constructor(component, parent, template_scope, info) {
23836 super(component, parent, template_scope, info);
23837 this.uses_context = false;
23838 this.can_make_passive = false;
23839 this.name = info.name;
23840 this.modifiers = new Set(info.modifiers);
23841 if (info.expression) {
23842 this.expression = new Expression(component, this, template_scope, info.expression);
23843 this.uses_context = this.expression.uses_context;
23844 if (/FunctionExpression/.test(info.expression.type) && info.expression.params.length === 0) {
23845 // TODO make this detection more accurate — if `event.preventDefault` isn't called, and
23846 // `event` is passed to another function, we can make it passive
23847 this.can_make_passive = true;
23848 }
23849 else if (info.expression.type === 'Identifier') {
23850 let node = component.node_for_declaration.get(info.expression.name);
23851 if (node) {
23852 if (node.type === 'VariableDeclaration') {
23853 // for `const handleClick = () => {...}`, we want the [arrow] function expression node
23854 const declarator = node.declarations.find(d => d.id.name === info.expression.name);
23855 node = declarator && declarator.init;
23856 }
23857 if (node && (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') && node.params.length === 0) {
23858 this.can_make_passive = true;
23859 }
23860 }
23861 }
23862 }
23863 else {
23864 this.handler_name = component.get_unique_name(`${sanitize(this.name)}_handler`);
23865 }
23866 }
23867 get reassigned() {
23868 if (!this.expression) {
23869 return false;
23870 }
23871 const node = this.expression.node;
23872 if (/FunctionExpression/.test(node.type)) {
23873 return false;
23874 }
23875 return this.expression.dynamic_dependencies().length > 0;
23876 }
23877 }
23878
23879 class Body extends Node$1 {
23880 constructor(component, parent, scope, info) {
23881 super(component, parent, scope, info);
23882 this.handlers = [];
23883 info.attributes.forEach(node => {
23884 if (node.type === 'EventHandler') {
23885 this.handlers.push(new EventHandler(component, this, scope, node));
23886 }
23887 });
23888 }
23889 }
23890
23891 const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m;
23892 class Comment$2 extends Node$1 {
23893 constructor(component, parent, scope, info) {
23894 super(component, parent, scope, info);
23895 this.data = info.data;
23896 const match = pattern.exec(this.data);
23897 this.ignores = match ? match[1].split(/[^\S]/).map(x => x.trim()).filter(Boolean) : [];
23898 }
23899 }
23900
23901 class ElseBlock extends AbstractBlock {
23902 constructor(component, parent, scope, info) {
23903 super(component, parent, scope, info);
23904 this.children = map_children(component, this, scope, info.children);
23905 this.warn_if_empty_block();
23906 }
23907 }
23908
23909 class EachBlock$1 extends AbstractBlock {
23910 constructor(component, parent, scope, info) {
23911 super(component, parent, scope, info);
23912 this.has_binding = false;
23913 this.expression = new Expression(component, this, scope, info.expression);
23914 this.context = info.context.name || 'each'; // TODO this is used to facilitate binding; currently fails with destructuring
23915 this.context_node = info.context;
23916 this.index = info.index;
23917 this.scope = scope.child();
23918 this.contexts = [];
23919 unpack_destructuring(this.contexts, info.context, node => node);
23920 this.contexts.forEach(context => {
23921 this.scope.add(context.key.name, this.expression.dependencies, this);
23922 });
23923 if (this.index) {
23924 // index can only change if this is a keyed each block
23925 const dependencies = info.key ? this.expression.dependencies : new Set([]);
23926 this.scope.add(this.index, dependencies, this);
23927 }
23928 this.key = info.key
23929 ? new Expression(component, this, this.scope, info.key)
23930 : null;
23931 this.has_animation = false;
23932 this.children = map_children(component, this, this.scope, info.children);
23933 if (this.has_animation) {
23934 if (this.children.length !== 1) {
23935 const child = this.children.find(child => !!child.animation);
23936 component.error(child.animation, {
23937 code: `invalid-animation`,
23938 message: `An element that use the animate directive must be the sole child of a keyed each block`
23939 });
23940 }
23941 }
23942 this.warn_if_empty_block();
23943 this.else = info.else
23944 ? new ElseBlock(component, this, this.scope, info.else)
23945 : null;
23946 }
23947 }
23948
23949 class Attribute extends Node$1 {
23950 constructor(component, parent, scope, info) {
23951 super(component, parent, scope, info);
23952 this.scope = scope;
23953 if (info.type === 'Spread') {
23954 this.name = null;
23955 this.is_spread = true;
23956 this.is_true = false;
23957 this.expression = new Expression(component, this, scope, info.expression);
23958 this.dependencies = this.expression.dependencies;
23959 this.chunks = null;
23960 this.is_static = false;
23961 }
23962 else {
23963 this.name = info.name;
23964 this.is_true = info.value === true;
23965 this.is_static = true;
23966 this.dependencies = new Set();
23967 this.chunks = this.is_true
23968 ? []
23969 : info.value.map(node => {
23970 if (node.type === 'Text')
23971 return node;
23972 this.is_static = false;
23973 const expression = new Expression(component, this, scope, node.expression);
23974 add_to_set(this.dependencies, expression.dependencies);
23975 return expression;
23976 });
23977 }
23978 }
23979 get_dependencies() {
23980 if (this.is_spread)
23981 return this.expression.dynamic_dependencies();
23982 const dependencies = new Set();
23983 this.chunks.forEach(chunk => {
23984 if (chunk.type === 'Expression') {
23985 add_to_set(dependencies, chunk.dynamic_dependencies());
23986 }
23987 });
23988 return Array.from(dependencies);
23989 }
23990 get_value(block) {
23991 if (this.is_true)
23992 return x `true`;
23993 if (this.chunks.length === 0)
23994 return x `""`;
23995 if (this.chunks.length === 1) {
23996 return this.chunks[0].type === 'Text'
23997 ? string_literal(this.chunks[0].data)
23998 : this.chunks[0].manipulate(block);
23999 }
24000 let expression = this.chunks
24001 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : chunk.manipulate(block))
24002 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
24003 if (this.chunks[0].type !== 'Text') {
24004 expression = x `"" + ${expression}`;
24005 }
24006 return expression;
24007 }
24008 get_static_value() {
24009 if (this.is_spread || this.dependencies.size > 0)
24010 return null;
24011 return this.is_true
24012 ? true
24013 : this.chunks[0]
24014 // method should be called only when `is_static = true`
24015 ? this.chunks[0].data
24016 : '';
24017 }
24018 should_cache() {
24019 return this.is_static
24020 ? false
24021 : this.chunks.length === 1
24022 // @ts-ignore todo: probably error
24023 ? this.chunks[0].node.type !== 'Identifier' || this.scope.names.has(this.chunks[0].node.name)
24024 : true;
24025 }
24026 }
24027
24028 // TODO this should live in a specific binding
24029 const read_only_media_attributes = new Set([
24030 'duration',
24031 'buffered',
24032 'seekable',
24033 'played',
24034 'seeking',
24035 'ended',
24036 'videoHeight',
24037 'videoWidth'
24038 ]);
24039 class Binding extends Node$1 {
24040 constructor(component, parent, scope, info) {
24041 super(component, parent, scope, info);
24042 if (info.expression.type !== 'Identifier' && info.expression.type !== 'MemberExpression') {
24043 component.error(info, {
24044 code: 'invalid-directive-value',
24045 message: 'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
24046 });
24047 }
24048 this.name = info.name;
24049 this.expression = new Expression(component, this, scope, info.expression);
24050 this.raw_expression = JSON.parse(JSON.stringify(info.expression));
24051 const { name } = get_object(this.expression.node);
24052 this.is_contextual = scope.names.has(name);
24053 // make sure we track this as a mutable ref
24054 if (scope.is_let(name)) {
24055 component.error(this, {
24056 code: 'invalid-binding',
24057 message: 'Cannot bind to a variable declared with the let: directive'
24058 });
24059 }
24060 else if (this.is_contextual) {
24061 if (scope.is_await(name)) {
24062 component.error(this, {
24063 code: 'invalid-binding',
24064 message: 'Cannot bind to a variable declared with {#await ... then} or {:catch} blocks'
24065 });
24066 }
24067 scope.dependencies_for_name.get(name).forEach(name => {
24068 const variable = component.var_lookup.get(name);
24069 if (variable) {
24070 variable.mutated = true;
24071 }
24072 });
24073 }
24074 else {
24075 const variable = component.var_lookup.get(name);
24076 if (!variable || variable.global)
24077 component.error(this.expression.node, {
24078 code: 'binding-undeclared',
24079 message: `${name} is not declared`
24080 });
24081 variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
24082 if (info.expression.type === 'Identifier' && !variable.writable)
24083 component.error(this.expression.node, {
24084 code: 'invalid-binding',
24085 message: 'Cannot bind to a variable which is not writable',
24086 });
24087 }
24088 const type = parent.get_static_attribute_value('type');
24089 this.is_readonly = (dimensions.test(this.name) ||
24090 (parent.is_media_node && parent.is_media_node() && read_only_media_attributes.has(this.name)) ||
24091 (parent.name === 'input' && type === 'file') // TODO others?
24092 );
24093 }
24094 is_readonly_media_attribute() {
24095 return read_only_media_attributes.has(this.name);
24096 }
24097 }
24098
24099 class Transition extends Node$1 {
24100 constructor(component, parent, scope, info) {
24101 super(component, parent, scope, info);
24102 component.warn_if_undefined(info.name, info, scope);
24103 this.name = info.name;
24104 component.add_reference(info.name.split('.')[0]);
24105 this.directive = info.intro && info.outro ? 'transition' : info.intro ? 'in' : 'out';
24106 this.is_local = info.modifiers.includes('local');
24107 if ((info.intro && parent.intro) || (info.outro && parent.outro)) {
24108 const parent_transition = (parent.intro || parent.outro);
24109 const message = this.directive === parent_transition.directive
24110 ? `An element can only have one '${this.directive}' directive`
24111 : `An element cannot have both ${describe(parent_transition)} directive and ${describe(this)} directive`;
24112 component.error(info, {
24113 code: `duplicate-transition`,
24114 message
24115 });
24116 }
24117 this.expression = info.expression
24118 ? new Expression(component, this, scope, info.expression, true)
24119 : null;
24120 }
24121 }
24122 function describe(transition) {
24123 return transition.directive === 'transition'
24124 ? `a 'transition'`
24125 : `an '${transition.directive}'`;
24126 }
24127
24128 class Animation extends Node$1 {
24129 constructor(component, parent, scope, info) {
24130 super(component, parent, scope, info);
24131 component.warn_if_undefined(info.name, info, scope);
24132 this.name = info.name;
24133 component.add_reference(info.name.split('.')[0]);
24134 if (parent.animation) {
24135 component.error(this, {
24136 code: `duplicate-animation`,
24137 message: `An element can only have one 'animate' directive`
24138 });
24139 }
24140 const block = parent.parent;
24141 if (!block || block.type !== 'EachBlock' || !block.key) {
24142 // TODO can we relax the 'immediate child' rule?
24143 component.error(this, {
24144 code: `invalid-animation`,
24145 message: `An element that use the animate directive must be the immediate child of a keyed each block`
24146 });
24147 }
24148 block.has_animation = true;
24149 this.expression = info.expression
24150 ? new Expression(component, this, scope, info.expression, true)
24151 : null;
24152 }
24153 }
24154
24155 class Class extends Node$1 {
24156 constructor(component, parent, scope, info) {
24157 super(component, parent, scope, info);
24158 this.name = info.name;
24159 this.expression = info.expression
24160 ? new Expression(component, this, scope, info.expression)
24161 : null;
24162 }
24163 }
24164
24165 // Whitespace inside one of these elements will not result in
24166 // a whitespace node being created in any circumstances. (This
24167 // list is almost certainly very incomplete)
24168 const elements_without_text = new Set([
24169 'audio',
24170 'datalist',
24171 'dl',
24172 'optgroup',
24173 'select',
24174 'video',
24175 ]);
24176 class Text$1 extends Node$1 {
24177 constructor(component, parent, scope, info) {
24178 super(component, parent, scope, info);
24179 this.data = info.data;
24180 this.synthetic = info.synthetic || false;
24181 }
24182 should_skip() {
24183 if (/\S/.test(this.data))
24184 return false;
24185 const parent_element = this.find_nearest(/(?:Element|InlineComponent|Head)/);
24186 if (!parent_element)
24187 return false;
24188 if (parent_element.type === 'Head')
24189 return true;
24190 if (parent_element.type === 'InlineComponent')
24191 return parent_element.children.length === 1 && this === parent_element.children[0];
24192 // svg namespace exclusions
24193 if (/svg$/.test(parent_element.namespace)) {
24194 if (this.prev && this.prev.type === "Element" && this.prev.name === "tspan")
24195 return false;
24196 }
24197 return parent_element.namespace || elements_without_text.has(parent_element.name);
24198 }
24199 }
24200
24201 const applicable = new Set(['Identifier', 'ObjectExpression', 'ArrayExpression', 'Property']);
24202 class Let extends Node$1 {
24203 constructor(component, parent, scope, info) {
24204 super(component, parent, scope, info);
24205 this.names = [];
24206 this.name = { type: 'Identifier', name: info.name };
24207 const { names } = this;
24208 if (info.expression) {
24209 this.value = info.expression;
24210 walk(info.expression, {
24211 enter(node) {
24212 if (!applicable.has(node.type)) {
24213 component.error(node, {
24214 code: 'invalid-let',
24215 message: `let directive value must be an identifier or an object/array pattern`
24216 });
24217 }
24218 if (node.type === 'Identifier') {
24219 names.push(node.name);
24220 }
24221 // slightly unfortunate hack
24222 if (node.type === 'ArrayExpression') {
24223 node.type = 'ArrayPattern';
24224 }
24225 if (node.type === 'ObjectExpression') {
24226 node.type = 'ObjectPattern';
24227 }
24228 }
24229 });
24230 }
24231 else {
24232 names.push(this.name.name);
24233 }
24234 }
24235 }
24236
24237 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)$/;
24238 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(' ');
24239 const aria_attribute_set = new Set(aria_attributes);
24240 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(' ');
24241 const aria_role_set = new Set(aria_roles);
24242 const a11y_required_attributes = {
24243 a: ['href'],
24244 area: ['alt', 'aria-label', 'aria-labelledby'],
24245 // html-has-lang
24246 html: ['lang'],
24247 // iframe-has-title
24248 iframe: ['title'],
24249 img: ['alt'],
24250 object: ['title', 'aria-label', 'aria-labelledby']
24251 };
24252 const a11y_distracting_elements = new Set([
24253 'blink',
24254 'marquee'
24255 ]);
24256 const a11y_required_content = new Set([
24257 // anchor-has-content
24258 'a',
24259 // heading-has-content
24260 'h1',
24261 'h2',
24262 'h3',
24263 'h4',
24264 'h5',
24265 'h6'
24266 ]);
24267 const a11y_no_onchange = new Set([
24268 'select',
24269 'option'
24270 ]);
24271 const invisible_elements = new Set(['meta', 'html', 'script', 'style']);
24272 const valid_modifiers = new Set([
24273 'preventDefault',
24274 'stopPropagation',
24275 'capture',
24276 'once',
24277 'passive',
24278 'self'
24279 ]);
24280 const passive_events = new Set([
24281 'wheel',
24282 'touchstart',
24283 'touchmove',
24284 'touchend',
24285 'touchcancel'
24286 ]);
24287 function get_namespace(parent, element, explicit_namespace) {
24288 const parent_element = parent.find_nearest(/^Element/);
24289 if (!parent_element) {
24290 return explicit_namespace || (svg$1.test(element.name)
24291 ? namespaces.svg
24292 : null);
24293 }
24294 if (svg$1.test(element.name.toLowerCase()))
24295 return namespaces.svg;
24296 if (parent_element.name.toLowerCase() === 'foreignobject')
24297 return null;
24298 return parent_element.namespace;
24299 }
24300 class Element$1 extends Node$1 {
24301 constructor(component, parent, scope, info) {
24302 super(component, parent, scope, info);
24303 this.attributes = [];
24304 this.actions = [];
24305 this.bindings = [];
24306 this.classes = [];
24307 this.handlers = [];
24308 this.lets = [];
24309 this.intro = null;
24310 this.outro = null;
24311 this.animation = null;
24312 this.name = info.name;
24313 this.namespace = get_namespace(parent, this, component.namespace);
24314 if (this.name === 'textarea') {
24315 if (info.children.length > 0) {
24316 const value_attribute = info.attributes.find(node => node.name === 'value');
24317 if (value_attribute) {
24318 component.error(value_attribute, {
24319 code: `textarea-duplicate-value`,
24320 message: `A <textarea> can have either a value attribute or (equivalently) child content, but not both`
24321 });
24322 }
24323 // this is an egregious hack, but it's the easiest way to get <textarea>
24324 // children treated the same way as a value attribute
24325 info.attributes.push({
24326 type: 'Attribute',
24327 name: 'value',
24328 value: info.children
24329 });
24330 info.children = [];
24331 }
24332 }
24333 if (this.name === 'option') {
24334 // Special case — treat these the same way:
24335 // <option>{foo}</option>
24336 // <option value={foo}>{foo}</option>
24337 const value_attribute = info.attributes.find(attribute => attribute.name === 'value');
24338 if (!value_attribute) {
24339 info.attributes.push({
24340 type: 'Attribute',
24341 name: 'value',
24342 value: info.children,
24343 synthetic: true
24344 });
24345 }
24346 }
24347 const has_let = info.attributes.some(node => node.type === 'Let');
24348 if (has_let) {
24349 scope = scope.child();
24350 }
24351 // Binding relies on Attribute, defer its evaluation
24352 const order = ['Binding']; // everything else is -1
24353 info.attributes.sort((a, b) => order.indexOf(a.type) - order.indexOf(b.type));
24354 info.attributes.forEach(node => {
24355 switch (node.type) {
24356 case 'Action':
24357 this.actions.push(new Action(component, this, scope, node));
24358 break;
24359 case 'Attribute':
24360 case 'Spread':
24361 // special case
24362 if (node.name === 'xmlns')
24363 this.namespace = node.value[0].data;
24364 this.attributes.push(new Attribute(component, this, scope, node));
24365 break;
24366 case 'Binding':
24367 this.bindings.push(new Binding(component, this, scope, node));
24368 break;
24369 case 'Class':
24370 this.classes.push(new Class(component, this, scope, node));
24371 break;
24372 case 'EventHandler':
24373 this.handlers.push(new EventHandler(component, this, scope, node));
24374 break;
24375 case 'Let': {
24376 const l = new Let(component, this, scope, node);
24377 this.lets.push(l);
24378 const dependencies = new Set([l.name.name]);
24379 l.names.forEach(name => {
24380 scope.add(name, dependencies, this);
24381 });
24382 break;
24383 }
24384 case 'Transition':
24385 {
24386 const transition = new Transition(component, this, scope, node);
24387 if (node.intro)
24388 this.intro = transition;
24389 if (node.outro)
24390 this.outro = transition;
24391 break;
24392 }
24393 case 'Animation':
24394 this.animation = new Animation(component, this, scope, node);
24395 break;
24396 default:
24397 throw new Error(`Not implemented: ${node.type}`);
24398 }
24399 });
24400 this.scope = scope;
24401 this.children = map_children(component, this, this.scope, info.children);
24402 this.validate();
24403 component.stylesheet.apply(this);
24404 }
24405 validate() {
24406 if (a11y_distracting_elements.has(this.name)) {
24407 // no-distracting-elements
24408 this.component.warn(this, {
24409 code: `a11y-distracting-elements`,
24410 message: `A11y: Avoid <${this.name}> elements`
24411 });
24412 }
24413 if (this.name === 'figcaption') {
24414 let { parent } = this;
24415 let is_figure_parent = false;
24416 while (parent) {
24417 if (parent.name === 'figure') {
24418 is_figure_parent = true;
24419 break;
24420 }
24421 if (parent.type === 'Element') {
24422 break;
24423 }
24424 parent = parent.parent;
24425 }
24426 if (!is_figure_parent) {
24427 this.component.warn(this, {
24428 code: `a11y-structure`,
24429 message: `A11y: <figcaption> must be an immediate child of <figure>`
24430 });
24431 }
24432 }
24433 if (this.name === 'figure') {
24434 const children = this.children.filter(node => {
24435 if (node.type === 'Comment')
24436 return false;
24437 if (node.type === 'Text')
24438 return /\S/.test(node.data);
24439 return true;
24440 });
24441 const index = children.findIndex(child => child.name === 'figcaption');
24442 if (index !== -1 && (index !== 0 && index !== children.length - 1)) {
24443 this.component.warn(children[index], {
24444 code: `a11y-structure`,
24445 message: `A11y: <figcaption> must be first or last child of <figure>`
24446 });
24447 }
24448 }
24449 this.validate_attributes();
24450 this.validate_special_cases();
24451 this.validate_bindings();
24452 this.validate_content();
24453 this.validate_event_handlers();
24454 }
24455 validate_attributes() {
24456 const { component, parent } = this;
24457 const attribute_map = new Map();
24458 this.attributes.forEach(attribute => {
24459 if (attribute.is_spread)
24460 return;
24461 const name = attribute.name.toLowerCase();
24462 // aria-props
24463 if (name.startsWith('aria-')) {
24464 if (invisible_elements.has(this.name)) {
24465 // aria-unsupported-elements
24466 component.warn(attribute, {
24467 code: `a11y-aria-attributes`,
24468 message: `A11y: <${this.name}> should not have aria-* attributes`
24469 });
24470 }
24471 const type = name.slice(5);
24472 if (!aria_attribute_set.has(type)) {
24473 const match = fuzzymatch(type, aria_attributes);
24474 let message = `A11y: Unknown aria attribute 'aria-${type}'`;
24475 if (match)
24476 message += ` (did you mean '${match}'?)`;
24477 component.warn(attribute, {
24478 code: `a11y-unknown-aria-attribute`,
24479 message
24480 });
24481 }
24482 if (name === 'aria-hidden' && /^h[1-6]$/.test(this.name)) {
24483 component.warn(attribute, {
24484 code: `a11y-hidden`,
24485 message: `A11y: <${this.name}> element should not be hidden`
24486 });
24487 }
24488 }
24489 // aria-role
24490 if (name === 'role') {
24491 if (invisible_elements.has(this.name)) {
24492 // aria-unsupported-elements
24493 component.warn(attribute, {
24494 code: `a11y-misplaced-role`,
24495 message: `A11y: <${this.name}> should not have role attribute`
24496 });
24497 }
24498 const value = attribute.get_static_value();
24499 // @ts-ignore
24500 if (value && !aria_role_set.has(value)) {
24501 // @ts-ignore
24502 const match = fuzzymatch(value, aria_roles);
24503 let message = `A11y: Unknown role '${value}'`;
24504 if (match)
24505 message += ` (did you mean '${match}'?)`;
24506 component.warn(attribute, {
24507 code: `a11y-unknown-role`,
24508 message
24509 });
24510 }
24511 }
24512 // no-access-key
24513 if (name === 'accesskey') {
24514 component.warn(attribute, {
24515 code: `a11y-accesskey`,
24516 message: `A11y: Avoid using accesskey`
24517 });
24518 }
24519 // no-autofocus
24520 if (name === 'autofocus') {
24521 component.warn(attribute, {
24522 code: `a11y-autofocus`,
24523 message: `A11y: Avoid using autofocus`
24524 });
24525 }
24526 // scope
24527 if (name === 'scope' && this.name !== 'th') {
24528 component.warn(attribute, {
24529 code: `a11y-misplaced-scope`,
24530 message: `A11y: The scope attribute should only be used with <th> elements`
24531 });
24532 }
24533 // tabindex-no-positive
24534 if (name === 'tabindex') {
24535 const value = attribute.get_static_value();
24536 // @ts-ignore todo is tabindex=true correct case?
24537 if (!isNaN(value) && +value > 0) {
24538 component.warn(attribute, {
24539 code: `a11y-positive-tabindex`,
24540 message: `A11y: avoid tabindex values above zero`
24541 });
24542 }
24543 }
24544 if (/(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/.test(name)) {
24545 component.error(attribute, {
24546 code: `illegal-attribute`,
24547 message: `'${name}' is not a valid attribute name`,
24548 });
24549 }
24550 if (name === 'slot') {
24551 if (!attribute.is_static) {
24552 component.error(attribute, {
24553 code: `invalid-slot-attribute`,
24554 message: `slot attribute cannot have a dynamic value`
24555 });
24556 }
24557 if (component.slot_outlets.has(name)) {
24558 component.error(attribute, {
24559 code: `duplicate-slot-attribute`,
24560 message: `Duplicate '${name}' slot`
24561 });
24562 component.slot_outlets.add(name);
24563 }
24564 if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
24565 component.error(attribute, {
24566 code: `invalid-slotted-content`,
24567 message: `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`,
24568 });
24569 }
24570 }
24571 if (name === 'is') {
24572 component.warn(attribute, {
24573 code: 'avoid-is',
24574 message: `The 'is' attribute is not supported cross-browser and should be avoided`
24575 });
24576 }
24577 attribute_map.set(attribute.name, attribute);
24578 });
24579 }
24580 validate_special_cases() {
24581 const { component, attributes, handlers } = this;
24582 const attribute_map = new Map();
24583 const handlers_map = new Map();
24584 attributes.forEach(attribute => (attribute_map.set(attribute.name, attribute)));
24585 handlers.forEach(handler => (handlers_map.set(handler.name, handler)));
24586 if (this.name === 'a') {
24587 const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
24588 const id_attribute = attribute_map.get('id');
24589 const name_attribute = attribute_map.get('name');
24590 if (href_attribute) {
24591 const href_value = href_attribute.get_static_value();
24592 if (href_value === '' || href_value === '#' || /^\W*javascript:/i.test(href_value)) {
24593 component.warn(href_attribute, {
24594 code: `a11y-invalid-attribute`,
24595 message: `A11y: '${href_value}' is not a valid ${href_attribute.name} attribute`
24596 });
24597 }
24598 }
24599 else {
24600 const id_attribute_valid = id_attribute && id_attribute.get_static_value() !== '';
24601 const name_attribute_valid = name_attribute && name_attribute.get_static_value() !== '';
24602 if (!id_attribute_valid && !name_attribute_valid) {
24603 component.warn(this, {
24604 code: `a11y-missing-attribute`,
24605 message: `A11y: <a> element should have an href attribute`
24606 });
24607 }
24608 }
24609 }
24610 else {
24611 const required_attributes = a11y_required_attributes[this.name];
24612 if (required_attributes) {
24613 const has_attribute = required_attributes.some(name => attribute_map.has(name));
24614 if (!has_attribute) {
24615 should_have_attribute(this, required_attributes);
24616 }
24617 }
24618 }
24619 if (this.name === 'input') {
24620 const type = attribute_map.get('type');
24621 if (type && type.get_static_value() === 'image') {
24622 const required_attributes = ['alt', 'aria-label', 'aria-labelledby'];
24623 const has_attribute = required_attributes.some(name => attribute_map.has(name));
24624 if (!has_attribute) {
24625 should_have_attribute(this, required_attributes, 'input type="image"');
24626 }
24627 }
24628 }
24629 if (this.name === 'img') {
24630 const alt_attribute = attribute_map.get('alt');
24631 const aria_hidden_attribute = attribute_map.get('aria-hidden');
24632 const aria_hidden_exist = aria_hidden_attribute && aria_hidden_attribute.get_static_value();
24633 if (alt_attribute && !aria_hidden_exist) {
24634 const alt_value = alt_attribute.get_static_value();
24635 if (/\b(image|picture|photo)\b/i.test(alt_value)) {
24636 component.warn(this, {
24637 code: `a11y-img-redundant-alt`,
24638 message: `A11y: Screenreaders already announce <img> elements as an image.`
24639 });
24640 }
24641 }
24642 }
24643 if (a11y_no_onchange.has(this.name)) {
24644 if (handlers_map.has('change') && !handlers_map.has('blur')) {
24645 component.warn(this, {
24646 code: `a11y-no-onchange`,
24647 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.`
24648 });
24649 }
24650 }
24651 }
24652 validate_bindings() {
24653 const { component } = this;
24654 const check_type_attribute = () => {
24655 const attribute = this.attributes.find((attribute) => attribute.name === 'type');
24656 if (!attribute)
24657 return null;
24658 if (!attribute.is_static) {
24659 component.error(attribute, {
24660 code: `invalid-type`,
24661 message: `'type' attribute cannot be dynamic if input uses two-way binding`
24662 });
24663 }
24664 const value = attribute.get_static_value();
24665 if (value === true) {
24666 component.error(attribute, {
24667 code: `missing-type`,
24668 message: `'type' attribute must be specified`
24669 });
24670 }
24671 return value;
24672 };
24673 this.bindings.forEach(binding => {
24674 const { name } = binding;
24675 if (name === 'value') {
24676 if (this.name !== 'input' &&
24677 this.name !== 'textarea' &&
24678 this.name !== 'select') {
24679 component.error(binding, {
24680 code: `invalid-binding`,
24681 message: `'value' is not a valid binding on <${this.name}> elements`
24682 });
24683 }
24684 if (this.name === 'select') {
24685 const attribute = this.attributes.find((attribute) => attribute.name === 'multiple');
24686 if (attribute && !attribute.is_static) {
24687 component.error(attribute, {
24688 code: `dynamic-multiple-attribute`,
24689 message: `'multiple' attribute cannot be dynamic if select uses two-way binding`
24690 });
24691 }
24692 }
24693 else {
24694 check_type_attribute();
24695 }
24696 }
24697 else if (name === 'checked' || name === 'indeterminate') {
24698 if (this.name !== 'input') {
24699 component.error(binding, {
24700 code: `invalid-binding`,
24701 message: `'${name}' is not a valid binding on <${this.name}> elements`
24702 });
24703 }
24704 const type = check_type_attribute();
24705 if (type !== 'checkbox') {
24706 let message = `'${name}' binding can only be used with <input type="checkbox">`;
24707 if (type === 'radio')
24708 message += ` — for <input type="radio">, use 'group' binding`;
24709 component.error(binding, { code: `invalid-binding`, message });
24710 }
24711 }
24712 else if (name === 'group') {
24713 if (this.name !== 'input') {
24714 component.error(binding, {
24715 code: `invalid-binding`,
24716 message: `'group' is not a valid binding on <${this.name}> elements`
24717 });
24718 }
24719 const type = check_type_attribute();
24720 if (type !== 'checkbox' && type !== 'radio') {
24721 component.error(binding, {
24722 code: `invalid-binding`,
24723 message: `'group' binding can only be used with <input type="checkbox"> or <input type="radio">`
24724 });
24725 }
24726 }
24727 else if (name === 'files') {
24728 if (this.name !== 'input') {
24729 component.error(binding, {
24730 code: `invalid-binding`,
24731 message: `'files' is not a valid binding on <${this.name}> elements`
24732 });
24733 }
24734 const type = check_type_attribute();
24735 if (type !== 'file') {
24736 component.error(binding, {
24737 code: `invalid-binding`,
24738 message: `'files' binding can only be used with <input type="file">`
24739 });
24740 }
24741 }
24742 else if (name === 'open') {
24743 if (this.name !== 'details') {
24744 component.error(binding, {
24745 code: `invalid-binding`,
24746 message: `'${name}' binding can only be used with <details>`
24747 });
24748 }
24749 }
24750 else if (name === 'currentTime' ||
24751 name === 'duration' ||
24752 name === 'paused' ||
24753 name === 'buffered' ||
24754 name === 'seekable' ||
24755 name === 'played' ||
24756 name === 'volume' ||
24757 name === 'muted' ||
24758 name === 'playbackRate' ||
24759 name === 'seeking' ||
24760 name === 'ended') {
24761 if (this.name !== 'audio' && this.name !== 'video') {
24762 component.error(binding, {
24763 code: `invalid-binding`,
24764 message: `'${name}' binding can only be used with <audio> or <video>`
24765 });
24766 }
24767 }
24768 else if (name === 'videoHeight' ||
24769 name === 'videoWidth') {
24770 if (this.name !== 'video') {
24771 component.error(binding, {
24772 code: `invalid-binding`,
24773 message: `'${name}' binding can only be used with <video>`
24774 });
24775 }
24776 }
24777 else if (dimensions.test(name)) {
24778 if (this.name === 'svg' && (name === 'offsetWidth' || name === 'offsetHeight')) {
24779 component.error(binding, {
24780 code: 'invalid-binding',
24781 message: `'${binding.name}' is not a valid binding on <svg>. Use '${name.replace('offset', 'client')}' instead`
24782 });
24783 }
24784 else if (svg$1.test(this.name)) {
24785 component.error(binding, {
24786 code: 'invalid-binding',
24787 message: `'${binding.name}' is not a valid binding on SVG elements`
24788 });
24789 }
24790 else if (is_void(this.name)) {
24791 component.error(binding, {
24792 code: 'invalid-binding',
24793 message: `'${binding.name}' is not a valid binding on void elements like <${this.name}>. Use a wrapper element instead`
24794 });
24795 }
24796 }
24797 else if (name === 'textContent' ||
24798 name === 'innerHTML') {
24799 const contenteditable = this.attributes.find((attribute) => attribute.name === 'contenteditable');
24800 if (!contenteditable) {
24801 component.error(binding, {
24802 code: `missing-contenteditable-attribute`,
24803 message: `'contenteditable' attribute is required for textContent and innerHTML two-way bindings`
24804 });
24805 }
24806 else if (contenteditable && !contenteditable.is_static) {
24807 component.error(contenteditable, {
24808 code: `dynamic-contenteditable-attribute`,
24809 message: `'contenteditable' attribute cannot be dynamic if element uses two-way binding`
24810 });
24811 }
24812 }
24813 else if (name !== 'this') {
24814 component.error(binding, {
24815 code: `invalid-binding`,
24816 message: `'${binding.name}' is not a valid binding`
24817 });
24818 }
24819 });
24820 }
24821 validate_content() {
24822 if (!a11y_required_content.has(this.name))
24823 return;
24824 if (this.children.length === 0) {
24825 this.component.warn(this, {
24826 code: `a11y-missing-content`,
24827 message: `A11y: <${this.name}> element should have child content`
24828 });
24829 }
24830 }
24831 validate_event_handlers() {
24832 const { component } = this;
24833 this.handlers.forEach(handler => {
24834 if (handler.modifiers.has('passive') && handler.modifiers.has('preventDefault')) {
24835 component.error(handler, {
24836 code: 'invalid-event-modifier',
24837 message: `The 'passive' and 'preventDefault' modifiers cannot be used together`
24838 });
24839 }
24840 handler.modifiers.forEach(modifier => {
24841 if (!valid_modifiers.has(modifier)) {
24842 component.error(handler, {
24843 code: 'invalid-event-modifier',
24844 message: `Valid event modifiers are ${list$1(Array.from(valid_modifiers))}`
24845 });
24846 }
24847 if (modifier === 'passive') {
24848 if (passive_events.has(handler.name)) {
24849 if (handler.can_make_passive) {
24850 component.warn(handler, {
24851 code: 'redundant-event-modifier',
24852 message: `Touch event handlers that don't use the 'event' object are passive by default`
24853 });
24854 }
24855 }
24856 else {
24857 component.warn(handler, {
24858 code: 'redundant-event-modifier',
24859 message: `The passive modifier only works with wheel and touch events`
24860 });
24861 }
24862 }
24863 if (component.compile_options.legacy && (modifier === 'once' || modifier === 'passive')) {
24864 // TODO this could be supported, but it would need a few changes to
24865 // how event listeners work
24866 component.error(handler, {
24867 code: 'invalid-event-modifier',
24868 message: `The '${modifier}' modifier cannot be used in legacy mode`
24869 });
24870 }
24871 });
24872 if (passive_events.has(handler.name) && handler.can_make_passive && !handler.modifiers.has('preventDefault')) {
24873 // touch/wheel events should be passive by default
24874 handler.modifiers.add('passive');
24875 }
24876 });
24877 }
24878 is_media_node() {
24879 return this.name === 'audio' || this.name === 'video';
24880 }
24881 add_css_class() {
24882 if (this.attributes.some(attr => attr.is_spread)) {
24883 this.needs_manual_style_scoping = true;
24884 return;
24885 }
24886 const { id } = this.component.stylesheet;
24887 const class_attribute = this.attributes.find(a => a.name === 'class');
24888 if (class_attribute && !class_attribute.is_true) {
24889 if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') {
24890 class_attribute.chunks[0].data += ` ${id}`;
24891 }
24892 else {
24893 class_attribute.chunks.push(new Text$1(this.component, this, this.scope, {
24894 type: 'Text',
24895 data: ` ${id}`,
24896 synthetic: true
24897 }));
24898 }
24899 }
24900 else {
24901 this.attributes.push(new Attribute(this.component, this, this.scope, {
24902 type: 'Attribute',
24903 name: 'class',
24904 value: [{ type: 'Text', data: id, synthetic: true }]
24905 }));
24906 }
24907 }
24908 }
24909 function should_have_attribute(node, attributes, name = node.name) {
24910 const article = /^[aeiou]/.test(attributes[0]) ? 'an' : 'a';
24911 const sequence = attributes.length > 1 ?
24912 attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}` :
24913 attributes[0];
24914 node.component.warn(node, {
24915 code: `a11y-missing-attribute`,
24916 message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
24917 });
24918 }
24919 function within_custom_element(parent) {
24920 while (parent) {
24921 if (parent.type === 'InlineComponent')
24922 return false;
24923 if (parent.type === 'Element' && /-/.test(parent.name))
24924 return true;
24925 parent = parent.parent;
24926 }
24927 return false;
24928 }
24929
24930 class Head$1 extends Node$1 {
24931 constructor(component, parent, scope, info) {
24932 super(component, parent, scope, info);
24933 if (info.attributes.length) {
24934 component.error(info.attributes[0], {
24935 code: `invalid-attribute`,
24936 message: `<svelte:head> should not have any attributes or directives`
24937 });
24938 }
24939 this.children = map_children(component, parent, scope, info.children.filter(child => {
24940 return (child.type !== 'Text' || /\S/.test(child.data));
24941 }));
24942 if (this.children.length > 0) {
24943 this.id = `svelte-${hash(this.component.source.slice(this.start, this.end))}`;
24944 }
24945 }
24946 }
24947
24948 class IfBlock$1 extends AbstractBlock {
24949 constructor(component, parent, scope, info) {
24950 super(component, parent, scope, info);
24951 this.expression = new Expression(component, this, scope, info.expression);
24952 this.children = map_children(component, this, scope, info.children);
24953 this.else = info.else
24954 ? new ElseBlock(component, this, scope, info.else)
24955 : null;
24956 this.warn_if_empty_block();
24957 }
24958 }
24959
24960 class InlineComponent$1 extends Node$1 {
24961 constructor(component, parent, scope, info) {
24962 super(component, parent, scope, info);
24963 this.attributes = [];
24964 this.bindings = [];
24965 this.handlers = [];
24966 this.lets = [];
24967 if (info.name !== 'svelte:component' && info.name !== 'svelte:self') {
24968 const name = info.name.split('.')[0]; // accommodate namespaces
24969 component.warn_if_undefined(name, info, scope);
24970 component.add_reference(name);
24971 }
24972 this.name = info.name;
24973 this.expression = this.name === 'svelte:component'
24974 ? new Expression(component, this, scope, info.expression)
24975 : null;
24976 info.attributes.forEach(node => {
24977 /* eslint-disable no-fallthrough */
24978 switch (node.type) {
24979 case 'Action':
24980 component.error(node, {
24981 code: `invalid-action`,
24982 message: `Actions can only be applied to DOM elements, not components`
24983 });
24984 case 'Attribute':
24985 if (node.name === 'slot') {
24986 component.error(node, {
24987 code: `invalid-prop`,
24988 message: `'slot' is reserved for future use in named slots`
24989 });
24990 }
24991 // fallthrough
24992 case 'Spread':
24993 this.attributes.push(new Attribute(component, this, scope, node));
24994 break;
24995 case 'Binding':
24996 this.bindings.push(new Binding(component, this, scope, node));
24997 break;
24998 case 'Class':
24999 component.error(node, {
25000 code: `invalid-class`,
25001 message: `Classes can only be applied to DOM elements, not components`
25002 });
25003 case 'EventHandler':
25004 this.handlers.push(new EventHandler(component, this, scope, node));
25005 break;
25006 case 'Let':
25007 this.lets.push(new Let(component, this, scope, node));
25008 break;
25009 case 'Transition':
25010 component.error(node, {
25011 code: `invalid-transition`,
25012 message: `Transitions can only be applied to DOM elements, not components`
25013 });
25014 default:
25015 throw new Error(`Not implemented: ${node.type}`);
25016 }
25017 /* eslint-enable no-fallthrough */
25018 });
25019 if (this.lets.length > 0) {
25020 this.scope = scope.child();
25021 this.lets.forEach(l => {
25022 const dependencies = new Set([l.name.name]);
25023 l.names.forEach(name => {
25024 this.scope.add(name, dependencies, this);
25025 });
25026 });
25027 }
25028 else {
25029 this.scope = scope;
25030 }
25031 this.handlers.forEach(handler => {
25032 handler.modifiers.forEach(modifier => {
25033 if (modifier !== 'once') {
25034 component.error(handler, {
25035 code: 'invalid-event-modifier',
25036 message: `Event modifiers other than 'once' can only be used on DOM elements`
25037 });
25038 }
25039 });
25040 });
25041 this.children = map_children(component, this, this.scope, info.children);
25042 }
25043 }
25044
25045 class Tag$2 extends Node$1 {
25046 constructor(component, parent, scope, info) {
25047 super(component, parent, scope, info);
25048 this.expression = new Expression(component, this, scope, info.expression);
25049 this.should_cache = (info.expression.type !== 'Identifier' ||
25050 (this.expression.dependencies.size && scope.names.has(info.expression.name)));
25051 }
25052 }
25053
25054 class MustacheTag extends Tag$2 {
25055 }
25056
25057 class Options extends Node$1 {
25058 }
25059
25060 class RawMustacheTag extends Tag$2 {
25061 }
25062
25063 class DebugTag$1 extends Node$1 {
25064 constructor(component, parent, scope, info) {
25065 super(component, parent, scope, info);
25066 this.expressions = info.identifiers.map(node => {
25067 return new Expression(component, parent, scope, node);
25068 });
25069 }
25070 }
25071
25072 class Slot$1 extends Element$1 {
25073 constructor(component, parent, scope, info) {
25074 super(component, parent, scope, info);
25075 this.values = new Map();
25076 info.attributes.forEach(attr => {
25077 if (attr.type !== 'Attribute') {
25078 component.error(attr, {
25079 code: `invalid-slot-directive`,
25080 message: `<slot> cannot have directives`
25081 });
25082 }
25083 if (attr.name === 'name') {
25084 if (attr.value.length !== 1 || attr.value[0].type !== 'Text') {
25085 component.error(attr, {
25086 code: `dynamic-slot-name`,
25087 message: `<slot> name cannot be dynamic`
25088 });
25089 }
25090 this.slot_name = attr.value[0].data;
25091 if (this.slot_name === 'default') {
25092 component.error(attr, {
25093 code: `invalid-slot-name`,
25094 message: `default is a reserved word — it cannot be used as a slot name`
25095 });
25096 }
25097 }
25098 this.values.set(attr.name, new Attribute(component, this, scope, attr));
25099 });
25100 if (!this.slot_name)
25101 this.slot_name = 'default';
25102 if (this.slot_name === 'default') {
25103 // if this is the default slot, add our dependencies to any
25104 // other slots (which inherit our slot values) that were
25105 // previously encountered
25106 component.slots.forEach((slot) => {
25107 this.values.forEach((attribute, name) => {
25108 if (!slot.values.has(name)) {
25109 slot.values.set(name, attribute);
25110 }
25111 });
25112 });
25113 }
25114 else if (component.slots.has('default')) {
25115 // otherwise, go the other way — inherit values from
25116 // a previously encountered default slot
25117 const default_slot = component.slots.get('default');
25118 default_slot.values.forEach((attribute, name) => {
25119 if (!this.values.has(name)) {
25120 this.values.set(name, attribute);
25121 }
25122 });
25123 }
25124 component.slots.set(this.slot_name, this);
25125 }
25126 }
25127
25128 class Title$1 extends Node$1 {
25129 constructor(component, parent, scope, info) {
25130 super(component, parent, scope, info);
25131 this.children = map_children(component, parent, scope, info.children);
25132 if (info.attributes.length > 0) {
25133 component.error(info.attributes[0], {
25134 code: `illegal-attribute`,
25135 message: `<title> cannot have attributes`
25136 });
25137 }
25138 info.children.forEach(child => {
25139 if (child.type !== 'Text' && child.type !== 'MustacheTag') {
25140 component.error(child, {
25141 code: 'illegal-structure',
25142 message: `<title> can only contain text and {tags}`
25143 });
25144 }
25145 });
25146 this.should_cache = info.children.length === 1
25147 ? (info.children[0].type !== 'Identifier' ||
25148 scope.names.has(info.children[0].name))
25149 : true;
25150 }
25151 }
25152
25153 const valid_bindings = [
25154 'innerWidth',
25155 'innerHeight',
25156 'outerWidth',
25157 'outerHeight',
25158 'scrollX',
25159 'scrollY',
25160 'online'
25161 ];
25162 class Window extends Node$1 {
25163 constructor(component, parent, scope, info) {
25164 super(component, parent, scope, info);
25165 this.handlers = [];
25166 this.bindings = [];
25167 this.actions = [];
25168 info.attributes.forEach(node => {
25169 if (node.type === 'EventHandler') {
25170 this.handlers.push(new EventHandler(component, this, scope, node));
25171 }
25172 else if (node.type === 'Binding') {
25173 if (node.expression.type !== 'Identifier') {
25174 const { parts } = flatten_reference(node.expression);
25175 // TODO is this constraint necessary?
25176 component.error(node.expression, {
25177 code: `invalid-binding`,
25178 message: `Bindings on <svelte:window> must be to top-level properties, e.g. '${parts[parts.length - 1]}' rather than '${parts.join('.')}'`
25179 });
25180 }
25181 if (!~valid_bindings.indexOf(node.name)) {
25182 const match = (node.name === 'width' ? 'innerWidth' :
25183 node.name === 'height' ? 'innerHeight' :
25184 fuzzymatch(node.name, valid_bindings));
25185 const message = `'${node.name}' is not a valid binding on <svelte:window>`;
25186 if (match) {
25187 component.error(node, {
25188 code: `invalid-binding`,
25189 message: `${message} (did you mean '${match}'?)`
25190 });
25191 }
25192 else {
25193 component.error(node, {
25194 code: `invalid-binding`,
25195 message: `${message} — valid bindings are ${list$1(valid_bindings)}`
25196 });
25197 }
25198 }
25199 this.bindings.push(new Binding(component, this, scope, node));
25200 }
25201 else if (node.type === 'Action') {
25202 this.actions.push(new Action(component, this, scope, node));
25203 }
25204 });
25205 }
25206 }
25207
25208 function get_constructor(type) {
25209 switch (type) {
25210 case 'AwaitBlock': return AwaitBlock$1;
25211 case 'Body': return Body;
25212 case 'Comment': return Comment$2;
25213 case 'EachBlock': return EachBlock$1;
25214 case 'Element': return Element$1;
25215 case 'Head': return Head$1;
25216 case 'IfBlock': return IfBlock$1;
25217 case 'InlineComponent': return InlineComponent$1;
25218 case 'MustacheTag': return MustacheTag;
25219 case 'Options': return Options;
25220 case 'RawMustacheTag': return RawMustacheTag;
25221 case 'DebugTag': return DebugTag$1;
25222 case 'Slot': return Slot$1;
25223 case 'Text': return Text$1;
25224 case 'Title': return Title$1;
25225 case 'Window': return Window;
25226 default: throw new Error(`Not implemented: ${type}`);
25227 }
25228 }
25229 function map_children(component, parent, scope, children) {
25230 let last = null;
25231 let ignores = [];
25232 return children.map(child => {
25233 const constructor = get_constructor(child.type);
25234 const use_ignores = child.type !== 'Text' && child.type !== 'Comment' && ignores.length;
25235 if (use_ignores)
25236 component.push_ignores(ignores);
25237 const node = new constructor(component, parent, scope, child);
25238 if (use_ignores)
25239 component.pop_ignores(), ignores = [];
25240 if (node.type === 'Comment' && node.ignores.length) {
25241 ignores.push(...node.ignores);
25242 }
25243 if (last)
25244 last.next = node;
25245 node.prev = last;
25246 last = node;
25247 return node;
25248 });
25249 }
25250
25251 class TemplateScope {
25252 constructor(parent) {
25253 this.owners = new Map();
25254 this.parent = parent;
25255 this.names = new Set(parent ? parent.names : []);
25256 this.dependencies_for_name = new Map(parent ? parent.dependencies_for_name : []);
25257 }
25258 add(name, dependencies, owner) {
25259 this.names.add(name);
25260 this.dependencies_for_name.set(name, dependencies);
25261 this.owners.set(name, owner);
25262 return this;
25263 }
25264 child() {
25265 const child = new TemplateScope(this);
25266 return child;
25267 }
25268 is_top_level(name) {
25269 return !this.parent || !this.names.has(name) && this.parent.is_top_level(name);
25270 }
25271 get_owner(name) {
25272 return this.owners.get(name) || (this.parent && this.parent.get_owner(name));
25273 }
25274 is_let(name) {
25275 const owner = this.get_owner(name);
25276 return owner && (owner.type === 'Element' || owner.type === 'InlineComponent');
25277 }
25278 is_await(name) {
25279 const owner = this.get_owner(name);
25280 return owner && (owner.type === 'ThenBlock' || owner.type === 'CatchBlock');
25281 }
25282 }
25283
25284 class Fragment extends Node$1 {
25285 constructor(component, info) {
25286 const scope = new TemplateScope();
25287 super(component, null, scope, info);
25288 this.scope = scope;
25289 this.children = map_children(component, this, scope, info.children);
25290 }
25291 }
25292
25293 // This file is automatically generated
25294 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"]);
25295
25296 function is_used_as_reference(node, parent) {
25297 if (!isReference(node, parent)) {
25298 return false;
25299 }
25300 if (!parent) {
25301 return true;
25302 }
25303 /* eslint-disable no-fallthrough */
25304 switch (parent.type) {
25305 // disregard the `foo` in `const foo = bar`
25306 case 'VariableDeclarator':
25307 return node !== parent.id;
25308 // disregard the `foo`, `bar` in `function foo(bar){}`
25309 case 'FunctionDeclaration':
25310 // disregard the `foo` in `import { foo } from 'foo'`
25311 case 'ImportSpecifier':
25312 // disregard the `foo` in `import foo from 'foo'`
25313 case 'ImportDefaultSpecifier':
25314 // disregard the `foo` in `import * as foo from 'foo'`
25315 case 'ImportNamespaceSpecifier':
25316 // disregard the `foo` in `export { foo }`
25317 case 'ExportSpecifier':
25318 return false;
25319 default:
25320 return true;
25321 }
25322 }
25323
25324 function check_graph_for_cycles(edges) {
25325 const graph = edges.reduce((g, edge) => {
25326 const [u, v] = edge;
25327 if (!g.has(u))
25328 g.set(u, []);
25329 if (!g.has(v))
25330 g.set(v, []);
25331 g.get(u).push(v);
25332 return g;
25333 }, new Map());
25334 const visited = new Set();
25335 const on_stack = new Set();
25336 const cycles = [];
25337 function visit(v) {
25338 visited.add(v);
25339 on_stack.add(v);
25340 graph.get(v).forEach(w => {
25341 if (!visited.has(w)) {
25342 visit(w);
25343 }
25344 else if (on_stack.has(w)) {
25345 cycles.push([...on_stack, w]);
25346 }
25347 });
25348 on_stack.delete(v);
25349 }
25350 graph.forEach((_, v) => {
25351 if (!visited.has(v)) {
25352 visit(v);
25353 }
25354 });
25355 return cycles[0];
25356 }
25357
25358 class Component {
25359 constructor(ast, source, name, compile_options, stats, warnings) {
25360 this.ignore_stack = [];
25361 this.vars = [];
25362 this.var_lookup = new Map();
25363 this.imports = [];
25364 this.hoistable_nodes = new Set();
25365 this.node_for_declaration = new Map();
25366 this.partly_hoisted = [];
25367 this.fully_hoisted = [];
25368 this.reactive_declarations = [];
25369 this.reactive_declaration_nodes = new Set();
25370 this.has_reactive_assignments = false;
25371 this.injected_reactive_declaration_vars = new Set();
25372 this.helpers = new Map();
25373 this.globals = new Map();
25374 this.indirect_dependencies = new Map();
25375 this.aliases = new Map();
25376 this.used_names = new Set();
25377 this.globally_used_names = new Set();
25378 this.slots = new Map();
25379 this.slot_outlets = new Set();
25380 this.name = { type: 'Identifier', name };
25381 this.stats = stats;
25382 this.warnings = warnings;
25383 this.ast = ast;
25384 this.source = source;
25385 this.compile_options = compile_options;
25386 // the instance JS gets mutated, so we park
25387 // a copy here for later. TODO this feels gross
25388 this.original_ast = {
25389 html: ast.html,
25390 css: ast.css,
25391 instance: ast.instance && JSON.parse(JSON.stringify(ast.instance)),
25392 module: ast.module
25393 };
25394 this.file =
25395 compile_options.filename &&
25396 (typeof process !== 'undefined'
25397 ? compile_options.filename
25398 .replace(process.cwd(), '')
25399 .replace(/^[/\\]/, '')
25400 : compile_options.filename);
25401 this.locate = getLocator(this.source, { offsetLine: 1 });
25402 // styles
25403 this.stylesheet = new Stylesheet(source, ast, compile_options.filename, compile_options.dev);
25404 this.stylesheet.validate(this);
25405 this.component_options = process_component_options(this, this.ast.html.children);
25406 this.namespace =
25407 namespaces[this.component_options.namespace] ||
25408 this.component_options.namespace;
25409 if (compile_options.customElement) {
25410 if (this.component_options.tag === undefined &&
25411 compile_options.tag === undefined) {
25412 const svelteOptions = ast.html.children.find(child => child.name === 'svelte:options') || { start: 0, end: 0 };
25413 this.warn(svelteOptions, {
25414 code: 'custom-element-no-tag',
25415 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}/>`,
25416 });
25417 }
25418 this.tag = this.component_options.tag || compile_options.tag;
25419 }
25420 else {
25421 this.tag = this.name.name;
25422 }
25423 this.walk_module_js();
25424 this.walk_instance_js_pre_template();
25425 this.fragment = new Fragment(this, ast.html);
25426 this.name = this.get_unique_name(name);
25427 this.walk_instance_js_post_template();
25428 if (!compile_options.customElement)
25429 this.stylesheet.reify();
25430 this.stylesheet.warn_on_unused_selectors(this);
25431 }
25432 add_var(variable) {
25433 this.vars.push(variable);
25434 this.var_lookup.set(variable.name, variable);
25435 }
25436 add_reference(name) {
25437 const variable = this.var_lookup.get(name);
25438 if (variable) {
25439 variable.referenced = true;
25440 }
25441 else if (is_reserved_keyword(name)) {
25442 this.add_var({
25443 name,
25444 injected: true,
25445 referenced: true,
25446 });
25447 }
25448 else if (name[0] === '$') {
25449 this.add_var({
25450 name,
25451 injected: true,
25452 referenced: true,
25453 mutated: true,
25454 writable: true,
25455 });
25456 const subscribable_name = name.slice(1);
25457 const variable = this.var_lookup.get(subscribable_name);
25458 if (variable) {
25459 variable.referenced = true;
25460 variable.subscribable = true;
25461 }
25462 }
25463 else {
25464 this.used_names.add(name);
25465 }
25466 }
25467 alias(name) {
25468 if (!this.aliases.has(name)) {
25469 this.aliases.set(name, this.get_unique_name(name));
25470 }
25471 return this.aliases.get(name);
25472 }
25473 global(name) {
25474 const alias = this.alias(name);
25475 this.globals.set(name, alias);
25476 return alias;
25477 }
25478 generate(result) {
25479 let js = null;
25480 let css = null;
25481 if (result) {
25482 const { compile_options, name } = this;
25483 const { format = 'esm' } = compile_options;
25484 const banner = `${this.file ? `${this.file} ` : ``}generated by Svelte v${'3.23.1'}`;
25485 const program = { type: 'Program', body: result.js };
25486 walk(program, {
25487 enter: (node, parent, key) => {
25488 if (node.type === 'Identifier') {
25489 if (node.name[0] === '@') {
25490 if (node.name[1] === '_') {
25491 const alias = this.global(node.name.slice(2));
25492 node.name = alias.name;
25493 }
25494 else {
25495 let name = node.name.slice(1);
25496 if (compile_options.dev) {
25497 if (internal_exports.has(`${name}_dev`)) {
25498 name += '_dev';
25499 }
25500 else if (internal_exports.has(`${name}Dev`)) {
25501 name += 'Dev';
25502 }
25503 }
25504 const alias = this.alias(name);
25505 this.helpers.set(name, alias);
25506 node.name = alias.name;
25507 }
25508 }
25509 else if (node.name[0] !== '#' && !is_valid(node.name)) {
25510 // this hack allows x`foo.${bar}` where bar could be invalid
25511 const literal = { type: 'Literal', value: node.name };
25512 if (parent.type === 'Property' && key === 'key') {
25513 parent.key = literal;
25514 }
25515 else if (parent.type === 'MemberExpression' && key === 'property') {
25516 parent.property = literal;
25517 parent.computed = true;
25518 }
25519 }
25520 }
25521 }
25522 });
25523 const referenced_globals = Array.from(this.globals, ([name, alias]) => name !== alias.name && { name, alias }).filter(Boolean);
25524 if (referenced_globals.length) {
25525 this.helpers.set('globals', this.alias('globals'));
25526 }
25527 const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({
25528 name,
25529 alias,
25530 }));
25531 create_module(program, format, name, banner, compile_options.sveltePath, imported_helpers, referenced_globals, this.imports, this.vars
25532 .filter(variable => variable.module && variable.export_name)
25533 .map(variable => ({
25534 name: variable.name,
25535 as: variable.export_name,
25536 })));
25537 css = compile_options.customElement
25538 ? { code: null, map: null }
25539 : result.css;
25540 js = print(program, {
25541 sourceMapSource: compile_options.filename
25542 });
25543 js.map.sources = [
25544 compile_options.filename ? get_relative_path(compile_options.outputFilename || '', compile_options.filename) : null
25545 ];
25546 js.map.sourcesContent = [
25547 this.source
25548 ];
25549 }
25550 return {
25551 js,
25552 css,
25553 ast: this.original_ast,
25554 warnings: this.warnings,
25555 vars: this.vars
25556 .filter(v => !v.global && !v.internal)
25557 .map(v => ({
25558 name: v.name,
25559 export_name: v.export_name || null,
25560 injected: v.injected || false,
25561 module: v.module || false,
25562 mutated: v.mutated || false,
25563 reassigned: v.reassigned || false,
25564 referenced: v.referenced || false,
25565 writable: v.writable || false,
25566 referenced_from_script: v.referenced_from_script || false,
25567 })),
25568 stats: this.stats.render(),
25569 };
25570 }
25571 get_unique_name(name, scope) {
25572 if (test)
25573 name = `${name}$`;
25574 let alias = name;
25575 for (let i = 1; reserved.has(alias) ||
25576 this.var_lookup.has(alias) ||
25577 this.used_names.has(alias) ||
25578 this.globally_used_names.has(alias) ||
25579 (scope && scope.has(alias)); alias = `${name}_${i++}`)
25580 ;
25581 this.used_names.add(alias);
25582 return { type: 'Identifier', name: alias };
25583 }
25584 get_unique_name_maker() {
25585 const local_used_names = new Set();
25586 function add(name) {
25587 local_used_names.add(name);
25588 }
25589 reserved.forEach(add);
25590 internal_exports.forEach(add);
25591 this.var_lookup.forEach((_value, key) => add(key));
25592 return (name) => {
25593 if (test)
25594 name = `${name}$`;
25595 let alias = name;
25596 for (let i = 1; this.used_names.has(alias) || local_used_names.has(alias); alias = `${name}_${i++}`)
25597 ;
25598 local_used_names.add(alias);
25599 this.globally_used_names.add(alias);
25600 return {
25601 type: 'Identifier',
25602 name: alias
25603 };
25604 };
25605 }
25606 error(pos, e) {
25607 error$1(e.message, {
25608 name: 'ValidationError',
25609 code: e.code,
25610 source: this.source,
25611 start: pos.start,
25612 end: pos.end,
25613 filename: this.compile_options.filename,
25614 });
25615 }
25616 warn(pos, warning) {
25617 if (this.ignores && this.ignores.has(warning.code)) {
25618 return;
25619 }
25620 const start = this.locate(pos.start);
25621 const end = this.locate(pos.end);
25622 const frame = get_code_frame(this.source, start.line - 1, start.column);
25623 this.warnings.push({
25624 code: warning.code,
25625 message: warning.message,
25626 frame,
25627 start,
25628 end,
25629 pos: pos.start,
25630 filename: this.compile_options.filename,
25631 toString: () => `${warning.message} (${start.line}:${start.column})\n${frame}`,
25632 });
25633 }
25634 extract_imports(node) {
25635 this.imports.push(node);
25636 }
25637 extract_exports(node) {
25638 if (node.type === 'ExportDefaultDeclaration') {
25639 this.error(node, {
25640 code: `default-export`,
25641 message: `A component cannot have a default export`,
25642 });
25643 }
25644 if (node.type === 'ExportNamedDeclaration') {
25645 if (node.source) {
25646 this.error(node, {
25647 code: `not-implemented`,
25648 message: `A component currently cannot have an export ... from`,
25649 });
25650 }
25651 if (node.declaration) {
25652 if (node.declaration.type === 'VariableDeclaration') {
25653 node.declaration.declarations.forEach(declarator => {
25654 extract_names(declarator.id).forEach(name => {
25655 const variable = this.var_lookup.get(name);
25656 variable.export_name = name;
25657 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
25658 this.warn(declarator, {
25659 code: `unused-export-let`,
25660 message: `${this.name.name} has unused export property '${name}'. If it is for external reference only, please consider using \`export const ${name}\``
25661 });
25662 }
25663 });
25664 });
25665 }
25666 else {
25667 const { name } = node.declaration.id;
25668 const variable = this.var_lookup.get(name);
25669 variable.export_name = name;
25670 }
25671 return node.declaration;
25672 }
25673 else {
25674 node.specifiers.forEach(specifier => {
25675 const variable = this.var_lookup.get(specifier.local.name);
25676 if (variable) {
25677 variable.export_name = specifier.exported.name;
25678 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
25679 this.warn(specifier, {
25680 code: `unused-export-let`,
25681 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}\``
25682 });
25683 }
25684 }
25685 });
25686 return null;
25687 }
25688 }
25689 }
25690 extract_javascript(script) {
25691 if (!script)
25692 return null;
25693 return script.content.body.filter(node => {
25694 if (!node)
25695 return false;
25696 if (this.hoistable_nodes.has(node))
25697 return false;
25698 if (this.reactive_declaration_nodes.has(node))
25699 return false;
25700 if (node.type === 'ImportDeclaration')
25701 return false;
25702 if (node.type === 'ExportDeclaration' && node.specifiers.length > 0)
25703 return false;
25704 return true;
25705 });
25706 }
25707 walk_module_js() {
25708 const component = this;
25709 const script = this.ast.module;
25710 if (!script)
25711 return;
25712 walk(script.content, {
25713 enter(node) {
25714 if (node.type === 'LabeledStatement' && node.label.name === '$') {
25715 component.warn(node, {
25716 code: 'module-script-reactive-declaration',
25717 message: '$: has no effect in a module script',
25718 });
25719 }
25720 },
25721 });
25722 const { scope, globals } = create_scopes(script.content);
25723 this.module_scope = scope;
25724 scope.declarations.forEach((node, name) => {
25725 if (name[0] === '$') {
25726 this.error(node, {
25727 code: 'illegal-declaration',
25728 message: `The $ prefix is reserved, and cannot be used for variable and import names`,
25729 });
25730 }
25731 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
25732 this.add_var({
25733 name,
25734 module: true,
25735 hoistable: true,
25736 writable
25737 });
25738 });
25739 globals.forEach((node, name) => {
25740 if (name[0] === '$') {
25741 this.error(node, {
25742 code: 'illegal-subscription',
25743 message: `Cannot reference store value inside <script context="module">`,
25744 });
25745 }
25746 else {
25747 this.add_var({
25748 name,
25749 global: true,
25750 hoistable: true
25751 });
25752 }
25753 });
25754 const { body } = script.content;
25755 let i = body.length;
25756 while (--i >= 0) {
25757 const node = body[i];
25758 if (node.type === 'ImportDeclaration') {
25759 this.extract_imports(node);
25760 body.splice(i, 1);
25761 }
25762 if (/^Export/.test(node.type)) {
25763 const replacement = this.extract_exports(node);
25764 if (replacement) {
25765 body[i] = replacement;
25766 }
25767 else {
25768 body.splice(i, 1);
25769 }
25770 }
25771 }
25772 }
25773 walk_instance_js_pre_template() {
25774 const script = this.ast.instance;
25775 if (!script)
25776 return;
25777 // inject vars for reactive declarations
25778 script.content.body.forEach(node => {
25779 if (node.type !== 'LabeledStatement')
25780 return;
25781 if (node.body.type !== 'ExpressionStatement')
25782 return;
25783 const { expression } = node.body;
25784 if (expression.type !== 'AssignmentExpression')
25785 return;
25786 if (expression.left.type === 'MemberExpression')
25787 return;
25788 extract_names(expression.left).forEach(name => {
25789 if (!this.var_lookup.has(name) && name[0] !== '$') {
25790 this.injected_reactive_declaration_vars.add(name);
25791 }
25792 });
25793 });
25794 const { scope: instance_scope, map, globals } = create_scopes(script.content);
25795 this.instance_scope = instance_scope;
25796 this.instance_scope_map = map;
25797 instance_scope.declarations.forEach((node, name) => {
25798 if (name[0] === '$') {
25799 this.error(node, {
25800 code: 'illegal-declaration',
25801 message: `The $ prefix is reserved, and cannot be used for variable and import names`,
25802 });
25803 }
25804 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
25805 this.add_var({
25806 name,
25807 initialised: instance_scope.initialised_declarations.has(name),
25808 writable
25809 });
25810 this.node_for_declaration.set(name, node);
25811 });
25812 globals.forEach((node, name) => {
25813 if (this.var_lookup.has(name))
25814 return;
25815 if (this.injected_reactive_declaration_vars.has(name)) {
25816 this.add_var({
25817 name,
25818 injected: true,
25819 writable: true,
25820 reassigned: true,
25821 initialised: true,
25822 });
25823 }
25824 else if (is_reserved_keyword(name)) {
25825 this.add_var({
25826 name,
25827 injected: true,
25828 });
25829 }
25830 else if (name[0] === '$') {
25831 if (name === '$' || name[1] === '$') {
25832 this.error(node, {
25833 code: 'illegal-global',
25834 message: `${name} is an illegal variable name`
25835 });
25836 }
25837 this.add_var({
25838 name,
25839 injected: true,
25840 mutated: true,
25841 writable: true,
25842 });
25843 this.add_reference(name.slice(1));
25844 const variable = this.var_lookup.get(name.slice(1));
25845 if (variable) {
25846 variable.subscribable = true;
25847 variable.referenced_from_script = true;
25848 }
25849 }
25850 else {
25851 this.add_var({
25852 name,
25853 global: true,
25854 hoistable: true
25855 });
25856 }
25857 });
25858 this.track_references_and_mutations();
25859 }
25860 walk_instance_js_post_template() {
25861 const script = this.ast.instance;
25862 if (!script)
25863 return;
25864 this.post_template_walk();
25865 this.hoist_instance_declarations();
25866 this.extract_reactive_declarations();
25867 }
25868 post_template_walk() {
25869 const script = this.ast.instance;
25870 if (!script)
25871 return;
25872 const component = this;
25873 const { content } = script;
25874 const { instance_scope, instance_scope_map: map } = this;
25875 let scope = instance_scope;
25876 const to_remove = [];
25877 const remove = (parent, prop, index) => {
25878 to_remove.unshift([parent, prop, index]);
25879 };
25880 let scope_updated = false;
25881 let generator_count = 0;
25882 walk(content, {
25883 enter(node, parent, prop, index) {
25884 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
25885 generator_count++;
25886 }
25887 if (map.has(node)) {
25888 scope = map.get(node);
25889 }
25890 if (node.type === 'ImportDeclaration') {
25891 component.extract_imports(node);
25892 // TODO: to use actual remove
25893 remove(parent, prop, index);
25894 return this.skip();
25895 }
25896 if (/^Export/.test(node.type)) {
25897 const replacement = component.extract_exports(node);
25898 if (replacement) {
25899 this.replace(replacement);
25900 }
25901 else {
25902 // TODO: to use actual remove
25903 remove(parent, prop, index);
25904 }
25905 return this.skip();
25906 }
25907 component.warn_on_undefined_store_value_references(node, parent, scope);
25908 },
25909 leave(node) {
25910 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
25911 generator_count--;
25912 }
25913 // do it on leave, to prevent infinite loop
25914 if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0 && generator_count <= 0) {
25915 const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout);
25916 if (to_replace_for_loop_protect) {
25917 this.replace(to_replace_for_loop_protect);
25918 scope_updated = true;
25919 }
25920 }
25921 if (map.has(node)) {
25922 scope = scope.parent;
25923 }
25924 },
25925 });
25926 for (const [parent, prop, index] of to_remove) {
25927 if (parent) {
25928 if (index !== null) {
25929 parent[prop].splice(index, 1);
25930 }
25931 else {
25932 delete parent[prop];
25933 }
25934 }
25935 }
25936 if (scope_updated) {
25937 const { scope, map } = create_scopes(script.content);
25938 this.instance_scope = scope;
25939 this.instance_scope_map = map;
25940 }
25941 }
25942 track_references_and_mutations() {
25943 const script = this.ast.instance;
25944 if (!script)
25945 return;
25946 const component = this;
25947 const { content } = script;
25948 const { instance_scope, module_scope, instance_scope_map: map } = this;
25949 let scope = instance_scope;
25950 walk(content, {
25951 enter(node, parent) {
25952 if (map.has(node)) {
25953 scope = map.get(node);
25954 }
25955 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
25956 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
25957 const names = extract_names(assignee);
25958 const deep = assignee.type === 'MemberExpression';
25959 names.forEach(name => {
25960 const scope_owner = scope.find_owner(name);
25961 if (scope_owner !== null
25962 ? scope_owner === instance_scope
25963 : module_scope && module_scope.has(name)) {
25964 const variable = component.var_lookup.get(name);
25965 variable[deep ? 'mutated' : 'reassigned'] = true;
25966 }
25967 });
25968 }
25969 if (is_used_as_reference(node, parent)) {
25970 const object = get_object(node);
25971 if (scope.find_owner(object.name) === instance_scope) {
25972 const variable = component.var_lookup.get(object.name);
25973 variable.referenced_from_script = true;
25974 }
25975 }
25976 },
25977 leave(node) {
25978 if (map.has(node)) {
25979 scope = scope.parent;
25980 }
25981 },
25982 });
25983 }
25984 warn_on_undefined_store_value_references(node, parent, scope) {
25985 if (node.type === 'LabeledStatement' &&
25986 node.label.name === '$' &&
25987 parent.type !== 'Program') {
25988 this.warn(node, {
25989 code: 'non-top-level-reactive-declaration',
25990 message: '$: has no effect outside of the top-level',
25991 });
25992 }
25993 if (isReference(node, parent)) {
25994 const object = get_object(node);
25995 const { name } = object;
25996 if (name[0] === '$' && !scope.has(name)) {
25997 this.warn_if_undefined(name, object, null);
25998 }
25999 }
26000 }
26001 loop_protect(node, scope, timeout) {
26002 if (node.type === 'WhileStatement' ||
26003 node.type === 'ForStatement' ||
26004 node.type === 'DoWhileStatement') {
26005 const guard = this.get_unique_name('guard', scope);
26006 this.used_names.add(guard.name);
26007 const before = b `const ${guard} = @loop_guard(${timeout})`;
26008 const inside = b `${guard}();`;
26009 // wrap expression statement with BlockStatement
26010 if (node.body.type !== 'BlockStatement') {
26011 node.body = {
26012 type: 'BlockStatement',
26013 body: [node.body],
26014 };
26015 }
26016 node.body.body.push(inside[0]);
26017 return {
26018 type: 'BlockStatement',
26019 body: [
26020 before[0],
26021 node,
26022 ],
26023 };
26024 }
26025 return null;
26026 }
26027 rewrite_props(get_insert) {
26028 if (!this.ast.instance)
26029 return;
26030 const component = this;
26031 const { instance_scope, instance_scope_map: map } = this;
26032 let scope = instance_scope;
26033 walk(this.ast.instance.content, {
26034 enter(node, parent, key, index) {
26035 if (/Function/.test(node.type)) {
26036 return this.skip();
26037 }
26038 if (map.has(node)) {
26039 scope = map.get(node);
26040 }
26041 if (node.type === 'VariableDeclaration') {
26042 if (node.kind === 'var' || scope === instance_scope) {
26043 node.declarations.forEach(declarator => {
26044 if (declarator.id.type !== 'Identifier') {
26045 const inserts = [];
26046 extract_names(declarator.id).forEach(name => {
26047 const variable = component.var_lookup.get(name);
26048 if (variable.export_name) {
26049 // TODO is this still true post-#3539?
26050 component.error(declarator, {
26051 code: 'destructured-prop',
26052 message: `Cannot declare props in destructured declaration`,
26053 });
26054 }
26055 if (variable.subscribable) {
26056 inserts.push(get_insert(variable));
26057 }
26058 });
26059 if (inserts.length) {
26060 parent[key].splice(index + 1, 0, ...inserts);
26061 }
26062 return;
26063 }
26064 const { name } = declarator.id;
26065 const variable = component.var_lookup.get(name);
26066 if (variable.export_name && variable.writable) {
26067 const insert = variable.subscribable
26068 ? get_insert(variable)
26069 : null;
26070 parent[key].splice(index + 1, 0, insert);
26071 declarator.id = {
26072 type: 'ObjectPattern',
26073 properties: [{
26074 type: 'Property',
26075 method: false,
26076 shorthand: false,
26077 computed: false,
26078 kind: 'init',
26079 key: { type: 'Identifier', name: variable.export_name },
26080 value: declarator.init
26081 ? {
26082 type: 'AssignmentPattern',
26083 left: declarator.id,
26084 right: declarator.init
26085 }
26086 : declarator.id
26087 }]
26088 };
26089 declarator.init = x `$$props`;
26090 }
26091 else if (variable.subscribable) {
26092 const insert = get_insert(variable);
26093 parent[key].splice(index + 1, 0, ...insert);
26094 }
26095 });
26096 }
26097 }
26098 },
26099 leave(node, parent, _key, index) {
26100 if (map.has(node)) {
26101 scope = scope.parent;
26102 }
26103 if (node.type === 'ExportNamedDeclaration' && node.declaration) {
26104 parent.body[index] = node.declaration;
26105 }
26106 },
26107 });
26108 }
26109 hoist_instance_declarations() {
26110 // we can safely hoist variable declarations that are
26111 // initialised to literals, and functions that don't
26112 // reference instance variables other than other
26113 // hoistable functions. TODO others?
26114 const { hoistable_nodes, var_lookup, injected_reactive_declaration_vars, imports, } = this;
26115 const top_level_function_declarations = new Map();
26116 const { body } = this.ast.instance.content;
26117 for (let i = 0; i < body.length; i += 1) {
26118 const node = body[i];
26119 if (node.type === 'VariableDeclaration') {
26120 const all_hoistable = node.declarations.every(d => {
26121 if (!d.init)
26122 return false;
26123 if (d.init.type !== 'Literal')
26124 return false;
26125 // everything except const values can be changed by e.g. svelte devtools
26126 // which means we can't hoist it
26127 if (node.kind !== 'const' && this.compile_options.dev)
26128 return false;
26129 const { name } = d.id;
26130 const v = this.var_lookup.get(name);
26131 if (v.reassigned)
26132 return false;
26133 if (v.export_name)
26134 return false;
26135 if (this.var_lookup.get(name).reassigned)
26136 return false;
26137 if (this.vars.find(variable => variable.name === name && variable.module))
26138 return false;
26139 return true;
26140 });
26141 if (all_hoistable) {
26142 node.declarations.forEach(d => {
26143 const variable = this.var_lookup.get(d.id.name);
26144 variable.hoistable = true;
26145 });
26146 hoistable_nodes.add(node);
26147 body.splice(i--, 1);
26148 this.fully_hoisted.push(node);
26149 }
26150 }
26151 if (node.type === 'ExportNamedDeclaration' &&
26152 node.declaration &&
26153 node.declaration.type === 'FunctionDeclaration') {
26154 top_level_function_declarations.set(node.declaration.id.name, node);
26155 }
26156 if (node.type === 'FunctionDeclaration') {
26157 top_level_function_declarations.set(node.id.name, node);
26158 }
26159 }
26160 const checked = new Set();
26161 const walking = new Set();
26162 const is_hoistable = fn_declaration => {
26163 if (fn_declaration.type === 'ExportNamedDeclaration') {
26164 fn_declaration = fn_declaration.declaration;
26165 }
26166 const instance_scope = this.instance_scope;
26167 let scope = this.instance_scope;
26168 const map = this.instance_scope_map;
26169 let hoistable = true;
26170 // handle cycles
26171 walking.add(fn_declaration);
26172 walk(fn_declaration, {
26173 enter(node, parent) {
26174 if (!hoistable)
26175 return this.skip();
26176 if (map.has(node)) {
26177 scope = map.get(node);
26178 }
26179 if (isReference(node, parent)) {
26180 const { name } = flatten_reference(node);
26181 const owner = scope.find_owner(name);
26182 if (injected_reactive_declaration_vars.has(name)) {
26183 hoistable = false;
26184 }
26185 else if (name[0] === '$' && !owner) {
26186 hoistable = false;
26187 }
26188 else if (owner === instance_scope) {
26189 const variable = var_lookup.get(name);
26190 if (variable.reassigned || variable.mutated)
26191 hoistable = false;
26192 if (name === fn_declaration.id.name)
26193 return;
26194 if (variable.hoistable)
26195 return;
26196 if (top_level_function_declarations.has(name)) {
26197 const other_declaration = top_level_function_declarations.get(name);
26198 if (walking.has(other_declaration)) {
26199 hoistable = false;
26200 }
26201 else if (other_declaration.type === 'ExportNamedDeclaration' &&
26202 walking.has(other_declaration.declaration)) {
26203 hoistable = false;
26204 }
26205 else if (!is_hoistable(other_declaration)) {
26206 hoistable = false;
26207 }
26208 }
26209 else {
26210 hoistable = false;
26211 }
26212 }
26213 this.skip();
26214 }
26215 },
26216 leave(node) {
26217 if (map.has(node)) {
26218 scope = scope.parent;
26219 }
26220 },
26221 });
26222 checked.add(fn_declaration);
26223 walking.delete(fn_declaration);
26224 return hoistable;
26225 };
26226 for (const [name, node] of top_level_function_declarations) {
26227 if (is_hoistable(node)) {
26228 const variable = this.var_lookup.get(name);
26229 variable.hoistable = true;
26230 hoistable_nodes.add(node);
26231 const i = body.indexOf(node);
26232 body.splice(i, 1);
26233 this.fully_hoisted.push(node);
26234 }
26235 }
26236 for (const { specifiers } of imports) {
26237 for (const specifier of specifiers) {
26238 const variable = var_lookup.get(specifier.local.name);
26239 if (!variable.mutated)
26240 variable.hoistable = true;
26241 }
26242 }
26243 }
26244 extract_reactive_declarations() {
26245 const component = this;
26246 const unsorted_reactive_declarations = [];
26247 this.ast.instance.content.body.forEach(node => {
26248 if (node.type === 'LabeledStatement' && node.label.name === '$') {
26249 this.reactive_declaration_nodes.add(node);
26250 const assignees = new Set();
26251 const assignee_nodes = new Set();
26252 const dependencies = new Set();
26253 let scope = this.instance_scope;
26254 const map = this.instance_scope_map;
26255 walk(node.body, {
26256 enter(node, parent) {
26257 if (map.has(node)) {
26258 scope = map.get(node);
26259 }
26260 if (node.type === 'AssignmentExpression') {
26261 const left = get_object(node.left);
26262 extract_identifiers(left).forEach(node => {
26263 assignee_nodes.add(node);
26264 assignees.add(node.name);
26265 });
26266 if (node.operator !== '=') {
26267 dependencies.add(left.name);
26268 }
26269 }
26270 else if (node.type === 'UpdateExpression') {
26271 const identifier = get_object(node.argument);
26272 assignees.add(identifier.name);
26273 }
26274 else if (isReference(node, parent)) {
26275 const identifier = get_object(node);
26276 if (!assignee_nodes.has(identifier)) {
26277 const { name } = identifier;
26278 const owner = scope.find_owner(name);
26279 const variable = component.var_lookup.get(name);
26280 if (variable)
26281 variable.is_reactive_dependency = true;
26282 const is_writable_or_mutated = variable && (variable.writable || variable.mutated);
26283 if ((!owner || owner === component.instance_scope) &&
26284 (name[0] === '$' || is_writable_or_mutated)) {
26285 dependencies.add(name);
26286 }
26287 }
26288 this.skip();
26289 }
26290 },
26291 leave(node) {
26292 if (map.has(node)) {
26293 scope = scope.parent;
26294 }
26295 },
26296 });
26297 const { expression } = node.body;
26298 const declaration = expression && expression.left;
26299 unsorted_reactive_declarations.push({
26300 assignees,
26301 dependencies,
26302 node,
26303 declaration,
26304 });
26305 }
26306 });
26307 const lookup = new Map();
26308 unsorted_reactive_declarations.forEach(declaration => {
26309 declaration.assignees.forEach(name => {
26310 if (!lookup.has(name)) {
26311 lookup.set(name, []);
26312 }
26313 // TODO warn or error if a name is assigned to in
26314 // multiple reactive declarations?
26315 lookup.get(name).push(declaration);
26316 });
26317 });
26318 const cycle = check_graph_for_cycles(unsorted_reactive_declarations.reduce((acc, declaration) => {
26319 declaration.assignees.forEach(v => {
26320 declaration.dependencies.forEach(w => {
26321 if (!declaration.assignees.has(w)) {
26322 acc.push([v, w]);
26323 }
26324 });
26325 });
26326 return acc;
26327 }, []));
26328 if (cycle && cycle.length) {
26329 const declarationList = lookup.get(cycle[0]);
26330 const declaration = declarationList[0];
26331 this.error(declaration.node, {
26332 code: 'cyclical-reactive-declaration',
26333 message: `Cyclical dependency detected: ${cycle.join(' → ')}`
26334 });
26335 }
26336 const add_declaration = declaration => {
26337 if (this.reactive_declarations.includes(declaration))
26338 return;
26339 declaration.dependencies.forEach(name => {
26340 if (declaration.assignees.has(name))
26341 return;
26342 const earlier_declarations = lookup.get(name);
26343 if (earlier_declarations)
26344 earlier_declarations.forEach(add_declaration);
26345 });
26346 this.reactive_declarations.push(declaration);
26347 };
26348 unsorted_reactive_declarations.forEach(add_declaration);
26349 }
26350 warn_if_undefined(name, node, template_scope) {
26351 if (name[0] === '$') {
26352 if (name === '$' || name[1] === '$' && !is_reserved_keyword(name)) {
26353 this.error(node, {
26354 code: 'illegal-global',
26355 message: `${name} is an illegal variable name`
26356 });
26357 }
26358 this.has_reactive_assignments = true; // TODO does this belong here?
26359 if (is_reserved_keyword(name))
26360 return;
26361 name = name.slice(1);
26362 }
26363 if (this.var_lookup.has(name) && !this.var_lookup.get(name).global)
26364 return;
26365 if (template_scope && template_scope.names.has(name))
26366 return;
26367 if (globals.has(name) && node.type !== 'InlineComponent')
26368 return;
26369 let message = `'${name}' is not defined`;
26370 if (!this.ast.instance)
26371 message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;
26372 this.warn(node, {
26373 code: 'missing-declaration',
26374 message,
26375 });
26376 }
26377 push_ignores(ignores) {
26378 this.ignores = new Set(this.ignores || []);
26379 add_to_set(this.ignores, ignores);
26380 this.ignore_stack.push(this.ignores);
26381 }
26382 pop_ignores() {
26383 this.ignore_stack.pop();
26384 this.ignores = this.ignore_stack[this.ignore_stack.length - 1];
26385 }
26386 }
26387 function process_component_options(component, nodes) {
26388 const component_options = {
26389 immutable: component.compile_options.immutable || false,
26390 accessors: 'accessors' in component.compile_options
26391 ? component.compile_options.accessors
26392 : !!component.compile_options.customElement,
26393 preserveWhitespace: !!component.compile_options.preserveWhitespace,
26394 };
26395 const node = nodes.find(node => node.name === 'svelte:options');
26396 function get_value(attribute, code, message) {
26397 const { value } = attribute;
26398 const chunk = value[0];
26399 if (!chunk)
26400 return true;
26401 if (value.length > 1) {
26402 component.error(attribute, { code, message });
26403 }
26404 if (chunk.type === 'Text')
26405 return chunk.data;
26406 if (chunk.expression.type !== 'Literal') {
26407 component.error(attribute, { code, message });
26408 }
26409 return chunk.expression.value;
26410 }
26411 if (node) {
26412 node.attributes.forEach(attribute => {
26413 if (attribute.type === 'Attribute') {
26414 const { name } = attribute;
26415 switch (name) {
26416 case 'tag': {
26417 const code = 'invalid-tag-attribute';
26418 const message = `'tag' must be a string literal`;
26419 const tag = get_value(attribute, code, message);
26420 if (typeof tag !== 'string' && tag !== null)
26421 component.error(attribute, { code, message });
26422 if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
26423 component.error(attribute, {
26424 code: `invalid-tag-property`,
26425 message: `tag name must be two or more words joined by the '-' character`,
26426 });
26427 }
26428 if (tag && !component.compile_options.customElement) {
26429 component.warn(attribute, {
26430 code: 'missing-custom-element-compile-options',
26431 message: `The 'tag' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?`
26432 });
26433 }
26434 component_options.tag = tag;
26435 break;
26436 }
26437 case 'namespace': {
26438 const code = 'invalid-namespace-attribute';
26439 const message = `The 'namespace' attribute must be a string literal representing a valid namespace`;
26440 const ns = get_value(attribute, code, message);
26441 if (typeof ns !== 'string')
26442 component.error(attribute, { code, message });
26443 if (valid_namespaces.indexOf(ns) === -1) {
26444 const match = fuzzymatch(ns, valid_namespaces);
26445 if (match) {
26446 component.error(attribute, {
26447 code: `invalid-namespace-property`,
26448 message: `Invalid namespace '${ns}' (did you mean '${match}'?)`,
26449 });
26450 }
26451 else {
26452 component.error(attribute, {
26453 code: `invalid-namespace-property`,
26454 message: `Invalid namespace '${ns}'`,
26455 });
26456 }
26457 }
26458 component_options.namespace = ns;
26459 break;
26460 }
26461 case 'accessors':
26462 case 'immutable':
26463 case 'preserveWhitespace': {
26464 const code = `invalid-${name}-value`;
26465 const message = `${name} attribute must be true or false`;
26466 const value = get_value(attribute, code, message);
26467 if (typeof value !== 'boolean')
26468 component.error(attribute, { code, message });
26469 component_options[name] = value;
26470 break;
26471 }
26472 default:
26473 component.error(attribute, {
26474 code: `invalid-options-attribute`,
26475 message: `<svelte:options> unknown attribute`,
26476 });
26477 }
26478 }
26479 else {
26480 component.error(attribute, {
26481 code: `invalid-options-attribute`,
26482 message: `<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes`,
26483 });
26484 }
26485 });
26486 }
26487 return component_options;
26488 }
26489 function get_relative_path(from, to) {
26490 const from_parts = from.split(/[/\\]/);
26491 const to_parts = to.split(/[/\\]/);
26492 from_parts.pop(); // get dirname
26493 while (from_parts[0] === to_parts[0]) {
26494 from_parts.shift();
26495 to_parts.shift();
26496 }
26497 if (from_parts.length) {
26498 let i = from_parts.length;
26499 while (i--)
26500 from_parts[i] = '..';
26501 }
26502 return from_parts.concat(to_parts).join('/');
26503 }
26504
26505 function get_name_from_filename(filename) {
26506 if (!filename)
26507 return null;
26508 const parts = filename.split(/[/\\]/).map(encodeURI);
26509 if (parts.length > 1) {
26510 const index_match = parts[parts.length - 1].match(/^index(\.\w+)/);
26511 if (index_match) {
26512 parts.pop();
26513 parts[parts.length - 1] += index_match[1];
26514 }
26515 }
26516 const base = parts.pop()
26517 .replace(/%/g, 'u')
26518 .replace(/\.[^.]+$/, "")
26519 .replace(/[^a-zA-Z_$0-9]+/g, '_')
26520 .replace(/^_/, '')
26521 .replace(/_$/, '')
26522 .replace(/^(\d)/, '_$1');
26523 if (!base) {
26524 throw new Error(`Could not derive component name from file ${filename}`);
26525 }
26526 return base[0].toUpperCase() + base.slice(1);
26527 }
26528
26529 const valid_options = [
26530 'format',
26531 'name',
26532 'filename',
26533 'generate',
26534 'outputFilename',
26535 'cssOutputFilename',
26536 'sveltePath',
26537 'dev',
26538 'accessors',
26539 'immutable',
26540 'hydratable',
26541 'legacy',
26542 'customElement',
26543 'tag',
26544 'css',
26545 'loopGuardTimeout',
26546 'preserveComments',
26547 'preserveWhitespace'
26548 ];
26549 function validate_options(options, warnings) {
26550 const { name, filename, loopGuardTimeout, dev } = options;
26551 Object.keys(options).forEach(key => {
26552 if (!valid_options.includes(key)) {
26553 const match = fuzzymatch(key, valid_options);
26554 let message = `Unrecognized option '${key}'`;
26555 if (match)
26556 message += ` (did you mean '${match}'?)`;
26557 throw new Error(message);
26558 }
26559 });
26560 if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) {
26561 throw new Error(`options.name must be a valid identifier (got '${name}')`);
26562 }
26563 if (name && /^[a-z]/.test(name)) {
26564 const message = `options.name should be capitalised`;
26565 warnings.push({
26566 code: `options-lowercase-name`,
26567 message,
26568 filename,
26569 toString: () => message,
26570 });
26571 }
26572 if (loopGuardTimeout && !dev) {
26573 const message = 'options.loopGuardTimeout is for options.dev = true only';
26574 warnings.push({
26575 code: `options-loop-guard-timeout`,
26576 message,
26577 filename,
26578 toString: () => message,
26579 });
26580 }
26581 }
26582 function compile(source, options = {}) {
26583 options = assign({ generate: 'dom', dev: false }, options);
26584 const stats = new Stats();
26585 const warnings = [];
26586 validate_options(options, warnings);
26587 stats.start('parse');
26588 const ast = parse$3(source, options);
26589 stats.stop('parse');
26590 stats.start('create component');
26591 const component = new Component(ast, source, options.name || get_name_from_filename(options.filename) || 'Component', options, stats, warnings);
26592 stats.stop('create component');
26593 const result = options.generate === false
26594 ? null
26595 : options.generate === 'ssr'
26596 ? ssr(component, options)
26597 : dom(component, options);
26598 return component.generate(result);
26599 }
26600
26601 function parse_attributes(str) {
26602 const attrs = {};
26603 str.split(/\s+/).filter(Boolean).forEach(attr => {
26604 const p = attr.indexOf('=');
26605 if (p === -1) {
26606 attrs[attr] = true;
26607 }
26608 else {
26609 attrs[attr.slice(0, p)] = `'"`.includes(attr[p + 1]) ?
26610 attr.slice(p + 2, -1) :
26611 attr.slice(p + 1);
26612 }
26613 });
26614 return attrs;
26615 }
26616 async function replace_async(str, re, func) {
26617 const replacements = [];
26618 str.replace(re, (...args) => {
26619 replacements.push(func(...args).then(res => ({
26620 offset: args[args.length - 2],
26621 length: args[0].length,
26622 replacement: res,
26623 })));
26624 return '';
26625 });
26626 let out = '';
26627 let last_end = 0;
26628 for (const { offset, length, replacement } of await Promise.all(replacements)) {
26629 out += str.slice(last_end, offset) + replacement;
26630 last_end = offset + length;
26631 }
26632 out += str.slice(last_end);
26633 return out;
26634 }
26635 async function preprocess(source, preprocessor, options) {
26636 // @ts-ignore todo: doublecheck
26637 const filename = (options && options.filename) || preprocessor.filename; // legacy
26638 const dependencies = [];
26639 const preprocessors = Array.isArray(preprocessor) ? preprocessor : [preprocessor];
26640 const markup = preprocessors.map(p => p.markup).filter(Boolean);
26641 const script = preprocessors.map(p => p.script).filter(Boolean);
26642 const style = preprocessors.map(p => p.style).filter(Boolean);
26643 for (const fn of markup) {
26644 const processed = await fn({
26645 content: source,
26646 filename
26647 });
26648 if (processed && processed.dependencies)
26649 dependencies.push(...processed.dependencies);
26650 source = processed ? processed.code : source;
26651 }
26652 for (const fn of script) {
26653 source = await replace_async(source, /<!--[^]*?-->|<script(\s[^]*?)?>([^]*?)<\/script>/gi, async (match, attributes = '', content) => {
26654 if (!attributes && !content) {
26655 return match;
26656 }
26657 attributes = attributes || '';
26658 const processed = await fn({
26659 content,
26660 attributes: parse_attributes(attributes),
26661 filename
26662 });
26663 if (processed && processed.dependencies)
26664 dependencies.push(...processed.dependencies);
26665 return processed ? `<script${attributes}>${processed.code}</script>` : match;
26666 });
26667 }
26668 for (const fn of style) {
26669 source = await replace_async(source, /<!--[^]*?-->|<style(\s[^]*?)?>([^]*?)<\/style>/gi, async (match, attributes = '', content) => {
26670 if (!attributes && !content) {
26671 return match;
26672 }
26673 const processed = await fn({
26674 content,
26675 attributes: parse_attributes(attributes),
26676 filename
26677 });
26678 if (processed && processed.dependencies)
26679 dependencies.push(...processed.dependencies);
26680 return processed ? `<style${attributes}>${processed.code}</style>` : match;
26681 });
26682 }
26683 return {
26684 // TODO return separated output, in future version where svelte.compile supports it:
26685 // style: { code: styleCode, map: styleMap },
26686 // script { code: scriptCode, map: scriptMap },
26687 // markup { code: markupCode, map: markupMap },
26688 code: source,
26689 dependencies: [...new Set(dependencies)],
26690 toString() {
26691 return source;
26692 }
26693 };
26694 }
26695
26696 const VERSION = '3.23.1';
26697
26698 exports.VERSION = VERSION;
26699 exports.compile = compile;
26700 exports.parse = parse$3;
26701 exports.preprocess = preprocess;
26702 exports.walk = walk;
26703
26704 Object.defineProperty(exports, '__esModule', { value: true });
26705
26706})));
26707//# sourceMappingURL=compiler.js.map