UNPKG

995 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 const now = (typeof process !== 'undefined' && process.hrtime)
8 ? () => {
9 const t = process.hrtime();
10 return t[0] * 1e3 + t[1] / 1e6;
11 }
12 : () => self.performance.now();
13 function collapse_timings(timings) {
14 const result = {};
15 timings.forEach(timing => {
16 result[timing.label] = Object.assign({
17 total: timing.end - timing.start
18 }, timing.children && collapse_timings(timing.children));
19 });
20 return result;
21 }
22 class Stats {
23 constructor() {
24 this.start_time = now();
25 this.stack = [];
26 this.current_children = this.timings = [];
27 }
28 start(label) {
29 const timing = {
30 label,
31 start: now(),
32 end: null,
33 children: []
34 };
35 this.current_children.push(timing);
36 this.stack.push(timing);
37 this.current_timing = timing;
38 this.current_children = timing.children;
39 }
40 stop(label) {
41 if (label !== this.current_timing.label) {
42 throw new Error(`Mismatched timing labels (expected ${this.current_timing.label}, got ${label})`);
43 }
44 this.current_timing.end = now();
45 this.stack.pop();
46 this.current_timing = this.stack[this.stack.length - 1];
47 this.current_children = this.current_timing ? this.current_timing.children : this.timings;
48 }
49 render() {
50 const timings = Object.assign({
51 total: now() - this.start_time
52 }, collapse_timings(this.timings));
53 return {
54 timings
55 };
56 }
57 }
58
59 // Reserved word lists for various dialects of the language
60
61 var reservedWords = {
62 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",
63 5: "class enum extends super const export import",
64 6: "enum",
65 strict: "implements interface let package private protected public static yield",
66 strictBind: "eval arguments"
67 };
68
69 // And the keywords
70
71 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";
72
73 var keywords = {
74 5: ecma5AndLessKeywords,
75 "5module": ecma5AndLessKeywords + " export import",
76 6: ecma5AndLessKeywords + " const class extends export import super"
77 };
78
79 var keywordRelationalOperator = /^in(stanceof)?$/;
80
81 // ## Character categories
82
83 // Big ugly regular expressions that match characters in the
84 // whitespace, identifier, and identifier-start categories. These
85 // are only applied when a character is found to actually have a
86 // code point above 128.
87 // Generated by `bin/generate-identifier-regex.js`.
88 var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
89 var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf\u1ac0\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
90
91 var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
92 var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
93
94 nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
95
96 // These are a run-length and offset encoded representation of the
97 // >0xffff code points that are a valid part of identifiers. The
98 // offset starts at 0x10000, and each pair of numbers represents an
99 // offset to the next range, and then a size of the range. They were
100 // generated by bin/generate-identifier-regex.js
101
102 // eslint-disable-next-line comma-spacing
103 var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,349,41,7,1,79,28,11,0,9,21,107,20,28,22,13,52,76,44,33,24,27,35,30,0,3,0,9,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,21,2,31,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,7,3,0,3,7,2,1,2,23,16,0,2,0,95,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,190,0,80,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,1237,43,8,8952,286,50,2,18,3,9,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,2357,44,11,6,17,0,370,43,1301,196,60,67,8,0,1205,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42717,35,4148,12,221,3,5761,15,7472,3104,541,1507,4938];
104
105 // eslint-disable-next-line comma-spacing
106 var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,370,1,154,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,2,11,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,71,5,2,1,3,3,2,0,2,1,13,9,120,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1014,0,2,54,8,3,82,0,12,1,19628,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,262,6,10,9,419,13,1495,6,110,6,6,9,4759,9,787719,239];
107
108 // This has a complexity linear to the value of the code. The
109 // assumption is that looking up astral identifier characters is
110 // rare.
111 function isInAstralSet(code, set) {
112 var pos = 0x10000;
113 for (var i = 0; i < set.length; i += 2) {
114 pos += set[i];
115 if (pos > code) { return false }
116 pos += set[i + 1];
117 if (pos >= code) { return true }
118 }
119 }
120
121 // Test whether a given character code starts an identifier.
122
123 function isIdentifierStart(code, astral) {
124 if (code < 65) { return code === 36 }
125 if (code < 91) { return true }
126 if (code < 97) { return code === 95 }
127 if (code < 123) { return true }
128 if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) }
129 if (astral === false) { return false }
130 return isInAstralSet(code, astralIdentifierStartCodes)
131 }
132
133 // Test whether a given character is part of an identifier.
134
135 function isIdentifierChar(code, astral) {
136 if (code < 48) { return code === 36 }
137 if (code < 58) { return true }
138 if (code < 65) { return false }
139 if (code < 91) { return true }
140 if (code < 97) { return code === 95 }
141 if (code < 123) { return true }
142 if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) }
143 if (astral === false) { return false }
144 return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
145 }
146
147 // ## Token types
148
149 // The assignment of fine-grained, information-carrying type objects
150 // allows the tokenizer to store the information it has about a
151 // token in a way that is very cheap for the parser to look up.
152
153 // All token type variables start with an underscore, to make them
154 // easy to recognize.
155
156 // The `beforeExpr` property is used to disambiguate between regular
157 // expressions and divisions. It is set on all token types that can
158 // be followed by an expression (thus, a slash after them would be a
159 // regular expression).
160 //
161 // The `startsExpr` property is used to check if the token ends a
162 // `yield` expression. It is set on all token types that either can
163 // directly start an expression (like a quotation mark) or can
164 // continue an expression (like the body of a string).
165 //
166 // `isLoop` marks a keyword as starting a loop, which is important
167 // to know when parsing a label, in order to allow or disallow
168 // continue jumps to that label.
169
170 var TokenType = function TokenType(label, conf) {
171 if ( conf === void 0 ) conf = {};
172
173 this.label = label;
174 this.keyword = conf.keyword;
175 this.beforeExpr = !!conf.beforeExpr;
176 this.startsExpr = !!conf.startsExpr;
177 this.isLoop = !!conf.isLoop;
178 this.isAssign = !!conf.isAssign;
179 this.prefix = !!conf.prefix;
180 this.postfix = !!conf.postfix;
181 this.binop = conf.binop || null;
182 this.updateContext = null;
183 };
184
185 function binop(name, prec) {
186 return new TokenType(name, {beforeExpr: true, binop: prec})
187 }
188 var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true};
189
190 // Map keyword names to token types.
191
192 var keywords$1 = {};
193
194 // Succinct definitions of keyword token types
195 function kw(name, options) {
196 if ( options === void 0 ) options = {};
197
198 options.keyword = name;
199 return keywords$1[name] = new TokenType(name, options)
200 }
201
202 var types = {
203 num: new TokenType("num", startsExpr),
204 regexp: new TokenType("regexp", startsExpr),
205 string: new TokenType("string", startsExpr),
206 name: new TokenType("name", startsExpr),
207 eof: new TokenType("eof"),
208
209 // Punctuation token types.
210 bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
211 bracketR: new TokenType("]"),
212 braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
213 braceR: new TokenType("}"),
214 parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
215 parenR: new TokenType(")"),
216 comma: new TokenType(",", beforeExpr),
217 semi: new TokenType(";", beforeExpr),
218 colon: new TokenType(":", beforeExpr),
219 dot: new TokenType("."),
220 question: new TokenType("?", beforeExpr),
221 questionDot: new TokenType("?."),
222 arrow: new TokenType("=>", beforeExpr),
223 template: new TokenType("template"),
224 invalidTemplate: new TokenType("invalidTemplate"),
225 ellipsis: new TokenType("...", beforeExpr),
226 backQuote: new TokenType("`", startsExpr),
227 dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
228
229 // Operators. These carry several kinds of properties to help the
230 // parser use them properly (the presence of these properties is
231 // what categorizes them as operators).
232 //
233 // `binop`, when present, specifies that this operator is a binary
234 // operator, and will refer to its precedence.
235 //
236 // `prefix` and `postfix` mark the operator as a prefix or postfix
237 // unary operator.
238 //
239 // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
240 // binary operators with a very low precedence, that should result
241 // in AssignmentExpression nodes.
242
243 eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
244 assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
245 incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
246 prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
247 logicalOR: binop("||", 1),
248 logicalAND: binop("&&", 2),
249 bitwiseOR: binop("|", 3),
250 bitwiseXOR: binop("^", 4),
251 bitwiseAND: binop("&", 5),
252 equality: binop("==/!=/===/!==", 6),
253 relational: binop("</>/<=/>=", 7),
254 bitShift: binop("<</>>/>>>", 8),
255 plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
256 modulo: binop("%", 10),
257 star: binop("*", 10),
258 slash: binop("/", 10),
259 starstar: new TokenType("**", {beforeExpr: true}),
260 coalesce: binop("??", 1),
261
262 // Keyword token types.
263 _break: kw("break"),
264 _case: kw("case", beforeExpr),
265 _catch: kw("catch"),
266 _continue: kw("continue"),
267 _debugger: kw("debugger"),
268 _default: kw("default", beforeExpr),
269 _do: kw("do", {isLoop: true, beforeExpr: true}),
270 _else: kw("else", beforeExpr),
271 _finally: kw("finally"),
272 _for: kw("for", {isLoop: true}),
273 _function: kw("function", startsExpr),
274 _if: kw("if"),
275 _return: kw("return", beforeExpr),
276 _switch: kw("switch"),
277 _throw: kw("throw", beforeExpr),
278 _try: kw("try"),
279 _var: kw("var"),
280 _const: kw("const"),
281 _while: kw("while", {isLoop: true}),
282 _with: kw("with"),
283 _new: kw("new", {beforeExpr: true, startsExpr: true}),
284 _this: kw("this", startsExpr),
285 _super: kw("super", startsExpr),
286 _class: kw("class", startsExpr),
287 _extends: kw("extends", beforeExpr),
288 _export: kw("export"),
289 _import: kw("import", startsExpr),
290 _null: kw("null", startsExpr),
291 _true: kw("true", startsExpr),
292 _false: kw("false", startsExpr),
293 _in: kw("in", {beforeExpr: true, binop: 7}),
294 _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
295 _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
296 _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
297 _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
298 };
299
300 // Matches a whole line break (where CRLF is considered a single
301 // line break). Used to count lines.
302
303 var lineBreak = /\r\n?|\n|\u2028|\u2029/;
304 var lineBreakG = new RegExp(lineBreak.source, "g");
305
306 function isNewLine(code, ecma2019String) {
307 return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029))
308 }
309
310 var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
311
312 var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
313
314 var ref = Object.prototype;
315 var hasOwnProperty = ref.hasOwnProperty;
316 var toString = ref.toString;
317
318 // Checks if an object has a property.
319
320 function has(obj, propName) {
321 return hasOwnProperty.call(obj, propName)
322 }
323
324 var isArray = Array.isArray || (function (obj) { return (
325 toString.call(obj) === "[object Array]"
326 ); });
327
328 function wordsRegexp(words) {
329 return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
330 }
331
332 // These are used when `options.locations` is on, for the
333 // `startLoc` and `endLoc` properties.
334
335 var Position = function Position(line, col) {
336 this.line = line;
337 this.column = col;
338 };
339
340 Position.prototype.offset = function offset (n) {
341 return new Position(this.line, this.column + n)
342 };
343
344 var SourceLocation = function SourceLocation(p, start, end) {
345 this.start = start;
346 this.end = end;
347 if (p.sourceFile !== null) { this.source = p.sourceFile; }
348 };
349
350 // The `getLineInfo` function is mostly useful when the
351 // `locations` option is off (for performance reasons) and you
352 // want to find the line/column position for a given character
353 // offset. `input` should be the code string that the offset refers
354 // into.
355
356 function getLineInfo(input, offset) {
357 for (var line = 1, cur = 0;;) {
358 lineBreakG.lastIndex = cur;
359 var match = lineBreakG.exec(input);
360 if (match && match.index < offset) {
361 ++line;
362 cur = match.index + match[0].length;
363 } else {
364 return new Position(line, offset - cur)
365 }
366 }
367 }
368
369 // A second optional argument can be given to further configure
370 // the parser process. These options are recognized:
371
372 var defaultOptions = {
373 // `ecmaVersion` indicates the ECMAScript version to parse. Must be
374 // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10
375 // (2019). This influences support for strict mode, the set of
376 // reserved words, and support for new syntax features. The default
377 // is 10.
378 ecmaVersion: 10,
379 // `sourceType` indicates the mode the code should be parsed in.
380 // Can be either `"script"` or `"module"`. This influences global
381 // strict mode and parsing of `import` and `export` declarations.
382 sourceType: "script",
383 // `onInsertedSemicolon` can be a callback that will be called
384 // when a semicolon is automatically inserted. It will be passed
385 // the position of the comma as an offset, and if `locations` is
386 // enabled, it is given the location as a `{line, column}` object
387 // as second argument.
388 onInsertedSemicolon: null,
389 // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
390 // trailing commas.
391 onTrailingComma: null,
392 // By default, reserved words are only enforced if ecmaVersion >= 5.
393 // Set `allowReserved` to a boolean value to explicitly turn this on
394 // an off. When this option has the value "never", reserved words
395 // and keywords can also not be used as property names.
396 allowReserved: null,
397 // When enabled, a return at the top level is not considered an
398 // error.
399 allowReturnOutsideFunction: false,
400 // When enabled, import/export statements are not constrained to
401 // appearing at the top of the program.
402 allowImportExportEverywhere: false,
403 // When enabled, await identifiers are allowed to appear at the top-level scope,
404 // but they are still not allowed in non-async functions.
405 allowAwaitOutsideFunction: false,
406 // When enabled, hashbang directive in the beginning of file
407 // is allowed and treated as a line comment.
408 allowHashBang: false,
409 // When `locations` is on, `loc` properties holding objects with
410 // `start` and `end` properties in `{line, column}` form (with
411 // line being 1-based and column 0-based) will be attached to the
412 // nodes.
413 locations: false,
414 // A function can be passed as `onToken` option, which will
415 // cause Acorn to call that function with object in the same
416 // format as tokens returned from `tokenizer().getToken()`. Note
417 // that you are not allowed to call the parser from the
418 // callback—that will corrupt its internal state.
419 onToken: null,
420 // A function can be passed as `onComment` option, which will
421 // cause Acorn to call that function with `(block, text, start,
422 // end)` parameters whenever a comment is skipped. `block` is a
423 // boolean indicating whether this is a block (`/* */`) comment,
424 // `text` is the content of the comment, and `start` and `end` are
425 // character offsets that denote the start and end of the comment.
426 // When the `locations` option is on, two more parameters are
427 // passed, the full `{line, column}` locations of the start and
428 // end of the comments. Note that you are not allowed to call the
429 // parser from the callback—that will corrupt its internal state.
430 onComment: null,
431 // Nodes have their start and end characters offsets recorded in
432 // `start` and `end` properties (directly on the node, rather than
433 // the `loc` object, which holds line/column data. To also add a
434 // [semi-standardized][range] `range` property holding a `[start,
435 // end]` array with the same numbers, set the `ranges` option to
436 // `true`.
437 //
438 // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
439 ranges: false,
440 // It is possible to parse multiple files into a single AST by
441 // passing the tree produced by parsing the first file as
442 // `program` option in subsequent parses. This will add the
443 // toplevel forms of the parsed file to the `Program` (top) node
444 // of an existing parse tree.
445 program: null,
446 // When `locations` is on, you can pass this to record the source
447 // file in every node's `loc` object.
448 sourceFile: null,
449 // This value, if given, is stored in every node, whether
450 // `locations` is on or off.
451 directSourceFile: null,
452 // When enabled, parenthesized expressions are represented by
453 // (non-standard) ParenthesizedExpression nodes
454 preserveParens: false
455 };
456
457 // Interpret and default an options object
458
459 function getOptions(opts) {
460 var options = {};
461
462 for (var opt in defaultOptions)
463 { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; }
464
465 if (options.ecmaVersion >= 2015)
466 { options.ecmaVersion -= 2009; }
467
468 if (options.allowReserved == null)
469 { options.allowReserved = options.ecmaVersion < 5; }
470
471 if (isArray(options.onToken)) {
472 var tokens = options.onToken;
473 options.onToken = function (token) { return tokens.push(token); };
474 }
475 if (isArray(options.onComment))
476 { options.onComment = pushComment(options, options.onComment); }
477
478 return options
479 }
480
481 function pushComment(options, array) {
482 return function(block, text, start, end, startLoc, endLoc) {
483 var comment = {
484 type: block ? "Block" : "Line",
485 value: text,
486 start: start,
487 end: end
488 };
489 if (options.locations)
490 { comment.loc = new SourceLocation(this, startLoc, endLoc); }
491 if (options.ranges)
492 { comment.range = [start, end]; }
493 array.push(comment);
494 }
495 }
496
497 // Each scope gets a bitset that may contain these flags
498 var
499 SCOPE_TOP = 1,
500 SCOPE_FUNCTION = 2,
501 SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION,
502 SCOPE_ASYNC = 4,
503 SCOPE_GENERATOR = 8,
504 SCOPE_ARROW = 16,
505 SCOPE_SIMPLE_CATCH = 32,
506 SCOPE_SUPER = 64,
507 SCOPE_DIRECT_SUPER = 128;
508
509 function functionFlags(async, generator) {
510 return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0)
511 }
512
513 // Used in checkLVal and declareName to determine the type of a binding
514 var
515 BIND_NONE = 0, // Not a binding
516 BIND_VAR = 1, // Var-style binding
517 BIND_LEXICAL = 2, // Let- or const-style binding
518 BIND_FUNCTION = 3, // Function declaration
519 BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding
520 BIND_OUTSIDE = 5; // Special case for function names as bound inside the function
521
522 var Parser = function Parser(options, input, startPos) {
523 this.options = options = getOptions(options);
524 this.sourceFile = options.sourceFile;
525 this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]);
526 var reserved = "";
527 if (options.allowReserved !== true) {
528 for (var v = options.ecmaVersion;; v--)
529 { if (reserved = reservedWords[v]) { break } }
530 if (options.sourceType === "module") { reserved += " await"; }
531 }
532 this.reservedWords = wordsRegexp(reserved);
533 var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
534 this.reservedWordsStrict = wordsRegexp(reservedStrict);
535 this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind);
536 this.input = String(input);
537
538 // Used to signal to callers of `readWord1` whether the word
539 // contained any escape sequences. This is needed because words with
540 // escape sequences must not be interpreted as keywords.
541 this.containsEsc = false;
542
543 // Set up token state
544
545 // The current position of the tokenizer in the input.
546 if (startPos) {
547 this.pos = startPos;
548 this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
549 this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
550 } else {
551 this.pos = this.lineStart = 0;
552 this.curLine = 1;
553 }
554
555 // Properties of the current token:
556 // Its type
557 this.type = types.eof;
558 // For tokens that include more information than their type, the value
559 this.value = null;
560 // Its start and end offset
561 this.start = this.end = this.pos;
562 // And, if locations are used, the {line, column} object
563 // corresponding to those offsets
564 this.startLoc = this.endLoc = this.curPosition();
565
566 // Position information for the previous token
567 this.lastTokEndLoc = this.lastTokStartLoc = null;
568 this.lastTokStart = this.lastTokEnd = this.pos;
569
570 // The context stack is used to superficially track syntactic
571 // context to predict whether a regular expression is allowed in a
572 // given position.
573 this.context = this.initialContext();
574 this.exprAllowed = true;
575
576 // Figure out if it's a module code.
577 this.inModule = options.sourceType === "module";
578 this.strict = this.inModule || this.strictDirective(this.pos);
579
580 // Used to signify the start of a potential arrow function
581 this.potentialArrowAt = -1;
582
583 // Positions to delayed-check that yield/await does not exist in default parameters.
584 this.yieldPos = this.awaitPos = this.awaitIdentPos = 0;
585 // Labels in scope.
586 this.labels = [];
587 // Thus-far undefined exports.
588 this.undefinedExports = {};
589
590 // If enabled, skip leading hashbang line.
591 if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
592 { this.skipLineComment(2); }
593
594 // Scope tracking for duplicate variable names (see scope.js)
595 this.scopeStack = [];
596 this.enterScope(SCOPE_TOP);
597
598 // For RegExp validation
599 this.regexpState = null;
600 };
601
602 var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true } };
603
604 Parser.prototype.parse = function parse () {
605 var node = this.options.program || this.startNode();
606 this.nextToken();
607 return this.parseTopLevel(node)
608 };
609
610 prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 };
611 prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 };
612 prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 };
613 prototypeAccessors.allowSuper.get = function () { return (this.currentThisScope().flags & SCOPE_SUPER) > 0 };
614 prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 };
615 prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) };
616
617 // Switch to a getter for 7.0.0.
618 Parser.prototype.inNonArrowFunction = function inNonArrowFunction () { return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0 };
619
620 Parser.extend = function extend () {
621 var plugins = [], len = arguments.length;
622 while ( len-- ) plugins[ len ] = arguments[ len ];
623
624 var cls = this;
625 for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
626 return cls
627 };
628
629 Parser.parse = function parse (input, options) {
630 return new this(options, input).parse()
631 };
632
633 Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) {
634 var parser = new this(options, input, pos);
635 parser.nextToken();
636 return parser.parseExpression()
637 };
638
639 Parser.tokenizer = function tokenizer (input, options) {
640 return new this(options, input)
641 };
642
643 Object.defineProperties( Parser.prototype, prototypeAccessors );
644
645 var pp = Parser.prototype;
646
647 // ## Parser utilities
648
649 var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)")/;
650 pp.strictDirective = function(start) {
651 for (;;) {
652 // Try to find string literal.
653 skipWhiteSpace.lastIndex = start;
654 start += skipWhiteSpace.exec(this.input)[0].length;
655 var match = literal.exec(this.input.slice(start));
656 if (!match) { return false }
657 if ((match[1] || match[2]) === "use strict") {
658 skipWhiteSpace.lastIndex = start + match[0].length;
659 var spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length;
660 var next = this.input.charAt(end);
661 return next === ";" || next === "}" ||
662 (lineBreak.test(spaceAfter[0]) &&
663 !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "="))
664 }
665 start += match[0].length;
666
667 // Skip semicolon, if any.
668 skipWhiteSpace.lastIndex = start;
669 start += skipWhiteSpace.exec(this.input)[0].length;
670 if (this.input[start] === ";")
671 { start++; }
672 }
673 };
674
675 // Predicate that tests whether the next token is of the given
676 // type, and if yes, consumes it as a side effect.
677
678 pp.eat = function(type) {
679 if (this.type === type) {
680 this.next();
681 return true
682 } else {
683 return false
684 }
685 };
686
687 // Tests whether parsed token is a contextual keyword.
688
689 pp.isContextual = function(name) {
690 return this.type === types.name && this.value === name && !this.containsEsc
691 };
692
693 // Consumes contextual keyword if possible.
694
695 pp.eatContextual = function(name) {
696 if (!this.isContextual(name)) { return false }
697 this.next();
698 return true
699 };
700
701 // Asserts that following token is given contextual keyword.
702
703 pp.expectContextual = function(name) {
704 if (!this.eatContextual(name)) { this.unexpected(); }
705 };
706
707 // Test whether a semicolon can be inserted at the current position.
708
709 pp.canInsertSemicolon = function() {
710 return this.type === types.eof ||
711 this.type === types.braceR ||
712 lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
713 };
714
715 pp.insertSemicolon = function() {
716 if (this.canInsertSemicolon()) {
717 if (this.options.onInsertedSemicolon)
718 { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
719 return true
720 }
721 };
722
723 // Consume a semicolon, or, failing that, see if we are allowed to
724 // pretend that there is a semicolon at this position.
725
726 pp.semicolon = function() {
727 if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); }
728 };
729
730 pp.afterTrailingComma = function(tokType, notNext) {
731 if (this.type === tokType) {
732 if (this.options.onTrailingComma)
733 { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
734 if (!notNext)
735 { this.next(); }
736 return true
737 }
738 };
739
740 // Expect a token of a given type. If found, consume it, otherwise,
741 // raise an unexpected token error.
742
743 pp.expect = function(type) {
744 this.eat(type) || this.unexpected();
745 };
746
747 // Raise an unexpected token error.
748
749 pp.unexpected = function(pos) {
750 this.raise(pos != null ? pos : this.start, "Unexpected token");
751 };
752
753 function DestructuringErrors() {
754 this.shorthandAssign =
755 this.trailingComma =
756 this.parenthesizedAssign =
757 this.parenthesizedBind =
758 this.doubleProto =
759 -1;
760 }
761
762 pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {
763 if (!refDestructuringErrors) { return }
764 if (refDestructuringErrors.trailingComma > -1)
765 { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
766 var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
767 if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); }
768 };
769
770 pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
771 if (!refDestructuringErrors) { return false }
772 var shorthandAssign = refDestructuringErrors.shorthandAssign;
773 var doubleProto = refDestructuringErrors.doubleProto;
774 if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 }
775 if (shorthandAssign >= 0)
776 { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); }
777 if (doubleProto >= 0)
778 { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); }
779 };
780
781 pp.checkYieldAwaitInDefaultParams = function() {
782 if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
783 { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
784 if (this.awaitPos)
785 { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
786 };
787
788 pp.isSimpleAssignTarget = function(expr) {
789 if (expr.type === "ParenthesizedExpression")
790 { return this.isSimpleAssignTarget(expr.expression) }
791 return expr.type === "Identifier" || expr.type === "MemberExpression"
792 };
793
794 var pp$1 = Parser.prototype;
795
796 // ### Statement parsing
797
798 // Parse a program. Initializes the parser, reads any number of
799 // statements, and wraps them in a Program node. Optionally takes a
800 // `program` argument. If present, the statements will be appended
801 // to its body instead of creating a new node.
802
803 pp$1.parseTopLevel = function(node) {
804 var exports = {};
805 if (!node.body) { node.body = []; }
806 while (this.type !== types.eof) {
807 var stmt = this.parseStatement(null, true, exports);
808 node.body.push(stmt);
809 }
810 if (this.inModule)
811 { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1)
812 {
813 var name = list[i];
814
815 this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined"));
816 } }
817 this.adaptDirectivePrologue(node.body);
818 this.next();
819 node.sourceType = this.options.sourceType;
820 return this.finishNode(node, "Program")
821 };
822
823 var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};
824
825 pp$1.isLet = function(context) {
826 if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false }
827 skipWhiteSpace.lastIndex = this.pos;
828 var skip = skipWhiteSpace.exec(this.input);
829 var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
830 // For ambiguous cases, determine if a LexicalDeclaration (or only a
831 // Statement) is allowed here. If context is not empty then only a Statement
832 // is allowed. However, `let [` is an explicit negative lookahead for
833 // ExpressionStatement, so special-case it first.
834 if (nextCh === 91) { return true } // '['
835 if (context) { return false }
836
837 if (nextCh === 123) { return true } // '{'
838 if (isIdentifierStart(nextCh, true)) {
839 var pos = next + 1;
840 while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; }
841 var ident = this.input.slice(next, pos);
842 if (!keywordRelationalOperator.test(ident)) { return true }
843 }
844 return false
845 };
846
847 // check 'async [no LineTerminator here] function'
848 // - 'async /*foo*/ function' is OK.
849 // - 'async /*\n*/ function' is invalid.
850 pp$1.isAsyncFunction = function() {
851 if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
852 { return false }
853
854 skipWhiteSpace.lastIndex = this.pos;
855 var skip = skipWhiteSpace.exec(this.input);
856 var next = this.pos + skip[0].length;
857 return !lineBreak.test(this.input.slice(this.pos, next)) &&
858 this.input.slice(next, next + 8) === "function" &&
859 (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))
860 };
861
862 // Parse a single statement.
863 //
864 // If expecting a statement and finding a slash operator, parse a
865 // regular expression literal. This is to handle cases like
866 // `if (foo) /blah/.exec(foo)`, where looking at the previous token
867 // does not help.
868
869 pp$1.parseStatement = function(context, topLevel, exports) {
870 var starttype = this.type, node = this.startNode(), kind;
871
872 if (this.isLet(context)) {
873 starttype = types._var;
874 kind = "let";
875 }
876
877 // Most types of statements are recognized by the keyword they
878 // start with. Many are trivial to parse, some require a bit of
879 // complexity.
880
881 switch (starttype) {
882 case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
883 case types._debugger: return this.parseDebuggerStatement(node)
884 case types._do: return this.parseDoStatement(node)
885 case types._for: return this.parseForStatement(node)
886 case types._function:
887 // Function as sole body of either an if statement or a labeled statement
888 // works, but not when it is part of a labeled statement that is the sole
889 // body of an if statement.
890 if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); }
891 return this.parseFunctionStatement(node, false, !context)
892 case types._class:
893 if (context) { this.unexpected(); }
894 return this.parseClass(node, true)
895 case types._if: return this.parseIfStatement(node)
896 case types._return: return this.parseReturnStatement(node)
897 case types._switch: return this.parseSwitchStatement(node)
898 case types._throw: return this.parseThrowStatement(node)
899 case types._try: return this.parseTryStatement(node)
900 case types._const: case types._var:
901 kind = kind || this.value;
902 if (context && kind !== "var") { this.unexpected(); }
903 return this.parseVarStatement(node, kind)
904 case types._while: return this.parseWhileStatement(node)
905 case types._with: return this.parseWithStatement(node)
906 case types.braceL: return this.parseBlock(true, node)
907 case types.semi: return this.parseEmptyStatement(node)
908 case types._export:
909 case types._import:
910 if (this.options.ecmaVersion > 10 && starttype === types._import) {
911 skipWhiteSpace.lastIndex = this.pos;
912 var skip = skipWhiteSpace.exec(this.input);
913 var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
914 if (nextCh === 40 || nextCh === 46) // '(' or '.'
915 { return this.parseExpressionStatement(node, this.parseExpression()) }
916 }
917
918 if (!this.options.allowImportExportEverywhere) {
919 if (!topLevel)
920 { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
921 if (!this.inModule)
922 { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
923 }
924 return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports)
925
926 // If the statement does not start with a statement keyword or a
927 // brace, it's an ExpressionStatement or LabeledStatement. We
928 // simply start parsing an expression, and afterwards, if the
929 // next token is a colon and the expression was a simple
930 // Identifier node, we switch to interpreting it as a label.
931 default:
932 if (this.isAsyncFunction()) {
933 if (context) { this.unexpected(); }
934 this.next();
935 return this.parseFunctionStatement(node, true, !context)
936 }
937
938 var maybeName = this.value, expr = this.parseExpression();
939 if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon))
940 { return this.parseLabeledStatement(node, maybeName, expr, context) }
941 else { return this.parseExpressionStatement(node, expr) }
942 }
943 };
944
945 pp$1.parseBreakContinueStatement = function(node, keyword) {
946 var isBreak = keyword === "break";
947 this.next();
948 if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; }
949 else if (this.type !== types.name) { this.unexpected(); }
950 else {
951 node.label = this.parseIdent();
952 this.semicolon();
953 }
954
955 // Verify that there is an actual destination to break or
956 // continue to.
957 var i = 0;
958 for (; i < this.labels.length; ++i) {
959 var lab = this.labels[i];
960 if (node.label == null || lab.name === node.label.name) {
961 if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
962 if (node.label && isBreak) { break }
963 }
964 }
965 if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
966 return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
967 };
968
969 pp$1.parseDebuggerStatement = function(node) {
970 this.next();
971 this.semicolon();
972 return this.finishNode(node, "DebuggerStatement")
973 };
974
975 pp$1.parseDoStatement = function(node) {
976 this.next();
977 this.labels.push(loopLabel);
978 node.body = this.parseStatement("do");
979 this.labels.pop();
980 this.expect(types._while);
981 node.test = this.parseParenExpression();
982 if (this.options.ecmaVersion >= 6)
983 { this.eat(types.semi); }
984 else
985 { this.semicolon(); }
986 return this.finishNode(node, "DoWhileStatement")
987 };
988
989 // Disambiguating between a `for` and a `for`/`in` or `for`/`of`
990 // loop is non-trivial. Basically, we have to parse the init `var`
991 // statement or expression, disallowing the `in` operator (see
992 // the second parameter to `parseExpression`), and then check
993 // whether the next token is `in` or `of`. When there is no init
994 // part (semicolon immediately after the opening parenthesis), it
995 // is a regular `for` loop.
996
997 pp$1.parseForStatement = function(node) {
998 this.next();
999 var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1;
1000 this.labels.push(loopLabel);
1001 this.enterScope(0);
1002 this.expect(types.parenL);
1003 if (this.type === types.semi) {
1004 if (awaitAt > -1) { this.unexpected(awaitAt); }
1005 return this.parseFor(node, null)
1006 }
1007 var isLet = this.isLet();
1008 if (this.type === types._var || this.type === types._const || isLet) {
1009 var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
1010 this.next();
1011 this.parseVar(init$1, true, kind);
1012 this.finishNode(init$1, "VariableDeclaration");
1013 if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1) {
1014 if (this.options.ecmaVersion >= 9) {
1015 if (this.type === types._in) {
1016 if (awaitAt > -1) { this.unexpected(awaitAt); }
1017 } else { node.await = awaitAt > -1; }
1018 }
1019 return this.parseForIn(node, init$1)
1020 }
1021 if (awaitAt > -1) { this.unexpected(awaitAt); }
1022 return this.parseFor(node, init$1)
1023 }
1024 var refDestructuringErrors = new DestructuringErrors;
1025 var init = this.parseExpression(true, refDestructuringErrors);
1026 if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
1027 if (this.options.ecmaVersion >= 9) {
1028 if (this.type === types._in) {
1029 if (awaitAt > -1) { this.unexpected(awaitAt); }
1030 } else { node.await = awaitAt > -1; }
1031 }
1032 this.toAssignable(init, false, refDestructuringErrors);
1033 this.checkLVal(init);
1034 return this.parseForIn(node, init)
1035 } else {
1036 this.checkExpressionErrors(refDestructuringErrors, true);
1037 }
1038 if (awaitAt > -1) { this.unexpected(awaitAt); }
1039 return this.parseFor(node, init)
1040 };
1041
1042 pp$1.parseFunctionStatement = function(node, isAsync, declarationPosition) {
1043 this.next();
1044 return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync)
1045 };
1046
1047 pp$1.parseIfStatement = function(node) {
1048 this.next();
1049 node.test = this.parseParenExpression();
1050 // allow function declarations in branches, but only in non-strict mode
1051 node.consequent = this.parseStatement("if");
1052 node.alternate = this.eat(types._else) ? this.parseStatement("if") : null;
1053 return this.finishNode(node, "IfStatement")
1054 };
1055
1056 pp$1.parseReturnStatement = function(node) {
1057 if (!this.inFunction && !this.options.allowReturnOutsideFunction)
1058 { this.raise(this.start, "'return' outside of function"); }
1059 this.next();
1060
1061 // In `return` (and `break`/`continue`), the keywords with
1062 // optional arguments, we eagerly look for a semicolon or the
1063 // possibility to insert one.
1064
1065 if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; }
1066 else { node.argument = this.parseExpression(); this.semicolon(); }
1067 return this.finishNode(node, "ReturnStatement")
1068 };
1069
1070 pp$1.parseSwitchStatement = function(node) {
1071 this.next();
1072 node.discriminant = this.parseParenExpression();
1073 node.cases = [];
1074 this.expect(types.braceL);
1075 this.labels.push(switchLabel);
1076 this.enterScope(0);
1077
1078 // Statements under must be grouped (by label) in SwitchCase
1079 // nodes. `cur` is used to keep the node that we are currently
1080 // adding statements to.
1081
1082 var cur;
1083 for (var sawDefault = false; this.type !== types.braceR;) {
1084 if (this.type === types._case || this.type === types._default) {
1085 var isCase = this.type === types._case;
1086 if (cur) { this.finishNode(cur, "SwitchCase"); }
1087 node.cases.push(cur = this.startNode());
1088 cur.consequent = [];
1089 this.next();
1090 if (isCase) {
1091 cur.test = this.parseExpression();
1092 } else {
1093 if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); }
1094 sawDefault = true;
1095 cur.test = null;
1096 }
1097 this.expect(types.colon);
1098 } else {
1099 if (!cur) { this.unexpected(); }
1100 cur.consequent.push(this.parseStatement(null));
1101 }
1102 }
1103 this.exitScope();
1104 if (cur) { this.finishNode(cur, "SwitchCase"); }
1105 this.next(); // Closing brace
1106 this.labels.pop();
1107 return this.finishNode(node, "SwitchStatement")
1108 };
1109
1110 pp$1.parseThrowStatement = function(node) {
1111 this.next();
1112 if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
1113 { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
1114 node.argument = this.parseExpression();
1115 this.semicolon();
1116 return this.finishNode(node, "ThrowStatement")
1117 };
1118
1119 // Reused empty array added for node fields that are always empty.
1120
1121 var empty = [];
1122
1123 pp$1.parseTryStatement = function(node) {
1124 this.next();
1125 node.block = this.parseBlock();
1126 node.handler = null;
1127 if (this.type === types._catch) {
1128 var clause = this.startNode();
1129 this.next();
1130 if (this.eat(types.parenL)) {
1131 clause.param = this.parseBindingAtom();
1132 var simple = clause.param.type === "Identifier";
1133 this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0);
1134 this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL);
1135 this.expect(types.parenR);
1136 } else {
1137 if (this.options.ecmaVersion < 10) { this.unexpected(); }
1138 clause.param = null;
1139 this.enterScope(0);
1140 }
1141 clause.body = this.parseBlock(false);
1142 this.exitScope();
1143 node.handler = this.finishNode(clause, "CatchClause");
1144 }
1145 node.finalizer = this.eat(types._finally) ? this.parseBlock() : null;
1146 if (!node.handler && !node.finalizer)
1147 { this.raise(node.start, "Missing catch or finally clause"); }
1148 return this.finishNode(node, "TryStatement")
1149 };
1150
1151 pp$1.parseVarStatement = function(node, kind) {
1152 this.next();
1153 this.parseVar(node, false, kind);
1154 this.semicolon();
1155 return this.finishNode(node, "VariableDeclaration")
1156 };
1157
1158 pp$1.parseWhileStatement = function(node) {
1159 this.next();
1160 node.test = this.parseParenExpression();
1161 this.labels.push(loopLabel);
1162 node.body = this.parseStatement("while");
1163 this.labels.pop();
1164 return this.finishNode(node, "WhileStatement")
1165 };
1166
1167 pp$1.parseWithStatement = function(node) {
1168 if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
1169 this.next();
1170 node.object = this.parseParenExpression();
1171 node.body = this.parseStatement("with");
1172 return this.finishNode(node, "WithStatement")
1173 };
1174
1175 pp$1.parseEmptyStatement = function(node) {
1176 this.next();
1177 return this.finishNode(node, "EmptyStatement")
1178 };
1179
1180 pp$1.parseLabeledStatement = function(node, maybeName, expr, context) {
1181 for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1)
1182 {
1183 var label = list[i$1];
1184
1185 if (label.name === maybeName)
1186 { this.raise(expr.start, "Label '" + maybeName + "' is already declared");
1187 } }
1188 var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null;
1189 for (var i = this.labels.length - 1; i >= 0; i--) {
1190 var label$1 = this.labels[i];
1191 if (label$1.statementStart === node.start) {
1192 // Update information about previous labels on this node
1193 label$1.statementStart = this.start;
1194 label$1.kind = kind;
1195 } else { break }
1196 }
1197 this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
1198 node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label");
1199 this.labels.pop();
1200 node.label = expr;
1201 return this.finishNode(node, "LabeledStatement")
1202 };
1203
1204 pp$1.parseExpressionStatement = function(node, expr) {
1205 node.expression = expr;
1206 this.semicolon();
1207 return this.finishNode(node, "ExpressionStatement")
1208 };
1209
1210 // Parse a semicolon-enclosed block of statements, handling `"use
1211 // strict"` declarations when `allowStrict` is true (used for
1212 // function bodies).
1213
1214 pp$1.parseBlock = function(createNewLexicalScope, node, exitStrict) {
1215 if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;
1216 if ( node === void 0 ) node = this.startNode();
1217
1218 node.body = [];
1219 this.expect(types.braceL);
1220 if (createNewLexicalScope) { this.enterScope(0); }
1221 while (this.type !== types.braceR) {
1222 var stmt = this.parseStatement(null);
1223 node.body.push(stmt);
1224 }
1225 if (exitStrict) { this.strict = false; }
1226 this.next();
1227 if (createNewLexicalScope) { this.exitScope(); }
1228 return this.finishNode(node, "BlockStatement")
1229 };
1230
1231 // Parse a regular `for` loop. The disambiguation code in
1232 // `parseStatement` will already have parsed the init statement or
1233 // expression.
1234
1235 pp$1.parseFor = function(node, init) {
1236 node.init = init;
1237 this.expect(types.semi);
1238 node.test = this.type === types.semi ? null : this.parseExpression();
1239 this.expect(types.semi);
1240 node.update = this.type === types.parenR ? null : this.parseExpression();
1241 this.expect(types.parenR);
1242 node.body = this.parseStatement("for");
1243 this.exitScope();
1244 this.labels.pop();
1245 return this.finishNode(node, "ForStatement")
1246 };
1247
1248 // Parse a `for`/`in` and `for`/`of` loop, which are almost
1249 // same from parser's perspective.
1250
1251 pp$1.parseForIn = function(node, init) {
1252 var isForIn = this.type === types._in;
1253 this.next();
1254
1255 if (
1256 init.type === "VariableDeclaration" &&
1257 init.declarations[0].init != null &&
1258 (
1259 !isForIn ||
1260 this.options.ecmaVersion < 8 ||
1261 this.strict ||
1262 init.kind !== "var" ||
1263 init.declarations[0].id.type !== "Identifier"
1264 )
1265 ) {
1266 this.raise(
1267 init.start,
1268 ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer")
1269 );
1270 } else if (init.type === "AssignmentPattern") {
1271 this.raise(init.start, "Invalid left-hand side in for-loop");
1272 }
1273 node.left = init;
1274 node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign();
1275 this.expect(types.parenR);
1276 node.body = this.parseStatement("for");
1277 this.exitScope();
1278 this.labels.pop();
1279 return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement")
1280 };
1281
1282 // Parse a list of variable declarations.
1283
1284 pp$1.parseVar = function(node, isFor, kind) {
1285 node.declarations = [];
1286 node.kind = kind;
1287 for (;;) {
1288 var decl = this.startNode();
1289 this.parseVarId(decl, kind);
1290 if (this.eat(types.eq)) {
1291 decl.init = this.parseMaybeAssign(isFor);
1292 } else if (kind === "const" && !(this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
1293 this.unexpected();
1294 } else if (decl.id.type !== "Identifier" && !(isFor && (this.type === types._in || this.isContextual("of")))) {
1295 this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value");
1296 } else {
1297 decl.init = null;
1298 }
1299 node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
1300 if (!this.eat(types.comma)) { break }
1301 }
1302 return node
1303 };
1304
1305 pp$1.parseVarId = function(decl, kind) {
1306 decl.id = this.parseBindingAtom();
1307 this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false);
1308 };
1309
1310 var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4;
1311
1312 // Parse a function declaration or literal (depending on the
1313 // `statement & FUNC_STATEMENT`).
1314
1315 // Remove `allowExpressionBody` for 7.0.0, as it is only called with false
1316 pp$1.parseFunction = function(node, statement, allowExpressionBody, isAsync) {
1317 this.initFunction(node);
1318 if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) {
1319 if (this.type === types.star && (statement & FUNC_HANGING_STATEMENT))
1320 { this.unexpected(); }
1321 node.generator = this.eat(types.star);
1322 }
1323 if (this.options.ecmaVersion >= 8)
1324 { node.async = !!isAsync; }
1325
1326 if (statement & FUNC_STATEMENT) {
1327 node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name ? null : this.parseIdent();
1328 if (node.id && !(statement & FUNC_HANGING_STATEMENT))
1329 // If it is a regular function declaration in sloppy mode, then it is
1330 // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
1331 // mode depends on properties of the current scope (see
1332 // treatFunctionsAsVar).
1333 { this.checkLVal(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); }
1334 }
1335
1336 var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
1337 this.yieldPos = 0;
1338 this.awaitPos = 0;
1339 this.awaitIdentPos = 0;
1340 this.enterScope(functionFlags(node.async, node.generator));
1341
1342 if (!(statement & FUNC_STATEMENT))
1343 { node.id = this.type === types.name ? this.parseIdent() : null; }
1344
1345 this.parseFunctionParams(node);
1346 this.parseFunctionBody(node, allowExpressionBody, false);
1347
1348 this.yieldPos = oldYieldPos;
1349 this.awaitPos = oldAwaitPos;
1350 this.awaitIdentPos = oldAwaitIdentPos;
1351 return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression")
1352 };
1353
1354 pp$1.parseFunctionParams = function(node) {
1355 this.expect(types.parenL);
1356 node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
1357 this.checkYieldAwaitInDefaultParams();
1358 };
1359
1360 // Parse a class declaration or literal (depending on the
1361 // `isStatement` parameter).
1362
1363 pp$1.parseClass = function(node, isStatement) {
1364 this.next();
1365
1366 // ecma-262 14.6 Class Definitions
1367 // A class definition is always strict mode code.
1368 var oldStrict = this.strict;
1369 this.strict = true;
1370
1371 this.parseClassId(node, isStatement);
1372 this.parseClassSuper(node);
1373 var classBody = this.startNode();
1374 var hadConstructor = false;
1375 classBody.body = [];
1376 this.expect(types.braceL);
1377 while (this.type !== types.braceR) {
1378 var element = this.parseClassElement(node.superClass !== null);
1379 if (element) {
1380 classBody.body.push(element);
1381 if (element.type === "MethodDefinition" && element.kind === "constructor") {
1382 if (hadConstructor) { this.raise(element.start, "Duplicate constructor in the same class"); }
1383 hadConstructor = true;
1384 }
1385 }
1386 }
1387 this.strict = oldStrict;
1388 this.next();
1389 node.body = this.finishNode(classBody, "ClassBody");
1390 return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
1391 };
1392
1393 pp$1.parseClassElement = function(constructorAllowsSuper) {
1394 var this$1 = this;
1395
1396 if (this.eat(types.semi)) { return null }
1397
1398 var method = this.startNode();
1399 var tryContextual = function (k, noLineBreak) {
1400 if ( noLineBreak === void 0 ) noLineBreak = false;
1401
1402 var start = this$1.start, startLoc = this$1.startLoc;
1403 if (!this$1.eatContextual(k)) { return false }
1404 if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true }
1405 if (method.key) { this$1.unexpected(); }
1406 method.computed = false;
1407 method.key = this$1.startNodeAt(start, startLoc);
1408 method.key.name = k;
1409 this$1.finishNode(method.key, "Identifier");
1410 return false
1411 };
1412
1413 method.kind = "method";
1414 method.static = tryContextual("static");
1415 var isGenerator = this.eat(types.star);
1416 var isAsync = false;
1417 if (!isGenerator) {
1418 if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) {
1419 isAsync = true;
1420 isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
1421 } else if (tryContextual("get")) {
1422 method.kind = "get";
1423 } else if (tryContextual("set")) {
1424 method.kind = "set";
1425 }
1426 }
1427 if (!method.key) { this.parsePropertyName(method); }
1428 var key = method.key;
1429 var allowsDirectSuper = false;
1430 if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" ||
1431 key.type === "Literal" && key.value === "constructor")) {
1432 if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); }
1433 if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); }
1434 if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); }
1435 method.kind = "constructor";
1436 allowsDirectSuper = constructorAllowsSuper;
1437 } else if (method.static && key.type === "Identifier" && key.name === "prototype") {
1438 this.raise(key.start, "Classes may not have a static property named prototype");
1439 }
1440 this.parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper);
1441 if (method.kind === "get" && method.value.params.length !== 0)
1442 { this.raiseRecoverable(method.value.start, "getter should have no params"); }
1443 if (method.kind === "set" && method.value.params.length !== 1)
1444 { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); }
1445 if (method.kind === "set" && method.value.params[0].type === "RestElement")
1446 { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); }
1447 return method
1448 };
1449
1450 pp$1.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) {
1451 method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper);
1452 return this.finishNode(method, "MethodDefinition")
1453 };
1454
1455 pp$1.parseClassId = function(node, isStatement) {
1456 if (this.type === types.name) {
1457 node.id = this.parseIdent();
1458 if (isStatement)
1459 { this.checkLVal(node.id, BIND_LEXICAL, false); }
1460 } else {
1461 if (isStatement === true)
1462 { this.unexpected(); }
1463 node.id = null;
1464 }
1465 };
1466
1467 pp$1.parseClassSuper = function(node) {
1468 node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null;
1469 };
1470
1471 // Parses module export declaration.
1472
1473 pp$1.parseExport = function(node, exports) {
1474 this.next();
1475 // export * from '...'
1476 if (this.eat(types.star)) {
1477 if (this.options.ecmaVersion >= 11) {
1478 if (this.eatContextual("as")) {
1479 node.exported = this.parseIdent(true);
1480 this.checkExport(exports, node.exported.name, this.lastTokStart);
1481 } else {
1482 node.exported = null;
1483 }
1484 }
1485 this.expectContextual("from");
1486 if (this.type !== types.string) { this.unexpected(); }
1487 node.source = this.parseExprAtom();
1488 this.semicolon();
1489 return this.finishNode(node, "ExportAllDeclaration")
1490 }
1491 if (this.eat(types._default)) { // export default ...
1492 this.checkExport(exports, "default", this.lastTokStart);
1493 var isAsync;
1494 if (this.type === types._function || (isAsync = this.isAsyncFunction())) {
1495 var fNode = this.startNode();
1496 this.next();
1497 if (isAsync) { this.next(); }
1498 node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync);
1499 } else if (this.type === types._class) {
1500 var cNode = this.startNode();
1501 node.declaration = this.parseClass(cNode, "nullableID");
1502 } else {
1503 node.declaration = this.parseMaybeAssign();
1504 this.semicolon();
1505 }
1506 return this.finishNode(node, "ExportDefaultDeclaration")
1507 }
1508 // export var|const|let|function|class ...
1509 if (this.shouldParseExportStatement()) {
1510 node.declaration = this.parseStatement(null);
1511 if (node.declaration.type === "VariableDeclaration")
1512 { this.checkVariableExport(exports, node.declaration.declarations); }
1513 else
1514 { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); }
1515 node.specifiers = [];
1516 node.source = null;
1517 } else { // export { x, y as z } [from '...']
1518 node.declaration = null;
1519 node.specifiers = this.parseExportSpecifiers(exports);
1520 if (this.eatContextual("from")) {
1521 if (this.type !== types.string) { this.unexpected(); }
1522 node.source = this.parseExprAtom();
1523 } else {
1524 for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
1525 // check for keywords used as local names
1526 var spec = list[i];
1527
1528 this.checkUnreserved(spec.local);
1529 // check if export is defined
1530 this.checkLocalExport(spec.local);
1531 }
1532
1533 node.source = null;
1534 }
1535 this.semicolon();
1536 }
1537 return this.finishNode(node, "ExportNamedDeclaration")
1538 };
1539
1540 pp$1.checkExport = function(exports, name, pos) {
1541 if (!exports) { return }
1542 if (has(exports, name))
1543 { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
1544 exports[name] = true;
1545 };
1546
1547 pp$1.checkPatternExport = function(exports, pat) {
1548 var type = pat.type;
1549 if (type === "Identifier")
1550 { this.checkExport(exports, pat.name, pat.start); }
1551 else if (type === "ObjectPattern")
1552 { for (var i = 0, list = pat.properties; i < list.length; i += 1)
1553 {
1554 var prop = list[i];
1555
1556 this.checkPatternExport(exports, prop);
1557 } }
1558 else if (type === "ArrayPattern")
1559 { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
1560 var elt = list$1[i$1];
1561
1562 if (elt) { this.checkPatternExport(exports, elt); }
1563 } }
1564 else if (type === "Property")
1565 { this.checkPatternExport(exports, pat.value); }
1566 else if (type === "AssignmentPattern")
1567 { this.checkPatternExport(exports, pat.left); }
1568 else if (type === "RestElement")
1569 { this.checkPatternExport(exports, pat.argument); }
1570 else if (type === "ParenthesizedExpression")
1571 { this.checkPatternExport(exports, pat.expression); }
1572 };
1573
1574 pp$1.checkVariableExport = function(exports, decls) {
1575 if (!exports) { return }
1576 for (var i = 0, list = decls; i < list.length; i += 1)
1577 {
1578 var decl = list[i];
1579
1580 this.checkPatternExport(exports, decl.id);
1581 }
1582 };
1583
1584 pp$1.shouldParseExportStatement = function() {
1585 return this.type.keyword === "var" ||
1586 this.type.keyword === "const" ||
1587 this.type.keyword === "class" ||
1588 this.type.keyword === "function" ||
1589 this.isLet() ||
1590 this.isAsyncFunction()
1591 };
1592
1593 // Parses a comma-separated list of module exports.
1594
1595 pp$1.parseExportSpecifiers = function(exports) {
1596 var nodes = [], first = true;
1597 // export { x, y as z } [from '...']
1598 this.expect(types.braceL);
1599 while (!this.eat(types.braceR)) {
1600 if (!first) {
1601 this.expect(types.comma);
1602 if (this.afterTrailingComma(types.braceR)) { break }
1603 } else { first = false; }
1604
1605 var node = this.startNode();
1606 node.local = this.parseIdent(true);
1607 node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local;
1608 this.checkExport(exports, node.exported.name, node.exported.start);
1609 nodes.push(this.finishNode(node, "ExportSpecifier"));
1610 }
1611 return nodes
1612 };
1613
1614 // Parses import declaration.
1615
1616 pp$1.parseImport = function(node) {
1617 this.next();
1618 // import '...'
1619 if (this.type === types.string) {
1620 node.specifiers = empty;
1621 node.source = this.parseExprAtom();
1622 } else {
1623 node.specifiers = this.parseImportSpecifiers();
1624 this.expectContextual("from");
1625 node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
1626 }
1627 this.semicolon();
1628 return this.finishNode(node, "ImportDeclaration")
1629 };
1630
1631 // Parses a comma-separated list of module imports.
1632
1633 pp$1.parseImportSpecifiers = function() {
1634 var nodes = [], first = true;
1635 if (this.type === types.name) {
1636 // import defaultObj, { x, y as z } from '...'
1637 var node = this.startNode();
1638 node.local = this.parseIdent();
1639 this.checkLVal(node.local, BIND_LEXICAL);
1640 nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
1641 if (!this.eat(types.comma)) { return nodes }
1642 }
1643 if (this.type === types.star) {
1644 var node$1 = this.startNode();
1645 this.next();
1646 this.expectContextual("as");
1647 node$1.local = this.parseIdent();
1648 this.checkLVal(node$1.local, BIND_LEXICAL);
1649 nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
1650 return nodes
1651 }
1652 this.expect(types.braceL);
1653 while (!this.eat(types.braceR)) {
1654 if (!first) {
1655 this.expect(types.comma);
1656 if (this.afterTrailingComma(types.braceR)) { break }
1657 } else { first = false; }
1658
1659 var node$2 = this.startNode();
1660 node$2.imported = this.parseIdent(true);
1661 if (this.eatContextual("as")) {
1662 node$2.local = this.parseIdent();
1663 } else {
1664 this.checkUnreserved(node$2.imported);
1665 node$2.local = node$2.imported;
1666 }
1667 this.checkLVal(node$2.local, BIND_LEXICAL);
1668 nodes.push(this.finishNode(node$2, "ImportSpecifier"));
1669 }
1670 return nodes
1671 };
1672
1673 // Set `ExpressionStatement#directive` property for directive prologues.
1674 pp$1.adaptDirectivePrologue = function(statements) {
1675 for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
1676 statements[i].directive = statements[i].expression.raw.slice(1, -1);
1677 }
1678 };
1679 pp$1.isDirectiveCandidate = function(statement) {
1680 return (
1681 statement.type === "ExpressionStatement" &&
1682 statement.expression.type === "Literal" &&
1683 typeof statement.expression.value === "string" &&
1684 // Reject parenthesized strings.
1685 (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
1686 )
1687 };
1688
1689 var pp$2 = Parser.prototype;
1690
1691 // Convert existing expression atom to assignable pattern
1692 // if possible.
1693
1694 pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) {
1695 if (this.options.ecmaVersion >= 6 && node) {
1696 switch (node.type) {
1697 case "Identifier":
1698 if (this.inAsync && node.name === "await")
1699 { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); }
1700 break
1701
1702 case "ObjectPattern":
1703 case "ArrayPattern":
1704 case "RestElement":
1705 break
1706
1707 case "ObjectExpression":
1708 node.type = "ObjectPattern";
1709 if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1710 for (var i = 0, list = node.properties; i < list.length; i += 1) {
1711 var prop = list[i];
1712
1713 this.toAssignable(prop, isBinding);
1714 // Early error:
1715 // AssignmentRestProperty[Yield, Await] :
1716 // `...` DestructuringAssignmentTarget[Yield, Await]
1717 //
1718 // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
1719 if (
1720 prop.type === "RestElement" &&
1721 (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")
1722 ) {
1723 this.raise(prop.argument.start, "Unexpected token");
1724 }
1725 }
1726 break
1727
1728 case "Property":
1729 // AssignmentProperty has type === "Property"
1730 if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); }
1731 this.toAssignable(node.value, isBinding);
1732 break
1733
1734 case "ArrayExpression":
1735 node.type = "ArrayPattern";
1736 if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1737 this.toAssignableList(node.elements, isBinding);
1738 break
1739
1740 case "SpreadElement":
1741 node.type = "RestElement";
1742 this.toAssignable(node.argument, isBinding);
1743 if (node.argument.type === "AssignmentPattern")
1744 { this.raise(node.argument.start, "Rest elements cannot have a default value"); }
1745 break
1746
1747 case "AssignmentExpression":
1748 if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); }
1749 node.type = "AssignmentPattern";
1750 delete node.operator;
1751 this.toAssignable(node.left, isBinding);
1752 // falls through to AssignmentPattern
1753
1754 case "AssignmentPattern":
1755 break
1756
1757 case "ParenthesizedExpression":
1758 this.toAssignable(node.expression, isBinding, refDestructuringErrors);
1759 break
1760
1761 case "ChainExpression":
1762 this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side");
1763 break
1764
1765 case "MemberExpression":
1766 if (!isBinding) { break }
1767
1768 default:
1769 this.raise(node.start, "Assigning to rvalue");
1770 }
1771 } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
1772 return node
1773 };
1774
1775 // Convert list of expression atoms to binding list.
1776
1777 pp$2.toAssignableList = function(exprList, isBinding) {
1778 var end = exprList.length;
1779 for (var i = 0; i < end; i++) {
1780 var elt = exprList[i];
1781 if (elt) { this.toAssignable(elt, isBinding); }
1782 }
1783 if (end) {
1784 var last = exprList[end - 1];
1785 if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
1786 { this.unexpected(last.argument.start); }
1787 }
1788 return exprList
1789 };
1790
1791 // Parses spread element.
1792
1793 pp$2.parseSpread = function(refDestructuringErrors) {
1794 var node = this.startNode();
1795 this.next();
1796 node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
1797 return this.finishNode(node, "SpreadElement")
1798 };
1799
1800 pp$2.parseRestBinding = function() {
1801 var node = this.startNode();
1802 this.next();
1803
1804 // RestElement inside of a function parameter must be an identifier
1805 if (this.options.ecmaVersion === 6 && this.type !== types.name)
1806 { this.unexpected(); }
1807
1808 node.argument = this.parseBindingAtom();
1809
1810 return this.finishNode(node, "RestElement")
1811 };
1812
1813 // Parses lvalue (assignable) atom.
1814
1815 pp$2.parseBindingAtom = function() {
1816 if (this.options.ecmaVersion >= 6) {
1817 switch (this.type) {
1818 case types.bracketL:
1819 var node = this.startNode();
1820 this.next();
1821 node.elements = this.parseBindingList(types.bracketR, true, true);
1822 return this.finishNode(node, "ArrayPattern")
1823
1824 case types.braceL:
1825 return this.parseObj(true)
1826 }
1827 }
1828 return this.parseIdent()
1829 };
1830
1831 pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
1832 var elts = [], first = true;
1833 while (!this.eat(close)) {
1834 if (first) { first = false; }
1835 else { this.expect(types.comma); }
1836 if (allowEmpty && this.type === types.comma) {
1837 elts.push(null);
1838 } else if (allowTrailingComma && this.afterTrailingComma(close)) {
1839 break
1840 } else if (this.type === types.ellipsis) {
1841 var rest = this.parseRestBinding();
1842 this.parseBindingListItem(rest);
1843 elts.push(rest);
1844 if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); }
1845 this.expect(close);
1846 break
1847 } else {
1848 var elem = this.parseMaybeDefault(this.start, this.startLoc);
1849 this.parseBindingListItem(elem);
1850 elts.push(elem);
1851 }
1852 }
1853 return elts
1854 };
1855
1856 pp$2.parseBindingListItem = function(param) {
1857 return param
1858 };
1859
1860 // Parses assignment pattern around given atom if possible.
1861
1862 pp$2.parseMaybeDefault = function(startPos, startLoc, left) {
1863 left = left || this.parseBindingAtom();
1864 if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left }
1865 var node = this.startNodeAt(startPos, startLoc);
1866 node.left = left;
1867 node.right = this.parseMaybeAssign();
1868 return this.finishNode(node, "AssignmentPattern")
1869 };
1870
1871 // Verify that a node is an lval — something that can be assigned
1872 // to.
1873 // bindingType can be either:
1874 // 'var' indicating that the lval creates a 'var' binding
1875 // 'let' indicating that the lval creates a lexical ('let' or 'const') binding
1876 // 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references
1877
1878 pp$2.checkLVal = function(expr, bindingType, checkClashes) {
1879 if ( bindingType === void 0 ) bindingType = BIND_NONE;
1880
1881 switch (expr.type) {
1882 case "Identifier":
1883 if (bindingType === BIND_LEXICAL && expr.name === "let")
1884 { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); }
1885 if (this.strict && this.reservedWordsStrictBind.test(expr.name))
1886 { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
1887 if (checkClashes) {
1888 if (has(checkClashes, expr.name))
1889 { this.raiseRecoverable(expr.start, "Argument name clash"); }
1890 checkClashes[expr.name] = true;
1891 }
1892 if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); }
1893 break
1894
1895 case "ChainExpression":
1896 this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side");
1897 break
1898
1899 case "MemberExpression":
1900 if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); }
1901 break
1902
1903 case "ObjectPattern":
1904 for (var i = 0, list = expr.properties; i < list.length; i += 1)
1905 {
1906 var prop = list[i];
1907
1908 this.checkLVal(prop, bindingType, checkClashes);
1909 }
1910 break
1911
1912 case "Property":
1913 // AssignmentProperty has type === "Property"
1914 this.checkLVal(expr.value, bindingType, checkClashes);
1915 break
1916
1917 case "ArrayPattern":
1918 for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
1919 var elem = list$1[i$1];
1920
1921 if (elem) { this.checkLVal(elem, bindingType, checkClashes); }
1922 }
1923 break
1924
1925 case "AssignmentPattern":
1926 this.checkLVal(expr.left, bindingType, checkClashes);
1927 break
1928
1929 case "RestElement":
1930 this.checkLVal(expr.argument, bindingType, checkClashes);
1931 break
1932
1933 case "ParenthesizedExpression":
1934 this.checkLVal(expr.expression, bindingType, checkClashes);
1935 break
1936
1937 default:
1938 this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue");
1939 }
1940 };
1941
1942 // A recursive descent parser operates by defining functions for all
1943
1944 var pp$3 = Parser.prototype;
1945
1946 // Check if property name clashes with already added.
1947 // Object/class getters and setters are not allowed to clash —
1948 // either with each other or with an init property — and in
1949 // strict mode, init properties are also not allowed to be repeated.
1950
1951 pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) {
1952 if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
1953 { return }
1954 if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
1955 { return }
1956 var key = prop.key;
1957 var name;
1958 switch (key.type) {
1959 case "Identifier": name = key.name; break
1960 case "Literal": name = String(key.value); break
1961 default: return
1962 }
1963 var kind = prop.kind;
1964 if (this.options.ecmaVersion >= 6) {
1965 if (name === "__proto__" && kind === "init") {
1966 if (propHash.proto) {
1967 if (refDestructuringErrors) {
1968 if (refDestructuringErrors.doubleProto < 0)
1969 { refDestructuringErrors.doubleProto = key.start; }
1970 // Backwards-compat kludge. Can be removed in version 6.0
1971 } else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); }
1972 }
1973 propHash.proto = true;
1974 }
1975 return
1976 }
1977 name = "$" + name;
1978 var other = propHash[name];
1979 if (other) {
1980 var redefinition;
1981 if (kind === "init") {
1982 redefinition = this.strict && other.init || other.get || other.set;
1983 } else {
1984 redefinition = other.init || other[kind];
1985 }
1986 if (redefinition)
1987 { this.raiseRecoverable(key.start, "Redefinition of property"); }
1988 } else {
1989 other = propHash[name] = {
1990 init: false,
1991 get: false,
1992 set: false
1993 };
1994 }
1995 other[kind] = true;
1996 };
1997
1998 // ### Expression parsing
1999
2000 // These nest, from the most general expression type at the top to
2001 // 'atomic', nondivisible expression types at the bottom. Most of
2002 // the functions will simply let the function(s) below them parse,
2003 // and, *if* the syntactic construct they handle is present, wrap
2004 // the AST node that the inner parser gave them in another node.
2005
2006 // Parse a full expression. The optional arguments are used to
2007 // forbid the `in` operator (in for loops initalization expressions)
2008 // and provide reference for storing '=' operator inside shorthand
2009 // property assignment in contexts where both object expression
2010 // and object pattern might appear (so it's possible to raise
2011 // delayed syntax error at correct position).
2012
2013 pp$3.parseExpression = function(noIn, refDestructuringErrors) {
2014 var startPos = this.start, startLoc = this.startLoc;
2015 var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
2016 if (this.type === types.comma) {
2017 var node = this.startNodeAt(startPos, startLoc);
2018 node.expressions = [expr];
2019 while (this.eat(types.comma)) { node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); }
2020 return this.finishNode(node, "SequenceExpression")
2021 }
2022 return expr
2023 };
2024
2025 // Parse an assignment expression. This includes applications of
2026 // operators like `+=`.
2027
2028 pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
2029 if (this.isContextual("yield")) {
2030 if (this.inGenerator) { return this.parseYield(noIn) }
2031 // The tokenizer will assume an expression is allowed after
2032 // `yield`, but this isn't that kind of yield
2033 else { this.exprAllowed = false; }
2034 }
2035
2036 var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1;
2037 if (refDestructuringErrors) {
2038 oldParenAssign = refDestructuringErrors.parenthesizedAssign;
2039 oldTrailingComma = refDestructuringErrors.trailingComma;
2040 refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
2041 } else {
2042 refDestructuringErrors = new DestructuringErrors;
2043 ownDestructuringErrors = true;
2044 }
2045
2046 var startPos = this.start, startLoc = this.startLoc;
2047 if (this.type === types.parenL || this.type === types.name)
2048 { this.potentialArrowAt = this.start; }
2049 var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
2050 if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
2051 if (this.type.isAssign) {
2052 var node = this.startNodeAt(startPos, startLoc);
2053 node.operator = this.value;
2054 node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left;
2055 if (!ownDestructuringErrors) {
2056 refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
2057 }
2058 if (refDestructuringErrors.shorthandAssign >= node.left.start)
2059 { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly
2060 this.checkLVal(left);
2061 this.next();
2062 node.right = this.parseMaybeAssign(noIn);
2063 return this.finishNode(node, "AssignmentExpression")
2064 } else {
2065 if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
2066 }
2067 if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
2068 if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
2069 return left
2070 };
2071
2072 // Parse a ternary conditional (`?:`) operator.
2073
2074 pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) {
2075 var startPos = this.start, startLoc = this.startLoc;
2076 var expr = this.parseExprOps(noIn, refDestructuringErrors);
2077 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2078 if (this.eat(types.question)) {
2079 var node = this.startNodeAt(startPos, startLoc);
2080 node.test = expr;
2081 node.consequent = this.parseMaybeAssign();
2082 this.expect(types.colon);
2083 node.alternate = this.parseMaybeAssign(noIn);
2084 return this.finishNode(node, "ConditionalExpression")
2085 }
2086 return expr
2087 };
2088
2089 // Start the precedence parser.
2090
2091 pp$3.parseExprOps = function(noIn, refDestructuringErrors) {
2092 var startPos = this.start, startLoc = this.startLoc;
2093 var expr = this.parseMaybeUnary(refDestructuringErrors, false);
2094 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2095 return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn)
2096 };
2097
2098 // Parse binary operators with the operator precedence parsing
2099 // algorithm. `left` is the left-hand side of the operator.
2100 // `minPrec` provides context that allows the function to stop and
2101 // defer further parser to one of its callers when it encounters an
2102 // operator that has a lower precedence than the set it is parsing.
2103
2104 pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
2105 var prec = this.type.binop;
2106 if (prec != null && (!noIn || this.type !== types._in)) {
2107 if (prec > minPrec) {
2108 var logical = this.type === types.logicalOR || this.type === types.logicalAND;
2109 var coalesce = this.type === types.coalesce;
2110 if (coalesce) {
2111 // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions.
2112 // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error.
2113 prec = types.logicalAND.binop;
2114 }
2115 var op = this.value;
2116 this.next();
2117 var startPos = this.start, startLoc = this.startLoc;
2118 var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
2119 var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce);
2120 if ((logical && this.type === types.coalesce) || (coalesce && (this.type === types.logicalOR || this.type === types.logicalAND))) {
2121 this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses");
2122 }
2123 return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
2124 }
2125 }
2126 return left
2127 };
2128
2129 pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) {
2130 var node = this.startNodeAt(startPos, startLoc);
2131 node.left = left;
2132 node.operator = op;
2133 node.right = right;
2134 return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
2135 };
2136
2137 // Parse unary operators, both prefix and postfix.
2138
2139 pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
2140 var startPos = this.start, startLoc = this.startLoc, expr;
2141 if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) {
2142 expr = this.parseAwait();
2143 sawUnary = true;
2144 } else if (this.type.prefix) {
2145 var node = this.startNode(), update = this.type === types.incDec;
2146 node.operator = this.value;
2147 node.prefix = true;
2148 this.next();
2149 node.argument = this.parseMaybeUnary(null, true);
2150 this.checkExpressionErrors(refDestructuringErrors, true);
2151 if (update) { this.checkLVal(node.argument); }
2152 else if (this.strict && node.operator === "delete" &&
2153 node.argument.type === "Identifier")
2154 { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
2155 else { sawUnary = true; }
2156 expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
2157 } else {
2158 expr = this.parseExprSubscripts(refDestructuringErrors);
2159 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
2160 while (this.type.postfix && !this.canInsertSemicolon()) {
2161 var node$1 = this.startNodeAt(startPos, startLoc);
2162 node$1.operator = this.value;
2163 node$1.prefix = false;
2164 node$1.argument = expr;
2165 this.checkLVal(expr);
2166 this.next();
2167 expr = this.finishNode(node$1, "UpdateExpression");
2168 }
2169 }
2170
2171 if (!sawUnary && this.eat(types.starstar))
2172 { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) }
2173 else
2174 { return expr }
2175 };
2176
2177 // Parse call, dot, and `[]`-subscript expressions.
2178
2179 pp$3.parseExprSubscripts = function(refDestructuringErrors) {
2180 var startPos = this.start, startLoc = this.startLoc;
2181 var expr = this.parseExprAtom(refDestructuringErrors);
2182 if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")")
2183 { return expr }
2184 var result = this.parseSubscripts(expr, startPos, startLoc);
2185 if (refDestructuringErrors && result.type === "MemberExpression") {
2186 if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
2187 if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
2188 }
2189 return result
2190 };
2191
2192 pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) {
2193 var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
2194 this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 &&
2195 this.potentialArrowAt === base.start;
2196 var optionalChained = false;
2197
2198 while (true) {
2199 var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained);
2200
2201 if (element.optional) { optionalChained = true; }
2202 if (element === base || element.type === "ArrowFunctionExpression") {
2203 if (optionalChained) {
2204 var chainNode = this.startNodeAt(startPos, startLoc);
2205 chainNode.expression = element;
2206 element = this.finishNode(chainNode, "ChainExpression");
2207 }
2208 return element
2209 }
2210
2211 base = element;
2212 }
2213 };
2214
2215 pp$3.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained) {
2216 var optionalSupported = this.options.ecmaVersion >= 11;
2217 var optional = optionalSupported && this.eat(types.questionDot);
2218 if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); }
2219
2220 var computed = this.eat(types.bracketL);
2221 if (computed || (optional && this.type !== types.parenL && this.type !== types.backQuote) || this.eat(types.dot)) {
2222 var node = this.startNodeAt(startPos, startLoc);
2223 node.object = base;
2224 node.property = computed ? this.parseExpression() : this.parseIdent(this.options.allowReserved !== "never");
2225 node.computed = !!computed;
2226 if (computed) { this.expect(types.bracketR); }
2227 if (optionalSupported) {
2228 node.optional = optional;
2229 }
2230 base = this.finishNode(node, "MemberExpression");
2231 } else if (!noCalls && this.eat(types.parenL)) {
2232 var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2233 this.yieldPos = 0;
2234 this.awaitPos = 0;
2235 this.awaitIdentPos = 0;
2236 var exprList = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors);
2237 if (maybeAsyncArrow && !optional && !this.canInsertSemicolon() && this.eat(types.arrow)) {
2238 this.checkPatternErrors(refDestructuringErrors, false);
2239 this.checkYieldAwaitInDefaultParams();
2240 if (this.awaitIdentPos > 0)
2241 { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); }
2242 this.yieldPos = oldYieldPos;
2243 this.awaitPos = oldAwaitPos;
2244 this.awaitIdentPos = oldAwaitIdentPos;
2245 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true)
2246 }
2247 this.checkExpressionErrors(refDestructuringErrors, true);
2248 this.yieldPos = oldYieldPos || this.yieldPos;
2249 this.awaitPos = oldAwaitPos || this.awaitPos;
2250 this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos;
2251 var node$1 = this.startNodeAt(startPos, startLoc);
2252 node$1.callee = base;
2253 node$1.arguments = exprList;
2254 if (optionalSupported) {
2255 node$1.optional = optional;
2256 }
2257 base = this.finishNode(node$1, "CallExpression");
2258 } else if (this.type === types.backQuote) {
2259 if (optional || optionalChained) {
2260 this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions");
2261 }
2262 var node$2 = this.startNodeAt(startPos, startLoc);
2263 node$2.tag = base;
2264 node$2.quasi = this.parseTemplate({isTagged: true});
2265 base = this.finishNode(node$2, "TaggedTemplateExpression");
2266 }
2267 return base
2268 };
2269
2270 // Parse an atomic expression — either a single token that is an
2271 // expression, an expression started by a keyword like `function` or
2272 // `new`, or an expression wrapped in punctuation like `()`, `[]`,
2273 // or `{}`.
2274
2275 pp$3.parseExprAtom = function(refDestructuringErrors) {
2276 // If a division operator appears in an expression position, the
2277 // tokenizer got confused, and we force it to read a regexp instead.
2278 if (this.type === types.slash) { this.readRegexp(); }
2279
2280 var node, canBeArrow = this.potentialArrowAt === this.start;
2281 switch (this.type) {
2282 case types._super:
2283 if (!this.allowSuper)
2284 { this.raise(this.start, "'super' keyword outside a method"); }
2285 node = this.startNode();
2286 this.next();
2287 if (this.type === types.parenL && !this.allowDirectSuper)
2288 { this.raise(node.start, "super() call outside constructor of a subclass"); }
2289 // The `super` keyword can appear at below:
2290 // SuperProperty:
2291 // super [ Expression ]
2292 // super . IdentifierName
2293 // SuperCall:
2294 // super ( Arguments )
2295 if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
2296 { this.unexpected(); }
2297 return this.finishNode(node, "Super")
2298
2299 case types._this:
2300 node = this.startNode();
2301 this.next();
2302 return this.finishNode(node, "ThisExpression")
2303
2304 case types.name:
2305 var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
2306 var id = this.parseIdent(false);
2307 if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function))
2308 { return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) }
2309 if (canBeArrow && !this.canInsertSemicolon()) {
2310 if (this.eat(types.arrow))
2311 { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) }
2312 if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) {
2313 id = this.parseIdent(false);
2314 if (this.canInsertSemicolon() || !this.eat(types.arrow))
2315 { this.unexpected(); }
2316 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
2317 }
2318 }
2319 return id
2320
2321 case types.regexp:
2322 var value = this.value;
2323 node = this.parseLiteral(value.value);
2324 node.regex = {pattern: value.pattern, flags: value.flags};
2325 return node
2326
2327 case types.num: case types.string:
2328 return this.parseLiteral(this.value)
2329
2330 case types._null: case types._true: case types._false:
2331 node = this.startNode();
2332 node.value = this.type === types._null ? null : this.type === types._true;
2333 node.raw = this.type.keyword;
2334 this.next();
2335 return this.finishNode(node, "Literal")
2336
2337 case types.parenL:
2338 var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow);
2339 if (refDestructuringErrors) {
2340 if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
2341 { refDestructuringErrors.parenthesizedAssign = start; }
2342 if (refDestructuringErrors.parenthesizedBind < 0)
2343 { refDestructuringErrors.parenthesizedBind = start; }
2344 }
2345 return expr
2346
2347 case types.bracketL:
2348 node = this.startNode();
2349 this.next();
2350 node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors);
2351 return this.finishNode(node, "ArrayExpression")
2352
2353 case types.braceL:
2354 return this.parseObj(false, refDestructuringErrors)
2355
2356 case types._function:
2357 node = this.startNode();
2358 this.next();
2359 return this.parseFunction(node, 0)
2360
2361 case types._class:
2362 return this.parseClass(this.startNode(), false)
2363
2364 case types._new:
2365 return this.parseNew()
2366
2367 case types.backQuote:
2368 return this.parseTemplate()
2369
2370 case types._import:
2371 if (this.options.ecmaVersion >= 11) {
2372 return this.parseExprImport()
2373 } else {
2374 return this.unexpected()
2375 }
2376
2377 default:
2378 this.unexpected();
2379 }
2380 };
2381
2382 pp$3.parseExprImport = function() {
2383 var node = this.startNode();
2384
2385 // Consume `import` as an identifier for `import.meta`.
2386 // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`.
2387 if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); }
2388 var meta = this.parseIdent(true);
2389
2390 switch (this.type) {
2391 case types.parenL:
2392 return this.parseDynamicImport(node)
2393 case types.dot:
2394 node.meta = meta;
2395 return this.parseImportMeta(node)
2396 default:
2397 this.unexpected();
2398 }
2399 };
2400
2401 pp$3.parseDynamicImport = function(node) {
2402 this.next(); // skip `(`
2403
2404 // Parse node.source.
2405 node.source = this.parseMaybeAssign();
2406
2407 // Verify ending.
2408 if (!this.eat(types.parenR)) {
2409 var errorPos = this.start;
2410 if (this.eat(types.comma) && this.eat(types.parenR)) {
2411 this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()");
2412 } else {
2413 this.unexpected(errorPos);
2414 }
2415 }
2416
2417 return this.finishNode(node, "ImportExpression")
2418 };
2419
2420 pp$3.parseImportMeta = function(node) {
2421 this.next(); // skip `.`
2422
2423 var containsEsc = this.containsEsc;
2424 node.property = this.parseIdent(true);
2425
2426 if (node.property.name !== "meta")
2427 { this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); }
2428 if (containsEsc)
2429 { this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); }
2430 if (this.options.sourceType !== "module")
2431 { this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); }
2432
2433 return this.finishNode(node, "MetaProperty")
2434 };
2435
2436 pp$3.parseLiteral = function(value) {
2437 var node = this.startNode();
2438 node.value = value;
2439 node.raw = this.input.slice(this.start, this.end);
2440 if (node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1).replace(/_/g, ""); }
2441 this.next();
2442 return this.finishNode(node, "Literal")
2443 };
2444
2445 pp$3.parseParenExpression = function() {
2446 this.expect(types.parenL);
2447 var val = this.parseExpression();
2448 this.expect(types.parenR);
2449 return val
2450 };
2451
2452 pp$3.parseParenAndDistinguishExpression = function(canBeArrow) {
2453 var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
2454 if (this.options.ecmaVersion >= 6) {
2455 this.next();
2456
2457 var innerStartPos = this.start, innerStartLoc = this.startLoc;
2458 var exprList = [], first = true, lastIsComma = false;
2459 var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
2460 this.yieldPos = 0;
2461 this.awaitPos = 0;
2462 // Do not save awaitIdentPos to allow checking awaits nested in parameters
2463 while (this.type !== types.parenR) {
2464 first ? first = false : this.expect(types.comma);
2465 if (allowTrailingComma && this.afterTrailingComma(types.parenR, true)) {
2466 lastIsComma = true;
2467 break
2468 } else if (this.type === types.ellipsis) {
2469 spreadStart = this.start;
2470 exprList.push(this.parseParenItem(this.parseRestBinding()));
2471 if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); }
2472 break
2473 } else {
2474 exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem));
2475 }
2476 }
2477 var innerEndPos = this.start, innerEndLoc = this.startLoc;
2478 this.expect(types.parenR);
2479
2480 if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
2481 this.checkPatternErrors(refDestructuringErrors, false);
2482 this.checkYieldAwaitInDefaultParams();
2483 this.yieldPos = oldYieldPos;
2484 this.awaitPos = oldAwaitPos;
2485 return this.parseParenArrowList(startPos, startLoc, exprList)
2486 }
2487
2488 if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
2489 if (spreadStart) { this.unexpected(spreadStart); }
2490 this.checkExpressionErrors(refDestructuringErrors, true);
2491 this.yieldPos = oldYieldPos || this.yieldPos;
2492 this.awaitPos = oldAwaitPos || this.awaitPos;
2493
2494 if (exprList.length > 1) {
2495 val = this.startNodeAt(innerStartPos, innerStartLoc);
2496 val.expressions = exprList;
2497 this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
2498 } else {
2499 val = exprList[0];
2500 }
2501 } else {
2502 val = this.parseParenExpression();
2503 }
2504
2505 if (this.options.preserveParens) {
2506 var par = this.startNodeAt(startPos, startLoc);
2507 par.expression = val;
2508 return this.finishNode(par, "ParenthesizedExpression")
2509 } else {
2510 return val
2511 }
2512 };
2513
2514 pp$3.parseParenItem = function(item) {
2515 return item
2516 };
2517
2518 pp$3.parseParenArrowList = function(startPos, startLoc, exprList) {
2519 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)
2520 };
2521
2522 // New's precedence is slightly tricky. It must allow its argument to
2523 // be a `[]` or dot subscript expression, but not a call — at least,
2524 // not without wrapping it in parentheses. Thus, it uses the noCalls
2525 // argument to parseSubscripts to prevent it from consuming the
2526 // argument list.
2527
2528 var empty$1 = [];
2529
2530 pp$3.parseNew = function() {
2531 if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); }
2532 var node = this.startNode();
2533 var meta = this.parseIdent(true);
2534 if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) {
2535 node.meta = meta;
2536 var containsEsc = this.containsEsc;
2537 node.property = this.parseIdent(true);
2538 if (node.property.name !== "target")
2539 { this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); }
2540 if (containsEsc)
2541 { this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); }
2542 if (!this.inNonArrowFunction())
2543 { this.raiseRecoverable(node.start, "'new.target' can only be used in functions"); }
2544 return this.finishNode(node, "MetaProperty")
2545 }
2546 var startPos = this.start, startLoc = this.startLoc, isImport = this.type === types._import;
2547 node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
2548 if (isImport && node.callee.type === "ImportExpression") {
2549 this.raise(startPos, "Cannot use new with import()");
2550 }
2551 if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); }
2552 else { node.arguments = empty$1; }
2553 return this.finishNode(node, "NewExpression")
2554 };
2555
2556 // Parse template expression.
2557
2558 pp$3.parseTemplateElement = function(ref) {
2559 var isTagged = ref.isTagged;
2560
2561 var elem = this.startNode();
2562 if (this.type === types.invalidTemplate) {
2563 if (!isTagged) {
2564 this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
2565 }
2566 elem.value = {
2567 raw: this.value,
2568 cooked: null
2569 };
2570 } else {
2571 elem.value = {
2572 raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
2573 cooked: this.value
2574 };
2575 }
2576 this.next();
2577 elem.tail = this.type === types.backQuote;
2578 return this.finishNode(elem, "TemplateElement")
2579 };
2580
2581 pp$3.parseTemplate = function(ref) {
2582 if ( ref === void 0 ) ref = {};
2583 var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;
2584
2585 var node = this.startNode();
2586 this.next();
2587 node.expressions = [];
2588 var curElt = this.parseTemplateElement({isTagged: isTagged});
2589 node.quasis = [curElt];
2590 while (!curElt.tail) {
2591 if (this.type === types.eof) { this.raise(this.pos, "Unterminated template literal"); }
2592 this.expect(types.dollarBraceL);
2593 node.expressions.push(this.parseExpression());
2594 this.expect(types.braceR);
2595 node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged}));
2596 }
2597 this.next();
2598 return this.finishNode(node, "TemplateLiteral")
2599 };
2600
2601 pp$3.isAsyncProp = function(prop) {
2602 return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
2603 (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)) &&
2604 !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
2605 };
2606
2607 // Parse an object literal or binding pattern.
2608
2609 pp$3.parseObj = function(isPattern, refDestructuringErrors) {
2610 var node = this.startNode(), first = true, propHash = {};
2611 node.properties = [];
2612 this.next();
2613 while (!this.eat(types.braceR)) {
2614 if (!first) {
2615 this.expect(types.comma);
2616 if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types.braceR)) { break }
2617 } else { first = false; }
2618
2619 var prop = this.parseProperty(isPattern, refDestructuringErrors);
2620 if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); }
2621 node.properties.push(prop);
2622 }
2623 return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
2624 };
2625
2626 pp$3.parseProperty = function(isPattern, refDestructuringErrors) {
2627 var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
2628 if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) {
2629 if (isPattern) {
2630 prop.argument = this.parseIdent(false);
2631 if (this.type === types.comma) {
2632 this.raise(this.start, "Comma is not permitted after the rest element");
2633 }
2634 return this.finishNode(prop, "RestElement")
2635 }
2636 // To disallow parenthesized identifier via `this.toAssignable()`.
2637 if (this.type === types.parenL && refDestructuringErrors) {
2638 if (refDestructuringErrors.parenthesizedAssign < 0) {
2639 refDestructuringErrors.parenthesizedAssign = this.start;
2640 }
2641 if (refDestructuringErrors.parenthesizedBind < 0) {
2642 refDestructuringErrors.parenthesizedBind = this.start;
2643 }
2644 }
2645 // Parse argument.
2646 prop.argument = this.parseMaybeAssign(false, refDestructuringErrors);
2647 // To disallow trailing comma via `this.toAssignable()`.
2648 if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
2649 refDestructuringErrors.trailingComma = this.start;
2650 }
2651 // Finish
2652 return this.finishNode(prop, "SpreadElement")
2653 }
2654 if (this.options.ecmaVersion >= 6) {
2655 prop.method = false;
2656 prop.shorthand = false;
2657 if (isPattern || refDestructuringErrors) {
2658 startPos = this.start;
2659 startLoc = this.startLoc;
2660 }
2661 if (!isPattern)
2662 { isGenerator = this.eat(types.star); }
2663 }
2664 var containsEsc = this.containsEsc;
2665 this.parsePropertyName(prop);
2666 if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
2667 isAsync = true;
2668 isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
2669 this.parsePropertyName(prop, refDestructuringErrors);
2670 } else {
2671 isAsync = false;
2672 }
2673 this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
2674 return this.finishNode(prop, "Property")
2675 };
2676
2677 pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
2678 if ((isGenerator || isAsync) && this.type === types.colon)
2679 { this.unexpected(); }
2680
2681 if (this.eat(types.colon)) {
2682 prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
2683 prop.kind = "init";
2684 } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) {
2685 if (isPattern) { this.unexpected(); }
2686 prop.kind = "init";
2687 prop.method = true;
2688 prop.value = this.parseMethod(isGenerator, isAsync);
2689 } else if (!isPattern && !containsEsc &&
2690 this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
2691 (prop.key.name === "get" || prop.key.name === "set") &&
2692 (this.type !== types.comma && this.type !== types.braceR && this.type !== types.eq)) {
2693 if (isGenerator || isAsync) { this.unexpected(); }
2694 prop.kind = prop.key.name;
2695 this.parsePropertyName(prop);
2696 prop.value = this.parseMethod(false);
2697 var paramCount = prop.kind === "get" ? 0 : 1;
2698 if (prop.value.params.length !== paramCount) {
2699 var start = prop.value.start;
2700 if (prop.kind === "get")
2701 { this.raiseRecoverable(start, "getter should have no params"); }
2702 else
2703 { this.raiseRecoverable(start, "setter should have exactly one param"); }
2704 } else {
2705 if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
2706 { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
2707 }
2708 } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
2709 if (isGenerator || isAsync) { this.unexpected(); }
2710 this.checkUnreserved(prop.key);
2711 if (prop.key.name === "await" && !this.awaitIdentPos)
2712 { this.awaitIdentPos = startPos; }
2713 prop.kind = "init";
2714 if (isPattern) {
2715 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
2716 } else if (this.type === types.eq && refDestructuringErrors) {
2717 if (refDestructuringErrors.shorthandAssign < 0)
2718 { refDestructuringErrors.shorthandAssign = this.start; }
2719 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
2720 } else {
2721 prop.value = prop.key;
2722 }
2723 prop.shorthand = true;
2724 } else { this.unexpected(); }
2725 };
2726
2727 pp$3.parsePropertyName = function(prop) {
2728 if (this.options.ecmaVersion >= 6) {
2729 if (this.eat(types.bracketL)) {
2730 prop.computed = true;
2731 prop.key = this.parseMaybeAssign();
2732 this.expect(types.bracketR);
2733 return prop.key
2734 } else {
2735 prop.computed = false;
2736 }
2737 }
2738 return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never")
2739 };
2740
2741 // Initialize empty function node.
2742
2743 pp$3.initFunction = function(node) {
2744 node.id = null;
2745 if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; }
2746 if (this.options.ecmaVersion >= 8) { node.async = false; }
2747 };
2748
2749 // Parse object or class method.
2750
2751 pp$3.parseMethod = function(isGenerator, isAsync, allowDirectSuper) {
2752 var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2753
2754 this.initFunction(node);
2755 if (this.options.ecmaVersion >= 6)
2756 { node.generator = isGenerator; }
2757 if (this.options.ecmaVersion >= 8)
2758 { node.async = !!isAsync; }
2759
2760 this.yieldPos = 0;
2761 this.awaitPos = 0;
2762 this.awaitIdentPos = 0;
2763 this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0));
2764
2765 this.expect(types.parenL);
2766 node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
2767 this.checkYieldAwaitInDefaultParams();
2768 this.parseFunctionBody(node, false, true);
2769
2770 this.yieldPos = oldYieldPos;
2771 this.awaitPos = oldAwaitPos;
2772 this.awaitIdentPos = oldAwaitIdentPos;
2773 return this.finishNode(node, "FunctionExpression")
2774 };
2775
2776 // Parse arrow function expression with given parameters.
2777
2778 pp$3.parseArrowExpression = function(node, params, isAsync) {
2779 var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
2780
2781 this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW);
2782 this.initFunction(node);
2783 if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; }
2784
2785 this.yieldPos = 0;
2786 this.awaitPos = 0;
2787 this.awaitIdentPos = 0;
2788
2789 node.params = this.toAssignableList(params, true);
2790 this.parseFunctionBody(node, true, false);
2791
2792 this.yieldPos = oldYieldPos;
2793 this.awaitPos = oldAwaitPos;
2794 this.awaitIdentPos = oldAwaitIdentPos;
2795 return this.finishNode(node, "ArrowFunctionExpression")
2796 };
2797
2798 // Parse function body and check parameters.
2799
2800 pp$3.parseFunctionBody = function(node, isArrowFunction, isMethod) {
2801 var isExpression = isArrowFunction && this.type !== types.braceL;
2802 var oldStrict = this.strict, useStrict = false;
2803
2804 if (isExpression) {
2805 node.body = this.parseMaybeAssign();
2806 node.expression = true;
2807 this.checkParams(node, false);
2808 } else {
2809 var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
2810 if (!oldStrict || nonSimple) {
2811 useStrict = this.strictDirective(this.end);
2812 // If this is a strict mode function, verify that argument names
2813 // are not repeated, and it does not try to bind the words `eval`
2814 // or `arguments`.
2815 if (useStrict && nonSimple)
2816 { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
2817 }
2818 // Start a new scope with regard to labels and the `inFunction`
2819 // flag (restore them to their old value afterwards).
2820 var oldLabels = this.labels;
2821 this.labels = [];
2822 if (useStrict) { this.strict = true; }
2823
2824 // Add the params to varDeclaredNames to ensure that an error is thrown
2825 // if a let/const declaration in the function clashes with one of the params.
2826 this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params));
2827 // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
2828 if (this.strict && node.id) { this.checkLVal(node.id, BIND_OUTSIDE); }
2829 node.body = this.parseBlock(false, undefined, useStrict && !oldStrict);
2830 node.expression = false;
2831 this.adaptDirectivePrologue(node.body.body);
2832 this.labels = oldLabels;
2833 }
2834 this.exitScope();
2835 };
2836
2837 pp$3.isSimpleParamList = function(params) {
2838 for (var i = 0, list = params; i < list.length; i += 1)
2839 {
2840 var param = list[i];
2841
2842 if (param.type !== "Identifier") { return false
2843 } }
2844 return true
2845 };
2846
2847 // Checks function params for various disallowed patterns such as using "eval"
2848 // or "arguments" and duplicate parameters.
2849
2850 pp$3.checkParams = function(node, allowDuplicates) {
2851 var nameHash = {};
2852 for (var i = 0, list = node.params; i < list.length; i += 1)
2853 {
2854 var param = list[i];
2855
2856 this.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash);
2857 }
2858 };
2859
2860 // Parses a comma-separated list of expressions, and returns them as
2861 // an array. `close` is the token type that ends the list, and
2862 // `allowEmpty` can be turned on to allow subsequent commas with
2863 // nothing in between them to be parsed as `null` (which is needed
2864 // for array literals).
2865
2866 pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
2867 var elts = [], first = true;
2868 while (!this.eat(close)) {
2869 if (!first) {
2870 this.expect(types.comma);
2871 if (allowTrailingComma && this.afterTrailingComma(close)) { break }
2872 } else { first = false; }
2873
2874 var elt = (void 0);
2875 if (allowEmpty && this.type === types.comma)
2876 { elt = null; }
2877 else if (this.type === types.ellipsis) {
2878 elt = this.parseSpread(refDestructuringErrors);
2879 if (refDestructuringErrors && this.type === types.comma && refDestructuringErrors.trailingComma < 0)
2880 { refDestructuringErrors.trailingComma = this.start; }
2881 } else {
2882 elt = this.parseMaybeAssign(false, refDestructuringErrors);
2883 }
2884 elts.push(elt);
2885 }
2886 return elts
2887 };
2888
2889 pp$3.checkUnreserved = function(ref) {
2890 var start = ref.start;
2891 var end = ref.end;
2892 var name = ref.name;
2893
2894 if (this.inGenerator && name === "yield")
2895 { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); }
2896 if (this.inAsync && name === "await")
2897 { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); }
2898 if (this.keywords.test(name))
2899 { this.raise(start, ("Unexpected keyword '" + name + "'")); }
2900 if (this.options.ecmaVersion < 6 &&
2901 this.input.slice(start, end).indexOf("\\") !== -1) { return }
2902 var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
2903 if (re.test(name)) {
2904 if (!this.inAsync && name === "await")
2905 { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); }
2906 this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved"));
2907 }
2908 };
2909
2910 // Parse the next token as an identifier. If `liberal` is true (used
2911 // when parsing properties), it will also convert keywords into
2912 // identifiers.
2913
2914 pp$3.parseIdent = function(liberal, isBinding) {
2915 var node = this.startNode();
2916 if (this.type === types.name) {
2917 node.name = this.value;
2918 } else if (this.type.keyword) {
2919 node.name = this.type.keyword;
2920
2921 // To fix https://github.com/acornjs/acorn/issues/575
2922 // `class` and `function` keywords push new context into this.context.
2923 // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
2924 // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
2925 if ((node.name === "class" || node.name === "function") &&
2926 (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
2927 this.context.pop();
2928 }
2929 } else {
2930 this.unexpected();
2931 }
2932 this.next(!!liberal);
2933 this.finishNode(node, "Identifier");
2934 if (!liberal) {
2935 this.checkUnreserved(node);
2936 if (node.name === "await" && !this.awaitIdentPos)
2937 { this.awaitIdentPos = node.start; }
2938 }
2939 return node
2940 };
2941
2942 // Parses yield expression inside generator.
2943
2944 pp$3.parseYield = function(noIn) {
2945 if (!this.yieldPos) { this.yieldPos = this.start; }
2946
2947 var node = this.startNode();
2948 this.next();
2949 if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) {
2950 node.delegate = false;
2951 node.argument = null;
2952 } else {
2953 node.delegate = this.eat(types.star);
2954 node.argument = this.parseMaybeAssign(noIn);
2955 }
2956 return this.finishNode(node, "YieldExpression")
2957 };
2958
2959 pp$3.parseAwait = function() {
2960 if (!this.awaitPos) { this.awaitPos = this.start; }
2961
2962 var node = this.startNode();
2963 this.next();
2964 node.argument = this.parseMaybeUnary(null, false);
2965 return this.finishNode(node, "AwaitExpression")
2966 };
2967
2968 var pp$4 = Parser.prototype;
2969
2970 // This function is used to raise exceptions on parse errors. It
2971 // takes an offset integer (into the current `input`) to indicate
2972 // the location of the error, attaches the position to the end
2973 // of the error message, and then raises a `SyntaxError` with that
2974 // message.
2975
2976 pp$4.raise = function(pos, message) {
2977 var loc = getLineInfo(this.input, pos);
2978 message += " (" + loc.line + ":" + loc.column + ")";
2979 var err = new SyntaxError(message);
2980 err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
2981 throw err
2982 };
2983
2984 pp$4.raiseRecoverable = pp$4.raise;
2985
2986 pp$4.curPosition = function() {
2987 if (this.options.locations) {
2988 return new Position(this.curLine, this.pos - this.lineStart)
2989 }
2990 };
2991
2992 var pp$5 = Parser.prototype;
2993
2994 var Scope = function Scope(flags) {
2995 this.flags = flags;
2996 // A list of var-declared names in the current lexical scope
2997 this.var = [];
2998 // A list of lexically-declared names in the current lexical scope
2999 this.lexical = [];
3000 // A list of lexically-declared FunctionDeclaration names in the current lexical scope
3001 this.functions = [];
3002 };
3003
3004 // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.
3005
3006 pp$5.enterScope = function(flags) {
3007 this.scopeStack.push(new Scope(flags));
3008 };
3009
3010 pp$5.exitScope = function() {
3011 this.scopeStack.pop();
3012 };
3013
3014 // The spec says:
3015 // > At the top level of a function, or script, function declarations are
3016 // > treated like var declarations rather than like lexical declarations.
3017 pp$5.treatFunctionsAsVarInScope = function(scope) {
3018 return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP)
3019 };
3020
3021 pp$5.declareName = function(name, bindingType, pos) {
3022 var redeclared = false;
3023 if (bindingType === BIND_LEXICAL) {
3024 var scope = this.currentScope();
3025 redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
3026 scope.lexical.push(name);
3027 if (this.inModule && (scope.flags & SCOPE_TOP))
3028 { delete this.undefinedExports[name]; }
3029 } else if (bindingType === BIND_SIMPLE_CATCH) {
3030 var scope$1 = this.currentScope();
3031 scope$1.lexical.push(name);
3032 } else if (bindingType === BIND_FUNCTION) {
3033 var scope$2 = this.currentScope();
3034 if (this.treatFunctionsAsVar)
3035 { redeclared = scope$2.lexical.indexOf(name) > -1; }
3036 else
3037 { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; }
3038 scope$2.functions.push(name);
3039 } else {
3040 for (var i = this.scopeStack.length - 1; i >= 0; --i) {
3041 var scope$3 = this.scopeStack[i];
3042 if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) ||
3043 !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) {
3044 redeclared = true;
3045 break
3046 }
3047 scope$3.var.push(name);
3048 if (this.inModule && (scope$3.flags & SCOPE_TOP))
3049 { delete this.undefinedExports[name]; }
3050 if (scope$3.flags & SCOPE_VAR) { break }
3051 }
3052 }
3053 if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); }
3054 };
3055
3056 pp$5.checkLocalExport = function(id) {
3057 // scope.functions must be empty as Module code is always strict.
3058 if (this.scopeStack[0].lexical.indexOf(id.name) === -1 &&
3059 this.scopeStack[0].var.indexOf(id.name) === -1) {
3060 this.undefinedExports[id.name] = id;
3061 }
3062 };
3063
3064 pp$5.currentScope = function() {
3065 return this.scopeStack[this.scopeStack.length - 1]
3066 };
3067
3068 pp$5.currentVarScope = function() {
3069 for (var i = this.scopeStack.length - 1;; i--) {
3070 var scope = this.scopeStack[i];
3071 if (scope.flags & SCOPE_VAR) { return scope }
3072 }
3073 };
3074
3075 // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
3076 pp$5.currentThisScope = function() {
3077 for (var i = this.scopeStack.length - 1;; i--) {
3078 var scope = this.scopeStack[i];
3079 if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) { return scope }
3080 }
3081 };
3082
3083 var Node = function Node(parser, pos, loc) {
3084 this.type = "";
3085 this.start = pos;
3086 this.end = 0;
3087 if (parser.options.locations)
3088 { this.loc = new SourceLocation(parser, loc); }
3089 if (parser.options.directSourceFile)
3090 { this.sourceFile = parser.options.directSourceFile; }
3091 if (parser.options.ranges)
3092 { this.range = [pos, 0]; }
3093 };
3094
3095 // Start an AST node, attaching a start offset.
3096
3097 var pp$6 = Parser.prototype;
3098
3099 pp$6.startNode = function() {
3100 return new Node(this, this.start, this.startLoc)
3101 };
3102
3103 pp$6.startNodeAt = function(pos, loc) {
3104 return new Node(this, pos, loc)
3105 };
3106
3107 // Finish an AST node, adding `type` and `end` properties.
3108
3109 function finishNodeAt(node, type, pos, loc) {
3110 node.type = type;
3111 node.end = pos;
3112 if (this.options.locations)
3113 { node.loc.end = loc; }
3114 if (this.options.ranges)
3115 { node.range[1] = pos; }
3116 return node
3117 }
3118
3119 pp$6.finishNode = function(node, type) {
3120 return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
3121 };
3122
3123 // Finish node at given position
3124
3125 pp$6.finishNodeAt = function(node, type, pos, loc) {
3126 return finishNodeAt.call(this, node, type, pos, loc)
3127 };
3128
3129 // The algorithm used to determine whether a regexp can appear at a
3130
3131 var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
3132 this.token = token;
3133 this.isExpr = !!isExpr;
3134 this.preserveSpace = !!preserveSpace;
3135 this.override = override;
3136 this.generator = !!generator;
3137 };
3138
3139 var types$1 = {
3140 b_stat: new TokContext("{", false),
3141 b_expr: new TokContext("{", true),
3142 b_tmpl: new TokContext("${", false),
3143 p_stat: new TokContext("(", false),
3144 p_expr: new TokContext("(", true),
3145 q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
3146 f_stat: new TokContext("function", false),
3147 f_expr: new TokContext("function", true),
3148 f_expr_gen: new TokContext("function", true, false, null, true),
3149 f_gen: new TokContext("function", false, false, null, true)
3150 };
3151
3152 var pp$7 = Parser.prototype;
3153
3154 pp$7.initialContext = function() {
3155 return [types$1.b_stat]
3156 };
3157
3158 pp$7.braceIsBlock = function(prevType) {
3159 var parent = this.curContext();
3160 if (parent === types$1.f_expr || parent === types$1.f_stat)
3161 { return true }
3162 if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr))
3163 { return !parent.isExpr }
3164
3165 // The check for `tt.name && exprAllowed` detects whether we are
3166 // after a `yield` or `of` construct. See the `updateContext` for
3167 // `tt.name`.
3168 if (prevType === types._return || prevType === types.name && this.exprAllowed)
3169 { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
3170 if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow)
3171 { return true }
3172 if (prevType === types.braceL)
3173 { return parent === types$1.b_stat }
3174 if (prevType === types._var || prevType === types._const || prevType === types.name)
3175 { return false }
3176 return !this.exprAllowed
3177 };
3178
3179 pp$7.inGeneratorContext = function() {
3180 for (var i = this.context.length - 1; i >= 1; i--) {
3181 var context = this.context[i];
3182 if (context.token === "function")
3183 { return context.generator }
3184 }
3185 return false
3186 };
3187
3188 pp$7.updateContext = function(prevType) {
3189 var update, type = this.type;
3190 if (type.keyword && prevType === types.dot)
3191 { this.exprAllowed = false; }
3192 else if (update = type.updateContext)
3193 { update.call(this, prevType); }
3194 else
3195 { this.exprAllowed = type.beforeExpr; }
3196 };
3197
3198 // Token-specific context update code
3199
3200 types.parenR.updateContext = types.braceR.updateContext = function() {
3201 if (this.context.length === 1) {
3202 this.exprAllowed = true;
3203 return
3204 }
3205 var out = this.context.pop();
3206 if (out === types$1.b_stat && this.curContext().token === "function") {
3207 out = this.context.pop();
3208 }
3209 this.exprAllowed = !out.isExpr;
3210 };
3211
3212 types.braceL.updateContext = function(prevType) {
3213 this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr);
3214 this.exprAllowed = true;
3215 };
3216
3217 types.dollarBraceL.updateContext = function() {
3218 this.context.push(types$1.b_tmpl);
3219 this.exprAllowed = true;
3220 };
3221
3222 types.parenL.updateContext = function(prevType) {
3223 var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while;
3224 this.context.push(statementParens ? types$1.p_stat : types$1.p_expr);
3225 this.exprAllowed = true;
3226 };
3227
3228 types.incDec.updateContext = function() {
3229 // tokExprAllowed stays unchanged
3230 };
3231
3232 types._function.updateContext = types._class.updateContext = function(prevType) {
3233 if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else &&
3234 !(prevType === types._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) &&
3235 !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat))
3236 { this.context.push(types$1.f_expr); }
3237 else
3238 { this.context.push(types$1.f_stat); }
3239 this.exprAllowed = false;
3240 };
3241
3242 types.backQuote.updateContext = function() {
3243 if (this.curContext() === types$1.q_tmpl)
3244 { this.context.pop(); }
3245 else
3246 { this.context.push(types$1.q_tmpl); }
3247 this.exprAllowed = false;
3248 };
3249
3250 types.star.updateContext = function(prevType) {
3251 if (prevType === types._function) {
3252 var index = this.context.length - 1;
3253 if (this.context[index] === types$1.f_expr)
3254 { this.context[index] = types$1.f_expr_gen; }
3255 else
3256 { this.context[index] = types$1.f_gen; }
3257 }
3258 this.exprAllowed = true;
3259 };
3260
3261 types.name.updateContext = function(prevType) {
3262 var allowed = false;
3263 if (this.options.ecmaVersion >= 6 && prevType !== types.dot) {
3264 if (this.value === "of" && !this.exprAllowed ||
3265 this.value === "yield" && this.inGeneratorContext())
3266 { allowed = true; }
3267 }
3268 this.exprAllowed = allowed;
3269 };
3270
3271 // This file contains Unicode properties extracted from the ECMAScript
3272 // specification. The lists are extracted like so:
3273 // $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText)
3274
3275 // #table-binary-unicode-properties
3276 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";
3277 var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic";
3278 var ecma11BinaryProperties = ecma10BinaryProperties;
3279 var unicodeBinaryProperties = {
3280 9: ecma9BinaryProperties,
3281 10: ecma10BinaryProperties,
3282 11: ecma11BinaryProperties
3283 };
3284
3285 // #table-unicode-general-category-values
3286 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";
3287
3288 // #table-unicode-script-values
3289 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";
3290 var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd";
3291 var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho";
3292 var unicodeScriptValues = {
3293 9: ecma9ScriptValues,
3294 10: ecma10ScriptValues,
3295 11: ecma11ScriptValues
3296 };
3297
3298 var data = {};
3299 function buildUnicodeData(ecmaVersion) {
3300 var d = data[ecmaVersion] = {
3301 binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues),
3302 nonBinary: {
3303 General_Category: wordsRegexp(unicodeGeneralCategoryValues),
3304 Script: wordsRegexp(unicodeScriptValues[ecmaVersion])
3305 }
3306 };
3307 d.nonBinary.Script_Extensions = d.nonBinary.Script;
3308
3309 d.nonBinary.gc = d.nonBinary.General_Category;
3310 d.nonBinary.sc = d.nonBinary.Script;
3311 d.nonBinary.scx = d.nonBinary.Script_Extensions;
3312 }
3313 buildUnicodeData(9);
3314 buildUnicodeData(10);
3315 buildUnicodeData(11);
3316
3317 var pp$8 = Parser.prototype;
3318
3319 var RegExpValidationState = function RegExpValidationState(parser) {
3320 this.parser = parser;
3321 this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "");
3322 this.unicodeProperties = data[parser.options.ecmaVersion >= 11 ? 11 : parser.options.ecmaVersion];
3323 this.source = "";
3324 this.flags = "";
3325 this.start = 0;
3326 this.switchU = false;
3327 this.switchN = false;
3328 this.pos = 0;
3329 this.lastIntValue = 0;
3330 this.lastStringValue = "";
3331 this.lastAssertionIsQuantifiable = false;
3332 this.numCapturingParens = 0;
3333 this.maxBackReference = 0;
3334 this.groupNames = [];
3335 this.backReferenceNames = [];
3336 };
3337
3338 RegExpValidationState.prototype.reset = function reset (start, pattern, flags) {
3339 var unicode = flags.indexOf("u") !== -1;
3340 this.start = start | 0;
3341 this.source = pattern + "";
3342 this.flags = flags;
3343 this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
3344 this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
3345 };
3346
3347 RegExpValidationState.prototype.raise = function raise (message) {
3348 this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message));
3349 };
3350
3351 // If u flag is given, this returns the code point at the index (it combines a surrogate pair).
3352 // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
3353 RegExpValidationState.prototype.at = function at (i, forceU) {
3354 if ( forceU === void 0 ) forceU = false;
3355
3356 var s = this.source;
3357 var l = s.length;
3358 if (i >= l) {
3359 return -1
3360 }
3361 var c = s.charCodeAt(i);
3362 if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
3363 return c
3364 }
3365 var next = s.charCodeAt(i + 1);
3366 return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c
3367 };
3368
3369 RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) {
3370 if ( forceU === void 0 ) forceU = false;
3371
3372 var s = this.source;
3373 var l = s.length;
3374 if (i >= l) {
3375 return l
3376 }
3377 var c = s.charCodeAt(i), next;
3378 if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l ||
3379 (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) {
3380 return i + 1
3381 }
3382 return i + 2
3383 };
3384
3385 RegExpValidationState.prototype.current = function current (forceU) {
3386 if ( forceU === void 0 ) forceU = false;
3387
3388 return this.at(this.pos, forceU)
3389 };
3390
3391 RegExpValidationState.prototype.lookahead = function lookahead (forceU) {
3392 if ( forceU === void 0 ) forceU = false;
3393
3394 return this.at(this.nextIndex(this.pos, forceU), forceU)
3395 };
3396
3397 RegExpValidationState.prototype.advance = function advance (forceU) {
3398 if ( forceU === void 0 ) forceU = false;
3399
3400 this.pos = this.nextIndex(this.pos, forceU);
3401 };
3402
3403 RegExpValidationState.prototype.eat = function eat (ch, forceU) {
3404 if ( forceU === void 0 ) forceU = false;
3405
3406 if (this.current(forceU) === ch) {
3407 this.advance(forceU);
3408 return true
3409 }
3410 return false
3411 };
3412
3413 function codePointToString(ch) {
3414 if (ch <= 0xFFFF) { return String.fromCharCode(ch) }
3415 ch -= 0x10000;
3416 return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00)
3417 }
3418
3419 /**
3420 * Validate the flags part of a given RegExpLiteral.
3421 *
3422 * @param {RegExpValidationState} state The state to validate RegExp.
3423 * @returns {void}
3424 */
3425 pp$8.validateRegExpFlags = function(state) {
3426 var validFlags = state.validFlags;
3427 var flags = state.flags;
3428
3429 for (var i = 0; i < flags.length; i++) {
3430 var flag = flags.charAt(i);
3431 if (validFlags.indexOf(flag) === -1) {
3432 this.raise(state.start, "Invalid regular expression flag");
3433 }
3434 if (flags.indexOf(flag, i + 1) > -1) {
3435 this.raise(state.start, "Duplicate regular expression flag");
3436 }
3437 }
3438 };
3439
3440 /**
3441 * Validate the pattern part of a given RegExpLiteral.
3442 *
3443 * @param {RegExpValidationState} state The state to validate RegExp.
3444 * @returns {void}
3445 */
3446 pp$8.validateRegExpPattern = function(state) {
3447 this.regexp_pattern(state);
3448
3449 // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
3450 // parsing contains a |GroupName|, reparse with the goal symbol
3451 // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
3452 // exception if _P_ did not conform to the grammar, if any elements of _P_
3453 // were not matched by the parse, or if any Early Error conditions exist.
3454 if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) {
3455 state.switchN = true;
3456 this.regexp_pattern(state);
3457 }
3458 };
3459
3460 // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
3461 pp$8.regexp_pattern = function(state) {
3462 state.pos = 0;
3463 state.lastIntValue = 0;
3464 state.lastStringValue = "";
3465 state.lastAssertionIsQuantifiable = false;
3466 state.numCapturingParens = 0;
3467 state.maxBackReference = 0;
3468 state.groupNames.length = 0;
3469 state.backReferenceNames.length = 0;
3470
3471 this.regexp_disjunction(state);
3472
3473 if (state.pos !== state.source.length) {
3474 // Make the same messages as V8.
3475 if (state.eat(0x29 /* ) */)) {
3476 state.raise("Unmatched ')'");
3477 }
3478 if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) {
3479 state.raise("Lone quantifier brackets");
3480 }
3481 }
3482 if (state.maxBackReference > state.numCapturingParens) {
3483 state.raise("Invalid escape");
3484 }
3485 for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) {
3486 var name = list[i];
3487
3488 if (state.groupNames.indexOf(name) === -1) {
3489 state.raise("Invalid named capture referenced");
3490 }
3491 }
3492 };
3493
3494 // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
3495 pp$8.regexp_disjunction = function(state) {
3496 this.regexp_alternative(state);
3497 while (state.eat(0x7C /* | */)) {
3498 this.regexp_alternative(state);
3499 }
3500
3501 // Make the same message as V8.
3502 if (this.regexp_eatQuantifier(state, true)) {
3503 state.raise("Nothing to repeat");
3504 }
3505 if (state.eat(0x7B /* { */)) {
3506 state.raise("Lone quantifier brackets");
3507 }
3508 };
3509
3510 // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
3511 pp$8.regexp_alternative = function(state) {
3512 while (state.pos < state.source.length && this.regexp_eatTerm(state))
3513 { }
3514 };
3515
3516 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
3517 pp$8.regexp_eatTerm = function(state) {
3518 if (this.regexp_eatAssertion(state)) {
3519 // Handle `QuantifiableAssertion Quantifier` alternative.
3520 // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
3521 // is a QuantifiableAssertion.
3522 if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
3523 // Make the same message as V8.
3524 if (state.switchU) {
3525 state.raise("Invalid quantifier");
3526 }
3527 }
3528 return true
3529 }
3530
3531 if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
3532 this.regexp_eatQuantifier(state);
3533 return true
3534 }
3535
3536 return false
3537 };
3538
3539 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
3540 pp$8.regexp_eatAssertion = function(state) {
3541 var start = state.pos;
3542 state.lastAssertionIsQuantifiable = false;
3543
3544 // ^, $
3545 if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) {
3546 return true
3547 }
3548
3549 // \b \B
3550 if (state.eat(0x5C /* \ */)) {
3551 if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) {
3552 return true
3553 }
3554 state.pos = start;
3555 }
3556
3557 // Lookahead / Lookbehind
3558 if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) {
3559 var lookbehind = false;
3560 if (this.options.ecmaVersion >= 9) {
3561 lookbehind = state.eat(0x3C /* < */);
3562 }
3563 if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) {
3564 this.regexp_disjunction(state);
3565 if (!state.eat(0x29 /* ) */)) {
3566 state.raise("Unterminated group");
3567 }
3568 state.lastAssertionIsQuantifiable = !lookbehind;
3569 return true
3570 }
3571 }
3572
3573 state.pos = start;
3574 return false
3575 };
3576
3577 // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
3578 pp$8.regexp_eatQuantifier = function(state, noError) {
3579 if ( noError === void 0 ) noError = false;
3580
3581 if (this.regexp_eatQuantifierPrefix(state, noError)) {
3582 state.eat(0x3F /* ? */);
3583 return true
3584 }
3585 return false
3586 };
3587
3588 // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
3589 pp$8.regexp_eatQuantifierPrefix = function(state, noError) {
3590 return (
3591 state.eat(0x2A /* * */) ||
3592 state.eat(0x2B /* + */) ||
3593 state.eat(0x3F /* ? */) ||
3594 this.regexp_eatBracedQuantifier(state, noError)
3595 )
3596 };
3597 pp$8.regexp_eatBracedQuantifier = function(state, noError) {
3598 var start = state.pos;
3599 if (state.eat(0x7B /* { */)) {
3600 var min = 0, max = -1;
3601 if (this.regexp_eatDecimalDigits(state)) {
3602 min = state.lastIntValue;
3603 if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) {
3604 max = state.lastIntValue;
3605 }
3606 if (state.eat(0x7D /* } */)) {
3607 // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
3608 if (max !== -1 && max < min && !noError) {
3609 state.raise("numbers out of order in {} quantifier");
3610 }
3611 return true
3612 }
3613 }
3614 if (state.switchU && !noError) {
3615 state.raise("Incomplete quantifier");
3616 }
3617 state.pos = start;
3618 }
3619 return false
3620 };
3621
3622 // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
3623 pp$8.regexp_eatAtom = function(state) {
3624 return (
3625 this.regexp_eatPatternCharacters(state) ||
3626 state.eat(0x2E /* . */) ||
3627 this.regexp_eatReverseSolidusAtomEscape(state) ||
3628 this.regexp_eatCharacterClass(state) ||
3629 this.regexp_eatUncapturingGroup(state) ||
3630 this.regexp_eatCapturingGroup(state)
3631 )
3632 };
3633 pp$8.regexp_eatReverseSolidusAtomEscape = function(state) {
3634 var start = state.pos;
3635 if (state.eat(0x5C /* \ */)) {
3636 if (this.regexp_eatAtomEscape(state)) {
3637 return true
3638 }
3639 state.pos = start;
3640 }
3641 return false
3642 };
3643 pp$8.regexp_eatUncapturingGroup = function(state) {
3644 var start = state.pos;
3645 if (state.eat(0x28 /* ( */)) {
3646 if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) {
3647 this.regexp_disjunction(state);
3648 if (state.eat(0x29 /* ) */)) {
3649 return true
3650 }
3651 state.raise("Unterminated group");
3652 }
3653 state.pos = start;
3654 }
3655 return false
3656 };
3657 pp$8.regexp_eatCapturingGroup = function(state) {
3658 if (state.eat(0x28 /* ( */)) {
3659 if (this.options.ecmaVersion >= 9) {
3660 this.regexp_groupSpecifier(state);
3661 } else if (state.current() === 0x3F /* ? */) {
3662 state.raise("Invalid group");
3663 }
3664 this.regexp_disjunction(state);
3665 if (state.eat(0x29 /* ) */)) {
3666 state.numCapturingParens += 1;
3667 return true
3668 }
3669 state.raise("Unterminated group");
3670 }
3671 return false
3672 };
3673
3674 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
3675 pp$8.regexp_eatExtendedAtom = function(state) {
3676 return (
3677 state.eat(0x2E /* . */) ||
3678 this.regexp_eatReverseSolidusAtomEscape(state) ||
3679 this.regexp_eatCharacterClass(state) ||
3680 this.regexp_eatUncapturingGroup(state) ||
3681 this.regexp_eatCapturingGroup(state) ||
3682 this.regexp_eatInvalidBracedQuantifier(state) ||
3683 this.regexp_eatExtendedPatternCharacter(state)
3684 )
3685 };
3686
3687 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
3688 pp$8.regexp_eatInvalidBracedQuantifier = function(state) {
3689 if (this.regexp_eatBracedQuantifier(state, true)) {
3690 state.raise("Nothing to repeat");
3691 }
3692 return false
3693 };
3694
3695 // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
3696 pp$8.regexp_eatSyntaxCharacter = function(state) {
3697 var ch = state.current();
3698 if (isSyntaxCharacter(ch)) {
3699 state.lastIntValue = ch;
3700 state.advance();
3701 return true
3702 }
3703 return false
3704 };
3705 function isSyntaxCharacter(ch) {
3706 return (
3707 ch === 0x24 /* $ */ ||
3708 ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ ||
3709 ch === 0x2E /* . */ ||
3710 ch === 0x3F /* ? */ ||
3711 ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ ||
3712 ch >= 0x7B /* { */ && ch <= 0x7D /* } */
3713 )
3714 }
3715
3716 // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
3717 // But eat eager.
3718 pp$8.regexp_eatPatternCharacters = function(state) {
3719 var start = state.pos;
3720 var ch = 0;
3721 while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
3722 state.advance();
3723 }
3724 return state.pos !== start
3725 };
3726
3727 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
3728 pp$8.regexp_eatExtendedPatternCharacter = function(state) {
3729 var ch = state.current();
3730 if (
3731 ch !== -1 &&
3732 ch !== 0x24 /* $ */ &&
3733 !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) &&
3734 ch !== 0x2E /* . */ &&
3735 ch !== 0x3F /* ? */ &&
3736 ch !== 0x5B /* [ */ &&
3737 ch !== 0x5E /* ^ */ &&
3738 ch !== 0x7C /* | */
3739 ) {
3740 state.advance();
3741 return true
3742 }
3743 return false
3744 };
3745
3746 // GroupSpecifier ::
3747 // [empty]
3748 // `?` GroupName
3749 pp$8.regexp_groupSpecifier = function(state) {
3750 if (state.eat(0x3F /* ? */)) {
3751 if (this.regexp_eatGroupName(state)) {
3752 if (state.groupNames.indexOf(state.lastStringValue) !== -1) {
3753 state.raise("Duplicate capture group name");
3754 }
3755 state.groupNames.push(state.lastStringValue);
3756 return
3757 }
3758 state.raise("Invalid group");
3759 }
3760 };
3761
3762 // GroupName ::
3763 // `<` RegExpIdentifierName `>`
3764 // Note: this updates `state.lastStringValue` property with the eaten name.
3765 pp$8.regexp_eatGroupName = function(state) {
3766 state.lastStringValue = "";
3767 if (state.eat(0x3C /* < */)) {
3768 if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) {
3769 return true
3770 }
3771 state.raise("Invalid capture group name");
3772 }
3773 return false
3774 };
3775
3776 // RegExpIdentifierName ::
3777 // RegExpIdentifierStart
3778 // RegExpIdentifierName RegExpIdentifierPart
3779 // Note: this updates `state.lastStringValue` property with the eaten name.
3780 pp$8.regexp_eatRegExpIdentifierName = function(state) {
3781 state.lastStringValue = "";
3782 if (this.regexp_eatRegExpIdentifierStart(state)) {
3783 state.lastStringValue += codePointToString(state.lastIntValue);
3784 while (this.regexp_eatRegExpIdentifierPart(state)) {
3785 state.lastStringValue += codePointToString(state.lastIntValue);
3786 }
3787 return true
3788 }
3789 return false
3790 };
3791
3792 // RegExpIdentifierStart ::
3793 // UnicodeIDStart
3794 // `$`
3795 // `_`
3796 // `\` RegExpUnicodeEscapeSequence[+U]
3797 pp$8.regexp_eatRegExpIdentifierStart = function(state) {
3798 var start = state.pos;
3799 var forceU = this.options.ecmaVersion >= 11;
3800 var ch = state.current(forceU);
3801 state.advance(forceU);
3802
3803 if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
3804 ch = state.lastIntValue;
3805 }
3806 if (isRegExpIdentifierStart(ch)) {
3807 state.lastIntValue = ch;
3808 return true
3809 }
3810
3811 state.pos = start;
3812 return false
3813 };
3814 function isRegExpIdentifierStart(ch) {
3815 return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */
3816 }
3817
3818 // RegExpIdentifierPart ::
3819 // UnicodeIDContinue
3820 // `$`
3821 // `_`
3822 // `\` RegExpUnicodeEscapeSequence[+U]
3823 // <ZWNJ>
3824 // <ZWJ>
3825 pp$8.regexp_eatRegExpIdentifierPart = function(state) {
3826 var start = state.pos;
3827 var forceU = this.options.ecmaVersion >= 11;
3828 var ch = state.current(forceU);
3829 state.advance(forceU);
3830
3831 if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
3832 ch = state.lastIntValue;
3833 }
3834 if (isRegExpIdentifierPart(ch)) {
3835 state.lastIntValue = ch;
3836 return true
3837 }
3838
3839 state.pos = start;
3840 return false
3841 };
3842 function isRegExpIdentifierPart(ch) {
3843 return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */
3844 }
3845
3846 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
3847 pp$8.regexp_eatAtomEscape = function(state) {
3848 if (
3849 this.regexp_eatBackReference(state) ||
3850 this.regexp_eatCharacterClassEscape(state) ||
3851 this.regexp_eatCharacterEscape(state) ||
3852 (state.switchN && this.regexp_eatKGroupName(state))
3853 ) {
3854 return true
3855 }
3856 if (state.switchU) {
3857 // Make the same message as V8.
3858 if (state.current() === 0x63 /* c */) {
3859 state.raise("Invalid unicode escape");
3860 }
3861 state.raise("Invalid escape");
3862 }
3863 return false
3864 };
3865 pp$8.regexp_eatBackReference = function(state) {
3866 var start = state.pos;
3867 if (this.regexp_eatDecimalEscape(state)) {
3868 var n = state.lastIntValue;
3869 if (state.switchU) {
3870 // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
3871 if (n > state.maxBackReference) {
3872 state.maxBackReference = n;
3873 }
3874 return true
3875 }
3876 if (n <= state.numCapturingParens) {
3877 return true
3878 }
3879 state.pos = start;
3880 }
3881 return false
3882 };
3883 pp$8.regexp_eatKGroupName = function(state) {
3884 if (state.eat(0x6B /* k */)) {
3885 if (this.regexp_eatGroupName(state)) {
3886 state.backReferenceNames.push(state.lastStringValue);
3887 return true
3888 }
3889 state.raise("Invalid named reference");
3890 }
3891 return false
3892 };
3893
3894 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
3895 pp$8.regexp_eatCharacterEscape = function(state) {
3896 return (
3897 this.regexp_eatControlEscape(state) ||
3898 this.regexp_eatCControlLetter(state) ||
3899 this.regexp_eatZero(state) ||
3900 this.regexp_eatHexEscapeSequence(state) ||
3901 this.regexp_eatRegExpUnicodeEscapeSequence(state, false) ||
3902 (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) ||
3903 this.regexp_eatIdentityEscape(state)
3904 )
3905 };
3906 pp$8.regexp_eatCControlLetter = function(state) {
3907 var start = state.pos;
3908 if (state.eat(0x63 /* c */)) {
3909 if (this.regexp_eatControlLetter(state)) {
3910 return true
3911 }
3912 state.pos = start;
3913 }
3914 return false
3915 };
3916 pp$8.regexp_eatZero = function(state) {
3917 if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) {
3918 state.lastIntValue = 0;
3919 state.advance();
3920 return true
3921 }
3922 return false
3923 };
3924
3925 // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
3926 pp$8.regexp_eatControlEscape = function(state) {
3927 var ch = state.current();
3928 if (ch === 0x74 /* t */) {
3929 state.lastIntValue = 0x09; /* \t */
3930 state.advance();
3931 return true
3932 }
3933 if (ch === 0x6E /* n */) {
3934 state.lastIntValue = 0x0A; /* \n */
3935 state.advance();
3936 return true
3937 }
3938 if (ch === 0x76 /* v */) {
3939 state.lastIntValue = 0x0B; /* \v */
3940 state.advance();
3941 return true
3942 }
3943 if (ch === 0x66 /* f */) {
3944 state.lastIntValue = 0x0C; /* \f */
3945 state.advance();
3946 return true
3947 }
3948 if (ch === 0x72 /* r */) {
3949 state.lastIntValue = 0x0D; /* \r */
3950 state.advance();
3951 return true
3952 }
3953 return false
3954 };
3955
3956 // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
3957 pp$8.regexp_eatControlLetter = function(state) {
3958 var ch = state.current();
3959 if (isControlLetter(ch)) {
3960 state.lastIntValue = ch % 0x20;
3961 state.advance();
3962 return true
3963 }
3964 return false
3965 };
3966 function isControlLetter(ch) {
3967 return (
3968 (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) ||
3969 (ch >= 0x61 /* a */ && ch <= 0x7A /* z */)
3970 )
3971 }
3972
3973 // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
3974 pp$8.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) {
3975 if ( forceU === void 0 ) forceU = false;
3976
3977 var start = state.pos;
3978 var switchU = forceU || state.switchU;
3979
3980 if (state.eat(0x75 /* u */)) {
3981 if (this.regexp_eatFixedHexDigits(state, 4)) {
3982 var lead = state.lastIntValue;
3983 if (switchU && lead >= 0xD800 && lead <= 0xDBFF) {
3984 var leadSurrogateEnd = state.pos;
3985 if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) {
3986 var trail = state.lastIntValue;
3987 if (trail >= 0xDC00 && trail <= 0xDFFF) {
3988 state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
3989 return true
3990 }
3991 }
3992 state.pos = leadSurrogateEnd;
3993 state.lastIntValue = lead;
3994 }
3995 return true
3996 }
3997 if (
3998 switchU &&
3999 state.eat(0x7B /* { */) &&
4000 this.regexp_eatHexDigits(state) &&
4001 state.eat(0x7D /* } */) &&
4002 isValidUnicode(state.lastIntValue)
4003 ) {
4004 return true
4005 }
4006 if (switchU) {
4007 state.raise("Invalid unicode escape");
4008 }
4009 state.pos = start;
4010 }
4011
4012 return false
4013 };
4014 function isValidUnicode(ch) {
4015 return ch >= 0 && ch <= 0x10FFFF
4016 }
4017
4018 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
4019 pp$8.regexp_eatIdentityEscape = function(state) {
4020 if (state.switchU) {
4021 if (this.regexp_eatSyntaxCharacter(state)) {
4022 return true
4023 }
4024 if (state.eat(0x2F /* / */)) {
4025 state.lastIntValue = 0x2F; /* / */
4026 return true
4027 }
4028 return false
4029 }
4030
4031 var ch = state.current();
4032 if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) {
4033 state.lastIntValue = ch;
4034 state.advance();
4035 return true
4036 }
4037
4038 return false
4039 };
4040
4041 // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
4042 pp$8.regexp_eatDecimalEscape = function(state) {
4043 state.lastIntValue = 0;
4044 var ch = state.current();
4045 if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) {
4046 do {
4047 state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
4048 state.advance();
4049 } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */)
4050 return true
4051 }
4052 return false
4053 };
4054
4055 // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
4056 pp$8.regexp_eatCharacterClassEscape = function(state) {
4057 var ch = state.current();
4058
4059 if (isCharacterClassEscape(ch)) {
4060 state.lastIntValue = -1;
4061 state.advance();
4062 return true
4063 }
4064
4065 if (
4066 state.switchU &&
4067 this.options.ecmaVersion >= 9 &&
4068 (ch === 0x50 /* P */ || ch === 0x70 /* p */)
4069 ) {
4070 state.lastIntValue = -1;
4071 state.advance();
4072 if (
4073 state.eat(0x7B /* { */) &&
4074 this.regexp_eatUnicodePropertyValueExpression(state) &&
4075 state.eat(0x7D /* } */)
4076 ) {
4077 return true
4078 }
4079 state.raise("Invalid property name");
4080 }
4081
4082 return false
4083 };
4084 function isCharacterClassEscape(ch) {
4085 return (
4086 ch === 0x64 /* d */ ||
4087 ch === 0x44 /* D */ ||
4088 ch === 0x73 /* s */ ||
4089 ch === 0x53 /* S */ ||
4090 ch === 0x77 /* w */ ||
4091 ch === 0x57 /* W */
4092 )
4093 }
4094
4095 // UnicodePropertyValueExpression ::
4096 // UnicodePropertyName `=` UnicodePropertyValue
4097 // LoneUnicodePropertyNameOrValue
4098 pp$8.regexp_eatUnicodePropertyValueExpression = function(state) {
4099 var start = state.pos;
4100
4101 // UnicodePropertyName `=` UnicodePropertyValue
4102 if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) {
4103 var name = state.lastStringValue;
4104 if (this.regexp_eatUnicodePropertyValue(state)) {
4105 var value = state.lastStringValue;
4106 this.regexp_validateUnicodePropertyNameAndValue(state, name, value);
4107 return true
4108 }
4109 }
4110 state.pos = start;
4111
4112 // LoneUnicodePropertyNameOrValue
4113 if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
4114 var nameOrValue = state.lastStringValue;
4115 this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue);
4116 return true
4117 }
4118 return false
4119 };
4120 pp$8.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
4121 if (!has(state.unicodeProperties.nonBinary, name))
4122 { state.raise("Invalid property name"); }
4123 if (!state.unicodeProperties.nonBinary[name].test(value))
4124 { state.raise("Invalid property value"); }
4125 };
4126 pp$8.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
4127 if (!state.unicodeProperties.binary.test(nameOrValue))
4128 { state.raise("Invalid property name"); }
4129 };
4130
4131 // UnicodePropertyName ::
4132 // UnicodePropertyNameCharacters
4133 pp$8.regexp_eatUnicodePropertyName = function(state) {
4134 var ch = 0;
4135 state.lastStringValue = "";
4136 while (isUnicodePropertyNameCharacter(ch = state.current())) {
4137 state.lastStringValue += codePointToString(ch);
4138 state.advance();
4139 }
4140 return state.lastStringValue !== ""
4141 };
4142 function isUnicodePropertyNameCharacter(ch) {
4143 return isControlLetter(ch) || ch === 0x5F /* _ */
4144 }
4145
4146 // UnicodePropertyValue ::
4147 // UnicodePropertyValueCharacters
4148 pp$8.regexp_eatUnicodePropertyValue = function(state) {
4149 var ch = 0;
4150 state.lastStringValue = "";
4151 while (isUnicodePropertyValueCharacter(ch = state.current())) {
4152 state.lastStringValue += codePointToString(ch);
4153 state.advance();
4154 }
4155 return state.lastStringValue !== ""
4156 };
4157 function isUnicodePropertyValueCharacter(ch) {
4158 return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch)
4159 }
4160
4161 // LoneUnicodePropertyNameOrValue ::
4162 // UnicodePropertyValueCharacters
4163 pp$8.regexp_eatLoneUnicodePropertyNameOrValue = function(state) {
4164 return this.regexp_eatUnicodePropertyValue(state)
4165 };
4166
4167 // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
4168 pp$8.regexp_eatCharacterClass = function(state) {
4169 if (state.eat(0x5B /* [ */)) {
4170 state.eat(0x5E /* ^ */);
4171 this.regexp_classRanges(state);
4172 if (state.eat(0x5D /* ] */)) {
4173 return true
4174 }
4175 // Unreachable since it threw "unterminated regular expression" error before.
4176 state.raise("Unterminated character class");
4177 }
4178 return false
4179 };
4180
4181 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
4182 // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
4183 // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
4184 pp$8.regexp_classRanges = function(state) {
4185 while (this.regexp_eatClassAtom(state)) {
4186 var left = state.lastIntValue;
4187 if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) {
4188 var right = state.lastIntValue;
4189 if (state.switchU && (left === -1 || right === -1)) {
4190 state.raise("Invalid character class");
4191 }
4192 if (left !== -1 && right !== -1 && left > right) {
4193 state.raise("Range out of order in character class");
4194 }
4195 }
4196 }
4197 };
4198
4199 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
4200 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
4201 pp$8.regexp_eatClassAtom = function(state) {
4202 var start = state.pos;
4203
4204 if (state.eat(0x5C /* \ */)) {
4205 if (this.regexp_eatClassEscape(state)) {
4206 return true
4207 }
4208 if (state.switchU) {
4209 // Make the same message as V8.
4210 var ch$1 = state.current();
4211 if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
4212 state.raise("Invalid class escape");
4213 }
4214 state.raise("Invalid escape");
4215 }
4216 state.pos = start;
4217 }
4218
4219 var ch = state.current();
4220 if (ch !== 0x5D /* ] */) {
4221 state.lastIntValue = ch;
4222 state.advance();
4223 return true
4224 }
4225
4226 return false
4227 };
4228
4229 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
4230 pp$8.regexp_eatClassEscape = function(state) {
4231 var start = state.pos;
4232
4233 if (state.eat(0x62 /* b */)) {
4234 state.lastIntValue = 0x08; /* <BS> */
4235 return true
4236 }
4237
4238 if (state.switchU && state.eat(0x2D /* - */)) {
4239 state.lastIntValue = 0x2D; /* - */
4240 return true
4241 }
4242
4243 if (!state.switchU && state.eat(0x63 /* c */)) {
4244 if (this.regexp_eatClassControlLetter(state)) {
4245 return true
4246 }
4247 state.pos = start;
4248 }
4249
4250 return (
4251 this.regexp_eatCharacterClassEscape(state) ||
4252 this.regexp_eatCharacterEscape(state)
4253 )
4254 };
4255
4256 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
4257 pp$8.regexp_eatClassControlLetter = function(state) {
4258 var ch = state.current();
4259 if (isDecimalDigit(ch) || ch === 0x5F /* _ */) {
4260 state.lastIntValue = ch % 0x20;
4261 state.advance();
4262 return true
4263 }
4264 return false
4265 };
4266
4267 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
4268 pp$8.regexp_eatHexEscapeSequence = function(state) {
4269 var start = state.pos;
4270 if (state.eat(0x78 /* x */)) {
4271 if (this.regexp_eatFixedHexDigits(state, 2)) {
4272 return true
4273 }
4274 if (state.switchU) {
4275 state.raise("Invalid escape");
4276 }
4277 state.pos = start;
4278 }
4279 return false
4280 };
4281
4282 // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
4283 pp$8.regexp_eatDecimalDigits = function(state) {
4284 var start = state.pos;
4285 var ch = 0;
4286 state.lastIntValue = 0;
4287 while (isDecimalDigit(ch = state.current())) {
4288 state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
4289 state.advance();
4290 }
4291 return state.pos !== start
4292 };
4293 function isDecimalDigit(ch) {
4294 return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */
4295 }
4296
4297 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
4298 pp$8.regexp_eatHexDigits = function(state) {
4299 var start = state.pos;
4300 var ch = 0;
4301 state.lastIntValue = 0;
4302 while (isHexDigit(ch = state.current())) {
4303 state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
4304 state.advance();
4305 }
4306 return state.pos !== start
4307 };
4308 function isHexDigit(ch) {
4309 return (
4310 (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) ||
4311 (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) ||
4312 (ch >= 0x61 /* a */ && ch <= 0x66 /* f */)
4313 )
4314 }
4315 function hexToInt(ch) {
4316 if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) {
4317 return 10 + (ch - 0x41 /* A */)
4318 }
4319 if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) {
4320 return 10 + (ch - 0x61 /* a */)
4321 }
4322 return ch - 0x30 /* 0 */
4323 }
4324
4325 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
4326 // Allows only 0-377(octal) i.e. 0-255(decimal).
4327 pp$8.regexp_eatLegacyOctalEscapeSequence = function(state) {
4328 if (this.regexp_eatOctalDigit(state)) {
4329 var n1 = state.lastIntValue;
4330 if (this.regexp_eatOctalDigit(state)) {
4331 var n2 = state.lastIntValue;
4332 if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
4333 state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
4334 } else {
4335 state.lastIntValue = n1 * 8 + n2;
4336 }
4337 } else {
4338 state.lastIntValue = n1;
4339 }
4340 return true
4341 }
4342 return false
4343 };
4344
4345 // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
4346 pp$8.regexp_eatOctalDigit = function(state) {
4347 var ch = state.current();
4348 if (isOctalDigit(ch)) {
4349 state.lastIntValue = ch - 0x30; /* 0 */
4350 state.advance();
4351 return true
4352 }
4353 state.lastIntValue = 0;
4354 return false
4355 };
4356 function isOctalDigit(ch) {
4357 return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */
4358 }
4359
4360 // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
4361 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
4362 // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
4363 pp$8.regexp_eatFixedHexDigits = function(state, length) {
4364 var start = state.pos;
4365 state.lastIntValue = 0;
4366 for (var i = 0; i < length; ++i) {
4367 var ch = state.current();
4368 if (!isHexDigit(ch)) {
4369 state.pos = start;
4370 return false
4371 }
4372 state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
4373 state.advance();
4374 }
4375 return true
4376 };
4377
4378 // Object type used to represent tokens. Note that normally, tokens
4379 // simply exist as properties on the parser object. This is only
4380 // used for the onToken callback and the external tokenizer.
4381
4382 var Token = function Token(p) {
4383 this.type = p.type;
4384 this.value = p.value;
4385 this.start = p.start;
4386 this.end = p.end;
4387 if (p.options.locations)
4388 { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
4389 if (p.options.ranges)
4390 { this.range = [p.start, p.end]; }
4391 };
4392
4393 // ## Tokenizer
4394
4395 var pp$9 = Parser.prototype;
4396
4397 // Move to the next token
4398
4399 pp$9.next = function(ignoreEscapeSequenceInKeyword) {
4400 if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc)
4401 { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); }
4402 if (this.options.onToken)
4403 { this.options.onToken(new Token(this)); }
4404
4405 this.lastTokEnd = this.end;
4406 this.lastTokStart = this.start;
4407 this.lastTokEndLoc = this.endLoc;
4408 this.lastTokStartLoc = this.startLoc;
4409 this.nextToken();
4410 };
4411
4412 pp$9.getToken = function() {
4413 this.next();
4414 return new Token(this)
4415 };
4416
4417 // If we're in an ES6 environment, make parsers iterable
4418 if (typeof Symbol !== "undefined")
4419 { pp$9[Symbol.iterator] = function() {
4420 var this$1 = this;
4421
4422 return {
4423 next: function () {
4424 var token = this$1.getToken();
4425 return {
4426 done: token.type === types.eof,
4427 value: token
4428 }
4429 }
4430 }
4431 }; }
4432
4433 // Toggle strict mode. Re-reads the next number or string to please
4434 // pedantic tests (`"use strict"; 010;` should fail).
4435
4436 pp$9.curContext = function() {
4437 return this.context[this.context.length - 1]
4438 };
4439
4440 // Read a single token, updating the parser object's token-related
4441 // properties.
4442
4443 pp$9.nextToken = function() {
4444 var curContext = this.curContext();
4445 if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }
4446
4447 this.start = this.pos;
4448 if (this.options.locations) { this.startLoc = this.curPosition(); }
4449 if (this.pos >= this.input.length) { return this.finishToken(types.eof) }
4450
4451 if (curContext.override) { return curContext.override(this) }
4452 else { this.readToken(this.fullCharCodeAtPos()); }
4453 };
4454
4455 pp$9.readToken = function(code) {
4456 // Identifier or keyword. '\uXXXX' sequences are allowed in
4457 // identifiers, so '\' also dispatches to that.
4458 if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
4459 { return this.readWord() }
4460
4461 return this.getTokenFromCode(code)
4462 };
4463
4464 pp$9.fullCharCodeAtPos = function() {
4465 var code = this.input.charCodeAt(this.pos);
4466 if (code <= 0xd7ff || code >= 0xe000) { return code }
4467 var next = this.input.charCodeAt(this.pos + 1);
4468 return (code << 10) + next - 0x35fdc00
4469 };
4470
4471 pp$9.skipBlockComment = function() {
4472 var startLoc = this.options.onComment && this.curPosition();
4473 var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
4474 if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
4475 this.pos = end + 2;
4476 if (this.options.locations) {
4477 lineBreakG.lastIndex = start;
4478 var match;
4479 while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
4480 ++this.curLine;
4481 this.lineStart = match.index + match[0].length;
4482 }
4483 }
4484 if (this.options.onComment)
4485 { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
4486 startLoc, this.curPosition()); }
4487 };
4488
4489 pp$9.skipLineComment = function(startSkip) {
4490 var start = this.pos;
4491 var startLoc = this.options.onComment && this.curPosition();
4492 var ch = this.input.charCodeAt(this.pos += startSkip);
4493 while (this.pos < this.input.length && !isNewLine(ch)) {
4494 ch = this.input.charCodeAt(++this.pos);
4495 }
4496 if (this.options.onComment)
4497 { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
4498 startLoc, this.curPosition()); }
4499 };
4500
4501 // Called at the start of the parse and after every token. Skips
4502 // whitespace and comments, and.
4503
4504 pp$9.skipSpace = function() {
4505 loop: while (this.pos < this.input.length) {
4506 var ch = this.input.charCodeAt(this.pos);
4507 switch (ch) {
4508 case 32: case 160: // ' '
4509 ++this.pos;
4510 break
4511 case 13:
4512 if (this.input.charCodeAt(this.pos + 1) === 10) {
4513 ++this.pos;
4514 }
4515 case 10: case 8232: case 8233:
4516 ++this.pos;
4517 if (this.options.locations) {
4518 ++this.curLine;
4519 this.lineStart = this.pos;
4520 }
4521 break
4522 case 47: // '/'
4523 switch (this.input.charCodeAt(this.pos + 1)) {
4524 case 42: // '*'
4525 this.skipBlockComment();
4526 break
4527 case 47:
4528 this.skipLineComment(2);
4529 break
4530 default:
4531 break loop
4532 }
4533 break
4534 default:
4535 if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
4536 ++this.pos;
4537 } else {
4538 break loop
4539 }
4540 }
4541 }
4542 };
4543
4544 // Called at the end of every token. Sets `end`, `val`, and
4545 // maintains `context` and `exprAllowed`, and skips the space after
4546 // the token, so that the next one's `start` will point at the
4547 // right position.
4548
4549 pp$9.finishToken = function(type, val) {
4550 this.end = this.pos;
4551 if (this.options.locations) { this.endLoc = this.curPosition(); }
4552 var prevType = this.type;
4553 this.type = type;
4554 this.value = val;
4555
4556 this.updateContext(prevType);
4557 };
4558
4559 // ### Token reading
4560
4561 // This is the function that is called to fetch the next token. It
4562 // is somewhat obscure, because it works in character codes rather
4563 // than characters, and because operator parsing has been inlined
4564 // into it.
4565 //
4566 // All in the name of speed.
4567 //
4568 pp$9.readToken_dot = function() {
4569 var next = this.input.charCodeAt(this.pos + 1);
4570 if (next >= 48 && next <= 57) { return this.readNumber(true) }
4571 var next2 = this.input.charCodeAt(this.pos + 2);
4572 if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
4573 this.pos += 3;
4574 return this.finishToken(types.ellipsis)
4575 } else {
4576 ++this.pos;
4577 return this.finishToken(types.dot)
4578 }
4579 };
4580
4581 pp$9.readToken_slash = function() { // '/'
4582 var next = this.input.charCodeAt(this.pos + 1);
4583 if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
4584 if (next === 61) { return this.finishOp(types.assign, 2) }
4585 return this.finishOp(types.slash, 1)
4586 };
4587
4588 pp$9.readToken_mult_modulo_exp = function(code) { // '%*'
4589 var next = this.input.charCodeAt(this.pos + 1);
4590 var size = 1;
4591 var tokentype = code === 42 ? types.star : types.modulo;
4592
4593 // exponentiation operator ** and **=
4594 if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
4595 ++size;
4596 tokentype = types.starstar;
4597 next = this.input.charCodeAt(this.pos + 2);
4598 }
4599
4600 if (next === 61) { return this.finishOp(types.assign, size + 1) }
4601 return this.finishOp(tokentype, size)
4602 };
4603
4604 pp$9.readToken_pipe_amp = function(code) { // '|&'
4605 var next = this.input.charCodeAt(this.pos + 1);
4606 if (next === code) {
4607 if (this.options.ecmaVersion >= 12) {
4608 var next2 = this.input.charCodeAt(this.pos + 2);
4609 if (next2 === 61) { return this.finishOp(types.assign, 3) }
4610 }
4611 return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2)
4612 }
4613 if (next === 61) { return this.finishOp(types.assign, 2) }
4614 return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1)
4615 };
4616
4617 pp$9.readToken_caret = function() { // '^'
4618 var next = this.input.charCodeAt(this.pos + 1);
4619 if (next === 61) { return this.finishOp(types.assign, 2) }
4620 return this.finishOp(types.bitwiseXOR, 1)
4621 };
4622
4623 pp$9.readToken_plus_min = function(code) { // '+-'
4624 var next = this.input.charCodeAt(this.pos + 1);
4625 if (next === code) {
4626 if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 &&
4627 (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
4628 // A `-->` line comment
4629 this.skipLineComment(3);
4630 this.skipSpace();
4631 return this.nextToken()
4632 }
4633 return this.finishOp(types.incDec, 2)
4634 }
4635 if (next === 61) { return this.finishOp(types.assign, 2) }
4636 return this.finishOp(types.plusMin, 1)
4637 };
4638
4639 pp$9.readToken_lt_gt = function(code) { // '<>'
4640 var next = this.input.charCodeAt(this.pos + 1);
4641 var size = 1;
4642 if (next === code) {
4643 size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
4644 if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) }
4645 return this.finishOp(types.bitShift, size)
4646 }
4647 if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 &&
4648 this.input.charCodeAt(this.pos + 3) === 45) {
4649 // `<!--`, an XML-style comment that should be interpreted as a line comment
4650 this.skipLineComment(4);
4651 this.skipSpace();
4652 return this.nextToken()
4653 }
4654 if (next === 61) { size = 2; }
4655 return this.finishOp(types.relational, size)
4656 };
4657
4658 pp$9.readToken_eq_excl = function(code) { // '=!'
4659 var next = this.input.charCodeAt(this.pos + 1);
4660 if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
4661 if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
4662 this.pos += 2;
4663 return this.finishToken(types.arrow)
4664 }
4665 return this.finishOp(code === 61 ? types.eq : types.prefix, 1)
4666 };
4667
4668 pp$9.readToken_question = function() { // '?'
4669 var ecmaVersion = this.options.ecmaVersion;
4670 if (ecmaVersion >= 11) {
4671 var next = this.input.charCodeAt(this.pos + 1);
4672 if (next === 46) {
4673 var next2 = this.input.charCodeAt(this.pos + 2);
4674 if (next2 < 48 || next2 > 57) { return this.finishOp(types.questionDot, 2) }
4675 }
4676 if (next === 63) {
4677 if (ecmaVersion >= 12) {
4678 var next2$1 = this.input.charCodeAt(this.pos + 2);
4679 if (next2$1 === 61) { return this.finishOp(types.assign, 3) }
4680 }
4681 return this.finishOp(types.coalesce, 2)
4682 }
4683 }
4684 return this.finishOp(types.question, 1)
4685 };
4686
4687 pp$9.getTokenFromCode = function(code) {
4688 switch (code) {
4689 // The interpretation of a dot depends on whether it is followed
4690 // by a digit or another two dots.
4691 case 46: // '.'
4692 return this.readToken_dot()
4693
4694 // Punctuation tokens.
4695 case 40: ++this.pos; return this.finishToken(types.parenL)
4696 case 41: ++this.pos; return this.finishToken(types.parenR)
4697 case 59: ++this.pos; return this.finishToken(types.semi)
4698 case 44: ++this.pos; return this.finishToken(types.comma)
4699 case 91: ++this.pos; return this.finishToken(types.bracketL)
4700 case 93: ++this.pos; return this.finishToken(types.bracketR)
4701 case 123: ++this.pos; return this.finishToken(types.braceL)
4702 case 125: ++this.pos; return this.finishToken(types.braceR)
4703 case 58: ++this.pos; return this.finishToken(types.colon)
4704
4705 case 96: // '`'
4706 if (this.options.ecmaVersion < 6) { break }
4707 ++this.pos;
4708 return this.finishToken(types.backQuote)
4709
4710 case 48: // '0'
4711 var next = this.input.charCodeAt(this.pos + 1);
4712 if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number
4713 if (this.options.ecmaVersion >= 6) {
4714 if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number
4715 if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number
4716 }
4717
4718 // Anything else beginning with a digit is an integer, octal
4719 // number, or float.
4720 case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
4721 return this.readNumber(false)
4722
4723 // Quotes produce strings.
4724 case 34: case 39: // '"', "'"
4725 return this.readString(code)
4726
4727 // Operators are parsed inline in tiny state machines. '=' (61) is
4728 // often referred to. `finishOp` simply skips the amount of
4729 // characters it is given as second argument, and returns a token
4730 // of the type given by its first argument.
4731
4732 case 47: // '/'
4733 return this.readToken_slash()
4734
4735 case 37: case 42: // '%*'
4736 return this.readToken_mult_modulo_exp(code)
4737
4738 case 124: case 38: // '|&'
4739 return this.readToken_pipe_amp(code)
4740
4741 case 94: // '^'
4742 return this.readToken_caret()
4743
4744 case 43: case 45: // '+-'
4745 return this.readToken_plus_min(code)
4746
4747 case 60: case 62: // '<>'
4748 return this.readToken_lt_gt(code)
4749
4750 case 61: case 33: // '=!'
4751 return this.readToken_eq_excl(code)
4752
4753 case 63: // '?'
4754 return this.readToken_question()
4755
4756 case 126: // '~'
4757 return this.finishOp(types.prefix, 1)
4758 }
4759
4760 this.raise(this.pos, "Unexpected character '" + codePointToString$1(code) + "'");
4761 };
4762
4763 pp$9.finishOp = function(type, size) {
4764 var str = this.input.slice(this.pos, this.pos + size);
4765 this.pos += size;
4766 return this.finishToken(type, str)
4767 };
4768
4769 pp$9.readRegexp = function() {
4770 var escaped, inClass, start = this.pos;
4771 for (;;) {
4772 if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); }
4773 var ch = this.input.charAt(this.pos);
4774 if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); }
4775 if (!escaped) {
4776 if (ch === "[") { inClass = true; }
4777 else if (ch === "]" && inClass) { inClass = false; }
4778 else if (ch === "/" && !inClass) { break }
4779 escaped = ch === "\\";
4780 } else { escaped = false; }
4781 ++this.pos;
4782 }
4783 var pattern = this.input.slice(start, this.pos);
4784 ++this.pos;
4785 var flagsStart = this.pos;
4786 var flags = this.readWord1();
4787 if (this.containsEsc) { this.unexpected(flagsStart); }
4788
4789 // Validate pattern
4790 var state = this.regexpState || (this.regexpState = new RegExpValidationState(this));
4791 state.reset(start, pattern, flags);
4792 this.validateRegExpFlags(state);
4793 this.validateRegExpPattern(state);
4794
4795 // Create Literal#value property value.
4796 var value = null;
4797 try {
4798 value = new RegExp(pattern, flags);
4799 } catch (e) {
4800 // ESTree requires null if it failed to instantiate RegExp object.
4801 // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral
4802 }
4803
4804 return this.finishToken(types.regexp, {pattern: pattern, flags: flags, value: value})
4805 };
4806
4807 // Read an integer in the given radix. Return null if zero digits
4808 // were read, the integer value otherwise. When `len` is given, this
4809 // will return `null` unless the integer has exactly `len` digits.
4810
4811 pp$9.readInt = function(radix, len, maybeLegacyOctalNumericLiteral) {
4812 // `len` is used for character escape sequences. In that case, disallow separators.
4813 var allowSeparators = this.options.ecmaVersion >= 12 && len === undefined;
4814
4815 // `maybeLegacyOctalNumericLiteral` is true if it doesn't have prefix (0x,0o,0b)
4816 // and isn't fraction part nor exponent part. In that case, if the first digit
4817 // is zero then disallow separators.
4818 var isLegacyOctalNumericLiteral = maybeLegacyOctalNumericLiteral && this.input.charCodeAt(this.pos) === 48;
4819
4820 var start = this.pos, total = 0, lastCode = 0;
4821 for (var i = 0, e = len == null ? Infinity : len; i < e; ++i, ++this.pos) {
4822 var code = this.input.charCodeAt(this.pos), val = (void 0);
4823
4824 if (allowSeparators && code === 95) {
4825 if (isLegacyOctalNumericLiteral) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed in legacy octal numeric literals"); }
4826 if (lastCode === 95) { this.raiseRecoverable(this.pos, "Numeric separator must be exactly one underscore"); }
4827 if (i === 0) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed at the first of digits"); }
4828 lastCode = code;
4829 continue
4830 }
4831
4832 if (code >= 97) { val = code - 97 + 10; } // a
4833 else if (code >= 65) { val = code - 65 + 10; } // A
4834 else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
4835 else { val = Infinity; }
4836 if (val >= radix) { break }
4837 lastCode = code;
4838 total = total * radix + val;
4839 }
4840
4841 if (allowSeparators && lastCode === 95) { this.raiseRecoverable(this.pos - 1, "Numeric separator is not allowed at the last of digits"); }
4842 if (this.pos === start || len != null && this.pos - start !== len) { return null }
4843
4844 return total
4845 };
4846
4847 function stringToNumber(str, isLegacyOctalNumericLiteral) {
4848 if (isLegacyOctalNumericLiteral) {
4849 return parseInt(str, 8)
4850 }
4851
4852 // `parseFloat(value)` stops parsing at the first numeric separator then returns a wrong value.
4853 return parseFloat(str.replace(/_/g, ""))
4854 }
4855
4856 function stringToBigInt(str) {
4857 if (typeof BigInt !== "function") {
4858 return null
4859 }
4860
4861 // `BigInt(value)` throws syntax error if the string contains numeric separators.
4862 return BigInt(str.replace(/_/g, ""))
4863 }
4864
4865 pp$9.readRadixNumber = function(radix) {
4866 var start = this.pos;
4867 this.pos += 2; // 0x
4868 var val = this.readInt(radix);
4869 if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
4870 if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
4871 val = stringToBigInt(this.input.slice(start, this.pos));
4872 ++this.pos;
4873 } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4874 return this.finishToken(types.num, val)
4875 };
4876
4877 // Read an integer, octal integer, or floating-point number.
4878
4879 pp$9.readNumber = function(startsWithDot) {
4880 var start = this.pos;
4881 if (!startsWithDot && this.readInt(10, undefined, true) === null) { this.raise(start, "Invalid number"); }
4882 var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48;
4883 if (octal && this.strict) { this.raise(start, "Invalid number"); }
4884 var next = this.input.charCodeAt(this.pos);
4885 if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
4886 var val$1 = stringToBigInt(this.input.slice(start, this.pos));
4887 ++this.pos;
4888 if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4889 return this.finishToken(types.num, val$1)
4890 }
4891 if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; }
4892 if (next === 46 && !octal) { // '.'
4893 ++this.pos;
4894 this.readInt(10);
4895 next = this.input.charCodeAt(this.pos);
4896 }
4897 if ((next === 69 || next === 101) && !octal) { // 'eE'
4898 next = this.input.charCodeAt(++this.pos);
4899 if (next === 43 || next === 45) { ++this.pos; } // '+-'
4900 if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
4901 }
4902 if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
4903
4904 var val = stringToNumber(this.input.slice(start, this.pos), octal);
4905 return this.finishToken(types.num, val)
4906 };
4907
4908 // Read a string value, interpreting backslash-escapes.
4909
4910 pp$9.readCodePoint = function() {
4911 var ch = this.input.charCodeAt(this.pos), code;
4912
4913 if (ch === 123) { // '{'
4914 if (this.options.ecmaVersion < 6) { this.unexpected(); }
4915 var codePos = ++this.pos;
4916 code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
4917 ++this.pos;
4918 if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
4919 } else {
4920 code = this.readHexChar(4);
4921 }
4922 return code
4923 };
4924
4925 function codePointToString$1(code) {
4926 // UTF-16 Decoding
4927 if (code <= 0xFFFF) { return String.fromCharCode(code) }
4928 code -= 0x10000;
4929 return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
4930 }
4931
4932 pp$9.readString = function(quote) {
4933 var out = "", chunkStart = ++this.pos;
4934 for (;;) {
4935 if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); }
4936 var ch = this.input.charCodeAt(this.pos);
4937 if (ch === quote) { break }
4938 if (ch === 92) { // '\'
4939 out += this.input.slice(chunkStart, this.pos);
4940 out += this.readEscapedChar(false);
4941 chunkStart = this.pos;
4942 } else {
4943 if (isNewLine(ch, this.options.ecmaVersion >= 10)) { this.raise(this.start, "Unterminated string constant"); }
4944 ++this.pos;
4945 }
4946 }
4947 out += this.input.slice(chunkStart, this.pos++);
4948 return this.finishToken(types.string, out)
4949 };
4950
4951 // Reads template string tokens.
4952
4953 var INVALID_TEMPLATE_ESCAPE_ERROR = {};
4954
4955 pp$9.tryReadTemplateToken = function() {
4956 this.inTemplateElement = true;
4957 try {
4958 this.readTmplToken();
4959 } catch (err) {
4960 if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
4961 this.readInvalidTemplateToken();
4962 } else {
4963 throw err
4964 }
4965 }
4966
4967 this.inTemplateElement = false;
4968 };
4969
4970 pp$9.invalidStringToken = function(position, message) {
4971 if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
4972 throw INVALID_TEMPLATE_ESCAPE_ERROR
4973 } else {
4974 this.raise(position, message);
4975 }
4976 };
4977
4978 pp$9.readTmplToken = function() {
4979 var out = "", chunkStart = this.pos;
4980 for (;;) {
4981 if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); }
4982 var ch = this.input.charCodeAt(this.pos);
4983 if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${'
4984 if (this.pos === this.start && (this.type === types.template || this.type === types.invalidTemplate)) {
4985 if (ch === 36) {
4986 this.pos += 2;
4987 return this.finishToken(types.dollarBraceL)
4988 } else {
4989 ++this.pos;
4990 return this.finishToken(types.backQuote)
4991 }
4992 }
4993 out += this.input.slice(chunkStart, this.pos);
4994 return this.finishToken(types.template, out)
4995 }
4996 if (ch === 92) { // '\'
4997 out += this.input.slice(chunkStart, this.pos);
4998 out += this.readEscapedChar(true);
4999 chunkStart = this.pos;
5000 } else if (isNewLine(ch)) {
5001 out += this.input.slice(chunkStart, this.pos);
5002 ++this.pos;
5003 switch (ch) {
5004 case 13:
5005 if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; }
5006 case 10:
5007 out += "\n";
5008 break
5009 default:
5010 out += String.fromCharCode(ch);
5011 break
5012 }
5013 if (this.options.locations) {
5014 ++this.curLine;
5015 this.lineStart = this.pos;
5016 }
5017 chunkStart = this.pos;
5018 } else {
5019 ++this.pos;
5020 }
5021 }
5022 };
5023
5024 // Reads a template token to search for the end, without validating any escape sequences
5025 pp$9.readInvalidTemplateToken = function() {
5026 for (; this.pos < this.input.length; this.pos++) {
5027 switch (this.input[this.pos]) {
5028 case "\\":
5029 ++this.pos;
5030 break
5031
5032 case "$":
5033 if (this.input[this.pos + 1] !== "{") {
5034 break
5035 }
5036 // falls through
5037
5038 case "`":
5039 return this.finishToken(types.invalidTemplate, this.input.slice(this.start, this.pos))
5040
5041 // no default
5042 }
5043 }
5044 this.raise(this.start, "Unterminated template");
5045 };
5046
5047 // Used to read escaped characters
5048
5049 pp$9.readEscapedChar = function(inTemplate) {
5050 var ch = this.input.charCodeAt(++this.pos);
5051 ++this.pos;
5052 switch (ch) {
5053 case 110: return "\n" // 'n' -> '\n'
5054 case 114: return "\r" // 'r' -> '\r'
5055 case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
5056 case 117: return codePointToString$1(this.readCodePoint()) // 'u'
5057 case 116: return "\t" // 't' -> '\t'
5058 case 98: return "\b" // 'b' -> '\b'
5059 case 118: return "\u000b" // 'v' -> '\u000b'
5060 case 102: return "\f" // 'f' -> '\f'
5061 case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
5062 case 10: // ' \n'
5063 if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
5064 return ""
5065 case 56:
5066 case 57:
5067 if (inTemplate) {
5068 var codePos = this.pos - 1;
5069
5070 this.invalidStringToken(
5071 codePos,
5072 "Invalid escape sequence in template string"
5073 );
5074
5075 return null
5076 }
5077 default:
5078 if (ch >= 48 && ch <= 55) {
5079 var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
5080 var octal = parseInt(octalStr, 8);
5081 if (octal > 255) {
5082 octalStr = octalStr.slice(0, -1);
5083 octal = parseInt(octalStr, 8);
5084 }
5085 this.pos += octalStr.length - 1;
5086 ch = this.input.charCodeAt(this.pos);
5087 if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
5088 this.invalidStringToken(
5089 this.pos - 1 - octalStr.length,
5090 inTemplate
5091 ? "Octal literal in template string"
5092 : "Octal literal in strict mode"
5093 );
5094 }
5095 return String.fromCharCode(octal)
5096 }
5097 if (isNewLine(ch)) {
5098 // Unicode new line characters after \ get removed from output in both
5099 // template literals and strings
5100 return ""
5101 }
5102 return String.fromCharCode(ch)
5103 }
5104 };
5105
5106 // Used to read character escape sequences ('\x', '\u', '\U').
5107
5108 pp$9.readHexChar = function(len) {
5109 var codePos = this.pos;
5110 var n = this.readInt(16, len);
5111 if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
5112 return n
5113 };
5114
5115 // Read an identifier, and return it as a string. Sets `this.containsEsc`
5116 // to whether the word contained a '\u' escape.
5117 //
5118 // Incrementally adds only escaped chars, adding other chunks as-is
5119 // as a micro-optimization.
5120
5121 pp$9.readWord1 = function() {
5122 this.containsEsc = false;
5123 var word = "", first = true, chunkStart = this.pos;
5124 var astral = this.options.ecmaVersion >= 6;
5125 while (this.pos < this.input.length) {
5126 var ch = this.fullCharCodeAtPos();
5127 if (isIdentifierChar(ch, astral)) {
5128 this.pos += ch <= 0xffff ? 1 : 2;
5129 } else if (ch === 92) { // "\"
5130 this.containsEsc = true;
5131 word += this.input.slice(chunkStart, this.pos);
5132 var escStart = this.pos;
5133 if (this.input.charCodeAt(++this.pos) !== 117) // "u"
5134 { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); }
5135 ++this.pos;
5136 var esc = this.readCodePoint();
5137 if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
5138 { this.invalidStringToken(escStart, "Invalid Unicode escape"); }
5139 word += codePointToString$1(esc);
5140 chunkStart = this.pos;
5141 } else {
5142 break
5143 }
5144 first = false;
5145 }
5146 return word + this.input.slice(chunkStart, this.pos)
5147 };
5148
5149 // Read an identifier or keyword token. Will check for reserved
5150 // words when necessary.
5151
5152 pp$9.readWord = function() {
5153 var word = this.readWord1();
5154 var type = types.name;
5155 if (this.keywords.test(word)) {
5156 type = keywords$1[word];
5157 }
5158 return this.finishToken(type, word)
5159 };
5160
5161 // Acorn is a tiny, fast JavaScript parser written in JavaScript.
5162
5163 var version = "7.4.0";
5164
5165 Parser.acorn = {
5166 Parser: Parser,
5167 version: version,
5168 defaultOptions: defaultOptions,
5169 Position: Position,
5170 SourceLocation: SourceLocation,
5171 getLineInfo: getLineInfo,
5172 Node: Node,
5173 TokenType: TokenType,
5174 tokTypes: types,
5175 keywordTypes: keywords$1,
5176 TokContext: TokContext,
5177 tokContexts: types$1,
5178 isIdentifierChar: isIdentifierChar,
5179 isIdentifierStart: isIdentifierStart,
5180 Token: Token,
5181 isNewLine: isNewLine,
5182 lineBreak: lineBreak,
5183 lineBreakG: lineBreakG,
5184 nonASCIIwhitespace: nonASCIIwhitespace
5185 };
5186
5187 // The main exported interface (under `self.acorn` when in the
5188 // browser) is a `parse` function that takes a code string and
5189 // returns an abstract syntax tree as specified by [Mozilla parser
5190 // API][api].
5191 //
5192 // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
5193
5194 function parse(input, options) {
5195 return Parser.parse(input, options)
5196 }
5197
5198 // This function tries to parse a single expression at a given
5199 // offset in a string. Useful for parsing mixed-language formats
5200 // that embed JavaScript expressions.
5201
5202 function parseExpressionAt(input, pos, options) {
5203 return Parser.parseExpressionAt(input, pos, options)
5204 }
5205
5206 function walk(ast, { enter, leave }) {
5207 return visit(ast, null, enter, leave);
5208 }
5209
5210 let should_skip = false;
5211 let should_remove = false;
5212 let replacement = null;
5213 const context = {
5214 skip: () => should_skip = true,
5215 remove: () => should_remove = true,
5216 replace: (node) => replacement = node
5217 };
5218
5219 function replace(parent, prop, index, node) {
5220 if (parent) {
5221 if (index !== null) {
5222 parent[prop][index] = node;
5223 } else {
5224 parent[prop] = node;
5225 }
5226 }
5227 }
5228
5229 function remove(parent, prop, index) {
5230 if (parent) {
5231 if (index !== null) {
5232 parent[prop].splice(index, 1);
5233 } else {
5234 delete parent[prop];
5235 }
5236 }
5237 }
5238
5239 function visit(
5240 node,
5241 parent,
5242 enter,
5243 leave,
5244 prop,
5245 index
5246 ) {
5247 if (node) {
5248 if (enter) {
5249 const _should_skip = should_skip;
5250 const _should_remove = should_remove;
5251 const _replacement = replacement;
5252 should_skip = false;
5253 should_remove = false;
5254 replacement = null;
5255
5256 enter.call(context, node, parent, prop, index);
5257
5258 if (replacement) {
5259 node = replacement;
5260 replace(parent, prop, index, node);
5261 }
5262
5263 if (should_remove) {
5264 remove(parent, prop, index);
5265 }
5266
5267 const skipped = should_skip;
5268 const removed = should_remove;
5269
5270 should_skip = _should_skip;
5271 should_remove = _should_remove;
5272 replacement = _replacement;
5273
5274 if (skipped) return node;
5275 if (removed) return null;
5276 }
5277
5278 for (const key in node) {
5279 const value = (node )[key];
5280
5281 if (typeof value !== 'object') {
5282 continue;
5283 }
5284
5285 else if (Array.isArray(value)) {
5286 for (let j = 0, k = 0; j < value.length; j += 1, k += 1) {
5287 if (value[j] !== null && typeof value[j].type === 'string') {
5288 if (!visit(value[j], node, enter, leave, key, k)) {
5289 // removed
5290 j--;
5291 }
5292 }
5293 }
5294 }
5295
5296 else if (value !== null && typeof value.type === 'string') {
5297 visit(value, node, enter, leave, key, null);
5298 }
5299 }
5300
5301 if (leave) {
5302 const _replacement = replacement;
5303 const _should_remove = should_remove;
5304 replacement = null;
5305 should_remove = false;
5306
5307 leave.call(context, node, parent, prop, index);
5308
5309 if (replacement) {
5310 node = replacement;
5311 replace(parent, prop, index, node);
5312 }
5313
5314 if (should_remove) {
5315 remove(parent, prop, index);
5316 }
5317
5318 const removed = should_remove;
5319
5320 replacement = _replacement;
5321 should_remove = _should_remove;
5322
5323 if (removed) return null;
5324 }
5325 }
5326
5327 return node;
5328 }
5329
5330 function isReference(node, parent) {
5331 if (node.type === 'MemberExpression') {
5332 return !node.computed && isReference(node.object, node);
5333 }
5334 if (node.type === 'Identifier') {
5335 if (!parent)
5336 return true;
5337 switch (parent.type) {
5338 // disregard `bar` in `foo.bar`
5339 case 'MemberExpression': return parent.computed || node === parent.object;
5340 // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
5341 case 'MethodDefinition': return parent.computed;
5342 // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
5343 case 'FieldDefinition': return parent.computed || node === parent.value;
5344 // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
5345 case 'Property': return parent.computed || node === parent.value;
5346 // disregard the `bar` in `export { foo as bar }` or
5347 // the foo in `import { foo as bar }`
5348 case 'ExportSpecifier':
5349 case 'ImportSpecifier': return node === parent.local;
5350 // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
5351 case 'LabeledStatement':
5352 case 'BreakStatement':
5353 case 'ContinueStatement': return false;
5354 default: return true;
5355 }
5356 }
5357 return false;
5358 }
5359
5360 function analyze(expression) {
5361 const map = new WeakMap();
5362
5363 let scope = new Scope$1(null, false);
5364
5365 walk(expression, {
5366 enter(node, parent) {
5367 if (node.type === 'ImportDeclaration') {
5368 node.specifiers.forEach((specifier) => {
5369 scope.declarations.set(specifier.local.name, specifier);
5370 });
5371 } else if (/(Function(Declaration|Expression)|ArrowFunctionExpression)/.test(node.type)) {
5372 if (node.type === 'FunctionDeclaration') {
5373 scope.declarations.set(node.id.name, node);
5374 map.set(node, scope = new Scope$1(scope, false));
5375 } else {
5376 map.set(node, scope = new Scope$1(scope, false));
5377 if (node.type === 'FunctionExpression' && node.id) scope.declarations.set(node.id.name, node);
5378 }
5379
5380 node.params.forEach((param) => {
5381 extract_names(param).forEach(name => {
5382 scope.declarations.set(name, node);
5383 });
5384 });
5385 } else if (/For(?:In|Of)?Statement/.test(node.type)) {
5386 map.set(node, scope = new Scope$1(scope, true));
5387 } else if (node.type === 'BlockStatement') {
5388 map.set(node, scope = new Scope$1(scope, true));
5389 } else if (/(Class|Variable)Declaration/.test(node.type)) {
5390 scope.add_declaration(node);
5391 } else if (node.type === 'CatchClause') {
5392 map.set(node, scope = new Scope$1(scope, true));
5393
5394 if (node.param) {
5395 extract_names(node.param).forEach(name => {
5396 scope.declarations.set(name, node.param);
5397 });
5398 }
5399 }
5400 },
5401
5402 leave(node) {
5403 if (map.has(node)) {
5404 scope = scope.parent;
5405 }
5406 }
5407 });
5408
5409 const globals = new Map();
5410
5411 walk(expression, {
5412 enter(node, parent) {
5413 if (map.has(node)) scope = map.get(node);
5414
5415 if (node.type === 'Identifier' && isReference(node, parent)) {
5416 const owner = scope.find_owner(node.name);
5417 if (!owner) globals.set(node.name, node);
5418
5419 add_reference(scope, node.name);
5420 }
5421 },
5422 leave(node) {
5423 if (map.has(node)) {
5424 scope = scope.parent;
5425 }
5426 }
5427 });
5428
5429 return { map, scope, globals };
5430 }
5431
5432 function add_reference(scope, name) {
5433 scope.references.add(name);
5434 if (scope.parent) add_reference(scope.parent, name);
5435 }
5436
5437 class Scope$1 {
5438
5439
5440 __init() {this.declarations = new Map();}
5441 __init2() {this.initialised_declarations = new Set();}
5442 __init3() {this.references = new Set();}
5443
5444 constructor(parent, block) {Scope$1.prototype.__init.call(this);Scope$1.prototype.__init2.call(this);Scope$1.prototype.__init3.call(this);
5445 this.parent = parent;
5446 this.block = block;
5447 }
5448
5449
5450 add_declaration(node) {
5451 if (node.type === 'VariableDeclaration') {
5452 if (node.kind === 'var' && this.block && this.parent) {
5453 this.parent.add_declaration(node);
5454 } else if (node.type === 'VariableDeclaration') {
5455 node.declarations.forEach((declarator) => {
5456 extract_names(declarator.id).forEach(name => {
5457 this.declarations.set(name, node);
5458 if (declarator.init) this.initialised_declarations.add(name);
5459 });
5460 });
5461 }
5462 } else {
5463 this.declarations.set(node.id.name, node);
5464 }
5465 }
5466
5467 find_owner(name) {
5468 if (this.declarations.has(name)) return this;
5469 return this.parent && this.parent.find_owner(name);
5470 }
5471
5472 has(name) {
5473 return (
5474 this.declarations.has(name) || (this.parent && this.parent.has(name))
5475 );
5476 }
5477 }
5478
5479 function extract_names(param) {
5480 return extract_identifiers(param).map(node => node.name);
5481 }
5482
5483 function extract_identifiers(param) {
5484 const nodes = [];
5485 extractors[param.type] && extractors[param.type](nodes, param);
5486 return nodes;
5487 }
5488
5489 const extractors = {
5490 Identifier(nodes, param) {
5491 nodes.push(param);
5492 },
5493
5494 MemberExpression(nodes, param) {
5495 let object = param;
5496 while (object.type === 'MemberExpression') object = object.object;
5497 nodes.push(object);
5498 },
5499
5500 ObjectPattern(nodes, param) {
5501 param.properties.forEach((prop) => {
5502 if (prop.type === 'RestElement') {
5503 nodes.push(prop.argument);
5504 } else {
5505 extractors[prop.value.type](nodes, prop.value);
5506 }
5507 });
5508 },
5509
5510 ArrayPattern(nodes, param) {
5511 param.elements.forEach((element) => {
5512 if (element) extractors[element.type](nodes, element);
5513 });
5514 },
5515
5516 RestElement(nodes, param) {
5517 extractors[param.argument.type](nodes, param.argument);
5518 },
5519
5520 AssignmentPattern(nodes, param) {
5521 extractors[param.left.type](nodes, param.left);
5522 }
5523 };
5524
5525 var charToInteger = {};
5526 var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
5527 for (var i = 0; i < chars.length; i++) {
5528 charToInteger[chars.charCodeAt(i)] = i;
5529 }
5530 function decode(mappings) {
5531 var decoded = [];
5532 var line = [];
5533 var segment = [
5534 0,
5535 0,
5536 0,
5537 0,
5538 0,
5539 ];
5540 var j = 0;
5541 for (var i = 0, shift = 0, value = 0; i < mappings.length; i++) {
5542 var c = mappings.charCodeAt(i);
5543 if (c === 44) { // ","
5544 segmentify(line, segment, j);
5545 j = 0;
5546 }
5547 else if (c === 59) { // ";"
5548 segmentify(line, segment, j);
5549 j = 0;
5550 decoded.push(line);
5551 line = [];
5552 segment[0] = 0;
5553 }
5554 else {
5555 var integer = charToInteger[c];
5556 if (integer === undefined) {
5557 throw new Error('Invalid character (' + String.fromCharCode(c) + ')');
5558 }
5559 var hasContinuationBit = integer & 32;
5560 integer &= 31;
5561 value += integer << shift;
5562 if (hasContinuationBit) {
5563 shift += 5;
5564 }
5565 else {
5566 var shouldNegate = value & 1;
5567 value >>>= 1;
5568 if (shouldNegate) {
5569 value = value === 0 ? -0x80000000 : -value;
5570 }
5571 segment[j] += value;
5572 j++;
5573 value = shift = 0; // reset
5574 }
5575 }
5576 }
5577 segmentify(line, segment, j);
5578 decoded.push(line);
5579 return decoded;
5580 }
5581 function segmentify(line, segment, j) {
5582 // This looks ugly, but we're creating specialized arrays with a specific
5583 // length. This is much faster than creating a new array (which v8 expands to
5584 // a capacity of 17 after pushing the first item), or slicing out a subarray
5585 // (which is slow). Length 4 is assumed to be the most frequent, followed by
5586 // length 5 (since not everything will have an associated name), followed by
5587 // length 1 (it's probably rare for a source substring to not have an
5588 // associated segment data).
5589 if (j === 4)
5590 line.push([segment[0], segment[1], segment[2], segment[3]]);
5591 else if (j === 5)
5592 line.push([segment[0], segment[1], segment[2], segment[3], segment[4]]);
5593 else if (j === 1)
5594 line.push([segment[0]]);
5595 }
5596 function encode(decoded) {
5597 var sourceFileIndex = 0; // second field
5598 var sourceCodeLine = 0; // third field
5599 var sourceCodeColumn = 0; // fourth field
5600 var nameIndex = 0; // fifth field
5601 var mappings = '';
5602 for (var i = 0; i < decoded.length; i++) {
5603 var line = decoded[i];
5604 if (i > 0)
5605 mappings += ';';
5606 if (line.length === 0)
5607 continue;
5608 var generatedCodeColumn = 0; // first field
5609 var lineMappings = [];
5610 for (var _i = 0, line_1 = line; _i < line_1.length; _i++) {
5611 var segment = line_1[_i];
5612 var segmentMappings = encodeInteger(segment[0] - generatedCodeColumn);
5613 generatedCodeColumn = segment[0];
5614 if (segment.length > 1) {
5615 segmentMappings +=
5616 encodeInteger(segment[1] - sourceFileIndex) +
5617 encodeInteger(segment[2] - sourceCodeLine) +
5618 encodeInteger(segment[3] - sourceCodeColumn);
5619 sourceFileIndex = segment[1];
5620 sourceCodeLine = segment[2];
5621 sourceCodeColumn = segment[3];
5622 }
5623 if (segment.length === 5) {
5624 segmentMappings += encodeInteger(segment[4] - nameIndex);
5625 nameIndex = segment[4];
5626 }
5627 lineMappings.push(segmentMappings);
5628 }
5629 mappings += lineMappings.join(',');
5630 }
5631 return mappings;
5632 }
5633 function encodeInteger(num) {
5634 var result = '';
5635 num = num < 0 ? (-num << 1) | 1 : num << 1;
5636 do {
5637 var clamped = num & 31;
5638 num >>>= 5;
5639 if (num > 0) {
5640 clamped |= 32;
5641 }
5642 result += chars[clamped];
5643 } while (num > 0);
5644 return result;
5645 }
5646
5647 // generate an ID that is, to all intents and purposes, unique
5648 const id = (Math.round(Math.random() * 1e20)).toString(36);
5649 const re = new RegExp(`_${id}_(?:(\\d+)|(AT)|(HASH))_(\\w+)?`, 'g');
5650
5651 const get_comment_handlers = (comments, raw) => ({
5652
5653 // pass to acorn options
5654 onComment: (block, value, start, end) => {
5655 if (block && /\n/.test(value)) {
5656 let a = start;
5657 while (a > 0 && raw[a - 1] !== '\n') a -= 1;
5658
5659 let b = a;
5660 while (/[ \t]/.test(raw[b])) b += 1;
5661
5662 const indentation = raw.slice(a, b);
5663 value = value.replace(new RegExp(`^${indentation}`, 'gm'), '');
5664 }
5665
5666 comments.push({ type: block ? 'Block' : 'Line', value, start, end });
5667 },
5668
5669 // pass to estree-walker options
5670 enter(node) {
5671 let comment;
5672
5673 while (comments[0] && comments[0].start < (node ).start) {
5674 comment = comments.shift();
5675
5676 comment.value = comment.value.replace(re, (match, id, at, hash, value) => {
5677 if (hash) return `#${value}`;
5678 if (at) return `@${value}`;
5679
5680 return match;
5681 });
5682
5683 const next = comments[0] || node;
5684 (comment ).has_trailing_newline = (
5685 comment.type === 'Line' ||
5686 /\n/.test(raw.slice(comment.end, (next ).start))
5687 );
5688
5689 (node.leadingComments || (node.leadingComments = [])).push(comment);
5690 }
5691 },
5692 leave(node) {
5693 if (comments[0]) {
5694 const slice = raw.slice((node ).end, comments[0].start);
5695
5696 if (/^[,) \t]*$/.test(slice)) {
5697 node.trailingComments = [comments.shift()];
5698 }
5699 }
5700 }
5701
5702 });
5703
5704 function handle(node, state) {
5705 const handler = handlers[node.type];
5706
5707 if (!handler) {
5708 throw new Error(`Not implemented ${node.type}`);
5709 }
5710
5711 const result = handler(node, state);
5712
5713 if (node.leadingComments) {
5714 result.unshift(c(node.leadingComments.map(comment => comment.type === 'Block'
5715 ? `/*${comment.value}*/${(comment ).has_trailing_newline ? `\n${state.indent}` : ` `}`
5716 : `//${comment.value}${(comment ).has_trailing_newline ? `\n${state.indent}` : ` `}`).join(``)));
5717 }
5718
5719 if (node.trailingComments) {
5720 state.comments.push(node.trailingComments[0]); // there is only ever one
5721 }
5722
5723 return result;
5724 }
5725
5726 function c(content, node) {
5727 return {
5728 content,
5729 loc: node && node.loc,
5730 has_newline: /\n/.test(content)
5731 };
5732 }
5733
5734 const OPERATOR_PRECEDENCE = {
5735 '||': 2,
5736 '&&': 3,
5737 '??': 4,
5738 '|': 5,
5739 '^': 6,
5740 '&': 7,
5741 '==': 8,
5742 '!=': 8,
5743 '===': 8,
5744 '!==': 8,
5745 '<': 9,
5746 '>': 9,
5747 '<=': 9,
5748 '>=': 9,
5749 in: 9,
5750 instanceof: 9,
5751 '<<': 10,
5752 '>>': 10,
5753 '>>>': 10,
5754 '+': 11,
5755 '-': 11,
5756 '*': 12,
5757 '%': 12,
5758 '/': 12,
5759 '**': 13,
5760 };
5761
5762 const EXPRESSIONS_PRECEDENCE = {
5763 ArrayExpression: 20,
5764 TaggedTemplateExpression: 20,
5765 ThisExpression: 20,
5766 Identifier: 20,
5767 Literal: 18,
5768 TemplateLiteral: 20,
5769 Super: 20,
5770 SequenceExpression: 20,
5771 MemberExpression: 19,
5772 CallExpression: 19,
5773 NewExpression: 19,
5774 AwaitExpression: 17,
5775 ClassExpression: 17,
5776 FunctionExpression: 17,
5777 ObjectExpression: 17,
5778 UpdateExpression: 16,
5779 UnaryExpression: 15,
5780 BinaryExpression: 14,
5781 LogicalExpression: 13,
5782 ConditionalExpression: 4,
5783 ArrowFunctionExpression: 3,
5784 AssignmentExpression: 3,
5785 YieldExpression: 2,
5786 RestElement: 1
5787 };
5788
5789 function needs_parens(node, parent, is_right) {
5790 // special case where logical expressions and coalesce expressions cannot be mixed,
5791 // either of them need to be wrapped with parentheses
5792 if (
5793 node.type === 'LogicalExpression' &&
5794 parent.type === 'LogicalExpression' &&
5795 ((parent.operator === '??' && node.operator !== '??') ||
5796 (parent.operator !== '??' && node.operator === '??'))
5797 ) {
5798 return true;
5799 }
5800
5801 const precedence = EXPRESSIONS_PRECEDENCE[node.type];
5802 const parent_precedence = EXPRESSIONS_PRECEDENCE[parent.type];
5803
5804 if (precedence !== parent_precedence) {
5805 // Different node types
5806 return (
5807 (!is_right &&
5808 precedence === 15 &&
5809 parent_precedence === 14 &&
5810 parent.operator === '**') ||
5811 precedence < parent_precedence
5812 );
5813 }
5814
5815 if (precedence !== 13 && precedence !== 14) {
5816 // Not a `LogicalExpression` or `BinaryExpression`
5817 return false;
5818 }
5819
5820 if ((node ).operator === '**' && parent.operator === '**') {
5821 // Exponentiation operator has right-to-left associativity
5822 return !is_right;
5823 }
5824
5825 if (is_right) {
5826 // Parenthesis are used if both operators have the same precedence
5827 return (
5828 OPERATOR_PRECEDENCE[(node ).operator] <=
5829 OPERATOR_PRECEDENCE[parent.operator]
5830 );
5831 }
5832
5833 return (
5834 OPERATOR_PRECEDENCE[(node ).operator] <
5835 OPERATOR_PRECEDENCE[parent.operator]
5836 );
5837 }
5838
5839 function has_call_expression(node) {
5840 while (node) {
5841 if (node.type[0] === 'CallExpression') {
5842 return true;
5843 } else if (node.type === 'MemberExpression') {
5844 node = node.object;
5845 } else {
5846 return false;
5847 }
5848 }
5849 }
5850
5851 const has_newline = (chunks) => {
5852 for (let i = 0; i < chunks.length; i += 1) {
5853 if (chunks[i].has_newline) return true;
5854 }
5855 return false;
5856 };
5857
5858 const get_length = (chunks) => {
5859 let total = 0;
5860 for (let i = 0; i < chunks.length; i += 1) {
5861 total += chunks[i].content.length;
5862 }
5863 return total;
5864 };
5865
5866 const sum = (a, b) => a + b;
5867
5868 const join = (nodes, separator) => {
5869 if (nodes.length === 0) return [];
5870 const joined = [...nodes[0]];
5871 for (let i = 1; i < nodes.length; i += 1) {
5872 joined.push(separator, ...nodes[i] );
5873 }
5874 return joined;
5875 };
5876
5877 const scoped = (fn) => {
5878 return (node, state) => {
5879 return fn(node, {
5880 ...state,
5881 scope: state.scope_map.get(node)
5882 });
5883 };
5884 };
5885
5886 const deconflict = (name, names) => {
5887 const original = name;
5888 let i = 1;
5889
5890 while (names.has(name)) {
5891 name = `${original}$${i++}`;
5892 }
5893
5894 return name;
5895 };
5896
5897 const handle_body = (nodes, state) => {
5898 const chunks = [];
5899
5900 const body = nodes.map(statement => {
5901 const chunks = handle(statement, {
5902 ...state,
5903 indent: state.indent
5904 });
5905
5906 let add_newline = false;
5907
5908 while (state.comments.length) {
5909 const comment = state.comments.shift();
5910 const prefix = add_newline ? `\n${state.indent}` : ` `;
5911
5912 chunks.push(c(comment.type === 'Block'
5913 ? `${prefix}/*${comment.value}*/`
5914 : `${prefix}//${comment.value}`));
5915
5916 add_newline = (comment.type === 'Line');
5917 }
5918
5919 return chunks;
5920 });
5921
5922 let needed_padding = false;
5923
5924 for (let i = 0; i < body.length; i += 1) {
5925 const needs_padding = has_newline(body[i]);
5926
5927 if (i > 0) {
5928 chunks.push(
5929 c(needs_padding || needed_padding ? `\n\n${state.indent}` : `\n${state.indent}`)
5930 );
5931 }
5932
5933 chunks.push(
5934 ...body[i]
5935 );
5936
5937 needed_padding = needs_padding;
5938 }
5939
5940 return chunks;
5941 };
5942
5943 const handle_var_declaration = (node, state) => {
5944 const chunks = [c(`${node.kind} `)];
5945
5946 const declarators = node.declarations.map(d => handle(d, {
5947 ...state,
5948 indent: state.indent + (node.declarations.length === 1 ? '' : '\t')
5949 }));
5950
5951 const multiple_lines = (
5952 declarators.some(has_newline) ||
5953 (declarators.map(get_length).reduce(sum, 0) + (state.indent.length + declarators.length - 1) * 2) > 80
5954 );
5955
5956 const separator = c(multiple_lines ? `,\n${state.indent}\t` : ', ');
5957
5958 if (multiple_lines) {
5959 chunks.push(...join(declarators, separator));
5960 } else {
5961 chunks.push(
5962 ...join(declarators, separator)
5963 );
5964 }
5965
5966 return chunks;
5967 };
5968
5969 const handlers = {
5970 Program(node, state) {
5971 return handle_body(node.body, state);
5972 },
5973
5974 BlockStatement: scoped((node, state) => {
5975 return [
5976 c(`{\n${state.indent}\t`),
5977 ...handle_body(node.body, { ...state, indent: state.indent + '\t' }),
5978 c(`\n${state.indent}}`)
5979 ];
5980 }),
5981
5982 EmptyStatement(node, state) {
5983 return [];
5984 },
5985
5986 ParenthesizedExpression(node, state) {
5987 return handle(node.expression, state);
5988 },
5989
5990 ExpressionStatement(node, state) {
5991 if (
5992 node.expression.type === 'AssignmentExpression' &&
5993 node.expression.left.type === 'ObjectPattern'
5994 ) {
5995 // is an AssignmentExpression to an ObjectPattern
5996 return [
5997 c('('),
5998 ...handle(node.expression, state),
5999 c(');')
6000 ];
6001 }
6002
6003 return [
6004 ...handle(node.expression, state),
6005 c(';')
6006 ];
6007 },
6008
6009 IfStatement(node, state) {
6010 const chunks = [
6011 c('if ('),
6012 ...handle(node.test, state),
6013 c(') '),
6014 ...handle(node.consequent, state)
6015 ];
6016
6017 if (node.alternate) {
6018 chunks.push(
6019 c(' else '),
6020 ...handle(node.alternate, state)
6021 );
6022 }
6023
6024 return chunks;
6025 },
6026
6027 LabeledStatement(node, state) {
6028 return [
6029 ...handle(node.label, state),
6030 c(': '),
6031 ...handle(node.body, state)
6032 ];
6033 },
6034
6035 BreakStatement(node, state) {
6036 return node.label
6037 ? [c('break '), ...handle(node.label, state), c(';')]
6038 : [c('break;')];
6039 },
6040
6041 ContinueStatement(node, state) {
6042 return node.label
6043 ? [c('continue '), ...handle(node.label, state), c(';')]
6044 : [c('continue;')];
6045 },
6046
6047 WithStatement(node, state) {
6048 return [
6049 c('with ('),
6050 ...handle(node.object, state),
6051 c(') '),
6052 ...handle(node.body, state)
6053 ];
6054 },
6055
6056 SwitchStatement(node, state) {
6057 const chunks = [
6058 c('switch ('),
6059 ...handle(node.discriminant, state),
6060 c(') {')
6061 ];
6062
6063 node.cases.forEach(block => {
6064 if (block.test) {
6065 chunks.push(
6066 c(`\n${state.indent}\tcase `),
6067 ...handle(block.test, { ...state, indent: `${state.indent}\t` }),
6068 c(':')
6069 );
6070 } else {
6071 chunks.push(c(`\n${state.indent}\tdefault:`));
6072 }
6073
6074 block.consequent.forEach(statement => {
6075 chunks.push(
6076 c(`\n${state.indent}\t\t`),
6077 ...handle(statement, { ...state, indent: `${state.indent}\t\t` })
6078 );
6079 });
6080 });
6081
6082 chunks.push(c(`\n${state.indent}}`));
6083
6084 return chunks;
6085 },
6086
6087 ReturnStatement(node, state) {
6088 if (node.argument) {
6089 return [
6090 c('return '),
6091 ...handle(node.argument, state),
6092 c(';')
6093 ];
6094 } else {
6095 return [c('return;')];
6096 }
6097 },
6098
6099 ThrowStatement(node, state) {
6100 return [
6101 c('throw '),
6102 ...handle(node.argument, state),
6103 c(';')
6104 ];
6105 },
6106
6107 TryStatement(node, state) {
6108 const chunks = [
6109 c('try '),
6110 ...handle(node.block, state)
6111 ];
6112
6113 if (node.handler) {
6114 if (node.handler.param) {
6115 chunks.push(
6116 c(' catch('),
6117 ...handle(node.handler.param, state),
6118 c(') ')
6119 );
6120 } else {
6121 chunks.push(c(' catch '));
6122 }
6123
6124 chunks.push(...handle(node.handler.body, state));
6125 }
6126
6127 if (node.finalizer) {
6128 chunks.push(c(' finally '), ...handle(node.finalizer, state));
6129 }
6130
6131 return chunks;
6132 },
6133
6134 WhileStatement(node, state) {
6135 return [
6136 c('while ('),
6137 ...handle(node.test, state),
6138 c(') '),
6139 ...handle(node.body, state)
6140 ];
6141 },
6142
6143 DoWhileStatement(node, state) {
6144 return [
6145 c('do '),
6146 ...handle(node.body, state),
6147 c(' while ('),
6148 ...handle(node.test, state),
6149 c(');')
6150 ];
6151 },
6152
6153 ForStatement: scoped((node, state) => {
6154 const chunks = [c('for (')];
6155
6156 if (node.init) {
6157 if ((node.init ).type === 'VariableDeclaration') {
6158 chunks.push(...handle_var_declaration(node.init , state));
6159 } else {
6160 chunks.push(...handle(node.init, state));
6161 }
6162 }
6163
6164 chunks.push(c('; '));
6165 if (node.test) chunks.push(...handle(node.test, state));
6166 chunks.push(c('; '));
6167 if (node.update) chunks.push(...handle(node.update, state));
6168
6169 chunks.push(
6170 c(') '),
6171 ...handle(node.body, state)
6172 );
6173
6174 return chunks;
6175 }),
6176
6177 ForInStatement: scoped((node, state) => {
6178 const chunks = [
6179 c(`for ${(node ).await ? 'await ' : ''}(`)
6180 ];
6181
6182 if ((node.left ).type === 'VariableDeclaration') {
6183 chunks.push(...handle_var_declaration(node.left , state));
6184 } else {
6185 chunks.push(...handle(node.left, state));
6186 }
6187
6188 chunks.push(
6189 c(node.type === 'ForInStatement' ? ` in ` : ` of `),
6190 ...handle(node.right, state),
6191 c(') '),
6192 ...handle(node.body, state)
6193 );
6194
6195 return chunks;
6196 }),
6197
6198 DebuggerStatement(node, state) {
6199 return [c('debugger', node), c(';')];
6200 },
6201
6202 FunctionDeclaration: scoped((node, state) => {
6203 const chunks = [];
6204
6205 if (node.async) chunks.push(c('async '));
6206 chunks.push(c(node.generator ? 'function* ' : 'function '));
6207 if (node.id) chunks.push(...handle(node.id, state));
6208 chunks.push(c('('));
6209
6210 const params = node.params.map(p => handle(p, {
6211 ...state,
6212 indent: state.indent + '\t'
6213 }));
6214
6215 const multiple_lines = (
6216 params.some(has_newline) ||
6217 (params.map(get_length).reduce(sum, 0) + (state.indent.length + params.length - 1) * 2) > 80
6218 );
6219
6220 const separator = c(multiple_lines ? `,\n${state.indent}` : ', ');
6221
6222 if (multiple_lines) {
6223 chunks.push(
6224 c(`\n${state.indent}\t`),
6225 ...join(params, separator),
6226 c(`\n${state.indent}`)
6227 );
6228 } else {
6229 chunks.push(
6230 ...join(params, separator)
6231 );
6232 }
6233
6234 chunks.push(
6235 c(') '),
6236 ...handle(node.body, state)
6237 );
6238
6239 return chunks;
6240 }),
6241
6242 VariableDeclaration(node, state) {
6243 return handle_var_declaration(node, state).concat(c(';'));
6244 },
6245
6246 VariableDeclarator(node, state) {
6247 if (node.init) {
6248 return [
6249 ...handle(node.id, state),
6250 c(' = '),
6251 ...handle(node.init, state)
6252 ];
6253 } else {
6254 return handle(node.id, state);
6255 }
6256 },
6257
6258 ClassDeclaration(node, state) {
6259 const chunks = [c('class ')];
6260
6261 if (node.id) chunks.push(...handle(node.id, state), c(' '));
6262
6263 if (node.superClass) {
6264 chunks.push(
6265 c('extends '),
6266 ...handle(node.superClass, state),
6267 c(' ')
6268 );
6269 }
6270
6271 chunks.push(...handle(node.body, state));
6272
6273 return chunks;
6274 },
6275
6276 ImportDeclaration(node, state) {
6277 const chunks = [c('import ')];
6278
6279 const { length } = node.specifiers;
6280 const source = handle(node.source, state);
6281
6282 if (length > 0) {
6283 let i = 0;
6284
6285 while (i < length) {
6286 if (i > 0) {
6287 chunks.push(c(', '));
6288 }
6289
6290 const specifier = node.specifiers[i];
6291
6292 if (specifier.type === 'ImportDefaultSpecifier') {
6293 chunks.push(c(specifier.local.name, specifier));
6294 i += 1;
6295 } else if (specifier.type === 'ImportNamespaceSpecifier') {
6296 chunks.push(c('* as ' + specifier.local.name, specifier));
6297 i += 1;
6298 } else {
6299 break;
6300 }
6301 }
6302
6303 if (i < length) {
6304 // we have named specifiers
6305 const specifiers = node.specifiers.slice(i).map((specifier) => {
6306 const name = handle(specifier.imported, state)[0];
6307 const as = handle(specifier.local, state)[0];
6308
6309 if (name.content === as.content) {
6310 return [as];
6311 }
6312
6313 return [name, c(' as '), as];
6314 });
6315
6316 const width = get_length(chunks) + specifiers.map(get_length).reduce(sum, 0) + (2 * specifiers.length) + 6 + get_length(source);
6317
6318 if (width > 80) {
6319 chunks.push(
6320 c(`{\n\t`),
6321 ...join(specifiers, c(',\n\t')),
6322 c('\n}')
6323 );
6324 } else {
6325 chunks.push(
6326 c(`{ `),
6327 ...join(specifiers, c(', ')),
6328 c(' }')
6329 );
6330 }
6331 }
6332
6333 chunks.push(c(' from '));
6334 }
6335
6336 chunks.push(
6337 ...source,
6338 c(';')
6339 );
6340
6341 return chunks;
6342 },
6343
6344 ImportExpression(node, state) {
6345 return [c('import('), ...handle(node.source, state), c(')')];
6346 },
6347
6348 ExportDefaultDeclaration(node, state) {
6349 const chunks = [
6350 c(`export default `),
6351 ...handle(node.declaration, state)
6352 ];
6353
6354 if (node.declaration.type !== 'FunctionDeclaration') {
6355 chunks.push(c(';'));
6356 }
6357
6358 return chunks;
6359 },
6360
6361 ExportNamedDeclaration(node, state) {
6362 const chunks = [c('export ')];
6363
6364 if (node.declaration) {
6365 chunks.push(...handle(node.declaration, state));
6366 } else {
6367 const specifiers = node.specifiers.map(specifier => {
6368 const name = handle(specifier.local, state)[0];
6369 const as = handle(specifier.exported, state)[0];
6370
6371 if (name.content === as.content) {
6372 return [name];
6373 }
6374
6375 return [name, c(' as '), as];
6376 });
6377
6378 const width = 7 + specifiers.map(get_length).reduce(sum, 0) + 2 * specifiers.length;
6379
6380 if (width > 80) {
6381 chunks.push(
6382 c('{\n\t'),
6383 ...join(specifiers, c(',\n\t')),
6384 c('\n}')
6385 );
6386 } else {
6387 chunks.push(
6388 c('{ '),
6389 ...join(specifiers, c(', ')),
6390 c(' }')
6391 );
6392 }
6393
6394 if (node.source) {
6395 chunks.push(
6396 c(' from '),
6397 ...handle(node.source, state)
6398 );
6399 }
6400 }
6401
6402 chunks.push(c(';'));
6403
6404 return chunks;
6405 },
6406
6407 ExportAllDeclaration(node, state) {
6408 return [
6409 c(`export * from `),
6410 ...handle(node.source, state),
6411 c(`;`)
6412 ];
6413 },
6414
6415 MethodDefinition(node, state) {
6416 const chunks = [];
6417
6418 if (node.static) {
6419 chunks.push(c('static '));
6420 }
6421
6422 if (node.kind === 'get' || node.kind === 'set') {
6423 // Getter or setter
6424 chunks.push(c(node.kind + ' '));
6425 }
6426
6427 if (node.value.async) {
6428 chunks.push(c('async '));
6429 }
6430
6431 if (node.value.generator) {
6432 chunks.push(c('*'));
6433 }
6434
6435 if (node.computed) {
6436 chunks.push(
6437 c('['),
6438 ...handle(node.key, state),
6439 c(']')
6440 );
6441 } else {
6442 chunks.push(...handle(node.key, state));
6443 }
6444
6445 chunks.push(c('('));
6446
6447 const { params } = node.value;
6448 for (let i = 0; i < params.length; i += 1) {
6449 chunks.push(...handle(params[i], state));
6450 if (i < params.length - 1) chunks.push(c(', '));
6451 }
6452
6453 chunks.push(
6454 c(') '),
6455 ...handle(node.value.body, state)
6456 );
6457
6458 return chunks;
6459 },
6460
6461 ArrowFunctionExpression: scoped((node, state) => {
6462 const chunks = [];
6463
6464 if (node.async) chunks.push(c('async '));
6465
6466 if (node.params.length === 1 && node.params[0].type === 'Identifier') {
6467 chunks.push(...handle(node.params[0], state));
6468 } else {
6469 const params = node.params.map(param => handle(param, {
6470 ...state,
6471 indent: state.indent + '\t'
6472 }));
6473
6474 chunks.push(
6475 c('('),
6476 ...join(params, c(', ')),
6477 c(')')
6478 );
6479 }
6480
6481 chunks.push(c(' => '));
6482
6483 if (node.body.type === 'ObjectExpression') {
6484 chunks.push(
6485 c('('),
6486 ...handle(node.body, state),
6487 c(')')
6488 );
6489 } else {
6490 chunks.push(...handle(node.body, state));
6491 }
6492
6493 return chunks;
6494 }),
6495
6496 ThisExpression(node, state) {
6497 return [c('this', node)];
6498 },
6499
6500 Super(node, state) {
6501 return [c('super', node)];
6502 },
6503
6504 RestElement(node, state) {
6505 return [c('...'), ...handle(node.argument, state)];
6506 },
6507
6508 YieldExpression(node, state) {
6509 if (node.argument) {
6510 return [c(node.delegate ? `yield* ` : `yield `), ...handle(node.argument, state)];
6511 }
6512
6513 return [c(node.delegate ? `yield*` : `yield`)];
6514 },
6515
6516 AwaitExpression(node, state) {
6517 if (node.argument) {
6518 const precedence = EXPRESSIONS_PRECEDENCE[node.argument.type];
6519
6520 if (precedence && (precedence < EXPRESSIONS_PRECEDENCE.AwaitExpression)) {
6521 return [c('await ('), ...handle(node.argument, state), c(')')];
6522 } else {
6523 return [c('await '), ...handle(node.argument, state)];
6524 }
6525 }
6526
6527 return [c('await')];
6528 },
6529
6530 TemplateLiteral(node, state) {
6531 const chunks = [c('`')];
6532
6533 const { quasis, expressions } = node;
6534
6535 for (let i = 0; i < expressions.length; i++) {
6536 chunks.push(
6537 c(quasis[i].value.raw),
6538 c('${'),
6539 ...handle(expressions[i], state),
6540 c('}')
6541 );
6542 }
6543
6544 chunks.push(
6545 c(quasis[quasis.length - 1].value.raw),
6546 c('`')
6547 );
6548
6549 return chunks;
6550 },
6551
6552 TaggedTemplateExpression(node, state) {
6553 return handle(node.tag, state).concat(handle(node.quasi, state));
6554 },
6555
6556 ArrayExpression(node, state) {
6557 const chunks = [c('[')];
6558
6559 const elements = [];
6560 let sparse_commas = [];
6561
6562 for (let i = 0; i < node.elements.length; i += 1) {
6563 // can't use map/forEach because of sparse arrays
6564 const element = node.elements[i];
6565 if (element) {
6566 elements.push([...sparse_commas, ...handle(element, {
6567 ...state,
6568 indent: state.indent + '\t'
6569 })]);
6570 sparse_commas = [];
6571 } else {
6572 sparse_commas.push(c(','));
6573 }
6574 }
6575
6576 const multiple_lines = (
6577 elements.some(has_newline) ||
6578 (elements.map(get_length).reduce(sum, 0) + (state.indent.length + elements.length - 1) * 2) > 80
6579 );
6580
6581 if (multiple_lines) {
6582 chunks.push(
6583 c(`\n${state.indent}\t`),
6584 ...join(elements, c(`,\n${state.indent}\t`)),
6585 c(`\n${state.indent}`),
6586 ...sparse_commas
6587 );
6588 } else {
6589 chunks.push(...join(elements, c(', ')), ...sparse_commas);
6590 }
6591
6592 chunks.push(c(']'));
6593
6594 return chunks;
6595 },
6596
6597 ObjectExpression(node, state) {
6598 if (node.properties.length === 0) {
6599 return [c('{}')];
6600 }
6601
6602 let has_inline_comment = false;
6603
6604 const chunks = [];
6605 const separator = c(', ');
6606
6607 node.properties.forEach((p, i) => {
6608 chunks.push(...handle(p, {
6609 ...state,
6610 indent: state.indent + '\t'
6611 }));
6612
6613 if (state.comments.length) {
6614 // TODO generalise this, so it works with ArrayExpressions and other things.
6615 // At present, stuff will just get appended to the closest statement/declaration
6616 chunks.push(c(', '));
6617
6618 while (state.comments.length) {
6619 const comment = state.comments.shift();
6620
6621 chunks.push(c(comment.type === 'Block'
6622 ? `/*${comment.value}*/\n${state.indent}\t`
6623 : `//${comment.value}\n${state.indent}\t`));
6624
6625 if (comment.type === 'Line') {
6626 has_inline_comment = true;
6627 }
6628 }
6629 } else {
6630 if (i < node.properties.length - 1) {
6631 chunks.push(separator);
6632 }
6633 }
6634 });
6635
6636 const multiple_lines = (
6637 has_inline_comment ||
6638 has_newline(chunks) ||
6639 get_length(chunks) > 40
6640 );
6641
6642 if (multiple_lines) {
6643 separator.content = `,\n${state.indent}\t`;
6644 }
6645
6646 return [
6647 c(multiple_lines ? `{\n${state.indent}\t` : `{ `),
6648 ...chunks,
6649 c(multiple_lines ? `\n${state.indent}}` : ` }`)
6650 ];
6651 },
6652
6653 Property(node, state) {
6654 const value = handle(node.value, state);
6655
6656 if (node.key === node.value) {
6657 return value;
6658 }
6659
6660 // special case
6661 if (
6662 !node.computed &&
6663 node.value.type === 'AssignmentPattern' &&
6664 node.value.left.type === 'Identifier' &&
6665 node.value.left.name === (node.key ).name
6666 ) {
6667 return value;
6668 }
6669
6670 if (node.value.type === 'Identifier' && (
6671 (node.key.type === 'Identifier' && node.key.name === value[0].content) ||
6672 (node.key.type === 'Literal' && node.key.value === value[0].content)
6673 )) {
6674 return value;
6675 }
6676
6677 const key = handle(node.key, state);
6678
6679 if (node.value.type === 'FunctionExpression' && !node.value.id) {
6680 state = {
6681 ...state,
6682 scope: state.scope_map.get(node.value)
6683 };
6684
6685 const chunks = node.kind !== 'init'
6686 ? [c(`${node.kind} `)]
6687 : [];
6688
6689 if (node.value.async) {
6690 chunks.push(c('async '));
6691 }
6692 if (node.value.generator) {
6693 chunks.push(c('*'));
6694 }
6695
6696 chunks.push(
6697 ...(node.computed ? [c('['), ...key, c(']')] : key),
6698 c('('),
6699 ...join((node.value ).params.map(param => handle(param, state)), c(', ')),
6700 c(') '),
6701 ...handle((node.value ).body, state)
6702 );
6703
6704 return chunks;
6705 }
6706
6707 if (node.computed) {
6708 return [
6709 c('['),
6710 ...key,
6711 c(']: '),
6712 ...value
6713 ];
6714 }
6715
6716 return [
6717 ...key,
6718 c(': '),
6719 ...value
6720 ];
6721 },
6722
6723 ObjectPattern(node, state) {
6724 const chunks = [c('{ ')];
6725
6726 for (let i = 0; i < node.properties.length; i += 1) {
6727 chunks.push(...handle(node.properties[i], state));
6728 if (i < node.properties.length - 1) chunks.push(c(', '));
6729 }
6730
6731 chunks.push(c(' }'));
6732
6733 return chunks;
6734 },
6735
6736 SequenceExpression(node, state) {
6737 const expressions = node.expressions.map(e => handle(e, state));
6738
6739 return [
6740 c('('),
6741 ...join(expressions, c(', ')),
6742 c(')')
6743 ];
6744 },
6745
6746 UnaryExpression(node, state) {
6747 const chunks = [c(node.operator)];
6748
6749 if (node.operator.length > 1) {
6750 chunks.push(c(' '));
6751 }
6752
6753 if (
6754 EXPRESSIONS_PRECEDENCE[node.argument.type] <
6755 EXPRESSIONS_PRECEDENCE.UnaryExpression
6756 ) {
6757 chunks.push(
6758 c('('),
6759 ...handle(node.argument, state),
6760 c(')')
6761 );
6762 } else {
6763 chunks.push(...handle(node.argument, state));
6764 }
6765
6766 return chunks;
6767 },
6768
6769 UpdateExpression(node, state) {
6770 return node.prefix
6771 ? [c(node.operator), ...handle(node.argument, state)]
6772 : [...handle(node.argument, state), c(node.operator)];
6773 },
6774
6775 AssignmentExpression(node, state) {
6776 return [
6777 ...handle(node.left, state),
6778 c(` ${node.operator || '='} `),
6779 ...handle(node.right, state)
6780 ];
6781 },
6782
6783 BinaryExpression(node, state) {
6784 const chunks = [];
6785
6786 // TODO
6787 // const is_in = node.operator === 'in';
6788 // if (is_in) {
6789 // // Avoids confusion in `for` loops initializers
6790 // chunks.push(c('('));
6791 // }
6792
6793 if (needs_parens(node.left, node, false)) {
6794 chunks.push(
6795 c('('),
6796 ...handle(node.left, state),
6797 c(')')
6798 );
6799 } else {
6800 chunks.push(...handle(node.left, state));
6801 }
6802
6803 chunks.push(c(` ${node.operator} `));
6804
6805 if (needs_parens(node.right, node, true)) {
6806 chunks.push(
6807 c('('),
6808 ...handle(node.right, state),
6809 c(')')
6810 );
6811 } else {
6812 chunks.push(...handle(node.right, state));
6813 }
6814
6815 return chunks;
6816 },
6817
6818 ConditionalExpression(node, state) {
6819 const chunks = [];
6820
6821 if (
6822 EXPRESSIONS_PRECEDENCE[node.test.type] >
6823 EXPRESSIONS_PRECEDENCE.ConditionalExpression
6824 ) {
6825 chunks.push(...handle(node.test, state));
6826 } else {
6827 chunks.push(
6828 c('('),
6829 ...handle(node.test, state),
6830 c(')')
6831 );
6832 }
6833
6834 const child_state = { ...state, indent: state.indent + '\t' };
6835
6836 const consequent = handle(node.consequent, child_state);
6837 const alternate = handle(node.alternate, child_state);
6838
6839 const multiple_lines = (
6840 has_newline(consequent) || has_newline(alternate) ||
6841 get_length(chunks) + get_length(consequent) + get_length(alternate) > 50
6842 );
6843
6844 if (multiple_lines) {
6845 chunks.push(
6846 c(`\n${state.indent}? `),
6847 ...consequent,
6848 c(`\n${state.indent}: `),
6849 ...alternate
6850 );
6851 } else {
6852 chunks.push(
6853 c(` ? `),
6854 ...consequent,
6855 c(` : `),
6856 ...alternate
6857 );
6858 }
6859
6860 return chunks;
6861 },
6862
6863 NewExpression(node, state) {
6864 const chunks = [c('new ')];
6865
6866 if (
6867 EXPRESSIONS_PRECEDENCE[node.callee.type] <
6868 EXPRESSIONS_PRECEDENCE.CallExpression || has_call_expression(node.callee)
6869 ) {
6870 chunks.push(
6871 c('('),
6872 ...handle(node.callee, state),
6873 c(')')
6874 );
6875 } else {
6876 chunks.push(...handle(node.callee, state));
6877 }
6878
6879 // TODO this is copied from CallExpression — DRY it out
6880 const args = node.arguments.map(arg => handle(arg, {
6881 ...state,
6882 indent: state.indent + '\t'
6883 }));
6884
6885 const separator = args.some(has_newline) // TODO or length exceeds 80
6886 ? c(',\n' + state.indent)
6887 : c(', ');
6888
6889 chunks.push(
6890 c('('),
6891 ...join(args, separator) ,
6892 c(')')
6893 );
6894
6895 return chunks;
6896 },
6897
6898 ChainExpression(node, state) {
6899 return handle(node.expression, state);
6900 },
6901
6902 CallExpression(node, state) {
6903 const chunks = [];
6904
6905 if (
6906 EXPRESSIONS_PRECEDENCE[node.callee.type] <
6907 EXPRESSIONS_PRECEDENCE.CallExpression
6908 ) {
6909 chunks.push(
6910 c('('),
6911 ...handle(node.callee, state),
6912 c(')')
6913 );
6914 } else {
6915 chunks.push(...handle(node.callee, state));
6916 }
6917
6918 if ((node ).optional) {
6919 chunks.push(c('?.'));
6920 }
6921
6922 const args = node.arguments.map(arg => handle(arg, state));
6923
6924 const multiple_lines = args.slice(0, -1).some(has_newline); // TODO or length exceeds 80
6925
6926 if (multiple_lines) {
6927 // need to handle args again. TODO find alternative approach?
6928 const args = node.arguments.map(arg => handle(arg, {
6929 ...state,
6930 indent: `${state.indent}\t`
6931 }));
6932
6933 chunks.push(
6934 c(`(\n${state.indent}\t`),
6935 ...join(args, c(`,\n${state.indent}\t`)),
6936 c(`\n${state.indent})`)
6937 );
6938 } else {
6939 chunks.push(
6940 c('('),
6941 ...join(args, c(', ')),
6942 c(')')
6943 );
6944 }
6945
6946 return chunks;
6947 },
6948
6949 MemberExpression(node, state) {
6950 const chunks = [];
6951
6952 if (EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression) {
6953 chunks.push(
6954 c('('),
6955 ...handle(node.object, state),
6956 c(')')
6957 );
6958 } else {
6959 chunks.push(...handle(node.object, state));
6960 }
6961
6962 if (node.computed) {
6963 if (node.optional) {
6964 chunks.push(c('?.'));
6965 }
6966 chunks.push(
6967 c('['),
6968 ...handle(node.property, state),
6969 c(']')
6970 );
6971 } else {
6972 chunks.push(
6973 c(node.optional ? '?.' : '.'),
6974 ...handle(node.property, state)
6975 );
6976 }
6977
6978 return chunks;
6979 },
6980
6981 MetaProperty(node, state) {
6982 return [...handle(node.meta, state), c('.'), ...handle(node.property, state)];
6983 },
6984
6985 Identifier(node, state) {
6986 let name = node.name;
6987
6988 if (name[0] === '@') {
6989 name = state.getName(name.slice(1));
6990 } else if (node.name[0] === '#') {
6991 const owner = state.scope.find_owner(node.name);
6992
6993 if (!owner) {
6994 throw new Error(`Could not find owner for node`);
6995 }
6996
6997 if (!state.deconflicted.has(owner)) {
6998 state.deconflicted.set(owner, new Map());
6999 }
7000
7001 const deconflict_map = state.deconflicted.get(owner);
7002
7003 if (!deconflict_map.has(node.name)) {
7004 deconflict_map.set(node.name, deconflict(node.name.slice(1), owner.references));
7005 }
7006
7007 name = deconflict_map.get(node.name);
7008 }
7009
7010 return [c(name, node)];
7011 },
7012
7013 Literal(node, state) {
7014 if (typeof node.value === 'string') {
7015 return [
7016 // TODO do we need to handle weird unicode characters somehow?
7017 // str.replace(/\\u(\d{4})/g, (m, n) => String.fromCharCode(+n))
7018 c(JSON.stringify(node.value).replace(re, (_m, _i, at, hash, name) => {
7019 if (at) return '@' + name;
7020 if (hash) return '#' + name;
7021 throw new Error(`this shouldn't happen`);
7022 }), node)
7023 ];
7024 }
7025
7026 const { regex } = node ; // TODO is this right?
7027 if (regex) {
7028 return [c(`/${regex.pattern}/${regex.flags}`, node)];
7029 }
7030
7031 return [c(String(node.value), node)];
7032 }
7033 };
7034
7035 handlers.ForOfStatement = handlers.ForInStatement;
7036 handlers.FunctionExpression = handlers.FunctionDeclaration;
7037 handlers.ClassExpression = handlers.ClassDeclaration;
7038 handlers.ClassBody = handlers.BlockStatement;
7039 handlers.SpreadElement = handlers.RestElement;
7040 handlers.ArrayPattern = handlers.ArrayExpression;
7041 handlers.LogicalExpression = handlers.BinaryExpression;
7042 handlers.AssignmentPattern = handlers.AssignmentExpression;
7043
7044 let btoa$1 = () => {
7045 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
7046 };
7047 if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
7048 btoa$1 = (str) => window.btoa(unescape(encodeURIComponent(str)));
7049 } else if (typeof Buffer === 'function') {
7050 btoa$1 = (str) => Buffer.from(str, 'utf-8').toString('base64');
7051 }
7052
7053
7054
7055
7056
7057
7058
7059
7060 function print(node, opts = {}) {
7061 if (Array.isArray(node)) {
7062 return print({
7063 type: 'Program',
7064 body: node
7065 } , opts);
7066 }
7067
7068 const {
7069 getName = (x) => {
7070 throw new Error(`Unhandled sigil @${x}`);
7071 }
7072 } = opts;
7073
7074 let { map: scope_map, scope } = analyze(node);
7075 const deconflicted = new WeakMap();
7076
7077 const chunks = handle(node, {
7078 indent: '',
7079 getName,
7080 scope,
7081 scope_map,
7082 deconflicted,
7083 comments: []
7084 });
7085
7086
7087
7088 let code = '';
7089 let mappings = [];
7090 let current_line = [];
7091 let current_column = 0;
7092
7093 for (let i = 0; i < chunks.length; i += 1) {
7094 const chunk = chunks[i];
7095
7096 code += chunk.content;
7097
7098 if (chunk.loc) {
7099 current_line.push([
7100 current_column,
7101 0, // source index is always zero
7102 chunk.loc.start.line - 1,
7103 chunk.loc.start.column,
7104 ]);
7105 }
7106
7107 for (let i = 0; i < chunk.content.length; i += 1) {
7108 if (chunk.content[i] === '\n') {
7109 mappings.push(current_line);
7110 current_line = [];
7111 current_column = 0;
7112 } else {
7113 current_column += 1;
7114 }
7115 }
7116
7117 if (chunk.loc) {
7118 current_line.push([
7119 current_column,
7120 0, // source index is always zero
7121 chunk.loc.end.line - 1,
7122 chunk.loc.end.column,
7123 ]);
7124 }
7125 }
7126
7127 mappings.push(current_line);
7128
7129 const map = {
7130 version: 3,
7131 names: [] ,
7132 sources: [opts.sourceMapSource || null],
7133 sourcesContent: [opts.sourceMapContent || null],
7134 mappings: encode(mappings)
7135 };
7136
7137 Object.defineProperties(map, {
7138 toString: {
7139 enumerable: false,
7140 value: function toString() {
7141 return JSON.stringify(this);
7142 }
7143 },
7144 toUrl: {
7145 enumerable: false,
7146 value: function toUrl() {
7147 return 'data:application/json;charset=utf-8;base64,' + btoa$1(this.toString());
7148 }
7149 }
7150 });
7151
7152 return {
7153 code,
7154 map
7155 };
7156 }
7157
7158 const sigils = {
7159 '@': 'AT',
7160 '#': 'HASH'
7161 };
7162
7163 const join$1 = (strings) => {
7164 let str = strings[0];
7165 for (let i = 1; i < strings.length; i += 1) {
7166 str += `_${id}_${i - 1}_${strings[i]}`;
7167 }
7168 return str.replace(/([@#])(\w+)/g, (_m, sigil, name) => `_${id}_${sigils[sigil]}_${name}`);
7169 };
7170
7171 const flatten_body = (array, target) => {
7172 for (let i = 0; i < array.length; i += 1) {
7173 const statement = array[i];
7174 if (Array.isArray(statement)) {
7175 flatten_body(statement, target);
7176 continue;
7177 }
7178
7179 if (statement.type === 'ExpressionStatement') {
7180 if (statement.expression === EMPTY) continue;
7181
7182 if (Array.isArray(statement.expression)) {
7183 // TODO this is hacktacular
7184 let node = statement.expression[0];
7185 while (Array.isArray(node)) node = node[0];
7186 if (node) node.leadingComments = statement.leadingComments;
7187
7188 flatten_body(statement.expression, target);
7189 continue;
7190 }
7191
7192 if (/(Expression|Literal)$/.test(statement.expression.type)) {
7193 target.push(statement);
7194 continue;
7195 }
7196
7197 if (statement.leadingComments) statement.expression.leadingComments = statement.leadingComments;
7198 if (statement.trailingComments) statement.expression.trailingComments = statement.trailingComments;
7199
7200 target.push(statement.expression);
7201 continue;
7202 }
7203
7204 target.push(statement);
7205 }
7206
7207 return target;
7208 };
7209
7210 const flatten_properties = (array, target) => {
7211 for (let i = 0; i < array.length; i += 1) {
7212 const property = array[i];
7213
7214 if (property.value === EMPTY) continue;
7215
7216 if (property.key === property.value && Array.isArray(property.key)) {
7217 flatten_properties(property.key, target);
7218 continue;
7219 }
7220
7221 target.push(property);
7222 }
7223
7224 return target;
7225 };
7226
7227 const flatten = (nodes, target) => {
7228 for (let i = 0; i < nodes.length; i += 1) {
7229 const node = nodes[i];
7230
7231 if (node === EMPTY) continue;
7232
7233 if (Array.isArray(node)) {
7234 flatten(node, target);
7235 continue;
7236 }
7237
7238 target.push(node);
7239 }
7240
7241 return target;
7242 };
7243
7244 const EMPTY = { type: 'Empty' };
7245
7246 const acorn_opts = (comments, raw) => {
7247 const { onComment } = get_comment_handlers(comments, raw);
7248 return {
7249 ecmaVersion: 2020,
7250 sourceType: 'module',
7251 allowAwaitOutsideFunction: true,
7252 allowImportExportEverywhere: true,
7253 allowReturnOutsideFunction: true,
7254 onComment
7255 } ;
7256 };
7257
7258 const inject = (raw, node, values, comments) => {
7259 comments.forEach(comment => {
7260 comment.value = comment.value.replace(re, (m, i) => +i in values ? values[+i] : m);
7261 });
7262
7263 const { enter, leave } = get_comment_handlers(comments, raw);
7264
7265 walk(node, {
7266 enter,
7267
7268 leave(node, parent, key, index) {
7269 if (node.type === 'Identifier') {
7270 re.lastIndex = 0;
7271 const match = re.exec(node.name);
7272
7273 if (match) {
7274 if (match[1]) {
7275 if (+match[1] in values) {
7276 let value = values[+match[1]];
7277
7278 if (typeof value === 'string') {
7279 value = { type: 'Identifier', name: value, leadingComments: node.leadingComments, trailingComments: node.trailingComments };
7280 } else if (typeof value === 'number') {
7281 value = { type: 'Literal', value, leadingComments: node.leadingComments, trailingComments: node.trailingComments };
7282 }
7283
7284 this.replace(value || EMPTY);
7285 }
7286 } else {
7287 node.name = `${match[2] ? `@` : `#`}${match[4]}`;
7288 }
7289 }
7290 }
7291
7292 if (node.type === 'Literal') {
7293 if (typeof node.value === 'string') {
7294 re.lastIndex = 0;
7295 node.value = node.value.replace(re, (m, i) => +i in values ? values[+i] : m);
7296 }
7297 }
7298
7299 if (node.type === 'TemplateElement') {
7300 re.lastIndex = 0;
7301 node.value.raw = (node.value.raw ).replace(re, (m, i) => +i in values ? values[+i] : m);
7302 }
7303
7304 if (node.type === 'Program' || node.type === 'BlockStatement') {
7305 node.body = flatten_body(node.body, []);
7306 }
7307
7308 if (node.type === 'ObjectExpression' || node.type === 'ObjectPattern') {
7309 node.properties = flatten_properties(node.properties, []);
7310 }
7311
7312 if (node.type === 'ArrayExpression' || node.type === 'ArrayPattern') {
7313 node.elements = flatten(node.elements, []);
7314 }
7315
7316 if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') {
7317 node.params = flatten(node.params, []);
7318 }
7319
7320 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
7321 node.arguments = flatten(node.arguments, []);
7322 }
7323
7324 if (node.type === 'ImportDeclaration' || node.type === 'ExportNamedDeclaration') {
7325 node.specifiers = flatten(node.specifiers, []);
7326 }
7327
7328 if (node.type === 'ForStatement') {
7329 node.init = node.init === EMPTY ? null : node.init;
7330 node.test = node.test === EMPTY ? null : node.test;
7331 node.update = node.update === EMPTY ? null : node.update;
7332 }
7333
7334 leave(node);
7335 }
7336 });
7337 };
7338
7339 function b(strings, ...values) {
7340 const str = join$1(strings);
7341 const comments = [];
7342
7343 try {
7344 const ast = parse(str, acorn_opts(comments, str));
7345
7346 inject(str, ast, values, comments);
7347
7348 return ast.body;
7349 } catch (err) {
7350 handle_error(str, err);
7351 }
7352 }
7353
7354 function x(strings, ...values) {
7355 const str = join$1(strings);
7356 const comments = [];
7357
7358 try {
7359 const expression = parseExpressionAt(str, 0, acorn_opts(comments, str)) ;
7360 const match = /\S+/.exec(str.slice((expression ).end));
7361 if (match) {
7362 throw new Error(`Unexpected token '${match[0]}'`);
7363 }
7364
7365 inject(str, expression, values, comments);
7366
7367 return expression;
7368 } catch (err) {
7369 handle_error(str, err);
7370 }
7371 }
7372
7373 function p(strings, ...values) {
7374 const str = `{${join$1(strings)}}`;
7375 const comments = [];
7376
7377 try {
7378 const expression = parseExpressionAt(str, 0, acorn_opts(comments, str)) ;
7379
7380 inject(str, expression, values, comments);
7381
7382 return expression.properties[0];
7383 } catch (err) {
7384 handle_error(str, err);
7385 }
7386 }
7387
7388 function handle_error(str, err) {
7389 // TODO location/code frame
7390
7391 re.lastIndex = 0;
7392
7393 str = str.replace(re, (m, i, at, hash, name) => {
7394 if (at) return `@${name}`;
7395 if (hash) return `#${name}`;
7396
7397 return '${...}';
7398 });
7399
7400 console.log(`failed to parse:\n${str}`);
7401 throw err;
7402 }
7403
7404 const parse$1 = (source, opts) => {
7405 const comments = [];
7406 const { onComment, enter, leave } = get_comment_handlers(comments, source);
7407 const ast = parse(source, { onComment, ...opts });
7408 walk(ast , { enter, leave });
7409 return ast;
7410 };
7411
7412 const parseExpressionAt$1 = (source, index, opts) => {
7413 const comments = [];
7414 const { onComment, enter, leave } = get_comment_handlers(comments, source);
7415 const ast = parseExpressionAt(source, index, { onComment, ...opts });
7416 walk(ast , { enter, leave });
7417 return ast;
7418 };
7419
7420 const parse$2 = (source) => parse$1(source, {
7421 sourceType: 'module',
7422 ecmaVersion: 12,
7423 locations: true
7424 });
7425 const parse_expression_at = (source, index) => parseExpressionAt$1(source, index, {
7426 sourceType: 'module',
7427 ecmaVersion: 12,
7428 locations: true
7429 });
7430
7431 const whitespace = /[ \t\r\n]/;
7432 const dimensions = /^(?:offset|client)(?:Width|Height)$/;
7433
7434 function read_expression(parser) {
7435 try {
7436 const node = parse_expression_at(parser.template, parser.index);
7437 let num_parens = 0;
7438 for (let i = parser.index; i < node.start; i += 1) {
7439 if (parser.template[i] === '(')
7440 num_parens += 1;
7441 }
7442 let index = node.end;
7443 while (num_parens > 0) {
7444 const char = parser.template[index];
7445 if (char === ')') {
7446 num_parens -= 1;
7447 }
7448 else if (!whitespace.test(char)) {
7449 parser.error({
7450 code: 'unexpected-token',
7451 message: 'Expected )'
7452 }, index);
7453 }
7454 index += 1;
7455 }
7456 parser.index = index;
7457 return node;
7458 }
7459 catch (err) {
7460 parser.acorn_error(err);
7461 }
7462 }
7463
7464 const script_closing_tag = '</script>';
7465 function get_context(parser, attributes, start) {
7466 const context = attributes.find(attribute => attribute.name === 'context');
7467 if (!context)
7468 return 'default';
7469 if (context.value.length !== 1 || context.value[0].type !== 'Text') {
7470 parser.error({
7471 code: 'invalid-script',
7472 message: 'context attribute must be static'
7473 }, start);
7474 }
7475 const value = context.value[0].data;
7476 if (value !== 'module') {
7477 parser.error({
7478 code: 'invalid-script',
7479 message: 'If the context attribute is supplied, its value must be "module"'
7480 }, context.start);
7481 }
7482 return value;
7483 }
7484 function read_script(parser, start, attributes) {
7485 const script_start = parser.index;
7486 const script_end = parser.template.indexOf(script_closing_tag, script_start);
7487 if (script_end === -1) {
7488 parser.error({
7489 code: 'unclosed-script',
7490 message: '<script> must have a closing tag'
7491 });
7492 }
7493 const source = parser.template.slice(0, script_start).replace(/[^\n]/g, ' ') +
7494 parser.template.slice(script_start, script_end);
7495 parser.index = script_end + script_closing_tag.length;
7496 let ast;
7497 try {
7498 ast = parse$2(source);
7499 }
7500 catch (err) {
7501 parser.acorn_error(err);
7502 }
7503 // TODO is this necessary?
7504 ast.start = script_start;
7505 return {
7506 type: 'Script',
7507 start,
7508 end: parser.index,
7509 context: get_context(parser, attributes, start),
7510 content: ast
7511 };
7512 }
7513
7514 var MAX_LINE_LENGTH = 100;
7515 var OFFSET_CORRECTION = 60;
7516 var TAB_REPLACEMENT = ' ';
7517
7518 function sourceFragment(error, extraLines) {
7519 function processLines(start, end) {
7520 return lines.slice(start, end).map(function(line, idx) {
7521 var num = String(start + idx + 1);
7522
7523 while (num.length < maxNumLength) {
7524 num = ' ' + num;
7525 }
7526
7527 return num + ' |' + line;
7528 }).join('\n');
7529 }
7530
7531 var lines = error.source.split(/\n|\r\n?|\f/);
7532 var line = error.line;
7533 var column = error.column;
7534 var startLine = Math.max(1, line - extraLines) - 1;
7535 var endLine = Math.min(line + extraLines, lines.length + 1);
7536 var maxNumLength = Math.max(4, String(endLine).length) + 1;
7537 var cutLeft = 0;
7538
7539 // correct column according to replaced tab before column
7540 column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;
7541
7542 if (column > MAX_LINE_LENGTH) {
7543 cutLeft = column - OFFSET_CORRECTION + 3;
7544 column = OFFSET_CORRECTION - 2;
7545 }
7546
7547 for (var i = startLine; i <= endLine; i++) {
7548 if (i >= 0 && i < lines.length) {
7549 lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT);
7550 lines[i] =
7551 (cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
7552 lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
7553 (lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
7554 }
7555 }
7556
7557 return [
7558 processLines(startLine, line),
7559 new Array(column + maxNumLength + 2).join('-') + '^',
7560 processLines(line, endLine)
7561 ].join('\n');
7562 }
7563
7564 var CssSyntaxError = function(message, source, offset, line, column) {
7565 // some VMs prevent setting line/column otherwise (iOS Safari 10 even throw an exception)
7566 var error = Object.create(SyntaxError.prototype);
7567
7568 error.name = 'CssSyntaxError';
7569 error.message = message;
7570 error.stack = (new Error().stack || '').replace(/^.+\n/, error.name + ': ' + error.message + '\n');
7571 error.source = source;
7572 error.offset = offset;
7573 error.line = line;
7574 error.column = column;
7575
7576 error.sourceFragment = function(extraLines) {
7577 return sourceFragment(error, isNaN(extraLines) ? 0 : extraLines);
7578 };
7579 Object.defineProperty(error, 'formattedMessage', {
7580 get: function() {
7581 return (
7582 'Parse error: ' + error.message + '\n' +
7583 sourceFragment(error, 2)
7584 );
7585 }
7586 });
7587
7588 // for backward capability
7589 error.parseError = {
7590 offset: offset,
7591 line: line,
7592 column: column
7593 };
7594
7595 return error;
7596 };
7597
7598 var error = CssSyntaxError;
7599
7600 // token types (note: value shouldn't intersect with used char codes)
7601 var WHITESPACE = 1;
7602 var IDENTIFIER = 2;
7603 var NUMBER = 3;
7604 var STRING = 4;
7605 var COMMENT = 5;
7606 var PUNCTUATOR = 6;
7607 var CDO = 7;
7608 var CDC = 8;
7609 var ATRULE = 14;
7610 var FUNCTION = 15;
7611 var URL$1 = 16;
7612 var RAW = 17;
7613
7614 var TAB = 9;
7615 var N = 10;
7616 var F = 12;
7617 var R = 13;
7618 var SPACE = 32;
7619
7620 var TYPE = {
7621 WhiteSpace: WHITESPACE,
7622 Identifier: IDENTIFIER,
7623 Number: NUMBER,
7624 String: STRING,
7625 Comment: COMMENT,
7626 Punctuator: PUNCTUATOR,
7627 CDO: CDO,
7628 CDC: CDC,
7629 Atrule: ATRULE,
7630 Function: FUNCTION,
7631 Url: URL$1,
7632 Raw: RAW,
7633
7634 ExclamationMark: 33, // !
7635 QuotationMark: 34, // "
7636 NumberSign: 35, // #
7637 DollarSign: 36, // $
7638 PercentSign: 37, // %
7639 Ampersand: 38, // &
7640 Apostrophe: 39, // '
7641 LeftParenthesis: 40, // (
7642 RightParenthesis: 41, // )
7643 Asterisk: 42, // *
7644 PlusSign: 43, // +
7645 Comma: 44, // ,
7646 HyphenMinus: 45, // -
7647 FullStop: 46, // .
7648 Solidus: 47, // /
7649 Colon: 58, // :
7650 Semicolon: 59, // ;
7651 LessThanSign: 60, // <
7652 EqualsSign: 61, // =
7653 GreaterThanSign: 62, // >
7654 QuestionMark: 63, // ?
7655 CommercialAt: 64, // @
7656 LeftSquareBracket: 91, // [
7657 Backslash: 92, // \
7658 RightSquareBracket: 93, // ]
7659 CircumflexAccent: 94, // ^
7660 LowLine: 95, // _
7661 GraveAccent: 96, // `
7662 LeftCurlyBracket: 123, // {
7663 VerticalLine: 124, // |
7664 RightCurlyBracket: 125, // }
7665 Tilde: 126 // ~
7666 };
7667
7668 var NAME = Object.keys(TYPE).reduce(function(result, key) {
7669 result[TYPE[key]] = key;
7670 return result;
7671 }, {});
7672
7673 // https://drafts.csswg.org/css-syntax/#tokenizer-definitions
7674 // > non-ASCII code point
7675 // > A code point with a value equal to or greater than U+0080 <control>
7676 // > name-start code point
7677 // > A letter, a non-ASCII code point, or U+005F LOW LINE (_).
7678 // > name code point
7679 // > A name-start code point, a digit, or U+002D HYPHEN-MINUS (-)
7680 // That means only ASCII code points has a special meaning and we a maps for 0..127 codes only
7681 var SafeUint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
7682 var SYMBOL_TYPE = new SafeUint32Array(0x80);
7683 var PUNCTUATION = new SafeUint32Array(0x80);
7684 var STOP_URL_RAW = new SafeUint32Array(0x80);
7685
7686 for (var i$1 = 0; i$1 < SYMBOL_TYPE.length; i$1++) {
7687 SYMBOL_TYPE[i$1] = IDENTIFIER;
7688 }
7689
7690 // fill categories
7691 [
7692 TYPE.ExclamationMark, // !
7693 TYPE.QuotationMark, // "
7694 TYPE.NumberSign, // #
7695 TYPE.DollarSign, // $
7696 TYPE.PercentSign, // %
7697 TYPE.Ampersand, // &
7698 TYPE.Apostrophe, // '
7699 TYPE.LeftParenthesis, // (
7700 TYPE.RightParenthesis, // )
7701 TYPE.Asterisk, // *
7702 TYPE.PlusSign, // +
7703 TYPE.Comma, // ,
7704 TYPE.HyphenMinus, // -
7705 TYPE.FullStop, // .
7706 TYPE.Solidus, // /
7707 TYPE.Colon, // :
7708 TYPE.Semicolon, // ;
7709 TYPE.LessThanSign, // <
7710 TYPE.EqualsSign, // =
7711 TYPE.GreaterThanSign, // >
7712 TYPE.QuestionMark, // ?
7713 TYPE.CommercialAt, // @
7714 TYPE.LeftSquareBracket, // [
7715 // TYPE.Backslash, // \
7716 TYPE.RightSquareBracket, // ]
7717 TYPE.CircumflexAccent, // ^
7718 // TYPE.LowLine, // _
7719 TYPE.GraveAccent, // `
7720 TYPE.LeftCurlyBracket, // {
7721 TYPE.VerticalLine, // |
7722 TYPE.RightCurlyBracket, // }
7723 TYPE.Tilde // ~
7724 ].forEach(function(key) {
7725 SYMBOL_TYPE[Number(key)] = PUNCTUATOR;
7726 PUNCTUATION[Number(key)] = PUNCTUATOR;
7727 });
7728
7729 for (var i$1 = 48; i$1 <= 57; i$1++) {
7730 SYMBOL_TYPE[i$1] = NUMBER;
7731 }
7732
7733 SYMBOL_TYPE[SPACE] = WHITESPACE;
7734 SYMBOL_TYPE[TAB] = WHITESPACE;
7735 SYMBOL_TYPE[N] = WHITESPACE;
7736 SYMBOL_TYPE[R] = WHITESPACE;
7737 SYMBOL_TYPE[F] = WHITESPACE;
7738
7739 SYMBOL_TYPE[TYPE.Apostrophe] = STRING;
7740 SYMBOL_TYPE[TYPE.QuotationMark] = STRING;
7741
7742 STOP_URL_RAW[SPACE] = 1;
7743 STOP_URL_RAW[TAB] = 1;
7744 STOP_URL_RAW[N] = 1;
7745 STOP_URL_RAW[R] = 1;
7746 STOP_URL_RAW[F] = 1;
7747 STOP_URL_RAW[TYPE.Apostrophe] = 1;
7748 STOP_URL_RAW[TYPE.QuotationMark] = 1;
7749 STOP_URL_RAW[TYPE.LeftParenthesis] = 1;
7750 STOP_URL_RAW[TYPE.RightParenthesis] = 1;
7751
7752 // whitespace is punctuation ...
7753 PUNCTUATION[SPACE] = PUNCTUATOR;
7754 PUNCTUATION[TAB] = PUNCTUATOR;
7755 PUNCTUATION[N] = PUNCTUATOR;
7756 PUNCTUATION[R] = PUNCTUATOR;
7757 PUNCTUATION[F] = PUNCTUATOR;
7758 // ... hyper minus is not
7759 PUNCTUATION[TYPE.HyphenMinus] = 0;
7760
7761 var _const = {
7762 TYPE: TYPE,
7763 NAME: NAME,
7764
7765 SYMBOL_TYPE: SYMBOL_TYPE,
7766 PUNCTUATION: PUNCTUATION,
7767 STOP_URL_RAW: STOP_URL_RAW
7768 };
7769
7770 var PUNCTUATION$1 = _const.PUNCTUATION;
7771 var STOP_URL_RAW$1 = _const.STOP_URL_RAW;
7772 var TYPE$1 = _const.TYPE;
7773 var FULLSTOP = TYPE$1.FullStop;
7774 var PLUSSIGN = TYPE$1.PlusSign;
7775 var HYPHENMINUS = TYPE$1.HyphenMinus;
7776 var PUNCTUATOR$1 = TYPE$1.Punctuator;
7777 var TAB$1 = 9;
7778 var N$1 = 10;
7779 var F$1 = 12;
7780 var R$1 = 13;
7781 var SPACE$1 = 32;
7782 var BACK_SLASH = 92;
7783 var E = 101; // 'e'.charCodeAt(0)
7784
7785 function firstCharOffset(source) {
7786 // detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
7787 if (source.charCodeAt(0) === 0xFEFF || // UTF-16BE
7788 source.charCodeAt(0) === 0xFFFE) { // UTF-16LE
7789 return 1;
7790 }
7791
7792 return 0;
7793 }
7794
7795 function isHex(code) {
7796 return (code >= 48 && code <= 57) || // 0 .. 9
7797 (code >= 65 && code <= 70) || // A .. F
7798 (code >= 97 && code <= 102); // a .. f
7799 }
7800
7801 function isNumber(code) {
7802 return code >= 48 && code <= 57;
7803 }
7804
7805 function isNewline(source, offset, code) {
7806 if (code === N$1 || code === F$1 || code === R$1) {
7807 if (code === R$1 && offset + 1 < source.length && source.charCodeAt(offset + 1) === N$1) {
7808 return 2;
7809 }
7810
7811 return 1;
7812 }
7813
7814 return 0;
7815 }
7816
7817 function cmpChar(testStr, offset, referenceCode) {
7818 var code = testStr.charCodeAt(offset);
7819
7820 // code.toLowerCase()
7821 if (code >= 65 && code <= 90) {
7822 code = code | 32;
7823 }
7824
7825 return code === referenceCode;
7826 }
7827
7828 function cmpStr(testStr, start, end, referenceStr) {
7829 if (end - start !== referenceStr.length) {
7830 return false;
7831 }
7832
7833 if (start < 0 || end > testStr.length) {
7834 return false;
7835 }
7836
7837 for (var i = start; i < end; i++) {
7838 var testCode = testStr.charCodeAt(i);
7839 var refCode = referenceStr.charCodeAt(i - start);
7840
7841 // testStr[i].toLowerCase()
7842 if (testCode >= 65 && testCode <= 90) {
7843 testCode = testCode | 32;
7844 }
7845
7846 if (testCode !== refCode) {
7847 return false;
7848 }
7849 }
7850
7851 return true;
7852 }
7853
7854 function endsWith(testStr, referenceStr) {
7855 return cmpStr(testStr, testStr.length - referenceStr.length, testStr.length, referenceStr);
7856 }
7857
7858 function findLastNonSpaceLocation(scanner) {
7859 for (var i = scanner.source.length - 1; i >= 0; i--) {
7860 var code = scanner.source.charCodeAt(i);
7861
7862 if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
7863 break;
7864 }
7865 }
7866
7867 return scanner.getLocation(i + 1);
7868 }
7869
7870 function findWhiteSpaceEnd(source, offset) {
7871 for (; offset < source.length; offset++) {
7872 var code = source.charCodeAt(offset);
7873
7874 if (code !== SPACE$1 && code !== TAB$1 && code !== R$1 && code !== N$1 && code !== F$1) {
7875 break;
7876 }
7877 }
7878
7879 return offset;
7880 }
7881
7882 function findCommentEnd(source, offset) {
7883 var commentEnd = source.indexOf('*/', offset);
7884
7885 if (commentEnd === -1) {
7886 return source.length;
7887 }
7888
7889 return commentEnd + 2;
7890 }
7891
7892 function findStringEnd(source, offset, quote) {
7893 for (; offset < source.length; offset++) {
7894 var code = source.charCodeAt(offset);
7895
7896 // TODO: bad string
7897 if (code === BACK_SLASH) {
7898 offset++;
7899 } else if (code === quote) {
7900 offset++;
7901 break;
7902 }
7903 }
7904
7905 return offset;
7906 }
7907
7908 function findDecimalNumberEnd(source, offset) {
7909 for (; offset < source.length; offset++) {
7910 var code = source.charCodeAt(offset);
7911
7912 if (code < 48 || code > 57) { // not a 0 .. 9
7913 break;
7914 }
7915 }
7916
7917 return offset;
7918 }
7919
7920 function findNumberEnd(source, offset, allowFraction) {
7921 var code;
7922
7923 offset = findDecimalNumberEnd(source, offset);
7924
7925 // fraction: .\d+
7926 if (allowFraction && offset + 1 < source.length && source.charCodeAt(offset) === FULLSTOP) {
7927 code = source.charCodeAt(offset + 1);
7928
7929 if (isNumber(code)) {
7930 offset = findDecimalNumberEnd(source, offset + 1);
7931 }
7932 }
7933
7934 // exponent: e[+-]\d+
7935 if (offset + 1 < source.length) {
7936 if ((source.charCodeAt(offset) | 32) === E) { // case insensitive check for `e`
7937 code = source.charCodeAt(offset + 1);
7938
7939 if (code === PLUSSIGN || code === HYPHENMINUS) {
7940 if (offset + 2 < source.length) {
7941 code = source.charCodeAt(offset + 2);
7942 }
7943 }
7944
7945 if (isNumber(code)) {
7946 offset = findDecimalNumberEnd(source, offset + 2);
7947 }
7948 }
7949 }
7950
7951 return offset;
7952 }
7953
7954 // skip escaped unicode sequence that can ends with space
7955 // [0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
7956 function findEscaseEnd(source, offset) {
7957 for (var i = 0; i < 7 && offset + i < source.length; i++) {
7958 var code = source.charCodeAt(offset + i);
7959
7960 if (i !== 6 && isHex(code)) {
7961 continue;
7962 }
7963
7964 if (i > 0) {
7965 offset += i - 1 + isNewline(source, offset + i, code);
7966 if (code === SPACE$1 || code === TAB$1) {
7967 offset++;
7968 }
7969 }
7970
7971 break;
7972 }
7973
7974 return offset;
7975 }
7976
7977 function findIdentifierEnd(source, offset) {
7978 for (; offset < source.length; offset++) {
7979 var code = source.charCodeAt(offset);
7980
7981 if (code === BACK_SLASH) {
7982 offset = findEscaseEnd(source, offset + 1);
7983 } else if (code < 0x80 && PUNCTUATION$1[code] === PUNCTUATOR$1) {
7984 break;
7985 }
7986 }
7987
7988 return offset;
7989 }
7990
7991 function findUrlRawEnd(source, offset) {
7992 for (; offset < source.length; offset++) {
7993 var code = source.charCodeAt(offset);
7994
7995 if (code === BACK_SLASH) {
7996 offset = findEscaseEnd(source, offset + 1);
7997 } else if (code < 0x80 && STOP_URL_RAW$1[code] === 1) {
7998 break;
7999 }
8000 }
8001
8002 return offset;
8003 }
8004
8005 var utils = {
8006 firstCharOffset: firstCharOffset,
8007
8008 isHex: isHex,
8009 isNumber: isNumber,
8010 isNewline: isNewline,
8011
8012 cmpChar: cmpChar,
8013 cmpStr: cmpStr,
8014 endsWith: endsWith,
8015
8016 findLastNonSpaceLocation: findLastNonSpaceLocation,
8017 findWhiteSpaceEnd: findWhiteSpaceEnd,
8018 findCommentEnd: findCommentEnd,
8019 findStringEnd: findStringEnd,
8020 findDecimalNumberEnd: findDecimalNumberEnd,
8021 findNumberEnd: findNumberEnd,
8022 findEscaseEnd: findEscaseEnd,
8023 findIdentifierEnd: findIdentifierEnd,
8024 findUrlRawEnd: findUrlRawEnd
8025 };
8026
8027 var TYPE$2 = _const.TYPE;
8028 var NAME$1 = _const.NAME;
8029 var SYMBOL_TYPE$1 = _const.SYMBOL_TYPE;
8030
8031
8032 var firstCharOffset$1 = utils.firstCharOffset;
8033 var cmpStr$1 = utils.cmpStr;
8034 var isNumber$1 = utils.isNumber;
8035 var findLastNonSpaceLocation$1 = utils.findLastNonSpaceLocation;
8036 var findWhiteSpaceEnd$1 = utils.findWhiteSpaceEnd;
8037 var findCommentEnd$1 = utils.findCommentEnd;
8038 var findStringEnd$1 = utils.findStringEnd;
8039 var findNumberEnd$1 = utils.findNumberEnd;
8040 var findIdentifierEnd$1 = utils.findIdentifierEnd;
8041 var findUrlRawEnd$1 = utils.findUrlRawEnd;
8042
8043 var NULL = 0;
8044 var WHITESPACE$1 = TYPE$2.WhiteSpace;
8045 var IDENTIFIER$1 = TYPE$2.Identifier;
8046 var NUMBER$1 = TYPE$2.Number;
8047 var STRING$1 = TYPE$2.String;
8048 var COMMENT$1 = TYPE$2.Comment;
8049 var PUNCTUATOR$2 = TYPE$2.Punctuator;
8050 var CDO$1 = TYPE$2.CDO;
8051 var CDC$1 = TYPE$2.CDC;
8052 var ATRULE$1 = TYPE$2.Atrule;
8053 var FUNCTION$1 = TYPE$2.Function;
8054 var URL$2 = TYPE$2.Url;
8055 var RAW$1 = TYPE$2.Raw;
8056
8057 var N$2 = 10;
8058 var F$2 = 12;
8059 var R$2 = 13;
8060 var STAR = TYPE$2.Asterisk;
8061 var SLASH = TYPE$2.Solidus;
8062 var FULLSTOP$1 = TYPE$2.FullStop;
8063 var PLUSSIGN$1 = TYPE$2.PlusSign;
8064 var HYPHENMINUS$1 = TYPE$2.HyphenMinus;
8065 var GREATERTHANSIGN = TYPE$2.GreaterThanSign;
8066 var LESSTHANSIGN = TYPE$2.LessThanSign;
8067 var EXCLAMATIONMARK = TYPE$2.ExclamationMark;
8068 var COMMERCIALAT = TYPE$2.CommercialAt;
8069 var QUOTATIONMARK = TYPE$2.QuotationMark;
8070 var APOSTROPHE = TYPE$2.Apostrophe;
8071 var LEFTPARENTHESIS = TYPE$2.LeftParenthesis;
8072 var RIGHTPARENTHESIS = TYPE$2.RightParenthesis;
8073 var LEFTCURLYBRACKET = TYPE$2.LeftCurlyBracket;
8074 var RIGHTCURLYBRACKET = TYPE$2.RightCurlyBracket;
8075 var LEFTSQUAREBRACKET = TYPE$2.LeftSquareBracket;
8076 var RIGHTSQUAREBRACKET = TYPE$2.RightSquareBracket;
8077
8078 var MIN_BUFFER_SIZE = 16 * 1024;
8079 var OFFSET_MASK = 0x00FFFFFF;
8080 var TYPE_SHIFT = 24;
8081 var SafeUint32Array$1 = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
8082
8083 function computeLinesAndColumns(tokenizer, source) {
8084 var sourceLength = source.length;
8085 var start = firstCharOffset$1(source);
8086 var lines = tokenizer.lines;
8087 var line = tokenizer.startLine;
8088 var columns = tokenizer.columns;
8089 var column = tokenizer.startColumn;
8090
8091 if (lines === null || lines.length < sourceLength + 1) {
8092 lines = new SafeUint32Array$1(Math.max(sourceLength + 1024, MIN_BUFFER_SIZE));
8093 columns = new SafeUint32Array$1(lines.length);
8094 }
8095
8096 for (var i = start; i < sourceLength; i++) {
8097 var code = source.charCodeAt(i);
8098
8099 lines[i] = line;
8100 columns[i] = column++;
8101
8102 if (code === N$2 || code === R$2 || code === F$2) {
8103 if (code === R$2 && i + 1 < sourceLength && source.charCodeAt(i + 1) === N$2) {
8104 i++;
8105 lines[i] = line;
8106 columns[i] = column;
8107 }
8108
8109 line++;
8110 column = 1;
8111 }
8112 }
8113
8114 lines[i] = line;
8115 columns[i] = column;
8116
8117 tokenizer.linesAnsColumnsComputed = true;
8118 tokenizer.lines = lines;
8119 tokenizer.columns = columns;
8120 }
8121
8122 function tokenLayout(tokenizer, source, startPos) {
8123 var sourceLength = source.length;
8124 var offsetAndType = tokenizer.offsetAndType;
8125 var balance = tokenizer.balance;
8126 var tokenCount = 0;
8127 var prevType = 0;
8128 var offset = startPos;
8129 var anchor = 0;
8130 var balanceCloseCode = 0;
8131 var balanceStart = 0;
8132 var balancePrev = 0;
8133
8134 if (offsetAndType === null || offsetAndType.length < sourceLength + 1) {
8135 offsetAndType = new SafeUint32Array$1(sourceLength + 1024);
8136 balance = new SafeUint32Array$1(sourceLength + 1024);
8137 }
8138
8139 while (offset < sourceLength) {
8140 var code = source.charCodeAt(offset);
8141 var type = code < 0x80 ? SYMBOL_TYPE$1[code] : IDENTIFIER$1;
8142
8143 balance[tokenCount] = sourceLength;
8144
8145 switch (type) {
8146 case WHITESPACE$1:
8147 offset = findWhiteSpaceEnd$1(source, offset + 1);
8148 break;
8149
8150 case PUNCTUATOR$2:
8151 switch (code) {
8152 case balanceCloseCode:
8153 balancePrev = balanceStart & OFFSET_MASK;
8154 balanceStart = balance[balancePrev];
8155 balanceCloseCode = balanceStart >> TYPE_SHIFT;
8156 balance[tokenCount] = balancePrev;
8157 balance[balancePrev++] = tokenCount;
8158 for (; balancePrev < tokenCount; balancePrev++) {
8159 if (balance[balancePrev] === sourceLength) {
8160 balance[balancePrev] = tokenCount;
8161 }
8162 }
8163 break;
8164
8165 case LEFTSQUAREBRACKET:
8166 balance[tokenCount] = balanceStart;
8167 balanceCloseCode = RIGHTSQUAREBRACKET;
8168 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8169 break;
8170
8171 case LEFTCURLYBRACKET:
8172 balance[tokenCount] = balanceStart;
8173 balanceCloseCode = RIGHTCURLYBRACKET;
8174 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8175 break;
8176
8177 case LEFTPARENTHESIS:
8178 balance[tokenCount] = balanceStart;
8179 balanceCloseCode = RIGHTPARENTHESIS;
8180 balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount;
8181 break;
8182 }
8183
8184 // /*
8185 if (code === STAR && prevType === SLASH) {
8186 type = COMMENT$1;
8187 offset = findCommentEnd$1(source, offset + 1);
8188 tokenCount--; // rewrite prev token
8189 break;
8190 }
8191
8192 // edge case for -.123 and +.123
8193 if (code === FULLSTOP$1 && (prevType === PLUSSIGN$1 || prevType === HYPHENMINUS$1)) {
8194 if (offset + 1 < sourceLength && isNumber$1(source.charCodeAt(offset + 1))) {
8195 type = NUMBER$1;
8196 offset = findNumberEnd$1(source, offset + 2, false);
8197 tokenCount--; // rewrite prev token
8198 break;
8199 }
8200 }
8201
8202 // <!--
8203 if (code === EXCLAMATIONMARK && prevType === LESSTHANSIGN) {
8204 if (offset + 2 < sourceLength &&
8205 source.charCodeAt(offset + 1) === HYPHENMINUS$1 &&
8206 source.charCodeAt(offset + 2) === HYPHENMINUS$1) {
8207 type = CDO$1;
8208 offset = offset + 3;
8209 tokenCount--; // rewrite prev token
8210 break;
8211 }
8212 }
8213
8214 // -->
8215 if (code === HYPHENMINUS$1 && prevType === HYPHENMINUS$1) {
8216 if (offset + 1 < sourceLength && source.charCodeAt(offset + 1) === GREATERTHANSIGN) {
8217 type = CDC$1;
8218 offset = offset + 2;
8219 tokenCount--; // rewrite prev token
8220 break;
8221 }
8222 }
8223
8224 // ident(
8225 if (code === LEFTPARENTHESIS && prevType === IDENTIFIER$1) {
8226 offset = offset + 1;
8227 tokenCount--; // rewrite prev token
8228 balance[tokenCount] = balance[tokenCount + 1];
8229 balanceStart--;
8230
8231 // 4 char length identifier and equal to `url(` (case insensitive)
8232 if (offset - anchor === 4 && cmpStr$1(source, anchor, offset, 'url(')) {
8233 // special case for url() because it can contain any symbols sequence with few exceptions
8234 anchor = findWhiteSpaceEnd$1(source, offset);
8235 code = source.charCodeAt(anchor);
8236 if (code !== LEFTPARENTHESIS &&
8237 code !== RIGHTPARENTHESIS &&
8238 code !== QUOTATIONMARK &&
8239 code !== APOSTROPHE) {
8240 // url(
8241 offsetAndType[tokenCount++] = (URL$2 << TYPE_SHIFT) | offset;
8242 balance[tokenCount] = sourceLength;
8243
8244 // ws*
8245 if (anchor !== offset) {
8246 offsetAndType[tokenCount++] = (WHITESPACE$1 << TYPE_SHIFT) | anchor;
8247 balance[tokenCount] = sourceLength;
8248 }
8249
8250 // raw
8251 type = RAW$1;
8252 offset = findUrlRawEnd$1(source, anchor);
8253 } else {
8254 type = URL$2;
8255 }
8256 } else {
8257 type = FUNCTION$1;
8258 }
8259 break;
8260 }
8261
8262 type = code;
8263 offset = offset + 1;
8264 break;
8265
8266 case NUMBER$1:
8267 offset = findNumberEnd$1(source, offset + 1, prevType !== FULLSTOP$1);
8268
8269 // merge number with a preceding dot, dash or plus
8270 if (prevType === FULLSTOP$1 ||
8271 prevType === HYPHENMINUS$1 ||
8272 prevType === PLUSSIGN$1) {
8273 tokenCount--; // rewrite prev token
8274 }
8275
8276 break;
8277
8278 case STRING$1:
8279 offset = findStringEnd$1(source, offset + 1, code);
8280 break;
8281
8282 default:
8283 anchor = offset;
8284 offset = findIdentifierEnd$1(source, offset);
8285
8286 // merge identifier with a preceding dash
8287 if (prevType === HYPHENMINUS$1) {
8288 // rewrite prev token
8289 tokenCount--;
8290 // restore prev prev token type
8291 // for case @-prefix-ident
8292 prevType = tokenCount === 0 ? 0 : offsetAndType[tokenCount - 1] >> TYPE_SHIFT;
8293 }
8294
8295 if (prevType === COMMERCIALAT) {
8296 // rewrite prev token and change type to <at-keyword-token>
8297 tokenCount--;
8298 type = ATRULE$1;
8299 }
8300 }
8301
8302 offsetAndType[tokenCount++] = (type << TYPE_SHIFT) | offset;
8303 prevType = type;
8304 }
8305
8306 // finalize arrays
8307 offsetAndType[tokenCount] = offset;
8308 balance[tokenCount] = sourceLength;
8309 while (balanceStart !== 0) {
8310 balancePrev = balanceStart & OFFSET_MASK;
8311 balanceStart = balance[balancePrev];
8312 balance[balancePrev] = sourceLength;
8313 }
8314
8315 tokenizer.offsetAndType = offsetAndType;
8316 tokenizer.tokenCount = tokenCount;
8317 tokenizer.balance = balance;
8318 }
8319
8320 //
8321 // tokenizer
8322 //
8323
8324 var Tokenizer = function(source, startOffset, startLine, startColumn) {
8325 this.offsetAndType = null;
8326 this.balance = null;
8327 this.lines = null;
8328 this.columns = null;
8329
8330 this.setSource(source, startOffset, startLine, startColumn);
8331 };
8332
8333 Tokenizer.prototype = {
8334 setSource: function(source, startOffset, startLine, startColumn) {
8335 var safeSource = String(source || '');
8336 var start = firstCharOffset$1(safeSource);
8337
8338 this.source = safeSource;
8339 this.firstCharOffset = start;
8340 this.startOffset = typeof startOffset === 'undefined' ? 0 : startOffset;
8341 this.startLine = typeof startLine === 'undefined' ? 1 : startLine;
8342 this.startColumn = typeof startColumn === 'undefined' ? 1 : startColumn;
8343 this.linesAnsColumnsComputed = false;
8344
8345 this.eof = false;
8346 this.currentToken = -1;
8347 this.tokenType = 0;
8348 this.tokenStart = start;
8349 this.tokenEnd = start;
8350
8351 tokenLayout(this, safeSource, start);
8352 this.next();
8353 },
8354
8355 lookupType: function(offset) {
8356 offset += this.currentToken;
8357
8358 if (offset < this.tokenCount) {
8359 return this.offsetAndType[offset] >> TYPE_SHIFT;
8360 }
8361
8362 return NULL;
8363 },
8364 lookupNonWSType: function(offset) {
8365 offset += this.currentToken;
8366
8367 for (var type; offset < this.tokenCount; offset++) {
8368 type = this.offsetAndType[offset] >> TYPE_SHIFT;
8369
8370 if (type !== WHITESPACE$1) {
8371 return type;
8372 }
8373 }
8374
8375 return NULL;
8376 },
8377 lookupValue: function(offset, referenceStr) {
8378 offset += this.currentToken;
8379
8380 if (offset < this.tokenCount) {
8381 return cmpStr$1(
8382 this.source,
8383 this.offsetAndType[offset - 1] & OFFSET_MASK,
8384 this.offsetAndType[offset] & OFFSET_MASK,
8385 referenceStr
8386 );
8387 }
8388
8389 return false;
8390 },
8391 getTokenStart: function(tokenNum) {
8392 if (tokenNum === this.currentToken) {
8393 return this.tokenStart;
8394 }
8395
8396 if (tokenNum > 0) {
8397 return tokenNum < this.tokenCount
8398 ? this.offsetAndType[tokenNum - 1] & OFFSET_MASK
8399 : this.offsetAndType[this.tokenCount] & OFFSET_MASK;
8400 }
8401
8402 return this.firstCharOffset;
8403 },
8404 getOffsetExcludeWS: function() {
8405 if (this.currentToken > 0) {
8406 if ((this.offsetAndType[this.currentToken - 1] >> TYPE_SHIFT) === WHITESPACE$1) {
8407 return this.currentToken > 1
8408 ? this.offsetAndType[this.currentToken - 2] & OFFSET_MASK
8409 : this.firstCharOffset;
8410 }
8411 }
8412 return this.tokenStart;
8413 },
8414 getRawLength: function(startToken, endTokenType1, endTokenType2, includeTokenType2) {
8415 var cursor = startToken;
8416 var balanceEnd;
8417
8418 loop:
8419 for (; cursor < this.tokenCount; cursor++) {
8420 balanceEnd = this.balance[cursor];
8421
8422 // belance end points to offset before start
8423 if (balanceEnd < startToken) {
8424 break loop;
8425 }
8426
8427 // check token is stop type
8428 switch (this.offsetAndType[cursor] >> TYPE_SHIFT) {
8429 case endTokenType1:
8430 break loop;
8431
8432 case endTokenType2:
8433 if (includeTokenType2) {
8434 cursor++;
8435 }
8436 break loop;
8437
8438 default:
8439 // fast forward to the end of balanced block
8440 if (this.balance[balanceEnd] === cursor) {
8441 cursor = balanceEnd;
8442 }
8443 }
8444
8445 }
8446
8447 return cursor - this.currentToken;
8448 },
8449
8450 getTokenValue: function() {
8451 return this.source.substring(this.tokenStart, this.tokenEnd);
8452 },
8453 substrToCursor: function(start) {
8454 return this.source.substring(start, this.tokenStart);
8455 },
8456
8457 skipWS: function() {
8458 for (var i = this.currentToken, skipTokenCount = 0; i < this.tokenCount; i++, skipTokenCount++) {
8459 if ((this.offsetAndType[i] >> TYPE_SHIFT) !== WHITESPACE$1) {
8460 break;
8461 }
8462 }
8463
8464 if (skipTokenCount > 0) {
8465 this.skip(skipTokenCount);
8466 }
8467 },
8468 skipSC: function() {
8469 while (this.tokenType === WHITESPACE$1 || this.tokenType === COMMENT$1) {
8470 this.next();
8471 }
8472 },
8473 skip: function(tokenCount) {
8474 var next = this.currentToken + tokenCount;
8475
8476 if (next < this.tokenCount) {
8477 this.currentToken = next;
8478 this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
8479 next = this.offsetAndType[next];
8480 this.tokenType = next >> TYPE_SHIFT;
8481 this.tokenEnd = next & OFFSET_MASK;
8482 } else {
8483 this.currentToken = this.tokenCount;
8484 this.next();
8485 }
8486 },
8487 next: function() {
8488 var next = this.currentToken + 1;
8489
8490 if (next < this.tokenCount) {
8491 this.currentToken = next;
8492 this.tokenStart = this.tokenEnd;
8493 next = this.offsetAndType[next];
8494 this.tokenType = next >> TYPE_SHIFT;
8495 this.tokenEnd = next & OFFSET_MASK;
8496 } else {
8497 this.currentToken = this.tokenCount;
8498 this.eof = true;
8499 this.tokenType = NULL;
8500 this.tokenStart = this.tokenEnd = this.source.length;
8501 }
8502 },
8503
8504 eat: function(tokenType) {
8505 if (this.tokenType !== tokenType) {
8506 var offset = this.tokenStart;
8507 var message = NAME$1[tokenType] + ' is expected';
8508
8509 // tweak message and offset
8510 if (tokenType === IDENTIFIER$1) {
8511 // when identifier is expected but there is a function or url
8512 if (this.tokenType === FUNCTION$1 || this.tokenType === URL$2) {
8513 offset = this.tokenEnd - 1;
8514 message += ' but function found';
8515 }
8516 } else {
8517 // when test type is part of another token show error for current position + 1
8518 // e.g. eat(HYPHENMINUS) will fail on "-foo", but pointing on "-" is odd
8519 if (this.source.charCodeAt(this.tokenStart) === tokenType) {
8520 offset = offset + 1;
8521 }
8522 }
8523
8524 this.error(message, offset);
8525 }
8526
8527 this.next();
8528 },
8529 eatNonWS: function(tokenType) {
8530 this.skipWS();
8531 this.eat(tokenType);
8532 },
8533
8534 consume: function(tokenType) {
8535 var value = this.getTokenValue();
8536
8537 this.eat(tokenType);
8538
8539 return value;
8540 },
8541 consumeFunctionName: function() {
8542 var name = this.source.substring(this.tokenStart, this.tokenEnd - 1);
8543
8544 this.eat(FUNCTION$1);
8545
8546 return name;
8547 },
8548 consumeNonWS: function(tokenType) {
8549 this.skipWS();
8550
8551 return this.consume(tokenType);
8552 },
8553
8554 expectIdentifier: function(name) {
8555 if (this.tokenType !== IDENTIFIER$1 || cmpStr$1(this.source, this.tokenStart, this.tokenEnd, name) === false) {
8556 this.error('Identifier `' + name + '` is expected');
8557 }
8558
8559 this.next();
8560 },
8561
8562 getLocation: function(offset, filename) {
8563 if (!this.linesAnsColumnsComputed) {
8564 computeLinesAndColumns(this, this.source);
8565 }
8566
8567 return {
8568 source: filename,
8569 offset: this.startOffset + offset,
8570 line: this.lines[offset],
8571 column: this.columns[offset]
8572 };
8573 },
8574
8575 getLocationRange: function(start, end, filename) {
8576 if (!this.linesAnsColumnsComputed) {
8577 computeLinesAndColumns(this, this.source);
8578 }
8579
8580 return {
8581 source: filename,
8582 start: {
8583 offset: this.startOffset + start,
8584 line: this.lines[start],
8585 column: this.columns[start]
8586 },
8587 end: {
8588 offset: this.startOffset + end,
8589 line: this.lines[end],
8590 column: this.columns[end]
8591 }
8592 };
8593 },
8594
8595 error: function(message, offset) {
8596 var location = typeof offset !== 'undefined' && offset < this.source.length
8597 ? this.getLocation(offset)
8598 : this.eof
8599 ? findLastNonSpaceLocation$1(this)
8600 : this.getLocation(this.tokenStart);
8601
8602 throw new error(
8603 message || 'Unexpected input',
8604 this.source,
8605 location.offset,
8606 location.line,
8607 location.column
8608 );
8609 },
8610
8611 dump: function() {
8612 var offset = 0;
8613
8614 return Array.prototype.slice.call(this.offsetAndType, 0, this.tokenCount).map(function(item, idx) {
8615 var start = offset;
8616 var end = item & OFFSET_MASK;
8617
8618 offset = end;
8619
8620 return {
8621 idx: idx,
8622 type: NAME$1[item >> TYPE_SHIFT],
8623 chunk: this.source.substring(start, end),
8624 balance: this.balance[idx]
8625 };
8626 }, this);
8627 }
8628 };
8629
8630 // extend with error class
8631 Tokenizer.CssSyntaxError = error;
8632
8633 // extend tokenizer with constants
8634 Object.keys(_const).forEach(function(key) {
8635 Tokenizer[key] = _const[key];
8636 });
8637
8638 // extend tokenizer with static methods from utils
8639 Object.keys(utils).forEach(function(key) {
8640 Tokenizer[key] = utils[key];
8641 });
8642
8643 // warm up tokenizer to elimitate code branches that never execute
8644 // fix soft deoptimizations (insufficient type feedback)
8645 new Tokenizer('\n\r\r\n\f<!---->//""\'\'/*\r\n\f*/1a;.\\31\t\+2{url(a);func();+1.2e3 -.4e-5 .6e+7}').getLocation();
8646
8647 var Tokenizer_1 = Tokenizer;
8648
8649 var tokenizer = Tokenizer_1;
8650
8651 //
8652 // item item item item
8653 // /------\ /------\ /------\ /------\
8654 // | data | | data | | data | | data |
8655 // null <--+-prev |<---+-prev |<---+-prev |<---+-prev |
8656 // | next-+--->| next-+--->| next-+--->| next-+--> null
8657 // \------/ \------/ \------/ \------/
8658 // ^ ^
8659 // | list |
8660 // | /------\ |
8661 // \--------------+-head | |
8662 // | tail-+--------------/
8663 // \------/
8664 //
8665
8666 function createItem(data) {
8667 return {
8668 prev: null,
8669 next: null,
8670 data: data
8671 };
8672 }
8673
8674 var cursors = null;
8675 var List = function() {
8676 this.cursor = null;
8677 this.head = null;
8678 this.tail = null;
8679 };
8680
8681 List.createItem = createItem;
8682 List.prototype.createItem = createItem;
8683
8684 List.prototype.getSize = function() {
8685 var size = 0;
8686 var cursor = this.head;
8687
8688 while (cursor) {
8689 size++;
8690 cursor = cursor.next;
8691 }
8692
8693 return size;
8694 };
8695
8696 List.prototype.fromArray = function(array) {
8697 var cursor = null;
8698
8699 this.head = null;
8700
8701 for (var i = 0; i < array.length; i++) {
8702 var item = createItem(array[i]);
8703
8704 if (cursor !== null) {
8705 cursor.next = item;
8706 } else {
8707 this.head = item;
8708 }
8709
8710 item.prev = cursor;
8711 cursor = item;
8712 }
8713
8714 this.tail = cursor;
8715
8716 return this;
8717 };
8718
8719 List.prototype.toArray = function() {
8720 var cursor = this.head;
8721 var result = [];
8722
8723 while (cursor) {
8724 result.push(cursor.data);
8725 cursor = cursor.next;
8726 }
8727
8728 return result;
8729 };
8730
8731 List.prototype.toJSON = List.prototype.toArray;
8732
8733 List.prototype.isEmpty = function() {
8734 return this.head === null;
8735 };
8736
8737 List.prototype.first = function() {
8738 return this.head && this.head.data;
8739 };
8740
8741 List.prototype.last = function() {
8742 return this.tail && this.tail.data;
8743 };
8744
8745 function allocateCursor(node, prev, next) {
8746 var cursor;
8747
8748 if (cursors !== null) {
8749 cursor = cursors;
8750 cursors = cursors.cursor;
8751 cursor.prev = prev;
8752 cursor.next = next;
8753 cursor.cursor = node.cursor;
8754 } else {
8755 cursor = {
8756 prev: prev,
8757 next: next,
8758 cursor: node.cursor
8759 };
8760 }
8761
8762 node.cursor = cursor;
8763
8764 return cursor;
8765 }
8766
8767 function releaseCursor(node) {
8768 var cursor = node.cursor;
8769
8770 node.cursor = cursor.cursor;
8771 cursor.prev = null;
8772 cursor.next = null;
8773 cursor.cursor = cursors;
8774 cursors = cursor;
8775 }
8776
8777 List.prototype.each = function(fn, context) {
8778 var item;
8779
8780 if (context === undefined) {
8781 context = this;
8782 }
8783
8784 // push cursor
8785 var cursor = allocateCursor(this, null, this.head);
8786
8787 while (cursor.next !== null) {
8788 item = cursor.next;
8789 cursor.next = item.next;
8790
8791 fn.call(context, item.data, item, this);
8792 }
8793
8794 // pop cursor
8795 releaseCursor(this);
8796 };
8797
8798 List.prototype.eachRight = function(fn, context) {
8799 var item;
8800
8801 if (context === undefined) {
8802 context = this;
8803 }
8804
8805 // push cursor
8806 var cursor = allocateCursor(this, this.tail, null);
8807
8808 while (cursor.prev !== null) {
8809 item = cursor.prev;
8810 cursor.prev = item.prev;
8811
8812 fn.call(context, item.data, item, this);
8813 }
8814
8815 // pop cursor
8816 releaseCursor(this);
8817 };
8818
8819 List.prototype.nextUntil = function(start, fn, context) {
8820 if (start === null) {
8821 return;
8822 }
8823
8824 var item;
8825
8826 if (context === undefined) {
8827 context = this;
8828 }
8829
8830 // push cursor
8831 var cursor = allocateCursor(this, null, start);
8832
8833 while (cursor.next !== null) {
8834 item = cursor.next;
8835 cursor.next = item.next;
8836
8837 if (fn.call(context, item.data, item, this)) {
8838 break;
8839 }
8840 }
8841
8842 // pop cursor
8843 releaseCursor(this);
8844 };
8845
8846 List.prototype.prevUntil = function(start, fn, context) {
8847 if (start === null) {
8848 return;
8849 }
8850
8851 var item;
8852
8853 if (context === undefined) {
8854 context = this;
8855 }
8856
8857 // push cursor
8858 var cursor = allocateCursor(this, start, null);
8859
8860 while (cursor.prev !== null) {
8861 item = cursor.prev;
8862 cursor.prev = item.prev;
8863
8864 if (fn.call(context, item.data, item, this)) {
8865 break;
8866 }
8867 }
8868
8869 // pop cursor
8870 releaseCursor(this);
8871 };
8872
8873 List.prototype.some = function(fn, context) {
8874 var cursor = this.head;
8875
8876 if (context === undefined) {
8877 context = this;
8878 }
8879
8880 while (cursor !== null) {
8881 if (fn.call(context, cursor.data, cursor, this)) {
8882 return true;
8883 }
8884
8885 cursor = cursor.next;
8886 }
8887
8888 return false;
8889 };
8890
8891 List.prototype.map = function(fn, context) {
8892 var result = [];
8893 var cursor = this.head;
8894
8895 if (context === undefined) {
8896 context = this;
8897 }
8898
8899 while (cursor !== null) {
8900 result.push(fn.call(context, cursor.data, cursor, this));
8901 cursor = cursor.next;
8902 }
8903
8904 return result;
8905 };
8906
8907 List.prototype.clear = function() {
8908 this.head = null;
8909 this.tail = null;
8910 };
8911
8912 List.prototype.copy = function() {
8913 var result = new List();
8914 var cursor = this.head;
8915
8916 while (cursor !== null) {
8917 result.insert(createItem(cursor.data));
8918 cursor = cursor.next;
8919 }
8920
8921 return result;
8922 };
8923
8924 List.prototype.updateCursors = function(prevOld, prevNew, nextOld, nextNew) {
8925 var cursor = this.cursor;
8926
8927 while (cursor !== null) {
8928 if (cursor.prev === prevOld) {
8929 cursor.prev = prevNew;
8930 }
8931
8932 if (cursor.next === nextOld) {
8933 cursor.next = nextNew;
8934 }
8935
8936 cursor = cursor.cursor;
8937 }
8938 };
8939
8940 List.prototype.prepend = function(item) {
8941 // head
8942 // ^
8943 // item
8944 this.updateCursors(null, item, this.head, item);
8945
8946 // insert to the beginning of the list
8947 if (this.head !== null) {
8948 // new item <- first item
8949 this.head.prev = item;
8950
8951 // new item -> first item
8952 item.next = this.head;
8953 } else {
8954 // if list has no head, then it also has no tail
8955 // in this case tail points to the new item
8956 this.tail = item;
8957 }
8958
8959 // head always points to new item
8960 this.head = item;
8961
8962 return this;
8963 };
8964
8965 List.prototype.prependData = function(data) {
8966 return this.prepend(createItem(data));
8967 };
8968
8969 List.prototype.append = function(item) {
8970 // tail
8971 // ^
8972 // item
8973 this.updateCursors(this.tail, item, null, item);
8974
8975 // insert to the ending of the list
8976 if (this.tail !== null) {
8977 // last item -> new item
8978 this.tail.next = item;
8979
8980 // last item <- new item
8981 item.prev = this.tail;
8982 } else {
8983 // if list has no tail, then it also has no head
8984 // in this case head points to new item
8985 this.head = item;
8986 }
8987
8988 // tail always points to new item
8989 this.tail = item;
8990
8991 return this;
8992 };
8993
8994 List.prototype.appendData = function(data) {
8995 return this.append(createItem(data));
8996 };
8997
8998 List.prototype.insert = function(item, before) {
8999 if (before !== undefined && before !== null) {
9000 // prev before
9001 // ^
9002 // item
9003 this.updateCursors(before.prev, item, before, item);
9004
9005 if (before.prev === null) {
9006 // insert to the beginning of list
9007 if (this.head !== before) {
9008 throw new Error('before doesn\'t belong to list');
9009 }
9010
9011 // since head points to before therefore list doesn't empty
9012 // no need to check tail
9013 this.head = item;
9014 before.prev = item;
9015 item.next = before;
9016
9017 this.updateCursors(null, item);
9018 } else {
9019
9020 // insert between two items
9021 before.prev.next = item;
9022 item.prev = before.prev;
9023
9024 before.prev = item;
9025 item.next = before;
9026 }
9027 } else {
9028 this.append(item);
9029 }
9030 };
9031
9032 List.prototype.insertData = function(data, before) {
9033 this.insert(createItem(data), before);
9034 };
9035
9036 List.prototype.remove = function(item) {
9037 // item
9038 // ^
9039 // prev next
9040 this.updateCursors(item, item.prev, item, item.next);
9041
9042 if (item.prev !== null) {
9043 item.prev.next = item.next;
9044 } else {
9045 if (this.head !== item) {
9046 throw new Error('item doesn\'t belong to list');
9047 }
9048
9049 this.head = item.next;
9050 }
9051
9052 if (item.next !== null) {
9053 item.next.prev = item.prev;
9054 } else {
9055 if (this.tail !== item) {
9056 throw new Error('item doesn\'t belong to list');
9057 }
9058
9059 this.tail = item.prev;
9060 }
9061
9062 item.prev = null;
9063 item.next = null;
9064
9065 return item;
9066 };
9067
9068 List.prototype.appendList = function(list) {
9069 // ignore empty lists
9070 if (list.head === null) {
9071 return;
9072 }
9073
9074 this.updateCursors(this.tail, list.tail, null, list.head);
9075
9076 // insert to end of the list
9077 if (this.tail !== null) {
9078 // if destination list has a tail, then it also has a head,
9079 // but head doesn't change
9080
9081 // dest tail -> source head
9082 this.tail.next = list.head;
9083
9084 // dest tail <- source head
9085 list.head.prev = this.tail;
9086 } else {
9087 // if list has no a tail, then it also has no a head
9088 // in this case points head to new item
9089 this.head = list.head;
9090 }
9091
9092 // tail always start point to new item
9093 this.tail = list.tail;
9094
9095 list.head = null;
9096 list.tail = null;
9097 };
9098
9099 List.prototype.insertList = function(list, before) {
9100 if (before !== undefined && before !== null) {
9101 // ignore empty lists
9102 if (list.head === null) {
9103 return;
9104 }
9105
9106 this.updateCursors(before.prev, list.tail, before, list.head);
9107
9108 // insert in the middle of dist list
9109 if (before.prev !== null) {
9110 // before.prev <-> list.head
9111 before.prev.next = list.head;
9112 list.head.prev = before.prev;
9113 } else {
9114 this.head = list.head;
9115 }
9116
9117 before.prev = list.tail;
9118 list.tail.next = before;
9119
9120 list.head = null;
9121 list.tail = null;
9122 } else {
9123 this.appendList(list);
9124 }
9125 };
9126
9127 List.prototype.replace = function(oldItem, newItemOrList) {
9128 if ('head' in newItemOrList) {
9129 this.insertList(newItemOrList, oldItem);
9130 } else {
9131 this.insert(newItemOrList, oldItem);
9132 }
9133 this.remove(oldItem);
9134 };
9135
9136 var list = List;
9137
9138 var TYPE$3 = tokenizer.TYPE;
9139 var WHITESPACE$2 = TYPE$3.WhiteSpace;
9140 var COMMENT$2 = TYPE$3.Comment;
9141
9142 var sequence = function readSequence(recognizer) {
9143 var children = new list();
9144 var child = null;
9145 var context = {
9146 recognizer: recognizer,
9147 space: null,
9148 ignoreWS: false,
9149 ignoreWSAfter: false
9150 };
9151
9152 this.scanner.skipSC();
9153
9154 while (!this.scanner.eof) {
9155 switch (this.scanner.tokenType) {
9156 case COMMENT$2:
9157 this.scanner.next();
9158 continue;
9159
9160 case WHITESPACE$2:
9161 if (context.ignoreWS) {
9162 this.scanner.next();
9163 } else {
9164 context.space = this.WhiteSpace();
9165 }
9166 continue;
9167 }
9168
9169 child = recognizer.getNode.call(this, context);
9170
9171 if (child === undefined) {
9172 break;
9173 }
9174
9175 if (context.space !== null) {
9176 children.appendData(context.space);
9177 context.space = null;
9178 }
9179
9180 children.appendData(child);
9181
9182 if (context.ignoreWSAfter) {
9183 context.ignoreWSAfter = false;
9184 context.ignoreWS = true;
9185 } else {
9186 context.ignoreWS = false;
9187 }
9188 }
9189
9190 return children;
9191 };
9192
9193 var noop = function() {};
9194
9195 function createParseContext(name) {
9196 return function() {
9197 return this[name]();
9198 };
9199 }
9200
9201 function processConfig(config) {
9202 var parserConfig = {
9203 context: {},
9204 scope: {},
9205 atrule: {},
9206 pseudo: {}
9207 };
9208
9209 if (config.parseContext) {
9210 for (var name in config.parseContext) {
9211 switch (typeof config.parseContext[name]) {
9212 case 'function':
9213 parserConfig.context[name] = config.parseContext[name];
9214 break;
9215
9216 case 'string':
9217 parserConfig.context[name] = createParseContext(config.parseContext[name]);
9218 break;
9219 }
9220 }
9221 }
9222
9223 if (config.scope) {
9224 for (var name in config.scope) {
9225 parserConfig.scope[name] = config.scope[name];
9226 }
9227 }
9228
9229 if (config.atrule) {
9230 for (var name in config.atrule) {
9231 var atrule = config.atrule[name];
9232
9233 if (atrule.parse) {
9234 parserConfig.atrule[name] = atrule.parse;
9235 }
9236 }
9237 }
9238
9239 if (config.pseudo) {
9240 for (var name in config.pseudo) {
9241 var pseudo = config.pseudo[name];
9242
9243 if (pseudo.parse) {
9244 parserConfig.pseudo[name] = pseudo.parse;
9245 }
9246 }
9247 }
9248
9249 if (config.node) {
9250 for (var name in config.node) {
9251 parserConfig[name] = config.node[name].parse;
9252 }
9253 }
9254
9255 return parserConfig;
9256 }
9257
9258 var create = function createParser(config) {
9259 var parser = {
9260 scanner: new tokenizer(),
9261 filename: '<unknown>',
9262 needPositions: false,
9263 tolerant: false,
9264 onParseError: noop,
9265 parseAtruleExpression: true,
9266 parseSelector: true,
9267 parseValue: true,
9268 parseCustomProperty: false,
9269
9270 readSequence: sequence,
9271
9272 tolerantParse: function(consumer, fallback) {
9273 if (this.tolerant) {
9274 var start = this.scanner.currentToken;
9275
9276 try {
9277 return consumer.call(this);
9278 } catch (e) {
9279 this.onParseError(e);
9280 return fallback.call(this, start);
9281 }
9282 } else {
9283 return consumer.call(this);
9284 }
9285 },
9286
9287 getLocation: function(start, end) {
9288 if (this.needPositions) {
9289 return this.scanner.getLocationRange(
9290 start,
9291 end,
9292 this.filename
9293 );
9294 }
9295
9296 return null;
9297 },
9298 getLocationFromList: function(list) {
9299 if (this.needPositions) {
9300 return this.scanner.getLocationRange(
9301 list.head !== null ? list.first().loc.start.offset - this.scanner.startOffset : this.scanner.tokenStart,
9302 list.head !== null ? list.last().loc.end.offset - this.scanner.startOffset : this.scanner.tokenStart,
9303 this.filename
9304 );
9305 }
9306
9307 return null;
9308 }
9309 };
9310
9311 config = processConfig(config || {});
9312 for (var key in config) {
9313 parser[key] = config[key];
9314 }
9315
9316 return function(source, options) {
9317 options = options || {};
9318
9319 var context = options.context || 'default';
9320 var ast;
9321
9322 parser.scanner.setSource(source, options.offset, options.line, options.column);
9323 parser.filename = options.filename || '<unknown>';
9324 parser.needPositions = Boolean(options.positions);
9325 parser.tolerant = Boolean(options.tolerant);
9326 parser.onParseError = typeof options.onParseError === 'function' ? options.onParseError : noop;
9327 parser.parseAtruleExpression = 'parseAtruleExpression' in options ? Boolean(options.parseAtruleExpression) : true;
9328 parser.parseSelector = 'parseSelector' in options ? Boolean(options.parseSelector) : true;
9329 parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
9330 parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;
9331
9332 if (!parser.context.hasOwnProperty(context)) {
9333 throw new Error('Unknown context `' + context + '`');
9334 }
9335
9336 ast = parser.context[context].call(parser, options);
9337
9338 if (!parser.scanner.eof) {
9339 parser.scanner.error();
9340 }
9341
9342 // console.log(JSON.stringify(ast, null, 4));
9343 return ast;
9344 };
9345 };
9346
9347 var cmpChar$1 = tokenizer.cmpChar;
9348 var TYPE$4 = tokenizer.TYPE;
9349
9350 var IDENTIFIER$2 = TYPE$4.Identifier;
9351 var STRING$2 = TYPE$4.String;
9352 var NUMBER$2 = TYPE$4.Number;
9353 var FUNCTION$2 = TYPE$4.Function;
9354 var URL$3 = TYPE$4.Url;
9355 var NUMBERSIGN = TYPE$4.NumberSign;
9356 var LEFTPARENTHESIS$1 = TYPE$4.LeftParenthesis;
9357 var LEFTSQUAREBRACKET$1 = TYPE$4.LeftSquareBracket;
9358 var PLUSSIGN$2 = TYPE$4.PlusSign;
9359 var HYPHENMINUS$2 = TYPE$4.HyphenMinus;
9360 var COMMA = TYPE$4.Comma;
9361 var SOLIDUS = TYPE$4.Solidus;
9362 var ASTERISK = TYPE$4.Asterisk;
9363 var PERCENTSIGN = TYPE$4.PercentSign;
9364 var BACKSLASH = TYPE$4.Backslash;
9365 var U = 117; // 'u'.charCodeAt(0)
9366
9367 var _default = function defaultRecognizer(context) {
9368 switch (this.scanner.tokenType) {
9369 case NUMBERSIGN:
9370 return this.HexColor();
9371
9372 case COMMA:
9373 context.space = null;
9374 context.ignoreWSAfter = true;
9375 return this.Operator();
9376
9377 case SOLIDUS:
9378 case ASTERISK:
9379 case PLUSSIGN$2:
9380 case HYPHENMINUS$2:
9381 return this.Operator();
9382
9383 case LEFTPARENTHESIS$1:
9384 return this.Parentheses(this.readSequence, context.recognizer);
9385
9386 case LEFTSQUAREBRACKET$1:
9387 return this.Brackets(this.readSequence, context.recognizer);
9388
9389 case STRING$2:
9390 return this.String();
9391
9392 case NUMBER$2:
9393 switch (this.scanner.lookupType(1)) {
9394 case PERCENTSIGN:
9395 return this.Percentage();
9396
9397 case IDENTIFIER$2:
9398 // edge case: number with folowing \0 and \9 hack shouldn't to be a Dimension
9399 if (cmpChar$1(this.scanner.source, this.scanner.tokenEnd, BACKSLASH)) {
9400 return this.Number();
9401 } else {
9402 return this.Dimension();
9403 }
9404
9405 default:
9406 return this.Number();
9407 }
9408
9409 case FUNCTION$2:
9410 return this.Function(this.readSequence, context.recognizer);
9411
9412 case URL$3:
9413 return this.Url();
9414
9415 case IDENTIFIER$2:
9416 // check for unicode range, it should start with u+ or U+
9417 if (cmpChar$1(this.scanner.source, this.scanner.tokenStart, U) &&
9418 cmpChar$1(this.scanner.source, this.scanner.tokenStart + 1, PLUSSIGN$2)) {
9419 return this.UnicodeRange();
9420 } else {
9421 return this.Identifier();
9422 }
9423 }
9424 };
9425
9426 var atruleExpression = {
9427 getNode: _default
9428 };
9429
9430 var TYPE$5 = tokenizer.TYPE;
9431
9432 var IDENTIFIER$3 = TYPE$5.Identifier;
9433 var NUMBER$3 = TYPE$5.Number;
9434 var NUMBERSIGN$1 = TYPE$5.NumberSign;
9435 var LEFTSQUAREBRACKET$2 = TYPE$5.LeftSquareBracket;
9436 var PLUSSIGN$3 = TYPE$5.PlusSign;
9437 var SOLIDUS$1 = TYPE$5.Solidus;
9438 var ASTERISK$1 = TYPE$5.Asterisk;
9439 var FULLSTOP$2 = TYPE$5.FullStop;
9440 var COLON = TYPE$5.Colon;
9441 var GREATERTHANSIGN$1 = TYPE$5.GreaterThanSign;
9442 var VERTICALLINE = TYPE$5.VerticalLine;
9443 var TILDE = TYPE$5.Tilde;
9444
9445 function getNode(context) {
9446 switch (this.scanner.tokenType) {
9447 case PLUSSIGN$3:
9448 case GREATERTHANSIGN$1:
9449 case TILDE:
9450 context.space = null;
9451 context.ignoreWSAfter = true;
9452 return this.Combinator();
9453
9454 case SOLIDUS$1: // /deep/
9455 return this.Combinator();
9456
9457 case FULLSTOP$2:
9458 return this.ClassSelector();
9459
9460 case LEFTSQUAREBRACKET$2:
9461 return this.AttributeSelector();
9462
9463 case NUMBERSIGN$1:
9464 return this.IdSelector();
9465
9466 case COLON:
9467 if (this.scanner.lookupType(1) === COLON) {
9468 return this.PseudoElementSelector();
9469 } else {
9470 return this.PseudoClassSelector();
9471 }
9472
9473 case IDENTIFIER$3:
9474 case ASTERISK$1:
9475 case VERTICALLINE:
9476 return this.TypeSelector();
9477
9478 case NUMBER$3:
9479 return this.Percentage();
9480 }
9481 }
9482 var selector = {
9483 getNode: getNode
9484 };
9485
9486 // https://drafts.csswg.org/css-images-4/#element-notation
9487 // https://developer.mozilla.org/en-US/docs/Web/CSS/element
9488 var element = function() {
9489 this.scanner.skipSC();
9490
9491 var id = this.IdSelector();
9492
9493 this.scanner.skipSC();
9494
9495 return new list().appendData(
9496 id
9497 );
9498 };
9499
9500 // legacy IE function
9501 // expression '(' raw ')'
9502 var expression = function() {
9503 return new list().appendData(
9504 this.Raw(this.scanner.currentToken, 0, 0, false, false)
9505 );
9506 };
9507
9508 var TYPE$6 = tokenizer.TYPE;
9509
9510 var IDENTIFIER$4 = TYPE$6.Identifier;
9511 var COMMA$1 = TYPE$6.Comma;
9512 var SEMICOLON = TYPE$6.Semicolon;
9513 var HYPHENMINUS$3 = TYPE$6.HyphenMinus;
9514 var EXCLAMATIONMARK$1 = TYPE$6.ExclamationMark;
9515
9516 // var '(' ident (',' <value>? )? ')'
9517 var _var = function() {
9518 var children = new list();
9519
9520 this.scanner.skipSC();
9521
9522 var identStart = this.scanner.tokenStart;
9523
9524 this.scanner.eat(HYPHENMINUS$3);
9525 if (this.scanner.source.charCodeAt(this.scanner.tokenStart) !== HYPHENMINUS$3) {
9526 this.scanner.error('HyphenMinus is expected');
9527 }
9528 this.scanner.eat(IDENTIFIER$4);
9529
9530 children.appendData({
9531 type: 'Identifier',
9532 loc: this.getLocation(identStart, this.scanner.tokenStart),
9533 name: this.scanner.substrToCursor(identStart)
9534 });
9535
9536 this.scanner.skipSC();
9537
9538 if (this.scanner.tokenType === COMMA$1) {
9539 children.appendData(this.Operator());
9540 children.appendData(this.parseCustomProperty
9541 ? this.Value(null)
9542 : this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$1, SEMICOLON, false, false)
9543 );
9544 }
9545
9546 return children;
9547 };
9548
9549 var value = {
9550 getNode: _default,
9551 '-moz-element': element,
9552 'element': element,
9553 'expression': expression,
9554 'var': _var
9555 };
9556
9557 var scope = {
9558 AtruleExpression: atruleExpression,
9559 Selector: selector,
9560 Value: value
9561 };
9562
9563 var fontFace = {
9564 parse: {
9565 expression: null,
9566 block: function() {
9567 return this.Block(this.Declaration);
9568 }
9569 }
9570 };
9571
9572 var TYPE$7 = tokenizer.TYPE;
9573
9574 var STRING$3 = TYPE$7.String;
9575 var IDENTIFIER$5 = TYPE$7.Identifier;
9576 var URL$4 = TYPE$7.Url;
9577 var LEFTPARENTHESIS$2 = TYPE$7.LeftParenthesis;
9578
9579 var _import = {
9580 parse: {
9581 expression: function() {
9582 var children = new list();
9583
9584 this.scanner.skipSC();
9585
9586 switch (this.scanner.tokenType) {
9587 case STRING$3:
9588 children.appendData(this.String());
9589 break;
9590
9591 case URL$4:
9592 children.appendData(this.Url());
9593 break;
9594
9595 default:
9596 this.scanner.error('String or url() is expected');
9597 }
9598
9599 if (this.scanner.lookupNonWSType(0) === IDENTIFIER$5 ||
9600 this.scanner.lookupNonWSType(0) === LEFTPARENTHESIS$2) {
9601 children.appendData(this.WhiteSpace());
9602 children.appendData(this.MediaQueryList());
9603 }
9604
9605 return children;
9606 },
9607 block: null
9608 }
9609 };
9610
9611 var media = {
9612 parse: {
9613 expression: function() {
9614 return new list().appendData(
9615 this.MediaQueryList()
9616 );
9617 },
9618 block: function() {
9619 return this.Block(this.Rule);
9620 }
9621 }
9622 };
9623
9624 var TYPE$8 = tokenizer.TYPE;
9625 var LEFTCURLYBRACKET$1 = TYPE$8.LeftCurlyBracket;
9626
9627 var page = {
9628 parse: {
9629 expression: function() {
9630 if (this.scanner.lookupNonWSType(0) === LEFTCURLYBRACKET$1) {
9631 return null;
9632 }
9633
9634 return new list().appendData(
9635 this.SelectorList()
9636 );
9637 },
9638 block: function() {
9639 return this.Block(this.Declaration);
9640 }
9641 }
9642 };
9643
9644 var TYPE$9 = tokenizer.TYPE;
9645
9646 var WHITESPACE$3 = TYPE$9.WhiteSpace;
9647 var COMMENT$3 = TYPE$9.Comment;
9648 var IDENTIFIER$6 = TYPE$9.Identifier;
9649 var FUNCTION$3 = TYPE$9.Function;
9650 var LEFTPARENTHESIS$3 = TYPE$9.LeftParenthesis;
9651 var HYPHENMINUS$4 = TYPE$9.HyphenMinus;
9652 var COLON$1 = TYPE$9.Colon;
9653
9654 function consumeRaw() {
9655 return new list().appendData(
9656 this.Raw(this.scanner.currentToken, 0, 0, false, false)
9657 );
9658 }
9659
9660 function parentheses() {
9661 var index = 0;
9662
9663 this.scanner.skipSC();
9664
9665 // TODO: make it simplier
9666 if (this.scanner.tokenType === IDENTIFIER$6) {
9667 index = 1;
9668 } else if (this.scanner.tokenType === HYPHENMINUS$4 &&
9669 this.scanner.lookupType(1) === IDENTIFIER$6) {
9670 index = 2;
9671 }
9672
9673 if (index !== 0 && this.scanner.lookupNonWSType(index) === COLON$1) {
9674 return new list().appendData(
9675 this.Declaration()
9676 );
9677 }
9678
9679 return readSequence.call(this);
9680 }
9681
9682 function readSequence() {
9683 var children = new list();
9684 var space = null;
9685 var child;
9686
9687 this.scanner.skipSC();
9688
9689 scan:
9690 while (!this.scanner.eof) {
9691 switch (this.scanner.tokenType) {
9692 case WHITESPACE$3:
9693 space = this.WhiteSpace();
9694 continue;
9695
9696 case COMMENT$3:
9697 this.scanner.next();
9698 continue;
9699
9700 case FUNCTION$3:
9701 child = this.Function(consumeRaw, this.scope.AtruleExpression);
9702 break;
9703
9704 case IDENTIFIER$6:
9705 child = this.Identifier();
9706 break;
9707
9708 case LEFTPARENTHESIS$3:
9709 child = this.Parentheses(parentheses, this.scope.AtruleExpression);
9710 break;
9711
9712 default:
9713 break scan;
9714 }
9715
9716 if (space !== null) {
9717 children.appendData(space);
9718 space = null;
9719 }
9720
9721 children.appendData(child);
9722 }
9723
9724 return children;
9725 }
9726
9727 var supports = {
9728 parse: {
9729 expression: function() {
9730 var children = readSequence.call(this);
9731
9732 if (children.isEmpty()) {
9733 this.scanner.error('Condition is expected');
9734 }
9735
9736 return children;
9737 },
9738 block: function() {
9739 return this.Block(this.Rule);
9740 }
9741 }
9742 };
9743
9744 var atrule = {
9745 'font-face': fontFace,
9746 'import': _import,
9747 'media': media,
9748 'page': page,
9749 'supports': supports
9750 };
9751
9752 var dir = {
9753 parse: function() {
9754 return new list().appendData(
9755 this.Identifier()
9756 );
9757 }
9758 };
9759
9760 var has$1 = {
9761 parse: function() {
9762 return new list().appendData(
9763 this.SelectorList()
9764 );
9765 }
9766 };
9767
9768 var lang = {
9769 parse: function() {
9770 return new list().appendData(
9771 this.Identifier()
9772 );
9773 }
9774 };
9775
9776 var selectorList = {
9777 parse: function selectorList() {
9778 return new list().appendData(
9779 this.SelectorList()
9780 );
9781 }
9782 };
9783
9784 var matches = selectorList;
9785
9786 var not = selectorList;
9787
9788 var ALLOW_OF_CLAUSE = true;
9789
9790 var nthWithOfClause = {
9791 parse: function() {
9792 return new list().appendData(
9793 this.Nth(ALLOW_OF_CLAUSE)
9794 );
9795 }
9796 };
9797
9798 var nthChild = nthWithOfClause;
9799
9800 var nthLastChild = nthWithOfClause;
9801
9802 var DISALLOW_OF_CLAUSE = false;
9803
9804 var nth = {
9805 parse: function nth() {
9806 return new list().appendData(
9807 this.Nth(DISALLOW_OF_CLAUSE)
9808 );
9809 }
9810 };
9811
9812 var nthLastOfType = nth;
9813
9814 var nthOfType = nth;
9815
9816 var slotted = {
9817 parse: function compoundSelector() {
9818 return new list().appendData(
9819 this.Selector()
9820 );
9821 }
9822 };
9823
9824 var pseudo = {
9825 'dir': dir,
9826 'has': has$1,
9827 'lang': lang,
9828 'matches': matches,
9829 'not': not,
9830 'nth-child': nthChild,
9831 'nth-last-child': nthLastChild,
9832 'nth-last-of-type': nthLastOfType,
9833 'nth-of-type': nthOfType,
9834 'slotted': slotted
9835 };
9836
9837 var cmpChar$2 = tokenizer.cmpChar;
9838 var isNumber$2 = tokenizer.isNumber;
9839 var TYPE$a = tokenizer.TYPE;
9840
9841 var IDENTIFIER$7 = TYPE$a.Identifier;
9842 var NUMBER$4 = TYPE$a.Number;
9843 var PLUSSIGN$4 = TYPE$a.PlusSign;
9844 var HYPHENMINUS$5 = TYPE$a.HyphenMinus;
9845 var N$3 = 110; // 'n'.charCodeAt(0)
9846 var DISALLOW_SIGN = true;
9847 var ALLOW_SIGN = false;
9848
9849 function checkTokenIsInteger(scanner, disallowSign) {
9850 var pos = scanner.tokenStart;
9851
9852 if (scanner.source.charCodeAt(pos) === PLUSSIGN$4 ||
9853 scanner.source.charCodeAt(pos) === HYPHENMINUS$5) {
9854 if (disallowSign) {
9855 scanner.error();
9856 }
9857 pos++;
9858 }
9859
9860 for (; pos < scanner.tokenEnd; pos++) {
9861 if (!isNumber$2(scanner.source.charCodeAt(pos))) {
9862 scanner.error('Unexpected input', pos);
9863 }
9864 }
9865 }
9866
9867 // An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
9868 var AnPlusB = {
9869 name: 'AnPlusB',
9870 structure: {
9871 a: [String, null],
9872 b: [String, null]
9873 },
9874 parse: function() {
9875 var start = this.scanner.tokenStart;
9876 var end = start;
9877 var prefix = '';
9878 var a = null;
9879 var b = null;
9880
9881 if (this.scanner.tokenType === NUMBER$4 ||
9882 this.scanner.tokenType === PLUSSIGN$4) {
9883 checkTokenIsInteger(this.scanner, ALLOW_SIGN);
9884 prefix = this.scanner.getTokenValue();
9885 this.scanner.next();
9886 end = this.scanner.tokenStart;
9887 }
9888
9889 if (this.scanner.tokenType === IDENTIFIER$7) {
9890 var bStart = this.scanner.tokenStart;
9891
9892 if (cmpChar$2(this.scanner.source, bStart, HYPHENMINUS$5)) {
9893 if (prefix === '') {
9894 prefix = '-';
9895 bStart++;
9896 } else {
9897 this.scanner.error('Unexpected hyphen minus');
9898 }
9899 }
9900
9901 if (!cmpChar$2(this.scanner.source, bStart, N$3)) {
9902 this.scanner.error();
9903 }
9904
9905 a = prefix === '' ? '1' :
9906 prefix === '+' ? '+1' :
9907 prefix === '-' ? '-1' :
9908 prefix;
9909
9910 var len = this.scanner.tokenEnd - bStart;
9911 if (len > 1) {
9912 // ..n-..
9913 if (this.scanner.source.charCodeAt(bStart + 1) !== HYPHENMINUS$5) {
9914 this.scanner.error('Unexpected input', bStart + 1);
9915 }
9916
9917 if (len > 2) {
9918 // ..n-{number}..
9919 this.scanner.tokenStart = bStart + 2;
9920 } else {
9921 // ..n- {number}
9922 this.scanner.next();
9923 this.scanner.skipSC();
9924 }
9925
9926 checkTokenIsInteger(this.scanner, DISALLOW_SIGN);
9927 b = '-' + this.scanner.getTokenValue();
9928 this.scanner.next();
9929 end = this.scanner.tokenStart;
9930 } else {
9931 prefix = '';
9932 this.scanner.next();
9933 end = this.scanner.tokenStart;
9934 this.scanner.skipSC();
9935
9936 if (this.scanner.tokenType === HYPHENMINUS$5 ||
9937 this.scanner.tokenType === PLUSSIGN$4) {
9938 prefix = this.scanner.getTokenValue();
9939 this.scanner.next();
9940 this.scanner.skipSC();
9941 }
9942
9943 if (this.scanner.tokenType === NUMBER$4) {
9944 checkTokenIsInteger(this.scanner, prefix !== '');
9945
9946 if (!isNumber$2(this.scanner.source.charCodeAt(this.scanner.tokenStart))) {
9947 prefix = this.scanner.source.charAt(this.scanner.tokenStart);
9948 this.scanner.tokenStart++;
9949 }
9950
9951 if (prefix === '') {
9952 // should be an operator before number
9953 this.scanner.error();
9954 } else if (prefix === '+') {
9955 // plus is using by default
9956 prefix = '';
9957 }
9958
9959 b = prefix + this.scanner.getTokenValue();
9960
9961 this.scanner.next();
9962 end = this.scanner.tokenStart;
9963 } else {
9964 if (prefix) {
9965 this.scanner.eat(NUMBER$4);
9966 }
9967 }
9968 }
9969 } else {
9970 if (prefix === '' || prefix === '+') { // no number
9971 this.scanner.error(
9972 'Number or identifier is expected',
9973 this.scanner.tokenStart + (
9974 this.scanner.tokenType === PLUSSIGN$4 ||
9975 this.scanner.tokenType === HYPHENMINUS$5
9976 )
9977 );
9978 }
9979
9980 b = prefix;
9981 }
9982
9983 return {
9984 type: 'AnPlusB',
9985 loc: this.getLocation(start, end),
9986 a: a,
9987 b: b
9988 };
9989 },
9990 generate: function(processChunk, node) {
9991 var a = node.a !== null && node.a !== undefined;
9992 var b = node.b !== null && node.b !== undefined;
9993
9994 if (a) {
9995 processChunk(
9996 node.a === '+1' ? '+n' :
9997 node.a === '1' ? 'n' :
9998 node.a === '-1' ? '-n' :
9999 node.a + 'n'
10000 );
10001
10002 if (b) {
10003 b = String(node.b);
10004 if (b.charAt(0) === '-' || b.charAt(0) === '+') {
10005 processChunk(b.charAt(0));
10006 processChunk(b.substr(1));
10007 } else {
10008 processChunk('+');
10009 processChunk(b);
10010 }
10011 }
10012 } else {
10013 processChunk(String(node.b));
10014 }
10015 }
10016 };
10017
10018 var TYPE$b = tokenizer.TYPE;
10019
10020 var ATRULE$2 = TYPE$b.Atrule;
10021 var SEMICOLON$1 = TYPE$b.Semicolon;
10022 var LEFTCURLYBRACKET$2 = TYPE$b.LeftCurlyBracket;
10023 var RIGHTCURLYBRACKET$1 = TYPE$b.RightCurlyBracket;
10024
10025 function isBlockAtrule() {
10026 for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) {
10027 if (type === RIGHTCURLYBRACKET$1) {
10028 return true;
10029 }
10030
10031 if (type === LEFTCURLYBRACKET$2 ||
10032 type === ATRULE$2) {
10033 return false;
10034 }
10035 }
10036
10037 this.scanner.skip(offset);
10038 this.scanner.eat(RIGHTCURLYBRACKET$1);
10039 }
10040
10041 var Atrule = {
10042 name: 'Atrule',
10043 structure: {
10044 name: String,
10045 expression: ['AtruleExpression', null],
10046 block: ['Block', null]
10047 },
10048 parse: function() {
10049 var start = this.scanner.tokenStart;
10050 var name;
10051 var nameLowerCase;
10052 var expression = null;
10053 var block = null;
10054
10055 this.scanner.eat(ATRULE$2);
10056
10057 name = this.scanner.substrToCursor(start + 1);
10058 nameLowerCase = name.toLowerCase();
10059 this.scanner.skipSC();
10060
10061 expression = this.AtruleExpression(name);
10062
10063 // turn empty AtruleExpression into null
10064 if (expression.children.head === null) {
10065 expression = null;
10066 }
10067
10068 this.scanner.skipSC();
10069
10070 if (this.atrule.hasOwnProperty(nameLowerCase)) {
10071 if (typeof this.atrule[nameLowerCase].block === 'function') {
10072 if (this.scanner.tokenType !== LEFTCURLYBRACKET$2) {
10073 // FIXME: make tolerant
10074 this.scanner.error('Curly bracket is expected');
10075 }
10076
10077 block = this.atrule[nameLowerCase].block.call(this);
10078 } else {
10079 if (!this.tolerant || !this.scanner.eof) {
10080 this.scanner.eat(SEMICOLON$1);
10081 }
10082 }
10083 } else {
10084 switch (this.scanner.tokenType) {
10085 case SEMICOLON$1:
10086 this.scanner.next();
10087 break;
10088
10089 case LEFTCURLYBRACKET$2:
10090 // TODO: should consume block content as Raw?
10091 block = this.Block(isBlockAtrule.call(this) ? this.Declaration : this.Rule);
10092 break;
10093
10094 default:
10095 if (!this.tolerant) {
10096 this.scanner.error('Semicolon or block is expected');
10097 }
10098 }
10099 }
10100
10101 return {
10102 type: 'Atrule',
10103 loc: this.getLocation(start, this.scanner.tokenStart),
10104 name: name,
10105 expression: expression,
10106 block: block
10107 };
10108 },
10109 generate: function(processChunk, node) {
10110 processChunk('@');
10111 processChunk(node.name);
10112
10113 if (node.expression !== null) {
10114 processChunk(' ');
10115 this.generate(processChunk, node.expression);
10116 }
10117
10118 if (node.block) {
10119 this.generate(processChunk, node.block);
10120 } else {
10121 processChunk(';');
10122 }
10123 },
10124 walkContext: 'atrule'
10125 };
10126
10127 var TYPE$c = tokenizer.TYPE;
10128 var SEMICOLON$2 = TYPE$c.Semicolon;
10129 var LEFTCURLYBRACKET$3 = TYPE$c.LeftCurlyBracket;
10130
10131 function consumeRaw$1(startToken) {
10132 return new list().appendData(
10133 this.Raw(startToken, SEMICOLON$2, LEFTCURLYBRACKET$3, false, true)
10134 );
10135 }
10136
10137 function consumeDefaultSequence() {
10138 return this.readSequence(this.scope.AtruleExpression);
10139 }
10140
10141 var AtruleExpression = {
10142 name: 'AtruleExpression',
10143 structure: {
10144 children: [[]]
10145 },
10146 parse: function(name) {
10147 var children = null;
10148 var startToken = this.scanner.currentToken;
10149
10150 if (name !== null) {
10151 name = name.toLowerCase();
10152 }
10153
10154 if (this.parseAtruleExpression) {
10155 // custom consumer
10156 if (this.atrule.hasOwnProperty(name)) {
10157 if (typeof this.atrule[name].expression === 'function') {
10158 children = this.tolerantParse(this.atrule[name].expression, consumeRaw$1);
10159 }
10160 } else {
10161 // default consumer
10162 this.scanner.skipSC();
10163 children = this.tolerantParse(consumeDefaultSequence, consumeRaw$1);
10164 }
10165
10166 if (this.tolerant) {
10167 if (this.scanner.eof || (this.scanner.tokenType !== SEMICOLON$2 && this.scanner.tokenType !== LEFTCURLYBRACKET$3)) {
10168 children = consumeRaw$1.call(this, startToken);
10169 }
10170 }
10171 } else {
10172 children = consumeRaw$1.call(this, startToken);
10173 }
10174
10175 if (children === null) {
10176 children = new list();
10177 }
10178
10179 return {
10180 type: 'AtruleExpression',
10181 loc: this.getLocationFromList(children),
10182 children: children
10183 };
10184 },
10185 generate: function(processChunk, node) {
10186 this.each(processChunk, node);
10187 },
10188 walkContext: 'atruleExpression'
10189 };
10190
10191 var TYPE$d = tokenizer.TYPE;
10192
10193 var IDENTIFIER$8 = TYPE$d.Identifier;
10194 var STRING$4 = TYPE$d.String;
10195 var DOLLARSIGN = TYPE$d.DollarSign;
10196 var ASTERISK$2 = TYPE$d.Asterisk;
10197 var COLON$2 = TYPE$d.Colon;
10198 var EQUALSSIGN = TYPE$d.EqualsSign;
10199 var LEFTSQUAREBRACKET$3 = TYPE$d.LeftSquareBracket;
10200 var RIGHTSQUAREBRACKET$1 = TYPE$d.RightSquareBracket;
10201 var CIRCUMFLEXACCENT = TYPE$d.CircumflexAccent;
10202 var VERTICALLINE$1 = TYPE$d.VerticalLine;
10203 var TILDE$1 = TYPE$d.Tilde;
10204
10205 function getAttributeName() {
10206 if (this.scanner.eof) {
10207 this.scanner.error('Unexpected end of input');
10208 }
10209
10210 var start = this.scanner.tokenStart;
10211 var expectIdentifier = false;
10212 var checkColon = true;
10213
10214 if (this.scanner.tokenType === ASTERISK$2) {
10215 expectIdentifier = true;
10216 checkColon = false;
10217 this.scanner.next();
10218 } else if (this.scanner.tokenType !== VERTICALLINE$1) {
10219 this.scanner.eat(IDENTIFIER$8);
10220 }
10221
10222 if (this.scanner.tokenType === VERTICALLINE$1) {
10223 if (this.scanner.lookupType(1) !== EQUALSSIGN) {
10224 this.scanner.next();
10225 this.scanner.eat(IDENTIFIER$8);
10226 } else if (expectIdentifier) {
10227 this.scanner.error('Identifier is expected', this.scanner.tokenEnd);
10228 }
10229 } else if (expectIdentifier) {
10230 this.scanner.error('Vertical line is expected');
10231 }
10232
10233 if (checkColon && this.scanner.tokenType === COLON$2) {
10234 this.scanner.next();
10235 this.scanner.eat(IDENTIFIER$8);
10236 }
10237
10238 return {
10239 type: 'Identifier',
10240 loc: this.getLocation(start, this.scanner.tokenStart),
10241 name: this.scanner.substrToCursor(start)
10242 };
10243 }
10244
10245 function getOperator() {
10246 var start = this.scanner.tokenStart;
10247 var tokenType = this.scanner.tokenType;
10248
10249 if (tokenType !== EQUALSSIGN && // =
10250 tokenType !== TILDE$1 && // ~=
10251 tokenType !== CIRCUMFLEXACCENT && // ^=
10252 tokenType !== DOLLARSIGN && // $=
10253 tokenType !== ASTERISK$2 && // *=
10254 tokenType !== VERTICALLINE$1 // |=
10255 ) {
10256 this.scanner.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
10257 }
10258
10259 if (tokenType === EQUALSSIGN) {
10260 this.scanner.next();
10261 } else {
10262 this.scanner.next();
10263 this.scanner.eat(EQUALSSIGN);
10264 }
10265
10266 return this.scanner.substrToCursor(start);
10267 }
10268
10269 // '[' S* attrib_name ']'
10270 // '[' S* attrib_name S* attrib_matcher S* [ IDENT | STRING ] S* attrib_flags? S* ']'
10271 var AttributeSelector = {
10272 name: 'AttributeSelector',
10273 structure: {
10274 name: 'Identifier',
10275 matcher: [String, null],
10276 value: ['String', 'Identifier', null],
10277 flags: [String, null]
10278 },
10279 parse: function() {
10280 var start = this.scanner.tokenStart;
10281 var name;
10282 var matcher = null;
10283 var value = null;
10284 var flags = null;
10285
10286 this.scanner.eat(LEFTSQUAREBRACKET$3);
10287 this.scanner.skipSC();
10288
10289 name = getAttributeName.call(this);
10290 this.scanner.skipSC();
10291
10292 if (this.scanner.tokenType !== RIGHTSQUAREBRACKET$1) {
10293 // avoid case `[name i]`
10294 if (this.scanner.tokenType !== IDENTIFIER$8) {
10295 matcher = getOperator.call(this);
10296
10297 this.scanner.skipSC();
10298
10299 value = this.scanner.tokenType === STRING$4
10300 ? this.String()
10301 : this.Identifier();
10302
10303 this.scanner.skipSC();
10304 }
10305
10306 // attribute flags
10307 if (this.scanner.tokenType === IDENTIFIER$8) {
10308 flags = this.scanner.getTokenValue();
10309 this.scanner.next();
10310
10311 this.scanner.skipSC();
10312 }
10313 }
10314
10315 this.scanner.eat(RIGHTSQUAREBRACKET$1);
10316
10317 return {
10318 type: 'AttributeSelector',
10319 loc: this.getLocation(start, this.scanner.tokenStart),
10320 name: name,
10321 matcher: matcher,
10322 value: value,
10323 flags: flags
10324 };
10325 },
10326 generate: function(processChunk, node) {
10327 var flagsPrefix = ' ';
10328
10329 processChunk('[');
10330 this.generate(processChunk, node.name);
10331
10332 if (node.matcher !== null) {
10333 processChunk(node.matcher);
10334
10335 if (node.value !== null) {
10336 this.generate(processChunk, node.value);
10337
10338 // space between string and flags is not required
10339 if (node.value.type === 'String') {
10340 flagsPrefix = '';
10341 }
10342 }
10343 }
10344
10345 if (node.flags !== null) {
10346 processChunk(flagsPrefix);
10347 processChunk(node.flags);
10348 }
10349
10350 processChunk(']');
10351 }
10352 };
10353
10354 var TYPE$e = tokenizer.TYPE;
10355
10356 var WHITESPACE$4 = TYPE$e.WhiteSpace;
10357 var COMMENT$4 = TYPE$e.Comment;
10358 var SEMICOLON$3 = TYPE$e.Semicolon;
10359 var ATRULE$3 = TYPE$e.Atrule;
10360 var LEFTCURLYBRACKET$4 = TYPE$e.LeftCurlyBracket;
10361 var RIGHTCURLYBRACKET$2 = TYPE$e.RightCurlyBracket;
10362
10363 function consumeRaw$2(startToken) {
10364 return this.Raw(startToken, 0, SEMICOLON$3, true, true);
10365 }
10366
10367 var Block = {
10368 name: 'Block',
10369 structure: {
10370 children: [['Atrule', 'Rule', 'Declaration']]
10371 },
10372 parse: function(defaultConsumer) {
10373 if (!defaultConsumer) {
10374 defaultConsumer = this.Declaration;
10375 }
10376
10377 var start = this.scanner.tokenStart;
10378 var children = new list();
10379
10380 this.scanner.eat(LEFTCURLYBRACKET$4);
10381
10382 scan:
10383 while (!this.scanner.eof) {
10384 switch (this.scanner.tokenType) {
10385 case RIGHTCURLYBRACKET$2:
10386 break scan;
10387
10388 case WHITESPACE$4:
10389 case COMMENT$4:
10390 case SEMICOLON$3:
10391 this.scanner.next();
10392 break;
10393
10394 case ATRULE$3:
10395 children.appendData(this.tolerantParse(this.Atrule, consumeRaw$2));
10396 break;
10397
10398 default:
10399 children.appendData(this.tolerantParse(defaultConsumer, consumeRaw$2));
10400 }
10401 }
10402
10403 if (!this.tolerant || !this.scanner.eof) {
10404 this.scanner.eat(RIGHTCURLYBRACKET$2);
10405 }
10406
10407 return {
10408 type: 'Block',
10409 loc: this.getLocation(start, this.scanner.tokenStart),
10410 children: children
10411 };
10412 },
10413 generate: function(processChunk, node) {
10414 processChunk('{');
10415 this.each(processChunk, node);
10416 processChunk('}');
10417 },
10418 walkContext: 'block'
10419 };
10420
10421 var TYPE$f = tokenizer.TYPE;
10422 var LEFTSQUAREBRACKET$4 = TYPE$f.LeftSquareBracket;
10423 var RIGHTSQUAREBRACKET$2 = TYPE$f.RightSquareBracket;
10424
10425 // currently only Grid Layout uses square brackets, but left it universal
10426 // https://drafts.csswg.org/css-grid/#track-sizing
10427 // [ ident* ]
10428 var Brackets = {
10429 name: 'Brackets',
10430 structure: {
10431 children: [[]]
10432 },
10433 parse: function(readSequence, recognizer) {
10434 var start = this.scanner.tokenStart;
10435 var children = null;
10436
10437 this.scanner.eat(LEFTSQUAREBRACKET$4);
10438 children = readSequence.call(this, recognizer);
10439 this.scanner.eat(RIGHTSQUAREBRACKET$2);
10440
10441 return {
10442 type: 'Brackets',
10443 loc: this.getLocation(start, this.scanner.tokenStart),
10444 children: children
10445 };
10446 },
10447 generate: function(processChunk, node) {
10448 processChunk('[');
10449 this.each(processChunk, node);
10450 processChunk(']');
10451 }
10452 };
10453
10454 var CDC$2 = tokenizer.TYPE.CDC;
10455
10456 var CDC_1 = {
10457 name: 'CDC',
10458 structure: [],
10459 parse: function() {
10460 var start = this.scanner.tokenStart;
10461
10462 this.scanner.eat(CDC$2); // -->
10463
10464 return {
10465 type: 'CDC',
10466 loc: this.getLocation(start, this.scanner.tokenStart)
10467 };
10468 },
10469 generate: function(processChunk) {
10470 processChunk('-->');
10471 }
10472 };
10473
10474 var CDO$2 = tokenizer.TYPE.CDO;
10475
10476 var CDO_1 = {
10477 name: 'CDO',
10478 structure: [],
10479 parse: function() {
10480 var start = this.scanner.tokenStart;
10481
10482 this.scanner.eat(CDO$2); // <!--
10483
10484 return {
10485 type: 'CDO',
10486 loc: this.getLocation(start, this.scanner.tokenStart)
10487 };
10488 },
10489 generate: function(processChunk) {
10490 processChunk('<!--');
10491 }
10492 };
10493
10494 var TYPE$g = tokenizer.TYPE;
10495 var IDENTIFIER$9 = TYPE$g.Identifier;
10496 var FULLSTOP$3 = TYPE$g.FullStop;
10497
10498 // '.' ident
10499 var ClassSelector = {
10500 name: 'ClassSelector',
10501 structure: {
10502 name: String
10503 },
10504 parse: function() {
10505 this.scanner.eat(FULLSTOP$3);
10506
10507 return {
10508 type: 'ClassSelector',
10509 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10510 name: this.scanner.consume(IDENTIFIER$9)
10511 };
10512 },
10513 generate: function(processChunk, node) {
10514 processChunk('.');
10515 processChunk(node.name);
10516 }
10517 };
10518
10519 var TYPE$h = tokenizer.TYPE;
10520
10521 var PLUSSIGN$5 = TYPE$h.PlusSign;
10522 var SOLIDUS$2 = TYPE$h.Solidus;
10523 var GREATERTHANSIGN$2 = TYPE$h.GreaterThanSign;
10524 var TILDE$2 = TYPE$h.Tilde;
10525
10526 // + | > | ~ | /deep/
10527 var Combinator = {
10528 name: 'Combinator',
10529 structure: {
10530 name: String
10531 },
10532 parse: function() {
10533 var start = this.scanner.tokenStart;
10534
10535 switch (this.scanner.tokenType) {
10536 case GREATERTHANSIGN$2:
10537 case PLUSSIGN$5:
10538 case TILDE$2:
10539 this.scanner.next();
10540 break;
10541
10542 case SOLIDUS$2:
10543 this.scanner.next();
10544 this.scanner.expectIdentifier('deep');
10545 this.scanner.eat(SOLIDUS$2);
10546 break;
10547
10548 default:
10549 this.scanner.error('Combinator is expected');
10550 }
10551
10552 return {
10553 type: 'Combinator',
10554 loc: this.getLocation(start, this.scanner.tokenStart),
10555 name: this.scanner.substrToCursor(start)
10556 };
10557 },
10558 generate: function(processChunk, node) {
10559 processChunk(node.name);
10560 }
10561 };
10562
10563 var TYPE$i = tokenizer.TYPE;
10564
10565 var ASTERISK$3 = TYPE$i.Asterisk;
10566 var SOLIDUS$3 = TYPE$i.Solidus;
10567
10568 // '/*' .* '*/'
10569 var Comment = {
10570 name: 'Comment',
10571 structure: {
10572 value: String
10573 },
10574 parse: function() {
10575 var start = this.scanner.tokenStart;
10576 var end = this.scanner.tokenEnd;
10577
10578 if ((end - start + 2) >= 2 &&
10579 this.scanner.source.charCodeAt(end - 2) === ASTERISK$3 &&
10580 this.scanner.source.charCodeAt(end - 1) === SOLIDUS$3) {
10581 end -= 2;
10582 }
10583
10584 this.scanner.next();
10585
10586 return {
10587 type: 'Comment',
10588 loc: this.getLocation(start, this.scanner.tokenStart),
10589 value: this.scanner.source.substring(start + 2, end)
10590 };
10591 },
10592 generate: function(processChunk, node) {
10593 processChunk('/*');
10594 processChunk(node.value);
10595 processChunk('*/');
10596 }
10597 };
10598
10599 var TYPE$j = tokenizer.TYPE;
10600
10601 var IDENTIFIER$a = TYPE$j.Identifier;
10602 var COLON$3 = TYPE$j.Colon;
10603 var EXCLAMATIONMARK$2 = TYPE$j.ExclamationMark;
10604 var SOLIDUS$4 = TYPE$j.Solidus;
10605 var ASTERISK$4 = TYPE$j.Asterisk;
10606 var DOLLARSIGN$1 = TYPE$j.DollarSign;
10607 var HYPHENMINUS$6 = TYPE$j.HyphenMinus;
10608 var SEMICOLON$4 = TYPE$j.Semicolon;
10609 var RIGHTCURLYBRACKET$3 = TYPE$j.RightCurlyBracket;
10610 var RIGHTPARENTHESIS$1 = TYPE$j.RightParenthesis;
10611 var PLUSSIGN$6 = TYPE$j.PlusSign;
10612 var NUMBERSIGN$2 = TYPE$j.NumberSign;
10613
10614 var Declaration = {
10615 name: 'Declaration',
10616 structure: {
10617 important: [Boolean, String],
10618 property: String,
10619 value: ['Value', 'Raw']
10620 },
10621 parse: function() {
10622 var start = this.scanner.tokenStart;
10623 var property = readProperty.call(this);
10624 var important = false;
10625 var value;
10626
10627 this.scanner.skipSC();
10628 this.scanner.eat(COLON$3);
10629
10630 if (isCustomProperty(property) ? this.parseCustomProperty : this.parseValue) {
10631 value = this.Value(property);
10632 } else {
10633 value = this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$2, SEMICOLON$4, false, false);
10634 }
10635
10636 if (this.scanner.tokenType === EXCLAMATIONMARK$2) {
10637 important = getImportant(this.scanner);
10638 this.scanner.skipSC();
10639 }
10640
10641 // TODO: include or not to include semicolon to range?
10642 // if (this.scanner.tokenType === SEMICOLON) {
10643 // this.scanner.next();
10644 // }
10645
10646 if (!this.scanner.eof &&
10647 this.scanner.tokenType !== SEMICOLON$4 &&
10648 this.scanner.tokenType !== RIGHTPARENTHESIS$1 &&
10649 this.scanner.tokenType !== RIGHTCURLYBRACKET$3) {
10650 this.scanner.error();
10651 }
10652
10653 return {
10654 type: 'Declaration',
10655 loc: this.getLocation(start, this.scanner.tokenStart),
10656 important: important,
10657 property: property,
10658 value: value
10659 };
10660 },
10661 generate: function(processChunk, node, item) {
10662 processChunk(node.property);
10663 processChunk(':');
10664 this.generate(processChunk, node.value);
10665
10666 if (node.important) {
10667 processChunk(node.important === true ? '!important' : '!' + node.important);
10668 }
10669
10670 if (item && item.next) {
10671 processChunk(';');
10672 }
10673 },
10674 walkContext: 'declaration'
10675 };
10676
10677 function isCustomProperty(name) {
10678 return name.length >= 2 &&
10679 name.charCodeAt(0) === HYPHENMINUS$6 &&
10680 name.charCodeAt(1) === HYPHENMINUS$6;
10681 }
10682
10683 function readProperty() {
10684 var start = this.scanner.tokenStart;
10685 var prefix = 0;
10686
10687 // hacks
10688 switch (this.scanner.tokenType) {
10689 case ASTERISK$4:
10690 case DOLLARSIGN$1:
10691 case PLUSSIGN$6:
10692 case NUMBERSIGN$2:
10693 prefix = 1;
10694 break;
10695
10696 // TODO: not sure we should support this hack
10697 case SOLIDUS$4:
10698 prefix = this.scanner.lookupType(1) === SOLIDUS$4 ? 2 : 1;
10699 break;
10700 }
10701
10702 if (this.scanner.lookupType(prefix) === HYPHENMINUS$6) {
10703 prefix++;
10704 }
10705
10706 if (prefix) {
10707 this.scanner.skip(prefix);
10708 }
10709
10710 this.scanner.eat(IDENTIFIER$a);
10711
10712 return this.scanner.substrToCursor(start);
10713 }
10714
10715 // ! ws* important
10716 function getImportant(scanner) {
10717 scanner.eat(EXCLAMATIONMARK$2);
10718 scanner.skipSC();
10719
10720 var important = scanner.consume(IDENTIFIER$a);
10721
10722 // store original value in case it differ from `important`
10723 // for better original source restoring and hacks like `!ie` support
10724 return important === 'important' ? true : important;
10725 }
10726
10727 var TYPE$k = tokenizer.TYPE;
10728
10729 var WHITESPACE$5 = TYPE$k.WhiteSpace;
10730 var COMMENT$5 = TYPE$k.Comment;
10731 var SEMICOLON$5 = TYPE$k.Semicolon;
10732
10733 function consumeRaw$3(startToken) {
10734 return this.Raw(startToken, 0, SEMICOLON$5, true, true);
10735 }
10736
10737 var DeclarationList = {
10738 name: 'DeclarationList',
10739 structure: {
10740 children: [['Declaration']]
10741 },
10742 parse: function() {
10743 var children = new list();
10744
10745
10746 while (!this.scanner.eof) {
10747 switch (this.scanner.tokenType) {
10748 case WHITESPACE$5:
10749 case COMMENT$5:
10750 case SEMICOLON$5:
10751 this.scanner.next();
10752 break;
10753
10754 default:
10755 children.appendData(this.tolerantParse(this.Declaration, consumeRaw$3));
10756 }
10757 }
10758
10759 return {
10760 type: 'DeclarationList',
10761 loc: this.getLocationFromList(children),
10762 children: children
10763 };
10764 },
10765 generate: function(processChunk, node) {
10766 this.each(processChunk, node);
10767 }
10768 };
10769
10770 var NUMBER$5 = tokenizer.TYPE.Number;
10771
10772 // special reader for units to avoid adjoined IE hacks (i.e. '1px\9')
10773 function readUnit(scanner) {
10774 var unit = scanner.getTokenValue();
10775 var backSlashPos = unit.indexOf('\\');
10776
10777 if (backSlashPos > 0) {
10778 // patch token offset
10779 scanner.tokenStart += backSlashPos;
10780
10781 // return part before backslash
10782 return unit.substring(0, backSlashPos);
10783 }
10784
10785 // no backslash in unit name
10786 scanner.next();
10787
10788 return unit;
10789 }
10790
10791 // number ident
10792 var Dimension = {
10793 name: 'Dimension',
10794 structure: {
10795 value: String,
10796 unit: String
10797 },
10798 parse: function() {
10799 var start = this.scanner.tokenStart;
10800 var value = this.scanner.consume(NUMBER$5);
10801 var unit = readUnit(this.scanner);
10802
10803 return {
10804 type: 'Dimension',
10805 loc: this.getLocation(start, this.scanner.tokenStart),
10806 value: value,
10807 unit: unit
10808 };
10809 },
10810 generate: function(processChunk, node) {
10811 processChunk(node.value);
10812 processChunk(node.unit);
10813 }
10814 };
10815
10816 var TYPE$l = tokenizer.TYPE;
10817 var RIGHTPARENTHESIS$2 = TYPE$l.RightParenthesis;
10818
10819 // <function-token> <sequence> ')'
10820 var _Function = {
10821 name: 'Function',
10822 structure: {
10823 name: String,
10824 children: [[]]
10825 },
10826 parse: function(readSequence, recognizer) {
10827 var start = this.scanner.tokenStart;
10828 var name = this.scanner.consumeFunctionName();
10829 var nameLowerCase = name.toLowerCase();
10830 var children;
10831
10832 children = recognizer.hasOwnProperty(nameLowerCase)
10833 ? recognizer[nameLowerCase].call(this, recognizer)
10834 : readSequence.call(this, recognizer);
10835
10836 this.scanner.eat(RIGHTPARENTHESIS$2);
10837
10838 return {
10839 type: 'Function',
10840 loc: this.getLocation(start, this.scanner.tokenStart),
10841 name: name,
10842 children: children
10843 };
10844 },
10845 generate: function(processChunk, node) {
10846 processChunk(node.name);
10847 processChunk('(');
10848 this.each(processChunk, node);
10849 processChunk(')');
10850 },
10851 walkContext: 'function'
10852 };
10853
10854 var isHex$1 = tokenizer.isHex;
10855 var TYPE$m = tokenizer.TYPE;
10856
10857 var IDENTIFIER$b = TYPE$m.Identifier;
10858 var NUMBER$6 = TYPE$m.Number;
10859 var NUMBERSIGN$3 = TYPE$m.NumberSign;
10860
10861 function consumeHexSequence(scanner, required) {
10862 if (!isHex$1(scanner.source.charCodeAt(scanner.tokenStart))) {
10863 if (required) {
10864 scanner.error('Unexpected input', scanner.tokenStart);
10865 } else {
10866 return;
10867 }
10868 }
10869
10870 for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
10871 var code = scanner.source.charCodeAt(pos);
10872
10873 // break on non-hex char
10874 if (!isHex$1(code)) {
10875 // break token, exclude symbol
10876 scanner.tokenStart = pos;
10877 return;
10878 }
10879 }
10880
10881 // token is full hex sequence, go to next token
10882 scanner.next();
10883 }
10884
10885 // # ident
10886 var HexColor = {
10887 name: 'HexColor',
10888 structure: {
10889 value: String
10890 },
10891 parse: function() {
10892 var start = this.scanner.tokenStart;
10893
10894 this.scanner.eat(NUMBERSIGN$3);
10895
10896
10897 switch (this.scanner.tokenType) {
10898 case NUMBER$6:
10899 consumeHexSequence(this.scanner, true);
10900
10901 // if token is identifier then number consists of hex only,
10902 // try to add identifier to result
10903 if (this.scanner.tokenType === IDENTIFIER$b) {
10904 consumeHexSequence(this.scanner, false);
10905 }
10906
10907 break;
10908
10909 case IDENTIFIER$b:
10910 consumeHexSequence(this.scanner, true);
10911 break;
10912
10913 default:
10914 this.scanner.error('Number or identifier is expected');
10915 }
10916
10917 return {
10918 type: 'HexColor',
10919 loc: this.getLocation(start, this.scanner.tokenStart),
10920 value: this.scanner.substrToCursor(start + 1) // skip #
10921 };
10922 },
10923 generate: function(processChunk, node) {
10924 processChunk('#');
10925 processChunk(node.value);
10926 }
10927 };
10928
10929 var TYPE$n = tokenizer.TYPE;
10930 var IDENTIFIER$c = TYPE$n.Identifier;
10931
10932 var Identifier = {
10933 name: 'Identifier',
10934 structure: {
10935 name: String
10936 },
10937 parse: function() {
10938 return {
10939 type: 'Identifier',
10940 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
10941 name: this.scanner.consume(IDENTIFIER$c)
10942 };
10943 },
10944 generate: function(processChunk, node) {
10945 processChunk(node.name);
10946 }
10947 };
10948
10949 var TYPE$o = tokenizer.TYPE;
10950 var IDENTIFIER$d = TYPE$o.Identifier;
10951 var NUMBERSIGN$4 = TYPE$o.NumberSign;
10952
10953 // '#' ident
10954 var IdSelector = {
10955 name: 'IdSelector',
10956 structure: {
10957 name: String
10958 },
10959 parse: function() {
10960 this.scanner.eat(NUMBERSIGN$4);
10961
10962 return {
10963 type: 'IdSelector',
10964 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10965 name: this.scanner.consume(IDENTIFIER$d)
10966 };
10967 },
10968 generate: function(processChunk, node) {
10969 processChunk('#');
10970 processChunk(node.name);
10971 }
10972 };
10973
10974 var TYPE$p = tokenizer.TYPE;
10975
10976 var IDENTIFIER$e = TYPE$p.Identifier;
10977 var NUMBER$7 = TYPE$p.Number;
10978 var LEFTPARENTHESIS$4 = TYPE$p.LeftParenthesis;
10979 var RIGHTPARENTHESIS$3 = TYPE$p.RightParenthesis;
10980 var COLON$4 = TYPE$p.Colon;
10981 var SOLIDUS$5 = TYPE$p.Solidus;
10982
10983 var MediaFeature = {
10984 name: 'MediaFeature',
10985 structure: {
10986 name: String,
10987 value: ['Identifier', 'Number', 'Dimension', 'Ratio', null]
10988 },
10989 parse: function() {
10990 var start = this.scanner.tokenStart;
10991 var name;
10992 var value = null;
10993
10994 this.scanner.eat(LEFTPARENTHESIS$4);
10995 this.scanner.skipSC();
10996
10997 name = this.scanner.consume(IDENTIFIER$e);
10998 this.scanner.skipSC();
10999
11000 if (this.scanner.tokenType !== RIGHTPARENTHESIS$3) {
11001 this.scanner.eat(COLON$4);
11002 this.scanner.skipSC();
11003
11004 switch (this.scanner.tokenType) {
11005 case NUMBER$7:
11006 if (this.scanner.lookupType(1) === IDENTIFIER$e) {
11007 value = this.Dimension();
11008 } else if (this.scanner.lookupNonWSType(1) === SOLIDUS$5) {
11009 value = this.Ratio();
11010 } else {
11011 value = this.Number();
11012 }
11013
11014 break;
11015
11016 case IDENTIFIER$e:
11017 value = this.Identifier();
11018
11019 break;
11020
11021 default:
11022 this.scanner.error('Number, dimension, ratio or identifier is expected');
11023 }
11024
11025 this.scanner.skipSC();
11026 }
11027
11028 this.scanner.eat(RIGHTPARENTHESIS$3);
11029
11030 return {
11031 type: 'MediaFeature',
11032 loc: this.getLocation(start, this.scanner.tokenStart),
11033 name: name,
11034 value: value
11035 };
11036 },
11037 generate: function(processChunk, node) {
11038 processChunk('(');
11039 processChunk(node.name);
11040 if (node.value !== null) {
11041 processChunk(':');
11042 this.generate(processChunk, node.value);
11043 }
11044 processChunk(')');
11045 }
11046 };
11047
11048 var TYPE$q = tokenizer.TYPE;
11049
11050 var WHITESPACE$6 = TYPE$q.WhiteSpace;
11051 var COMMENT$6 = TYPE$q.Comment;
11052 var IDENTIFIER$f = TYPE$q.Identifier;
11053 var LEFTPARENTHESIS$5 = TYPE$q.LeftParenthesis;
11054
11055 var MediaQuery = {
11056 name: 'MediaQuery',
11057 structure: {
11058 children: [['Identifier', 'MediaFeature', 'WhiteSpace']]
11059 },
11060 parse: function() {
11061 this.scanner.skipSC();
11062
11063 var children = new list();
11064 var child = null;
11065 var space = null;
11066
11067 scan:
11068 while (!this.scanner.eof) {
11069 switch (this.scanner.tokenType) {
11070 case COMMENT$6:
11071 this.scanner.next();
11072 continue;
11073
11074 case WHITESPACE$6:
11075 space = this.WhiteSpace();
11076 continue;
11077
11078 case IDENTIFIER$f:
11079 child = this.Identifier();
11080 break;
11081
11082 case LEFTPARENTHESIS$5:
11083 child = this.MediaFeature();
11084 break;
11085
11086 default:
11087 break scan;
11088 }
11089
11090 if (space !== null) {
11091 children.appendData(space);
11092 space = null;
11093 }
11094
11095 children.appendData(child);
11096 }
11097
11098 if (child === null) {
11099 this.scanner.error('Identifier or parenthesis is expected');
11100 }
11101
11102 return {
11103 type: 'MediaQuery',
11104 loc: this.getLocationFromList(children),
11105 children: children
11106 };
11107 },
11108 generate: function(processChunk, node) {
11109 this.each(processChunk, node);
11110 }
11111 };
11112
11113 var COMMA$2 = tokenizer.TYPE.Comma;
11114
11115 var MediaQueryList = {
11116 name: 'MediaQueryList',
11117 structure: {
11118 children: [['MediaQuery']]
11119 },
11120 parse: function(relative) {
11121 var children = new list();
11122
11123 this.scanner.skipSC();
11124
11125 while (!this.scanner.eof) {
11126 children.appendData(this.MediaQuery(relative));
11127
11128 if (this.scanner.tokenType !== COMMA$2) {
11129 break;
11130 }
11131
11132 this.scanner.next();
11133 }
11134
11135 return {
11136 type: 'MediaQueryList',
11137 loc: this.getLocationFromList(children),
11138 children: children
11139 };
11140 },
11141 generate: function(processChunk, node) {
11142 this.eachComma(processChunk, node);
11143 }
11144 };
11145
11146 // https://drafts.csswg.org/css-syntax-3/#the-anb-type
11147 var Nth = {
11148 name: 'Nth',
11149 structure: {
11150 nth: ['AnPlusB', 'Identifier'],
11151 selector: ['SelectorList', null]
11152 },
11153 parse: function(allowOfClause) {
11154 this.scanner.skipSC();
11155
11156 var start = this.scanner.tokenStart;
11157 var end = start;
11158 var selector = null;
11159 var query;
11160
11161 if (this.scanner.lookupValue(0, 'odd') || this.scanner.lookupValue(0, 'even')) {
11162 query = this.Identifier();
11163 } else {
11164 query = this.AnPlusB();
11165 }
11166
11167 this.scanner.skipSC();
11168
11169 if (allowOfClause && this.scanner.lookupValue(0, 'of')) {
11170 this.scanner.next();
11171
11172 selector = this.SelectorList();
11173
11174 if (this.needPositions) {
11175 end = selector.children.last().loc.end.offset;
11176 }
11177 } else {
11178 if (this.needPositions) {
11179 end = query.loc.end.offset;
11180 }
11181 }
11182
11183 return {
11184 type: 'Nth',
11185 loc: this.getLocation(start, end),
11186 nth: query,
11187 selector: selector
11188 };
11189 },
11190 generate: function(processChunk, node) {
11191 this.generate(processChunk, node.nth);
11192 if (node.selector !== null) {
11193 processChunk(' of ');
11194 this.generate(processChunk, node.selector);
11195 }
11196 }
11197 };
11198
11199 var NUMBER$8 = tokenizer.TYPE.Number;
11200
11201 var _Number = {
11202 name: 'Number',
11203 structure: {
11204 value: String
11205 },
11206 parse: function() {
11207 return {
11208 type: 'Number',
11209 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11210 value: this.scanner.consume(NUMBER$8)
11211 };
11212 },
11213 generate: function(processChunk, node) {
11214 processChunk(node.value);
11215 }
11216 };
11217
11218 // '/' | '*' | ',' | ':' | '+' | '-'
11219 var Operator = {
11220 name: 'Operator',
11221 structure: {
11222 value: String
11223 },
11224 parse: function() {
11225 var start = this.scanner.tokenStart;
11226
11227 this.scanner.next();
11228
11229 return {
11230 type: 'Operator',
11231 loc: this.getLocation(start, this.scanner.tokenStart),
11232 value: this.scanner.substrToCursor(start)
11233 };
11234 },
11235 generate: function(processChunk, node) {
11236 processChunk(node.value);
11237 }
11238 };
11239
11240 var TYPE$r = tokenizer.TYPE;
11241 var LEFTPARENTHESIS$6 = TYPE$r.LeftParenthesis;
11242 var RIGHTPARENTHESIS$4 = TYPE$r.RightParenthesis;
11243
11244 var Parentheses = {
11245 name: 'Parentheses',
11246 structure: {
11247 children: [[]]
11248 },
11249 parse: function(readSequence, recognizer) {
11250 var start = this.scanner.tokenStart;
11251 var children = null;
11252
11253 this.scanner.eat(LEFTPARENTHESIS$6);
11254 children = readSequence.call(this, recognizer);
11255 this.scanner.eat(RIGHTPARENTHESIS$4);
11256
11257 return {
11258 type: 'Parentheses',
11259 loc: this.getLocation(start, this.scanner.tokenStart),
11260 children: children
11261 };
11262 },
11263 generate: function(processChunk, node) {
11264 processChunk('(');
11265 this.each(processChunk, node);
11266 processChunk(')');
11267 }
11268 };
11269
11270 var TYPE$s = tokenizer.TYPE;
11271
11272 var NUMBER$9 = TYPE$s.Number;
11273 var PERCENTSIGN$1 = TYPE$s.PercentSign;
11274
11275 var Percentage = {
11276 name: 'Percentage',
11277 structure: {
11278 value: String
11279 },
11280 parse: function() {
11281 var start = this.scanner.tokenStart;
11282 var number = this.scanner.consume(NUMBER$9);
11283
11284 this.scanner.eat(PERCENTSIGN$1);
11285
11286 return {
11287 type: 'Percentage',
11288 loc: this.getLocation(start, this.scanner.tokenStart),
11289 value: number
11290 };
11291 },
11292 generate: function(processChunk, node) {
11293 processChunk(node.value);
11294 processChunk('%');
11295 }
11296 };
11297
11298 var TYPE$t = tokenizer.TYPE;
11299
11300 var IDENTIFIER$g = TYPE$t.Identifier;
11301 var FUNCTION$4 = TYPE$t.Function;
11302 var COLON$5 = TYPE$t.Colon;
11303 var RIGHTPARENTHESIS$5 = TYPE$t.RightParenthesis;
11304
11305 // : ident [ '(' .. ')' ]?
11306 var PseudoClassSelector = {
11307 name: 'PseudoClassSelector',
11308 structure: {
11309 name: String,
11310 children: [['Raw'], null]
11311 },
11312 parse: function() {
11313 var start = this.scanner.tokenStart;
11314 var children = null;
11315 var name;
11316 var nameLowerCase;
11317
11318 this.scanner.eat(COLON$5);
11319
11320 if (this.scanner.tokenType === FUNCTION$4) {
11321 name = this.scanner.consumeFunctionName();
11322 nameLowerCase = name.toLowerCase();
11323
11324 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11325 this.scanner.skipSC();
11326 children = this.pseudo[nameLowerCase].call(this);
11327 this.scanner.skipSC();
11328 } else {
11329 children = new list().appendData(
11330 this.Raw(this.scanner.currentToken, 0, 0, false, false)
11331 );
11332 }
11333
11334 this.scanner.eat(RIGHTPARENTHESIS$5);
11335 } else {
11336 name = this.scanner.consume(IDENTIFIER$g);
11337 }
11338
11339 return {
11340 type: 'PseudoClassSelector',
11341 loc: this.getLocation(start, this.scanner.tokenStart),
11342 name: name,
11343 children: children
11344 };
11345 },
11346 generate: function(processChunk, node) {
11347 processChunk(':');
11348 processChunk(node.name);
11349
11350 if (node.children !== null) {
11351 processChunk('(');
11352 this.each(processChunk, node);
11353 processChunk(')');
11354 }
11355 },
11356 walkContext: 'function'
11357 };
11358
11359 var TYPE$u = tokenizer.TYPE;
11360
11361 var IDENTIFIER$h = TYPE$u.Identifier;
11362 var FUNCTION$5 = TYPE$u.Function;
11363 var COLON$6 = TYPE$u.Colon;
11364 var RIGHTPARENTHESIS$6 = TYPE$u.RightParenthesis;
11365
11366 // :: ident [ '(' .. ')' ]?
11367 var PseudoElementSelector = {
11368 name: 'PseudoElementSelector',
11369 structure: {
11370 name: String,
11371 children: [['Raw'], null]
11372 },
11373 parse: function() {
11374 var start = this.scanner.tokenStart;
11375 var children = null;
11376 var name;
11377 var nameLowerCase;
11378
11379 this.scanner.eat(COLON$6);
11380 this.scanner.eat(COLON$6);
11381
11382 if (this.scanner.tokenType === FUNCTION$5) {
11383 name = this.scanner.consumeFunctionName();
11384 nameLowerCase = name.toLowerCase();
11385
11386 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11387 this.scanner.skipSC();
11388 children = this.pseudo[nameLowerCase].call(this);
11389 this.scanner.skipSC();
11390 } else {
11391 children = new list().appendData(
11392 this.Raw(this.scanner.currentToken, 0, 0, false, false)
11393 );
11394 }
11395
11396 this.scanner.eat(RIGHTPARENTHESIS$6);
11397 } else {
11398 name = this.scanner.consume(IDENTIFIER$h);
11399 }
11400
11401 return {
11402 type: 'PseudoElementSelector',
11403 loc: this.getLocation(start, this.scanner.tokenStart),
11404 name: name,
11405 children: children
11406 };
11407 },
11408 generate: function(processChunk, node) {
11409 processChunk('::');
11410 processChunk(node.name);
11411
11412 if (node.children !== null) {
11413 processChunk('(');
11414 this.each(processChunk, node);
11415 processChunk(')');
11416 }
11417 },
11418 walkContext: 'function'
11419 };
11420
11421 var isNumber$3 = tokenizer.isNumber;
11422 var TYPE$v = tokenizer.TYPE;
11423 var NUMBER$a = TYPE$v.Number;
11424 var SOLIDUS$6 = TYPE$v.Solidus;
11425 var FULLSTOP$4 = TYPE$v.FullStop;
11426
11427 // Terms of <ratio> should to be a positive number (not zero or negative)
11428 // (see https://drafts.csswg.org/mediaqueries-3/#values)
11429 // However, -o-min-device-pixel-ratio takes fractional values as a ratio's term
11430 // and this is using by various sites. Therefore we relax checking on parse
11431 // to test a term is unsigned number without exponent part.
11432 // Additional checks may to be applied on lexer validation.
11433 function consumeNumber(scanner) {
11434 var value = scanner.consumeNonWS(NUMBER$a);
11435
11436 for (var i = 0; i < value.length; i++) {
11437 var code = value.charCodeAt(i);
11438 if (!isNumber$3(code) && code !== FULLSTOP$4) {
11439 scanner.error('Unsigned number is expected', scanner.tokenStart - value.length + i);
11440 }
11441 }
11442
11443 if (Number(value) === 0) {
11444 scanner.error('Zero number is not allowed', scanner.tokenStart - value.length);
11445 }
11446
11447 return value;
11448 }
11449
11450 // <positive-integer> S* '/' S* <positive-integer>
11451 var Ratio = {
11452 name: 'Ratio',
11453 structure: {
11454 left: String,
11455 right: String
11456 },
11457 parse: function() {
11458 var start = this.scanner.tokenStart;
11459 var left = consumeNumber(this.scanner);
11460 var right;
11461
11462 this.scanner.eatNonWS(SOLIDUS$6);
11463 right = consumeNumber(this.scanner);
11464
11465 return {
11466 type: 'Ratio',
11467 loc: this.getLocation(start, this.scanner.tokenStart),
11468 left: left,
11469 right: right
11470 };
11471 },
11472 generate: function(processChunk, node) {
11473 processChunk(node.left);
11474 processChunk('/');
11475 processChunk(node.right);
11476 }
11477 };
11478
11479 var Raw = {
11480 name: 'Raw',
11481 structure: {
11482 value: String
11483 },
11484 parse: function(startToken, endTokenType1, endTokenType2, includeTokenType2, excludeWhiteSpace) {
11485 var startOffset = this.scanner.getTokenStart(startToken);
11486 var endOffset;
11487
11488 this.scanner.skip(
11489 this.scanner.getRawLength(
11490 startToken,
11491 endTokenType1,
11492 endTokenType2,
11493 includeTokenType2
11494 )
11495 );
11496
11497 if (excludeWhiteSpace && this.scanner.tokenStart > startOffset) {
11498 endOffset = this.scanner.getOffsetExcludeWS();
11499 } else {
11500 endOffset = this.scanner.tokenStart;
11501 }
11502
11503 return {
11504 type: 'Raw',
11505 loc: this.getLocation(startOffset, endOffset),
11506 value: this.scanner.source.substring(startOffset, endOffset)
11507 };
11508 },
11509 generate: function(processChunk, node) {
11510 processChunk(node.value);
11511 }
11512 };
11513
11514 var TYPE$w = tokenizer.TYPE;
11515
11516 var LEFTCURLYBRACKET$5 = TYPE$w.LeftCurlyBracket;
11517
11518 function consumeRaw$4(startToken) {
11519 return this.Raw(startToken, LEFTCURLYBRACKET$5, 0, false, true);
11520 }
11521
11522 var Rule = {
11523 name: 'Rule',
11524 structure: {
11525 selector: ['SelectorList', 'Raw'],
11526 block: ['Block']
11527 },
11528 parse: function() {
11529 var startToken = this.scanner.currentToken;
11530 var startOffset = this.scanner.tokenStart;
11531 var selector = this.parseSelector
11532 ? this.tolerantParse(this.SelectorList, consumeRaw$4)
11533 : consumeRaw$4.call(this, startToken);
11534 var block = this.Block(this.Declaration);
11535
11536 return {
11537 type: 'Rule',
11538 loc: this.getLocation(startOffset, this.scanner.tokenStart),
11539 selector: selector,
11540 block: block
11541 };
11542 },
11543 generate: function(processChunk, node) {
11544 this.generate(processChunk, node.selector);
11545 this.generate(processChunk, node.block);
11546 },
11547 walkContext: 'rule'
11548 };
11549
11550 var Selector = {
11551 name: 'Selector',
11552 structure: {
11553 children: [[
11554 'TypeSelector',
11555 'IdSelector',
11556 'ClassSelector',
11557 'AttributeSelector',
11558 'PseudoClassSelector',
11559 'PseudoElementSelector',
11560 'Combinator',
11561 'WhiteSpace'
11562 ]]
11563 },
11564 parse: function() {
11565 var children = this.readSequence(this.scope.Selector);
11566
11567 // nothing were consumed
11568 if (children.isEmpty()) {
11569 this.scanner.error('Selector is expected');
11570 }
11571
11572 return {
11573 type: 'Selector',
11574 loc: this.getLocationFromList(children),
11575 children: children
11576 };
11577 },
11578 generate: function(processChunk, node) {
11579 this.each(processChunk, node);
11580 }
11581 };
11582
11583 var TYPE$x = tokenizer.TYPE;
11584
11585 var COMMA$3 = TYPE$x.Comma;
11586 var LEFTCURLYBRACKET$6 = TYPE$x.LeftCurlyBracket;
11587
11588 var SelectorList = {
11589 name: 'SelectorList',
11590 structure: {
11591 children: [['Selector', 'Raw']]
11592 },
11593 parse: function() {
11594 var children = new list();
11595
11596 while (!this.scanner.eof) {
11597 children.appendData(this.parseSelector
11598 ? this.Selector()
11599 : this.Raw(this.scanner.currentToken, COMMA$3, LEFTCURLYBRACKET$6, false, false)
11600 );
11601
11602 if (this.scanner.tokenType === COMMA$3) {
11603 this.scanner.next();
11604 continue;
11605 }
11606
11607 break;
11608 }
11609
11610 return {
11611 type: 'SelectorList',
11612 loc: this.getLocationFromList(children),
11613 children: children
11614 };
11615 },
11616 generate: function(processChunk, node) {
11617 this.eachComma(processChunk, node);
11618 },
11619 walkContext: 'selector'
11620 };
11621
11622 var STRING$5 = tokenizer.TYPE.String;
11623
11624 var _String = {
11625 name: 'String',
11626 structure: {
11627 value: String
11628 },
11629 parse: function() {
11630 return {
11631 type: 'String',
11632 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11633 value: this.scanner.consume(STRING$5)
11634 };
11635 },
11636 generate: function(processChunk, node) {
11637 processChunk(node.value);
11638 }
11639 };
11640
11641 var TYPE$y = tokenizer.TYPE;
11642
11643 var WHITESPACE$7 = TYPE$y.WhiteSpace;
11644 var COMMENT$7 = TYPE$y.Comment;
11645 var EXCLAMATIONMARK$3 = TYPE$y.ExclamationMark;
11646 var ATRULE$4 = TYPE$y.Atrule;
11647 var CDO$3 = TYPE$y.CDO;
11648 var CDC$3 = TYPE$y.CDC;
11649
11650 function consumeRaw$5(startToken) {
11651 return this.Raw(startToken, 0, 0, false, false);
11652 }
11653
11654 var StyleSheet = {
11655 name: 'StyleSheet',
11656 structure: {
11657 children: [['Comment', 'Atrule', 'Rule', 'Raw']]
11658 },
11659 parse: function() {
11660 var start = this.scanner.tokenStart;
11661 var children = new list();
11662 var child;
11663
11664
11665 while (!this.scanner.eof) {
11666 switch (this.scanner.tokenType) {
11667 case WHITESPACE$7:
11668 this.scanner.next();
11669 continue;
11670
11671 case COMMENT$7:
11672 // ignore comments except exclamation comments (i.e. /*! .. */) on top level
11673 if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 2) !== EXCLAMATIONMARK$3) {
11674 this.scanner.next();
11675 continue;
11676 }
11677
11678 child = this.Comment();
11679 break;
11680
11681 case CDO$3: // <!--
11682 child = this.CDO();
11683 break;
11684
11685 case CDC$3: // -->
11686 child = this.CDC();
11687 break;
11688
11689 // CSS Syntax Module Level 3
11690 // §2.2 Error handling
11691 // At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule.
11692 case ATRULE$4:
11693 child = this.Atrule();
11694 break;
11695
11696 // Anything else starts a qualified rule ...
11697 default:
11698 child = this.tolerantParse(this.Rule, consumeRaw$5);
11699 }
11700
11701 children.appendData(child);
11702 }
11703
11704 return {
11705 type: 'StyleSheet',
11706 loc: this.getLocation(start, this.scanner.tokenStart),
11707 children: children
11708 };
11709 },
11710 generate: function(processChunk, node) {
11711 this.each(processChunk, node);
11712 },
11713 walkContext: 'stylesheet'
11714 };
11715
11716 var TYPE$z = tokenizer.TYPE;
11717
11718 var IDENTIFIER$i = TYPE$z.Identifier;
11719 var ASTERISK$5 = TYPE$z.Asterisk;
11720 var VERTICALLINE$2 = TYPE$z.VerticalLine;
11721
11722 function eatIdentifierOrAsterisk() {
11723 if (this.scanner.tokenType !== IDENTIFIER$i &&
11724 this.scanner.tokenType !== ASTERISK$5) {
11725 this.scanner.error('Identifier or asterisk is expected');
11726 }
11727
11728 this.scanner.next();
11729 }
11730
11731 // ident
11732 // ident|ident
11733 // ident|*
11734 // *
11735 // *|ident
11736 // *|*
11737 // |ident
11738 // |*
11739 var TypeSelector = {
11740 name: 'TypeSelector',
11741 structure: {
11742 name: String
11743 },
11744 parse: function() {
11745 var start = this.scanner.tokenStart;
11746
11747 if (this.scanner.tokenType === VERTICALLINE$2) {
11748 this.scanner.next();
11749 eatIdentifierOrAsterisk.call(this);
11750 } else {
11751 eatIdentifierOrAsterisk.call(this);
11752
11753 if (this.scanner.tokenType === VERTICALLINE$2) {
11754 this.scanner.next();
11755 eatIdentifierOrAsterisk.call(this);
11756 }
11757 }
11758
11759 return {
11760 type: 'TypeSelector',
11761 loc: this.getLocation(start, this.scanner.tokenStart),
11762 name: this.scanner.substrToCursor(start)
11763 };
11764 },
11765 generate: function(processChunk, node) {
11766 processChunk(node.name);
11767 }
11768 };
11769
11770 var isHex$2 = tokenizer.isHex;
11771 var TYPE$A = tokenizer.TYPE;
11772
11773 var IDENTIFIER$j = TYPE$A.Identifier;
11774 var NUMBER$b = TYPE$A.Number;
11775 var PLUSSIGN$7 = TYPE$A.PlusSign;
11776 var HYPHENMINUS$7 = TYPE$A.HyphenMinus;
11777 var FULLSTOP$5 = TYPE$A.FullStop;
11778 var QUESTIONMARK = TYPE$A.QuestionMark;
11779
11780 function scanUnicodeNumber(scanner) {
11781 for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
11782 var code = scanner.source.charCodeAt(pos);
11783
11784 // break on fullstop or hyperminus/plussign after exponent
11785 if (code === FULLSTOP$5 || code === PLUSSIGN$7) {
11786 // break token, exclude symbol
11787 scanner.tokenStart = pos;
11788 return false;
11789 }
11790 }
11791
11792 return true;
11793 }
11794
11795 // https://drafts.csswg.org/css-syntax-3/#urange
11796 function scanUnicodeRange(scanner) {
11797 var hexStart = scanner.tokenStart + 1; // skip +
11798 var hexLength = 0;
11799
11800 scan: {
11801 if (scanner.tokenType === NUMBER$b) {
11802 if (scanner.source.charCodeAt(scanner.tokenStart) !== FULLSTOP$5 && scanUnicodeNumber(scanner)) {
11803 scanner.next();
11804 } else if (scanner.source.charCodeAt(scanner.tokenStart) !== HYPHENMINUS$7) {
11805 break scan;
11806 }
11807 } else {
11808 scanner.next(); // PLUSSIGN
11809 }
11810
11811 if (scanner.tokenType === HYPHENMINUS$7) {
11812 scanner.next();
11813 }
11814
11815 if (scanner.tokenType === NUMBER$b) {
11816 scanner.next();
11817 }
11818
11819 if (scanner.tokenType === IDENTIFIER$j) {
11820 scanner.next();
11821 }
11822
11823 if (scanner.tokenStart === hexStart) {
11824 scanner.error('Unexpected input', hexStart);
11825 }
11826 }
11827
11828 // validate for U+x{1,6} or U+x{1,6}-x{1,6}
11829 // where x is [0-9a-fA-F]
11830 for (var i = hexStart, wasHyphenMinus = false; i < scanner.tokenStart; i++) {
11831 var code = scanner.source.charCodeAt(i);
11832
11833 if (isHex$2(code) === false && (code !== HYPHENMINUS$7 || wasHyphenMinus)) {
11834 scanner.error('Unexpected input', i);
11835 }
11836
11837 if (code === HYPHENMINUS$7) {
11838 // hex sequence shouldn't be an empty
11839 if (hexLength === 0) {
11840 scanner.error('Unexpected input', i);
11841 }
11842
11843 wasHyphenMinus = true;
11844 hexLength = 0;
11845 } else {
11846 hexLength++;
11847
11848 // too long hex sequence
11849 if (hexLength > 6) {
11850 scanner.error('Too long hex sequence', i);
11851 }
11852 }
11853
11854 }
11855
11856 // check we have a non-zero sequence
11857 if (hexLength === 0) {
11858 scanner.error('Unexpected input', i - 1);
11859 }
11860
11861 // U+abc???
11862 if (!wasHyphenMinus) {
11863 // consume as many U+003F QUESTION MARK (?) code points as possible
11864 for (; hexLength < 6 && !scanner.eof; scanner.next()) {
11865 if (scanner.tokenType !== QUESTIONMARK) {
11866 break;
11867 }
11868
11869 hexLength++;
11870 }
11871 }
11872 }
11873
11874 var UnicodeRange = {
11875 name: 'UnicodeRange',
11876 structure: {
11877 value: String
11878 },
11879 parse: function() {
11880 var start = this.scanner.tokenStart;
11881
11882 this.scanner.next(); // U or u
11883 scanUnicodeRange(this.scanner);
11884
11885 return {
11886 type: 'UnicodeRange',
11887 loc: this.getLocation(start, this.scanner.tokenStart),
11888 value: this.scanner.substrToCursor(start)
11889 };
11890 },
11891 generate: function(processChunk, node) {
11892 processChunk(node.value);
11893 }
11894 };
11895
11896 var TYPE$B = tokenizer.TYPE;
11897
11898 var STRING$6 = TYPE$B.String;
11899 var URL$5 = TYPE$B.Url;
11900 var RAW$2 = TYPE$B.Raw;
11901 var RIGHTPARENTHESIS$7 = TYPE$B.RightParenthesis;
11902
11903 // url '(' S* (string | raw) S* ')'
11904 var Url = {
11905 name: 'Url',
11906 structure: {
11907 value: ['String', 'Raw']
11908 },
11909 parse: function() {
11910 var start = this.scanner.tokenStart;
11911 var value;
11912
11913 this.scanner.eat(URL$5);
11914 this.scanner.skipSC();
11915
11916 switch (this.scanner.tokenType) {
11917 case STRING$6:
11918 value = this.String();
11919 break;
11920
11921 case RAW$2:
11922 value = this.Raw(this.scanner.currentToken, 0, RAW$2, true, false);
11923 break;
11924
11925 default:
11926 this.scanner.error('String or Raw is expected');
11927 }
11928
11929 this.scanner.skipSC();
11930 this.scanner.eat(RIGHTPARENTHESIS$7);
11931
11932 return {
11933 type: 'Url',
11934 loc: this.getLocation(start, this.scanner.tokenStart),
11935 value: value
11936 };
11937 },
11938 generate: function(processChunk, node) {
11939 processChunk('url');
11940 processChunk('(');
11941 this.generate(processChunk, node.value);
11942 processChunk(')');
11943 }
11944 };
11945
11946 var endsWith$1 = tokenizer.endsWith;
11947 var TYPE$C = tokenizer.TYPE;
11948
11949 var WHITESPACE$8 = TYPE$C.WhiteSpace;
11950 var COMMENT$8 = TYPE$C.Comment;
11951 var FUNCTION$6 = TYPE$C.Function;
11952 var COLON$7 = TYPE$C.Colon;
11953 var SEMICOLON$6 = TYPE$C.Semicolon;
11954 var EXCLAMATIONMARK$4 = TYPE$C.ExclamationMark;
11955
11956 // 'progid:' ws* 'DXImageTransform.Microsoft.' ident ws* '(' .* ')'
11957 function checkProgid(scanner) {
11958 var offset = 0;
11959
11960 for (var type; type = scanner.lookupType(offset); offset++) {
11961 if (type !== WHITESPACE$8 && type !== COMMENT$8) {
11962 break;
11963 }
11964 }
11965
11966 if (scanner.lookupValue(offset, 'alpha(') ||
11967 scanner.lookupValue(offset, 'chroma(') ||
11968 scanner.lookupValue(offset, 'dropshadow(')) {
11969 if (scanner.lookupType(offset) !== FUNCTION$6) {
11970 return false;
11971 }
11972 } else {
11973 if (scanner.lookupValue(offset, 'progid') === false ||
11974 scanner.lookupType(offset + 1) !== COLON$7) {
11975 return false;
11976 }
11977 }
11978
11979 return true;
11980 }
11981
11982 var Value = {
11983 name: 'Value',
11984 structure: {
11985 children: [[]]
11986 },
11987 parse: function(property) {
11988 // special parser for filter property since it can contains non-standart syntax for old IE
11989 if (property !== null && endsWith$1(property, 'filter') && checkProgid(this.scanner)) {
11990 this.scanner.skipSC();
11991 return this.Raw(this.scanner.currentToken, EXCLAMATIONMARK$4, SEMICOLON$6, false, false);
11992 }
11993
11994 var start = this.scanner.tokenStart;
11995 var children = this.readSequence(this.scope.Value);
11996
11997 return {
11998 type: 'Value',
11999 loc: this.getLocation(start, this.scanner.tokenStart),
12000 children: children
12001 };
12002 },
12003 generate: function(processChunk, node) {
12004 this.each(processChunk, node);
12005 }
12006 };
12007
12008 var WHITESPACE$9 = tokenizer.TYPE.WhiteSpace;
12009 var SPACE$2 = Object.freeze({
12010 type: 'WhiteSpace',
12011 loc: null,
12012 value: ' '
12013 });
12014
12015 var WhiteSpace = {
12016 name: 'WhiteSpace',
12017 structure: {
12018 value: String
12019 },
12020 parse: function() {
12021 this.scanner.eat(WHITESPACE$9);
12022 return SPACE$2;
12023
12024 // return {
12025 // type: 'WhiteSpace',
12026 // loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
12027 // value: this.scanner.consume(WHITESPACE)
12028 // };
12029 },
12030 generate: function(processChunk, node) {
12031 processChunk(node.value);
12032 }
12033 };
12034
12035 var node = {
12036 AnPlusB: AnPlusB,
12037 Atrule: Atrule,
12038 AtruleExpression: AtruleExpression,
12039 AttributeSelector: AttributeSelector,
12040 Block: Block,
12041 Brackets: Brackets,
12042 CDC: CDC_1,
12043 CDO: CDO_1,
12044 ClassSelector: ClassSelector,
12045 Combinator: Combinator,
12046 Comment: Comment,
12047 Declaration: Declaration,
12048 DeclarationList: DeclarationList,
12049 Dimension: Dimension,
12050 Function: _Function,
12051 HexColor: HexColor,
12052 Identifier: Identifier,
12053 IdSelector: IdSelector,
12054 MediaFeature: MediaFeature,
12055 MediaQuery: MediaQuery,
12056 MediaQueryList: MediaQueryList,
12057 Nth: Nth,
12058 Number: _Number,
12059 Operator: Operator,
12060 Parentheses: Parentheses,
12061 Percentage: Percentage,
12062 PseudoClassSelector: PseudoClassSelector,
12063 PseudoElementSelector: PseudoElementSelector,
12064 Ratio: Ratio,
12065 Raw: Raw,
12066 Rule: Rule,
12067 Selector: Selector,
12068 SelectorList: SelectorList,
12069 String: _String,
12070 StyleSheet: StyleSheet,
12071 TypeSelector: TypeSelector,
12072 UnicodeRange: UnicodeRange,
12073 Url: Url,
12074 Value: Value,
12075 WhiteSpace: WhiteSpace
12076 };
12077
12078 var parser = {
12079 parseContext: {
12080 default: 'StyleSheet',
12081 stylesheet: 'StyleSheet',
12082 atrule: 'Atrule',
12083 atruleExpression: function(options) {
12084 return this.AtruleExpression(options.atrule ? String(options.atrule) : null);
12085 },
12086 mediaQueryList: 'MediaQueryList',
12087 mediaQuery: 'MediaQuery',
12088 rule: 'Rule',
12089 selectorList: 'SelectorList',
12090 selector: 'Selector',
12091 block: function() {
12092 return this.Block(this.Declaration);
12093 },
12094 declarationList: 'DeclarationList',
12095 declaration: 'Declaration',
12096 value: function(options) {
12097 return this.Value(options.property ? String(options.property) : null);
12098 }
12099 },
12100 scope: scope,
12101 atrule: atrule,
12102 pseudo: pseudo,
12103 node: node
12104 };
12105
12106 var parser$1 = create(parser);
12107
12108 function read_style(parser, start, attributes) {
12109 const content_start = parser.index;
12110 const styles = parser.read_until(/<\/style>/);
12111 const content_end = parser.index;
12112 let ast;
12113 try {
12114 ast = parser$1(styles, {
12115 positions: true,
12116 offset: content_start
12117 });
12118 }
12119 catch (err) {
12120 if (err.name === 'CssSyntaxError') {
12121 parser.error({
12122 code: 'css-syntax-error',
12123 message: err.message
12124 }, err.offset);
12125 }
12126 else {
12127 throw err;
12128 }
12129 }
12130 ast = JSON.parse(JSON.stringify(ast));
12131 // tidy up AST
12132 walk(ast, {
12133 enter: (node) => {
12134 // replace `ref:a` nodes
12135 if (node.type === 'Selector') {
12136 for (let i = 0; i < node.children.length; i += 1) {
12137 const a = node.children[i];
12138 const b = node.children[i + 1];
12139 if (is_ref_selector(a, b)) {
12140 parser.error({
12141 code: 'invalid-ref-selector',
12142 message: 'ref selectors are no longer supported'
12143 }, a.loc.start.offset);
12144 }
12145 }
12146 }
12147 if (node.type === 'Declaration' && node.value.type === 'Value' && node.value.children.length === 0) {
12148 parser.error({
12149 code: 'invalid-declaration',
12150 message: 'Declaration cannot be empty'
12151 }, node.start);
12152 }
12153 if (node.type === 'PseudoClassSelector' && node.name === 'global' && node.children === null) {
12154 parser.error({
12155 code: 'css-syntax-error',
12156 message: ':global() must contain a selector'
12157 }, node.loc.start.offset);
12158 }
12159 if (node.loc) {
12160 node.start = node.loc.start.offset;
12161 node.end = node.loc.end.offset;
12162 delete node.loc;
12163 }
12164 }
12165 });
12166 parser.eat('</style>', true);
12167 const end = parser.index;
12168 return {
12169 type: 'Style',
12170 start,
12171 end,
12172 attributes,
12173 children: ast.children,
12174 content: {
12175 start: content_start,
12176 end: content_end,
12177 styles
12178 }
12179 };
12180 }
12181 function is_ref_selector(a, b) {
12182 if (!b)
12183 return false;
12184 return (a.type === 'TypeSelector' &&
12185 a.name === 'ref' &&
12186 b.type === 'PseudoClassSelector');
12187 }
12188
12189 // https://dev.w3.org/html5/html-author/charref
12190 var entities = {
12191 CounterClockwiseContourIntegral: 8755,
12192 ClockwiseContourIntegral: 8754,
12193 DoubleLongLeftRightArrow: 10234,
12194 DiacriticalDoubleAcute: 733,
12195 NotSquareSupersetEqual: 8931,
12196 CloseCurlyDoubleQuote: 8221,
12197 DoubleContourIntegral: 8751,
12198 FilledVerySmallSquare: 9642,
12199 NegativeVeryThinSpace: 8203,
12200 NotPrecedesSlantEqual: 8928,
12201 NotRightTriangleEqual: 8941,
12202 NotSucceedsSlantEqual: 8929,
12203 CapitalDifferentialD: 8517,
12204 DoubleLeftRightArrow: 8660,
12205 DoubleLongRightArrow: 10233,
12206 EmptyVerySmallSquare: 9643,
12207 NestedGreaterGreater: 8811,
12208 NotDoubleVerticalBar: 8742,
12209 NotLeftTriangleEqual: 8940,
12210 NotSquareSubsetEqual: 8930,
12211 OpenCurlyDoubleQuote: 8220,
12212 ReverseUpEquilibrium: 10607,
12213 DoubleLongLeftArrow: 10232,
12214 DownLeftRightVector: 10576,
12215 LeftArrowRightArrow: 8646,
12216 NegativeMediumSpace: 8203,
12217 RightArrowLeftArrow: 8644,
12218 SquareSupersetEqual: 8850,
12219 leftrightsquigarrow: 8621,
12220 DownRightTeeVector: 10591,
12221 DownRightVectorBar: 10583,
12222 LongLeftRightArrow: 10231,
12223 Longleftrightarrow: 10234,
12224 NegativeThickSpace: 8203,
12225 PrecedesSlantEqual: 8828,
12226 ReverseEquilibrium: 8651,
12227 RightDoubleBracket: 10215,
12228 RightDownTeeVector: 10589,
12229 RightDownVectorBar: 10581,
12230 RightTriangleEqual: 8885,
12231 SquareIntersection: 8851,
12232 SucceedsSlantEqual: 8829,
12233 blacktriangleright: 9656,
12234 longleftrightarrow: 10231,
12235 DoubleUpDownArrow: 8661,
12236 DoubleVerticalBar: 8741,
12237 DownLeftTeeVector: 10590,
12238 DownLeftVectorBar: 10582,
12239 FilledSmallSquare: 9724,
12240 GreaterSlantEqual: 10878,
12241 LeftDoubleBracket: 10214,
12242 LeftDownTeeVector: 10593,
12243 LeftDownVectorBar: 10585,
12244 LeftTriangleEqual: 8884,
12245 NegativeThinSpace: 8203,
12246 NotReverseElement: 8716,
12247 NotTildeFullEqual: 8775,
12248 RightAngleBracket: 10217,
12249 RightUpDownVector: 10575,
12250 SquareSubsetEqual: 8849,
12251 VerticalSeparator: 10072,
12252 blacktriangledown: 9662,
12253 blacktriangleleft: 9666,
12254 leftrightharpoons: 8651,
12255 rightleftharpoons: 8652,
12256 twoheadrightarrow: 8608,
12257 DiacriticalAcute: 180,
12258 DiacriticalGrave: 96,
12259 DiacriticalTilde: 732,
12260 DoubleRightArrow: 8658,
12261 DownArrowUpArrow: 8693,
12262 EmptySmallSquare: 9723,
12263 GreaterEqualLess: 8923,
12264 GreaterFullEqual: 8807,
12265 LeftAngleBracket: 10216,
12266 LeftUpDownVector: 10577,
12267 LessEqualGreater: 8922,
12268 NonBreakingSpace: 160,
12269 NotRightTriangle: 8939,
12270 NotSupersetEqual: 8841,
12271 RightTriangleBar: 10704,
12272 RightUpTeeVector: 10588,
12273 RightUpVectorBar: 10580,
12274 UnderParenthesis: 9181,
12275 UpArrowDownArrow: 8645,
12276 circlearrowright: 8635,
12277 downharpoonright: 8642,
12278 ntrianglerighteq: 8941,
12279 rightharpoondown: 8641,
12280 rightrightarrows: 8649,
12281 twoheadleftarrow: 8606,
12282 vartriangleright: 8883,
12283 CloseCurlyQuote: 8217,
12284 ContourIntegral: 8750,
12285 DoubleDownArrow: 8659,
12286 DoubleLeftArrow: 8656,
12287 DownRightVector: 8641,
12288 LeftRightVector: 10574,
12289 LeftTriangleBar: 10703,
12290 LeftUpTeeVector: 10592,
12291 LeftUpVectorBar: 10584,
12292 LowerRightArrow: 8600,
12293 NotGreaterEqual: 8817,
12294 NotGreaterTilde: 8821,
12295 NotLeftTriangle: 8938,
12296 OverParenthesis: 9180,
12297 RightDownVector: 8642,
12298 ShortRightArrow: 8594,
12299 UpperRightArrow: 8599,
12300 bigtriangledown: 9661,
12301 circlearrowleft: 8634,
12302 curvearrowright: 8631,
12303 downharpoonleft: 8643,
12304 leftharpoondown: 8637,
12305 leftrightarrows: 8646,
12306 nLeftrightarrow: 8654,
12307 nleftrightarrow: 8622,
12308 ntrianglelefteq: 8940,
12309 rightleftarrows: 8644,
12310 rightsquigarrow: 8605,
12311 rightthreetimes: 8908,
12312 straightepsilon: 1013,
12313 trianglerighteq: 8885,
12314 vartriangleleft: 8882,
12315 DiacriticalDot: 729,
12316 DoubleRightTee: 8872,
12317 DownLeftVector: 8637,
12318 GreaterGreater: 10914,
12319 HorizontalLine: 9472,
12320 InvisibleComma: 8291,
12321 InvisibleTimes: 8290,
12322 LeftDownVector: 8643,
12323 LeftRightArrow: 8596,
12324 Leftrightarrow: 8660,
12325 LessSlantEqual: 10877,
12326 LongRightArrow: 10230,
12327 Longrightarrow: 10233,
12328 LowerLeftArrow: 8601,
12329 NestedLessLess: 8810,
12330 NotGreaterLess: 8825,
12331 NotLessGreater: 8824,
12332 NotSubsetEqual: 8840,
12333 NotVerticalBar: 8740,
12334 OpenCurlyQuote: 8216,
12335 ReverseElement: 8715,
12336 RightTeeVector: 10587,
12337 RightVectorBar: 10579,
12338 ShortDownArrow: 8595,
12339 ShortLeftArrow: 8592,
12340 SquareSuperset: 8848,
12341 TildeFullEqual: 8773,
12342 UpperLeftArrow: 8598,
12343 ZeroWidthSpace: 8203,
12344 curvearrowleft: 8630,
12345 doublebarwedge: 8966,
12346 downdownarrows: 8650,
12347 hookrightarrow: 8618,
12348 leftleftarrows: 8647,
12349 leftrightarrow: 8596,
12350 leftthreetimes: 8907,
12351 longrightarrow: 10230,
12352 looparrowright: 8620,
12353 nshortparallel: 8742,
12354 ntriangleright: 8939,
12355 rightarrowtail: 8611,
12356 rightharpoonup: 8640,
12357 trianglelefteq: 8884,
12358 upharpoonright: 8638,
12359 ApplyFunction: 8289,
12360 DifferentialD: 8518,
12361 DoubleLeftTee: 10980,
12362 DoubleUpArrow: 8657,
12363 LeftTeeVector: 10586,
12364 LeftVectorBar: 10578,
12365 LessFullEqual: 8806,
12366 LongLeftArrow: 10229,
12367 Longleftarrow: 10232,
12368 NotTildeEqual: 8772,
12369 NotTildeTilde: 8777,
12370 Poincareplane: 8460,
12371 PrecedesEqual: 10927,
12372 PrecedesTilde: 8830,
12373 RightArrowBar: 8677,
12374 RightTeeArrow: 8614,
12375 RightTriangle: 8883,
12376 RightUpVector: 8638,
12377 SucceedsEqual: 10928,
12378 SucceedsTilde: 8831,
12379 SupersetEqual: 8839,
12380 UpEquilibrium: 10606,
12381 VerticalTilde: 8768,
12382 VeryThinSpace: 8202,
12383 bigtriangleup: 9651,
12384 blacktriangle: 9652,
12385 divideontimes: 8903,
12386 fallingdotseq: 8786,
12387 hookleftarrow: 8617,
12388 leftarrowtail: 8610,
12389 leftharpoonup: 8636,
12390 longleftarrow: 10229,
12391 looparrowleft: 8619,
12392 measuredangle: 8737,
12393 ntriangleleft: 8938,
12394 shortparallel: 8741,
12395 smallsetminus: 8726,
12396 triangleright: 9657,
12397 upharpoonleft: 8639,
12398 DownArrowBar: 10515,
12399 DownTeeArrow: 8615,
12400 ExponentialE: 8519,
12401 GreaterEqual: 8805,
12402 GreaterTilde: 8819,
12403 HilbertSpace: 8459,
12404 HumpDownHump: 8782,
12405 Intersection: 8898,
12406 LeftArrowBar: 8676,
12407 LeftTeeArrow: 8612,
12408 LeftTriangle: 8882,
12409 LeftUpVector: 8639,
12410 NotCongruent: 8802,
12411 NotLessEqual: 8816,
12412 NotLessTilde: 8820,
12413 Proportional: 8733,
12414 RightCeiling: 8969,
12415 RoundImplies: 10608,
12416 ShortUpArrow: 8593,
12417 SquareSubset: 8847,
12418 UnderBracket: 9141,
12419 VerticalLine: 124,
12420 blacklozenge: 10731,
12421 exponentiale: 8519,
12422 risingdotseq: 8787,
12423 triangledown: 9663,
12424 triangleleft: 9667,
12425 CircleMinus: 8854,
12426 CircleTimes: 8855,
12427 Equilibrium: 8652,
12428 GreaterLess: 8823,
12429 LeftCeiling: 8968,
12430 LessGreater: 8822,
12431 MediumSpace: 8287,
12432 NotPrecedes: 8832,
12433 NotSucceeds: 8833,
12434 OverBracket: 9140,
12435 RightVector: 8640,
12436 Rrightarrow: 8667,
12437 RuleDelayed: 10740,
12438 SmallCircle: 8728,
12439 SquareUnion: 8852,
12440 SubsetEqual: 8838,
12441 UpDownArrow: 8597,
12442 Updownarrow: 8661,
12443 VerticalBar: 8739,
12444 backepsilon: 1014,
12445 blacksquare: 9642,
12446 circledcirc: 8858,
12447 circleddash: 8861,
12448 curlyeqprec: 8926,
12449 curlyeqsucc: 8927,
12450 diamondsuit: 9830,
12451 eqslantless: 10901,
12452 expectation: 8496,
12453 nRightarrow: 8655,
12454 nrightarrow: 8603,
12455 preccurlyeq: 8828,
12456 precnapprox: 10937,
12457 quaternions: 8461,
12458 straightphi: 981,
12459 succcurlyeq: 8829,
12460 succnapprox: 10938,
12461 thickapprox: 8776,
12462 updownarrow: 8597,
12463 Bernoullis: 8492,
12464 CirclePlus: 8853,
12465 EqualTilde: 8770,
12466 Fouriertrf: 8497,
12467 ImaginaryI: 8520,
12468 Laplacetrf: 8466,
12469 LeftVector: 8636,
12470 Lleftarrow: 8666,
12471 NotElement: 8713,
12472 NotGreater: 8815,
12473 Proportion: 8759,
12474 RightArrow: 8594,
12475 RightFloor: 8971,
12476 Rightarrow: 8658,
12477 TildeEqual: 8771,
12478 TildeTilde: 8776,
12479 UnderBrace: 9183,
12480 UpArrowBar: 10514,
12481 UpTeeArrow: 8613,
12482 circledast: 8859,
12483 complement: 8705,
12484 curlywedge: 8911,
12485 eqslantgtr: 10902,
12486 gtreqqless: 10892,
12487 lessapprox: 10885,
12488 lesseqqgtr: 10891,
12489 lmoustache: 9136,
12490 longmapsto: 10236,
12491 mapstodown: 8615,
12492 mapstoleft: 8612,
12493 nLeftarrow: 8653,
12494 nleftarrow: 8602,
12495 precapprox: 10935,
12496 rightarrow: 8594,
12497 rmoustache: 9137,
12498 sqsubseteq: 8849,
12499 sqsupseteq: 8850,
12500 subsetneqq: 10955,
12501 succapprox: 10936,
12502 supsetneqq: 10956,
12503 upuparrows: 8648,
12504 varepsilon: 949,
12505 varnothing: 8709,
12506 Backslash: 8726,
12507 CenterDot: 183,
12508 CircleDot: 8857,
12509 Congruent: 8801,
12510 Coproduct: 8720,
12511 DoubleDot: 168,
12512 DownArrow: 8595,
12513 DownBreve: 785,
12514 Downarrow: 8659,
12515 HumpEqual: 8783,
12516 LeftArrow: 8592,
12517 LeftFloor: 8970,
12518 Leftarrow: 8656,
12519 LessTilde: 8818,
12520 Mellintrf: 8499,
12521 MinusPlus: 8723,
12522 NotCupCap: 8813,
12523 NotExists: 8708,
12524 OverBrace: 9182,
12525 PlusMinus: 177,
12526 Therefore: 8756,
12527 ThinSpace: 8201,
12528 TripleDot: 8411,
12529 UnionPlus: 8846,
12530 backprime: 8245,
12531 backsimeq: 8909,
12532 bigotimes: 10754,
12533 centerdot: 183,
12534 checkmark: 10003,
12535 complexes: 8450,
12536 dotsquare: 8865,
12537 downarrow: 8595,
12538 gtrapprox: 10886,
12539 gtreqless: 8923,
12540 heartsuit: 9829,
12541 leftarrow: 8592,
12542 lesseqgtr: 8922,
12543 nparallel: 8742,
12544 nshortmid: 8740,
12545 nsubseteq: 8840,
12546 nsupseteq: 8841,
12547 pitchfork: 8916,
12548 rationals: 8474,
12549 spadesuit: 9824,
12550 subseteqq: 10949,
12551 subsetneq: 8842,
12552 supseteqq: 10950,
12553 supsetneq: 8843,
12554 therefore: 8756,
12555 triangleq: 8796,
12556 varpropto: 8733,
12557 DDotrahd: 10513,
12558 DotEqual: 8784,
12559 Integral: 8747,
12560 LessLess: 10913,
12561 NotEqual: 8800,
12562 NotTilde: 8769,
12563 PartialD: 8706,
12564 Precedes: 8826,
12565 RightTee: 8866,
12566 Succeeds: 8827,
12567 SuchThat: 8715,
12568 Superset: 8835,
12569 Uarrocir: 10569,
12570 UnderBar: 818,
12571 andslope: 10840,
12572 angmsdaa: 10664,
12573 angmsdab: 10665,
12574 angmsdac: 10666,
12575 angmsdad: 10667,
12576 angmsdae: 10668,
12577 angmsdaf: 10669,
12578 angmsdag: 10670,
12579 angmsdah: 10671,
12580 angrtvbd: 10653,
12581 approxeq: 8778,
12582 awconint: 8755,
12583 backcong: 8780,
12584 barwedge: 8965,
12585 bbrktbrk: 9142,
12586 bigoplus: 10753,
12587 bigsqcup: 10758,
12588 biguplus: 10756,
12589 bigwedge: 8896,
12590 boxminus: 8863,
12591 boxtimes: 8864,
12592 capbrcup: 10825,
12593 circledR: 174,
12594 circledS: 9416,
12595 cirfnint: 10768,
12596 clubsuit: 9827,
12597 cupbrcap: 10824,
12598 curlyvee: 8910,
12599 cwconint: 8754,
12600 doteqdot: 8785,
12601 dotminus: 8760,
12602 drbkarow: 10512,
12603 dzigrarr: 10239,
12604 elinters: 9191,
12605 emptyset: 8709,
12606 eqvparsl: 10725,
12607 fpartint: 10765,
12608 geqslant: 10878,
12609 gesdotol: 10884,
12610 gnapprox: 10890,
12611 hksearow: 10533,
12612 hkswarow: 10534,
12613 imagline: 8464,
12614 imagpart: 8465,
12615 infintie: 10717,
12616 integers: 8484,
12617 intercal: 8890,
12618 intlarhk: 10775,
12619 laemptyv: 10676,
12620 ldrushar: 10571,
12621 leqslant: 10877,
12622 lesdotor: 10883,
12623 llcorner: 8990,
12624 lnapprox: 10889,
12625 lrcorner: 8991,
12626 lurdshar: 10570,
12627 mapstoup: 8613,
12628 multimap: 8888,
12629 naturals: 8469,
12630 otimesas: 10806,
12631 parallel: 8741,
12632 plusacir: 10787,
12633 pointint: 10773,
12634 precneqq: 10933,
12635 precnsim: 8936,
12636 profalar: 9006,
12637 profline: 8978,
12638 profsurf: 8979,
12639 raemptyv: 10675,
12640 realpart: 8476,
12641 rppolint: 10770,
12642 rtriltri: 10702,
12643 scpolint: 10771,
12644 setminus: 8726,
12645 shortmid: 8739,
12646 smeparsl: 10724,
12647 sqsubset: 8847,
12648 sqsupset: 8848,
12649 subseteq: 8838,
12650 succneqq: 10934,
12651 succnsim: 8937,
12652 supseteq: 8839,
12653 thetasym: 977,
12654 thicksim: 8764,
12655 timesbar: 10801,
12656 triangle: 9653,
12657 triminus: 10810,
12658 trpezium: 9186,
12659 ulcorner: 8988,
12660 urcorner: 8989,
12661 varkappa: 1008,
12662 varsigma: 962,
12663 vartheta: 977,
12664 Because: 8757,
12665 Cayleys: 8493,
12666 Cconint: 8752,
12667 Cedilla: 184,
12668 Diamond: 8900,
12669 DownTee: 8868,
12670 Element: 8712,
12671 Epsilon: 917,
12672 Implies: 8658,
12673 LeftTee: 8867,
12674 NewLine: 10,
12675 NoBreak: 8288,
12676 NotLess: 8814,
12677 Omicron: 927,
12678 OverBar: 175,
12679 Product: 8719,
12680 UpArrow: 8593,
12681 Uparrow: 8657,
12682 Upsilon: 933,
12683 alefsym: 8501,
12684 angrtvb: 8894,
12685 angzarr: 9084,
12686 asympeq: 8781,
12687 backsim: 8765,
12688 because: 8757,
12689 bemptyv: 10672,
12690 between: 8812,
12691 bigcirc: 9711,
12692 bigodot: 10752,
12693 bigstar: 9733,
12694 boxplus: 8862,
12695 ccupssm: 10832,
12696 cemptyv: 10674,
12697 cirscir: 10690,
12698 coloneq: 8788,
12699 congdot: 10861,
12700 cudarrl: 10552,
12701 cudarrr: 10549,
12702 cularrp: 10557,
12703 curarrm: 10556,
12704 dbkarow: 10511,
12705 ddagger: 8225,
12706 ddotseq: 10871,
12707 demptyv: 10673,
12708 diamond: 8900,
12709 digamma: 989,
12710 dotplus: 8724,
12711 dwangle: 10662,
12712 epsilon: 949,
12713 eqcolon: 8789,
12714 equivDD: 10872,
12715 gesdoto: 10882,
12716 gtquest: 10876,
12717 gtrless: 8823,
12718 harrcir: 10568,
12719 intprod: 10812,
12720 isindot: 8949,
12721 larrbfs: 10527,
12722 larrsim: 10611,
12723 lbrksld: 10639,
12724 lbrkslu: 10637,
12725 ldrdhar: 10599,
12726 lesdoto: 10881,
12727 lessdot: 8918,
12728 lessgtr: 8822,
12729 lesssim: 8818,
12730 lotimes: 10804,
12731 lozenge: 9674,
12732 ltquest: 10875,
12733 luruhar: 10598,
12734 maltese: 10016,
12735 minusdu: 10794,
12736 napprox: 8777,
12737 natural: 9838,
12738 nearrow: 8599,
12739 nexists: 8708,
12740 notinva: 8713,
12741 notinvb: 8951,
12742 notinvc: 8950,
12743 notniva: 8716,
12744 notnivb: 8958,
12745 notnivc: 8957,
12746 npolint: 10772,
12747 nsqsube: 8930,
12748 nsqsupe: 8931,
12749 nvinfin: 10718,
12750 nwarrow: 8598,
12751 olcross: 10683,
12752 omicron: 959,
12753 orderof: 8500,
12754 orslope: 10839,
12755 pertenk: 8241,
12756 planckh: 8462,
12757 pluscir: 10786,
12758 plussim: 10790,
12759 plustwo: 10791,
12760 precsim: 8830,
12761 quatint: 10774,
12762 questeq: 8799,
12763 rarrbfs: 10528,
12764 rarrsim: 10612,
12765 rbrksld: 10638,
12766 rbrkslu: 10640,
12767 rdldhar: 10601,
12768 realine: 8475,
12769 rotimes: 10805,
12770 ruluhar: 10600,
12771 searrow: 8600,
12772 simplus: 10788,
12773 simrarr: 10610,
12774 subedot: 10947,
12775 submult: 10945,
12776 subplus: 10943,
12777 subrarr: 10617,
12778 succsim: 8831,
12779 supdsub: 10968,
12780 supedot: 10948,
12781 suphsub: 10967,
12782 suplarr: 10619,
12783 supmult: 10946,
12784 supplus: 10944,
12785 swarrow: 8601,
12786 topfork: 10970,
12787 triplus: 10809,
12788 tritime: 10811,
12789 uparrow: 8593,
12790 upsilon: 965,
12791 uwangle: 10663,
12792 vzigzag: 10650,
12793 zigrarr: 8669,
12794 Aacute: 193,
12795 Abreve: 258,
12796 Agrave: 192,
12797 Assign: 8788,
12798 Atilde: 195,
12799 Barwed: 8966,
12800 Bumpeq: 8782,
12801 Cacute: 262,
12802 Ccaron: 268,
12803 Ccedil: 199,
12804 Colone: 10868,
12805 Conint: 8751,
12806 CupCap: 8781,
12807 Dagger: 8225,
12808 Dcaron: 270,
12809 DotDot: 8412,
12810 Dstrok: 272,
12811 Eacute: 201,
12812 Ecaron: 282,
12813 Egrave: 200,
12814 Exists: 8707,
12815 ForAll: 8704,
12816 Gammad: 988,
12817 Gbreve: 286,
12818 Gcedil: 290,
12819 HARDcy: 1066,
12820 Hstrok: 294,
12821 Iacute: 205,
12822 Igrave: 204,
12823 Itilde: 296,
12824 Jsercy: 1032,
12825 Kcedil: 310,
12826 Lacute: 313,
12827 Lambda: 923,
12828 Lcaron: 317,
12829 Lcedil: 315,
12830 Lmidot: 319,
12831 Lstrok: 321,
12832 Nacute: 323,
12833 Ncaron: 327,
12834 Ncedil: 325,
12835 Ntilde: 209,
12836 Oacute: 211,
12837 Odblac: 336,
12838 Ograve: 210,
12839 Oslash: 216,
12840 Otilde: 213,
12841 Otimes: 10807,
12842 Racute: 340,
12843 Rarrtl: 10518,
12844 Rcaron: 344,
12845 Rcedil: 342,
12846 SHCHcy: 1065,
12847 SOFTcy: 1068,
12848 Sacute: 346,
12849 Scaron: 352,
12850 Scedil: 350,
12851 Square: 9633,
12852 Subset: 8912,
12853 Supset: 8913,
12854 Tcaron: 356,
12855 Tcedil: 354,
12856 Tstrok: 358,
12857 Uacute: 218,
12858 Ubreve: 364,
12859 Udblac: 368,
12860 Ugrave: 217,
12861 Utilde: 360,
12862 Vdashl: 10982,
12863 Verbar: 8214,
12864 Vvdash: 8874,
12865 Yacute: 221,
12866 Zacute: 377,
12867 Zcaron: 381,
12868 aacute: 225,
12869 abreve: 259,
12870 agrave: 224,
12871 andand: 10837,
12872 angmsd: 8737,
12873 angsph: 8738,
12874 apacir: 10863,
12875 approx: 8776,
12876 atilde: 227,
12877 barvee: 8893,
12878 barwed: 8965,
12879 becaus: 8757,
12880 bernou: 8492,
12881 bigcap: 8898,
12882 bigcup: 8899,
12883 bigvee: 8897,
12884 bkarow: 10509,
12885 bottom: 8869,
12886 bowtie: 8904,
12887 boxbox: 10697,
12888 bprime: 8245,
12889 brvbar: 166,
12890 bullet: 8226,
12891 bumpeq: 8783,
12892 cacute: 263,
12893 capand: 10820,
12894 capcap: 10827,
12895 capcup: 10823,
12896 capdot: 10816,
12897 ccaron: 269,
12898 ccedil: 231,
12899 circeq: 8791,
12900 cirmid: 10991,
12901 colone: 8788,
12902 commat: 64,
12903 compfn: 8728,
12904 conint: 8750,
12905 coprod: 8720,
12906 copysr: 8471,
12907 cularr: 8630,
12908 cupcap: 10822,
12909 cupcup: 10826,
12910 cupdot: 8845,
12911 curarr: 8631,
12912 curren: 164,
12913 cylcty: 9005,
12914 dagger: 8224,
12915 daleth: 8504,
12916 dcaron: 271,
12917 dfisht: 10623,
12918 divide: 247,
12919 divonx: 8903,
12920 dlcorn: 8990,
12921 dlcrop: 8973,
12922 dollar: 36,
12923 drcorn: 8991,
12924 drcrop: 8972,
12925 dstrok: 273,
12926 eacute: 233,
12927 easter: 10862,
12928 ecaron: 283,
12929 ecolon: 8789,
12930 egrave: 232,
12931 egsdot: 10904,
12932 elsdot: 10903,
12933 emptyv: 8709,
12934 emsp13: 8196,
12935 emsp14: 8197,
12936 eparsl: 10723,
12937 eqcirc: 8790,
12938 equals: 61,
12939 equest: 8799,
12940 female: 9792,
12941 ffilig: 64259,
12942 ffllig: 64260,
12943 forall: 8704,
12944 frac12: 189,
12945 frac13: 8531,
12946 frac14: 188,
12947 frac15: 8533,
12948 frac16: 8537,
12949 frac18: 8539,
12950 frac23: 8532,
12951 frac25: 8534,
12952 frac34: 190,
12953 frac35: 8535,
12954 frac38: 8540,
12955 frac45: 8536,
12956 frac56: 8538,
12957 frac58: 8541,
12958 frac78: 8542,
12959 gacute: 501,
12960 gammad: 989,
12961 gbreve: 287,
12962 gesdot: 10880,
12963 gesles: 10900,
12964 gtlPar: 10645,
12965 gtrarr: 10616,
12966 gtrdot: 8919,
12967 gtrsim: 8819,
12968 hairsp: 8202,
12969 hamilt: 8459,
12970 hardcy: 1098,
12971 hearts: 9829,
12972 hellip: 8230,
12973 hercon: 8889,
12974 homtht: 8763,
12975 horbar: 8213,
12976 hslash: 8463,
12977 hstrok: 295,
12978 hybull: 8259,
12979 hyphen: 8208,
12980 iacute: 237,
12981 igrave: 236,
12982 iiiint: 10764,
12983 iinfin: 10716,
12984 incare: 8453,
12985 inodot: 305,
12986 intcal: 8890,
12987 iquest: 191,
12988 isinsv: 8947,
12989 itilde: 297,
12990 jsercy: 1112,
12991 kappav: 1008,
12992 kcedil: 311,
12993 kgreen: 312,
12994 lAtail: 10523,
12995 lacute: 314,
12996 lagran: 8466,
12997 lambda: 955,
12998 langle: 10216,
12999 larrfs: 10525,
13000 larrhk: 8617,
13001 larrlp: 8619,
13002 larrpl: 10553,
13003 larrtl: 8610,
13004 latail: 10521,
13005 lbrace: 123,
13006 lbrack: 91,
13007 lcaron: 318,
13008 lcedil: 316,
13009 ldquor: 8222,
13010 lesdot: 10879,
13011 lesges: 10899,
13012 lfisht: 10620,
13013 lfloor: 8970,
13014 lharul: 10602,
13015 llhard: 10603,
13016 lmidot: 320,
13017 lmoust: 9136,
13018 loplus: 10797,
13019 lowast: 8727,
13020 lowbar: 95,
13021 lparlt: 10643,
13022 lrhard: 10605,
13023 lsaquo: 8249,
13024 lsquor: 8218,
13025 lstrok: 322,
13026 lthree: 8907,
13027 ltimes: 8905,
13028 ltlarr: 10614,
13029 ltrPar: 10646,
13030 mapsto: 8614,
13031 marker: 9646,
13032 mcomma: 10793,
13033 midast: 42,
13034 midcir: 10992,
13035 middot: 183,
13036 minusb: 8863,
13037 minusd: 8760,
13038 mnplus: 8723,
13039 models: 8871,
13040 mstpos: 8766,
13041 nVDash: 8879,
13042 nVdash: 8878,
13043 nacute: 324,
13044 ncaron: 328,
13045 ncedil: 326,
13046 nearhk: 10532,
13047 nequiv: 8802,
13048 nesear: 10536,
13049 nexist: 8708,
13050 nltrie: 8940,
13051 nprcue: 8928,
13052 nrtrie: 8941,
13053 nsccue: 8929,
13054 nsimeq: 8772,
13055 ntilde: 241,
13056 numero: 8470,
13057 nvDash: 8877,
13058 nvHarr: 10500,
13059 nvdash: 8876,
13060 nvlArr: 10498,
13061 nvrArr: 10499,
13062 nwarhk: 10531,
13063 nwnear: 10535,
13064 oacute: 243,
13065 odblac: 337,
13066 odsold: 10684,
13067 ograve: 242,
13068 ominus: 8854,
13069 origof: 8886,
13070 oslash: 248,
13071 otilde: 245,
13072 otimes: 8855,
13073 parsim: 10995,
13074 percnt: 37,
13075 period: 46,
13076 permil: 8240,
13077 phmmat: 8499,
13078 planck: 8463,
13079 plankv: 8463,
13080 plusdo: 8724,
13081 plusdu: 10789,
13082 plusmn: 177,
13083 preceq: 10927,
13084 primes: 8473,
13085 prnsim: 8936,
13086 propto: 8733,
13087 prurel: 8880,
13088 puncsp: 8200,
13089 qprime: 8279,
13090 rAtail: 10524,
13091 racute: 341,
13092 rangle: 10217,
13093 rarrap: 10613,
13094 rarrfs: 10526,
13095 rarrhk: 8618,
13096 rarrlp: 8620,
13097 rarrpl: 10565,
13098 rarrtl: 8611,
13099 ratail: 10522,
13100 rbrace: 125,
13101 rbrack: 93,
13102 rcaron: 345,
13103 rcedil: 343,
13104 rdquor: 8221,
13105 rfisht: 10621,
13106 rfloor: 8971,
13107 rharul: 10604,
13108 rmoust: 9137,
13109 roplus: 10798,
13110 rpargt: 10644,
13111 rsaquo: 8250,
13112 rsquor: 8217,
13113 rthree: 8908,
13114 rtimes: 8906,
13115 sacute: 347,
13116 scaron: 353,
13117 scedil: 351,
13118 scnsim: 8937,
13119 searhk: 10533,
13120 seswar: 10537,
13121 sfrown: 8994,
13122 shchcy: 1097,
13123 sigmaf: 962,
13124 sigmav: 962,
13125 simdot: 10858,
13126 smashp: 10803,
13127 softcy: 1100,
13128 solbar: 9023,
13129 spades: 9824,
13130 sqsube: 8849,
13131 sqsupe: 8850,
13132 square: 9633,
13133 squarf: 9642,
13134 ssetmn: 8726,
13135 ssmile: 8995,
13136 sstarf: 8902,
13137 subdot: 10941,
13138 subset: 8834,
13139 subsim: 10951,
13140 subsub: 10965,
13141 subsup: 10963,
13142 succeq: 10928,
13143 supdot: 10942,
13144 supset: 8835,
13145 supsim: 10952,
13146 supsub: 10964,
13147 supsup: 10966,
13148 swarhk: 10534,
13149 swnwar: 10538,
13150 target: 8982,
13151 tcaron: 357,
13152 tcedil: 355,
13153 telrec: 8981,
13154 there4: 8756,
13155 thetav: 977,
13156 thinsp: 8201,
13157 thksim: 8764,
13158 timesb: 8864,
13159 timesd: 10800,
13160 topbot: 9014,
13161 topcir: 10993,
13162 tprime: 8244,
13163 tridot: 9708,
13164 tstrok: 359,
13165 uacute: 250,
13166 ubreve: 365,
13167 udblac: 369,
13168 ufisht: 10622,
13169 ugrave: 249,
13170 ulcorn: 8988,
13171 ulcrop: 8975,
13172 urcorn: 8989,
13173 urcrop: 8974,
13174 utilde: 361,
13175 vangrt: 10652,
13176 varphi: 966,
13177 varrho: 1009,
13178 veebar: 8891,
13179 vellip: 8942,
13180 verbar: 124,
13181 wedbar: 10847,
13182 wedgeq: 8793,
13183 weierp: 8472,
13184 wreath: 8768,
13185 xoplus: 10753,
13186 xotime: 10754,
13187 xsqcup: 10758,
13188 xuplus: 10756,
13189 xwedge: 8896,
13190 yacute: 253,
13191 zacute: 378,
13192 zcaron: 382,
13193 zeetrf: 8488,
13194 AElig: 198,
13195 Acirc: 194,
13196 Alpha: 913,
13197 Amacr: 256,
13198 Aogon: 260,
13199 Aring: 197,
13200 Breve: 728,
13201 Ccirc: 264,
13202 Colon: 8759,
13203 Cross: 10799,
13204 Dashv: 10980,
13205 Delta: 916,
13206 Ecirc: 202,
13207 Emacr: 274,
13208 Eogon: 280,
13209 Equal: 10869,
13210 Gamma: 915,
13211 Gcirc: 284,
13212 Hacek: 711,
13213 Hcirc: 292,
13214 IJlig: 306,
13215 Icirc: 206,
13216 Imacr: 298,
13217 Iogon: 302,
13218 Iukcy: 1030,
13219 Jcirc: 308,
13220 Jukcy: 1028,
13221 Kappa: 922,
13222 OElig: 338,
13223 Ocirc: 212,
13224 Omacr: 332,
13225 Omega: 937,
13226 Prime: 8243,
13227 RBarr: 10512,
13228 Scirc: 348,
13229 Sigma: 931,
13230 THORN: 222,
13231 TRADE: 8482,
13232 TSHcy: 1035,
13233 Theta: 920,
13234 Tilde: 8764,
13235 Ubrcy: 1038,
13236 Ucirc: 219,
13237 Umacr: 362,
13238 Union: 8899,
13239 Uogon: 370,
13240 UpTee: 8869,
13241 Uring: 366,
13242 VDash: 8875,
13243 Vdash: 8873,
13244 Wcirc: 372,
13245 Wedge: 8896,
13246 Ycirc: 374,
13247 acirc: 226,
13248 acute: 180,
13249 aelig: 230,
13250 aleph: 8501,
13251 alpha: 945,
13252 amacr: 257,
13253 amalg: 10815,
13254 angle: 8736,
13255 angrt: 8735,
13256 angst: 8491,
13257 aogon: 261,
13258 aring: 229,
13259 asymp: 8776,
13260 awint: 10769,
13261 bcong: 8780,
13262 bdquo: 8222,
13263 bepsi: 1014,
13264 blank: 9251,
13265 blk12: 9618,
13266 blk14: 9617,
13267 blk34: 9619,
13268 block: 9608,
13269 boxDL: 9559,
13270 boxDR: 9556,
13271 boxDl: 9558,
13272 boxDr: 9555,
13273 boxHD: 9574,
13274 boxHU: 9577,
13275 boxHd: 9572,
13276 boxHu: 9575,
13277 boxUL: 9565,
13278 boxUR: 9562,
13279 boxUl: 9564,
13280 boxUr: 9561,
13281 boxVH: 9580,
13282 boxVL: 9571,
13283 boxVR: 9568,
13284 boxVh: 9579,
13285 boxVl: 9570,
13286 boxVr: 9567,
13287 boxdL: 9557,
13288 boxdR: 9554,
13289 boxdl: 9488,
13290 boxdr: 9484,
13291 boxhD: 9573,
13292 boxhU: 9576,
13293 boxhd: 9516,
13294 boxhu: 9524,
13295 boxuL: 9563,
13296 boxuR: 9560,
13297 boxul: 9496,
13298 boxur: 9492,
13299 boxvH: 9578,
13300 boxvL: 9569,
13301 boxvR: 9566,
13302 boxvh: 9532,
13303 boxvl: 9508,
13304 boxvr: 9500,
13305 breve: 728,
13306 bsemi: 8271,
13307 bsime: 8909,
13308 bsolb: 10693,
13309 bumpE: 10926,
13310 bumpe: 8783,
13311 caret: 8257,
13312 caron: 711,
13313 ccaps: 10829,
13314 ccirc: 265,
13315 ccups: 10828,
13316 cedil: 184,
13317 check: 10003,
13318 clubs: 9827,
13319 colon: 58,
13320 comma: 44,
13321 crarr: 8629,
13322 cross: 10007,
13323 csube: 10961,
13324 csupe: 10962,
13325 ctdot: 8943,
13326 cuepr: 8926,
13327 cuesc: 8927,
13328 cupor: 10821,
13329 cuvee: 8910,
13330 cuwed: 8911,
13331 cwint: 8753,
13332 dashv: 8867,
13333 dblac: 733,
13334 ddarr: 8650,
13335 delta: 948,
13336 dharl: 8643,
13337 dharr: 8642,
13338 diams: 9830,
13339 disin: 8946,
13340 doteq: 8784,
13341 dtdot: 8945,
13342 dtrif: 9662,
13343 duarr: 8693,
13344 duhar: 10607,
13345 eDDot: 10871,
13346 ecirc: 234,
13347 efDot: 8786,
13348 emacr: 275,
13349 empty: 8709,
13350 eogon: 281,
13351 eplus: 10865,
13352 epsiv: 949,
13353 eqsim: 8770,
13354 equiv: 8801,
13355 erDot: 8787,
13356 erarr: 10609,
13357 esdot: 8784,
13358 exist: 8707,
13359 fflig: 64256,
13360 filig: 64257,
13361 fllig: 64258,
13362 fltns: 9649,
13363 forkv: 10969,
13364 frasl: 8260,
13365 frown: 8994,
13366 gamma: 947,
13367 gcirc: 285,
13368 gescc: 10921,
13369 gimel: 8503,
13370 gneqq: 8809,
13371 gnsim: 8935,
13372 grave: 96,
13373 gsime: 10894,
13374 gsiml: 10896,
13375 gtcir: 10874,
13376 gtdot: 8919,
13377 harrw: 8621,
13378 hcirc: 293,
13379 hoarr: 8703,
13380 icirc: 238,
13381 iexcl: 161,
13382 iiint: 8749,
13383 iiota: 8489,
13384 ijlig: 307,
13385 imacr: 299,
13386 image: 8465,
13387 imath: 305,
13388 imped: 437,
13389 infin: 8734,
13390 iogon: 303,
13391 iprod: 10812,
13392 isinE: 8953,
13393 isins: 8948,
13394 isinv: 8712,
13395 iukcy: 1110,
13396 jcirc: 309,
13397 jmath: 567,
13398 jukcy: 1108,
13399 kappa: 954,
13400 lAarr: 8666,
13401 lBarr: 10510,
13402 langd: 10641,
13403 laquo: 171,
13404 larrb: 8676,
13405 lbarr: 10508,
13406 lbbrk: 10098,
13407 lbrke: 10635,
13408 lceil: 8968,
13409 ldquo: 8220,
13410 lescc: 10920,
13411 lhard: 8637,
13412 lharu: 8636,
13413 lhblk: 9604,
13414 llarr: 8647,
13415 lltri: 9722,
13416 lneqq: 8808,
13417 lnsim: 8934,
13418 loang: 10220,
13419 loarr: 8701,
13420 lobrk: 10214,
13421 lopar: 10629,
13422 lrarr: 8646,
13423 lrhar: 8651,
13424 lrtri: 8895,
13425 lsime: 10893,
13426 lsimg: 10895,
13427 lsquo: 8216,
13428 ltcir: 10873,
13429 ltdot: 8918,
13430 ltrie: 8884,
13431 ltrif: 9666,
13432 mDDot: 8762,
13433 mdash: 8212,
13434 micro: 181,
13435 minus: 8722,
13436 mumap: 8888,
13437 nabla: 8711,
13438 napos: 329,
13439 natur: 9838,
13440 ncong: 8775,
13441 ndash: 8211,
13442 neArr: 8663,
13443 nearr: 8599,
13444 ngsim: 8821,
13445 nhArr: 8654,
13446 nharr: 8622,
13447 nhpar: 10994,
13448 nlArr: 8653,
13449 nlarr: 8602,
13450 nless: 8814,
13451 nlsim: 8820,
13452 nltri: 8938,
13453 notin: 8713,
13454 notni: 8716,
13455 nprec: 8832,
13456 nrArr: 8655,
13457 nrarr: 8603,
13458 nrtri: 8939,
13459 nsime: 8772,
13460 nsmid: 8740,
13461 nspar: 8742,
13462 nsube: 8840,
13463 nsucc: 8833,
13464 nsupe: 8841,
13465 numsp: 8199,
13466 nwArr: 8662,
13467 nwarr: 8598,
13468 ocirc: 244,
13469 odash: 8861,
13470 oelig: 339,
13471 ofcir: 10687,
13472 ohbar: 10677,
13473 olarr: 8634,
13474 olcir: 10686,
13475 oline: 8254,
13476 omacr: 333,
13477 omega: 969,
13478 operp: 10681,
13479 oplus: 8853,
13480 orarr: 8635,
13481 order: 8500,
13482 ovbar: 9021,
13483 parsl: 11005,
13484 phone: 9742,
13485 plusb: 8862,
13486 pluse: 10866,
13487 pound: 163,
13488 prcue: 8828,
13489 prime: 8242,
13490 prnap: 10937,
13491 prsim: 8830,
13492 quest: 63,
13493 rAarr: 8667,
13494 rBarr: 10511,
13495 radic: 8730,
13496 rangd: 10642,
13497 range: 10661,
13498 raquo: 187,
13499 rarrb: 8677,
13500 rarrc: 10547,
13501 rarrw: 8605,
13502 ratio: 8758,
13503 rbarr: 10509,
13504 rbbrk: 10099,
13505 rbrke: 10636,
13506 rceil: 8969,
13507 rdquo: 8221,
13508 reals: 8477,
13509 rhard: 8641,
13510 rharu: 8640,
13511 rlarr: 8644,
13512 rlhar: 8652,
13513 rnmid: 10990,
13514 roang: 10221,
13515 roarr: 8702,
13516 robrk: 10215,
13517 ropar: 10630,
13518 rrarr: 8649,
13519 rsquo: 8217,
13520 rtrie: 8885,
13521 rtrif: 9656,
13522 sbquo: 8218,
13523 sccue: 8829,
13524 scirc: 349,
13525 scnap: 10938,
13526 scsim: 8831,
13527 sdotb: 8865,
13528 sdote: 10854,
13529 seArr: 8664,
13530 searr: 8600,
13531 setmn: 8726,
13532 sharp: 9839,
13533 sigma: 963,
13534 simeq: 8771,
13535 simgE: 10912,
13536 simlE: 10911,
13537 simne: 8774,
13538 slarr: 8592,
13539 smile: 8995,
13540 sqcap: 8851,
13541 sqcup: 8852,
13542 sqsub: 8847,
13543 sqsup: 8848,
13544 srarr: 8594,
13545 starf: 9733,
13546 strns: 175,
13547 subnE: 10955,
13548 subne: 8842,
13549 supnE: 10956,
13550 supne: 8843,
13551 swArr: 8665,
13552 swarr: 8601,
13553 szlig: 223,
13554 theta: 952,
13555 thkap: 8776,
13556 thorn: 254,
13557 tilde: 732,
13558 times: 215,
13559 trade: 8482,
13560 trisb: 10701,
13561 tshcy: 1115,
13562 twixt: 8812,
13563 ubrcy: 1118,
13564 ucirc: 251,
13565 udarr: 8645,
13566 udhar: 10606,
13567 uharl: 8639,
13568 uharr: 8638,
13569 uhblk: 9600,
13570 ultri: 9720,
13571 umacr: 363,
13572 uogon: 371,
13573 uplus: 8846,
13574 upsih: 978,
13575 uring: 367,
13576 urtri: 9721,
13577 utdot: 8944,
13578 utrif: 9652,
13579 uuarr: 8648,
13580 vBarv: 10985,
13581 vDash: 8872,
13582 varpi: 982,
13583 vdash: 8866,
13584 veeeq: 8794,
13585 vltri: 8882,
13586 vprop: 8733,
13587 vrtri: 8883,
13588 wcirc: 373,
13589 wedge: 8743,
13590 xcirc: 9711,
13591 xdtri: 9661,
13592 xhArr: 10234,
13593 xharr: 10231,
13594 xlArr: 10232,
13595 xlarr: 10229,
13596 xodot: 10752,
13597 xrArr: 10233,
13598 xrarr: 10230,
13599 xutri: 9651,
13600 ycirc: 375,
13601 Aopf: 120120,
13602 Ascr: 119964,
13603 Auml: 196,
13604 Barv: 10983,
13605 Beta: 914,
13606 Bopf: 120121,
13607 Bscr: 8492,
13608 CHcy: 1063,
13609 COPY: 169,
13610 Cdot: 266,
13611 Copf: 8450,
13612 Cscr: 119966,
13613 DJcy: 1026,
13614 DScy: 1029,
13615 DZcy: 1039,
13616 Darr: 8609,
13617 Dopf: 120123,
13618 Dscr: 119967,
13619 Edot: 278,
13620 Eopf: 120124,
13621 Escr: 8496,
13622 Esim: 10867,
13623 Euml: 203,
13624 Fopf: 120125,
13625 Fscr: 8497,
13626 GJcy: 1027,
13627 Gdot: 288,
13628 Gopf: 120126,
13629 Gscr: 119970,
13630 Hopf: 8461,
13631 Hscr: 8459,
13632 IEcy: 1045,
13633 IOcy: 1025,
13634 Idot: 304,
13635 Iopf: 120128,
13636 Iota: 921,
13637 Iscr: 8464,
13638 Iuml: 207,
13639 Jopf: 120129,
13640 Jscr: 119973,
13641 KHcy: 1061,
13642 KJcy: 1036,
13643 Kopf: 120130,
13644 Kscr: 119974,
13645 LJcy: 1033,
13646 Lang: 10218,
13647 Larr: 8606,
13648 Lopf: 120131,
13649 Lscr: 8466,
13650 Mopf: 120132,
13651 Mscr: 8499,
13652 NJcy: 1034,
13653 Nopf: 8469,
13654 Nscr: 119977,
13655 Oopf: 120134,
13656 Oscr: 119978,
13657 Ouml: 214,
13658 Popf: 8473,
13659 Pscr: 119979,
13660 QUOT: 34,
13661 Qopf: 8474,
13662 Qscr: 119980,
13663 Rang: 10219,
13664 Rarr: 8608,
13665 Ropf: 8477,
13666 Rscr: 8475,
13667 SHcy: 1064,
13668 Sopf: 120138,
13669 Sqrt: 8730,
13670 Sscr: 119982,
13671 Star: 8902,
13672 TScy: 1062,
13673 Topf: 120139,
13674 Tscr: 119983,
13675 Uarr: 8607,
13676 Uopf: 120140,
13677 Upsi: 978,
13678 Uscr: 119984,
13679 Uuml: 220,
13680 Vbar: 10987,
13681 Vert: 8214,
13682 Vopf: 120141,
13683 Vscr: 119985,
13684 Wopf: 120142,
13685 Wscr: 119986,
13686 Xopf: 120143,
13687 Xscr: 119987,
13688 YAcy: 1071,
13689 YIcy: 1031,
13690 YUcy: 1070,
13691 Yopf: 120144,
13692 Yscr: 119988,
13693 Yuml: 376,
13694 ZHcy: 1046,
13695 Zdot: 379,
13696 Zeta: 918,
13697 Zopf: 8484,
13698 Zscr: 119989,
13699 andd: 10844,
13700 andv: 10842,
13701 ange: 10660,
13702 aopf: 120146,
13703 apid: 8779,
13704 apos: 39,
13705 ascr: 119990,
13706 auml: 228,
13707 bNot: 10989,
13708 bbrk: 9141,
13709 beta: 946,
13710 beth: 8502,
13711 bnot: 8976,
13712 bopf: 120147,
13713 boxH: 9552,
13714 boxV: 9553,
13715 boxh: 9472,
13716 boxv: 9474,
13717 bscr: 119991,
13718 bsim: 8765,
13719 bsol: 92,
13720 bull: 8226,
13721 bump: 8782,
13722 cdot: 267,
13723 cent: 162,
13724 chcy: 1095,
13725 cirE: 10691,
13726 circ: 710,
13727 cire: 8791,
13728 comp: 8705,
13729 cong: 8773,
13730 copf: 120148,
13731 copy: 169,
13732 cscr: 119992,
13733 csub: 10959,
13734 csup: 10960,
13735 dArr: 8659,
13736 dHar: 10597,
13737 darr: 8595,
13738 dash: 8208,
13739 diam: 8900,
13740 djcy: 1106,
13741 dopf: 120149,
13742 dscr: 119993,
13743 dscy: 1109,
13744 dsol: 10742,
13745 dtri: 9663,
13746 dzcy: 1119,
13747 eDot: 8785,
13748 ecir: 8790,
13749 edot: 279,
13750 emsp: 8195,
13751 ensp: 8194,
13752 eopf: 120150,
13753 epar: 8917,
13754 epsi: 1013,
13755 escr: 8495,
13756 esim: 8770,
13757 euml: 235,
13758 euro: 8364,
13759 excl: 33,
13760 flat: 9837,
13761 fnof: 402,
13762 fopf: 120151,
13763 fork: 8916,
13764 fscr: 119995,
13765 gdot: 289,
13766 geqq: 8807,
13767 gjcy: 1107,
13768 gnap: 10890,
13769 gneq: 10888,
13770 gopf: 120152,
13771 gscr: 8458,
13772 gsim: 8819,
13773 gtcc: 10919,
13774 hArr: 8660,
13775 half: 189,
13776 harr: 8596,
13777 hbar: 8463,
13778 hopf: 120153,
13779 hscr: 119997,
13780 iecy: 1077,
13781 imof: 8887,
13782 iocy: 1105,
13783 iopf: 120154,
13784 iota: 953,
13785 iscr: 119998,
13786 isin: 8712,
13787 iuml: 239,
13788 jopf: 120155,
13789 jscr: 119999,
13790 khcy: 1093,
13791 kjcy: 1116,
13792 kopf: 120156,
13793 kscr: 120000,
13794 lArr: 8656,
13795 lHar: 10594,
13796 lang: 10216,
13797 larr: 8592,
13798 late: 10925,
13799 lcub: 123,
13800 ldca: 10550,
13801 ldsh: 8626,
13802 leqq: 8806,
13803 ljcy: 1113,
13804 lnap: 10889,
13805 lneq: 10887,
13806 lopf: 120157,
13807 lozf: 10731,
13808 lpar: 40,
13809 lscr: 120001,
13810 lsim: 8818,
13811 lsqb: 91,
13812 ltcc: 10918,
13813 ltri: 9667,
13814 macr: 175,
13815 male: 9794,
13816 malt: 10016,
13817 mlcp: 10971,
13818 mldr: 8230,
13819 mopf: 120158,
13820 mscr: 120002,
13821 nbsp: 160,
13822 ncap: 10819,
13823 ncup: 10818,
13824 ngeq: 8817,
13825 ngtr: 8815,
13826 nisd: 8954,
13827 njcy: 1114,
13828 nldr: 8229,
13829 nleq: 8816,
13830 nmid: 8740,
13831 nopf: 120159,
13832 npar: 8742,
13833 nscr: 120003,
13834 nsim: 8769,
13835 nsub: 8836,
13836 nsup: 8837,
13837 ntgl: 8825,
13838 ntlg: 8824,
13839 oast: 8859,
13840 ocir: 8858,
13841 odiv: 10808,
13842 odot: 8857,
13843 ogon: 731,
13844 oint: 8750,
13845 omid: 10678,
13846 oopf: 120160,
13847 opar: 10679,
13848 ordf: 170,
13849 ordm: 186,
13850 oror: 10838,
13851 oscr: 8500,
13852 osol: 8856,
13853 ouml: 246,
13854 para: 182,
13855 part: 8706,
13856 perp: 8869,
13857 phiv: 966,
13858 plus: 43,
13859 popf: 120161,
13860 prap: 10935,
13861 prec: 8826,
13862 prnE: 10933,
13863 prod: 8719,
13864 prop: 8733,
13865 pscr: 120005,
13866 qint: 10764,
13867 qopf: 120162,
13868 qscr: 120006,
13869 quot: 34,
13870 rArr: 8658,
13871 rHar: 10596,
13872 race: 10714,
13873 rang: 10217,
13874 rarr: 8594,
13875 rcub: 125,
13876 rdca: 10551,
13877 rdsh: 8627,
13878 real: 8476,
13879 rect: 9645,
13880 rhov: 1009,
13881 ring: 730,
13882 ropf: 120163,
13883 rpar: 41,
13884 rscr: 120007,
13885 rsqb: 93,
13886 rtri: 9657,
13887 scap: 10936,
13888 scnE: 10934,
13889 sdot: 8901,
13890 sect: 167,
13891 semi: 59,
13892 sext: 10038,
13893 shcy: 1096,
13894 sime: 8771,
13895 simg: 10910,
13896 siml: 10909,
13897 smid: 8739,
13898 smte: 10924,
13899 solb: 10692,
13900 sopf: 120164,
13901 spar: 8741,
13902 squf: 9642,
13903 sscr: 120008,
13904 star: 9734,
13905 subE: 10949,
13906 sube: 8838,
13907 succ: 8827,
13908 sung: 9834,
13909 sup1: 185,
13910 sup2: 178,
13911 sup3: 179,
13912 supE: 10950,
13913 supe: 8839,
13914 tbrk: 9140,
13915 tdot: 8411,
13916 tint: 8749,
13917 toea: 10536,
13918 topf: 120165,
13919 tosa: 10537,
13920 trie: 8796,
13921 tscr: 120009,
13922 tscy: 1094,
13923 uArr: 8657,
13924 uHar: 10595,
13925 uarr: 8593,
13926 uopf: 120166,
13927 upsi: 965,
13928 uscr: 120010,
13929 utri: 9653,
13930 uuml: 252,
13931 vArr: 8661,
13932 vBar: 10984,
13933 varr: 8597,
13934 vert: 124,
13935 vopf: 120167,
13936 vscr: 120011,
13937 wopf: 120168,
13938 wscr: 120012,
13939 xcap: 8898,
13940 xcup: 8899,
13941 xmap: 10236,
13942 xnis: 8955,
13943 xopf: 120169,
13944 xscr: 120013,
13945 xvee: 8897,
13946 yacy: 1103,
13947 yicy: 1111,
13948 yopf: 120170,
13949 yscr: 120014,
13950 yucy: 1102,
13951 yuml: 255,
13952 zdot: 380,
13953 zeta: 950,
13954 zhcy: 1078,
13955 zopf: 120171,
13956 zscr: 120015,
13957 zwnj: 8204,
13958 AMP: 38,
13959 Acy: 1040,
13960 Afr: 120068,
13961 And: 10835,
13962 Bcy: 1041,
13963 Bfr: 120069,
13964 Cap: 8914,
13965 Cfr: 8493,
13966 Chi: 935,
13967 Cup: 8915,
13968 Dcy: 1044,
13969 Del: 8711,
13970 Dfr: 120071,
13971 Dot: 168,
13972 ENG: 330,
13973 ETH: 208,
13974 Ecy: 1069,
13975 Efr: 120072,
13976 Eta: 919,
13977 Fcy: 1060,
13978 Ffr: 120073,
13979 Gcy: 1043,
13980 Gfr: 120074,
13981 Hat: 94,
13982 Hfr: 8460,
13983 Icy: 1048,
13984 Ifr: 8465,
13985 Int: 8748,
13986 Jcy: 1049,
13987 Jfr: 120077,
13988 Kcy: 1050,
13989 Kfr: 120078,
13990 Lcy: 1051,
13991 Lfr: 120079,
13992 Lsh: 8624,
13993 Map: 10501,
13994 Mcy: 1052,
13995 Mfr: 120080,
13996 Ncy: 1053,
13997 Nfr: 120081,
13998 Not: 10988,
13999 Ocy: 1054,
14000 Ofr: 120082,
14001 Pcy: 1055,
14002 Pfr: 120083,
14003 Phi: 934,
14004 Psi: 936,
14005 Qfr: 120084,
14006 REG: 174,
14007 Rcy: 1056,
14008 Rfr: 8476,
14009 Rho: 929,
14010 Rsh: 8625,
14011 Scy: 1057,
14012 Sfr: 120086,
14013 Sub: 8912,
14014 Sum: 8721,
14015 Sup: 8913,
14016 Tab: 9,
14017 Tau: 932,
14018 Tcy: 1058,
14019 Tfr: 120087,
14020 Ucy: 1059,
14021 Ufr: 120088,
14022 Vcy: 1042,
14023 Vee: 8897,
14024 Vfr: 120089,
14025 Wfr: 120090,
14026 Xfr: 120091,
14027 Ycy: 1067,
14028 Yfr: 120092,
14029 Zcy: 1047,
14030 Zfr: 8488,
14031 acd: 8767,
14032 acy: 1072,
14033 afr: 120094,
14034 amp: 38,
14035 and: 8743,
14036 ang: 8736,
14037 apE: 10864,
14038 ape: 8778,
14039 ast: 42,
14040 bcy: 1073,
14041 bfr: 120095,
14042 bot: 8869,
14043 cap: 8745,
14044 cfr: 120096,
14045 chi: 967,
14046 cir: 9675,
14047 cup: 8746,
14048 dcy: 1076,
14049 deg: 176,
14050 dfr: 120097,
14051 die: 168,
14052 div: 247,
14053 dot: 729,
14054 ecy: 1101,
14055 efr: 120098,
14056 egs: 10902,
14057 ell: 8467,
14058 els: 10901,
14059 eng: 331,
14060 eta: 951,
14061 eth: 240,
14062 fcy: 1092,
14063 ffr: 120099,
14064 gEl: 10892,
14065 gap: 10886,
14066 gcy: 1075,
14067 gel: 8923,
14068 geq: 8805,
14069 ges: 10878,
14070 gfr: 120100,
14071 ggg: 8921,
14072 glE: 10898,
14073 gla: 10917,
14074 glj: 10916,
14075 gnE: 8809,
14076 gne: 10888,
14077 hfr: 120101,
14078 icy: 1080,
14079 iff: 8660,
14080 ifr: 120102,
14081 int: 8747,
14082 jcy: 1081,
14083 jfr: 120103,
14084 kcy: 1082,
14085 kfr: 120104,
14086 lEg: 10891,
14087 lap: 10885,
14088 lat: 10923,
14089 lcy: 1083,
14090 leg: 8922,
14091 leq: 8804,
14092 les: 10877,
14093 lfr: 120105,
14094 lgE: 10897,
14095 lnE: 8808,
14096 lne: 10887,
14097 loz: 9674,
14098 lrm: 8206,
14099 lsh: 8624,
14100 map: 8614,
14101 mcy: 1084,
14102 mfr: 120106,
14103 mho: 8487,
14104 mid: 8739,
14105 nap: 8777,
14106 ncy: 1085,
14107 nfr: 120107,
14108 nge: 8817,
14109 ngt: 8815,
14110 nis: 8956,
14111 niv: 8715,
14112 nle: 8816,
14113 nlt: 8814,
14114 not: 172,
14115 npr: 8832,
14116 nsc: 8833,
14117 num: 35,
14118 ocy: 1086,
14119 ofr: 120108,
14120 ogt: 10689,
14121 ohm: 8486,
14122 olt: 10688,
14123 ord: 10845,
14124 orv: 10843,
14125 par: 8741,
14126 pcy: 1087,
14127 pfr: 120109,
14128 phi: 966,
14129 piv: 982,
14130 prE: 10931,
14131 pre: 10927,
14132 psi: 968,
14133 qfr: 120110,
14134 rcy: 1088,
14135 reg: 174,
14136 rfr: 120111,
14137 rho: 961,
14138 rlm: 8207,
14139 rsh: 8625,
14140 scE: 10932,
14141 sce: 10928,
14142 scy: 1089,
14143 sfr: 120112,
14144 shy: 173,
14145 sim: 8764,
14146 smt: 10922,
14147 sol: 47,
14148 squ: 9633,
14149 sub: 8834,
14150 sum: 8721,
14151 sup: 8835,
14152 tau: 964,
14153 tcy: 1090,
14154 tfr: 120113,
14155 top: 8868,
14156 ucy: 1091,
14157 ufr: 120114,
14158 uml: 168,
14159 vcy: 1074,
14160 vee: 8744,
14161 vfr: 120115,
14162 wfr: 120116,
14163 xfr: 120117,
14164 ycy: 1099,
14165 yen: 165,
14166 yfr: 120118,
14167 zcy: 1079,
14168 zfr: 120119,
14169 zwj: 8205,
14170 DD: 8517,
14171 GT: 62,
14172 Gg: 8921,
14173 Gt: 8811,
14174 Im: 8465,
14175 LT: 60,
14176 Ll: 8920,
14177 Lt: 8810,
14178 Mu: 924,
14179 Nu: 925,
14180 Or: 10836,
14181 Pi: 928,
14182 Pr: 10939,
14183 Re: 8476,
14184 Sc: 10940,
14185 Xi: 926,
14186 ac: 8766,
14187 af: 8289,
14188 ap: 8776,
14189 dd: 8518,
14190 ee: 8519,
14191 eg: 10906,
14192 el: 10905,
14193 gE: 8807,
14194 ge: 8805,
14195 gg: 8811,
14196 gl: 8823,
14197 gt: 62,
14198 ic: 8291,
14199 ii: 8520,
14200 in: 8712,
14201 it: 8290,
14202 lE: 8806,
14203 le: 8804,
14204 lg: 8822,
14205 ll: 8810,
14206 lt: 60,
14207 mp: 8723,
14208 mu: 956,
14209 ne: 8800,
14210 ni: 8715,
14211 nu: 957,
14212 oS: 9416,
14213 or: 8744,
14214 pi: 960,
14215 pm: 177,
14216 pr: 8826,
14217 rx: 8478,
14218 sc: 8827,
14219 wp: 8472,
14220 wr: 8768,
14221 xi: 958
14222 };
14223
14224 const windows_1252 = [
14225 8364,
14226 129,
14227 8218,
14228 402,
14229 8222,
14230 8230,
14231 8224,
14232 8225,
14233 710,
14234 8240,
14235 352,
14236 8249,
14237 338,
14238 141,
14239 381,
14240 143,
14241 144,
14242 8216,
14243 8217,
14244 8220,
14245 8221,
14246 8226,
14247 8211,
14248 8212,
14249 732,
14250 8482,
14251 353,
14252 8250,
14253 339,
14254 157,
14255 382,
14256 376
14257 ];
14258 const entity_pattern = new RegExp(`&(#?(?:x[\\w\\d]+|\\d+|${Object.keys(entities).join('|')}))(?:;|\\b)`, 'g');
14259 function decode_character_references(html) {
14260 return html.replace(entity_pattern, (match, entity) => {
14261 let code;
14262 // Handle named entities
14263 if (entity[0] !== '#') {
14264 code = entities[entity];
14265 }
14266 else if (entity[1] === 'x') {
14267 code = parseInt(entity.substring(2), 16);
14268 }
14269 else {
14270 code = parseInt(entity.substring(1), 10);
14271 }
14272 if (!code) {
14273 return match;
14274 }
14275 return String.fromCodePoint(validate_code(code));
14276 });
14277 }
14278 const NUL = 0;
14279 // some code points are verboten. If we were inserting HTML, the browser would replace the illegal
14280 // code points with alternatives in some cases - since we're bypassing that mechanism, we need
14281 // to replace them ourselves
14282 //
14283 // Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
14284 function validate_code(code) {
14285 // line feed becomes generic whitespace
14286 if (code === 10) {
14287 return 32;
14288 }
14289 // ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
14290 if (code < 128) {
14291 return code;
14292 }
14293 // code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
14294 // to correct the mistake or we'll end up with missing € signs and so on
14295 if (code <= 159) {
14296 return windows_1252[code - 128];
14297 }
14298 // basic multilingual plane
14299 if (code < 55296) {
14300 return code;
14301 }
14302 // UTF-16 surrogate halves
14303 if (code <= 57343) {
14304 return NUL;
14305 }
14306 // rest of the basic multilingual plane
14307 if (code <= 65535) {
14308 return code;
14309 }
14310 // supplementary multilingual plane 0x10000 - 0x1ffff
14311 if (code >= 65536 && code <= 131071) {
14312 return code;
14313 }
14314 // supplementary ideographic plane 0x20000 - 0x2ffff
14315 if (code >= 131072 && code <= 196607) {
14316 return code;
14317 }
14318 return NUL;
14319 }
14320 // based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
14321 const disallowed_contents = new Map([
14322 ['li', new Set(['li'])],
14323 ['dt', new Set(['dt', 'dd'])],
14324 ['dd', new Set(['dt', 'dd'])],
14325 [
14326 'p',
14327 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(' '))
14328 ],
14329 ['rt', new Set(['rt', 'rp'])],
14330 ['rp', new Set(['rt', 'rp'])],
14331 ['optgroup', new Set(['optgroup'])],
14332 ['option', new Set(['option', 'optgroup'])],
14333 ['thead', new Set(['tbody', 'tfoot'])],
14334 ['tbody', new Set(['tbody', 'tfoot'])],
14335 ['tfoot', new Set(['tbody'])],
14336 ['tr', new Set(['tr', 'tbody'])],
14337 ['td', new Set(['td', 'th', 'tr'])],
14338 ['th', new Set(['td', 'th', 'tr'])]
14339 ]);
14340 // can this be a child of the parent element, or does it implicitly
14341 // close it, like `<li>one<li>two`?
14342 function closing_tag_omitted(current, next) {
14343 if (disallowed_contents.has(current)) {
14344 if (!next || disallowed_contents.get(current).has(next)) {
14345 return true;
14346 }
14347 }
14348 return false;
14349 }
14350
14351 // Adapted from https://github.com/acornjs/acorn/blob/6584815dca7440e00de841d1dad152302fdd7ca5/src/tokenize.js
14352 // Reproduced under MIT License https://github.com/acornjs/acorn/blob/master/LICENSE
14353 function full_char_code_at(str, i) {
14354 const code = str.charCodeAt(i);
14355 if (code <= 0xd7ff || code >= 0xe000)
14356 return code;
14357 const next = str.charCodeAt(i + 1);
14358 return (code << 10) + next - 0x35fdc00;
14359 }
14360
14361 const globals = new Set([
14362 'alert',
14363 'Array',
14364 'Boolean',
14365 'clearInterval',
14366 'clearTimeout',
14367 'confirm',
14368 'console',
14369 'Date',
14370 'decodeURI',
14371 'decodeURIComponent',
14372 'document',
14373 'Element',
14374 'encodeURI',
14375 'encodeURIComponent',
14376 'Error',
14377 'EvalError',
14378 'Event',
14379 'EventSource',
14380 'fetch',
14381 'global',
14382 'globalThis',
14383 'history',
14384 'Infinity',
14385 'InternalError',
14386 'Intl',
14387 'isFinite',
14388 'isNaN',
14389 'JSON',
14390 'localStorage',
14391 'location',
14392 'Map',
14393 'Math',
14394 'NaN',
14395 'navigator',
14396 'Number',
14397 'Node',
14398 'Object',
14399 'parseFloat',
14400 'parseInt',
14401 'process',
14402 'Promise',
14403 'prompt',
14404 'RangeError',
14405 'ReferenceError',
14406 'RegExp',
14407 'sessionStorage',
14408 'Set',
14409 'setInterval',
14410 'setTimeout',
14411 'String',
14412 'SyntaxError',
14413 'TypeError',
14414 'undefined',
14415 'URIError',
14416 'URL',
14417 'window'
14418 ]);
14419 const reserved = new Set([
14420 'arguments',
14421 'await',
14422 'break',
14423 'case',
14424 'catch',
14425 'class',
14426 'const',
14427 'continue',
14428 'debugger',
14429 'default',
14430 'delete',
14431 'do',
14432 'else',
14433 'enum',
14434 'eval',
14435 'export',
14436 'extends',
14437 'false',
14438 'finally',
14439 'for',
14440 'function',
14441 'if',
14442 'implements',
14443 'import',
14444 'in',
14445 'instanceof',
14446 'interface',
14447 'let',
14448 'new',
14449 'null',
14450 'package',
14451 'private',
14452 'protected',
14453 'public',
14454 'return',
14455 'static',
14456 'super',
14457 'switch',
14458 'this',
14459 'throw',
14460 'true',
14461 'try',
14462 'typeof',
14463 'var',
14464 'void',
14465 'while',
14466 'with',
14467 'yield'
14468 ]);
14469 const void_element_names = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
14470 function is_void(name) {
14471 return void_element_names.test(name) || name.toLowerCase() === '!doctype';
14472 }
14473 function is_valid(str) {
14474 let i = 0;
14475 while (i < str.length) {
14476 const code = full_char_code_at(str, i);
14477 if (!(i === 0 ? isIdentifierStart : isIdentifierChar)(code, true))
14478 return false;
14479 i += code <= 0xffff ? 1 : 2;
14480 }
14481 return true;
14482 }
14483 function sanitize(name) {
14484 return name
14485 .replace(/[^a-zA-Z0-9_]+/g, '_')
14486 .replace(/^_/, '')
14487 .replace(/_$/, '')
14488 .replace(/^[0-9]/, '_$&');
14489 }
14490
14491 function fuzzymatch(name, names) {
14492 const set = new FuzzySet(names);
14493 const matches = set.get(name);
14494 return matches && matches[0] && matches[0][0] > 0.7 ? matches[0][1] : null;
14495 }
14496 // adapted from https://github.com/Glench/fuzzyset.js/blob/master/lib/fuzzyset.js
14497 // BSD Licensed
14498 const GRAM_SIZE_LOWER = 2;
14499 const GRAM_SIZE_UPPER = 3;
14500 // return an edit distance from 0 to 1
14501 function _distance(str1, str2) {
14502 if (str1 === null && str2 === null) {
14503 throw 'Trying to compare two null values';
14504 }
14505 if (str1 === null || str2 === null)
14506 return 0;
14507 str1 = String(str1);
14508 str2 = String(str2);
14509 const distance = levenshtein(str1, str2);
14510 if (str1.length > str2.length) {
14511 return 1 - distance / str1.length;
14512 }
14513 else {
14514 return 1 - distance / str2.length;
14515 }
14516 }
14517 // helper functions
14518 function levenshtein(str1, str2) {
14519 const current = [];
14520 let prev;
14521 let value;
14522 for (let i = 0; i <= str2.length; i++) {
14523 for (let j = 0; j <= str1.length; j++) {
14524 if (i && j) {
14525 if (str1.charAt(j - 1) === str2.charAt(i - 1)) {
14526 value = prev;
14527 }
14528 else {
14529 value = Math.min(current[j], current[j - 1], prev) + 1;
14530 }
14531 }
14532 else {
14533 value = i + j;
14534 }
14535 prev = current[j];
14536 current[j] = value;
14537 }
14538 }
14539 return current.pop();
14540 }
14541 const non_word_regex = /[^\w, ]+/;
14542 function iterate_grams(value, gram_size = 2) {
14543 const simplified = '-' + value.toLowerCase().replace(non_word_regex, '') + '-';
14544 const len_diff = gram_size - simplified.length;
14545 const results = [];
14546 if (len_diff > 0) {
14547 for (let i = 0; i < len_diff; ++i) {
14548 value += '-';
14549 }
14550 }
14551 for (let i = 0; i < simplified.length - gram_size + 1; ++i) {
14552 results.push(simplified.slice(i, i + gram_size));
14553 }
14554 return results;
14555 }
14556 function gram_counter(value, gram_size = 2) {
14557 // return an object where key=gram, value=number of occurrences
14558 const result = {};
14559 const grams = iterate_grams(value, gram_size);
14560 let i = 0;
14561 for (i; i < grams.length; ++i) {
14562 if (grams[i] in result) {
14563 result[grams[i]] += 1;
14564 }
14565 else {
14566 result[grams[i]] = 1;
14567 }
14568 }
14569 return result;
14570 }
14571 function sort_descending(a, b) {
14572 return b[0] - a[0];
14573 }
14574 class FuzzySet {
14575 constructor(arr) {
14576 this.exact_set = {};
14577 this.match_dict = {};
14578 this.items = {};
14579 // initialization
14580 for (let i = GRAM_SIZE_LOWER; i < GRAM_SIZE_UPPER + 1; ++i) {
14581 this.items[i] = [];
14582 }
14583 // add all the items to the set
14584 for (let i = 0; i < arr.length; ++i) {
14585 this.add(arr[i]);
14586 }
14587 }
14588 add(value) {
14589 const normalized_value = value.toLowerCase();
14590 if (normalized_value in this.exact_set) {
14591 return false;
14592 }
14593 let i = GRAM_SIZE_LOWER;
14594 for (i; i < GRAM_SIZE_UPPER + 1; ++i) {
14595 this._add(value, i);
14596 }
14597 }
14598 _add(value, gram_size) {
14599 const normalized_value = value.toLowerCase();
14600 const items = this.items[gram_size] || [];
14601 const index = items.length;
14602 items.push(0);
14603 const gram_counts = gram_counter(normalized_value, gram_size);
14604 let sum_of_square_gram_counts = 0;
14605 let gram;
14606 let gram_count;
14607 for (gram in gram_counts) {
14608 gram_count = gram_counts[gram];
14609 sum_of_square_gram_counts += Math.pow(gram_count, 2);
14610 if (gram in this.match_dict) {
14611 this.match_dict[gram].push([index, gram_count]);
14612 }
14613 else {
14614 this.match_dict[gram] = [[index, gram_count]];
14615 }
14616 }
14617 const vector_normal = Math.sqrt(sum_of_square_gram_counts);
14618 items[index] = [vector_normal, normalized_value];
14619 this.items[gram_size] = items;
14620 this.exact_set[normalized_value] = value;
14621 }
14622 get(value) {
14623 const normalized_value = value.toLowerCase();
14624 const result = this.exact_set[normalized_value];
14625 if (result) {
14626 return [[1, result]];
14627 }
14628 let results = [];
14629 // start with high gram size and if there are no results, go to lower gram sizes
14630 for (let gram_size = GRAM_SIZE_UPPER; gram_size >= GRAM_SIZE_LOWER; --gram_size) {
14631 results = this.__get(value, gram_size);
14632 if (results) {
14633 return results;
14634 }
14635 }
14636 return null;
14637 }
14638 __get(value, gram_size) {
14639 const normalized_value = value.toLowerCase();
14640 const matches = {};
14641 const gram_counts = gram_counter(normalized_value, gram_size);
14642 const items = this.items[gram_size];
14643 let sum_of_square_gram_counts = 0;
14644 let gram;
14645 let gram_count;
14646 let i;
14647 let index;
14648 let other_gram_count;
14649 for (gram in gram_counts) {
14650 gram_count = gram_counts[gram];
14651 sum_of_square_gram_counts += Math.pow(gram_count, 2);
14652 if (gram in this.match_dict) {
14653 for (i = 0; i < this.match_dict[gram].length; ++i) {
14654 index = this.match_dict[gram][i][0];
14655 other_gram_count = this.match_dict[gram][i][1];
14656 if (index in matches) {
14657 matches[index] += gram_count * other_gram_count;
14658 }
14659 else {
14660 matches[index] = gram_count * other_gram_count;
14661 }
14662 }
14663 }
14664 }
14665 const vector_normal = Math.sqrt(sum_of_square_gram_counts);
14666 let results = [];
14667 let match_score;
14668 // build a results list of [score, str]
14669 for (const match_index in matches) {
14670 match_score = matches[match_index];
14671 results.push([
14672 match_score / (vector_normal * items[match_index][0]),
14673 items[match_index][1]
14674 ]);
14675 }
14676 results.sort(sort_descending);
14677 let new_results = [];
14678 const end_index = Math.min(50, results.length);
14679 // truncate somewhat arbitrarily to 50
14680 for (let i = 0; i < end_index; ++i) {
14681 new_results.push([
14682 _distance(results[i][1], normalized_value),
14683 results[i][1]
14684 ]);
14685 }
14686 results = new_results;
14687 results.sort(sort_descending);
14688 new_results = [];
14689 for (let i = 0; i < results.length; ++i) {
14690 if (results[i][0] == results[0][0]) {
14691 new_results.push([results[i][0], this.exact_set[results[i][1]]]);
14692 }
14693 }
14694 return new_results;
14695 }
14696 }
14697
14698 function list$1(items, conjunction = 'or') {
14699 if (items.length === 1)
14700 return items[0];
14701 return `${items.slice(0, -1).join(', ')} ${conjunction} ${items[items.length - 1]}`;
14702 }
14703
14704 // eslint-disable-next-line no-useless-escape
14705 const valid_tag_name = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
14706 const meta_tags = new Map([
14707 ['svelte:head', 'Head'],
14708 ['svelte:options', 'Options'],
14709 ['svelte:window', 'Window'],
14710 ['svelte:body', 'Body']
14711 ]);
14712 const valid_meta_tags = Array.from(meta_tags.keys()).concat('svelte:self', 'svelte:component');
14713 const specials = new Map([
14714 [
14715 'script',
14716 {
14717 read: read_script,
14718 property: 'js'
14719 }
14720 ],
14721 [
14722 'style',
14723 {
14724 read: read_style,
14725 property: 'css'
14726 }
14727 ]
14728 ]);
14729 const SELF = /^svelte:self(?=[\s/>])/;
14730 const COMPONENT = /^svelte:component(?=[\s/>])/;
14731 function parent_is_head(stack) {
14732 let i = stack.length;
14733 while (i--) {
14734 const { type } = stack[i];
14735 if (type === 'Head')
14736 return true;
14737 if (type === 'Element' || type === 'InlineComponent')
14738 return false;
14739 }
14740 return false;
14741 }
14742 function tag(parser) {
14743 const start = parser.index++;
14744 let parent = parser.current();
14745 if (parser.eat('!--')) {
14746 const data = parser.read_until(/-->/);
14747 parser.eat('-->', true, 'comment was left open, expected -->');
14748 parser.current().children.push({
14749 start,
14750 end: parser.index,
14751 type: 'Comment',
14752 data
14753 });
14754 return;
14755 }
14756 const is_closing_tag = parser.eat('/');
14757 const name = read_tag_name(parser);
14758 if (meta_tags.has(name)) {
14759 const slug = meta_tags.get(name).toLowerCase();
14760 if (is_closing_tag) {
14761 if ((name === 'svelte:window' || name === 'svelte:body') &&
14762 parser.current().children.length) {
14763 parser.error({
14764 code: `invalid-${slug}-content`,
14765 message: `<${name}> cannot have children`
14766 }, parser.current().children[0].start);
14767 }
14768 }
14769 else {
14770 if (name in parser.meta_tags) {
14771 parser.error({
14772 code: `duplicate-${slug}`,
14773 message: `A component can only have one <${name}> tag`
14774 }, start);
14775 }
14776 if (parser.stack.length > 1) {
14777 parser.error({
14778 code: `invalid-${slug}-placement`,
14779 message: `<${name}> tags cannot be inside elements or blocks`
14780 }, start);
14781 }
14782 parser.meta_tags[name] = true;
14783 }
14784 }
14785 const type = meta_tags.has(name)
14786 ? meta_tags.get(name)
14787 : (/[A-Z]/.test(name[0]) || name === 'svelte:self' || name === 'svelte:component') ? 'InlineComponent'
14788 : name === 'title' && parent_is_head(parser.stack) ? 'Title'
14789 : name === 'slot' && !parser.customElement ? 'Slot' : 'Element';
14790 const element = {
14791 start,
14792 end: null,
14793 type,
14794 name,
14795 attributes: [],
14796 children: []
14797 };
14798 parser.allow_whitespace();
14799 if (is_closing_tag) {
14800 if (is_void(name)) {
14801 parser.error({
14802 code: 'invalid-void-content',
14803 message: `<${name}> is a void element and cannot have children, or a closing tag`
14804 }, start);
14805 }
14806 parser.eat('>', true);
14807 // close any elements that don't have their own closing tags, e.g. <div><p></div>
14808 while (parent.name !== name) {
14809 if (parent.type !== 'Element') {
14810 const message = parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name
14811 ? `</${name}> attempted to close <${name}> that was already automatically closed by <${parser.last_auto_closed_tag.reason}>`
14812 : `</${name}> attempted to close an element that was not open`;
14813 parser.error({
14814 code: 'invalid-closing-tag',
14815 message
14816 }, start);
14817 }
14818 parent.end = start;
14819 parser.stack.pop();
14820 parent = parser.current();
14821 }
14822 parent.end = parser.index;
14823 parser.stack.pop();
14824 if (parser.last_auto_closed_tag && parser.stack.length < parser.last_auto_closed_tag.depth) {
14825 parser.last_auto_closed_tag = null;
14826 }
14827 return;
14828 }
14829 else if (closing_tag_omitted(parent.name, name)) {
14830 parent.end = start;
14831 parser.stack.pop();
14832 parser.last_auto_closed_tag = {
14833 tag: parent.name,
14834 reason: name,
14835 depth: parser.stack.length
14836 };
14837 }
14838 const unique_names = new Set();
14839 let attribute;
14840 while ((attribute = read_attribute(parser, unique_names))) {
14841 element.attributes.push(attribute);
14842 parser.allow_whitespace();
14843 }
14844 if (name === 'svelte:component') {
14845 const index = element.attributes.findIndex(attr => attr.type === 'Attribute' && attr.name === 'this');
14846 if (!~index) {
14847 parser.error({
14848 code: 'missing-component-definition',
14849 message: "<svelte:component> must have a 'this' attribute"
14850 }, start);
14851 }
14852 const definition = element.attributes.splice(index, 1)[0];
14853 if (definition.value === true || definition.value.length !== 1 || definition.value[0].type === 'Text') {
14854 parser.error({
14855 code: 'invalid-component-definition',
14856 message: 'invalid component definition'
14857 }, definition.start);
14858 }
14859 element.expression = definition.value[0].expression;
14860 }
14861 // special cases – top-level <script> and <style>
14862 if (specials.has(name) && parser.stack.length === 1) {
14863 const special = specials.get(name);
14864 parser.eat('>', true);
14865 const content = special.read(parser, start, element.attributes);
14866 if (content)
14867 parser[special.property].push(content);
14868 return;
14869 }
14870 parser.current().children.push(element);
14871 const self_closing = parser.eat('/') || is_void(name);
14872 parser.eat('>', true);
14873 if (self_closing) {
14874 // don't push self-closing elements onto the stack
14875 element.end = parser.index;
14876 }
14877 else if (name === 'textarea') {
14878 // special case
14879 element.children = read_sequence(parser, () => parser.template.slice(parser.index, parser.index + 11) === '</textarea>');
14880 parser.read(/<\/textarea>/);
14881 element.end = parser.index;
14882 }
14883 else if (name === 'script' || name === 'style') {
14884 // special case
14885 const start = parser.index;
14886 const data = parser.read_until(new RegExp(`</${name}>`));
14887 const end = parser.index;
14888 element.children.push({ start, end, type: 'Text', data });
14889 parser.eat(`</${name}>`, true);
14890 element.end = parser.index;
14891 }
14892 else {
14893 parser.stack.push(element);
14894 }
14895 }
14896 function read_tag_name(parser) {
14897 const start = parser.index;
14898 if (parser.read(SELF)) {
14899 // check we're inside a block, otherwise this
14900 // will cause infinite recursion
14901 let i = parser.stack.length;
14902 let legal = false;
14903 while (i--) {
14904 const fragment = parser.stack[i];
14905 if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock' || fragment.type === 'InlineComponent') {
14906 legal = true;
14907 break;
14908 }
14909 }
14910 if (!legal) {
14911 parser.error({
14912 code: 'invalid-self-placement',
14913 message: '<svelte:self> components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components'
14914 }, start);
14915 }
14916 return 'svelte:self';
14917 }
14918 if (parser.read(COMPONENT))
14919 return 'svelte:component';
14920 const name = parser.read_until(/(\s|\/|>)/);
14921 if (meta_tags.has(name))
14922 return name;
14923 if (name.startsWith('svelte:')) {
14924 const match = fuzzymatch(name.slice(7), valid_meta_tags);
14925 let message = `Valid <svelte:...> tag names are ${list$1(valid_meta_tags)}`;
14926 if (match)
14927 message += ` (did you mean '${match}'?)`;
14928 parser.error({
14929 code: 'invalid-tag-name',
14930 message
14931 }, start);
14932 }
14933 if (!valid_tag_name.test(name)) {
14934 parser.error({
14935 code: 'invalid-tag-name',
14936 message: 'Expected valid tag name'
14937 }, start);
14938 }
14939 return name;
14940 }
14941 function read_attribute(parser, unique_names) {
14942 const start = parser.index;
14943 function check_unique(name) {
14944 if (unique_names.has(name)) {
14945 parser.error({
14946 code: 'duplicate-attribute',
14947 message: 'Attributes need to be unique'
14948 }, start);
14949 }
14950 unique_names.add(name);
14951 }
14952 if (parser.eat('{')) {
14953 parser.allow_whitespace();
14954 if (parser.eat('...')) {
14955 const expression = read_expression(parser);
14956 parser.allow_whitespace();
14957 parser.eat('}', true);
14958 return {
14959 start,
14960 end: parser.index,
14961 type: 'Spread',
14962 expression
14963 };
14964 }
14965 else {
14966 const value_start = parser.index;
14967 const name = parser.read_identifier();
14968 parser.allow_whitespace();
14969 parser.eat('}', true);
14970 check_unique(name);
14971 return {
14972 start,
14973 end: parser.index,
14974 type: 'Attribute',
14975 name,
14976 value: [{
14977 start: value_start,
14978 end: value_start + name.length,
14979 type: 'AttributeShorthand',
14980 expression: {
14981 start: value_start,
14982 end: value_start + name.length,
14983 type: 'Identifier',
14984 name
14985 }
14986 }]
14987 };
14988 }
14989 }
14990 // eslint-disable-next-line no-useless-escape
14991 const name = parser.read_until(/[\s=\/>"']/);
14992 if (!name)
14993 return null;
14994 let end = parser.index;
14995 parser.allow_whitespace();
14996 const colon_index = name.indexOf(':');
14997 const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index));
14998 let value = true;
14999 if (parser.eat('=')) {
15000 parser.allow_whitespace();
15001 value = read_attribute_value(parser);
15002 end = parser.index;
15003 }
15004 else if (parser.match_regex(/["']/)) {
15005 parser.error({
15006 code: 'unexpected-token',
15007 message: 'Expected ='
15008 }, parser.index);
15009 }
15010 if (type) {
15011 const [directive_name, ...modifiers] = name.slice(colon_index + 1).split('|');
15012 if (type === 'Binding' && directive_name !== 'this') {
15013 check_unique(directive_name);
15014 }
15015 else if (type !== 'EventHandler') {
15016 check_unique(name);
15017 }
15018 if (type === 'Ref') {
15019 parser.error({
15020 code: 'invalid-ref-directive',
15021 message: `The ref directive is no longer supported — use \`bind:this={${directive_name}}\` instead`
15022 }, start);
15023 }
15024 if (value[0]) {
15025 if (value.length > 1 || value[0].type === 'Text') {
15026 parser.error({
15027 code: 'invalid-directive-value',
15028 message: 'Directive value must be a JavaScript expression enclosed in curly braces'
15029 }, value[0].start);
15030 }
15031 }
15032 const directive = {
15033 start,
15034 end,
15035 type,
15036 name: directive_name,
15037 modifiers,
15038 expression: (value[0] && value[0].expression) || null
15039 };
15040 if (type === 'Transition') {
15041 const direction = name.slice(0, colon_index);
15042 directive.intro = direction === 'in' || direction === 'transition';
15043 directive.outro = direction === 'out' || direction === 'transition';
15044 }
15045 if (!directive.expression && (type === 'Binding' || type === 'Class')) {
15046 directive.expression = {
15047 start: directive.start + colon_index + 1,
15048 end: directive.end,
15049 type: 'Identifier',
15050 name: directive.name
15051 };
15052 }
15053 return directive;
15054 }
15055 check_unique(name);
15056 return {
15057 start,
15058 end,
15059 type: 'Attribute',
15060 name,
15061 value
15062 };
15063 }
15064 function get_directive_type(name) {
15065 if (name === 'use')
15066 return 'Action';
15067 if (name === 'animate')
15068 return 'Animation';
15069 if (name === 'bind')
15070 return 'Binding';
15071 if (name === 'class')
15072 return 'Class';
15073 if (name === 'on')
15074 return 'EventHandler';
15075 if (name === 'let')
15076 return 'Let';
15077 if (name === 'ref')
15078 return 'Ref';
15079 if (name === 'in' || name === 'out' || name === 'transition')
15080 return 'Transition';
15081 }
15082 function read_attribute_value(parser) {
15083 const quote_mark = parser.eat("'") ? "'" : parser.eat('"') ? '"' : null;
15084 const regex = (quote_mark === "'" ? /'/ :
15085 quote_mark === '"' ? /"/ :
15086 /(\/>|[\s"'=<>`])/);
15087 const value = read_sequence(parser, () => !!parser.match_regex(regex));
15088 if (quote_mark)
15089 parser.index += 1;
15090 return value;
15091 }
15092 function read_sequence(parser, done) {
15093 let current_chunk = {
15094 start: parser.index,
15095 end: null,
15096 type: 'Text',
15097 raw: '',
15098 data: null
15099 };
15100 function flush() {
15101 if (current_chunk.raw) {
15102 current_chunk.data = decode_character_references(current_chunk.raw);
15103 current_chunk.end = parser.index;
15104 chunks.push(current_chunk);
15105 }
15106 }
15107 const chunks = [];
15108 while (parser.index < parser.template.length) {
15109 const index = parser.index;
15110 if (done()) {
15111 flush();
15112 return chunks;
15113 }
15114 else if (parser.eat('{')) {
15115 flush();
15116 parser.allow_whitespace();
15117 const expression = read_expression(parser);
15118 parser.allow_whitespace();
15119 parser.eat('}', true);
15120 chunks.push({
15121 start: index,
15122 end: parser.index,
15123 type: 'MustacheTag',
15124 expression
15125 });
15126 current_chunk = {
15127 start: parser.index,
15128 end: null,
15129 type: 'Text',
15130 raw: '',
15131 data: null
15132 };
15133 }
15134 else {
15135 current_chunk.raw += parser.template[parser.index++];
15136 }
15137 }
15138 parser.error({
15139 code: 'unexpected-eof',
15140 message: 'Unexpected end of input'
15141 });
15142 }
15143
15144 const SQUARE_BRACKET_OPEN = '['.charCodeAt(0);
15145 const SQUARE_BRACKET_CLOSE = ']'.charCodeAt(0);
15146 const CURLY_BRACKET_OPEN = '{'.charCodeAt(0);
15147 const CURLY_BRACKET_CLOSE = '}'.charCodeAt(0);
15148 function is_bracket_open(code) {
15149 return code === SQUARE_BRACKET_OPEN || code === CURLY_BRACKET_OPEN;
15150 }
15151 function is_bracket_close(code) {
15152 return code === SQUARE_BRACKET_CLOSE || code === CURLY_BRACKET_CLOSE;
15153 }
15154 function is_bracket_pair(open, close) {
15155 return ((open === SQUARE_BRACKET_OPEN && close === SQUARE_BRACKET_CLOSE) ||
15156 (open === CURLY_BRACKET_OPEN && close === CURLY_BRACKET_CLOSE));
15157 }
15158 function get_bracket_close(open) {
15159 if (open === SQUARE_BRACKET_OPEN) {
15160 return SQUARE_BRACKET_CLOSE;
15161 }
15162 if (open === CURLY_BRACKET_OPEN) {
15163 return CURLY_BRACKET_CLOSE;
15164 }
15165 }
15166
15167 function read_context(parser) {
15168 const start = parser.index;
15169 let i = parser.index;
15170 const code = full_char_code_at(parser.template, i);
15171 if (isIdentifierStart(code, true)) {
15172 return {
15173 type: 'Identifier',
15174 name: parser.read_identifier(),
15175 start,
15176 end: parser.index
15177 };
15178 }
15179 if (!is_bracket_open(code)) {
15180 parser.error({
15181 code: 'unexpected-token',
15182 message: 'Expected identifier or destructure pattern'
15183 });
15184 }
15185 const bracket_stack = [code];
15186 i += code <= 0xffff ? 1 : 2;
15187 while (i < parser.template.length) {
15188 const code = full_char_code_at(parser.template, i);
15189 if (is_bracket_open(code)) {
15190 bracket_stack.push(code);
15191 }
15192 else if (is_bracket_close(code)) {
15193 if (!is_bracket_pair(bracket_stack[bracket_stack.length - 1], code)) {
15194 parser.error({
15195 code: 'unexpected-token',
15196 message: `Expected ${String.fromCharCode(get_bracket_close(bracket_stack[bracket_stack.length - 1]))}`
15197 });
15198 }
15199 bracket_stack.pop();
15200 if (bracket_stack.length === 0) {
15201 i += code <= 0xffff ? 1 : 2;
15202 break;
15203 }
15204 }
15205 i += code <= 0xffff ? 1 : 2;
15206 }
15207 parser.index = i;
15208 const pattern_string = parser.template.slice(start, i);
15209 try {
15210 // the length of the `space_with_newline` has to be start - 1
15211 // because we added a `(` in front of the pattern_string,
15212 // which shifted the entire string to right by 1
15213 // so we offset it by removing 1 character in the `space_with_newline`
15214 // to achieve that, we remove the 1st space encountered,
15215 // so it will not affect the `column` of the node
15216 let space_with_newline = parser.template.slice(0, start).replace(/[^\n]/g, ' ');
15217 const first_space = space_with_newline.indexOf(' ');
15218 space_with_newline = space_with_newline.slice(0, first_space) + space_with_newline.slice(first_space + 1);
15219 return parse_expression_at(`${space_with_newline}(${pattern_string} = 1)`, start - 1).left;
15220 }
15221 catch (error) {
15222 parser.acorn_error(error);
15223 }
15224 }
15225
15226 function trim_start(str) {
15227 let i = 0;
15228 while (whitespace.test(str[i]))
15229 i += 1;
15230 return str.slice(i);
15231 }
15232 function trim_end(str) {
15233 let i = str.length;
15234 while (whitespace.test(str[i - 1]))
15235 i -= 1;
15236 return str.slice(0, i);
15237 }
15238
15239 function to_string(node) {
15240 switch (node.type) {
15241 case 'IfBlock':
15242 return '{#if} block';
15243 case 'ThenBlock':
15244 return '{:then} block';
15245 case 'ElseBlock':
15246 return '{:else} block';
15247 case 'PendingBlock':
15248 case 'AwaitBlock':
15249 return '{#await} block';
15250 case 'CatchBlock':
15251 return '{:catch} block';
15252 case 'EachBlock':
15253 return '{#each} block';
15254 case 'RawMustacheTag':
15255 return '{@html} block';
15256 case 'DebugTag':
15257 return '{@debug} block';
15258 case 'Element':
15259 case 'InlineComponent':
15260 case 'Slot':
15261 case 'Title':
15262 return `<${node.name}> tag`;
15263 default:
15264 return node.type;
15265 }
15266 }
15267
15268 function trim_whitespace(block, trim_before, trim_after) {
15269 if (!block.children || block.children.length === 0)
15270 return; // AwaitBlock
15271 const first_child = block.children[0];
15272 const last_child = block.children[block.children.length - 1];
15273 if (first_child.type === 'Text' && trim_before) {
15274 first_child.data = trim_start(first_child.data);
15275 if (!first_child.data)
15276 block.children.shift();
15277 }
15278 if (last_child.type === 'Text' && trim_after) {
15279 last_child.data = trim_end(last_child.data);
15280 if (!last_child.data)
15281 block.children.pop();
15282 }
15283 if (block.else) {
15284 trim_whitespace(block.else, trim_before, trim_after);
15285 }
15286 if (first_child.elseif) {
15287 trim_whitespace(first_child, trim_before, trim_after);
15288 }
15289 }
15290 function mustache(parser) {
15291 const start = parser.index;
15292 parser.index += 1;
15293 parser.allow_whitespace();
15294 // {/if}, {/each}, {/await} or {/key}
15295 if (parser.eat('/')) {
15296 let block = parser.current();
15297 let expected;
15298 if (closing_tag_omitted(block.name)) {
15299 block.end = start;
15300 parser.stack.pop();
15301 block = parser.current();
15302 }
15303 if (block.type === 'ElseBlock' || block.type === 'PendingBlock' || block.type === 'ThenBlock' || block.type === 'CatchBlock') {
15304 block.end = start;
15305 parser.stack.pop();
15306 block = parser.current();
15307 expected = 'await';
15308 }
15309 if (block.type === 'IfBlock') {
15310 expected = 'if';
15311 }
15312 else if (block.type === 'EachBlock') {
15313 expected = 'each';
15314 }
15315 else if (block.type === 'AwaitBlock') {
15316 expected = 'await';
15317 }
15318 else if (block.type === 'KeyBlock') {
15319 expected = 'key';
15320 }
15321 else {
15322 parser.error({
15323 code: 'unexpected-block-close',
15324 message: 'Unexpected block closing tag'
15325 });
15326 }
15327 parser.eat(expected, true);
15328 parser.allow_whitespace();
15329 parser.eat('}', true);
15330 while (block.elseif) {
15331 block.end = parser.index;
15332 parser.stack.pop();
15333 block = parser.current();
15334 if (block.else) {
15335 block.else.end = start;
15336 }
15337 }
15338 // strip leading/trailing whitespace as necessary
15339 const char_before = parser.template[block.start - 1];
15340 const char_after = parser.template[parser.index];
15341 const trim_before = !char_before || whitespace.test(char_before);
15342 const trim_after = !char_after || whitespace.test(char_after);
15343 trim_whitespace(block, trim_before, trim_after);
15344 block.end = parser.index;
15345 parser.stack.pop();
15346 }
15347 else if (parser.eat(':else')) {
15348 if (parser.eat('if')) {
15349 parser.error({
15350 code: 'invalid-elseif',
15351 message: "'elseif' should be 'else if'"
15352 });
15353 }
15354 parser.allow_whitespace();
15355 // :else if
15356 if (parser.eat('if')) {
15357 const block = parser.current();
15358 if (block.type !== 'IfBlock') {
15359 parser.error({
15360 code: 'invalid-elseif-placement',
15361 message: parser.stack.some(block => block.type === 'IfBlock')
15362 ? `Expected to close ${to_string(block)} before seeing {:else if ...} block`
15363 : 'Cannot have an {:else if ...} block outside an {#if ...} block'
15364 });
15365 }
15366 parser.require_whitespace();
15367 const expression = read_expression(parser);
15368 parser.allow_whitespace();
15369 parser.eat('}', true);
15370 block.else = {
15371 start: parser.index,
15372 end: null,
15373 type: 'ElseBlock',
15374 children: [
15375 {
15376 start: parser.index,
15377 end: null,
15378 type: 'IfBlock',
15379 elseif: true,
15380 expression,
15381 children: []
15382 }
15383 ]
15384 };
15385 parser.stack.push(block.else.children[0]);
15386 }
15387 else {
15388 // :else
15389 const block = parser.current();
15390 if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
15391 parser.error({
15392 code: 'invalid-else-placement',
15393 message: parser.stack.some(block => block.type === 'IfBlock' || block.type === 'EachBlock')
15394 ? `Expected to close ${to_string(block)} before seeing {:else} block`
15395 : 'Cannot have an {:else} block outside an {#if ...} or {#each ...} block'
15396 });
15397 }
15398 parser.allow_whitespace();
15399 parser.eat('}', true);
15400 block.else = {
15401 start: parser.index,
15402 end: null,
15403 type: 'ElseBlock',
15404 children: []
15405 };
15406 parser.stack.push(block.else);
15407 }
15408 }
15409 else if (parser.match(':then') || parser.match(':catch')) {
15410 const block = parser.current();
15411 const is_then = parser.eat(':then') || !parser.eat(':catch');
15412 if (is_then) {
15413 if (block.type !== 'PendingBlock') {
15414 parser.error({
15415 code: 'invalid-then-placement',
15416 message: parser.stack.some(block => block.type === 'PendingBlock')
15417 ? `Expected to close ${to_string(block)} before seeing {:then} block`
15418 : 'Cannot have an {:then} block outside an {#await ...} block'
15419 });
15420 }
15421 }
15422 else {
15423 if (block.type !== 'ThenBlock' && block.type !== 'PendingBlock') {
15424 parser.error({
15425 code: 'invalid-catch-placement',
15426 message: parser.stack.some(block => block.type === 'ThenBlock' || block.type === 'PendingBlock')
15427 ? `Expected to close ${to_string(block)} before seeing {:catch} block`
15428 : 'Cannot have an {:catch} block outside an {#await ...} block'
15429 });
15430 }
15431 }
15432 block.end = start;
15433 parser.stack.pop();
15434 const await_block = parser.current();
15435 if (!parser.eat('}')) {
15436 parser.require_whitespace();
15437 await_block[is_then ? 'value' : 'error'] = read_context(parser);
15438 parser.allow_whitespace();
15439 parser.eat('}', true);
15440 }
15441 const new_block = {
15442 start,
15443 end: null,
15444 type: is_then ? 'ThenBlock' : 'CatchBlock',
15445 children: [],
15446 skip: false
15447 };
15448 await_block[is_then ? 'then' : 'catch'] = new_block;
15449 parser.stack.push(new_block);
15450 }
15451 else if (parser.eat('#')) {
15452 // {#if foo}, {#each foo} or {#await foo}
15453 let type;
15454 if (parser.eat('if')) {
15455 type = 'IfBlock';
15456 }
15457 else if (parser.eat('each')) {
15458 type = 'EachBlock';
15459 }
15460 else if (parser.eat('await')) {
15461 type = 'AwaitBlock';
15462 }
15463 else if (parser.eat('key')) {
15464 type = 'KeyBlock';
15465 }
15466 else {
15467 parser.error({
15468 code: 'expected-block-type',
15469 message: 'Expected if, each, await or key'
15470 });
15471 }
15472 parser.require_whitespace();
15473 const expression = read_expression(parser);
15474 const block = type === 'AwaitBlock' ?
15475 {
15476 start,
15477 end: null,
15478 type,
15479 expression,
15480 value: null,
15481 error: null,
15482 pending: {
15483 start: null,
15484 end: null,
15485 type: 'PendingBlock',
15486 children: [],
15487 skip: true
15488 },
15489 then: {
15490 start: null,
15491 end: null,
15492 type: 'ThenBlock',
15493 children: [],
15494 skip: true
15495 },
15496 catch: {
15497 start: null,
15498 end: null,
15499 type: 'CatchBlock',
15500 children: [],
15501 skip: true
15502 }
15503 } :
15504 {
15505 start,
15506 end: null,
15507 type,
15508 expression,
15509 children: []
15510 };
15511 parser.allow_whitespace();
15512 // {#each} blocks must declare a context – {#each list as item}
15513 if (type === 'EachBlock') {
15514 parser.eat('as', true);
15515 parser.require_whitespace();
15516 block.context = read_context(parser);
15517 parser.allow_whitespace();
15518 if (parser.eat(',')) {
15519 parser.allow_whitespace();
15520 block.index = parser.read_identifier();
15521 if (!block.index) {
15522 parser.error({
15523 code: 'expected-name',
15524 message: 'Expected name'
15525 });
15526 }
15527 parser.allow_whitespace();
15528 }
15529 if (parser.eat('(')) {
15530 parser.allow_whitespace();
15531 block.key = read_expression(parser);
15532 parser.allow_whitespace();
15533 parser.eat(')', true);
15534 parser.allow_whitespace();
15535 }
15536 }
15537 const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then');
15538 if (await_block_shorthand) {
15539 parser.require_whitespace();
15540 block.value = read_context(parser);
15541 parser.allow_whitespace();
15542 }
15543 const await_block_catch_shorthand = !await_block_shorthand && type === 'AwaitBlock' && parser.eat('catch');
15544 if (await_block_catch_shorthand) {
15545 parser.require_whitespace();
15546 block.error = read_context(parser);
15547 parser.allow_whitespace();
15548 }
15549 parser.eat('}', true);
15550 parser.current().children.push(block);
15551 parser.stack.push(block);
15552 if (type === 'AwaitBlock') {
15553 let child_block;
15554 if (await_block_shorthand) {
15555 block.then.skip = false;
15556 child_block = block.then;
15557 }
15558 else if (await_block_catch_shorthand) {
15559 block.catch.skip = false;
15560 child_block = block.catch;
15561 }
15562 else {
15563 block.pending.skip = false;
15564 child_block = block.pending;
15565 }
15566 child_block.start = parser.index;
15567 parser.stack.push(child_block);
15568 }
15569 }
15570 else if (parser.eat('@html')) {
15571 // {@html content} tag
15572 parser.require_whitespace();
15573 const expression = read_expression(parser);
15574 parser.allow_whitespace();
15575 parser.eat('}', true);
15576 parser.current().children.push({
15577 start,
15578 end: parser.index,
15579 type: 'RawMustacheTag',
15580 expression
15581 });
15582 }
15583 else if (parser.eat('@debug')) {
15584 let identifiers;
15585 // Implies {@debug} which indicates "debug all"
15586 if (parser.read(/\s*}/)) {
15587 identifiers = [];
15588 }
15589 else {
15590 const expression = read_expression(parser);
15591 identifiers = expression.type === 'SequenceExpression'
15592 ? expression.expressions
15593 : [expression];
15594 identifiers.forEach(node => {
15595 if (node.type !== 'Identifier') {
15596 parser.error({
15597 code: 'invalid-debug-args',
15598 message: '{@debug ...} arguments must be identifiers, not arbitrary expressions'
15599 }, node.start);
15600 }
15601 });
15602 parser.allow_whitespace();
15603 parser.eat('}', true);
15604 }
15605 parser.current().children.push({
15606 start,
15607 end: parser.index,
15608 type: 'DebugTag',
15609 identifiers
15610 });
15611 }
15612 else {
15613 const expression = read_expression(parser);
15614 parser.allow_whitespace();
15615 parser.eat('}', true);
15616 parser.current().children.push({
15617 start,
15618 end: parser.index,
15619 type: 'MustacheTag',
15620 expression
15621 });
15622 }
15623 }
15624
15625 function text(parser) {
15626 const start = parser.index;
15627 let data = '';
15628 while (parser.index < parser.template.length &&
15629 !parser.match('<') &&
15630 !parser.match('{')) {
15631 data += parser.template[parser.index++];
15632 }
15633 const node = {
15634 start,
15635 end: parser.index,
15636 type: 'Text',
15637 raw: data,
15638 data: decode_character_references(data)
15639 };
15640 parser.current().children.push(node);
15641 }
15642
15643 function fragment(parser) {
15644 if (parser.match('<')) {
15645 return tag;
15646 }
15647 if (parser.match('{')) {
15648 return mustache;
15649 }
15650 return text;
15651 }
15652
15653 function getLocator(source, options) {
15654 if (options === void 0) { options = {}; }
15655 var offsetLine = options.offsetLine || 0;
15656 var offsetColumn = options.offsetColumn || 0;
15657 var originalLines = source.split('\n');
15658 var start = 0;
15659 var lineRanges = originalLines.map(function (line, i) {
15660 var end = start + line.length + 1;
15661 var range = { start: start, end: end, line: i };
15662 start = end;
15663 return range;
15664 });
15665 var i = 0;
15666 function rangeContains(range, index) {
15667 return range.start <= index && index < range.end;
15668 }
15669 function getLocation(range, index) {
15670 return { line: offsetLine + range.line, column: offsetColumn + index - range.start, character: index };
15671 }
15672 function locate(search, startIndex) {
15673 if (typeof search === 'string') {
15674 search = source.indexOf(search, startIndex || 0);
15675 }
15676 var range = lineRanges[i];
15677 var d = search >= range.end ? 1 : -1;
15678 while (range) {
15679 if (rangeContains(range, search))
15680 return getLocation(range, search);
15681 i += d;
15682 range = lineRanges[i];
15683 }
15684 }
15685 return locate;
15686 }
15687 function locate(source, search, options) {
15688 if (typeof options === 'number') {
15689 throw new Error('locate takes a { startIndex, offsetLine, offsetColumn } object as the third argument');
15690 }
15691 return getLocator(source, options)(search, options && options.startIndex);
15692 }
15693
15694 function tabs_to_spaces(str) {
15695 return str.replace(/^\t+/, match => match.split('\t').join(' '));
15696 }
15697 function get_code_frame(source, line, column) {
15698 const lines = source.split('\n');
15699 const frame_start = Math.max(0, line - 2);
15700 const frame_end = Math.min(line + 3, lines.length);
15701 const digits = String(frame_end + 1).length;
15702 return lines
15703 .slice(frame_start, frame_end)
15704 .map((str, i) => {
15705 const isErrorLine = frame_start + i === line;
15706 const line_num = String(i + frame_start + 1).padStart(digits, ' ');
15707 if (isErrorLine) {
15708 const indicator = ' '.repeat(digits + 2 + tabs_to_spaces(str.slice(0, column)).length) + '^';
15709 return `${line_num}: ${tabs_to_spaces(str)}\n${indicator}`;
15710 }
15711 return `${line_num}: ${tabs_to_spaces(str)}`;
15712 })
15713 .join('\n');
15714 }
15715
15716 class CompileError extends Error {
15717 toString() {
15718 return `${this.message} (${this.start.line}:${this.start.column})\n${this.frame}`;
15719 }
15720 }
15721 function error$1(message, props) {
15722 const error = new CompileError(message);
15723 error.name = props.name;
15724 const start = locate(props.source, props.start, { offsetLine: 1 });
15725 const end = locate(props.source, props.end || props.start, { offsetLine: 1 });
15726 error.code = props.code;
15727 error.start = start;
15728 error.end = end;
15729 error.pos = props.start;
15730 error.filename = props.filename;
15731 error.frame = get_code_frame(props.source, start.line - 1, start.column);
15732 throw error;
15733 }
15734
15735 class Parser$1 {
15736 constructor(template, options) {
15737 this.index = 0;
15738 this.stack = [];
15739 this.css = [];
15740 this.js = [];
15741 this.meta_tags = {};
15742 if (typeof template !== 'string') {
15743 throw new TypeError('Template must be a string');
15744 }
15745 this.template = template.replace(/\s+$/, '');
15746 this.filename = options.filename;
15747 this.customElement = options.customElement;
15748 this.html = {
15749 start: null,
15750 end: null,
15751 type: 'Fragment',
15752 children: []
15753 };
15754 this.stack.push(this.html);
15755 let state = fragment;
15756 while (this.index < this.template.length) {
15757 state = state(this) || fragment;
15758 }
15759 if (this.stack.length > 1) {
15760 const current = this.current();
15761 const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
15762 const slug = current.type === 'Element' ? 'element' : 'block';
15763 this.error({
15764 code: `unclosed-${slug}`,
15765 message: `${type} was left open`
15766 }, current.start);
15767 }
15768 if (state !== fragment) {
15769 this.error({
15770 code: 'unexpected-eof',
15771 message: 'Unexpected end of input'
15772 });
15773 }
15774 if (this.html.children.length) {
15775 let start = this.html.children[0].start;
15776 while (whitespace.test(template[start]))
15777 start += 1;
15778 let end = this.html.children[this.html.children.length - 1].end;
15779 while (whitespace.test(template[end - 1]))
15780 end -= 1;
15781 this.html.start = start;
15782 this.html.end = end;
15783 }
15784 else {
15785 this.html.start = this.html.end = null;
15786 }
15787 }
15788 current() {
15789 return this.stack[this.stack.length - 1];
15790 }
15791 acorn_error(err) {
15792 this.error({
15793 code: 'parse-error',
15794 message: err.message.replace(/ \(\d+:\d+\)$/, '')
15795 }, err.pos);
15796 }
15797 error({ code, message }, index = this.index) {
15798 error$1(message, {
15799 name: 'ParseError',
15800 code,
15801 source: this.template,
15802 start: index,
15803 filename: this.filename
15804 });
15805 }
15806 eat(str, required, message) {
15807 if (this.match(str)) {
15808 this.index += str.length;
15809 return true;
15810 }
15811 if (required) {
15812 this.error({
15813 code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`,
15814 message: message || `Expected ${str}`
15815 });
15816 }
15817 return false;
15818 }
15819 match(str) {
15820 return this.template.slice(this.index, this.index + str.length) === str;
15821 }
15822 match_regex(pattern) {
15823 const match = pattern.exec(this.template.slice(this.index));
15824 if (!match || match.index !== 0)
15825 return null;
15826 return match[0];
15827 }
15828 allow_whitespace() {
15829 while (this.index < this.template.length &&
15830 whitespace.test(this.template[this.index])) {
15831 this.index++;
15832 }
15833 }
15834 read(pattern) {
15835 const result = this.match_regex(pattern);
15836 if (result)
15837 this.index += result.length;
15838 return result;
15839 }
15840 read_identifier(allow_reserved = false) {
15841 const start = this.index;
15842 let i = this.index;
15843 const code = full_char_code_at(this.template, i);
15844 if (!isIdentifierStart(code, true))
15845 return null;
15846 i += code <= 0xffff ? 1 : 2;
15847 while (i < this.template.length) {
15848 const code = full_char_code_at(this.template, i);
15849 if (!isIdentifierChar(code, true))
15850 break;
15851 i += code <= 0xffff ? 1 : 2;
15852 }
15853 const identifier = this.template.slice(this.index, this.index = i);
15854 if (!allow_reserved && reserved.has(identifier)) {
15855 this.error({
15856 code: 'unexpected-reserved-word',
15857 message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`
15858 }, start);
15859 }
15860 return identifier;
15861 }
15862 read_until(pattern) {
15863 if (this.index >= this.template.length) {
15864 this.error({
15865 code: 'unexpected-eof',
15866 message: 'Unexpected end of input'
15867 });
15868 }
15869 const start = this.index;
15870 const match = pattern.exec(this.template.slice(start));
15871 if (match) {
15872 this.index = start + match.index;
15873 return this.template.slice(start, this.index);
15874 }
15875 this.index = this.template.length;
15876 return this.template.slice(start);
15877 }
15878 require_whitespace() {
15879 if (!whitespace.test(this.template[this.index])) {
15880 this.error({
15881 code: 'missing-whitespace',
15882 message: 'Expected whitespace'
15883 });
15884 }
15885 this.allow_whitespace();
15886 }
15887 }
15888 function parse$3(template, options = {}) {
15889 const parser = new Parser$1(template, options);
15890 // TODO we may want to allow multiple <style> tags —
15891 // one scoped, one global. for now, only allow one
15892 if (parser.css.length > 1) {
15893 parser.error({
15894 code: 'duplicate-style',
15895 message: 'You can only have one top-level <style> tag per component'
15896 }, parser.css[1].start);
15897 }
15898 const instance_scripts = parser.js.filter(script => script.context === 'default');
15899 const module_scripts = parser.js.filter(script => script.context === 'module');
15900 if (instance_scripts.length > 1) {
15901 parser.error({
15902 code: 'invalid-script',
15903 message: 'A component can only have one instance-level <script> element'
15904 }, instance_scripts[1].start);
15905 }
15906 if (module_scripts.length > 1) {
15907 parser.error({
15908 code: 'invalid-script',
15909 message: 'A component can only have one <script context="module"> element'
15910 }, module_scripts[1].start);
15911 }
15912 return {
15913 html: parser.html,
15914 css: parser.css[0],
15915 instance: instance_scripts[0],
15916 module: module_scripts[0]
15917 };
15918 }
15919
15920 function is_head(node) {
15921 return node && node.type === 'MemberExpression' && node.object.name === '@_document' && node.property.name === 'head';
15922 }
15923
15924 class Block$1 {
15925 constructor(options) {
15926 this.dependencies = new Set();
15927 this.binding_group_initialised = new Set();
15928 this.event_listeners = [];
15929 this.variables = new Map();
15930 this.has_update_method = false;
15931 this.parent = options.parent;
15932 this.renderer = options.renderer;
15933 this.name = options.name;
15934 this.type = options.type;
15935 this.comment = options.comment;
15936 this.wrappers = [];
15937 // for keyed each blocks
15938 this.key = options.key;
15939 this.first = null;
15940 this.bindings = options.bindings;
15941 this.chunks = {
15942 declarations: [],
15943 init: [],
15944 create: [],
15945 claim: [],
15946 hydrate: [],
15947 mount: [],
15948 measure: [],
15949 fix: [],
15950 animate: [],
15951 intro: [],
15952 update: [],
15953 outro: [],
15954 destroy: []
15955 };
15956 this.has_animation = false;
15957 this.has_intro_method = false; // a block could have an intro method but not intro transitions, e.g. if a sibling block has intros
15958 this.has_outro_method = false;
15959 this.outros = 0;
15960 this.get_unique_name = this.renderer.component.get_unique_name_maker();
15961 this.aliases = new Map();
15962 if (this.key)
15963 this.aliases.set('key', this.get_unique_name('key'));
15964 }
15965 assign_variable_names() {
15966 const seen = new Set();
15967 const dupes = new Set();
15968 let i = this.wrappers.length;
15969 while (i--) {
15970 const wrapper = this.wrappers[i];
15971 if (!wrapper.var)
15972 continue;
15973 if (seen.has(wrapper.var.name)) {
15974 dupes.add(wrapper.var.name);
15975 }
15976 seen.add(wrapper.var.name);
15977 }
15978 const counts = new Map();
15979 i = this.wrappers.length;
15980 while (i--) {
15981 const wrapper = this.wrappers[i];
15982 if (!wrapper.var)
15983 continue;
15984 let suffix = '';
15985 if (dupes.has(wrapper.var.name)) {
15986 const i = counts.get(wrapper.var.name) || 0;
15987 counts.set(wrapper.var.name, i + 1);
15988 suffix = i;
15989 }
15990 wrapper.var.name = this.get_unique_name(wrapper.var.name + suffix).name;
15991 }
15992 }
15993 add_dependencies(dependencies) {
15994 dependencies.forEach(dependency => {
15995 this.dependencies.add(dependency);
15996 });
15997 this.has_update_method = true;
15998 if (this.parent) {
15999 this.parent.add_dependencies(dependencies);
16000 }
16001 }
16002 add_element(id, render_statement, claim_statement, parent_node, no_detach) {
16003 this.add_variable(id);
16004 this.chunks.create.push(b `${id} = ${render_statement};`);
16005 if (this.renderer.options.hydratable) {
16006 this.chunks.claim.push(b `${id} = ${claim_statement || render_statement};`);
16007 }
16008 if (parent_node) {
16009 this.chunks.mount.push(b `@append(${parent_node}, ${id});`);
16010 if (is_head(parent_node) && !no_detach)
16011 this.chunks.destroy.push(b `@detach(${id});`);
16012 }
16013 else {
16014 this.chunks.mount.push(b `@insert(#target, ${id}, #anchor);`);
16015 if (!no_detach)
16016 this.chunks.destroy.push(b `if (detaching) @detach(${id});`);
16017 }
16018 }
16019 add_intro(local) {
16020 this.has_intros = this.has_intro_method = true;
16021 if (!local && this.parent)
16022 this.parent.add_intro();
16023 }
16024 add_outro(local) {
16025 this.has_outros = this.has_outro_method = true;
16026 this.outros += 1;
16027 if (!local && this.parent)
16028 this.parent.add_outro();
16029 }
16030 add_animation() {
16031 this.has_animation = true;
16032 }
16033 add_variable(id, init) {
16034 if (this.variables.has(id.name)) {
16035 throw new Error(`Variable '${id.name}' already initialised with a different value`);
16036 }
16037 this.variables.set(id.name, { id, init });
16038 }
16039 alias(name) {
16040 if (!this.aliases.has(name)) {
16041 this.aliases.set(name, this.get_unique_name(name));
16042 }
16043 return this.aliases.get(name);
16044 }
16045 child(options) {
16046 return new Block$1(Object.assign({}, this, { key: null }, options, { parent: this }));
16047 }
16048 get_contents(key) {
16049 const { dev } = this.renderer.options;
16050 if (this.has_outros) {
16051 this.add_variable({ type: 'Identifier', name: '#current' });
16052 if (this.chunks.intro.length > 0) {
16053 this.chunks.intro.push(b `#current = true;`);
16054 this.chunks.mount.push(b `#current = true;`);
16055 }
16056 if (this.chunks.outro.length > 0) {
16057 this.chunks.outro.push(b `#current = false;`);
16058 }
16059 }
16060 if (this.autofocus) {
16061 this.chunks.mount.push(b `${this.autofocus}.focus();`);
16062 }
16063 this.render_listeners();
16064 const properties = {};
16065 const noop = x `@noop`;
16066 properties.key = key;
16067 if (this.first) {
16068 properties.first = x `null`;
16069 this.chunks.hydrate.push(b `this.first = ${this.first};`);
16070 }
16071 if (this.chunks.create.length === 0 && this.chunks.hydrate.length === 0) {
16072 properties.create = noop;
16073 }
16074 else {
16075 const hydrate = this.chunks.hydrate.length > 0 && (this.renderer.options.hydratable
16076 ? b `this.h();`
16077 : this.chunks.hydrate);
16078 properties.create = x `function #create() {
16079 ${this.chunks.create}
16080 ${hydrate}
16081 }`;
16082 }
16083 if (this.renderer.options.hydratable || this.chunks.claim.length > 0) {
16084 if (this.chunks.claim.length === 0 && this.chunks.hydrate.length === 0) {
16085 properties.claim = noop;
16086 }
16087 else {
16088 properties.claim = x `function #claim(#nodes) {
16089 ${this.chunks.claim}
16090 ${this.renderer.options.hydratable && this.chunks.hydrate.length > 0 && b `this.h();`}
16091 }`;
16092 }
16093 }
16094 if (this.renderer.options.hydratable && this.chunks.hydrate.length > 0) {
16095 properties.hydrate = x `function #hydrate() {
16096 ${this.chunks.hydrate}
16097 }`;
16098 }
16099 if (this.chunks.mount.length === 0) {
16100 properties.mount = noop;
16101 }
16102 else if (this.event_listeners.length === 0) {
16103 properties.mount = x `function #mount(#target, #anchor) {
16104 ${this.chunks.mount}
16105 }`;
16106 }
16107 else {
16108 properties.mount = x `function #mount(#target, #anchor) {
16109 ${this.chunks.mount}
16110 }`;
16111 }
16112 if (this.has_update_method || this.maintain_context) {
16113 if (this.chunks.update.length === 0 && !this.maintain_context) {
16114 properties.update = noop;
16115 }
16116 else {
16117 const ctx = this.maintain_context ? x `#new_ctx` : x `#ctx`;
16118 let dirty = { type: 'Identifier', name: '#dirty' };
16119 if (!this.renderer.context_overflow && !this.parent) {
16120 dirty = { type: 'ArrayPattern', elements: [dirty] };
16121 }
16122 properties.update = x `function #update(${ctx}, ${dirty}) {
16123 ${this.maintain_context && b `#ctx = ${ctx};`}
16124 ${this.chunks.update}
16125 }`;
16126 }
16127 }
16128 if (this.has_animation) {
16129 properties.measure = x `function #measure() {
16130 ${this.chunks.measure}
16131 }`;
16132 properties.fix = x `function #fix() {
16133 ${this.chunks.fix}
16134 }`;
16135 properties.animate = x `function #animate() {
16136 ${this.chunks.animate}
16137 }`;
16138 }
16139 if (this.has_intro_method || this.has_outro_method) {
16140 if (this.chunks.intro.length === 0) {
16141 properties.intro = noop;
16142 }
16143 else {
16144 properties.intro = x `function #intro(#local) {
16145 ${this.has_outros && b `if (#current) return;`}
16146 ${this.chunks.intro}
16147 }`;
16148 }
16149 if (this.chunks.outro.length === 0) {
16150 properties.outro = noop;
16151 }
16152 else {
16153 properties.outro = x `function #outro(#local) {
16154 ${this.chunks.outro}
16155 }`;
16156 }
16157 }
16158 if (this.chunks.destroy.length === 0) {
16159 properties.destroy = noop;
16160 }
16161 else {
16162 properties.destroy = x `function #destroy(detaching) {
16163 ${this.chunks.destroy}
16164 }`;
16165 }
16166 if (!this.renderer.component.compile_options.dev) {
16167 // allow shorthand names
16168 for (const name in properties) {
16169 const property = properties[name];
16170 if (property)
16171 property.id = null;
16172 }
16173 }
16174 const return_value = x `{
16175 key: ${properties.key},
16176 first: ${properties.first},
16177 c: ${properties.create},
16178 l: ${properties.claim},
16179 h: ${properties.hydrate},
16180 m: ${properties.mount},
16181 p: ${properties.update},
16182 r: ${properties.measure},
16183 f: ${properties.fix},
16184 a: ${properties.animate},
16185 i: ${properties.intro},
16186 o: ${properties.outro},
16187 d: ${properties.destroy}
16188 }`;
16189 const block = dev && this.get_unique_name('block');
16190 const body = b `
16191 ${this.chunks.declarations}
16192
16193 ${Array.from(this.variables.values()).map(({ id, init }) => {
16194 return init
16195 ? b `let ${id} = ${init}`
16196 : b `let ${id}`;
16197 })}
16198
16199 ${this.chunks.init}
16200
16201 ${dev
16202 ? b `
16203 const ${block} = ${return_value};
16204 @dispatch_dev("SvelteRegisterBlock", {
16205 block: ${block},
16206 id: ${this.name || 'create_fragment'}.name,
16207 type: "${this.type}",
16208 source: "${this.comment ? this.comment.replace(/"/g, '\\"') : ''}",
16209 ctx: #ctx
16210 });
16211 return ${block};`
16212 : b `
16213 return ${return_value};`}
16214 `;
16215 return body;
16216 }
16217 has_content() {
16218 return !!this.first ||
16219 this.event_listeners.length > 0 ||
16220 this.chunks.intro.length > 0 ||
16221 this.chunks.outro.length > 0 ||
16222 this.chunks.create.length > 0 ||
16223 this.chunks.hydrate.length > 0 ||
16224 this.chunks.claim.length > 0 ||
16225 this.chunks.mount.length > 0 ||
16226 this.chunks.update.length > 0 ||
16227 this.chunks.destroy.length > 0 ||
16228 this.has_animation;
16229 }
16230 render() {
16231 const key = this.key && this.get_unique_name('key');
16232 const args = [x `#ctx`];
16233 if (key)
16234 args.unshift(key);
16235 const fn = b `function ${this.name}(${args}) {
16236 ${this.get_contents(key)}
16237 }`;
16238 return this.comment
16239 ? b `
16240 // ${this.comment}
16241 ${fn}`
16242 : fn;
16243 }
16244 render_listeners(chunk = '') {
16245 if (this.event_listeners.length > 0) {
16246 this.add_variable({ type: 'Identifier', name: '#mounted' });
16247 this.chunks.destroy.push(b `#mounted = false`);
16248 const dispose = {
16249 type: 'Identifier',
16250 name: `#dispose${chunk}`
16251 };
16252 this.add_variable(dispose);
16253 if (this.event_listeners.length === 1) {
16254 this.chunks.mount.push(b `
16255 if (!#mounted) {
16256 ${dispose} = ${this.event_listeners[0]};
16257 #mounted = true;
16258 }
16259 `);
16260 this.chunks.destroy.push(b `${dispose}();`);
16261 }
16262 else {
16263 this.chunks.mount.push(b `
16264 if (!#mounted) {
16265 ${dispose} = [
16266 ${this.event_listeners}
16267 ];
16268 #mounted = true;
16269 }
16270 `);
16271 this.chunks.destroy.push(b `@run_all(${dispose});`);
16272 }
16273 }
16274 }
16275 }
16276
16277 class Wrapper {
16278 constructor(renderer, block, parent, node) {
16279 this.node = node;
16280 // make these non-enumerable so that they can be logged sensibly
16281 // (TODO in dev only?)
16282 Object.defineProperties(this, {
16283 renderer: {
16284 value: renderer
16285 },
16286 parent: {
16287 value: parent
16288 }
16289 });
16290 this.can_use_innerhtml = !renderer.options.hydratable;
16291 this.is_static_content = !renderer.options.hydratable;
16292 block.wrappers.push(this);
16293 }
16294 cannot_use_innerhtml() {
16295 this.can_use_innerhtml = false;
16296 if (this.parent)
16297 this.parent.cannot_use_innerhtml();
16298 }
16299 not_static_content() {
16300 this.is_static_content = false;
16301 if (this.parent)
16302 this.parent.not_static_content();
16303 }
16304 get_or_create_anchor(block, parent_node, parent_nodes) {
16305 // TODO use this in EachBlock and IfBlock — tricky because
16306 // children need to be created first
16307 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
16308 const anchor = needs_anchor
16309 ? block.get_unique_name(`${this.var.name}_anchor`)
16310 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16311 if (needs_anchor) {
16312 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16313 }
16314 return anchor;
16315 }
16316 get_update_mount_node(anchor) {
16317 return ((this.parent && this.parent.is_dom_node())
16318 ? this.parent.var
16319 : x `${anchor}.parentNode`);
16320 }
16321 is_dom_node() {
16322 return (this.node.type === 'Element' ||
16323 this.node.type === 'Text' ||
16324 this.node.type === 'MustacheTag');
16325 }
16326 render(_block, _parent_node, _parent_nodes) {
16327 throw Error('Wrapper class is not renderable');
16328 }
16329 }
16330
16331 function create_debugging_comment(node, component) {
16332 const { locate, source } = component;
16333 let c = node.start;
16334 if (node.type === 'ElseBlock') {
16335 while (source[c - 1] !== '{')
16336 c -= 1;
16337 while (source[c - 1] === '{')
16338 c -= 1;
16339 }
16340 let d;
16341 if (node.type === 'InlineComponent' || node.type === 'Element') {
16342 if (node.children.length) {
16343 d = node.children[0].start;
16344 while (source[d - 1] !== '>')
16345 d -= 1;
16346 }
16347 else {
16348 d = node.start;
16349 while (source[d] !== '>')
16350 d += 1;
16351 d += 1;
16352 }
16353 }
16354 else if (node.type === 'Text' || node.type === 'Comment') {
16355 d = node.end;
16356 }
16357 else {
16358 // @ts-ignore
16359 d = node.expression ? node.expression.node.end : c;
16360 while (source[d] !== '}' && d <= source.length)
16361 d += 1;
16362 while (source[d] === '}')
16363 d += 1;
16364 }
16365 const start = locate(c);
16366 const loc = `(${start.line}:${start.column})`;
16367 return `${loc} ${source.slice(c, d)}`.replace(/\s/g, ' ');
16368 }
16369
16370 class AwaitBlockBranch extends Wrapper {
16371 constructor(status, renderer, block, parent, node, strip_whitespace, next_sibling) {
16372 super(renderer, block, parent, node);
16373 this.var = null;
16374 this.status = status;
16375 this.block = block.child({
16376 comment: create_debugging_comment(node, this.renderer.component),
16377 name: this.renderer.component.get_unique_name(`create_${status}_block`),
16378 type: status
16379 });
16380 this.add_context(parent.node[status + '_node'], parent.node[status + '_contexts']);
16381 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16382 this.is_dynamic = this.block.dependencies.size > 0;
16383 }
16384 add_context(node, contexts) {
16385 if (!node)
16386 return;
16387 if (node.type === 'Identifier') {
16388 this.value = node.name;
16389 this.renderer.add_to_context(this.value, true);
16390 }
16391 else {
16392 contexts.forEach(context => {
16393 this.renderer.add_to_context(context.key.name, true);
16394 });
16395 this.value = this.block.parent.get_unique_name('value').name;
16396 this.value_contexts = contexts;
16397 this.renderer.add_to_context(this.value, true);
16398 this.is_destructured = true;
16399 }
16400 this.value_index = this.renderer.context_lookup.get(this.value).index;
16401 }
16402 render(block, parent_node, parent_nodes) {
16403 this.fragment.render(block, parent_node, parent_nodes);
16404 if (this.is_destructured) {
16405 this.render_destructure();
16406 }
16407 }
16408 render_destructure() {
16409 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}]`)};`);
16410 const get_context = this.block.renderer.component.get_unique_name(`get_${this.status}_context`);
16411 this.block.renderer.blocks.push(b `
16412 function ${get_context}(#ctx) {
16413 ${props}
16414 }
16415 `);
16416 this.block.chunks.declarations.push(b `${get_context}(#ctx)`);
16417 if (this.block.has_update_method) {
16418 this.block.chunks.update.unshift(b `${get_context}(#ctx)`);
16419 }
16420 }
16421 }
16422 class AwaitBlockWrapper extends Wrapper {
16423 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16424 super(renderer, block, parent, node);
16425 this.var = { type: 'Identifier', name: 'await_block' };
16426 this.cannot_use_innerhtml();
16427 this.not_static_content();
16428 block.add_dependencies(this.node.expression.dependencies);
16429 let is_dynamic = false;
16430 let has_intros = false;
16431 let has_outros = false;
16432 ['pending', 'then', 'catch'].forEach((status) => {
16433 const child = this.node[status];
16434 const branch = new AwaitBlockBranch(status, renderer, block, this, child, strip_whitespace, next_sibling);
16435 renderer.blocks.push(branch.block);
16436 if (branch.is_dynamic) {
16437 is_dynamic = true;
16438 // TODO should blocks update their own parents?
16439 block.add_dependencies(branch.block.dependencies);
16440 }
16441 if (branch.block.has_intros)
16442 has_intros = true;
16443 if (branch.block.has_outros)
16444 has_outros = true;
16445 this[status] = branch;
16446 });
16447 ['pending', 'then', 'catch'].forEach(status => {
16448 this[status].block.has_update_method = is_dynamic;
16449 this[status].block.has_intro_method = has_intros;
16450 this[status].block.has_outro_method = has_outros;
16451 });
16452 if (has_outros) {
16453 block.add_outro();
16454 }
16455 }
16456 render(block, parent_node, parent_nodes) {
16457 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
16458 const update_mount_node = this.get_update_mount_node(anchor);
16459 const snippet = this.node.expression.manipulate(block);
16460 const info = block.get_unique_name('info');
16461 const promise = block.get_unique_name('promise');
16462 block.add_variable(promise);
16463 block.maintain_context = true;
16464 const info_props = x `{
16465 ctx: #ctx,
16466 current: null,
16467 token: null,
16468 hasCatch: ${this.catch.node.start !== null ? 'true' : 'false'},
16469 pending: ${this.pending.block.name},
16470 then: ${this.then.block.name},
16471 catch: ${this.catch.block.name},
16472 value: ${this.then.value_index},
16473 error: ${this.catch.value_index},
16474 blocks: ${this.pending.block.has_outro_method && x `[,,,]`}
16475 }`;
16476 block.chunks.init.push(b `
16477 let ${info} = ${info_props};
16478 `);
16479 block.chunks.init.push(b `
16480 @handle_promise(${promise} = ${snippet}, ${info});
16481 `);
16482 block.chunks.create.push(b `
16483 ${info}.block.c();
16484 `);
16485 if (parent_nodes && this.renderer.options.hydratable) {
16486 block.chunks.claim.push(b `
16487 ${info}.block.l(${parent_nodes});
16488 `);
16489 }
16490 const initial_mount_node = parent_node || '#target';
16491 const anchor_node = parent_node ? 'null' : '#anchor';
16492 const has_transitions = this.pending.block.has_intro_method || this.pending.block.has_outro_method;
16493 block.chunks.mount.push(b `
16494 ${info}.block.m(${initial_mount_node}, ${info}.anchor = ${anchor_node});
16495 ${info}.mount = () => ${update_mount_node};
16496 ${info}.anchor = ${anchor};
16497 `);
16498 if (has_transitions) {
16499 block.chunks.intro.push(b `@transition_in(${info}.block);`);
16500 }
16501 const dependencies = this.node.expression.dynamic_dependencies();
16502 let update_child_context;
16503 if (this.then.value && this.catch.value) {
16504 update_child_context = b `#child_ctx[${this.then.value_index}] = #child_ctx[${this.catch.value_index}] = ${info}.resolved;`;
16505 }
16506 else if (this.then.value) {
16507 update_child_context = b `#child_ctx[${this.then.value_index}] = ${info}.resolved;`;
16508 }
16509 else if (this.catch.value) {
16510 update_child_context = b `#child_ctx[${this.catch.value_index}] = ${info}.resolved;`;
16511 }
16512 if (dependencies.length > 0) {
16513 const condition = x `
16514 ${block.renderer.dirty(dependencies)} &&
16515 ${promise} !== (${promise} = ${snippet}) &&
16516 @handle_promise(${promise}, ${info})`;
16517 block.chunks.update.push(b `${info}.ctx = #ctx;`);
16518 if (this.pending.block.has_update_method) {
16519 block.chunks.update.push(b `
16520 if (${condition}) {
16521
16522 } else {
16523 const #child_ctx = #ctx.slice();
16524 ${update_child_context}
16525 ${info}.block.p(#child_ctx, #dirty);
16526 }
16527 `);
16528 }
16529 else {
16530 block.chunks.update.push(b `
16531 ${condition}
16532 `);
16533 }
16534 }
16535 else {
16536 if (this.pending.block.has_update_method) {
16537 block.chunks.update.push(b `
16538 {
16539 const #child_ctx = #ctx.slice();
16540 ${update_child_context}
16541 ${info}.block.p(#child_ctx, #dirty);
16542 }
16543 `);
16544 }
16545 }
16546 if (this.pending.block.has_outro_method) {
16547 block.chunks.outro.push(b `
16548 for (let #i = 0; #i < 3; #i += 1) {
16549 const block = ${info}.blocks[#i];
16550 @transition_out(block);
16551 }
16552 `);
16553 }
16554 block.chunks.destroy.push(b `
16555 ${info}.block.d(${parent_node ? null : 'detaching'});
16556 ${info}.token = null;
16557 ${info} = null;
16558 `);
16559 [this.pending, this.then, this.catch].forEach(branch => {
16560 branch.render(branch.block, null, x `#nodes`);
16561 });
16562 }
16563 }
16564
16565 const TRUE = x `true`;
16566 const FALSE = x `false`;
16567 class EventHandlerWrapper {
16568 constructor(node, parent) {
16569 this.node = node;
16570 this.parent = parent;
16571 if (!node.expression) {
16572 this.parent.renderer.add_to_context(node.handler_name.name);
16573 this.parent.renderer.component.partly_hoisted.push(b `
16574 function ${node.handler_name.name}(event) {
16575 @bubble($$self, event);
16576 }
16577 `);
16578 }
16579 }
16580 get_snippet(block) {
16581 const snippet = this.node.expression ? this.node.expression.manipulate(block) : block.renderer.reference(this.node.handler_name);
16582 if (this.node.reassigned) {
16583 block.maintain_context = true;
16584 return x `function () { if (@is_function(${snippet})) ${snippet}.apply(this, arguments); }`;
16585 }
16586 return snippet;
16587 }
16588 render(block, target) {
16589 let snippet = this.get_snippet(block);
16590 if (this.node.modifiers.has('preventDefault'))
16591 snippet = x `@prevent_default(${snippet})`;
16592 if (this.node.modifiers.has('stopPropagation'))
16593 snippet = x `@stop_propagation(${snippet})`;
16594 if (this.node.modifiers.has('self'))
16595 snippet = x `@self(${snippet})`;
16596 const args = [];
16597 const opts = ['nonpassive', 'passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod));
16598 if (opts.length) {
16599 if (opts.length === 1 && opts[0] === 'capture') {
16600 args.push(TRUE);
16601 }
16602 else {
16603 args.push(x `{ ${opts.map(opt => opt === 'nonpassive'
16604 ? p `passive: false`
16605 : p `${opt}: true`)} }`);
16606 }
16607 }
16608 else if (block.renderer.options.dev) {
16609 args.push(FALSE);
16610 }
16611 if (block.renderer.options.dev) {
16612 args.push(this.node.modifiers.has('preventDefault') ? TRUE : FALSE);
16613 args.push(this.node.modifiers.has('stopPropagation') ? TRUE : FALSE);
16614 }
16615 block.event_listeners.push(x `@listen(${target}, "${this.node.name}", ${snippet}, ${args})`);
16616 }
16617 }
16618
16619 function add_event_handlers(block, target, handlers) {
16620 handlers.forEach(handler => add_event_handler(block, target, handler));
16621 }
16622 function add_event_handler(block, target, handler) {
16623 handler.render(block, target);
16624 }
16625
16626 class BodyWrapper extends Wrapper {
16627 constructor(renderer, block, parent, node) {
16628 super(renderer, block, parent, node);
16629 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
16630 }
16631 render(block, _parent_node, _parent_nodes) {
16632 add_event_handlers(block, x `@_document.body`, this.handlers);
16633 }
16634 }
16635
16636 function add_to_set(a, b) {
16637 // @ts-ignore
16638 b.forEach(item => {
16639 a.add(item);
16640 });
16641 }
16642
16643 class DebugTagWrapper extends Wrapper {
16644 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
16645 super(renderer, block, parent, node);
16646 }
16647 render(block, _parent_node, _parent_nodes) {
16648 const { renderer } = this;
16649 const { component } = renderer;
16650 if (!renderer.options.dev)
16651 return;
16652 const { var_lookup } = component;
16653 const start = component.locate(this.node.start + 1);
16654 const end = { line: start.line, column: start.column + 6 };
16655 const loc = { start, end };
16656 const debug = {
16657 type: 'DebuggerStatement',
16658 loc
16659 };
16660 if (this.node.expressions.length === 0) {
16661 // Debug all
16662 block.chunks.create.push(debug);
16663 block.chunks.update.push(debug);
16664 }
16665 else {
16666 const log = {
16667 type: 'Identifier',
16668 name: 'log',
16669 loc
16670 };
16671 const dependencies = new Set();
16672 this.node.expressions.forEach(expression => {
16673 add_to_set(dependencies, expression.dependencies);
16674 });
16675 const contextual_identifiers = this.node.expressions
16676 .filter(e => {
16677 const variable = var_lookup.get(e.node.name);
16678 return !(variable && variable.hoistable);
16679 })
16680 .map(e => e.node.name);
16681 const logged_identifiers = this.node.expressions.map(e => p `${e.node.name}`);
16682 const debug_statements = b `
16683 ${contextual_identifiers.map(name => b `const ${name} = ${renderer.reference(name)};`)}
16684 @_console.${log}({ ${logged_identifiers} });
16685 debugger;`;
16686 if (dependencies.size) {
16687 const condition = renderer.dirty(Array.from(dependencies));
16688 block.chunks.update.push(b `
16689 if (${condition}) {
16690 ${debug_statements}
16691 }
16692 `);
16693 }
16694 block.chunks.create.push(b `{
16695 ${debug_statements}
16696 }`);
16697 }
16698 }
16699 }
16700
16701 function get_object(node) {
16702 while (node.type === 'MemberExpression')
16703 node = node.object;
16704 return node;
16705 }
16706
16707 class ElseBlockWrapper extends Wrapper {
16708 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16709 super(renderer, block, parent, node);
16710 this.var = null;
16711 this.block = block.child({
16712 comment: create_debugging_comment(node, this.renderer.component),
16713 name: this.renderer.component.get_unique_name('create_else_block'),
16714 type: 'else'
16715 });
16716 this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling);
16717 this.is_dynamic = this.block.dependencies.size > 0;
16718 }
16719 }
16720 class EachBlockWrapper extends Wrapper {
16721 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
16722 super(renderer, block, parent, node);
16723 this.updates = [];
16724 this.var = { type: 'Identifier', name: 'each' };
16725 this.cannot_use_innerhtml();
16726 this.not_static_content();
16727 const { dependencies } = node.expression;
16728 block.add_dependencies(dependencies);
16729 this.node.contexts.forEach(context => {
16730 renderer.add_to_context(context.key.name, true);
16731 });
16732 this.block = block.child({
16733 comment: create_debugging_comment(this.node, this.renderer.component),
16734 name: renderer.component.get_unique_name('create_each_block'),
16735 type: 'each',
16736 // @ts-ignore todo: probably error
16737 key: node.key,
16738 bindings: new Map(block.bindings)
16739 });
16740 // TODO this seems messy
16741 this.block.has_animation = this.node.has_animation;
16742 this.index_name = this.node.index
16743 ? { type: 'Identifier', name: this.node.index }
16744 : renderer.component.get_unique_name(`${this.node.context}_index`);
16745 const fixed_length = node.expression.node.type === 'ArrayExpression' &&
16746 node.expression.node.elements.every(element => element.type !== 'SpreadElement')
16747 ? node.expression.node.elements.length
16748 : null;
16749 // hack the sourcemap, so that if data is missing the bug
16750 // is easy to find
16751 let c = this.node.start + 2;
16752 while (renderer.component.source[c] !== 'e')
16753 c += 1;
16754 const start = renderer.component.locate(c);
16755 const end = { line: start.line, column: start.column + 4 };
16756 const length = {
16757 type: 'Identifier',
16758 name: 'length',
16759 loc: { start, end }
16760 };
16761 const each_block_value = renderer.component.get_unique_name(`${this.var.name}_value`);
16762 const iterations = block.get_unique_name(`${this.var.name}_blocks`);
16763 renderer.add_to_context(each_block_value.name, true);
16764 renderer.add_to_context(this.index_name.name, true);
16765 this.vars = {
16766 create_each_block: this.block.name,
16767 each_block_value,
16768 get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`),
16769 iterations,
16770 // optimisation for array literal
16771 fixed_length,
16772 data_length: fixed_length === null ? x `${each_block_value}.${length}` : fixed_length,
16773 view_length: fixed_length === null ? x `${iterations}.length` : fixed_length
16774 };
16775 const object = get_object(node.expression.node);
16776 const store = object.type === 'Identifier' && object.name[0] === '$' ? object.name.slice(1) : null;
16777 node.contexts.forEach(prop => {
16778 this.block.bindings.set(prop.key.name, {
16779 object: this.vars.each_block_value,
16780 property: this.index_name,
16781 modifier: prop.modifier,
16782 snippet: prop.modifier(x `${this.vars.each_block_value}[${this.index_name}]`),
16783 store,
16784 tail: prop.modifier(x `[${this.index_name}]`)
16785 });
16786 });
16787 if (this.node.index) {
16788 this.block.get_unique_name(this.node.index); // this prevents name collisions (#1254)
16789 }
16790 renderer.blocks.push(this.block);
16791 this.fragment = new FragmentWrapper(renderer, this.block, node.children, this, strip_whitespace, next_sibling);
16792 if (this.node.else) {
16793 this.else = new ElseBlockWrapper(renderer, block, this, this.node.else, strip_whitespace, next_sibling);
16794 renderer.blocks.push(this.else.block);
16795 if (this.else.is_dynamic) {
16796 this.block.add_dependencies(this.else.block.dependencies);
16797 }
16798 }
16799 block.add_dependencies(this.block.dependencies);
16800 if (this.block.has_outros || (this.else && this.else.block.has_outros)) {
16801 block.add_outro();
16802 }
16803 }
16804 render(block, parent_node, parent_nodes) {
16805 if (this.fragment.nodes.length === 0)
16806 return;
16807 const { renderer } = this;
16808 const { component } = renderer;
16809 const needs_anchor = this.next
16810 ? !this.next.is_dom_node() :
16811 !parent_node || !this.parent.is_dom_node();
16812 const snippet = this.node.expression.manipulate(block);
16813 block.chunks.init.push(b `let ${this.vars.each_block_value} = ${snippet};`);
16814 if (this.renderer.options.dev) {
16815 block.chunks.init.push(b `@validate_each_argument(${this.vars.each_block_value});`);
16816 }
16817 const initial_anchor_node = { type: 'Identifier', name: parent_node ? 'null' : '#anchor' };
16818 const initial_mount_node = parent_node || { type: 'Identifier', name: '#target' };
16819 const update_anchor_node = needs_anchor
16820 ? block.get_unique_name(`${this.var.name}_anchor`)
16821 : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
16822 const update_mount_node = this.get_update_mount_node(update_anchor_node);
16823 const args = {
16824 block,
16825 parent_node,
16826 parent_nodes,
16827 snippet,
16828 initial_anchor_node,
16829 initial_mount_node,
16830 update_anchor_node,
16831 update_mount_node
16832 };
16833 const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
16834 this.node.expression.dynamic_dependencies().forEach((dependency) => {
16835 all_dependencies.add(dependency);
16836 });
16837 if (this.node.key) {
16838 this.node.key.dynamic_dependencies().forEach((dependency) => {
16839 all_dependencies.add(dependency);
16840 });
16841 }
16842 this.dependencies = all_dependencies;
16843 if (this.node.key) {
16844 this.render_keyed(args);
16845 }
16846 else {
16847 this.render_unkeyed(args);
16848 }
16849 if (this.block.has_intro_method || this.block.has_outro_method) {
16850 block.chunks.intro.push(b `
16851 for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) {
16852 @transition_in(${this.vars.iterations}[#i]);
16853 }
16854 `);
16855 }
16856 if (needs_anchor) {
16857 block.add_element(update_anchor_node, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
16858 }
16859 if (this.else) {
16860 const each_block_else = component.get_unique_name(`${this.var.name}_else`);
16861 block.chunks.init.push(b `let ${each_block_else} = null;`);
16862 // TODO neaten this up... will end up with an empty line in the block
16863 block.chunks.init.push(b `
16864 if (!${this.vars.data_length}) {
16865 ${each_block_else} = ${this.else.block.name}(#ctx);
16866 }
16867 `);
16868 block.chunks.create.push(b `
16869 if (${each_block_else}) {
16870 ${each_block_else}.c();
16871 }
16872 `);
16873 if (this.renderer.options.hydratable) {
16874 block.chunks.claim.push(b `
16875 if (${each_block_else}) {
16876 ${each_block_else}.l(${parent_nodes});
16877 }
16878 `);
16879 }
16880 block.chunks.mount.push(b `
16881 if (${each_block_else}) {
16882 ${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node});
16883 }
16884 `);
16885 const has_transitions = !!(this.else.block.has_intro_method || this.else.block.has_outro_method);
16886 const destroy_block_else = this.else.block.has_outro_method
16887 ? b `
16888 @group_outros();
16889 @transition_out(${each_block_else}, 1, 1, () => {
16890 ${each_block_else} = null;
16891 });
16892 @check_outros();`
16893 : b `
16894 ${each_block_else}.d(1);
16895 ${each_block_else} = null;`;
16896 if (this.else.block.has_update_method) {
16897 this.updates.push(b `
16898 if (!${this.vars.data_length} && ${each_block_else}) {
16899 ${each_block_else}.p(#ctx, #dirty);
16900 } else if (!${this.vars.data_length}) {
16901 ${each_block_else} = ${this.else.block.name}(#ctx);
16902 ${each_block_else}.c();
16903 ${has_transitions && b `@transition_in(${each_block_else}, 1);`}
16904 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16905 } else if (${each_block_else}) {
16906 ${destroy_block_else};
16907 }
16908 `);
16909 }
16910 else {
16911 this.updates.push(b `
16912 if (${this.vars.data_length}) {
16913 if (${each_block_else}) {
16914 ${destroy_block_else};
16915 }
16916 } else if (!${each_block_else}) {
16917 ${each_block_else} = ${this.else.block.name}(#ctx);
16918 ${each_block_else}.c();
16919 ${has_transitions && b `@transition_in(${each_block_else}, 1);`}
16920 ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
16921 }
16922 `);
16923 }
16924 block.chunks.destroy.push(b `
16925 if (${each_block_else}) ${each_block_else}.d(${parent_node ? '' : 'detaching'});
16926 `);
16927 }
16928 if (this.updates.length) {
16929 block.chunks.update.push(b `
16930 if (${block.renderer.dirty(Array.from(all_dependencies))}) {
16931 ${this.updates}
16932 }
16933 `);
16934 }
16935 this.fragment.render(this.block, null, x `#nodes`);
16936 if (this.else) {
16937 this.else.fragment.render(this.else.block, null, x `#nodes`);
16938 }
16939 this.context_props = this.node.contexts.map(prop => b `child_ctx[${renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x `list[i]`)};`);
16940 if (this.node.has_binding)
16941 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`);
16942 if (this.node.has_binding || this.node.has_index_binding || this.node.index)
16943 this.context_props.push(b `child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`);
16944 // TODO which is better — Object.create(array) or array.slice()?
16945 renderer.blocks.push(b `
16946 function ${this.vars.get_each_context}(#ctx, list, i) {
16947 const child_ctx = #ctx.slice();
16948 ${this.context_props}
16949 return child_ctx;
16950 }
16951 `);
16952 }
16953 render_keyed({ block, parent_node, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
16954 const { create_each_block, iterations, data_length, view_length } = this.vars;
16955 const get_key = block.get_unique_name('get_key');
16956 const lookup = block.get_unique_name(`${this.var.name}_lookup`);
16957 block.add_variable(iterations, x `[]`);
16958 block.add_variable(lookup, x `new @_Map()`);
16959 if (this.fragment.nodes[0].is_dom_node()) {
16960 this.block.first = this.fragment.nodes[0].var;
16961 }
16962 else {
16963 this.block.first = this.block.get_unique_name('first');
16964 this.block.add_element(this.block.first, x `@empty()`, parent_nodes && x `@empty()`, null);
16965 }
16966 block.chunks.init.push(b `
16967 const ${get_key} = #ctx => ${this.node.key.manipulate(block)};
16968
16969 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
16970 for (let #i = 0; #i < ${data_length}; #i += 1) {
16971 let child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
16972 let key = ${get_key}(child_ctx);
16973 ${lookup}.set(key, ${iterations}[#i] = ${create_each_block}(key, child_ctx));
16974 }
16975 `);
16976 block.chunks.create.push(b `
16977 for (let #i = 0; #i < ${view_length}; #i += 1) {
16978 ${iterations}[#i].c();
16979 }
16980 `);
16981 if (parent_nodes && this.renderer.options.hydratable) {
16982 block.chunks.claim.push(b `
16983 for (let #i = 0; #i < ${view_length}; #i += 1) {
16984 ${iterations}[#i].l(${parent_nodes});
16985 }
16986 `);
16987 }
16988 block.chunks.mount.push(b `
16989 for (let #i = 0; #i < ${view_length}; #i += 1) {
16990 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
16991 }
16992 `);
16993 const dynamic = this.block.has_update_method;
16994 const destroy = this.node.has_animation
16995 ? (this.block.has_outros
16996 ? '@fix_and_outro_and_destroy_block'
16997 : '@fix_and_destroy_block')
16998 : this.block.has_outros
16999 ? '@outro_and_destroy_block'
17000 : '@destroy_block';
17001 if (this.dependencies.size) {
17002 this.block.maintain_context = true;
17003 this.updates.push(b `
17004 ${this.vars.each_block_value} = ${snippet};
17005 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
17006
17007 ${this.block.has_outros && b `@group_outros();`}
17008 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`}
17009 ${this.renderer.options.dev && b `@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
17010 ${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});
17011 ${this.node.has_animation && b `for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
17012 ${this.block.has_outros && b `@check_outros();`}
17013 `);
17014 }
17015 if (this.block.has_outros) {
17016 block.chunks.outro.push(b `
17017 for (let #i = 0; #i < ${view_length}; #i += 1) {
17018 @transition_out(${iterations}[#i]);
17019 }
17020 `);
17021 }
17022 block.chunks.destroy.push(b `
17023 for (let #i = 0; #i < ${view_length}; #i += 1) {
17024 ${iterations}[#i].d(${parent_node ? null : 'detaching'});
17025 }
17026 `);
17027 }
17028 render_unkeyed({ block, parent_nodes, snippet, initial_anchor_node, initial_mount_node, update_anchor_node, update_mount_node }) {
17029 const { create_each_block, iterations, fixed_length, data_length, view_length } = this.vars;
17030 block.chunks.init.push(b `
17031 let ${iterations} = [];
17032
17033 for (let #i = 0; #i < ${data_length}; #i += 1) {
17034 ${iterations}[#i] = ${create_each_block}(${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i));
17035 }
17036 `);
17037 block.chunks.create.push(b `
17038 for (let #i = 0; #i < ${view_length}; #i += 1) {
17039 ${iterations}[#i].c();
17040 }
17041 `);
17042 if (parent_nodes && this.renderer.options.hydratable) {
17043 block.chunks.claim.push(b `
17044 for (let #i = 0; #i < ${view_length}; #i += 1) {
17045 ${iterations}[#i].l(${parent_nodes});
17046 }
17047 `);
17048 }
17049 block.chunks.mount.push(b `
17050 for (let #i = 0; #i < ${view_length}; #i += 1) {
17051 ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
17052 }
17053 `);
17054 if (this.dependencies.size) {
17055 const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
17056 const for_loop_body = this.block.has_update_method
17057 ? b `
17058 if (${iterations}[#i]) {
17059 ${iterations}[#i].p(child_ctx, #dirty);
17060 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
17061 } else {
17062 ${iterations}[#i] = ${create_each_block}(child_ctx);
17063 ${iterations}[#i].c();
17064 ${has_transitions && b `@transition_in(${this.vars.iterations}[#i], 1);`}
17065 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
17066 }
17067 `
17068 : has_transitions
17069 ? b `
17070 if (${iterations}[#i]) {
17071 @transition_in(${this.vars.iterations}[#i], 1);
17072 } else {
17073 ${iterations}[#i] = ${create_each_block}(child_ctx);
17074 ${iterations}[#i].c();
17075 @transition_in(${this.vars.iterations}[#i], 1);
17076 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
17077 }
17078 `
17079 : b `
17080 if (!${iterations}[#i]) {
17081 ${iterations}[#i] = ${create_each_block}(child_ctx);
17082 ${iterations}[#i].c();
17083 ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
17084 }
17085 `;
17086 const start = this.block.has_update_method ? 0 : '#old_length';
17087 let remove_old_blocks;
17088 if (this.block.has_outros) {
17089 const out = block.get_unique_name('out');
17090 block.chunks.init.push(b `
17091 const ${out} = i => @transition_out(${iterations}[i], 1, 1, () => {
17092 ${iterations}[i] = null;
17093 });
17094 `);
17095 remove_old_blocks = b `
17096 @group_outros();
17097 for (#i = ${data_length}; #i < ${view_length}; #i += 1) {
17098 ${out}(#i);
17099 }
17100 @check_outros();
17101 `;
17102 }
17103 else {
17104 remove_old_blocks = b `
17105 for (${this.block.has_update_method ? null : x `#i = ${data_length}`}; #i < ${this.block.has_update_method ? view_length : '#old_length'}; #i += 1) {
17106 ${iterations}[#i].d(1);
17107 }
17108 ${!fixed_length && b `${view_length} = ${data_length};`}
17109 `;
17110 }
17111 // We declare `i` as block scoped here, as the `remove_old_blocks` code
17112 // may rely on continuing where this iteration stopped.
17113 const update = b `
17114 ${!this.block.has_update_method && b `const #old_length = ${this.vars.each_block_value}.length;`}
17115 ${this.vars.each_block_value} = ${snippet};
17116 ${this.renderer.options.dev && b `@validate_each_argument(${this.vars.each_block_value});`}
17117
17118 let #i;
17119 for (#i = ${start}; #i < ${data_length}; #i += 1) {
17120 const child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
17121
17122 ${for_loop_body}
17123 }
17124
17125 ${remove_old_blocks}
17126 `;
17127 this.updates.push(update);
17128 }
17129 if (this.block.has_outros) {
17130 block.chunks.outro.push(b `
17131 ${iterations} = ${iterations}.filter(@_Boolean);
17132 for (let #i = 0; #i < ${view_length}; #i += 1) {
17133 @transition_out(${iterations}[#i]);
17134 }
17135 `);
17136 }
17137 block.chunks.destroy.push(b `@destroy_each(${iterations}, detaching);`);
17138 }
17139 }
17140
17141 function string_literal(data) {
17142 return {
17143 type: 'Literal',
17144 value: data
17145 };
17146 }
17147 const escaped = {
17148 '"': '&quot;',
17149 "'": '&#39;',
17150 '&': '&amp;',
17151 '<': '&lt;',
17152 '>': '&gt;'
17153 };
17154 function escape_html(html) {
17155 return String(html).replace(/["'&<>]/g, match => escaped[match]);
17156 }
17157 function escape_template(str) {
17158 return str.replace(/(\${|`|\\)/g, '\\$1');
17159 }
17160
17161 class TextWrapper extends Wrapper {
17162 constructor(renderer, block, parent, node, data) {
17163 super(renderer, block, parent, node);
17164 this.skip = this.node.should_skip();
17165 this.data = data;
17166 this.var = (this.skip ? null : x `t`);
17167 }
17168 use_space() {
17169 if (this.renderer.component.component_options.preserveWhitespace)
17170 return false;
17171 if (/[\S\u00A0]/.test(this.data))
17172 return false;
17173 let node = this.parent && this.parent.node;
17174 while (node) {
17175 if (node.type === 'Element' && node.name === 'pre') {
17176 return false;
17177 }
17178 node = node.parent;
17179 }
17180 return true;
17181 }
17182 render(block, parent_node, parent_nodes) {
17183 if (this.skip)
17184 return;
17185 const use_space = this.use_space();
17186 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);
17187 }
17188 }
17189
17190 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(' ');
17191 const svg_attribute_lookup = new Map();
17192 svg_attributes.forEach(name => {
17193 svg_attribute_lookup.set(name.toLowerCase(), name);
17194 });
17195 function fix_attribute_casing(name) {
17196 name = name.toLowerCase();
17197 return svg_attribute_lookup.get(name) || name;
17198 }
17199
17200 const html = 'http://www.w3.org/1999/xhtml';
17201 const mathml = 'http://www.w3.org/1998/Math/MathML';
17202 const svg = 'http://www.w3.org/2000/svg';
17203 const xlink = 'http://www.w3.org/1999/xlink';
17204 const xml = 'http://www.w3.org/XML/1998/namespace';
17205 const xmlns = 'http://www.w3.org/2000/xmlns';
17206 const valid_namespaces = [
17207 'html',
17208 'mathml',
17209 'svg',
17210 'xlink',
17211 'xml',
17212 'xmlns',
17213 html,
17214 mathml,
17215 svg,
17216 xlink,
17217 xml,
17218 xmlns
17219 ];
17220 const namespaces = { html, mathml, svg, xlink, xml, xmlns };
17221
17222 function handle_select_value_binding(attr, dependencies) {
17223 const { parent } = attr;
17224 if (parent.node.name === 'select') {
17225 parent.select_binding_dependencies = dependencies;
17226 dependencies.forEach((prop) => {
17227 parent.renderer.component.indirect_dependencies.set(prop, new Set());
17228 });
17229 }
17230 }
17231
17232 class BaseAttributeWrapper {
17233 constructor(parent, block, node) {
17234 this.node = node;
17235 this.parent = parent;
17236 if (node.dependencies.size > 0) {
17237 parent.cannot_use_innerhtml();
17238 parent.not_static_content();
17239 block.add_dependencies(node.dependencies);
17240 }
17241 }
17242 render(_block) { }
17243 }
17244 class AttributeWrapper extends BaseAttributeWrapper {
17245 constructor(parent, block, node) {
17246 super(parent, block, node);
17247 if (node.dependencies.size > 0) {
17248 // special case — <option value={foo}> — see below
17249 if (this.parent.node.name === 'option' && node.name === 'value') {
17250 let select = this.parent;
17251 while (select && (select.node.type !== 'Element' || select.node.name !== 'select')) {
17252 // @ts-ignore todo: doublecheck this, but looks to be correct
17253 select = select.parent;
17254 }
17255 if (select && select.select_binding_dependencies) {
17256 select.select_binding_dependencies.forEach(prop => {
17257 this.node.dependencies.forEach((dependency) => {
17258 this.parent.renderer.component.indirect_dependencies.get(prop).add(dependency);
17259 });
17260 });
17261 }
17262 }
17263 if (node.name === 'value') {
17264 handle_select_value_binding(this, node.dependencies);
17265 }
17266 }
17267 this.name = fix_attribute_casing(this.node.name);
17268 this.metadata = this.get_metadata();
17269 this.is_indirectly_bound_value = is_indirectly_bound_value(this);
17270 this.property_name = this.is_indirectly_bound_value
17271 ? '__value'
17272 : this.metadata && this.metadata.property_name;
17273 this.is_src = this.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
17274 this.is_select_value_attribute = this.name === 'value' && this.parent.node.name === 'select';
17275 this.is_input_value = this.name === 'value' && this.parent.node.name === 'input';
17276 this.should_cache = should_cache(this);
17277 }
17278 render(block) {
17279 const element = this.parent;
17280 const { name, property_name, should_cache, is_indirectly_bound_value } = this;
17281 // xlink is a special case... we could maybe extend this to generic
17282 // namespaced attributes but I'm not sure that's applicable in
17283 // HTML5?
17284 const method = /-/.test(element.node.name)
17285 ? '@set_custom_element_data'
17286 : name.slice(0, 6) === 'xlink:'
17287 ? '@xlink_attr'
17288 : '@attr';
17289 const is_legacy_input_type = element.renderer.component.compile_options.legacy && name === 'type' && this.parent.node.name === 'input';
17290 const dependencies = this.get_dependencies();
17291 const value = this.get_value(block);
17292 let updater;
17293 const init = this.get_init(block, value);
17294 if (is_legacy_input_type) {
17295 block.chunks.hydrate.push(b `@set_input_type(${element.var}, ${init});`);
17296 updater = b `@set_input_type(${element.var}, ${should_cache ? this.last : value});`;
17297 }
17298 else if (this.is_select_value_attribute) {
17299 // annoying special case
17300 const is_multiple_select = element.node.get_static_attribute_value('multiple');
17301 if (is_multiple_select) {
17302 updater = b `@select_options(${element.var}, ${value});`;
17303 }
17304 else {
17305 updater = b `@select_option(${element.var}, ${value});`;
17306 }
17307 block.chunks.mount.push(b `
17308 ${updater}
17309 `);
17310 }
17311 else if (this.is_src) {
17312 block.chunks.hydrate.push(b `if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${this.last});`);
17313 updater = b `${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
17314 }
17315 else if (property_name) {
17316 block.chunks.hydrate.push(b `${element.var}.${property_name} = ${init};`);
17317 updater = block.renderer.options.dev
17318 ? b `@prop_dev(${element.var}, "${property_name}", ${should_cache ? this.last : value});`
17319 : b `${element.var}.${property_name} = ${should_cache ? this.last : value};`;
17320 }
17321 else {
17322 block.chunks.hydrate.push(b `${method}(${element.var}, "${name}", ${init});`);
17323 updater = b `${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
17324 }
17325 if (is_indirectly_bound_value) {
17326 const update_value = b `${element.var}.value = ${element.var}.__value;`;
17327 block.chunks.hydrate.push(update_value);
17328 updater = b `
17329 ${updater}
17330 ${update_value};
17331 `;
17332 }
17333 if (dependencies.length > 0) {
17334 const condition = this.get_dom_update_conditions(block, block.renderer.dirty(dependencies));
17335 block.chunks.update.push(b `
17336 if (${condition}) {
17337 ${updater}
17338 }`);
17339 }
17340 // special case – autofocus. has to be handled in a bit of a weird way
17341 if (this.node.is_true && name === 'autofocus') {
17342 block.autofocus = element.var;
17343 }
17344 }
17345 get_init(block, value) {
17346 this.last = this.should_cache && block.get_unique_name(`${this.parent.var.name}_${this.name.replace(/[^a-zA-Z_$]/g, '_')}_value`);
17347 if (this.should_cache)
17348 block.add_variable(this.last);
17349 return this.should_cache ? x `${this.last} = ${value}` : value;
17350 }
17351 get_dom_update_conditions(block, dependency_condition) {
17352 const { property_name, should_cache, last } = this;
17353 const element = this.parent;
17354 const value = this.get_value(block);
17355 let condition = dependency_condition;
17356 if (should_cache) {
17357 condition = this.is_src
17358 ? x `${condition} && (${element.var}.src !== (${last} = ${value}))`
17359 : x `${condition} && (${last} !== (${last} = ${value}))`;
17360 }
17361 if (this.is_input_value) {
17362 const type = element.node.get_static_attribute_value('type');
17363 if (type === null || type === '' || type === 'text' || type === 'email' || type === 'password') {
17364 condition = x `${condition} && ${element.var}.${property_name} !== ${should_cache ? last : value}`;
17365 }
17366 }
17367 if (block.has_outros) {
17368 condition = x `!#current || ${condition}`;
17369 }
17370 return condition;
17371 }
17372 get_dependencies() {
17373 const node_dependencies = this.node.get_dependencies();
17374 const dependencies = new Set(node_dependencies);
17375 node_dependencies.forEach((prop) => {
17376 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17377 if (indirect_dependencies) {
17378 indirect_dependencies.forEach(indirect_dependency => {
17379 dependencies.add(indirect_dependency);
17380 });
17381 }
17382 });
17383 return Array.from(dependencies);
17384 }
17385 get_metadata() {
17386 if (this.parent.node.namespace)
17387 return null;
17388 const metadata = attribute_lookup[this.name];
17389 if (metadata && metadata.applies_to && !metadata.applies_to.includes(this.parent.node.name))
17390 return null;
17391 return metadata;
17392 }
17393 get_value(block) {
17394 if (this.node.is_true) {
17395 if (this.metadata && boolean_attribute.has(this.metadata.property_name.toLowerCase())) {
17396 return x `true`;
17397 }
17398 return x `""`;
17399 }
17400 if (this.node.chunks.length === 0)
17401 return x `""`;
17402 // TODO some of this code is repeated in Tag.ts — would be good to
17403 // DRY it out if that's possible without introducing crazy indirection
17404 if (this.node.chunks.length === 1) {
17405 return this.node.chunks[0].type === 'Text'
17406 ? string_literal(this.node.chunks[0].data)
17407 : this.node.chunks[0].manipulate(block);
17408 }
17409 let value = this.node.name === 'class'
17410 ? this.get_class_name_text(block)
17411 : this.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17412 // '{foo} {bar}' — treat as string concatenation
17413 if (this.node.chunks[0].type !== 'Text') {
17414 value = x `"" + ${value}`;
17415 }
17416 return value;
17417 }
17418 get_class_name_text(block) {
17419 const scoped_css = this.node.chunks.some((chunk) => chunk.synthetic);
17420 const rendered = this.render_chunks(block);
17421 if (scoped_css && rendered.length === 2) {
17422 // we have a situation like class={possiblyUndefined}
17423 rendered[0] = x `@null_to_empty(${rendered[0]})`;
17424 }
17425 return rendered.reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17426 }
17427 render_chunks(block) {
17428 return this.node.chunks.map((chunk) => {
17429 if (chunk.type === 'Text') {
17430 return string_literal(chunk.data);
17431 }
17432 return chunk.manipulate(block);
17433 });
17434 }
17435 stringify() {
17436 if (this.node.is_true)
17437 return '';
17438 const value = this.node.chunks;
17439 if (value.length === 0)
17440 return '=""';
17441 return `="${value.map(chunk => {
17442 return chunk.type === 'Text'
17443 ? chunk.data.replace(/"/g, '\\"')
17444 : `\${${chunk.manipulate()}}`;
17445 }).join('')}"`;
17446 }
17447 }
17448 // source: https://html.spec.whatwg.org/multipage/indices.html
17449 const attribute_lookup = {
17450 allowfullscreen: { property_name: 'allowFullscreen', applies_to: ['iframe'] },
17451 allowpaymentrequest: { property_name: 'allowPaymentRequest', applies_to: ['iframe'] },
17452 async: { applies_to: ['script'] },
17453 autofocus: { applies_to: ['button', 'input', 'keygen', 'select', 'textarea'] },
17454 autoplay: { applies_to: ['audio', 'video'] },
17455 checked: { applies_to: ['input'] },
17456 controls: { applies_to: ['audio', 'video'] },
17457 default: { applies_to: ['track'] },
17458 defer: { applies_to: ['script'] },
17459 disabled: {
17460 applies_to: [
17461 'button',
17462 'fieldset',
17463 'input',
17464 'keygen',
17465 'optgroup',
17466 'option',
17467 'select',
17468 'textarea'
17469 ]
17470 },
17471 formnovalidate: { property_name: 'formNoValidate', applies_to: ['button', 'input'] },
17472 hidden: {},
17473 indeterminate: { applies_to: ['input'] },
17474 ismap: { property_name: 'isMap', applies_to: ['img'] },
17475 loop: { applies_to: ['audio', 'bgsound', 'video'] },
17476 multiple: { applies_to: ['input', 'select'] },
17477 muted: { applies_to: ['audio', 'video'] },
17478 nomodule: { property_name: 'noModule', applies_to: ['script'] },
17479 novalidate: { property_name: 'noValidate', applies_to: ['form'] },
17480 open: { applies_to: ['details', 'dialog'] },
17481 playsinline: { property_name: 'playsInline', applies_to: ['video'] },
17482 readonly: { property_name: 'readOnly', applies_to: ['input', 'textarea'] },
17483 required: { applies_to: ['input', 'select', 'textarea'] },
17484 reversed: { applies_to: ['ol'] },
17485 selected: { applies_to: ['option'] },
17486 value: {
17487 applies_to: [
17488 'button',
17489 'option',
17490 'input',
17491 'li',
17492 'meter',
17493 'progress',
17494 'param',
17495 'select',
17496 'textarea'
17497 ]
17498 }
17499 };
17500 Object.keys(attribute_lookup).forEach(name => {
17501 const metadata = attribute_lookup[name];
17502 if (!metadata.property_name)
17503 metadata.property_name = name;
17504 });
17505 // source: https://html.spec.whatwg.org/multipage/indices.html
17506 const boolean_attribute = new Set([
17507 'allowfullscreen',
17508 'allowpaymentrequest',
17509 'async',
17510 'autofocus',
17511 'autoplay',
17512 'checked',
17513 'controls',
17514 'default',
17515 'defer',
17516 'disabled',
17517 'formnovalidate',
17518 'hidden',
17519 'ismap',
17520 'itemscope',
17521 'loop',
17522 'multiple',
17523 'muted',
17524 'nomodule',
17525 'novalidate',
17526 'open',
17527 'playsinline',
17528 'readonly',
17529 'required',
17530 'reversed',
17531 'selected'
17532 ]);
17533 function should_cache(attribute) {
17534 return attribute.is_src || attribute.node.should_cache();
17535 }
17536 function is_indirectly_bound_value(attribute) {
17537 const element = attribute.parent;
17538 return attribute.name === 'value' &&
17539 (element.node.name === 'option' || // TODO check it's actually bound
17540 (element.node.name === 'input' &&
17541 element.node.bindings.some((binding) => /checked|group/.test(binding.name))));
17542 }
17543
17544 class StyleAttributeWrapper extends AttributeWrapper {
17545 render(block) {
17546 const style_props = optimize_style(this.node.chunks);
17547 if (!style_props)
17548 return super.render(block);
17549 style_props.forEach((prop) => {
17550 let value;
17551 if (is_dynamic(prop.value)) {
17552 const prop_dependencies = new Set();
17553 value = prop.value
17554 .map(chunk => {
17555 if (chunk.type === 'Text') {
17556 return string_literal(chunk.data);
17557 }
17558 else {
17559 add_to_set(prop_dependencies, chunk.dynamic_dependencies());
17560 return chunk.manipulate(block);
17561 }
17562 })
17563 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
17564 // TODO is this necessary? style.setProperty always treats value as string, no?
17565 // if (prop.value.length === 1 || prop.value[0].type !== 'Text') {
17566 // value = x`"" + ${value}`;
17567 // }
17568 if (prop_dependencies.size) {
17569 let condition = block.renderer.dirty(Array.from(prop_dependencies));
17570 if (block.has_outros) {
17571 condition = x `!#current || ${condition}`;
17572 }
17573 const update = b `
17574 if (${condition}) {
17575 @set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});
17576 }`;
17577 block.chunks.update.push(update);
17578 }
17579 }
17580 else {
17581 value = string_literal(prop.value[0].data);
17582 }
17583 block.chunks.hydrate.push(b `@set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});`);
17584 });
17585 }
17586 }
17587 function optimize_style(value) {
17588 const props = [];
17589 let chunks = value.slice();
17590 while (chunks.length) {
17591 const chunk = chunks[0];
17592 if (chunk.type !== 'Text')
17593 return null;
17594 const key_match = /^\s*([\w-]+):\s*/.exec(chunk.data);
17595 if (!key_match)
17596 return null;
17597 const key = key_match[1];
17598 const offset = key_match.index + key_match[0].length;
17599 const remaining_data = chunk.data.slice(offset);
17600 if (remaining_data) {
17601 chunks[0] = {
17602 start: chunk.start + offset,
17603 end: chunk.end,
17604 type: 'Text',
17605 data: remaining_data
17606 };
17607 }
17608 else {
17609 chunks.shift();
17610 }
17611 const result = get_style_value(chunks);
17612 props.push({ key, value: result.value, important: result.important });
17613 chunks = result.chunks;
17614 }
17615 return props;
17616 }
17617 function get_style_value(chunks) {
17618 const value = [];
17619 let in_url = false;
17620 let quote_mark = null;
17621 let escaped = false;
17622 let closed = false;
17623 while (chunks.length && !closed) {
17624 const chunk = chunks.shift();
17625 if (chunk.type === 'Text') {
17626 let c = 0;
17627 while (c < chunk.data.length) {
17628 const char = chunk.data[c];
17629 if (escaped) {
17630 escaped = false;
17631 }
17632 else if (char === '\\') {
17633 escaped = true;
17634 }
17635 else if (char === quote_mark) {
17636 quote_mark = null;
17637 }
17638 else if (char === '"' || char === "'") {
17639 quote_mark = char;
17640 }
17641 else if (char === ')' && in_url) {
17642 in_url = false;
17643 }
17644 else if (char === 'u' && chunk.data.slice(c, c + 4) === 'url(') {
17645 in_url = true;
17646 }
17647 else if (char === ';' && !in_url && !quote_mark) {
17648 closed = true;
17649 break;
17650 }
17651 c += 1;
17652 }
17653 if (c > 0) {
17654 value.push({
17655 type: 'Text',
17656 start: chunk.start,
17657 end: chunk.start + c,
17658 data: chunk.data.slice(0, c)
17659 });
17660 }
17661 while (/[;\s]/.test(chunk.data[c]))
17662 c += 1;
17663 const remaining_data = chunk.data.slice(c);
17664 if (remaining_data) {
17665 chunks.unshift({
17666 start: chunk.start + c,
17667 end: chunk.end,
17668 type: 'Text',
17669 data: remaining_data
17670 });
17671 break;
17672 }
17673 }
17674 else {
17675 value.push(chunk);
17676 }
17677 }
17678 let important = false;
17679 const last_chunk = value[value.length - 1];
17680 if (last_chunk && last_chunk.type === 'Text' && /\s*!important\s*$/.test(last_chunk.data)) {
17681 important = true;
17682 last_chunk.data = last_chunk.data.replace(/\s*!important\s*$/, '');
17683 if (!last_chunk.data)
17684 value.pop();
17685 }
17686 return {
17687 chunks,
17688 value,
17689 important
17690 };
17691 }
17692 function is_dynamic(value) {
17693 return value.length > 1 || value[0].type !== 'Text';
17694 }
17695
17696 class SpreadAttributeWrapper extends BaseAttributeWrapper {
17697 }
17698
17699 function replace_object(node, replacement) {
17700 if (node.type === 'Identifier')
17701 return replacement;
17702 const ancestor = node;
17703 let parent;
17704 while (node.type === 'MemberExpression') {
17705 parent = node;
17706 node = node.object;
17707 }
17708 parent.object = replacement;
17709 return ancestor;
17710 }
17711
17712 function flatten_reference(node) {
17713 const nodes = [];
17714 const parts = [];
17715 while (node.type === 'MemberExpression') {
17716 nodes.unshift(node.property);
17717 if (!node.computed) {
17718 parts.unshift(node.property.name);
17719 }
17720 else {
17721 const computed_property = to_string$1(node.property);
17722 if (computed_property) {
17723 parts.unshift(`[${computed_property}]`);
17724 }
17725 }
17726 node = node.object;
17727 }
17728 const name = node.type === 'Identifier'
17729 ? node.name
17730 : node.type === 'ThisExpression' ? 'this' : null;
17731 nodes.unshift(node);
17732 parts.unshift(name);
17733 return { name, nodes, parts };
17734 }
17735 function to_string$1(node) {
17736 switch (node.type) {
17737 case 'Literal':
17738 return String(node.value);
17739 case 'Identifier':
17740 return node.name;
17741 }
17742 }
17743
17744 function mark_each_block_bindings(parent, binding) {
17745 // we need to ensure that the each block creates a context including
17746 // the list and the index, if they're not otherwise referenced
17747 binding.expression.references.forEach(name => {
17748 const each_block = parent.node.scope.get_owner(name);
17749 if (each_block) {
17750 each_block.has_binding = true;
17751 }
17752 });
17753 if (binding.name === 'group') {
17754 const add_index_binding = (name) => {
17755 const each_block = parent.node.scope.get_owner(name);
17756 if (each_block.type === 'EachBlock') {
17757 each_block.has_index_binding = true;
17758 for (const dep of each_block.expression.contextual_dependencies) {
17759 add_index_binding(dep);
17760 }
17761 }
17762 };
17763 // for `<input bind:group={} >`, we make sure that all the each blocks creates context with `index`
17764 for (const name of binding.expression.contextual_dependencies) {
17765 add_index_binding(name);
17766 }
17767 }
17768 }
17769
17770 class BindingWrapper {
17771 constructor(block, node, parent) {
17772 this.node = node;
17773 this.parent = parent;
17774 const { dependencies } = this.node.expression;
17775 block.add_dependencies(dependencies);
17776 // TODO does this also apply to e.g. `<input type='checkbox' bind:group='foo'>`?
17777 handle_select_value_binding(this, dependencies);
17778 if (node.is_contextual) {
17779 mark_each_block_bindings(this.parent, this.node);
17780 }
17781 this.object = get_object(this.node.expression.node).name;
17782 // view to model
17783 this.handler = get_event_handler(this, parent.renderer, block, this.object, this.node.raw_expression);
17784 this.snippet = this.node.expression.manipulate(block);
17785 this.is_readonly = this.node.is_readonly;
17786 this.needs_lock = this.node.name === 'currentTime'; // TODO others?
17787 }
17788 get_dependencies() {
17789 const dependencies = new Set(this.node.expression.dependencies);
17790 this.node.expression.dependencies.forEach((prop) => {
17791 const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
17792 if (indirect_dependencies) {
17793 indirect_dependencies.forEach(indirect_dependency => {
17794 dependencies.add(indirect_dependency);
17795 });
17796 }
17797 });
17798 return dependencies;
17799 }
17800 is_readonly_media_attribute() {
17801 return this.node.is_readonly_media_attribute();
17802 }
17803 render(block, lock) {
17804 if (this.is_readonly)
17805 return;
17806 const { parent } = this;
17807 const update_conditions = this.needs_lock ? [x `!${lock}`] : [];
17808 const mount_conditions = [];
17809 const dependency_array = Array.from(this.get_dependencies());
17810 if (dependency_array.length > 0) {
17811 update_conditions.push(block.renderer.dirty(dependency_array));
17812 }
17813 if (parent.node.name === 'input') {
17814 const type = parent.node.get_static_attribute_value('type');
17815 if (type === null ||
17816 type === '' ||
17817 type === 'text' ||
17818 type === 'email' ||
17819 type === 'password') {
17820 update_conditions.push(x `${parent.var}.${this.node.name} !== ${this.snippet}`);
17821 }
17822 else if (type === 'number') {
17823 update_conditions.push(x `@to_number(${parent.var}.${this.node.name}) !== ${this.snippet}`);
17824 }
17825 }
17826 // model to view
17827 let update_dom = get_dom_updater(parent, this);
17828 let mount_dom = update_dom;
17829 // special cases
17830 switch (this.node.name) {
17831 case 'group':
17832 {
17833 const { binding_group, is_context, contexts, index, keypath } = get_binding_group(parent.renderer, this.node, block);
17834 block.renderer.add_to_context('$$binding_groups');
17835 if (is_context && !block.binding_group_initialised.has(keypath)) {
17836 if (contexts.length > 1) {
17837 let binding_group = x `${block.renderer.reference('$$binding_groups')}[${index}]`;
17838 for (const name of contexts.slice(0, -1)) {
17839 binding_group = x `${binding_group}[${block.renderer.reference(name)}]`;
17840 block.chunks.init.push(b `${binding_group} = ${binding_group} || [];`);
17841 }
17842 }
17843 block.chunks.init.push(b `${binding_group(true)} = [];`);
17844 block.binding_group_initialised.add(keypath);
17845 }
17846 block.chunks.hydrate.push(b `${binding_group(true)}.push(${parent.var});`);
17847 block.chunks.destroy.push(b `${binding_group(true)}.splice(${binding_group(true)}.indexOf(${parent.var}), 1);`);
17848 break;
17849 }
17850 case 'textContent':
17851 update_conditions.push(x `${this.snippet} !== ${parent.var}.textContent`);
17852 mount_conditions.push(x `${this.snippet} !== void 0`);
17853 break;
17854 case 'innerHTML':
17855 update_conditions.push(x `${this.snippet} !== ${parent.var}.innerHTML`);
17856 mount_conditions.push(x `${this.snippet} !== void 0`);
17857 break;
17858 case 'currentTime':
17859 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17860 mount_dom = null;
17861 break;
17862 case 'playbackRate':
17863 case 'volume':
17864 update_conditions.push(x `!@_isNaN(${this.snippet})`);
17865 mount_conditions.push(x `!@_isNaN(${this.snippet})`);
17866 break;
17867 case 'paused':
17868 {
17869 // this is necessary to prevent audio restarting by itself
17870 const last = block.get_unique_name(`${parent.var.name}_is_paused`);
17871 block.add_variable(last, x `true`);
17872 update_conditions.push(x `${last} !== (${last} = ${this.snippet})`);
17873 update_dom = b `${parent.var}[${last} ? "pause" : "play"]();`;
17874 mount_dom = null;
17875 break;
17876 }
17877 case 'value':
17878 if (parent.node.get_static_attribute_value('type') === 'file') {
17879 update_dom = null;
17880 mount_dom = null;
17881 }
17882 }
17883 if (update_dom) {
17884 if (update_conditions.length > 0) {
17885 const condition = update_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17886 block.chunks.update.push(b `
17887 if (${condition}) {
17888 ${update_dom}
17889 }
17890 `);
17891 }
17892 else {
17893 block.chunks.update.push(update_dom);
17894 }
17895 }
17896 if (mount_dom) {
17897 if (mount_conditions.length > 0) {
17898 const condition = mount_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`);
17899 block.chunks.mount.push(b `
17900 if (${condition}) {
17901 ${mount_dom}
17902 }
17903 `);
17904 }
17905 else {
17906 block.chunks.mount.push(mount_dom);
17907 }
17908 }
17909 }
17910 }
17911 function get_dom_updater(element, binding) {
17912 const { node } = element;
17913 if (binding.is_readonly_media_attribute()) {
17914 return null;
17915 }
17916 if (binding.node.name === 'this') {
17917 return null;
17918 }
17919 if (node.name === 'select') {
17920 return node.get_static_attribute_value('multiple') === true ?
17921 b `@select_options(${element.var}, ${binding.snippet})` :
17922 b `@select_option(${element.var}, ${binding.snippet})`;
17923 }
17924 if (binding.node.name === 'group') {
17925 const type = node.get_static_attribute_value('type');
17926 const condition = type === 'checkbox'
17927 ? x `~${binding.snippet}.indexOf(${element.var}.__value)`
17928 : x `${element.var}.__value === ${binding.snippet}`;
17929 return b `${element.var}.checked = ${condition};`;
17930 }
17931 if (binding.node.name === 'value') {
17932 return b `@set_input_value(${element.var}, ${binding.snippet});`;
17933 }
17934 return b `${element.var}.${binding.node.name} = ${binding.snippet};`;
17935 }
17936 function get_binding_group(renderer, value, block) {
17937 const { parts } = flatten_reference(value.raw_expression);
17938 let keypath = parts.join('.');
17939 const contexts = [];
17940 const contextual_dependencies = new Set();
17941 const { template_scope } = value.expression;
17942 const add_contextual_dependency = (dep) => {
17943 contextual_dependencies.add(dep);
17944 const owner = template_scope.get_owner(dep);
17945 if (owner.type === 'EachBlock') {
17946 for (const dep of owner.expression.contextual_dependencies) {
17947 add_contextual_dependency(dep);
17948 }
17949 }
17950 };
17951 for (const dep of value.expression.contextual_dependencies) {
17952 add_contextual_dependency(dep);
17953 }
17954 for (const dep of contextual_dependencies) {
17955 const context = block.bindings.get(dep);
17956 let key;
17957 let name;
17958 if (context) {
17959 key = context.object.name;
17960 name = context.property.name;
17961 }
17962 else {
17963 key = dep;
17964 name = dep;
17965 }
17966 keypath = `${key}@${keypath}`;
17967 contexts.push(name);
17968 }
17969 if (!renderer.binding_groups.has(keypath)) {
17970 const index = renderer.binding_groups.size;
17971 contexts.forEach(context => {
17972 renderer.add_to_context(context, true);
17973 });
17974 renderer.binding_groups.set(keypath, {
17975 binding_group: (to_reference = false) => {
17976 let binding_group = '$$binding_groups';
17977 let _secondary_indexes = contexts;
17978 if (to_reference) {
17979 binding_group = block.renderer.reference(binding_group);
17980 _secondary_indexes = _secondary_indexes.map(name => block.renderer.reference(name));
17981 }
17982 if (_secondary_indexes.length > 0) {
17983 let obj = x `${binding_group}[${index}]`;
17984 _secondary_indexes.forEach(secondary_index => {
17985 obj = x `${obj}[${secondary_index}]`;
17986 });
17987 return obj;
17988 }
17989 else {
17990 return x `${binding_group}[${index}]`;
17991 }
17992 },
17993 is_context: contexts.length > 0,
17994 contexts,
17995 index,
17996 keypath
17997 });
17998 }
17999 return renderer.binding_groups.get(keypath);
18000 }
18001 function get_event_handler(binding, renderer, block, name, lhs) {
18002 const contextual_dependencies = new Set(binding.node.expression.contextual_dependencies);
18003 const context = block.bindings.get(name);
18004 let set_store;
18005 if (context) {
18006 const { object, property, store, snippet } = context;
18007 lhs = replace_object(lhs, snippet);
18008 contextual_dependencies.add(object.name);
18009 contextual_dependencies.add(property.name);
18010 contextual_dependencies.delete(name);
18011 if (store) {
18012 set_store = b `${store}.set(${`$${store}`});`;
18013 }
18014 }
18015 else {
18016 const object = get_object(lhs);
18017 if (object.name[0] === '$') {
18018 const store = object.name.slice(1);
18019 set_store = b `${store}.set(${object.name});`;
18020 }
18021 }
18022 const value = get_value_from_dom(renderer, binding.parent, binding, block, contextual_dependencies);
18023 const mutation = b `
18024 ${lhs} = ${value};
18025 ${set_store}
18026 `;
18027 return {
18028 uses_context: binding.node.is_contextual || binding.node.expression.uses_context,
18029 mutation,
18030 contextual_dependencies,
18031 lhs
18032 };
18033 }
18034 function get_value_from_dom(renderer, element, binding, block, contextual_dependencies) {
18035 const { node } = element;
18036 const { name } = binding.node;
18037 if (name === 'this') {
18038 return x `$$value`;
18039 }
18040 // <select bind:value='selected>
18041 if (node.name === 'select') {
18042 return node.get_static_attribute_value('multiple') === true ?
18043 x `@select_multiple_value(this)` :
18044 x `@select_value(this)`;
18045 }
18046 const type = node.get_static_attribute_value('type');
18047 // <input type='checkbox' bind:group='foo'>
18048 if (name === 'group') {
18049 if (type === 'checkbox') {
18050 const { binding_group, contexts } = get_binding_group(renderer, binding.node, block);
18051 add_to_set(contextual_dependencies, contexts);
18052 return x `@get_binding_group_value(${binding_group()}, this.__value, this.checked)`;
18053 }
18054 return x `this.__value`;
18055 }
18056 // <input type='range|number' bind:value>
18057 if (type === 'range' || type === 'number') {
18058 return x `@to_number(this.${name})`;
18059 }
18060 if ((name === 'buffered' || name === 'seekable' || name === 'played')) {
18061 return x `@time_ranges_to_array(this.${name})`;
18062 }
18063 // everything else
18064 return x `this.${name}`;
18065 }
18066
18067 const reserved_keywords = new Set(['$$props', '$$restProps', '$$slots']);
18068 function is_reserved_keyword(name) {
18069 return reserved_keywords.has(name);
18070 }
18071
18072 function is_contextual(component, scope, name) {
18073 if (is_reserved_keyword(name))
18074 return true;
18075 // if it's a name below root scope, it's contextual
18076 if (!scope.is_top_level(name))
18077 return true;
18078 const variable = component.var_lookup.get(name);
18079 // hoistables, module declarations, and imports are non-contextual
18080 if (!variable || variable.hoistable)
18081 return false;
18082 // assume contextual
18083 return true;
18084 }
18085
18086 function add_actions(block, target, actions) {
18087 actions.forEach(action => add_action(block, target, action));
18088 }
18089 function add_action(block, target, action) {
18090 const { expression, template_scope } = action;
18091 let snippet;
18092 let dependencies;
18093 if (expression) {
18094 snippet = expression.manipulate(block);
18095 dependencies = expression.dynamic_dependencies();
18096 }
18097 const id = block.get_unique_name(`${action.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action`);
18098 block.add_variable(id);
18099 const [obj, ...properties] = action.name.split('.');
18100 const fn = is_contextual(action.component, template_scope, obj)
18101 ? block.renderer.reference(obj)
18102 : obj;
18103 if (properties.length) {
18104 const member_expression = properties.reduce((lhs, rhs) => x `${lhs}.${rhs}`, fn);
18105 block.event_listeners.push(x `@action_destroyer(${id} = ${member_expression}(${target}, ${snippet}))`);
18106 }
18107 else {
18108 block.event_listeners.push(x `@action_destroyer(${id} = ${fn}.call(null, ${target}, ${snippet}))`);
18109 }
18110 if (dependencies && dependencies.length > 0) {
18111 let condition = x `${id} && @is_function(${id}.update)`;
18112 if (dependencies.length > 0) {
18113 condition = x `${condition} && ${block.renderer.dirty(dependencies)}`;
18114 }
18115 block.chunks.update.push(b `if (${condition}) ${id}.update.call(null, ${snippet});`);
18116 }
18117 }
18118
18119 function compare_node(a, b) {
18120 if (a === b)
18121 return true;
18122 if (!a || !b)
18123 return false;
18124 if (a.type !== b.type)
18125 return false;
18126 switch (a.type) {
18127 case 'Identifier':
18128 return a.name === b.name;
18129 case 'MemberExpression':
18130 return (compare_node(a.object, b.object) &&
18131 compare_node(a.property, b.property) &&
18132 a.computed === b.computed);
18133 case 'Literal':
18134 return a.value === b.value;
18135 }
18136 }
18137
18138 function bind_this(component, block, binding, variable) {
18139 const fn = component.get_unique_name(`${variable.name}_binding`);
18140 block.renderer.add_to_context(fn.name);
18141 const callee = block.renderer.reference(fn.name);
18142 const { contextual_dependencies, mutation } = binding.handler;
18143 const dependencies = binding.get_dependencies();
18144 const body = b `
18145 ${mutation}
18146 ${Array.from(dependencies)
18147 .filter(dep => dep[0] !== '$')
18148 .filter(dep => !contextual_dependencies.has(dep))
18149 .map(dep => b `${block.renderer.invalidate(dep)};`)}
18150 `;
18151 if (contextual_dependencies.size) {
18152 const params = Array.from(contextual_dependencies).map(name => ({
18153 type: 'Identifier',
18154 name
18155 }));
18156 component.partly_hoisted.push(b `
18157 function ${fn}($$value, ${params}) {
18158 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
18159 ${body}
18160 });
18161 }
18162 `);
18163 const alias_map = new Map();
18164 const args = [];
18165 for (let id of params) {
18166 const value = block.renderer.reference(id.name);
18167 let found = false;
18168 if (block.variables.has(id.name)) {
18169 let alias = id.name;
18170 for (let i = 1; block.variables.has(alias) && !compare_node(block.variables.get(alias).init, value); alias = `${id.name}_${i++}`)
18171 ;
18172 alias_map.set(alias, id.name);
18173 id = { type: 'Identifier', name: alias };
18174 found = block.variables.has(alias);
18175 }
18176 args.push(id);
18177 if (!found) {
18178 block.add_variable(id, value);
18179 }
18180 }
18181 const assign = block.get_unique_name(`assign_${variable.name}`);
18182 const unassign = block.get_unique_name(`unassign_${variable.name}`);
18183 block.chunks.init.push(b `
18184 const ${assign} = () => ${callee}(${variable}, ${args});
18185 const ${unassign} = () => ${callee}(null, ${args});
18186 `);
18187 const condition = Array.from(args)
18188 .map(name => x `${name} !== ${block.renderer.reference(alias_map.get(name.name) || name.name)}`)
18189 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
18190 // we push unassign and unshift assign so that references are
18191 // nulled out before they're created, to avoid glitches
18192 // with shifting indices
18193 block.chunks.update.push(b `
18194 if (${condition}) {
18195 ${unassign}();
18196 ${args.map(a => b `${a} = ${block.renderer.reference(alias_map.get(a.name) || a.name)}`)};
18197 ${assign}();
18198 }`);
18199 block.chunks.destroy.push(b `${unassign}();`);
18200 return b `${assign}();`;
18201 }
18202 component.partly_hoisted.push(b `
18203 function ${fn}($$value) {
18204 @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
18205 ${body}
18206 });
18207 }
18208 `);
18209 block.chunks.destroy.push(b `${callee}(null);`);
18210 return b `${callee}(${variable});`;
18211 }
18212
18213 class Node$1 {
18214 constructor(component, parent, _scope, info) {
18215 this.start = info.start;
18216 this.end = info.end;
18217 this.type = info.type;
18218 // this makes properties non-enumerable, which makes logging
18219 // bearable. might have a performance cost. TODO remove in prod?
18220 Object.defineProperties(this, {
18221 component: {
18222 value: component
18223 },
18224 parent: {
18225 value: parent
18226 }
18227 });
18228 }
18229 cannot_use_innerhtml() {
18230 if (this.can_use_innerhtml !== false) {
18231 this.can_use_innerhtml = false;
18232 if (this.parent)
18233 this.parent.cannot_use_innerhtml();
18234 }
18235 }
18236 find_nearest(selector) {
18237 if (selector.test(this.type))
18238 return this;
18239 if (this.parent)
18240 return this.parent.find_nearest(selector);
18241 }
18242 get_static_attribute_value(name) {
18243 const attribute = this.attributes && this.attributes.find((attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === name);
18244 if (!attribute)
18245 return null;
18246 if (attribute.is_true)
18247 return true;
18248 if (attribute.chunks.length === 0)
18249 return '';
18250 if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
18251 return attribute.chunks[0].data;
18252 }
18253 return null;
18254 }
18255 has_ancestor(type) {
18256 return this.parent ?
18257 this.parent.type === type || this.parent.has_ancestor(type) :
18258 false;
18259 }
18260 }
18261
18262 function create_scopes(expression) {
18263 return analyze(expression);
18264 }
18265
18266 function is_dynamic$1(variable) {
18267 if (variable) {
18268 if (variable.mutated || variable.reassigned)
18269 return true; // dynamic internal state
18270 if (!variable.module && variable.writable && variable.export_name)
18271 return true; // writable props
18272 if (is_reserved_keyword(variable.name))
18273 return true;
18274 }
18275 return false;
18276 }
18277
18278 function nodes_match(a, b) {
18279 if (!!a !== !!b)
18280 return false;
18281 if (Array.isArray(a) !== Array.isArray(b))
18282 return false;
18283 if (a && typeof a === 'object') {
18284 if (Array.isArray(a)) {
18285 if (a.length !== b.length)
18286 return false;
18287 return a.every((child, i) => nodes_match(child, b[i]));
18288 }
18289 const a_keys = Object.keys(a).sort();
18290 const b_keys = Object.keys(b).sort();
18291 if (a_keys.length !== b_keys.length)
18292 return false;
18293 let i = a_keys.length;
18294 while (i--) {
18295 const key = a_keys[i];
18296 if (b_keys[i] !== key)
18297 return false;
18298 if (key === 'start' || key === 'end')
18299 continue;
18300 if (!nodes_match(a[key], b[key])) {
18301 return false;
18302 }
18303 }
18304 return true;
18305 }
18306 return a === b;
18307 }
18308
18309 function invalidate(renderer, scope, node, names, main_execution_context = false) {
18310 const { component } = renderer;
18311 const [head, ...tail] = Array.from(names)
18312 .filter(name => {
18313 const owner = scope.find_owner(name);
18314 return !owner || owner === component.instance_scope;
18315 })
18316 .map(name => component.var_lookup.get(name))
18317 .filter(variable => {
18318 return variable && (!variable.hoistable &&
18319 !variable.global &&
18320 !variable.module &&
18321 (variable.referenced ||
18322 variable.subscribable ||
18323 variable.is_reactive_dependency ||
18324 variable.export_name ||
18325 variable.name[0] === '$'));
18326 });
18327 function get_invalidated(variable, node) {
18328 if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') {
18329 return node;
18330 }
18331 return renderer_invalidate(renderer, variable.name, undefined, main_execution_context);
18332 }
18333 if (!head) {
18334 return node;
18335 }
18336 component.has_reactive_assignments = true;
18337 if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) {
18338 return get_invalidated(head, node);
18339 }
18340 const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
18341 const extra_args = tail.map(variable => get_invalidated(variable)).filter(Boolean);
18342 if (is_store_value) {
18343 return x `@set_store_value(${head.name.slice(1)}, ${node}, ${head.name}, ${extra_args})`;
18344 }
18345 let invalidate;
18346 if (!main_execution_context) {
18347 const pass_value = (extra_args.length > 0 ||
18348 (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
18349 (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier')));
18350 if (pass_value) {
18351 extra_args.unshift({
18352 type: 'Identifier',
18353 name: head.name
18354 });
18355 }
18356 invalidate = x `$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`;
18357 }
18358 else {
18359 // skip `$$invalidate` if it is in the main execution context
18360 invalidate = extra_args.length ? [node, ...extra_args] : node;
18361 }
18362 if (head.subscribable && head.reassigned) {
18363 const subscribe = `$$subscribe_${head.name}`;
18364 invalidate = x `${subscribe}(${invalidate})`;
18365 }
18366 return invalidate;
18367 }
18368 function renderer_invalidate(renderer, name, value, main_execution_context = false) {
18369 const variable = renderer.component.var_lookup.get(name);
18370 if (variable && (variable.subscribable && (variable.reassigned || variable.export_name))) {
18371 if (main_execution_context) {
18372 return x `${`$$subscribe_${name}`}(${value || name})`;
18373 }
18374 else {
18375 const member = renderer.context_lookup.get(name);
18376 return x `${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
18377 }
18378 }
18379 if (name[0] === '$' && name[1] !== '$') {
18380 return x `${name.slice(1)}.set(${value || name})`;
18381 }
18382 if (variable && (variable.module || (!variable.referenced &&
18383 !variable.is_reactive_dependency &&
18384 !variable.export_name &&
18385 !name.startsWith('$$')))) {
18386 return value || name;
18387 }
18388 if (value) {
18389 if (main_execution_context) {
18390 return x `${value}`;
18391 }
18392 else {
18393 const member = renderer.context_lookup.get(name);
18394 return x `$$invalidate(${member.index}, ${value})`;
18395 }
18396 }
18397 if (main_execution_context)
18398 return;
18399 // if this is a reactive declaration, invalidate dependencies recursively
18400 const deps = new Set([name]);
18401 deps.forEach(name => {
18402 const reactive_declarations = renderer.component.reactive_declarations.filter(x => x.assignees.has(name));
18403 reactive_declarations.forEach(declaration => {
18404 declaration.dependencies.forEach(name => {
18405 deps.add(name);
18406 });
18407 });
18408 });
18409 // TODO ideally globals etc wouldn't be here in the first place
18410 const filtered = Array.from(deps).filter(n => renderer.context_lookup.has(n));
18411 if (!filtered.length)
18412 return null;
18413 return filtered
18414 .map(n => x `$$invalidate(${renderer.context_lookup.get(n).index}, ${n})`)
18415 .reduce((lhs, rhs) => x `${lhs}, ${rhs}`);
18416 }
18417
18418 class Expression {
18419 constructor(component, owner, template_scope, info, lazy) {
18420 this.type = 'Expression';
18421 this.references = new Set();
18422 this.dependencies = new Set();
18423 this.contextual_dependencies = new Set();
18424 this.declarations = [];
18425 this.uses_context = false;
18426 // TODO revert to direct property access in prod?
18427 Object.defineProperties(this, {
18428 component: {
18429 value: component
18430 }
18431 });
18432 this.node = info;
18433 this.template_scope = template_scope;
18434 this.owner = owner;
18435 const { dependencies, contextual_dependencies, references } = this;
18436 let { map, scope } = create_scopes(info);
18437 this.scope = scope;
18438 this.scope_map = map;
18439 const expression = this;
18440 let function_expression;
18441 // discover dependencies, but don't change the code yet
18442 walk(info, {
18443 enter(node, parent, key) {
18444 // don't manipulate shorthand props twice
18445 if (key === 'value' && parent.shorthand)
18446 return;
18447 // don't manipulate `import.meta`, `new.target`
18448 if (node.type === 'MetaProperty')
18449 return this.skip();
18450 if (map.has(node)) {
18451 scope = map.get(node);
18452 }
18453 if (!function_expression && /FunctionExpression/.test(node.type)) {
18454 function_expression = node;
18455 }
18456 if (isReference(node, parent)) {
18457 const { name, nodes } = flatten_reference(node);
18458 references.add(name);
18459 if (scope.has(name))
18460 return;
18461 if (name[0] === '$') {
18462 const store_name = name.slice(1);
18463 if (template_scope.names.has(store_name) || scope.has(store_name)) {
18464 component.error(node, {
18465 code: 'contextual-store',
18466 message: 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
18467 });
18468 }
18469 }
18470 if (template_scope.is_let(name)) {
18471 if (!function_expression) { // TODO should this be `!lazy` ?
18472 contextual_dependencies.add(name);
18473 dependencies.add(name);
18474 }
18475 }
18476 else if (template_scope.names.has(name)) {
18477 expression.uses_context = true;
18478 contextual_dependencies.add(name);
18479 const owner = template_scope.get_owner(name);
18480 const is_index = owner.type === 'EachBlock' && owner.key && name === owner.index;
18481 if (!lazy || is_index) {
18482 template_scope.dependencies_for_name.get(name).forEach(name => dependencies.add(name));
18483 }
18484 }
18485 else {
18486 if (!lazy) {
18487 dependencies.add(name);
18488 }
18489 component.add_reference(name);
18490 component.warn_if_undefined(name, nodes[0], template_scope);
18491 }
18492 this.skip();
18493 }
18494 // track any assignments from template expressions as mutable
18495 let names;
18496 let deep = false;
18497 if (function_expression) {
18498 if (node.type === 'AssignmentExpression') {
18499 deep = node.left.type === 'MemberExpression';
18500 names = extract_names(deep ? get_object(node.left) : node.left);
18501 }
18502 else if (node.type === 'UpdateExpression') {
18503 names = extract_names(get_object(node.argument));
18504 }
18505 }
18506 if (names) {
18507 names.forEach(name => {
18508 if (template_scope.names.has(name)) {
18509 template_scope.dependencies_for_name.get(name).forEach(name => {
18510 const variable = component.var_lookup.get(name);
18511 if (variable)
18512 variable[deep ? 'mutated' : 'reassigned'] = true;
18513 });
18514 const each_block = template_scope.get_owner(name);
18515 each_block.has_binding = true;
18516 }
18517 else {
18518 component.add_reference(name);
18519 const variable = component.var_lookup.get(name);
18520 if (variable)
18521 variable[deep ? 'mutated' : 'reassigned'] = true;
18522 }
18523 });
18524 }
18525 },
18526 leave(node) {
18527 if (map.has(node)) {
18528 scope = scope.parent;
18529 }
18530 if (node === function_expression) {
18531 function_expression = null;
18532 }
18533 }
18534 });
18535 }
18536 dynamic_dependencies() {
18537 return Array.from(this.dependencies).filter(name => {
18538 if (this.template_scope.is_let(name))
18539 return true;
18540 if (is_reserved_keyword(name))
18541 return true;
18542 const variable = this.component.var_lookup.get(name);
18543 return is_dynamic$1(variable);
18544 });
18545 }
18546 // TODO move this into a render-dom wrapper?
18547 manipulate(block) {
18548 // TODO ideally we wouldn't end up calling this method
18549 // multiple times
18550 if (this.manipulated)
18551 return this.manipulated;
18552 const { component, declarations, scope_map: map, template_scope, owner } = this;
18553 let scope = this.scope;
18554 let function_expression;
18555 let dependencies;
18556 let contextual_dependencies;
18557 const node = walk(this.node, {
18558 enter(node, parent) {
18559 if (node.type === 'Property' && node.shorthand) {
18560 node.value = JSON.parse(JSON.stringify(node.value));
18561 node.shorthand = false;
18562 }
18563 if (map.has(node)) {
18564 scope = map.get(node);
18565 }
18566 if (node.type === 'Identifier' && isReference(node, parent)) {
18567 const { name } = flatten_reference(node);
18568 if (scope.has(name))
18569 return;
18570 if (function_expression) {
18571 if (template_scope.names.has(name)) {
18572 contextual_dependencies.add(name);
18573 template_scope.dependencies_for_name.get(name).forEach(dependency => {
18574 dependencies.add(dependency);
18575 });
18576 }
18577 else {
18578 dependencies.add(name);
18579 component.add_reference(name); // TODO is this redundant/misplaced?
18580 }
18581 }
18582 else if (is_contextual(component, template_scope, name)) {
18583 const reference = block.renderer.reference(node);
18584 this.replace(reference);
18585 }
18586 this.skip();
18587 }
18588 if (!function_expression) {
18589 if (node.type === 'AssignmentExpression') ;
18590 if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
18591 function_expression = node;
18592 dependencies = new Set();
18593 contextual_dependencies = new Set();
18594 }
18595 }
18596 },
18597 leave(node, parent) {
18598 if (map.has(node))
18599 scope = scope.parent;
18600 if (node === function_expression) {
18601 const id = component.get_unique_name(sanitize(get_function_name(node, owner)));
18602 const declaration = b `const ${id} = ${node}`;
18603 if (dependencies.size === 0 && contextual_dependencies.size === 0) {
18604 // we can hoist this out of the component completely
18605 component.fully_hoisted.push(declaration);
18606 this.replace(id);
18607 component.add_var({
18608 name: id.name,
18609 internal: true,
18610 hoistable: true,
18611 referenced: true
18612 });
18613 }
18614 else if (contextual_dependencies.size === 0) {
18615 // function can be hoisted inside the component init
18616 component.partly_hoisted.push(declaration);
18617 block.renderer.add_to_context(id.name);
18618 this.replace(block.renderer.reference(id));
18619 }
18620 else {
18621 // we need a combo block/init recipe
18622 const deps = Array.from(contextual_dependencies);
18623 const function_expression = node;
18624 const has_args = function_expression.params.length > 0;
18625 function_expression.params = [
18626 ...deps.map(name => ({ type: 'Identifier', name })),
18627 ...function_expression.params
18628 ];
18629 const context_args = deps.map(name => block.renderer.reference(name));
18630 component.partly_hoisted.push(declaration);
18631 block.renderer.add_to_context(id.name);
18632 const callee = block.renderer.reference(id);
18633 this.replace(id);
18634 const func_declaration = has_args
18635 ? b `function ${id}(...args) {
18636 return ${callee}(${context_args}, ...args);
18637 }`
18638 : b `function ${id}() {
18639 return ${callee}(${context_args});
18640 }`;
18641 if (owner.type === 'Attribute' && owner.parent.name === 'slot') {
18642 const dep_scopes = new Set(deps.map(name => template_scope.get_owner(name)));
18643 // find the nearest scopes
18644 let node = owner.parent;
18645 while (node && !dep_scopes.has(node)) {
18646 node = node.parent;
18647 }
18648 const func_expression = func_declaration[0];
18649 if (node.type === 'InlineComponent') {
18650 // <Comp let:data />
18651 this.replace(func_expression);
18652 }
18653 else {
18654 // {#each}, {#await}
18655 const func_id = component.get_unique_name(id.name + '_func');
18656 block.renderer.add_to_context(func_id.name, true);
18657 // rename #ctx -> child_ctx;
18658 walk(func_expression, {
18659 enter(node) {
18660 if (node.type === 'Identifier' && node.name === '#ctx') {
18661 node.name = 'child_ctx';
18662 }
18663 }
18664 });
18665 // add to get_xxx_context
18666 // child_ctx[x] = function () { ... }
18667 template_scope.get_owner(deps[0]).contexts.push({
18668 key: func_id,
18669 modifier: () => func_expression
18670 });
18671 this.replace(block.renderer.reference(func_id));
18672 }
18673 }
18674 else {
18675 declarations.push(func_declaration);
18676 }
18677 }
18678 function_expression = null;
18679 dependencies = null;
18680 contextual_dependencies = null;
18681 if (parent && parent.type === 'Property') {
18682 parent.method = false;
18683 }
18684 }
18685 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
18686 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
18687 const object_name = get_object(assignee).name;
18688 if (scope.has(object_name))
18689 return;
18690 // normally (`a = 1`, `b.c = 2`), there'll be a single name
18691 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
18692 // may be more, in which case we need to tack the extra ones
18693 // onto the initial function call
18694 const names = new Set(extract_names(assignee));
18695 const traced = new Set();
18696 names.forEach(name => {
18697 const dependencies = template_scope.dependencies_for_name.get(name);
18698 if (dependencies) {
18699 dependencies.forEach(name => traced.add(name));
18700 }
18701 else {
18702 traced.add(name);
18703 }
18704 });
18705 const context = block.bindings.get(object_name);
18706 if (context) {
18707 // for `{#each array as item}`
18708 // replace `item = 1` to `each_array[each_index] = 1`, this allow us to mutate the array
18709 // rather than mutating the local `item` variable
18710 const { snippet, object, property } = context;
18711 const replaced = replace_object(assignee, snippet);
18712 if (node.type === 'AssignmentExpression') {
18713 node.left = replaced;
18714 }
18715 else {
18716 node.argument = replaced;
18717 }
18718 contextual_dependencies.add(object.name);
18719 contextual_dependencies.add(property.name);
18720 }
18721 this.replace(invalidate(block.renderer, scope, node, traced));
18722 }
18723 }
18724 });
18725 if (declarations.length > 0) {
18726 block.maintain_context = true;
18727 declarations.forEach(declaration => {
18728 block.chunks.init.push(declaration);
18729 });
18730 }
18731 return (this.manipulated = node);
18732 }
18733 }
18734 function get_function_name(_node, parent) {
18735 if (parent.type === 'EventHandler') {
18736 return `${parent.name}_handler`;
18737 }
18738 if (parent.type === 'Action') {
18739 return `${parent.name}_function`;
18740 }
18741 return 'func';
18742 }
18743
18744 class Action extends Node$1 {
18745 constructor(component, parent, scope, info) {
18746 super(component, parent, scope, info);
18747 const object = info.name.split('.')[0];
18748 component.warn_if_undefined(object, info, scope);
18749 this.name = info.name;
18750 component.add_reference(object);
18751 this.expression = info.expression
18752 ? new Expression(component, this, scope, info.expression)
18753 : null;
18754 this.template_scope = scope;
18755 this.uses_context = this.expression && this.expression.uses_context;
18756 }
18757 }
18758
18759 class Tag extends Wrapper {
18760 constructor(renderer, block, parent, node) {
18761 super(renderer, block, parent, node);
18762 this.cannot_use_innerhtml();
18763 if (!this.is_dependencies_static()) {
18764 this.not_static_content();
18765 }
18766 block.add_dependencies(node.expression.dependencies);
18767 }
18768 is_dependencies_static() {
18769 return this.node.expression.contextual_dependencies.size === 0 && this.node.expression.dynamic_dependencies().length === 0;
18770 }
18771 rename_this_method(block, update) {
18772 const dependencies = this.node.expression.dynamic_dependencies();
18773 let snippet = this.node.expression.manipulate(block);
18774 const value = this.node.should_cache && block.get_unique_name(`${this.var.name}_value`);
18775 const content = this.node.should_cache ? value : snippet;
18776 snippet = x `${snippet} + ""`;
18777 if (this.node.should_cache)
18778 block.add_variable(value, snippet); // TODO may need to coerce snippet to string
18779 if (dependencies.length > 0) {
18780 let condition = block.renderer.dirty(dependencies);
18781 if (block.has_outros) {
18782 condition = x `!#current || ${condition}`;
18783 }
18784 const update_cached_value = x `${value} !== (${value} = ${snippet})`;
18785 if (this.node.should_cache) {
18786 condition = x `${condition} && ${update_cached_value}`;
18787 }
18788 block.chunks.update.push(b `if (${condition}) ${update(content)}`);
18789 }
18790 return { init: content };
18791 }
18792 }
18793
18794 class MustacheTagWrapper extends Tag {
18795 constructor(renderer, block, parent, node) {
18796 super(renderer, block, parent, node);
18797 this.var = { type: 'Identifier', name: 't' };
18798 }
18799 render(block, parent_node, parent_nodes) {
18800 const { init } = this.rename_this_method(block, value => x `@set_data(${this.var}, ${value})`);
18801 block.add_element(this.var, x `@text(${init})`, parent_nodes && x `@claim_text(${parent_nodes}, ${init})`, parent_node);
18802 }
18803 }
18804
18805 class RawMustacheTagWrapper extends Tag {
18806 constructor(renderer, block, parent, node) {
18807 super(renderer, block, parent, node);
18808 this.var = { type: 'Identifier', name: 'raw' };
18809 this.cannot_use_innerhtml();
18810 this.not_static_content();
18811 }
18812 render(block, parent_node, _parent_nodes) {
18813 const in_head = is_head(parent_node);
18814 const can_use_innerhtml = !in_head && parent_node && !this.prev && !this.next;
18815 if (can_use_innerhtml) {
18816 const insert = content => b `${parent_node}.innerHTML = ${content};`[0];
18817 const { init } = this.rename_this_method(block, content => insert(content));
18818 block.chunks.mount.push(insert(init));
18819 }
18820 else {
18821 const needs_anchor = in_head || (this.next ? !this.next.is_dom_node() : (!this.parent || !this.parent.is_dom_node()));
18822 const html_tag = block.get_unique_name('html_tag');
18823 const html_anchor = needs_anchor && block.get_unique_name('html_anchor');
18824 block.add_variable(html_tag);
18825 const { init } = this.rename_this_method(block, content => x `${html_tag}.p(${content})`);
18826 const update_anchor = needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
18827 block.chunks.hydrate.push(b `${html_tag} = new @HtmlTag(${update_anchor});`);
18828 block.chunks.mount.push(b `${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`);
18829 if (needs_anchor) {
18830 block.add_element(html_anchor, x `@empty()`, x `@empty()`, parent_node);
18831 }
18832 if (!parent_node || in_head) {
18833 block.chunks.destroy.push(b `if (detaching) ${html_tag}.d();`);
18834 }
18835 }
18836 }
18837 }
18838
18839 function get_slot_definition(block, scope, lets) {
18840 if (lets.length === 0)
18841 return { block, scope };
18842 const context_input = {
18843 type: 'ObjectPattern',
18844 properties: lets.map(l => ({
18845 type: 'Property',
18846 kind: 'init',
18847 key: l.name,
18848 value: l.value || l.name
18849 }))
18850 };
18851 const properties = [];
18852 const value_map = new Map();
18853 lets.forEach(l => {
18854 let value;
18855 if (l.names.length > 1) {
18856 // more than one, probably destructuring
18857 const unique_name = block.get_unique_name(l.names.join('_')).name;
18858 value_map.set(l.value, unique_name);
18859 value = { type: 'Identifier', name: unique_name };
18860 }
18861 else {
18862 value = l.value || l.name;
18863 }
18864 properties.push({
18865 type: 'Property',
18866 kind: 'init',
18867 key: l.name,
18868 value
18869 });
18870 });
18871 const changes_input = {
18872 type: 'ObjectPattern',
18873 properties
18874 };
18875 const names = new Set();
18876 const names_lookup = new Map();
18877 lets.forEach(l => {
18878 l.names.forEach(name => {
18879 names.add(name);
18880 if (value_map.has(l.value)) {
18881 names_lookup.set(name, value_map.get(l.value));
18882 }
18883 });
18884 });
18885 const context = {
18886 type: 'ObjectExpression',
18887 properties: Array.from(names).map(name => p `${block.renderer.context_lookup.get(name).index}: ${name}`)
18888 };
18889 const { context_lookup } = block.renderer;
18890 // i am well aware that this code is gross
18891 // TODO: context-overflow make it less gross
18892 const changes = {
18893 type: 'ParenthesizedExpression',
18894 get expression() {
18895 if (block.renderer.context_overflow) {
18896 const grouped = [];
18897 Array.from(names).forEach(name => {
18898 const i = context_lookup.get(name).index.value;
18899 const g = Math.floor(i / 31);
18900 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
18901 if (!grouped[g])
18902 grouped[g] = [];
18903 grouped[g].push({ name: lookup_name, n: i % 31 });
18904 });
18905 const elements = [];
18906 for (let g = 0; g < grouped.length; g += 1) {
18907 elements[g] = grouped[g]
18908 ? grouped[g]
18909 .map(({ name, n }) => x `${name} ? ${1 << n} : 0`)
18910 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`)
18911 : x `0`;
18912 }
18913 return {
18914 type: 'ArrayExpression',
18915 elements
18916 };
18917 }
18918 return Array.from(names)
18919 .map(name => {
18920 const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
18921 const i = context_lookup.get(name).index.value;
18922 return x `${lookup_name} ? ${1 << i} : 0`;
18923 })
18924 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
18925 }
18926 };
18927 return {
18928 block,
18929 scope,
18930 get_context: x `${context_input} => ${context}`,
18931 get_changes: x `${changes_input} => ${changes}`
18932 };
18933 }
18934
18935 function create_slot_block(attribute, element, block) {
18936 const owner = find_slot_owner(element.parent);
18937 if (owner && owner.node.type === 'InlineComponent') {
18938 const name = attribute.get_static_value();
18939 if (!owner.slots.has(name)) {
18940 const child_block = block.child({
18941 comment: create_debugging_comment(element.node, element.renderer.component),
18942 name: element.renderer.component.get_unique_name(`create_${sanitize(name)}_slot`),
18943 type: 'slot'
18944 });
18945 const { scope, lets } = element.node;
18946 const seen = new Set(lets.map(l => l.name.name));
18947 owner.node.lets.forEach(l => {
18948 if (!seen.has(l.name.name))
18949 lets.push(l);
18950 });
18951 owner.slots.set(name, get_slot_definition(child_block, scope, lets));
18952 element.renderer.blocks.push(child_block);
18953 }
18954 element.slot_block = owner.slots.get(name).block;
18955 return element.slot_block;
18956 }
18957 return block;
18958 }
18959 function find_slot_owner(owner) {
18960 while (owner) {
18961 if (owner.node.type === 'InlineComponent') {
18962 break;
18963 }
18964 if (owner.node.type === 'Element' && /-/.test(owner.node.name)) {
18965 break;
18966 }
18967 owner = owner.parent;
18968 }
18969 return owner;
18970 }
18971
18972 const events = [
18973 {
18974 event_names: ['input'],
18975 filter: (node, _name) => node.name === 'textarea' ||
18976 node.name === 'input' && !/radio|checkbox|range|file/.test(node.get_static_attribute_value('type'))
18977 },
18978 {
18979 event_names: ['input'],
18980 filter: (node, name) => (name === 'textContent' || name === 'innerHTML') &&
18981 node.attributes.some(attribute => attribute.name === 'contenteditable')
18982 },
18983 {
18984 event_names: ['change'],
18985 filter: (node, _name) => node.name === 'select' ||
18986 node.name === 'input' && /radio|checkbox|file/.test(node.get_static_attribute_value('type'))
18987 },
18988 {
18989 event_names: ['change', 'input'],
18990 filter: (node, _name) => node.name === 'input' && node.get_static_attribute_value('type') === 'range'
18991 },
18992 {
18993 event_names: ['elementresize'],
18994 filter: (_node, name) => dimensions.test(name)
18995 },
18996 // media events
18997 {
18998 event_names: ['timeupdate'],
18999 filter: (node, name) => node.is_media_node() &&
19000 (name === 'currentTime' || name === 'played' || name === 'ended')
19001 },
19002 {
19003 event_names: ['durationchange'],
19004 filter: (node, name) => node.is_media_node() &&
19005 name === 'duration'
19006 },
19007 {
19008 event_names: ['play', 'pause'],
19009 filter: (node, name) => node.is_media_node() &&
19010 name === 'paused'
19011 },
19012 {
19013 event_names: ['progress'],
19014 filter: (node, name) => node.is_media_node() &&
19015 name === 'buffered'
19016 },
19017 {
19018 event_names: ['loadedmetadata'],
19019 filter: (node, name) => node.is_media_node() &&
19020 (name === 'buffered' || name === 'seekable')
19021 },
19022 {
19023 event_names: ['volumechange'],
19024 filter: (node, name) => node.is_media_node() &&
19025 (name === 'volume' || name === 'muted')
19026 },
19027 {
19028 event_names: ['ratechange'],
19029 filter: (node, name) => node.is_media_node() &&
19030 name === 'playbackRate'
19031 },
19032 {
19033 event_names: ['seeking', 'seeked'],
19034 filter: (node, name) => node.is_media_node() &&
19035 (name === 'seeking')
19036 },
19037 {
19038 event_names: ['ended'],
19039 filter: (node, name) => node.is_media_node() &&
19040 name === 'ended'
19041 },
19042 {
19043 event_names: ['resize'],
19044 filter: (node, name) => node.is_media_node() &&
19045 (name === 'videoHeight' || name === 'videoWidth')
19046 },
19047 // details event
19048 {
19049 event_names: ['toggle'],
19050 filter: (node, _name) => node.name === 'details'
19051 }
19052 ];
19053 class ElementWrapper extends Wrapper {
19054 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19055 super(renderer, block, parent, node);
19056 this.var = {
19057 type: 'Identifier',
19058 name: node.name.replace(/[^a-zA-Z0-9_$]/g, '_')
19059 };
19060 this.void = is_void(node.name);
19061 this.class_dependencies = [];
19062 if (this.node.children.length) {
19063 this.node.lets.forEach(l => {
19064 extract_names(l.value || l.name).forEach(name => {
19065 renderer.add_to_context(name, true);
19066 });
19067 });
19068 }
19069 this.attributes = this.node.attributes.map(attribute => {
19070 if (attribute.name === 'slot') {
19071 block = create_slot_block(attribute, this, block);
19072 }
19073 if (attribute.name === 'style') {
19074 return new StyleAttributeWrapper(this, block, attribute);
19075 }
19076 if (attribute.type === 'Spread') {
19077 return new SpreadAttributeWrapper(this, block, attribute);
19078 }
19079 return new AttributeWrapper(this, block, attribute);
19080 });
19081 // ordinarily, there'll only be one... but we need to handle
19082 // the rare case where an element can have multiple bindings,
19083 // e.g. <audio bind:paused bind:currentTime>
19084 this.bindings = this.node.bindings.map(binding => new BindingWrapper(block, binding, this));
19085 this.event_handlers = this.node.handlers.map(event_handler => new EventHandlerWrapper(event_handler, this));
19086 if (node.intro || node.outro) {
19087 if (node.intro)
19088 block.add_intro(node.intro.is_local);
19089 if (node.outro)
19090 block.add_outro(node.outro.is_local);
19091 }
19092 if (node.animation) {
19093 block.add_animation();
19094 }
19095 // add directive and handler dependencies
19096 [node.animation, node.outro, ...node.actions, ...node.classes].forEach(directive => {
19097 if (directive && directive.expression) {
19098 block.add_dependencies(directive.expression.dependencies);
19099 }
19100 });
19101 node.handlers.forEach(handler => {
19102 if (handler.expression) {
19103 block.add_dependencies(handler.expression.dependencies);
19104 }
19105 });
19106 if (this.parent) {
19107 if (node.actions.length > 0 ||
19108 node.animation ||
19109 node.bindings.length > 0 ||
19110 node.classes.length > 0 ||
19111 node.intro || node.outro ||
19112 node.handlers.length > 0 ||
19113 this.node.name === 'option' ||
19114 renderer.options.dev) {
19115 this.parent.cannot_use_innerhtml(); // need to use add_location
19116 this.parent.not_static_content();
19117 }
19118 }
19119 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
19120 if (this.slot_block) {
19121 block.parent.add_dependencies(block.dependencies);
19122 // appalling hack
19123 const index = block.parent.wrappers.indexOf(this);
19124 block.parent.wrappers.splice(index, 1);
19125 block.wrappers.push(this);
19126 }
19127 }
19128 render(block, parent_node, parent_nodes) {
19129 const { renderer } = this;
19130 if (this.node.name === 'noscript')
19131 return;
19132 if (this.slot_block) {
19133 block = this.slot_block;
19134 }
19135 const node = this.var;
19136 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
19137 const children = x `@children(${this.node.name === 'template' ? x `${node}.content` : node})`;
19138 block.add_variable(node);
19139 const render_statement = this.get_render_statement(block);
19140 block.chunks.create.push(b `${node} = ${render_statement};`);
19141 if (renderer.options.hydratable) {
19142 if (parent_nodes) {
19143 block.chunks.claim.push(b `
19144 ${node} = ${this.get_claim_statement(parent_nodes)};
19145 `);
19146 if (!this.void && this.node.children.length > 0) {
19147 block.chunks.claim.push(b `
19148 var ${nodes} = ${children};
19149 `);
19150 }
19151 }
19152 else {
19153 block.chunks.claim.push(b `${node} = ${render_statement};`);
19154 }
19155 }
19156 if (parent_node) {
19157 block.chunks.mount.push(b `@append(${parent_node}, ${node});`);
19158 if (is_head(parent_node)) {
19159 block.chunks.destroy.push(b `@detach(${node});`);
19160 }
19161 }
19162 else {
19163 block.chunks.mount.push(b `@insert(#target, ${node}, #anchor);`);
19164 // TODO we eventually need to consider what happens to elements
19165 // that belong to the same outgroup as an outroing element...
19166 block.chunks.destroy.push(b `if (detaching) @detach(${node});`);
19167 }
19168 // insert static children with textContent or innerHTML
19169 const can_use_textcontent = this.can_use_textcontent();
19170 if (!this.node.namespace && (this.can_use_innerhtml || can_use_textcontent) && this.fragment.nodes.length > 0) {
19171 if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
19172 block.chunks.create.push(b `${node}.textContent = ${string_literal(this.fragment.nodes[0].data)};`);
19173 }
19174 else {
19175 const state = {
19176 quasi: {
19177 type: 'TemplateElement',
19178 value: { raw: '' }
19179 }
19180 };
19181 const literal = {
19182 type: 'TemplateLiteral',
19183 expressions: [],
19184 quasis: []
19185 };
19186 const can_use_raw_text = !this.can_use_innerhtml && can_use_textcontent;
19187 to_html(this.fragment.nodes, block, literal, state, can_use_raw_text);
19188 literal.quasis.push(state.quasi);
19189 block.chunks.create.push(b `${node}.${this.can_use_innerhtml ? 'innerHTML' : 'textContent'} = ${literal};`);
19190 }
19191 }
19192 else {
19193 this.fragment.nodes.forEach((child) => {
19194 child.render(block, this.node.name === 'template' ? x `${node}.content` : node, nodes);
19195 });
19196 }
19197 const event_handler_or_binding_uses_context = (this.bindings.some(binding => binding.handler.uses_context) ||
19198 this.node.handlers.some(handler => handler.uses_context) ||
19199 this.node.actions.some(action => action.uses_context));
19200 if (event_handler_or_binding_uses_context) {
19201 block.maintain_context = true;
19202 }
19203 this.add_attributes(block);
19204 this.add_directives_in_order(block);
19205 this.add_transitions(block);
19206 this.add_animation(block);
19207 this.add_classes(block);
19208 this.add_manual_style_scoping(block);
19209 if (nodes && this.renderer.options.hydratable && !this.void) {
19210 block.chunks.claim.push(b `${this.node.children.length > 0 ? nodes : children}.forEach(@detach);`);
19211 }
19212 if (renderer.options.dev) {
19213 const loc = renderer.locate(this.node.start);
19214 block.chunks.hydrate.push(b `@add_location(${this.var}, ${renderer.file_var}, ${loc.line - 1}, ${loc.column}, ${this.node.start});`);
19215 }
19216 }
19217 can_use_textcontent() {
19218 return this.is_static_content && this.fragment.nodes.every(node => node.node.type === 'Text' || node.node.type === 'MustacheTag');
19219 }
19220 get_render_statement(block) {
19221 const { name, namespace } = this.node;
19222 if (namespace === namespaces.svg) {
19223 return x `@svg_element("${name}")`;
19224 }
19225 if (namespace) {
19226 return x `@_document.createElementNS("${namespace}", "${name}")`;
19227 }
19228 const is = this.attributes.find(attr => attr.node.name === 'is');
19229 if (is) {
19230 return x `@element_is("${name}", ${is.render_chunks(block).reduce((lhs, rhs) => x `${lhs} + ${rhs}`)})`;
19231 }
19232 return x `@element("${name}")`;
19233 }
19234 get_claim_statement(nodes) {
19235 const attributes = this.node.attributes
19236 .filter((attr) => attr.type === 'Attribute')
19237 .map((attr) => p `${attr.name}: true`);
19238 const name = this.node.namespace
19239 ? this.node.name
19240 : this.node.name.toUpperCase();
19241 const svg = this.node.namespace === namespaces.svg ? 1 : null;
19242 return x `@claim_element(${nodes}, "${name}", { ${attributes} }, ${svg})`;
19243 }
19244 add_directives_in_order(block) {
19245 const binding_groups = events
19246 .map(event => ({
19247 events: event.event_names,
19248 bindings: this.bindings
19249 .filter(binding => binding.node.name !== 'this')
19250 .filter(binding => event.filter(this.node, binding.node.name))
19251 }))
19252 .filter(group => group.bindings.length);
19253 const this_binding = this.bindings.find(b => b.node.name === 'this');
19254 function getOrder(item) {
19255 if (item instanceof EventHandlerWrapper) {
19256 return item.node.start;
19257 }
19258 else if (item instanceof BindingWrapper) {
19259 return item.node.start;
19260 }
19261 else if (item instanceof Action) {
19262 return item.start;
19263 }
19264 else {
19265 return item.bindings[0].node.start;
19266 }
19267 }
19268 [
19269 ...binding_groups,
19270 ...this.event_handlers,
19271 this_binding,
19272 ...this.node.actions
19273 ]
19274 .filter(Boolean)
19275 .sort((a, b) => getOrder(a) - getOrder(b))
19276 .forEach(item => {
19277 if (item instanceof EventHandlerWrapper) {
19278 add_event_handler(block, this.var, item);
19279 }
19280 else if (item instanceof BindingWrapper) {
19281 this.add_this_binding(block, item);
19282 }
19283 else if (item instanceof Action) {
19284 add_action(block, this.var, item);
19285 }
19286 else {
19287 this.add_bindings(block, item);
19288 }
19289 });
19290 }
19291 add_bindings(block, binding_group) {
19292 const { renderer } = this;
19293 if (binding_group.bindings.length === 0)
19294 return;
19295 renderer.component.has_reactive_assignments = true;
19296 const lock = binding_group.bindings.some(binding => binding.needs_lock) ?
19297 block.get_unique_name(`${this.var.name}_updating`) :
19298 null;
19299 if (lock)
19300 block.add_variable(lock, x `false`);
19301 const handler = renderer.component.get_unique_name(`${this.var.name}_${binding_group.events.join('_')}_handler`);
19302 renderer.add_to_context(handler.name);
19303 // TODO figure out how to handle locks
19304 const needs_lock = binding_group.bindings.some(binding => binding.needs_lock);
19305 const dependencies = new Set();
19306 const contextual_dependencies = new Set();
19307 binding_group.bindings.forEach(binding => {
19308 // TODO this is a mess
19309 add_to_set(dependencies, binding.get_dependencies());
19310 add_to_set(contextual_dependencies, binding.handler.contextual_dependencies);
19311 binding.render(block, lock);
19312 });
19313 // media bindings — awkward special case. The native timeupdate events
19314 // fire too infrequently, so we need to take matters into our
19315 // own hands
19316 let animation_frame;
19317 if (binding_group.events[0] === 'timeupdate') {
19318 animation_frame = block.get_unique_name(`${this.var.name}_animationframe`);
19319 block.add_variable(animation_frame);
19320 }
19321 const has_local_function = contextual_dependencies.size > 0 || needs_lock || animation_frame;
19322 let callee = renderer.reference(handler);
19323 // TODO dry this out — similar code for event handlers and component bindings
19324 if (has_local_function) {
19325 const args = Array.from(contextual_dependencies).map(name => renderer.reference(name));
19326 // need to create a block-local function that calls an instance-level function
19327 if (animation_frame) {
19328 block.chunks.init.push(b `
19329 function ${handler}() {
19330 @_cancelAnimationFrame(${animation_frame});
19331 if (!${this.var}.paused) {
19332 ${animation_frame} = @raf(${handler});
19333 ${needs_lock && b `${lock} = true;`}
19334 }
19335 ${callee}.call(${this.var}, ${args});
19336 }
19337 `);
19338 }
19339 else {
19340 block.chunks.init.push(b `
19341 function ${handler}() {
19342 ${needs_lock && b `${lock} = true;`}
19343 ${callee}.call(${this.var}, ${args});
19344 }
19345 `);
19346 }
19347 callee = handler;
19348 }
19349 const params = Array.from(contextual_dependencies).map(name => ({
19350 type: 'Identifier',
19351 name
19352 }));
19353 this.renderer.component.partly_hoisted.push(b `
19354 function ${handler}(${params}) {
19355 ${binding_group.bindings.map(b => b.handler.mutation)}
19356 ${Array.from(dependencies)
19357 .filter(dep => dep[0] !== '$')
19358 .filter(dep => !contextual_dependencies.has(dep))
19359 .map(dep => b `${this.renderer.invalidate(dep)};`)}
19360 }
19361 `);
19362 binding_group.events.forEach(name => {
19363 if (name === 'elementresize') {
19364 // special case
19365 const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`);
19366 block.add_variable(resize_listener);
19367 block.chunks.mount.push(b `${resize_listener} = @add_resize_listener(${this.var}, ${callee}.bind(${this.var}));`);
19368 block.chunks.destroy.push(b `${resize_listener}();`);
19369 }
19370 else {
19371 block.event_listeners.push(x `@listen(${this.var}, "${name}", ${callee})`);
19372 }
19373 });
19374 const some_initial_state_is_undefined = binding_group.bindings
19375 .map(binding => x `${binding.snippet} === void 0`)
19376 .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
19377 const should_initialise = (this.node.name === 'select' ||
19378 binding_group.bindings.find(binding => {
19379 return (binding.node.name === 'indeterminate' ||
19380 binding.node.name === 'textContent' ||
19381 binding.node.name === 'innerHTML' ||
19382 binding.is_readonly_media_attribute());
19383 }));
19384 if (should_initialise) {
19385 const callback = has_local_function ? handler : x `() => ${callee}.call(${this.var})`;
19386 block.chunks.hydrate.push(b `if (${some_initial_state_is_undefined}) @add_render_callback(${callback});`);
19387 }
19388 if (binding_group.events[0] === 'elementresize') {
19389 block.chunks.hydrate.push(b `@add_render_callback(() => ${callee}.call(${this.var}));`);
19390 }
19391 if (lock) {
19392 block.chunks.update.push(b `${lock} = false;`);
19393 }
19394 }
19395 add_this_binding(block, this_binding) {
19396 const { renderer } = this;
19397 renderer.component.has_reactive_assignments = true;
19398 const binding_callback = bind_this(renderer.component, block, this_binding, this.var);
19399 block.chunks.mount.push(binding_callback);
19400 }
19401 add_attributes(block) {
19402 // Get all the class dependencies first
19403 this.attributes.forEach((attribute) => {
19404 if (attribute.node.name === 'class') {
19405 const dependencies = attribute.node.get_dependencies();
19406 this.class_dependencies.push(...dependencies);
19407 }
19408 });
19409 if (this.node.attributes.some(attr => attr.is_spread)) {
19410 this.add_spread_attributes(block);
19411 return;
19412 }
19413 this.attributes.forEach((attribute) => {
19414 attribute.render(block);
19415 });
19416 }
19417 add_spread_attributes(block) {
19418 const levels = block.get_unique_name(`${this.var.name}_levels`);
19419 const data = block.get_unique_name(`${this.var.name}_data`);
19420 const initial_props = [];
19421 const updates = [];
19422 this.attributes
19423 .forEach(attr => {
19424 const dependencies = attr.node.get_dependencies();
19425 const condition = dependencies.length > 0
19426 ? block.renderer.dirty(dependencies)
19427 : null;
19428 if (attr instanceof SpreadAttributeWrapper) {
19429 const snippet = attr.node.expression.manipulate(block);
19430 initial_props.push(snippet);
19431 updates.push(condition ? x `${condition} && ${snippet}` : snippet);
19432 }
19433 else {
19434 const name = attr.property_name || attr.name;
19435 initial_props.push(x `{ ${name}: ${attr.get_init(block, attr.get_value(block))} }`);
19436 const snippet = x `{ ${name}: ${attr.should_cache ? attr.last : attr.get_value(block)} }`;
19437 updates.push(condition ? x `${attr.get_dom_update_conditions(block, condition)} && ${snippet}` : snippet);
19438 }
19439 });
19440 block.chunks.init.push(b `
19441 let ${levels} = [${initial_props}];
19442
19443 let ${data} = {};
19444 for (let #i = 0; #i < ${levels}.length; #i += 1) {
19445 ${data} = @assign(${data}, ${levels}[#i]);
19446 }
19447 `);
19448 const fn = this.node.namespace === namespaces.svg ? x `@set_svg_attributes` : x `@set_attributes`;
19449 block.chunks.hydrate.push(b `${fn}(${this.var}, ${data});`);
19450 block.chunks.update.push(b `
19451 ${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
19452 ${updates}
19453 ]));
19454 `);
19455 // handle edge cases for elements
19456 if (this.node.name === 'select') {
19457 const dependencies = new Set();
19458 for (const attr of this.attributes) {
19459 for (const dep of attr.node.dependencies) {
19460 dependencies.add(dep);
19461 }
19462 }
19463 block.chunks.mount.push(b `
19464 if (${data}.multiple) @select_options(${this.var}, ${data}.value);
19465 `);
19466 block.chunks.update.push(b `
19467 if (${block.renderer.dirty(Array.from(dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value);
19468 `);
19469 }
19470 else if (this.node.name === 'input' && this.attributes.find(attr => attr.node.name === 'value')) {
19471 const type = this.node.get_static_attribute_value('type');
19472 if (type === null || type === '' || type === 'text' || type === 'email' || type === 'password') {
19473 block.chunks.mount.push(b `
19474 ${this.var}.value = ${data}.value;
19475 `);
19476 block.chunks.update.push(b `
19477 if ('value' in ${data}) {
19478 ${this.var}.value = ${data}.value;
19479 }
19480 `);
19481 }
19482 }
19483 }
19484 add_transitions(block) {
19485 const { intro, outro } = this.node;
19486 if (!intro && !outro)
19487 return;
19488 if (intro === outro) {
19489 // bidirectional transition
19490 const name = block.get_unique_name(`${this.var.name}_transition`);
19491 const snippet = intro.expression
19492 ? intro.expression.manipulate(block)
19493 : x `{}`;
19494 block.add_variable(name);
19495 const fn = this.renderer.reference(intro.name);
19496 const intro_block = b `
19497 @add_render_callback(() => {
19498 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, true);
19499 ${name}.run(1);
19500 });
19501 `;
19502 const outro_block = b `
19503 if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, false);
19504 ${name}.run(0);
19505 `;
19506 if (intro.is_local) {
19507 block.chunks.intro.push(b `
19508 if (#local) {
19509 ${intro_block}
19510 }
19511 `);
19512 block.chunks.outro.push(b `
19513 if (#local) {
19514 ${outro_block}
19515 }
19516 `);
19517 }
19518 else {
19519 block.chunks.intro.push(intro_block);
19520 block.chunks.outro.push(outro_block);
19521 }
19522 block.chunks.destroy.push(b `if (detaching && ${name}) ${name}.end();`);
19523 }
19524 else {
19525 const intro_name = intro && block.get_unique_name(`${this.var.name}_intro`);
19526 const outro_name = outro && block.get_unique_name(`${this.var.name}_outro`);
19527 if (intro) {
19528 block.add_variable(intro_name);
19529 const snippet = intro.expression
19530 ? intro.expression.manipulate(block)
19531 : x `{}`;
19532 const fn = this.renderer.reference(intro.name);
19533 let intro_block;
19534 if (outro) {
19535 intro_block = b `
19536 @add_render_callback(() => {
19537 if (${outro_name}) ${outro_name}.end(1);
19538 if (!${intro_name}) ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
19539 ${intro_name}.start();
19540 });
19541 `;
19542 block.chunks.outro.push(b `if (${intro_name}) ${intro_name}.invalidate();`);
19543 }
19544 else {
19545 intro_block = b `
19546 if (!${intro_name}) {
19547 @add_render_callback(() => {
19548 ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet});
19549 ${intro_name}.start();
19550 });
19551 }
19552 `;
19553 }
19554 if (intro.is_local) {
19555 intro_block = b `
19556 if (#local) {
19557 ${intro_block}
19558 }
19559 `;
19560 }
19561 block.chunks.intro.push(intro_block);
19562 }
19563 if (outro) {
19564 block.add_variable(outro_name);
19565 const snippet = outro.expression
19566 ? outro.expression.manipulate(block)
19567 : x `{}`;
19568 const fn = this.renderer.reference(outro.name);
19569 if (!intro) {
19570 block.chunks.intro.push(b `
19571 if (${outro_name}) ${outro_name}.end(1);
19572 `);
19573 }
19574 // TODO hide elements that have outro'd (unless they belong to a still-outroing
19575 // group) prior to their removal from the DOM
19576 let outro_block = b `
19577 ${outro_name} = @create_out_transition(${this.var}, ${fn}, ${snippet});
19578 `;
19579 if (outro.is_local) {
19580 outro_block = b `
19581 if (#local) {
19582 ${outro_block}
19583 }
19584 `;
19585 }
19586 block.chunks.outro.push(outro_block);
19587 block.chunks.destroy.push(b `if (detaching && ${outro_name}) ${outro_name}.end();`);
19588 }
19589 }
19590 if ((intro && intro.expression && intro.expression.dependencies.size) || (outro && outro.expression && outro.expression.dependencies.size)) {
19591 block.maintain_context = true;
19592 }
19593 }
19594 add_animation(block) {
19595 if (!this.node.animation)
19596 return;
19597 const { outro } = this.node;
19598 const rect = block.get_unique_name('rect');
19599 const stop_animation = block.get_unique_name('stop_animation');
19600 block.add_variable(rect);
19601 block.add_variable(stop_animation, x `@noop`);
19602 block.chunks.measure.push(b `
19603 ${rect} = ${this.var}.getBoundingClientRect();
19604 `);
19605 block.chunks.fix.push(b `
19606 @fix_position(${this.var});
19607 ${stop_animation}();
19608 ${outro && b `@add_transform(${this.var}, ${rect});`}
19609 `);
19610 let params;
19611 if (this.node.animation.expression) {
19612 params = this.node.animation.expression.manipulate(block);
19613 if (this.node.animation.expression.dynamic_dependencies().length) {
19614 // if `params` is dynamic, calculate params ahead of time in the `.r()` method
19615 const params_var = block.get_unique_name('params');
19616 block.add_variable(params_var);
19617 block.chunks.measure.push(b `${params_var} = ${params};`);
19618 params = params_var;
19619 }
19620 }
19621 else {
19622 params = x `{}`;
19623 }
19624 const name = this.renderer.reference(this.node.animation.name);
19625 block.chunks.animate.push(b `
19626 ${stop_animation}();
19627 ${stop_animation} = @create_animation(${this.var}, ${rect}, ${name}, ${params});
19628 `);
19629 }
19630 add_classes(block) {
19631 const has_spread = this.node.attributes.some(attr => attr.is_spread);
19632 this.node.classes.forEach(class_directive => {
19633 const { expression, name } = class_directive;
19634 let snippet;
19635 let dependencies;
19636 if (expression) {
19637 snippet = expression.manipulate(block);
19638 dependencies = expression.dependencies;
19639 }
19640 else {
19641 snippet = name;
19642 dependencies = new Set([name]);
19643 }
19644 const updater = b `@toggle_class(${this.var}, "${name}", ${snippet});`;
19645 block.chunks.hydrate.push(updater);
19646 if (has_spread) {
19647 block.chunks.update.push(updater);
19648 }
19649 else if ((dependencies && dependencies.size > 0) || this.class_dependencies.length) {
19650 const all_dependencies = this.class_dependencies.concat(...dependencies);
19651 const condition = block.renderer.dirty(all_dependencies);
19652 block.chunks.update.push(b `
19653 if (${condition}) {
19654 ${updater}
19655 }`);
19656 }
19657 });
19658 }
19659 add_manual_style_scoping(block) {
19660 if (this.node.needs_manual_style_scoping) {
19661 const updater = b `@toggle_class(${this.var}, "${this.node.component.stylesheet.id}", true);`;
19662 block.chunks.hydrate.push(updater);
19663 block.chunks.update.push(updater);
19664 }
19665 }
19666 }
19667 function to_html(wrappers, block, literal, state, can_use_raw_text) {
19668 wrappers.forEach(wrapper => {
19669 if (wrapper instanceof TextWrapper) {
19670 if (wrapper.use_space())
19671 state.quasi.value.raw += ' ';
19672 const parent = wrapper.node.parent;
19673 const raw = parent && (parent.name === 'script' ||
19674 parent.name === 'style' ||
19675 can_use_raw_text);
19676 state.quasi.value.raw += (raw ? wrapper.data : escape_html(wrapper.data))
19677 .replace(/\\/g, '\\\\')
19678 .replace(/`/g, '\\`')
19679 .replace(/\$/g, '\\$');
19680 }
19681 else if (wrapper instanceof MustacheTagWrapper || wrapper instanceof RawMustacheTagWrapper) {
19682 literal.quasis.push(state.quasi);
19683 literal.expressions.push(wrapper.node.expression.manipulate(block));
19684 state.quasi = {
19685 type: 'TemplateElement',
19686 value: { raw: '' }
19687 };
19688 }
19689 else if (wrapper.node.name === 'noscript') ;
19690 else {
19691 // element
19692 state.quasi.value.raw += `<${wrapper.node.name}`;
19693 wrapper.attributes.forEach((attr) => {
19694 state.quasi.value.raw += ` ${fix_attribute_casing(attr.node.name)}="`;
19695 attr.node.chunks.forEach(chunk => {
19696 if (chunk.type === 'Text') {
19697 state.quasi.value.raw += escape_html(chunk.data);
19698 }
19699 else {
19700 literal.quasis.push(state.quasi);
19701 literal.expressions.push(chunk.manipulate(block));
19702 state.quasi = {
19703 type: 'TemplateElement',
19704 value: { raw: '' }
19705 };
19706 }
19707 });
19708 state.quasi.value.raw += '"';
19709 });
19710 if (!wrapper.void) {
19711 state.quasi.value.raw += '>';
19712 to_html(wrapper.fragment.nodes, block, literal, state);
19713 state.quasi.value.raw += `</${wrapper.node.name}>`;
19714 }
19715 else {
19716 state.quasi.value.raw += '/>';
19717 }
19718 }
19719 });
19720 }
19721
19722 class HeadWrapper extends Wrapper {
19723 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19724 super(renderer, block, parent, node);
19725 this.can_use_innerhtml = false;
19726 this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling);
19727 }
19728 render(block, _parent_node, _parent_nodes) {
19729 let nodes;
19730 if (this.renderer.options.hydratable && this.fragment.nodes.length) {
19731 nodes = block.get_unique_name('head_nodes');
19732 block.chunks.claim.push(b `const ${nodes} = @query_selector_all('[data-svelte="${this.node.id}"]', @_document.head);`);
19733 }
19734 this.fragment.render(block, x `@_document.head`, nodes);
19735 if (nodes && this.renderer.options.hydratable) {
19736 block.chunks.claim.push(b `${nodes}.forEach(@detach);`);
19737 }
19738 }
19739 }
19740
19741 function is_else_if(node) {
19742 return (node && node.children.length === 1 && node.children[0].type === 'IfBlock');
19743 }
19744 class IfBlockBranch extends Wrapper {
19745 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19746 super(renderer, block, parent, node);
19747 this.var = null;
19748 const { expression } = node;
19749 const is_else = !expression;
19750 if (expression) {
19751 this.dependencies = expression.dynamic_dependencies();
19752 // TODO is this the right rule? or should any non-reference count?
19753 // const should_cache = !is_reference(expression.node, null) && dependencies.length > 0;
19754 let should_cache = false;
19755 walk(expression.node, {
19756 enter(node) {
19757 if (node.type === 'CallExpression' || node.type === 'NewExpression') {
19758 should_cache = true;
19759 }
19760 }
19761 });
19762 if (should_cache) {
19763 this.condition = block.get_unique_name('show_if');
19764 this.snippet = expression.manipulate(block);
19765 }
19766 else {
19767 this.condition = expression.manipulate(block);
19768 }
19769 }
19770 this.block = block.child({
19771 comment: create_debugging_comment(node, parent.renderer.component),
19772 name: parent.renderer.component.get_unique_name(is_else ? 'create_else_block' : 'create_if_block'),
19773 type: node.expression ? 'if' : 'else'
19774 });
19775 this.fragment = new FragmentWrapper(renderer, this.block, node.children, parent, strip_whitespace, next_sibling);
19776 this.is_dynamic = this.block.dependencies.size > 0;
19777 }
19778 }
19779 class IfBlockWrapper extends Wrapper {
19780 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
19781 super(renderer, block, parent, node);
19782 this.needs_update = false;
19783 this.var = { type: 'Identifier', name: 'if_block' };
19784 this.cannot_use_innerhtml();
19785 this.not_static_content();
19786 this.branches = [];
19787 const blocks = [];
19788 let is_dynamic = false;
19789 let has_intros = false;
19790 let has_outros = false;
19791 const create_branches = (node) => {
19792 const branch = new IfBlockBranch(renderer, block, this, node, strip_whitespace, next_sibling);
19793 this.branches.push(branch);
19794 blocks.push(branch.block);
19795 block.add_dependencies(node.expression.dependencies);
19796 if (branch.block.dependencies.size > 0) {
19797 // the condition, or its contents, is dynamic
19798 is_dynamic = true;
19799 block.add_dependencies(branch.block.dependencies);
19800 }
19801 if (branch.dependencies && branch.dependencies.length > 0) {
19802 // the condition itself is dynamic
19803 this.needs_update = true;
19804 }
19805 if (branch.block.has_intros)
19806 has_intros = true;
19807 if (branch.block.has_outros)
19808 has_outros = true;
19809 if (is_else_if(node.else)) {
19810 create_branches(node.else.children[0]);
19811 }
19812 else if (node.else) {
19813 const branch = new IfBlockBranch(renderer, block, this, node.else, strip_whitespace, next_sibling);
19814 this.branches.push(branch);
19815 blocks.push(branch.block);
19816 if (branch.block.dependencies.size > 0) {
19817 is_dynamic = true;
19818 block.add_dependencies(branch.block.dependencies);
19819 }
19820 if (branch.block.has_intros)
19821 has_intros = true;
19822 if (branch.block.has_outros)
19823 has_outros = true;
19824 }
19825 };
19826 create_branches(this.node);
19827 blocks.forEach(block => {
19828 block.has_update_method = is_dynamic;
19829 block.has_intro_method = has_intros;
19830 block.has_outro_method = has_outros;
19831 });
19832 renderer.blocks.push(...blocks);
19833 }
19834 render(block, parent_node, parent_nodes) {
19835 const name = this.var;
19836 const needs_anchor = this.next ? !this.next.is_dom_node() : !parent_node || !this.parent.is_dom_node();
19837 const anchor = needs_anchor
19838 ? block.get_unique_name(`${this.var.name}_anchor`)
19839 : (this.next && this.next.var) || 'null';
19840 const has_else = !(this.branches[this.branches.length - 1].condition);
19841 const if_exists_condition = has_else ? null : name;
19842 const dynamic = this.branches[0].block.has_update_method; // can use [0] as proxy for all, since they necessarily have the same value
19843 const has_intros = this.branches[0].block.has_intro_method;
19844 const has_outros = this.branches[0].block.has_outro_method;
19845 const has_transitions = has_intros || has_outros;
19846 const vars = { name, anchor, if_exists_condition, has_else, has_transitions };
19847 const detaching = parent_node && !is_head(parent_node) ? null : 'detaching';
19848 if (this.node.else) {
19849 this.branches.forEach(branch => {
19850 if (branch.snippet)
19851 block.add_variable(branch.condition);
19852 });
19853 if (has_outros) {
19854 this.render_compound_with_outros(block, parent_node, parent_nodes, dynamic, vars, detaching);
19855 block.chunks.outro.push(b `@transition_out(${name});`);
19856 }
19857 else {
19858 this.render_compound(block, parent_node, parent_nodes, dynamic, vars, detaching);
19859 }
19860 }
19861 else {
19862 this.render_simple(block, parent_node, parent_nodes, dynamic, vars, detaching);
19863 if (has_outros) {
19864 block.chunks.outro.push(b `@transition_out(${name});`);
19865 }
19866 }
19867 if (if_exists_condition) {
19868 block.chunks.create.push(b `if (${if_exists_condition}) ${name}.c();`);
19869 }
19870 else {
19871 block.chunks.create.push(b `${name}.c();`);
19872 }
19873 if (parent_nodes && this.renderer.options.hydratable) {
19874 if (if_exists_condition) {
19875 block.chunks.claim.push(b `if (${if_exists_condition}) ${name}.l(${parent_nodes});`);
19876 }
19877 else {
19878 block.chunks.claim.push(b `${name}.l(${parent_nodes});`);
19879 }
19880 }
19881 if (has_intros || has_outros) {
19882 block.chunks.intro.push(b `@transition_in(${name});`);
19883 }
19884 if (needs_anchor) {
19885 block.add_element(anchor, x `@empty()`, parent_nodes && x `@empty()`, parent_node);
19886 }
19887 this.branches.forEach(branch => {
19888 branch.fragment.render(branch.block, null, x `#nodes`);
19889 });
19890 }
19891 render_compound(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, if_exists_condition, has_transitions }, detaching) {
19892 const select_block_type = this.renderer.component.get_unique_name('select_block_type');
19893 const current_block_type = block.get_unique_name('current_block_type');
19894 const get_block = has_else
19895 ? x `${current_block_type}(#ctx)`
19896 : x `${current_block_type} && ${current_block_type}(#ctx)`;
19897 if (this.needs_update) {
19898 block.chunks.init.push(b `
19899 function ${select_block_type}(#ctx, #dirty) {
19900 ${this.branches.map(({ dependencies, condition, snippet, block }) => condition
19901 ? b `
19902 ${snippet && (dependencies.length > 0
19903 ? b `if (${condition} == null || ${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
19904 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
19905 if (${condition}) return ${block.name};`
19906 : b `return ${block.name};`)}
19907 }
19908 `);
19909 }
19910 else {
19911 block.chunks.init.push(b `
19912 function ${select_block_type}(#ctx, #dirty) {
19913 ${this.branches.map(({ condition, snippet, block }) => condition
19914 ? b `if (${snippet || condition}) return ${block.name};`
19915 : b `return ${block.name};`)}
19916 }
19917 `);
19918 }
19919 block.chunks.init.push(b `
19920 let ${current_block_type} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
19921 let ${name} = ${get_block};
19922 `);
19923 const initial_mount_node = parent_node || '#target';
19924 const anchor_node = parent_node ? 'null' : '#anchor';
19925 if (if_exists_condition) {
19926 block.chunks.mount.push(b `if (${if_exists_condition}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
19927 }
19928 else {
19929 block.chunks.mount.push(b `${name}.m(${initial_mount_node}, ${anchor_node});`);
19930 }
19931 if (this.needs_update) {
19932 const update_mount_node = this.get_update_mount_node(anchor);
19933 const change_block = b `
19934 ${if_exists_condition ? b `if (${if_exists_condition}) ${name}.d(1)` : b `${name}.d(1)`};
19935 ${name} = ${get_block};
19936 if (${name}) {
19937 ${name}.c();
19938 ${has_transitions && b `@transition_in(${name}, 1);`}
19939 ${name}.m(${update_mount_node}, ${anchor});
19940 }
19941 `;
19942 if (dynamic) {
19943 block.chunks.update.push(b `
19944 if (${current_block_type} === (${current_block_type} = ${select_block_type}(#ctx, #dirty)) && ${name}) {
19945 ${name}.p(#ctx, #dirty);
19946 } else {
19947 ${change_block}
19948 }
19949 `);
19950 }
19951 else {
19952 block.chunks.update.push(b `
19953 if (${current_block_type} !== (${current_block_type} = ${select_block_type}(#ctx, #dirty))) {
19954 ${change_block}
19955 }
19956 `);
19957 }
19958 }
19959 else if (dynamic) {
19960 if (if_exists_condition) {
19961 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
19962 }
19963 else {
19964 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
19965 }
19966 }
19967 if (if_exists_condition) {
19968 block.chunks.destroy.push(b `
19969 if (${if_exists_condition}) {
19970 ${name}.d(${detaching});
19971 }
19972 `);
19973 }
19974 else {
19975 block.chunks.destroy.push(b `
19976 ${name}.d(${detaching});
19977 `);
19978 }
19979 }
19980 // if any of the siblings have outros, we need to keep references to the blocks
19981 // (TODO does this only apply to bidi transitions?)
19982 render_compound_with_outros(block, parent_node, _parent_nodes, dynamic, { name, anchor, has_else, has_transitions, if_exists_condition }, detaching) {
19983 const select_block_type = this.renderer.component.get_unique_name('select_block_type');
19984 const current_block_type_index = block.get_unique_name('current_block_type_index');
19985 const previous_block_index = block.get_unique_name('previous_block_index');
19986 const if_block_creators = block.get_unique_name('if_block_creators');
19987 const if_blocks = block.get_unique_name('if_blocks');
19988 const if_current_block_type_index = has_else
19989 ? nodes => nodes
19990 : nodes => b `if (~${current_block_type_index}) { ${nodes} }`;
19991 block.add_variable(current_block_type_index);
19992 block.add_variable(name);
19993 block.chunks.init.push(b `
19994 const ${if_block_creators} = [
19995 ${this.branches.map(branch => branch.block.name)}
19996 ];
19997
19998 const ${if_blocks} = [];
19999
20000 ${this.needs_update
20001 ? b `
20002 function ${select_block_type}(#ctx, #dirty) {
20003 ${this.branches.map(({ dependencies, condition, snippet }, i) => condition
20004 ? b `
20005 ${snippet && (dependencies.length > 0
20006 ? b `if (${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}`
20007 : b `if (${condition} == null) ${condition} = !!${snippet}`)}
20008 if (${condition}) return ${i};`
20009 : b `return ${i};`)}
20010 ${!has_else && b `return -1;`}
20011 }
20012 `
20013 : b `
20014 function ${select_block_type}(#ctx, #dirty) {
20015 ${this.branches.map(({ condition, snippet }, i) => condition
20016 ? b `if (${snippet || condition}) return ${i};`
20017 : b `return ${i};`)}
20018 ${!has_else && b `return -1;`}
20019 }
20020 `}
20021 `);
20022 if (has_else) {
20023 block.chunks.init.push(b `
20024 ${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()});
20025 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
20026 `);
20027 }
20028 else {
20029 block.chunks.init.push(b `
20030 if (~(${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}))) {
20031 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
20032 }
20033 `);
20034 }
20035 const initial_mount_node = parent_node || '#target';
20036 const anchor_node = parent_node ? 'null' : '#anchor';
20037 block.chunks.mount.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].m(${initial_mount_node}, ${anchor_node});`));
20038 if (this.needs_update) {
20039 const update_mount_node = this.get_update_mount_node(anchor);
20040 const destroy_old_block = b `
20041 @group_outros();
20042 @transition_out(${if_blocks}[${previous_block_index}], 1, 1, () => {
20043 ${if_blocks}[${previous_block_index}] = null;
20044 });
20045 @check_outros();
20046 `;
20047 const create_new_block = b `
20048 ${name} = ${if_blocks}[${current_block_type_index}];
20049 if (!${name}) {
20050 ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx);
20051 ${name}.c();
20052 } else {
20053 ${dynamic && b `${name}.p(#ctx, #dirty);`}
20054 }
20055 ${has_transitions && b `@transition_in(${name}, 1);`}
20056 ${name}.m(${update_mount_node}, ${anchor});
20057 `;
20058 const change_block = has_else
20059 ? b `
20060 ${destroy_old_block}
20061
20062 ${create_new_block}
20063 `
20064 : b `
20065 if (${name}) {
20066 ${destroy_old_block}
20067 }
20068
20069 if (~${current_block_type_index}) {
20070 ${create_new_block}
20071 } else {
20072 ${name} = null;
20073 }
20074 `;
20075 block.chunks.update.push(b `
20076 let ${previous_block_index} = ${current_block_type_index};
20077 ${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
20078 `);
20079 if (dynamic) {
20080 block.chunks.update.push(b `
20081 if (${current_block_type_index} === ${previous_block_index}) {
20082 ${if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].p(#ctx, #dirty);`)}
20083 } else {
20084 ${change_block}
20085 }
20086 `);
20087 }
20088 else {
20089 block.chunks.update.push(b `
20090 if (${current_block_type_index} !== ${previous_block_index}) {
20091 ${change_block}
20092 }
20093 `);
20094 }
20095 }
20096 else if (dynamic) {
20097 if (if_exists_condition) {
20098 block.chunks.update.push(b `if (${if_exists_condition}) ${name}.p(#ctx, #dirty);`);
20099 }
20100 else {
20101 block.chunks.update.push(b `${name}.p(#ctx, #dirty);`);
20102 }
20103 }
20104 block.chunks.destroy.push(if_current_block_type_index(b `${if_blocks}[${current_block_type_index}].d(${detaching});`));
20105 }
20106 render_simple(block, parent_node, _parent_nodes, dynamic, { name, anchor, if_exists_condition, has_transitions }, detaching) {
20107 const branch = this.branches[0];
20108 if (branch.snippet)
20109 block.add_variable(branch.condition, branch.snippet);
20110 block.chunks.init.push(b `
20111 let ${name} = ${branch.condition} && ${branch.block.name}(#ctx);
20112 `);
20113 const initial_mount_node = parent_node || '#target';
20114 const anchor_node = parent_node ? 'null' : '#anchor';
20115 block.chunks.mount.push(b `if (${name}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
20116 if (branch.dependencies.length > 0) {
20117 const update_mount_node = this.get_update_mount_node(anchor);
20118 const enter = b `
20119 if (${name}) {
20120 ${dynamic && b `${name}.p(#ctx, #dirty);`}
20121 ${has_transitions &&
20122 b `if (${block.renderer.dirty(branch.dependencies)}) {
20123 @transition_in(${name}, 1);
20124 }`}
20125 } else {
20126 ${name} = ${branch.block.name}(#ctx);
20127 ${name}.c();
20128 ${has_transitions && b `@transition_in(${name}, 1);`}
20129 ${name}.m(${update_mount_node}, ${anchor});
20130 }
20131 `;
20132 if (branch.snippet) {
20133 block.chunks.update.push(b `if (${block.renderer.dirty(branch.dependencies)}) ${branch.condition} = ${branch.snippet}`);
20134 }
20135 // no `p()` here — we don't want to update outroing nodes,
20136 // as that will typically result in glitching
20137 if (branch.block.has_outro_method) {
20138 block.chunks.update.push(b `
20139 if (${branch.condition}) {
20140 ${enter}
20141 } else if (${name}) {
20142 @group_outros();
20143 @transition_out(${name}, 1, 1, () => {
20144 ${name} = null;
20145 });
20146 @check_outros();
20147 }
20148 `);
20149 }
20150 else {
20151 block.chunks.update.push(b `
20152 if (${branch.condition}) {
20153 ${enter}
20154 } else if (${name}) {
20155 ${name}.d(1);
20156 ${name} = null;
20157 }
20158 `);
20159 }
20160 }
20161 else if (dynamic) {
20162 block.chunks.update.push(b `
20163 if (${branch.condition}) ${name}.p(#ctx, #dirty);
20164 `);
20165 }
20166 if (if_exists_condition) {
20167 block.chunks.destroy.push(b `
20168 if (${if_exists_condition}) ${name}.d(${detaching});
20169 `);
20170 }
20171 else {
20172 block.chunks.destroy.push(b `
20173 ${name}.d(${detaching});
20174 `);
20175 }
20176 }
20177 get_initial_dirty_bit() {
20178 const _this = this;
20179 // TODO: context-overflow make it less gross
20180 const val = x `-1`;
20181 return {
20182 get type() {
20183 return _this.renderer.context_overflow ? 'ArrayExpression' : 'UnaryExpression';
20184 },
20185 // as [-1]
20186 elements: [val],
20187 // as -1
20188 operator: val.operator,
20189 prefix: val.prefix,
20190 argument: val.argument
20191 };
20192 }
20193 }
20194
20195 class KeyBlockWrapper extends Wrapper {
20196 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20197 super(renderer, block, parent, node);
20198 this.var = { type: 'Identifier', name: 'key_block' };
20199 this.cannot_use_innerhtml();
20200 this.not_static_content();
20201 this.dependencies = node.expression.dynamic_dependencies();
20202 if (this.dependencies.length) {
20203 block = block.child({
20204 comment: create_debugging_comment(node, renderer.component),
20205 name: renderer.component.get_unique_name('create_key_block'),
20206 type: 'key'
20207 });
20208 renderer.blocks.push(block);
20209 }
20210 this.block = block;
20211 this.fragment = new FragmentWrapper(renderer, this.block, node.children, this, strip_whitespace, next_sibling);
20212 }
20213 render(block, parent_node, parent_nodes) {
20214 if (this.dependencies.length === 0) {
20215 this.render_static_key(block, parent_node, parent_nodes);
20216 }
20217 else {
20218 this.render_dynamic_key(block, parent_node, parent_nodes);
20219 }
20220 }
20221 render_static_key(_block, parent_node, parent_nodes) {
20222 this.fragment.render(this.block, parent_node, parent_nodes);
20223 }
20224 render_dynamic_key(block, parent_node, parent_nodes) {
20225 this.fragment.render(this.block, null, x `#nodes`);
20226 const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
20227 const dynamic = this.block.has_update_method;
20228 const previous_key = block.get_unique_name('previous_key');
20229 const snippet = this.node.expression.manipulate(block);
20230 block.add_variable(previous_key, snippet);
20231 const not_equal = this.renderer.component.component_options.immutable ? x `@not_equal` : x `@safe_not_equal`;
20232 const condition = x `${this.renderer.dirty(this.dependencies)} && ${not_equal}(${previous_key}, ${previous_key} = ${snippet})`;
20233 block.chunks.init.push(b `
20234 let ${this.var} = ${this.block.name}(#ctx);
20235 `);
20236 block.chunks.create.push(b `${this.var}.c();`);
20237 if (this.renderer.options.hydratable) {
20238 block.chunks.claim.push(b `${this.var}.l(${parent_nodes});`);
20239 }
20240 block.chunks.mount.push(b `${this.var}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});`);
20241 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
20242 const body = b `
20243 ${has_transitions
20244 ? b `
20245 @group_outros();
20246 @transition_out(${this.var}, 1, 1, @noop);
20247 @check_outros();
20248 `
20249 : b `${this.var}.d(1);`}
20250 ${this.var} = ${this.block.name}(#ctx);
20251 ${this.var}.c();
20252 ${has_transitions && b `@transition_in(${this.var})`}
20253 ${this.var}.m(${this.get_update_mount_node(anchor)}, ${anchor});
20254 `;
20255 if (dynamic) {
20256 block.chunks.update.push(b `
20257 if (${condition}) {
20258 ${body}
20259 } else {
20260 ${this.var}.p(#ctx, #dirty);
20261 }
20262 `);
20263 }
20264 else {
20265 block.chunks.update.push(b `
20266 if (${condition}) {
20267 ${body}
20268 }
20269 `);
20270 }
20271 if (has_transitions) {
20272 block.chunks.intro.push(b `@transition_in(${this.var})`);
20273 block.chunks.outro.push(b `@transition_out(${this.var})`);
20274 }
20275 block.chunks.destroy.push(b `${this.var}.d(detaching)`);
20276 }
20277 }
20278
20279 function string_to_member_expression(name) {
20280 const parts = name.split('.');
20281 let node = {
20282 type: 'Identifier',
20283 name: parts[0]
20284 };
20285 for (let i = 1; i < parts.length; i++) {
20286 node = {
20287 type: 'MemberExpression',
20288 object: node,
20289 property: { type: 'Identifier', name: parts[i] }
20290 };
20291 }
20292 return node;
20293 }
20294
20295 class InlineComponentWrapper extends Wrapper {
20296 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20297 super(renderer, block, parent, node);
20298 this.slots = new Map();
20299 this.cannot_use_innerhtml();
20300 this.not_static_content();
20301 if (this.node.expression) {
20302 block.add_dependencies(this.node.expression.dependencies);
20303 }
20304 this.node.attributes.forEach(attr => {
20305 block.add_dependencies(attr.dependencies);
20306 });
20307 this.node.bindings.forEach(binding => {
20308 if (binding.is_contextual) {
20309 mark_each_block_bindings(this, binding);
20310 }
20311 block.add_dependencies(binding.expression.dependencies);
20312 });
20313 this.node.handlers.forEach(handler => {
20314 if (handler.expression) {
20315 block.add_dependencies(handler.expression.dependencies);
20316 }
20317 });
20318 this.var = {
20319 type: 'Identifier',
20320 name: (this.node.name === 'svelte:self' ? renderer.component.name.name :
20321 this.node.name === 'svelte:component' ? 'switch_instance' :
20322 sanitize(this.node.name)).toLowerCase()
20323 };
20324 if (this.node.children.length) {
20325 this.node.lets.forEach(l => {
20326 extract_names(l.value || l.name).forEach(name => {
20327 renderer.add_to_context(name, true);
20328 });
20329 });
20330 const default_slot = block.child({
20331 comment: create_debugging_comment(node, renderer.component),
20332 name: renderer.component.get_unique_name('create_default_slot'),
20333 type: 'slot'
20334 });
20335 this.renderer.blocks.push(default_slot);
20336 this.slots.set('default', get_slot_definition(default_slot, this.node.scope, this.node.lets));
20337 this.fragment = new FragmentWrapper(renderer, default_slot, node.children, this, strip_whitespace, next_sibling);
20338 const dependencies = new Set();
20339 // TODO is this filtering necessary? (I *think* so)
20340 default_slot.dependencies.forEach(name => {
20341 if (!this.node.scope.is_let(name)) {
20342 dependencies.add(name);
20343 }
20344 });
20345 block.add_dependencies(dependencies);
20346 }
20347 block.add_outro();
20348 }
20349 warn_if_reactive() {
20350 const { name } = this.node;
20351 const variable = this.renderer.component.var_lookup.get(name);
20352 if (!variable) {
20353 return;
20354 }
20355 if (variable.reassigned || variable.export_name || variable.is_reactive_dependency) {
20356 this.renderer.component.warn(this.node, {
20357 code: 'reactive-component',
20358 message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`
20359 });
20360 }
20361 }
20362 render(block, parent_node, parent_nodes) {
20363 this.warn_if_reactive();
20364 const { renderer } = this;
20365 const { component } = renderer;
20366 const name = this.var;
20367 block.add_variable(name);
20368 const component_opts = x `{}`;
20369 const statements = [];
20370 const updates = [];
20371 if (this.fragment) {
20372 this.renderer.add_to_context('$$scope', true);
20373 const default_slot = this.slots.get('default');
20374 this.fragment.nodes.forEach((child) => {
20375 child.render(default_slot.block, null, x `#nodes`);
20376 });
20377 }
20378 let props;
20379 const name_changes = block.get_unique_name(`${name.name}_changes`);
20380 const uses_spread = !!this.node.attributes.find(a => a.is_spread);
20381 // removing empty slot
20382 for (const slot of this.slots.keys()) {
20383 if (!this.slots.get(slot).block.has_content()) {
20384 this.renderer.remove_block(this.slots.get(slot).block);
20385 this.slots.delete(slot);
20386 }
20387 }
20388 const initial_props = this.slots.size > 0
20389 ? [
20390 p `$$slots: {
20391 ${Array.from(this.slots).map(([name, slot]) => {
20392 return p `${name}: [${slot.block.name}, ${slot.get_context || null}, ${slot.get_changes || null}]`;
20393 })}
20394 }`,
20395 p `$$scope: {
20396 ctx: #ctx
20397 }`
20398 ]
20399 : [];
20400 const attribute_object = uses_spread
20401 ? x `{ ${initial_props} }`
20402 : x `{
20403 ${this.node.attributes.map(attr => p `${attr.name}: ${attr.get_value(block)}`)},
20404 ${initial_props}
20405 }`;
20406 if (this.node.attributes.length || this.node.bindings.length || initial_props.length) {
20407 if (!uses_spread && this.node.bindings.length === 0) {
20408 component_opts.properties.push(p `props: ${attribute_object}`);
20409 }
20410 else {
20411 props = block.get_unique_name(`${name.name}_props`);
20412 component_opts.properties.push(p `props: ${props}`);
20413 }
20414 }
20415 if (component.compile_options.dev) {
20416 // TODO this is a terrible hack, but without it the component
20417 // will complain that options.target is missing. This would
20418 // work better if components had separate public and private
20419 // APIs
20420 component_opts.properties.push(p `$$inline: true`);
20421 }
20422 const fragment_dependencies = new Set(this.fragment ? ['$$scope'] : []);
20423 this.slots.forEach(slot => {
20424 slot.block.dependencies.forEach(name => {
20425 const is_let = slot.scope.is_let(name);
20426 const variable = renderer.component.var_lookup.get(name);
20427 if (is_let || is_dynamic$1(variable))
20428 fragment_dependencies.add(name);
20429 });
20430 });
20431 const dynamic_attributes = this.node.attributes.filter(a => a.get_dependencies().length > 0);
20432 if (!uses_spread && (dynamic_attributes.length > 0 || this.node.bindings.length > 0 || fragment_dependencies.size > 0)) {
20433 updates.push(b `const ${name_changes} = {};`);
20434 }
20435 if (this.node.attributes.length) {
20436 if (uses_spread) {
20437 const levels = block.get_unique_name(`${this.var.name}_spread_levels`);
20438 const initial_props = [];
20439 const changes = [];
20440 const all_dependencies = new Set();
20441 this.node.attributes.forEach(attr => {
20442 add_to_set(all_dependencies, attr.dependencies);
20443 });
20444 this.node.attributes.forEach((attr, i) => {
20445 const { name, dependencies } = attr;
20446 const condition = dependencies.size > 0 && (dependencies.size !== all_dependencies.size)
20447 ? renderer.dirty(Array.from(dependencies))
20448 : null;
20449 const unchanged = dependencies.size === 0;
20450 let change_object;
20451 if (attr.is_spread) {
20452 const value = attr.expression.manipulate(block);
20453 initial_props.push(value);
20454 let value_object = value;
20455 if (attr.expression.node.type !== 'ObjectExpression') {
20456 value_object = x `@get_spread_object(${value})`;
20457 }
20458 change_object = value_object;
20459 }
20460 else {
20461 const obj = x `{ ${name}: ${attr.get_value(block)} }`;
20462 initial_props.push(obj);
20463 change_object = obj;
20464 }
20465 changes.push(unchanged
20466 ? x `${levels}[${i}]`
20467 : condition
20468 ? x `${condition} && ${change_object}`
20469 : change_object);
20470 });
20471 block.chunks.init.push(b `
20472 const ${levels} = [
20473 ${initial_props}
20474 ];
20475 `);
20476 statements.push(b `
20477 for (let #i = 0; #i < ${levels}.length; #i += 1) {
20478 ${props} = @assign(${props}, ${levels}[#i]);
20479 }
20480 `);
20481 if (all_dependencies.size) {
20482 const condition = renderer.dirty(Array.from(all_dependencies));
20483 updates.push(b `
20484 const ${name_changes} = ${condition} ? @get_spread_update(${levels}, [
20485 ${changes}
20486 ]) : {}
20487 `);
20488 }
20489 else {
20490 updates.push(b `
20491 const ${name_changes} = {};
20492 `);
20493 }
20494 }
20495 else {
20496 dynamic_attributes.forEach((attribute) => {
20497 const dependencies = attribute.get_dependencies();
20498 if (dependencies.length > 0) {
20499 const condition = renderer.dirty(dependencies);
20500 updates.push(b `
20501 if (${condition}) ${name_changes}.${attribute.name} = ${attribute.get_value(block)};
20502 `);
20503 }
20504 });
20505 }
20506 }
20507 if (fragment_dependencies.size > 0) {
20508 updates.push(b `
20509 if (${renderer.dirty(Array.from(fragment_dependencies))}) {
20510 ${name_changes}.$$scope = { dirty: #dirty, ctx: #ctx };
20511 }`);
20512 }
20513 const munged_bindings = this.node.bindings.map(binding => {
20514 component.has_reactive_assignments = true;
20515 if (binding.name === 'this') {
20516 return bind_this(component, block, new BindingWrapper(block, binding, this), this.var);
20517 }
20518 const id = component.get_unique_name(`${this.var.name}_${binding.name}_binding`);
20519 renderer.add_to_context(id.name);
20520 const callee = renderer.reference(id);
20521 const updating = block.get_unique_name(`updating_${binding.name}`);
20522 block.add_variable(updating);
20523 const snippet = binding.expression.manipulate(block);
20524 statements.push(b `
20525 if (${snippet} !== void 0) {
20526 ${props}.${binding.name} = ${snippet};
20527 }`);
20528 updates.push(b `
20529 if (!${updating} && ${renderer.dirty(Array.from(binding.expression.dependencies))}) {
20530 ${updating} = true;
20531 ${name_changes}.${binding.name} = ${snippet};
20532 @add_flush_callback(() => ${updating} = false);
20533 }
20534 `);
20535 const contextual_dependencies = Array.from(binding.expression.contextual_dependencies);
20536 const dependencies = Array.from(binding.expression.dependencies);
20537 let lhs = binding.raw_expression;
20538 if (binding.is_contextual && binding.expression.node.type === 'Identifier') {
20539 // bind:x={y} — we can't just do `y = x`, we need to
20540 // to `array[index] = x;
20541 const { name } = binding.expression.node;
20542 const { object, property, snippet } = block.bindings.get(name);
20543 lhs = snippet;
20544 contextual_dependencies.push(object.name, property.name);
20545 }
20546 const params = [x `#value`];
20547 if (contextual_dependencies.length > 0) {
20548 const args = [];
20549 contextual_dependencies.forEach(name => {
20550 params.push({
20551 type: 'Identifier',
20552 name
20553 });
20554 renderer.add_to_context(name, true);
20555 args.push(renderer.reference(name));
20556 });
20557 block.chunks.init.push(b `
20558 function ${id}(#value) {
20559 ${callee}.call(null, #value, ${args});
20560 }
20561 `);
20562 block.maintain_context = true; // TODO put this somewhere more logical
20563 }
20564 else {
20565 block.chunks.init.push(b `
20566 function ${id}(#value) {
20567 ${callee}.call(null, #value);
20568 }
20569 `);
20570 }
20571 const body = b `
20572 function ${id}(${params}) {
20573 ${lhs} = #value;
20574 ${renderer.invalidate(dependencies[0])};
20575 }
20576 `;
20577 component.partly_hoisted.push(body);
20578 return b `@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
20579 });
20580 const munged_handlers = this.node.handlers.map(handler => {
20581 const event_handler = new EventHandlerWrapper(handler, this);
20582 let snippet = event_handler.get_snippet(block);
20583 if (handler.modifiers.has('once'))
20584 snippet = x `@once(${snippet})`;
20585 return b `${name}.$on("${handler.name}", ${snippet});`;
20586 });
20587 if (this.node.name === 'svelte:component') {
20588 const switch_value = block.get_unique_name('switch_value');
20589 const switch_props = block.get_unique_name('switch_props');
20590 const snippet = this.node.expression.manipulate(block);
20591 block.chunks.init.push(b `
20592 var ${switch_value} = ${snippet};
20593
20594 function ${switch_props}(#ctx) {
20595 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
20596 ${props && b `let ${props} = ${attribute_object};`}`}
20597 ${statements}
20598 return ${component_opts};
20599 }
20600
20601 if (${switch_value}) {
20602 ${name} = new ${switch_value}(${switch_props}(#ctx));
20603
20604 ${munged_bindings}
20605 ${munged_handlers}
20606 }
20607 `);
20608 block.chunks.create.push(b `if (${name}) @create_component(${name}.$$.fragment);`);
20609 if (parent_nodes && this.renderer.options.hydratable) {
20610 block.chunks.claim.push(b `if (${name}) @claim_component(${name}.$$.fragment, ${parent_nodes});`);
20611 }
20612 block.chunks.mount.push(b `
20613 if (${name}) {
20614 @mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20615 }
20616 `);
20617 const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
20618 const update_mount_node = this.get_update_mount_node(anchor);
20619 if (updates.length) {
20620 block.chunks.update.push(b `
20621 ${updates}
20622 `);
20623 }
20624 block.chunks.update.push(b `
20625 if (${switch_value} !== (${switch_value} = ${snippet})) {
20626 if (${name}) {
20627 @group_outros();
20628 const old_component = ${name};
20629 @transition_out(old_component.$$.fragment, 1, 0, () => {
20630 @destroy_component(old_component, 1);
20631 });
20632 @check_outros();
20633 }
20634
20635 if (${switch_value}) {
20636 ${name} = new ${switch_value}(${switch_props}(#ctx));
20637
20638 ${munged_bindings}
20639 ${munged_handlers}
20640
20641 @create_component(${name}.$$.fragment);
20642 @transition_in(${name}.$$.fragment, 1);
20643 @mount_component(${name}, ${update_mount_node}, ${anchor});
20644 } else {
20645 ${name} = null;
20646 }
20647 } else if (${switch_value}) {
20648 ${updates.length > 0 && b `${name}.$set(${name_changes});`}
20649 }
20650 `);
20651 block.chunks.intro.push(b `
20652 if (${name}) @transition_in(${name}.$$.fragment, #local);
20653 `);
20654 block.chunks.outro.push(b `if (${name}) @transition_out(${name}.$$.fragment, #local);`);
20655 block.chunks.destroy.push(b `if (${name}) @destroy_component(${name}, ${parent_node ? null : 'detaching'});`);
20656 }
20657 else {
20658 const expression = this.node.name === 'svelte:self'
20659 ? component.name
20660 : this.renderer.reference(string_to_member_expression(this.node.name));
20661 block.chunks.init.push(b `
20662 ${(this.node.attributes.length > 0 || this.node.bindings.length > 0) && b `
20663 ${props && b `let ${props} = ${attribute_object};`}`}
20664 ${statements}
20665 ${name} = new ${expression}(${component_opts});
20666
20667 ${munged_bindings}
20668 ${munged_handlers}
20669 `);
20670 block.chunks.create.push(b `@create_component(${name}.$$.fragment);`);
20671 if (parent_nodes && this.renderer.options.hydratable) {
20672 block.chunks.claim.push(b `@claim_component(${name}.$$.fragment, ${parent_nodes});`);
20673 }
20674 block.chunks.mount.push(b `@mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});`);
20675 block.chunks.intro.push(b `
20676 @transition_in(${name}.$$.fragment, #local);
20677 `);
20678 if (updates.length) {
20679 block.chunks.update.push(b `
20680 ${updates}
20681 ${name}.$set(${name_changes});
20682 `);
20683 }
20684 block.chunks.destroy.push(b `
20685 @destroy_component(${name}, ${parent_node ? null : 'detaching'});
20686 `);
20687 block.chunks.outro.push(b `@transition_out(${name}.$$.fragment, #local);`);
20688 }
20689 }
20690 }
20691
20692 function get_slot_data(values, block = null) {
20693 return {
20694 type: 'ObjectExpression',
20695 properties: Array.from(values.values())
20696 .filter(attribute => attribute.name !== 'name')
20697 .map(attribute => {
20698 if (attribute.is_spread) {
20699 const argument = get_spread_value(block, attribute);
20700 return {
20701 type: 'SpreadElement',
20702 argument
20703 };
20704 }
20705 const value = get_value(block, attribute);
20706 return p `${attribute.name}: ${value}`;
20707 })
20708 };
20709 }
20710 function get_value(block, attribute) {
20711 if (attribute.is_true)
20712 return x `true`;
20713 if (attribute.chunks.length === 0)
20714 return x `""`;
20715 let value = attribute.chunks
20716 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : (block ? chunk.manipulate(block) : chunk.node))
20717 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20718 if (attribute.chunks.length > 1 && attribute.chunks[0].type !== 'Text') {
20719 value = x `"" + ${value}`;
20720 }
20721 return value;
20722 }
20723 function get_spread_value(block, attribute) {
20724 return block ? attribute.expression.manipulate(block) : attribute.expression.node;
20725 }
20726
20727 class SlotWrapper extends Wrapper {
20728 constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
20729 super(renderer, block, parent, node);
20730 this.fallback = null;
20731 this.var = { type: 'Identifier', name: 'slot' };
20732 this.dependencies = new Set(['$$scope']);
20733 this.cannot_use_innerhtml();
20734 this.not_static_content();
20735 if (this.node.children.length) {
20736 this.fallback = block.child({
20737 comment: create_debugging_comment(this.node.children[0], this.renderer.component),
20738 name: this.renderer.component.get_unique_name('fallback_block'),
20739 type: 'fallback'
20740 });
20741 renderer.blocks.push(this.fallback);
20742 }
20743 if (this.node.values.has('slot')) {
20744 block = create_slot_block(this.node.values.get('slot'), this, block);
20745 }
20746 this.fragment = new FragmentWrapper(renderer, this.fallback, node.children, this, strip_whitespace, next_sibling);
20747 this.node.values.forEach(attribute => {
20748 add_to_set(this.dependencies, attribute.dependencies);
20749 });
20750 block.add_dependencies(this.dependencies);
20751 // we have to do this, just in case
20752 block.add_intro();
20753 block.add_outro();
20754 }
20755 render(block, parent_node, parent_nodes) {
20756 const { renderer } = this;
20757 const { slot_name } = this.node;
20758 if (this.slot_block) {
20759 block = this.slot_block;
20760 }
20761 let get_slot_changes_fn;
20762 let get_slot_spread_changes_fn;
20763 let get_slot_context_fn;
20764 if (this.node.values.size > 0) {
20765 get_slot_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_changes`);
20766 get_slot_context_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_context`);
20767 const changes = x `{}`;
20768 const spread_dynamic_dependencies = new Set();
20769 this.node.values.forEach(attribute => {
20770 if (attribute.type === 'Spread') {
20771 add_to_set(spread_dynamic_dependencies, Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name)));
20772 }
20773 else {
20774 const dynamic_dependencies = Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name));
20775 if (dynamic_dependencies.length > 0) {
20776 changes.properties.push(p `${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`);
20777 }
20778 }
20779 });
20780 renderer.blocks.push(b `
20781 const ${get_slot_changes_fn} = #dirty => ${changes};
20782 const ${get_slot_context_fn} = #ctx => ${get_slot_data(this.node.values, block)};
20783 `);
20784 if (spread_dynamic_dependencies.size) {
20785 get_slot_spread_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_spread_changes`);
20786 renderer.blocks.push(b `
20787 const ${get_slot_spread_changes_fn} = #dirty => ${renderer.dirty(Array.from(spread_dynamic_dependencies))} > 0 ? -1 : 0;
20788 `);
20789 }
20790 }
20791 else {
20792 get_slot_changes_fn = 'null';
20793 get_slot_context_fn = 'null';
20794 }
20795 let has_fallback = !!this.fallback;
20796 if (this.fallback) {
20797 this.fragment.render(this.fallback, null, x `#nodes`);
20798 has_fallback = this.fallback.has_content();
20799 if (!has_fallback) {
20800 renderer.remove_block(this.fallback);
20801 }
20802 }
20803 const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`);
20804 const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
20805 const slot_or_fallback = has_fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot;
20806 block.chunks.init.push(b `
20807 const ${slot_definition} = ${renderer.reference('#slots')}.${slot_name};
20808 const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn});
20809 ${has_fallback ? b `const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
20810 `);
20811 block.chunks.create.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.c();`);
20812 if (renderer.options.hydratable) {
20813 block.chunks.claim.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});`);
20814 }
20815 block.chunks.mount.push(b `
20816 if (${slot_or_fallback}) {
20817 ${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
20818 }
20819 `);
20820 block.chunks.intro.push(b `@transition_in(${slot_or_fallback}, #local);`);
20821 block.chunks.outro.push(b `@transition_out(${slot_or_fallback}, #local);`);
20822 const dynamic_dependencies = Array.from(this.dependencies).filter((name) => this.is_dependency_dynamic(name));
20823 const fallback_dynamic_dependencies = has_fallback
20824 ? Array.from(this.fallback.dependencies).filter((name) => this.is_dependency_dynamic(name))
20825 : [];
20826 const slot_update = get_slot_spread_changes_fn ? b `
20827 if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
20828 @update_slot_spread(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_spread_changes_fn}, ${get_slot_context_fn});
20829 }
20830 ` : b `
20831 if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
20832 @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn});
20833 }
20834 `;
20835 const fallback_update = has_fallback && fallback_dynamic_dependencies.length > 0 && b `
20836 if (${slot_or_fallback} && ${slot_or_fallback}.p && ${renderer.dirty(fallback_dynamic_dependencies)}) {
20837 ${slot_or_fallback}.p(#ctx, #dirty);
20838 }
20839 `;
20840 if (fallback_update) {
20841 block.chunks.update.push(b `
20842 if (${slot}) {
20843 ${slot_update}
20844 } else {
20845 ${fallback_update}
20846 }
20847 `);
20848 }
20849 else {
20850 block.chunks.update.push(b `
20851 if (${slot}) {
20852 ${slot_update}
20853 }
20854 `);
20855 }
20856 block.chunks.destroy.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`);
20857 }
20858 is_dependency_dynamic(name) {
20859 if (name === '$$scope')
20860 return true;
20861 if (this.node.scope.is_let(name))
20862 return true;
20863 if (is_reserved_keyword(name))
20864 return true;
20865 const variable = this.renderer.component.var_lookup.get(name);
20866 return is_dynamic$1(variable);
20867 }
20868 }
20869
20870 class TitleWrapper extends Wrapper {
20871 constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
20872 super(renderer, block, parent, node);
20873 }
20874 render(block, _parent_node, _parent_nodes) {
20875 const is_dynamic = !!this.node.children.find(node => node.type !== 'Text');
20876 if (is_dynamic) {
20877 let value;
20878 const all_dependencies = new Set();
20879 // TODO some of this code is repeated in Tag.ts — would be good to
20880 // DRY it out if that's possible without introducing crazy indirection
20881 if (this.node.children.length === 1) {
20882 // single {tag} — may be a non-string
20883 // @ts-ignore todo: check this
20884 const { expression } = this.node.children[0];
20885 value = expression.manipulate(block);
20886 add_to_set(all_dependencies, expression.dependencies);
20887 }
20888 else {
20889 // '{foo} {bar}' — treat as string concatenation
20890 value = this.node.children
20891 .map(chunk => {
20892 if (chunk.type === 'Text')
20893 return string_literal(chunk.data);
20894 chunk.expression.dependencies.forEach(d => {
20895 all_dependencies.add(d);
20896 });
20897 return chunk.expression.manipulate(block);
20898 })
20899 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
20900 if (this.node.children[0].type !== 'Text') {
20901 value = x `"" + ${value}`;
20902 }
20903 }
20904 const last = this.node.should_cache && block.get_unique_name('title_value');
20905 if (this.node.should_cache)
20906 block.add_variable(last);
20907 const init = this.node.should_cache ? x `${last} = ${value}` : value;
20908 block.chunks.init.push(b `@_document.title = ${init};`);
20909 const updater = b `@_document.title = ${this.node.should_cache ? last : value};`;
20910 if (all_dependencies.size) {
20911 const dependencies = Array.from(all_dependencies);
20912 let condition = block.renderer.dirty(dependencies);
20913 if (block.has_outros) {
20914 condition = x `!#current || ${condition}`;
20915 }
20916 if (this.node.should_cache) {
20917 condition = x `${condition} && (${last} !== (${last} = ${value}))`;
20918 }
20919 block.chunks.update.push(b `
20920 if (${condition}) {
20921 ${updater}
20922 }`);
20923 }
20924 }
20925 else {
20926 const value = this.node.children.length > 0
20927 ? string_literal(this.node.children[0].data)
20928 : x `""`;
20929 block.chunks.hydrate.push(b `@_document.title = ${value};`);
20930 }
20931 }
20932 }
20933
20934 const associated_events = {
20935 innerWidth: 'resize',
20936 innerHeight: 'resize',
20937 outerWidth: 'resize',
20938 outerHeight: 'resize',
20939 scrollX: 'scroll',
20940 scrollY: 'scroll'
20941 };
20942 const properties = {
20943 scrollX: 'pageXOffset',
20944 scrollY: 'pageYOffset'
20945 };
20946 const readonly = new Set([
20947 'innerWidth',
20948 'innerHeight',
20949 'outerWidth',
20950 'outerHeight',
20951 'online'
20952 ]);
20953 class WindowWrapper extends Wrapper {
20954 constructor(renderer, block, parent, node) {
20955 super(renderer, block, parent, node);
20956 this.handlers = this.node.handlers.map(handler => new EventHandlerWrapper(handler, this));
20957 }
20958 render(block, _parent_node, _parent_nodes) {
20959 const { renderer } = this;
20960 const { component } = renderer;
20961 const events = {};
20962 const bindings = {};
20963 add_actions(block, '@_window', this.node.actions);
20964 add_event_handlers(block, '@_window', this.handlers);
20965 this.node.bindings.forEach(binding => {
20966 // TODO: what if it's a MemberExpression?
20967 const binding_name = binding.expression.node.name;
20968 // in dev mode, throw if read-only values are written to
20969 if (readonly.has(binding.name)) {
20970 renderer.readonly.add(binding_name);
20971 }
20972 bindings[binding.name] = binding_name;
20973 // bind:online is a special case, we need to listen for two separate events
20974 if (binding.name === 'online')
20975 return;
20976 const associated_event = associated_events[binding.name];
20977 const property = properties[binding.name] || binding.name;
20978 if (!events[associated_event])
20979 events[associated_event] = [];
20980 events[associated_event].push({
20981 name: binding_name,
20982 value: property
20983 });
20984 });
20985 const scrolling = block.get_unique_name('scrolling');
20986 const clear_scrolling = block.get_unique_name('clear_scrolling');
20987 const scrolling_timeout = block.get_unique_name('scrolling_timeout');
20988 Object.keys(events).forEach(event => {
20989 const id = block.get_unique_name(`onwindow${event}`);
20990 const props = events[event];
20991 renderer.add_to_context(id.name);
20992 const fn = renderer.reference(id.name);
20993 if (event === 'scroll') {
20994 // TODO other bidirectional bindings...
20995 block.add_variable(scrolling, x `false`);
20996 block.add_variable(clear_scrolling, x `() => { ${scrolling} = false }`);
20997 block.add_variable(scrolling_timeout);
20998 const condition = bindings.scrollX && bindings.scrollY
20999 ? x `"${bindings.scrollX}" in this._state || "${bindings.scrollY}" in this._state`
21000 : x `"${bindings.scrollX || bindings.scrollY}" in this._state`;
21001 const scrollX = bindings.scrollX && x `this._state.${bindings.scrollX}`;
21002 const scrollY = bindings.scrollY && x `this._state.${bindings.scrollY}`;
21003 renderer.meta_bindings.push(b `
21004 if (${condition}) {
21005 @_scrollTo(${scrollX || '@_window.pageXOffset'}, ${scrollY || '@_window.pageYOffset'});
21006 }
21007 ${scrollX && `${scrollX} = @_window.pageXOffset;`}
21008 ${scrollY && `${scrollY} = @_window.pageYOffset;`}
21009 `);
21010 block.event_listeners.push(x `
21011 @listen(@_window, "${event}", () => {
21012 ${scrolling} = true;
21013 @_clearTimeout(${scrolling_timeout});
21014 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
21015 ${fn}();
21016 })
21017 `);
21018 }
21019 else {
21020 props.forEach(prop => {
21021 renderer.meta_bindings.push(b `this._state.${prop.name} = @_window.${prop.value};`);
21022 });
21023 block.event_listeners.push(x `
21024 @listen(@_window, "${event}", ${fn})
21025 `);
21026 }
21027 component.partly_hoisted.push(b `
21028 function ${id}() {
21029 ${props.map(prop => renderer.invalidate(prop.name, x `${prop.name} = @_window.${prop.value}`))}
21030 }
21031 `);
21032 block.chunks.init.push(b `
21033 @add_render_callback(${fn});
21034 `);
21035 component.has_reactive_assignments = true;
21036 });
21037 // special case... might need to abstract this out if we add more special cases
21038 if (bindings.scrollX || bindings.scrollY) {
21039 const condition = renderer.dirty([bindings.scrollX, bindings.scrollY].filter(Boolean));
21040 const scrollX = bindings.scrollX ? renderer.reference(bindings.scrollX) : x `@_window.pageXOffset`;
21041 const scrollY = bindings.scrollY ? renderer.reference(bindings.scrollY) : x `@_window.pageYOffset`;
21042 block.chunks.update.push(b `
21043 if (${condition} && !${scrolling}) {
21044 ${scrolling} = true;
21045 @_clearTimeout(${scrolling_timeout});
21046 @_scrollTo(${scrollX}, ${scrollY});
21047 ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
21048 }
21049 `);
21050 }
21051 // another special case. (I'm starting to think these are all special cases.)
21052 if (bindings.online) {
21053 const id = block.get_unique_name('onlinestatuschanged');
21054 const name = bindings.online;
21055 renderer.add_to_context(id.name);
21056 const reference = renderer.reference(id.name);
21057 component.partly_hoisted.push(b `
21058 function ${id}() {
21059 ${renderer.invalidate(name, x `${name} = @_navigator.onLine`)}
21060 }
21061 `);
21062 block.chunks.init.push(b `
21063 @add_render_callback(${reference});
21064 `);
21065 block.event_listeners.push(x `@listen(@_window, "online", ${reference})`, x `@listen(@_window, "offline", ${reference})`);
21066 component.has_reactive_assignments = true;
21067 }
21068 }
21069 }
21070
21071 function link(next, prev) {
21072 prev.next = next;
21073 if (next)
21074 next.prev = prev;
21075 }
21076
21077 const wrappers = {
21078 AwaitBlock: AwaitBlockWrapper,
21079 Body: BodyWrapper,
21080 Comment: null,
21081 DebugTag: DebugTagWrapper,
21082 EachBlock: EachBlockWrapper,
21083 Element: ElementWrapper,
21084 Head: HeadWrapper,
21085 IfBlock: IfBlockWrapper,
21086 InlineComponent: InlineComponentWrapper,
21087 KeyBlock: KeyBlockWrapper,
21088 MustacheTag: MustacheTagWrapper,
21089 Options: null,
21090 RawMustacheTag: RawMustacheTagWrapper,
21091 Slot: SlotWrapper,
21092 Text: TextWrapper,
21093 Title: TitleWrapper,
21094 Window: WindowWrapper
21095 };
21096 function trimmable_at(child, next_sibling) {
21097 // Whitespace is trimmable if one of the following is true:
21098 // The child and its sibling share a common nearest each block (not at an each block boundary)
21099 // The next sibling's previous node is an each block
21100 return (next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/)) || next_sibling.node.prev.type === 'EachBlock';
21101 }
21102 class FragmentWrapper {
21103 constructor(renderer, block, nodes, parent, strip_whitespace, next_sibling) {
21104 this.nodes = [];
21105 let last_child;
21106 let window_wrapper;
21107 let i = nodes.length;
21108 while (i--) {
21109 const child = nodes[i];
21110 if (!child.type) {
21111 throw new Error('missing type');
21112 }
21113 if (!(child.type in wrappers)) {
21114 throw new Error(`TODO implement ${child.type}`);
21115 }
21116 // special case — this is an easy way to remove whitespace surrounding
21117 // <svelte:window/>. lil hacky but it works
21118 if (child.type === 'Window') {
21119 window_wrapper = new WindowWrapper(renderer, block, parent, child);
21120 continue;
21121 }
21122 if (child.type === 'Text') {
21123 let { data } = child;
21124 // We want to remove trailing whitespace inside an element/component/block,
21125 // *unless* there is no whitespace between this node and its next sibling
21126 if (this.nodes.length === 0) {
21127 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'));
21128 if (should_trim) {
21129 data = trim_end(data);
21130 if (!data)
21131 continue;
21132 }
21133 }
21134 // glue text nodes (which could e.g. be separated by comments) together
21135 if (last_child && last_child.node.type === 'Text') {
21136 last_child.data = data + last_child.data;
21137 continue;
21138 }
21139 const wrapper = new TextWrapper(renderer, block, parent, child, data);
21140 if (wrapper.skip)
21141 continue;
21142 this.nodes.unshift(wrapper);
21143 link(last_child, last_child = wrapper);
21144 }
21145 else {
21146 const Wrapper = wrappers[child.type];
21147 if (!Wrapper)
21148 continue;
21149 const wrapper = new Wrapper(renderer, block, parent, child, strip_whitespace, last_child || next_sibling);
21150 this.nodes.unshift(wrapper);
21151 link(last_child, last_child = wrapper);
21152 }
21153 }
21154 if (strip_whitespace) {
21155 const first = this.nodes[0];
21156 if (first && first.node.type === 'Text') {
21157 first.data = trim_start(first.data);
21158 if (!first.data) {
21159 first.var = null;
21160 this.nodes.shift();
21161 if (this.nodes[0]) {
21162 this.nodes[0].prev = null;
21163 }
21164 }
21165 }
21166 }
21167 if (window_wrapper) {
21168 this.nodes.unshift(window_wrapper);
21169 link(last_child, window_wrapper);
21170 }
21171 }
21172 render(block, parent_node, parent_nodes) {
21173 for (let i = 0; i < this.nodes.length; i += 1) {
21174 this.nodes[i].render(block, parent_node, parent_nodes);
21175 }
21176 }
21177 }
21178
21179 class Renderer {
21180 constructor(component, options) {
21181 this.context = [];
21182 this.initial_context = [];
21183 this.context_lookup = new Map();
21184 this.blocks = [];
21185 this.readonly = new Set();
21186 this.meta_bindings = []; // initial values for e.g. window.innerWidth, if there's a <svelte:window> meta tag
21187 this.binding_groups = new Map();
21188 this.component = component;
21189 this.options = options;
21190 this.locate = component.locate; // TODO messy
21191 this.file_var = options.dev && this.component.get_unique_name('file');
21192 component.vars.filter(v => !v.hoistable || (v.export_name && !v.module)).forEach(v => this.add_to_context(v.name));
21193 // ensure store values are included in context
21194 component.vars.filter(v => v.subscribable).forEach(v => this.add_to_context(`$${v.name}`));
21195 reserved_keywords.forEach(keyword => {
21196 if (component.var_lookup.has(keyword)) {
21197 this.add_to_context(keyword);
21198 }
21199 });
21200 if (component.slots.size > 0) {
21201 this.add_to_context('$$scope');
21202 this.add_to_context('#slots');
21203 }
21204 if (this.binding_groups.size > 0) {
21205 this.add_to_context('$$binding_groups');
21206 }
21207 // main block
21208 this.block = new Block$1({
21209 renderer: this,
21210 name: null,
21211 type: 'component',
21212 key: null,
21213 bindings: new Map(),
21214 dependencies: new Set()
21215 });
21216 this.block.has_update_method = true;
21217 this.fragment = new FragmentWrapper(this, this.block, component.fragment.children, null, true, null);
21218 // TODO messy
21219 this.blocks.forEach(block => {
21220 if (block instanceof Block$1) {
21221 block.assign_variable_names();
21222 }
21223 });
21224 this.block.assign_variable_names();
21225 this.fragment.render(this.block, null, x `#nodes`);
21226 this.context_overflow = this.context.length > 31;
21227 this.context.forEach(member => {
21228 const { variable } = member;
21229 if (variable) {
21230 member.priority += 2;
21231 if (variable.mutated || variable.reassigned)
21232 member.priority += 4;
21233 // these determine whether variable is included in initial context
21234 // array, so must have the highest priority
21235 if (variable.is_reactive_dependency && (variable.mutated || variable.reassigned))
21236 member.priority += 16;
21237 if (variable.export_name)
21238 member.priority += 32;
21239 if (variable.referenced)
21240 member.priority += 64;
21241 }
21242 else if (member.is_non_contextual) {
21243 // determine whether variable is included in initial context
21244 // array, so must have the highest priority
21245 member.priority += 8;
21246 }
21247 if (!member.is_contextual) {
21248 member.priority += 1;
21249 }
21250 });
21251 this.context.sort((a, b) => (b.priority - a.priority) || (a.index.value - b.index.value));
21252 this.context.forEach((member, i) => member.index.value = i);
21253 let i = this.context.length;
21254 while (i--) {
21255 const member = this.context[i];
21256 if (member.variable) {
21257 if (member.variable.referenced || member.variable.export_name || (member.variable.is_reactive_dependency && (member.variable.mutated || member.variable.reassigned)))
21258 break;
21259 }
21260 else if (member.is_non_contextual) {
21261 break;
21262 }
21263 }
21264 this.initial_context = this.context.slice(0, i + 1);
21265 }
21266 add_to_context(name, contextual = false) {
21267 if (!this.context_lookup.has(name)) {
21268 const member = {
21269 name,
21270 index: { type: 'Literal', value: this.context.length },
21271 is_contextual: false,
21272 is_non_contextual: false,
21273 variable: null,
21274 priority: 0
21275 };
21276 this.context_lookup.set(name, member);
21277 this.context.push(member);
21278 }
21279 const member = this.context_lookup.get(name);
21280 if (contextual) {
21281 member.is_contextual = true;
21282 }
21283 else {
21284 member.is_non_contextual = true;
21285 member.variable = this.component.var_lookup.get(name);
21286 }
21287 return member;
21288 }
21289 invalidate(name, value, main_execution_context = false) {
21290 return renderer_invalidate(this, name, value, main_execution_context);
21291 }
21292 dirty(names, is_reactive_declaration = false) {
21293 const renderer = this;
21294 const dirty = (is_reactive_declaration
21295 ? x `$$self.$$.dirty`
21296 : x `#dirty`);
21297 const get_bitmask = () => {
21298 const bitmask = [];
21299 names.forEach((name) => {
21300 const member = renderer.context_lookup.get(name);
21301 if (!member)
21302 return;
21303 if (member.index.value === -1) {
21304 throw new Error('unset index');
21305 }
21306 const value = member.index.value;
21307 const i = (value / 31) | 0;
21308 const n = 1 << (value % 31);
21309 if (!bitmask[i])
21310 bitmask[i] = { n: 0, names: [] };
21311 bitmask[i].n |= n;
21312 bitmask[i].names.push(name);
21313 });
21314 return bitmask;
21315 };
21316 // TODO: context-overflow make it less gross
21317 return {
21318 // Using a ParenthesizedExpression allows us to create
21319 // the expression lazily. TODO would be better if
21320 // context was determined before rendering, so that
21321 // this indirection was unnecessary
21322 type: 'ParenthesizedExpression',
21323 get expression() {
21324 const bitmask = get_bitmask();
21325 if (!bitmask.length) {
21326 return x `${dirty} & /*${names.join(', ')}*/ 0`;
21327 }
21328 if (renderer.context_overflow) {
21329 return bitmask
21330 .map((b, i) => ({ b, i }))
21331 .filter(({ b }) => b)
21332 .map(({ b, i }) => x `${dirty}[${i}] & /*${b.names.join(', ')}*/ ${b.n}`)
21333 .reduce((lhs, rhs) => x `${lhs} | ${rhs}`);
21334 }
21335 return x `${dirty} & /*${names.join(', ')}*/ ${bitmask[0].n}`;
21336 }
21337 };
21338 }
21339 reference(node) {
21340 if (typeof node === 'string') {
21341 node = { type: 'Identifier', name: node };
21342 }
21343 const { name, nodes } = flatten_reference(node);
21344 const member = this.context_lookup.get(name);
21345 // TODO is this correct?
21346 if (this.component.var_lookup.get(name)) {
21347 this.component.add_reference(name);
21348 }
21349 if (member !== undefined) {
21350 const replacement = x `/*${member.name}*/ #ctx[${member.index}]`;
21351 if (nodes[0].loc)
21352 replacement.object.loc = nodes[0].loc;
21353 nodes[0] = replacement;
21354 return nodes.reduce((lhs, rhs) => x `${lhs}.${rhs}`);
21355 }
21356 return node;
21357 }
21358 remove_block(block) {
21359 this.blocks.splice(this.blocks.indexOf(block), 1);
21360 }
21361 }
21362
21363 var charToInteger$1 = {};
21364 var chars$1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
21365 for (var i$2 = 0; i$2 < chars$1.length; i$2++) {
21366 charToInteger$1[chars$1.charCodeAt(i$2)] = i$2;
21367 }
21368 function decode$1(mappings) {
21369 var decoded = [];
21370 var line = [];
21371 var segment = [
21372 0,
21373 0,
21374 0,
21375 0,
21376 0,
21377 ];
21378 var j = 0;
21379 for (var i = 0, shift = 0, value = 0; i < mappings.length; i++) {
21380 var c = mappings.charCodeAt(i);
21381 if (c === 44) { // ","
21382 segmentify$1(line, segment, j);
21383 j = 0;
21384 }
21385 else if (c === 59) { // ";"
21386 segmentify$1(line, segment, j);
21387 j = 0;
21388 decoded.push(line);
21389 line = [];
21390 segment[0] = 0;
21391 }
21392 else {
21393 var integer = charToInteger$1[c];
21394 if (integer === undefined) {
21395 throw new Error('Invalid character (' + String.fromCharCode(c) + ')');
21396 }
21397 var hasContinuationBit = integer & 32;
21398 integer &= 31;
21399 value += integer << shift;
21400 if (hasContinuationBit) {
21401 shift += 5;
21402 }
21403 else {
21404 var shouldNegate = value & 1;
21405 value >>>= 1;
21406 if (shouldNegate) {
21407 value = value === 0 ? -0x80000000 : -value;
21408 }
21409 segment[j] += value;
21410 j++;
21411 value = shift = 0; // reset
21412 }
21413 }
21414 }
21415 segmentify$1(line, segment, j);
21416 decoded.push(line);
21417 return decoded;
21418 }
21419 function segmentify$1(line, segment, j) {
21420 // This looks ugly, but we're creating specialized arrays with a specific
21421 // length. This is much faster than creating a new array (which v8 expands to
21422 // a capacity of 17 after pushing the first item), or slicing out a subarray
21423 // (which is slow). Length 4 is assumed to be the most frequent, followed by
21424 // length 5 (since not everything will have an associated name), followed by
21425 // length 1 (it's probably rare for a source substring to not have an
21426 // associated segment data).
21427 if (j === 4)
21428 line.push([segment[0], segment[1], segment[2], segment[3]]);
21429 else if (j === 5)
21430 line.push([segment[0], segment[1], segment[2], segment[3], segment[4]]);
21431 else if (j === 1)
21432 line.push([segment[0]]);
21433 }
21434 function encode$1(decoded) {
21435 var sourceFileIndex = 0; // second field
21436 var sourceCodeLine = 0; // third field
21437 var sourceCodeColumn = 0; // fourth field
21438 var nameIndex = 0; // fifth field
21439 var mappings = '';
21440 for (var i = 0; i < decoded.length; i++) {
21441 var line = decoded[i];
21442 if (i > 0)
21443 mappings += ';';
21444 if (line.length === 0)
21445 continue;
21446 var generatedCodeColumn = 0; // first field
21447 var lineMappings = [];
21448 for (var _i = 0, line_1 = line; _i < line_1.length; _i++) {
21449 var segment = line_1[_i];
21450 var segmentMappings = encodeInteger$1(segment[0] - generatedCodeColumn);
21451 generatedCodeColumn = segment[0];
21452 if (segment.length > 1) {
21453 segmentMappings +=
21454 encodeInteger$1(segment[1] - sourceFileIndex) +
21455 encodeInteger$1(segment[2] - sourceCodeLine) +
21456 encodeInteger$1(segment[3] - sourceCodeColumn);
21457 sourceFileIndex = segment[1];
21458 sourceCodeLine = segment[2];
21459 sourceCodeColumn = segment[3];
21460 }
21461 if (segment.length === 5) {
21462 segmentMappings += encodeInteger$1(segment[4] - nameIndex);
21463 nameIndex = segment[4];
21464 }
21465 lineMappings.push(segmentMappings);
21466 }
21467 mappings += lineMappings.join(',');
21468 }
21469 return mappings;
21470 }
21471 function encodeInteger$1(num) {
21472 var result = '';
21473 num = num < 0 ? (-num << 1) | 1 : num << 1;
21474 do {
21475 var clamped = num & 31;
21476 num >>>= 5;
21477 if (num > 0) {
21478 clamped |= 32;
21479 }
21480 result += chars$1[clamped];
21481 } while (num > 0);
21482 return result;
21483 }
21484
21485 /**
21486 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21487 *
21488 * Licensed under the Apache License, Version 2.0 (the "License");
21489 * you may not use this file except in compliance with the License.
21490 * You may obtain a copy of the License at
21491 *
21492 * http://www.apache.org/licenses/LICENSE-2.0
21493 *
21494 * Unless required by applicable law or agreed to in writing, software
21495 * distributed under the License is distributed on an "AS IS" BASIS,
21496 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21497 * See the License for the specific language governing permissions and
21498 * limitations under the License.
21499 */
21500 /**
21501 * Creates a brand new (prototype-less) object with the enumerable-own
21502 * properties of `target`. Any enumerable-own properties from `source` which
21503 * are not present on `target` will be copied as well.
21504 */
21505 function defaults(target, source) {
21506 return Object.assign(Object.create(null), source, target);
21507 }
21508
21509 /**
21510 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21511 *
21512 * Licensed under the Apache License, Version 2.0 (the "License");
21513 * you may not use this file except in compliance with the License.
21514 * You may obtain a copy of the License at
21515 *
21516 * http://www.apache.org/licenses/LICENSE-2.0
21517 *
21518 * Unless required by applicable law or agreed to in writing, software
21519 * distributed under the License is distributed on an "AS IS" BASIS,
21520 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21521 * See the License for the specific language governing permissions and
21522 * limitations under the License.
21523 */
21524 /**
21525 * Decodes an input sourcemap into a `DecodedSourceMap` sourcemap object.
21526 *
21527 * Valid input maps include a `DecodedSourceMap`, a `RawSourceMap`, or JSON
21528 * representations of either type.
21529 */
21530 function decodeSourceMap(map) {
21531 if (typeof map === 'string') {
21532 map = JSON.parse(map);
21533 }
21534 let { mappings } = map;
21535 if (typeof mappings === 'string') {
21536 mappings = decode$1(mappings);
21537 }
21538 else {
21539 // Clone the Line so that we can sort it. We don't want to mutate an array
21540 // that we don't own directly.
21541 mappings = mappings.map(cloneSegmentLine);
21542 }
21543 // Sort each Line's segments. There's no guarantee that segments are sorted for us,
21544 // and even Chrome's implementation sorts:
21545 // https://cs.chromium.org/chromium/src/third_party/devtools-frontend/src/front_end/sdk/SourceMap.js?l=507-508&rcl=109232bcf479c8f4ef8ead3cf56c49eb25f8c2f0
21546 mappings.forEach(sortSegments);
21547 return defaults({ mappings }, map);
21548 }
21549 function cloneSegmentLine(segments) {
21550 return segments.slice();
21551 }
21552 function sortSegments(segments) {
21553 segments.sort(segmentComparator);
21554 }
21555 function segmentComparator(a, b) {
21556 return a[0] - b[0];
21557 }
21558
21559 /**
21560 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21561 *
21562 * Licensed under the Apache License, Version 2.0 (the "License");
21563 * you may not use this file except in compliance with the License.
21564 * You may obtain a copy of the License at
21565 *
21566 * http://www.apache.org/licenses/LICENSE-2.0
21567 *
21568 * Unless required by applicable law or agreed to in writing, software
21569 * distributed under the License is distributed on an "AS IS" BASIS,
21570 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21571 * See the License for the specific language governing permissions and
21572 * limitations under the License.
21573 */
21574 /**
21575 * A "leaf" node in the sourcemap tree, representing an original, unmodified
21576 * source file. Recursive segment tracing ends at the `OriginalSource`.
21577 */
21578 class OriginalSource {
21579 constructor(filename, content) {
21580 this.filename = filename;
21581 this.content = content;
21582 }
21583 /**
21584 * Tracing a `SourceMapSegment` ends when we get to an `OriginalSource`,
21585 * meaning this line/column location originated from this source file.
21586 */
21587 traceSegment(line, column, name) {
21588 return { column, line, name, source: this };
21589 }
21590 }
21591
21592 /* istanbul ignore next */
21593 const Url$1 = (typeof URL !== 'undefined' ? URL : require('url').URL);
21594 // Matches "..", which must be preceeded by "/" or the start of the string, and
21595 // must be followed by a "/". We do not eat the following "/", so that the next
21596 // iteration can match on it.
21597 const parentRegex = /(^|\/)\.\.(?=\/|$)/g;
21598 function isAbsoluteUrl(url) {
21599 try {
21600 return !!new Url$1(url);
21601 }
21602 catch (e) {
21603 return false;
21604 }
21605 }
21606 /**
21607 * Creates a directory name that is guaranteed to not be in `str`.
21608 */
21609 function uniqInStr(str) {
21610 let uniq = String(Math.random()).slice(2);
21611 while (str.indexOf(uniq) > -1) {
21612 /* istanbul ignore next */
21613 uniq += uniq;
21614 }
21615 return uniq;
21616 }
21617 /**
21618 * Removes the filename from the path (everything trailing the last "/"). This
21619 * is only safe to call on a path, never call with an absolute or protocol
21620 * relative URL.
21621 */
21622 function stripPathFilename(path) {
21623 path = normalizePath(path);
21624 const index = path.lastIndexOf('/');
21625 return path.slice(0, index + 1);
21626 }
21627 /**
21628 * Normalizes a protocol-relative URL, but keeps it protocol relative by
21629 * stripping out the protocl before returning it.
21630 */
21631 function normalizeProtocolRelative(input, absoluteBase) {
21632 const { href, protocol } = new Url$1(input, absoluteBase);
21633 return href.slice(protocol.length);
21634 }
21635 /**
21636 * Normalizes a simple path (one that has no ".."s, or is absolute so ".."s can
21637 * be normalized absolutely).
21638 */
21639 function normalizeSimplePath(input) {
21640 const { href } = new Url$1(input, 'https://foo.com/');
21641 return href.slice('https://foo.com/'.length);
21642 }
21643 /**
21644 * Normalizes a path, ensuring that excess ".."s are preserved for relative
21645 * paths in the output.
21646 *
21647 * If the input is absolute, this will return an absolutey normalized path, but
21648 * it will not have a leading "/".
21649 *
21650 * If the input has a leading "..", the output will have a leading "..".
21651 *
21652 * If the input has a leading ".", the output will not have a leading "."
21653 * unless there are too many ".."s, in which case there will be a leading "..".
21654 */
21655 function normalizePath(input) {
21656 // If there are no ".."s, we can treat this as if it were an absolute path.
21657 // The return won't be an absolute path, so it's easy.
21658 if (!parentRegex.test(input))
21659 return normalizeSimplePath(input);
21660 // We already found one "..". Let's see how many there are.
21661 let total = 1;
21662 while (parentRegex.test(input))
21663 total++;
21664 // If there are ".."s, we need to prefix the the path with the same number of
21665 // unique directories. This is to ensure that we "remember" how many parent
21666 // directories we are accessing. Eg, "../../.." must keep 3, and "foo/../.."
21667 // must keep 1.
21668 const uniqDirectory = `z${uniqInStr(input)}/`;
21669 // uniqDirectory is just a "z", followed by numbers, followed by a "/". So
21670 // generating a runtime regex from it is safe. We'll use this search regex to
21671 // strip out our uniq directory names and insert any needed ".."s.
21672 const search = new RegExp(`^(?:${uniqDirectory})*`);
21673 // Now we can resolve the total path. If there are excess ".."s, they will
21674 // eliminate one or more of the unique directories we prefix with.
21675 const relative = normalizeSimplePath(uniqDirectory.repeat(total) + input);
21676 // We can now count the number of unique directories that were eliminated. If
21677 // there were 3, and 1 was eliminated, we know we only need to add 1 "..". If
21678 // 2 were eliminated, we need to insert 2 ".."s. If all 3 were eliminated,
21679 // then we need 3, etc. This replace is guranteed to match (it may match 0 or
21680 // more times), and we can count the total match to see how many were eliminated.
21681 return relative.replace(search, (all) => {
21682 const leftover = all.length / uniqDirectory.length;
21683 return '../'.repeat(total - leftover);
21684 });
21685 }
21686 /**
21687 * Attempts to resolve `input` URL relative to `base`.
21688 */
21689 function resolve(input, base) {
21690 if (!base)
21691 base = '';
21692 // Absolute URLs are very easy to resolve right.
21693 if (isAbsoluteUrl(input))
21694 return new Url$1(input).href;
21695 if (base) {
21696 // Absolute URLs are easy...
21697 if (isAbsoluteUrl(base))
21698 return new Url$1(input, base).href;
21699 // If base is protocol relative, we'll resolve with it but keep the result
21700 // protocol relative.
21701 if (base.startsWith('//'))
21702 return normalizeProtocolRelative(input, `https:${base}`);
21703 }
21704 // Normalize input, but keep it protocol relative. We know base doesn't supply
21705 // a protocol, because that would have been handled above.
21706 if (input.startsWith('//'))
21707 return normalizeProtocolRelative(input, 'https://foo.com/');
21708 // We now know that base (if there is one) and input are paths. We've handled
21709 // both absolute and protocol-relative variations above.
21710 // Absolute paths don't need any special handling, because they cannot have
21711 // extra "." or ".."s. That'll all be stripped away. Input takes priority here,
21712 // because if input is an absolute path, base path won't affect it in any way.
21713 if (input.startsWith('/'))
21714 return '/' + normalizeSimplePath(input);
21715 // Since input and base are paths, we need to join them to do any further
21716 // processing. Paths are joined at the directory level, so we need to remove
21717 // the base's filename before joining. We also know that input does not have a
21718 // leading slash, and that the stripped base will have a trailing slash if
21719 // there are any directories (or it'll be empty).
21720 const joined = stripPathFilename(base) + input;
21721 // If base is an absolute path, then input will be relative to it.
21722 if (base.startsWith('/'))
21723 return '/' + normalizeSimplePath(joined);
21724 // We now know both base (if there is one) and input are relative paths.
21725 const relative = normalizePath(joined);
21726 // If base started with a leading ".", or there is no base and input started
21727 // with a ".", then we need to ensure that the relative path starts with a
21728 // ".". We don't know if relative starts with a "..", though, so check before
21729 // prepending.
21730 if ((base || input).startsWith('.') && !relative.startsWith('.')) {
21731 return './' + relative;
21732 }
21733 return relative;
21734 }
21735
21736 /**
21737 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21738 *
21739 * Licensed under the Apache License, Version 2.0 (the "License");
21740 * you may not use this file except in compliance with the License.
21741 * You may obtain a copy of the License at
21742 *
21743 * http://www.apache.org/licenses/LICENSE-2.0
21744 *
21745 * Unless required by applicable law or agreed to in writing, software
21746 * distributed under the License is distributed on an "AS IS" BASIS,
21747 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21748 * See the License for the specific language governing permissions and
21749 * limitations under the License.
21750 */
21751 function resolve$1(input, base) {
21752 // The base is always treated as a directory, if it's not empty.
21753 // https://github.com/mozilla/source-map/blob/8cb3ee57/lib/util.js#L327
21754 // https://github.com/chromium/chromium/blob/da4adbb3/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js#L400-L401
21755 if (base && !base.endsWith('/'))
21756 base += '/';
21757 return resolve(input, base);
21758 }
21759
21760 /**
21761 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21762 *
21763 * Licensed under the Apache License, Version 2.0 (the "License");
21764 * you may not use this file except in compliance with the License.
21765 * You may obtain a copy of the License at
21766 *
21767 * http://www.apache.org/licenses/LICENSE-2.0
21768 *
21769 * Unless required by applicable law or agreed to in writing, software
21770 * distributed under the License is distributed on an "AS IS" BASIS,
21771 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21772 * See the License for the specific language governing permissions and
21773 * limitations under the License.
21774 */
21775 /**
21776 * A binary search implementation that returns the index if a match is found,
21777 * or the negated index of where the `needle` should be inserted.
21778 *
21779 * The `comparator` callback receives both the `item` under comparison and the
21780 * needle we are searching for. It must return `0` if the `item` is a match,
21781 * any negative number if `item` is too small (and we must search after it), or
21782 * any positive number if the `item` is too large (and we must search before
21783 * it).
21784 *
21785 * If no match is found, a negated index of where to insert the `needle` is
21786 * returned. This negated index is guaranteed to be less than 0. To insert an
21787 * item, negate it (again) and splice:
21788 *
21789 * ```js
21790 * const array = [1, 3];
21791 * const needle = 2;
21792 * const index = binarySearch(array, needle, (item, needle) => item - needle);
21793 *
21794 * assert.equal(index, -2);
21795 * assert.equal(~index, 1);
21796 * array.splice(~index, 0, needle);
21797 * assert.deepEqual(array, [1, 2, 3]);
21798 * ```
21799 */
21800 function binarySearch(haystack, needle, comparator) {
21801 let low = 0;
21802 let high = haystack.length - 1;
21803 while (low <= high) {
21804 const mid = low + ((high - low) >> 1);
21805 const cmp = comparator(haystack[mid], needle);
21806 if (cmp === 0) {
21807 return mid;
21808 }
21809 if (cmp < 0) {
21810 low = mid + 1;
21811 }
21812 else {
21813 high = mid - 1;
21814 }
21815 }
21816 return ~low;
21817 }
21818
21819 /**
21820 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21821 *
21822 * Licensed under the Apache License, Version 2.0 (the "License");
21823 * you may not use this file except in compliance with the License.
21824 * You may obtain a copy of the License at
21825 *
21826 * http://www.apache.org/licenses/LICENSE-2.0
21827 *
21828 * Unless required by applicable law or agreed to in writing, software
21829 * distributed under the License is distributed on an "AS IS" BASIS,
21830 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21831 * See the License for the specific language governing permissions and
21832 * limitations under the License.
21833 */
21834 /**
21835 * FastStringArray acts like a `Set` (allowing only one occurrence of a string
21836 * `key`), but provides the index of the `key` in the backing array.
21837 *
21838 * This is designed to allow synchronizing a second array with the contents of
21839 * the backing array, like how `sourcesContent[i]` is the source content
21840 * associated with `source[i]`, and there are never duplicates.
21841 */
21842 class FastStringArray {
21843 constructor() {
21844 this.indexes = Object.create(null);
21845 this.array = [];
21846 }
21847 /**
21848 * Puts `key` into the backing array, if it is not already present. Returns
21849 * the index of the `key` in the backing array.
21850 */
21851 put(key) {
21852 const { array, indexes } = this;
21853 // The key may or may not be present. If it is present, it's a number.
21854 let index = indexes[key];
21855 // If it's not yet present, we need to insert it and track the index in the
21856 // indexes.
21857 if (index === undefined) {
21858 index = indexes[key] = array.length;
21859 array.push(key);
21860 }
21861 return index;
21862 }
21863 }
21864
21865 /**
21866 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21867 *
21868 * Licensed under the Apache License, Version 2.0 (the "License");
21869 * you may not use this file except in compliance with the License.
21870 * You may obtain a copy of the License at
21871 *
21872 * http://www.apache.org/licenses/LICENSE-2.0
21873 *
21874 * Unless required by applicable law or agreed to in writing, software
21875 * distributed under the License is distributed on an "AS IS" BASIS,
21876 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21877 * See the License for the specific language governing permissions and
21878 * limitations under the License.
21879 */
21880 /**
21881 * SourceMapTree represents a single sourcemap, with the ability to trace
21882 * mappings into its child nodes (which may themselves be SourceMapTrees).
21883 */
21884 class SourceMapTree {
21885 constructor(map, sources) {
21886 this.map = map;
21887 this.sources = sources;
21888 }
21889 /**
21890 * traceMappings is only called on the root level SourceMapTree, and begins
21891 * the process of resolving each mapping in terms of the original source
21892 * files.
21893 */
21894 traceMappings() {
21895 const mappings = [];
21896 const names = new FastStringArray();
21897 const sources = new FastStringArray();
21898 const sourcesContent = [];
21899 const { mappings: rootMappings, names: rootNames } = this.map;
21900 for (let i = 0; i < rootMappings.length; i++) {
21901 const segments = rootMappings[i];
21902 const tracedSegments = [];
21903 for (let j = 0; j < segments.length; j++) {
21904 const segment = segments[j];
21905 // 1-length segments only move the current generated column, there's no
21906 // source information to gather from it.
21907 if (segment.length === 1)
21908 continue;
21909 const source = this.sources[segment[1]];
21910 const traced = source.traceSegment(segment[2], segment[3], segment.length === 5 ? rootNames[segment[4]] : '');
21911 if (!traced)
21912 continue;
21913 // So we traced a segment down into its original source file. Now push a
21914 // new segment pointing to this location.
21915 const { column, line, name } = traced;
21916 const { content, filename } = traced.source;
21917 // Store the source location, and ensure we keep sourcesContent up to
21918 // date with the sources array.
21919 const sourceIndex = sources.put(filename);
21920 sourcesContent[sourceIndex] = content;
21921 // This looks like unnecessary duplication, but it noticeably increases
21922 // performance. If we were to push the nameIndex onto length-4 array, v8
21923 // would internally allocate 22 slots! That's 68 wasted bytes! Array
21924 // literals have the same capacity as their length, saving memory.
21925 if (name) {
21926 tracedSegments.push([segment[0], sourceIndex, line, column, names.put(name)]);
21927 }
21928 else {
21929 tracedSegments.push([segment[0], sourceIndex, line, column]);
21930 }
21931 }
21932 mappings.push(tracedSegments);
21933 }
21934 // TODO: Make all sources relative to the sourceRoot.
21935 return defaults({
21936 mappings,
21937 names: names.array,
21938 sources: sources.array,
21939 sourcesContent,
21940 }, this.map);
21941 }
21942 /**
21943 * traceSegment is only called on children SourceMapTrees. It recurses down
21944 * into its own child SourceMapTrees, until we find the original source map.
21945 */
21946 traceSegment(line, column, name) {
21947 const { mappings, names } = this.map;
21948 // It's common for parent sourcemaps to have pointers to lines that have no
21949 // mapping (like a "//# sourceMappingURL=") at the end of the child file.
21950 if (line >= mappings.length)
21951 return null;
21952 const segments = mappings[line];
21953 if (segments.length === 0)
21954 return null;
21955 let index = binarySearch(segments, column, segmentComparator$1);
21956 if (index === -1)
21957 return null; // we come before any mapped segment
21958 // If we can't find a segment that lines up to this column, we use the
21959 // segment before.
21960 if (index < 0) {
21961 index = ~index - 1;
21962 }
21963 const segment = segments[index];
21964 // 1-length segments only move the current generated column, there's no
21965 // source information to gather from it.
21966 if (segment.length === 1)
21967 return null;
21968 const source = this.sources[segment[1]];
21969 // So now we can recurse down, until we hit the original source file.
21970 return source.traceSegment(segment[2], segment[3],
21971 // A child map's recorded name for this segment takes precedence over the
21972 // parent's mapped name. Imagine a mangler changing the name over, etc.
21973 segment.length === 5 ? names[segment[4]] : name);
21974 }
21975 }
21976 function segmentComparator$1(segment, column) {
21977 return segment[0] - column;
21978 }
21979
21980 /**
21981 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
21982 *
21983 * Licensed under the Apache License, Version 2.0 (the "License");
21984 * you may not use this file except in compliance with the License.
21985 * You may obtain a copy of the License at
21986 *
21987 * http://www.apache.org/licenses/LICENSE-2.0
21988 *
21989 * Unless required by applicable law or agreed to in writing, software
21990 * distributed under the License is distributed on an "AS IS" BASIS,
21991 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21992 * See the License for the specific language governing permissions and
21993 * limitations under the License.
21994 */
21995 /**
21996 * Removes the filename from a path.
21997 */
21998 function stripFilename(path) {
21999 if (!path)
22000 return '';
22001 const index = path.lastIndexOf('/');
22002 return path.slice(0, index + 1);
22003 }
22004
22005 /**
22006 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
22007 *
22008 * Licensed under the Apache License, Version 2.0 (the "License");
22009 * you may not use this file except in compliance with the License.
22010 * You may obtain a copy of the License at
22011 *
22012 * http://www.apache.org/licenses/LICENSE-2.0
22013 *
22014 * Unless required by applicable law or agreed to in writing, software
22015 * distributed under the License is distributed on an "AS IS" BASIS,
22016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22017 * See the License for the specific language governing permissions and
22018 * limitations under the License.
22019 */
22020 function asArray(value) {
22021 if (Array.isArray(value))
22022 return value;
22023 return [value];
22024 }
22025 /**
22026 * Recursively builds a tree structure out of sourcemap files, with each node
22027 * being either an `OriginalSource` "leaf" or a `SourceMapTree` composed of
22028 * `OriginalSource`s and `SourceMapTree`s.
22029 *
22030 * Every sourcemap is composed of a collection of source files and mappings
22031 * into locations of those source files. When we generate a `SourceMapTree` for
22032 * the sourcemap, we attempt to load each source file's own sourcemap. If it
22033 * does not have an associated sourcemap, it is considered an original,
22034 * unmodified source file.
22035 */
22036 function buildSourceMapTree(input, loader, relativeRoot) {
22037 const maps = asArray(input).map(decodeSourceMap);
22038 const map = maps.pop();
22039 for (let i = 0; i < maps.length; i++) {
22040 if (maps[i].sources.length !== 1) {
22041 throw new Error(`Transformation map ${i} must have exactly one source file.\n` +
22042 'Did you specify these with the most recent transformation maps first?');
22043 }
22044 }
22045 const { sourceRoot, sources, sourcesContent } = map;
22046 const children = sources.map((sourceFile, i) => {
22047 // Each source file is loaded relative to the sourcemap's own sourceRoot,
22048 // which is itself relative to the sourcemap's parent.
22049 const uri = resolve$1(sourceFile || '', resolve$1(sourceRoot || '', stripFilename(relativeRoot)));
22050 // Use the provided loader callback to retrieve the file's sourcemap.
22051 // TODO: We should eventually support async loading of sourcemap files.
22052 const sourceMap = loader(uri);
22053 // If there is no sourcemap, then it is an unmodified source file.
22054 if (!sourceMap) {
22055 // The source file's actual contents must be included in the sourcemap
22056 // (done when generating the sourcemap) for it to be included as a
22057 // sourceContent in the output sourcemap.
22058 const sourceContent = sourcesContent ? sourcesContent[i] : null;
22059 return new OriginalSource(uri, sourceContent);
22060 }
22061 // Else, it's a real sourcemap, and we need to recurse into it to load its
22062 // source files.
22063 return buildSourceMapTree(decodeSourceMap(sourceMap), loader, uri);
22064 });
22065 let tree = new SourceMapTree(map, children);
22066 for (let i = maps.length - 1; i >= 0; i--) {
22067 tree = new SourceMapTree(maps[i], [tree]);
22068 }
22069 return tree;
22070 }
22071
22072 /**
22073 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
22074 *
22075 * Licensed under the Apache License, Version 2.0 (the "License");
22076 * you may not use this file except in compliance with the License.
22077 * You may obtain a copy of the License at
22078 *
22079 * http://www.apache.org/licenses/LICENSE-2.0
22080 *
22081 * Unless required by applicable law or agreed to in writing, software
22082 * distributed under the License is distributed on an "AS IS" BASIS,
22083 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22084 * See the License for the specific language governing permissions and
22085 * limitations under the License.
22086 */
22087 /**
22088 * A SourceMap v3 compatible sourcemap, which only includes fields that were
22089 * provided to it.
22090 */
22091 class SourceMap {
22092 constructor(map, excludeContent) {
22093 this.version = 3; // SourceMap spec says this should be first.
22094 if ('file' in map)
22095 this.file = map.file;
22096 this.mappings = encode$1(map.mappings);
22097 this.names = map.names;
22098 // TODO: We first need to make all source URIs relative to the sourceRoot
22099 // before we can support a sourceRoot.
22100 // if ('sourceRoot' in map) this.sourceRoot = map.sourceRoot;
22101 this.sources = map.sources;
22102 if (!excludeContent && 'sourcesContent' in map)
22103 this.sourcesContent = map.sourcesContent;
22104 }
22105 toString() {
22106 return JSON.stringify(this);
22107 }
22108 }
22109
22110 /**
22111 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
22112 *
22113 * Licensed under the Apache License, Version 2.0 (the "License");
22114 * you may not use this file except in compliance with the License.
22115 * You may obtain a copy of the License at
22116 *
22117 * http://www.apache.org/licenses/LICENSE-2.0
22118 *
22119 * Unless required by applicable law or agreed to in writing, software
22120 * distributed under the License is distributed on an "AS IS" BASIS,
22121 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22122 * See the License for the specific language governing permissions and
22123 * limitations under the License.
22124 */
22125 /**
22126 * Traces through all the mappings in the root sourcemap, through the sources
22127 * (and their sourcemaps), all the way back to the original source location.
22128 *
22129 * `loader` will be called every time we encounter a source file. If it returns
22130 * a sourcemap, we will recurse into that sourcemap to continue the trace. If
22131 * it returns a falsey value, that source file is treated as an original,
22132 * unmodified source file.
22133 *
22134 * Pass `excludeContent` content to exclude any self-containing source file
22135 * content from the output sourcemap.
22136 */
22137 function remapping(input, loader, excludeContent) {
22138 const graph = buildSourceMapTree(input, loader);
22139 return new SourceMap(graph.traceMappings(), !!excludeContent);
22140 }
22141
22142 function last_line_length(s) {
22143 return s.length - s.lastIndexOf('\n') - 1;
22144 }
22145 // mutate map in-place
22146 function sourcemap_add_offset(map, offset, source_index) {
22147 if (map.mappings.length == 0)
22148 return;
22149 for (let line = 0; line < map.mappings.length; line++) {
22150 const segment_list = map.mappings[line];
22151 for (let segment = 0; segment < segment_list.length; segment++) {
22152 const seg = segment_list[segment];
22153 // shift only segments that belong to component source file
22154 if (seg[1] === source_index) { // also ensures that seg.length >= 4
22155 // shift column if it points at the first line
22156 if (seg[2] === 0) {
22157 seg[3] += offset.column;
22158 }
22159 // shift line
22160 seg[2] += offset.line;
22161 }
22162 }
22163 }
22164 }
22165 function merge_tables(this_table, other_table) {
22166 const new_table = this_table.slice();
22167 const idx_map = [];
22168 other_table = other_table || [];
22169 let val_changed = false;
22170 for (const [other_idx, other_val] of other_table.entries()) {
22171 const this_idx = this_table.indexOf(other_val);
22172 if (this_idx >= 0) {
22173 idx_map[other_idx] = this_idx;
22174 }
22175 else {
22176 const new_idx = new_table.length;
22177 new_table[new_idx] = other_val;
22178 idx_map[other_idx] = new_idx;
22179 val_changed = true;
22180 }
22181 }
22182 let idx_changed = val_changed;
22183 if (val_changed) {
22184 if (idx_map.find((val, idx) => val != idx) === undefined) {
22185 // idx_map is identity map [0, 1, 2, 3, 4, ....]
22186 idx_changed = false;
22187 }
22188 }
22189 return [new_table, idx_map, val_changed, idx_changed];
22190 }
22191 function pushArray(_this, other) {
22192 // We use push to mutate in place for memory and perf reasons
22193 // We use the for loop instead of _this.push(...other) to avoid the JS engine's function argument limit (65,535 in JavascriptCore)
22194 for (let i = 0; i < other.length; i++) {
22195 _this.push(other[i]);
22196 }
22197 }
22198 class StringWithSourcemap {
22199 constructor(string = '', map = null) {
22200 this.string = string;
22201 if (map) {
22202 this.map = map;
22203 }
22204 else {
22205 this.map = {
22206 version: 3,
22207 mappings: [],
22208 sources: [],
22209 names: []
22210 };
22211 }
22212 }
22213 /**
22214 * concat in-place (mutable), return this (chainable)
22215 * will also mutate the `other` object
22216 */
22217 concat(other) {
22218 // noop: if one is empty, return the other
22219 if (other.string == '')
22220 return this;
22221 if (this.string == '') {
22222 this.string = other.string;
22223 this.map = other.map;
22224 return this;
22225 }
22226 // compute last line length before mutating
22227 const column_offset = last_line_length(this.string);
22228 this.string += other.string;
22229 const m1 = this.map;
22230 const m2 = other.map;
22231 if (m2.mappings.length == 0)
22232 return this;
22233 // combine sources and names
22234 const [sources, new_source_idx, sources_changed, sources_idx_changed] = merge_tables(m1.sources, m2.sources);
22235 const [names, new_name_idx, names_changed, names_idx_changed] = merge_tables(m1.names, m2.names);
22236 if (sources_changed)
22237 m1.sources = sources;
22238 if (names_changed)
22239 m1.names = names;
22240 // unswitched loops are faster
22241 if (sources_idx_changed && names_idx_changed) {
22242 for (let line = 0; line < m2.mappings.length; line++) {
22243 const segment_list = m2.mappings[line];
22244 for (let segment = 0; segment < segment_list.length; segment++) {
22245 const seg = segment_list[segment];
22246 if (seg[1] >= 0)
22247 seg[1] = new_source_idx[seg[1]];
22248 if (seg[4] >= 0)
22249 seg[4] = new_name_idx[seg[4]];
22250 }
22251 }
22252 }
22253 else if (sources_idx_changed) {
22254 for (let line = 0; line < m2.mappings.length; line++) {
22255 const segment_list = m2.mappings[line];
22256 for (let segment = 0; segment < segment_list.length; segment++) {
22257 const seg = segment_list[segment];
22258 if (seg[1] >= 0)
22259 seg[1] = new_source_idx[seg[1]];
22260 }
22261 }
22262 }
22263 else if (names_idx_changed) {
22264 for (let line = 0; line < m2.mappings.length; line++) {
22265 const segment_list = m2.mappings[line];
22266 for (let segment = 0; segment < segment_list.length; segment++) {
22267 const seg = segment_list[segment];
22268 if (seg[4] >= 0)
22269 seg[4] = new_name_idx[seg[4]];
22270 }
22271 }
22272 }
22273 // combine the mappings
22274 // combine
22275 // 1. last line of first map
22276 // 2. first line of second map
22277 // columns of 2 must be shifted
22278 if (m2.mappings.length > 0 && column_offset > 0) {
22279 const first_line = m2.mappings[0];
22280 for (let i = 0; i < first_line.length; i++) {
22281 first_line[i][0] += column_offset;
22282 }
22283 }
22284 // combine last line + first line
22285 pushArray(m1.mappings[m1.mappings.length - 1], m2.mappings.shift());
22286 // append other lines
22287 pushArray(m1.mappings, m2.mappings);
22288 return this;
22289 }
22290 static from_processed(string, map) {
22291 const line_count = string.split('\n').length;
22292 if (map) {
22293 // ensure that count of source map mappings lines
22294 // is equal to count of generated code lines
22295 // (some tools may produce less)
22296 const missing_lines = line_count - map.mappings.length;
22297 for (let i = 0; i < missing_lines; i++) {
22298 map.mappings.push([]);
22299 }
22300 return new StringWithSourcemap(string, map);
22301 }
22302 if (string == '')
22303 return new StringWithSourcemap();
22304 map = { version: 3, names: [], sources: [], mappings: [] };
22305 // add empty SourceMapSegment[] for every line
22306 for (let i = 0; i < line_count; i++)
22307 map.mappings.push([]);
22308 return new StringWithSourcemap(string, map);
22309 }
22310 static from_source(source_file, source, offset) {
22311 if (!offset)
22312 offset = { line: 0, column: 0 };
22313 const map = { version: 3, names: [], sources: [source_file], mappings: [] };
22314 if (source == '')
22315 return new StringWithSourcemap(source, map);
22316 // we create a high resolution identity map here,
22317 // we know that it will eventually be merged with svelte's map,
22318 // at which stage the resolution will decrease.
22319 const line_list = source.split('\n');
22320 for (let line = 0; line < line_list.length; line++) {
22321 map.mappings.push([]);
22322 const token_list = line_list[line].split(/([^\d\w\s]|\s+)/g);
22323 for (let token = 0, column = 0; token < token_list.length; token++) {
22324 if (token_list[token] == '')
22325 continue;
22326 map.mappings[line].push([column, 0, offset.line + line, column]);
22327 column += token_list[token].length;
22328 }
22329 }
22330 // shift columns in first line
22331 const segment_list = map.mappings[0];
22332 for (let segment = 0; segment < segment_list.length; segment++) {
22333 segment_list[segment][3] += offset.column;
22334 }
22335 return new StringWithSourcemap(source, map);
22336 }
22337 }
22338 function combine_sourcemaps(filename, sourcemap_list) {
22339 if (sourcemap_list.length == 0)
22340 return null;
22341 let map_idx = 1;
22342 const map = sourcemap_list.slice(0, -1)
22343 .find(m => m.sources.length !== 1) === undefined
22344 ? remapping(// use array interface
22345 // only the oldest sourcemap can have multiple sources
22346 sourcemap_list, () => null, true // skip optional field `sourcesContent`
22347 )
22348 : remapping(// use loader interface
22349 sourcemap_list[0], // last map
22350 function loader(sourcefile) {
22351 if (sourcefile === filename && sourcemap_list[map_idx]) {
22352 return sourcemap_list[map_idx++]; // idx 1, 2, ...
22353 // bundle file = branch node
22354 }
22355 else {
22356 return null; // source file = leaf node
22357 }
22358 }, true);
22359 if (!map.file)
22360 delete map.file; // skip optional field `file`
22361 return map;
22362 }
22363 // browser vs node.js
22364 const b64enc = typeof btoa == 'function' ? btoa : b => Buffer.from(b).toString('base64');
22365 function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_map_input) {
22366 if (!svelte_map || !preprocessor_map_input)
22367 return svelte_map;
22368 const preprocessor_map = typeof preprocessor_map_input === 'string' ? JSON.parse(preprocessor_map_input) : preprocessor_map_input;
22369 const result_map = combine_sourcemaps(filename, [
22370 svelte_map,
22371 preprocessor_map
22372 ]);
22373 // Svelte expects a SourceMap which includes toUrl and toString. Instead of wrapping our output in a class,
22374 // we just tack on the extra properties.
22375 Object.defineProperties(result_map, {
22376 toString: {
22377 enumerable: false,
22378 value: function toString() {
22379 return JSON.stringify(this);
22380 }
22381 },
22382 toUrl: {
22383 enumerable: false,
22384 value: function toUrl() {
22385 return 'data:application/json;charset=utf-8;base64,' + b64enc(this.toString());
22386 }
22387 }
22388 });
22389 return result_map;
22390 }
22391
22392 function dom(component, options) {
22393 const { name } = component;
22394 const renderer = new Renderer(component, options);
22395 const { block } = renderer;
22396 block.has_outro_method = true;
22397 // prevent fragment being created twice (#1063)
22398 if (options.customElement)
22399 block.chunks.create.push(b `this.c = @noop;`);
22400 const body = [];
22401 if (renderer.file_var) {
22402 const file = component.file ? x `"${component.file}"` : x `undefined`;
22403 body.push(b `const ${renderer.file_var} = ${file};`);
22404 }
22405 const css = component.stylesheet.render(options.filename, !options.customElement);
22406 css.map = apply_preprocessor_sourcemap(options.filename, css.map, options.sourcemap);
22407 const styles = component.stylesheet.has_styles && options.dev
22408 ? `${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */`
22409 : css.code;
22410 const add_css = component.get_unique_name('add_css');
22411 const should_add_css = (!options.customElement &&
22412 !!styles &&
22413 options.css !== false);
22414 if (should_add_css) {
22415 body.push(b `
22416 function ${add_css}() {
22417 var style = @element("style");
22418 style.id = "${component.stylesheet.id}-style";
22419 style.textContent = "${styles}";
22420 @append(@_document.head, style);
22421 }
22422 `);
22423 }
22424 // fix order
22425 // TODO the deconflicted names of blocks are reversed... should set them here
22426 const blocks = renderer.blocks.slice().reverse();
22427 body.push(...blocks.map(block => {
22428 // TODO this is a horrible mess — renderer.blocks
22429 // contains a mixture of Blocks and Nodes
22430 if (block.render)
22431 return block.render();
22432 return block;
22433 }));
22434 if (options.dev && !options.hydratable) {
22435 block.chunks.claim.push(b `throw new @_Error("options.hydrate only works if the component was compiled with the \`hydratable: true\` option");`);
22436 }
22437 const uses_slots = component.var_lookup.has('$$slots');
22438 let compute_slots;
22439 if (uses_slots) {
22440 compute_slots = b `
22441 const $$slots = @compute_slots(#slots);
22442 `;
22443 }
22444 const uses_props = component.var_lookup.has('$$props');
22445 const uses_rest = component.var_lookup.has('$$restProps');
22446 const $$props = uses_props || uses_rest ? '$$new_props' : '$$props';
22447 const props = component.vars.filter(variable => !variable.module && variable.export_name);
22448 const writable_props = props.filter(variable => variable.writable);
22449 const omit_props_names = component.get_unique_name('omit_props_names');
22450 const compute_rest = x `@compute_rest_props($$props, ${omit_props_names.name})`;
22451 const rest = uses_rest ? b `
22452 const ${omit_props_names.name} = [${props.map(prop => `"${prop.export_name}"`).join(',')}];
22453 let $$restProps = ${compute_rest};
22454 ` : null;
22455 const set = (uses_props || uses_rest || writable_props.length > 0 || component.slots.size > 0)
22456 ? x `
22457 ${$$props} => {
22458 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`)}
22459 ${uses_rest && !uses_props && x `$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`}
22460 ${uses_rest && renderer.invalidate('$$restProps', x `$$restProps = ${compute_rest}`)}
22461 ${writable_props.map(prop => b `if ('${prop.export_name}' in ${$$props}) ${renderer.invalidate(prop.name, x `${prop.name} = ${$$props}.${prop.export_name}`)};`)}
22462 ${component.slots.size > 0 &&
22463 b `if ('$$scope' in ${$$props}) ${renderer.invalidate('$$scope', x `$$scope = ${$$props}.$$scope`)};`}
22464 }
22465 `
22466 : null;
22467 const accessors = [];
22468 const not_equal = component.component_options.immutable ? x `@not_equal` : x `@safe_not_equal`;
22469 let dev_props_check;
22470 let inject_state;
22471 let capture_state;
22472 let props_inject;
22473 props.forEach(prop => {
22474 const variable = component.var_lookup.get(prop.name);
22475 if (!variable.writable || component.component_options.accessors) {
22476 accessors.push({
22477 type: 'MethodDefinition',
22478 kind: 'get',
22479 key: { type: 'Identifier', name: prop.export_name },
22480 value: x `function() {
22481 return ${prop.hoistable ? prop.name : x `this.$$.ctx[${renderer.context_lookup.get(prop.name).index}]`}
22482 }`
22483 });
22484 }
22485 else if (component.compile_options.dev) {
22486 accessors.push({
22487 type: 'MethodDefinition',
22488 kind: 'get',
22489 key: { type: 'Identifier', name: prop.export_name },
22490 value: x `function() {
22491 throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
22492 }`
22493 });
22494 }
22495 if (component.component_options.accessors) {
22496 if (variable.writable && !renderer.readonly.has(prop.name)) {
22497 accessors.push({
22498 type: 'MethodDefinition',
22499 kind: 'set',
22500 key: { type: 'Identifier', name: prop.export_name },
22501 value: x `function(${prop.name}) {
22502 this.$set({ ${prop.export_name}: ${prop.name} });
22503 @flush();
22504 }`
22505 });
22506 }
22507 else if (component.compile_options.dev) {
22508 accessors.push({
22509 type: 'MethodDefinition',
22510 kind: 'set',
22511 key: { type: 'Identifier', name: prop.export_name },
22512 value: x `function(value) {
22513 throw new @_Error("<${component.tag}>: Cannot set read-only property '${prop.export_name}'");
22514 }`
22515 });
22516 }
22517 }
22518 else if (component.compile_options.dev) {
22519 accessors.push({
22520 type: 'MethodDefinition',
22521 kind: 'set',
22522 key: { type: 'Identifier', name: prop.export_name },
22523 value: x `function(value) {
22524 throw new @_Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
22525 }`
22526 });
22527 }
22528 });
22529 if (component.compile_options.dev) {
22530 // checking that expected ones were passed
22531 const expected = props.filter(prop => prop.writable && !prop.initialised);
22532 if (expected.length) {
22533 dev_props_check = b `
22534 const { ctx: #ctx } = this.$$;
22535 const props = ${options.customElement ? x `this.attributes` : x `options.props || {}`};
22536 ${expected.map(prop => b `
22537 if (${renderer.reference(prop.name)} === undefined && !('${prop.export_name}' in props)) {
22538 @_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'");
22539 }`)}
22540 `;
22541 }
22542 const capturable_vars = component.vars.filter(v => !v.internal && !v.global && !v.name.startsWith('$$'));
22543 if (capturable_vars.length > 0) {
22544 capture_state = x `() => ({ ${capturable_vars.map(prop => p `${prop.name}`)} })`;
22545 }
22546 const injectable_vars = capturable_vars.filter(v => !v.module && v.writable && v.name[0] !== '$');
22547 if (uses_props || injectable_vars.length > 0) {
22548 inject_state = x `
22549 ${$$props} => {
22550 ${uses_props && renderer.invalidate('$$props', x `$$props = @assign(@assign({}, $$props), $$new_props)`)}
22551 ${injectable_vars.map(v => b `if ('${v.name}' in $$props) ${renderer.invalidate(v.name, x `${v.name} = ${$$props}.${v.name}`)};`)}
22552 }
22553 `;
22554 props_inject = b `
22555 if ($$props && "$$inject" in $$props) {
22556 $$self.$inject_state($$props.$$inject);
22557 }
22558 `;
22559 }
22560 }
22561 // instrument assignments
22562 if (component.ast.instance) {
22563 let scope = component.instance_scope;
22564 const map = component.instance_scope_map;
22565 let execution_context = null;
22566 walk(component.ast.instance.content, {
22567 enter(node) {
22568 if (map.has(node)) {
22569 scope = map.get(node);
22570 if (!execution_context && !scope.block) {
22571 execution_context = node;
22572 }
22573 }
22574 else if (!execution_context && node.type === 'LabeledStatement' && node.label.name === '$') {
22575 execution_context = node;
22576 }
22577 },
22578 leave(node) {
22579 if (map.has(node)) {
22580 scope = scope.parent;
22581 }
22582 if (execution_context === node) {
22583 execution_context = null;
22584 }
22585 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
22586 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
22587 // normally (`a = 1`, `b.c = 2`), there'll be a single name
22588 // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
22589 // may be more, in which case we need to tack the extra ones
22590 // onto the initial function call
22591 const names = new Set(extract_names(assignee));
22592 this.replace(invalidate(renderer, scope, node, names, execution_context === null));
22593 }
22594 }
22595 });
22596 component.rewrite_props(({ name, reassigned, export_name }) => {
22597 const value = `$${name}`;
22598 const i = renderer.context_lookup.get(`$${name}`).index;
22599 const insert = (reassigned || export_name)
22600 ? b `${`$$subscribe_${name}`}()`
22601 : b `@component_subscribe($$self, ${name}, #value => $$invalidate(${i}, ${value} = #value))`;
22602 if (component.compile_options.dev) {
22603 return b `@validate_store(${name}, '${name}'); ${insert}`;
22604 }
22605 return insert;
22606 });
22607 }
22608 const args = [x `$$self`];
22609 const has_invalidate = props.length > 0 ||
22610 component.has_reactive_assignments ||
22611 component.slots.size > 0 ||
22612 capture_state ||
22613 inject_state;
22614 if (has_invalidate) {
22615 args.push(x `$$props`, x `$$invalidate`);
22616 }
22617 else if (component.compile_options.dev) {
22618 // $$props arg is still needed for unknown prop check
22619 args.push(x `$$props`);
22620 }
22621 const has_create_fragment = component.compile_options.dev || block.has_content();
22622 if (has_create_fragment) {
22623 body.push(b `
22624 function create_fragment(#ctx) {
22625 ${block.get_contents()}
22626 }
22627 `);
22628 }
22629 body.push(b `
22630 ${component.extract_javascript(component.ast.module)}
22631
22632 ${component.fully_hoisted}
22633 `);
22634 const filtered_props = props.filter(prop => {
22635 const variable = component.var_lookup.get(prop.name);
22636 if (variable.hoistable)
22637 return false;
22638 return prop.name[0] !== '$';
22639 });
22640 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
22641 const instance_javascript = component.extract_javascript(component.ast.instance);
22642 const has_definition = (component.compile_options.dev ||
22643 (instance_javascript && instance_javascript.length > 0) ||
22644 filtered_props.length > 0 ||
22645 uses_props ||
22646 component.partly_hoisted.length > 0 ||
22647 renderer.initial_context.length > 0 ||
22648 component.reactive_declarations.length > 0 ||
22649 capture_state ||
22650 inject_state);
22651 const definition = has_definition
22652 ? component.alias('instance')
22653 : { type: 'Literal', value: null };
22654 const reactive_store_subscriptions = reactive_stores
22655 .filter(store => {
22656 const variable = component.var_lookup.get(store.name.slice(1));
22657 return !variable || variable.hoistable;
22658 })
22659 .map(({ name }) => b `
22660 ${component.compile_options.dev && b `@validate_store(${name.slice(1)}, '${name.slice(1)}');`}
22661 @component_subscribe($$self, ${name.slice(1)}, $$value => $$invalidate(${renderer.context_lookup.get(name).index}, ${name} = $$value));
22662 `);
22663 const resubscribable_reactive_store_unsubscribers = reactive_stores
22664 .filter(store => {
22665 const variable = component.var_lookup.get(store.name.slice(1));
22666 return variable && (variable.reassigned || variable.export_name);
22667 })
22668 .map(({ name }) => b `$$self.$$.on_destroy.push(() => ${`$$unsubscribe_${name.slice(1)}`}());`);
22669 if (has_definition) {
22670 const reactive_declarations = [];
22671 const fixed_reactive_declarations = []; // not really 'reactive' but whatever
22672 component.reactive_declarations.forEach(d => {
22673 const dependencies = Array.from(d.dependencies);
22674 const uses_rest_or_props = !!dependencies.find(n => n === '$$props' || n === '$$restProps');
22675 const writable = dependencies.filter(n => {
22676 const variable = component.var_lookup.get(n);
22677 return variable && (variable.export_name || variable.mutated || variable.reassigned);
22678 });
22679 const condition = !uses_rest_or_props && writable.length > 0 && renderer.dirty(writable, true);
22680 let statement = d.node; // TODO remove label (use d.node.body) if it's not referenced
22681 if (condition)
22682 statement = b `if (${condition}) { ${statement} }`[0];
22683 if (condition || uses_rest_or_props) {
22684 reactive_declarations.push(statement);
22685 }
22686 else {
22687 fixed_reactive_declarations.push(statement);
22688 }
22689 });
22690 const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
22691 const variable = component.var_lookup.get(name);
22692 return variable.injected && variable.name[0] !== '$';
22693 });
22694 const reactive_store_declarations = reactive_stores.map(variable => {
22695 const $name = variable.name;
22696 const name = $name.slice(1);
22697 const store = component.var_lookup.get(name);
22698 if (store && (store.reassigned || store.export_name)) {
22699 const unsubscribe = `$$unsubscribe_${name}`;
22700 const subscribe = `$$subscribe_${name}`;
22701 const i = renderer.context_lookup.get($name).index;
22702 return b `let ${$name}, ${unsubscribe} = @noop, ${subscribe} = () => (${unsubscribe}(), ${unsubscribe} = @subscribe(${name}, $$value => $$invalidate(${i}, ${$name} = $$value)), ${name})`;
22703 }
22704 return b `let ${$name};`;
22705 });
22706 let unknown_props_check;
22707 if (component.compile_options.dev && !(uses_props || uses_rest)) {
22708 unknown_props_check = b `
22709 const writable_props = [${writable_props.map(prop => x `'${prop.export_name}'`)}];
22710 @_Object.keys($$props).forEach(key => {
22711 if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$') @_console.warn(\`<${component.tag}> was created with unknown prop '\${key}'\`);
22712 });
22713 `;
22714 }
22715 const return_value = {
22716 type: 'ArrayExpression',
22717 elements: renderer.initial_context.map(member => ({
22718 type: 'Identifier',
22719 name: member.name
22720 }))
22721 };
22722 body.push(b `
22723 function ${definition}(${args}) {
22724 ${injected.map(name => b `let ${name};`)}
22725
22726 ${rest}
22727
22728 ${reactive_store_declarations}
22729
22730 ${reactive_store_subscriptions}
22731
22732 ${resubscribable_reactive_store_unsubscribers}
22733
22734 ${component.slots.size || component.compile_options.dev || uses_slots ? b `let { $$slots: #slots = {}, $$scope } = $$props;` : null}
22735 ${component.compile_options.dev && b `@validate_slots('${component.tag}', #slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
22736 ${compute_slots}
22737
22738 ${instance_javascript}
22739
22740 ${unknown_props_check}
22741
22742 ${renderer.binding_groups.size > 0 && b `const $$binding_groups = [${[...renderer.binding_groups.keys()].map(_ => x `[]`)}];`}
22743
22744 ${component.partly_hoisted}
22745
22746 ${set && b `$$self.$$set = ${set};`}
22747
22748 ${capture_state && b `$$self.$capture_state = ${capture_state};`}
22749
22750 ${inject_state && b `$$self.$inject_state = ${inject_state};`}
22751
22752 ${ /* before reactive declarations */props_inject}
22753
22754 ${reactive_declarations.length > 0 && b `
22755 $$self.$$.update = () => {
22756 ${reactive_declarations}
22757 };
22758 `}
22759
22760 ${fixed_reactive_declarations}
22761
22762 ${uses_props && b `$$props = @exclude_internal_props($$props);`}
22763
22764 return ${return_value};
22765 }
22766 `);
22767 }
22768 const prop_indexes = x `{
22769 ${props.filter(v => v.export_name && !v.module).map(v => p `${v.export_name}: ${renderer.context_lookup.get(v.name).index}`)}
22770 }`;
22771 let dirty;
22772 if (renderer.context_overflow) {
22773 dirty = x `[]`;
22774 for (let i = 0; i < renderer.context.length; i += 31) {
22775 dirty.elements.push(x `-1`);
22776 }
22777 }
22778 if (options.customElement) {
22779 let init_props = x `@attribute_to_object(this.attributes)`;
22780 if (uses_slots) {
22781 init_props = x `{ ...${init_props}, $$slots: @get_custom_elements_slots(this) }`;
22782 }
22783 const declaration = b `
22784 class ${name} extends @SvelteElement {
22785 constructor(options) {
22786 super();
22787
22788 ${css.code && b `this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
22789
22790 @init(this, { target: this.shadowRoot, props: ${init_props} }, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
22791
22792 ${dev_props_check}
22793
22794 if (options) {
22795 if (options.target) {
22796 @insert(options.target, this, options.anchor);
22797 }
22798
22799 ${(props.length > 0 || uses_props || uses_rest) && b `
22800 if (options.props) {
22801 this.$set(options.props);
22802 @flush();
22803 }`}
22804 }
22805 }
22806 }
22807 `[0];
22808 if (props.length > 0) {
22809 declaration.body.body.push({
22810 type: 'MethodDefinition',
22811 kind: 'get',
22812 static: true,
22813 computed: false,
22814 key: { type: 'Identifier', name: 'observedAttributes' },
22815 value: x `function() {
22816 return [${props.map(prop => x `"${prop.export_name}"`)}];
22817 }`
22818 });
22819 }
22820 declaration.body.body.push(...accessors);
22821 body.push(declaration);
22822 if (component.tag != null) {
22823 body.push(b `
22824 @_customElements.define("${component.tag}", ${name});
22825 `);
22826 }
22827 }
22828 else {
22829 const superclass = {
22830 type: 'Identifier',
22831 name: options.dev ? '@SvelteComponentDev' : '@SvelteComponent'
22832 };
22833 const declaration = b `
22834 class ${name} extends ${superclass} {
22835 constructor(options) {
22836 super(${options.dev && 'options'});
22837 ${should_add_css && b `if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
22838 @init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${dirty});
22839 ${options.dev && b `@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`}
22840
22841 ${dev_props_check}
22842 }
22843 }
22844 `[0];
22845 declaration.body.body.push(...accessors);
22846 body.push(declaration);
22847 }
22848 return { js: flatten$1(body, []), css };
22849 }
22850 function flatten$1(nodes, target) {
22851 for (let i = 0; i < nodes.length; i += 1) {
22852 const node = nodes[i];
22853 if (Array.isArray(node)) {
22854 flatten$1(node, target);
22855 }
22856 else {
22857 target.push(node);
22858 }
22859 }
22860 return target;
22861 }
22862
22863 function AwaitBlock (node, renderer, options) {
22864 renderer.push();
22865 renderer.render(node.pending.children, options);
22866 const pending = renderer.pop();
22867 renderer.push();
22868 renderer.render(node.then.children, options);
22869 const then = renderer.pop();
22870 renderer.add_expression(x `
22871 function(__value) {
22872 if (@is_promise(__value)) return ${pending};
22873 return (function(${node.then_node ? node.then_node : ''}) { return ${then}; }(__value));
22874 }(${node.expression.node})
22875 `);
22876 }
22877
22878 function Comment$1 (_node, _renderer, _options) {
22879 // TODO preserve comments
22880 // if (options.preserveComments) {
22881 // renderer.append(`<!--${node.data}-->`);
22882 // }
22883 }
22884
22885 function DebugTag (node, renderer, options) {
22886 if (!options.dev)
22887 return;
22888 const filename = options.filename || null;
22889 const { line, column } = options.locate(node.start + 1);
22890 const obj = x `{
22891 ${node.expressions.map(e => p `${e.node.name}`)}
22892 }`;
22893 renderer.add_expression(x `@debug(${filename ? x `"${filename}"` : x `null`}, ${line - 1}, ${column}, ${obj})`);
22894 }
22895
22896 function EachBlock (node, renderer, options) {
22897 const args = [node.context_node];
22898 if (node.index)
22899 args.push({ type: 'Identifier', name: node.index });
22900 renderer.push();
22901 renderer.render(node.children, options);
22902 const result = renderer.pop();
22903 const consequent = x `@each(${node.expression.node}, (${args}) => ${result})`;
22904 if (node.else) {
22905 renderer.push();
22906 renderer.render(node.else.children, options);
22907 const alternate = renderer.pop();
22908 renderer.add_expression(x `${node.expression.node}.length ? ${consequent} : ${alternate}`);
22909 }
22910 else {
22911 renderer.add_expression(consequent);
22912 }
22913 }
22914
22915 function get_class_attribute_value(attribute) {
22916 // handle special case — `class={possiblyUndefined}` with scoped CSS
22917 if (attribute.chunks.length === 2 && attribute.chunks[1].synthetic) {
22918 const value = attribute.chunks[0].node;
22919 return x `@escape(@null_to_empty(${value})) + "${attribute.chunks[1].data}"`;
22920 }
22921 return get_attribute_value(attribute);
22922 }
22923 function get_attribute_value(attribute) {
22924 if (attribute.chunks.length === 0)
22925 return x `""`;
22926 return attribute.chunks
22927 .map((chunk) => {
22928 return chunk.type === 'Text'
22929 ? string_literal(chunk.data.replace(/"/g, '&quot;'))
22930 : x `@escape(${chunk.node})`;
22931 })
22932 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
22933 }
22934
22935 function get_slot_scope(lets) {
22936 if (lets.length === 0)
22937 return null;
22938 return {
22939 type: 'ObjectPattern',
22940 properties: lets.map(l => {
22941 return {
22942 type: 'Property',
22943 kind: 'init',
22944 method: false,
22945 shorthand: false,
22946 computed: false,
22947 key: l.name,
22948 value: l.value || l.name
22949 };
22950 })
22951 };
22952 }
22953
22954 // source: https://html.spec.whatwg.org/multipage/indices.html
22955 const boolean_attributes = new Set([
22956 'allowfullscreen',
22957 'allowpaymentrequest',
22958 'async',
22959 'autofocus',
22960 'autoplay',
22961 'checked',
22962 'controls',
22963 'default',
22964 'defer',
22965 'disabled',
22966 'formnovalidate',
22967 'hidden',
22968 'ismap',
22969 'loop',
22970 'multiple',
22971 'muted',
22972 'nomodule',
22973 'novalidate',
22974 'open',
22975 'playsinline',
22976 'readonly',
22977 'required',
22978 'reversed',
22979 'selected'
22980 ]);
22981
22982 // similar logic from `compile/render_dom/wrappers/Fragment`
22983 // We want to remove trailing whitespace inside an element/component/block,
22984 // *unless* there is no whitespace between this node and its next sibling
22985 function remove_whitespace_children(children, next) {
22986 const nodes = [];
22987 let last_child;
22988 let i = children.length;
22989 while (i--) {
22990 const child = children[i];
22991 if (child.type === 'Text') {
22992 if (child.should_skip()) {
22993 continue;
22994 }
22995 let { data } = child;
22996 if (nodes.length === 0) {
22997 const should_trim = next
22998 ? next.type === 'Text' &&
22999 /^\s/.test(next.data) &&
23000 trimmable_at$1(child, next)
23001 : !child.has_ancestor('EachBlock');
23002 if (should_trim) {
23003 data = trim_end(data);
23004 if (!data)
23005 continue;
23006 }
23007 }
23008 // glue text nodes (which could e.g. be separated by comments) together
23009 if (last_child && last_child.type === 'Text') {
23010 last_child.data = data + last_child.data;
23011 continue;
23012 }
23013 nodes.unshift(child);
23014 link(last_child, last_child = child);
23015 }
23016 else {
23017 nodes.unshift(child);
23018 link(last_child, last_child = child);
23019 }
23020 }
23021 const first = nodes[0];
23022 if (first && first.type === 'Text') {
23023 first.data = trim_start(first.data);
23024 if (!first.data) {
23025 first.var = null;
23026 nodes.shift();
23027 if (nodes[0]) {
23028 nodes[0].prev = null;
23029 }
23030 }
23031 }
23032 return nodes;
23033 }
23034 function trimmable_at$1(child, next_sibling) {
23035 // Whitespace is trimmable if one of the following is true:
23036 // The child and its sibling share a common nearest each block (not at an each block boundary)
23037 // The next sibling's previous node is an each block
23038 return (next_sibling.find_nearest(/EachBlock/) ===
23039 child.find_nearest(/EachBlock/) || next_sibling.prev.type === 'EachBlock');
23040 }
23041
23042 function Element (node, renderer, options) {
23043 const children = remove_whitespace_children(node.children, node.next);
23044 // awkward special case
23045 let node_contents;
23046 const contenteditable = (node.name !== 'textarea' &&
23047 node.name !== 'input' &&
23048 node.attributes.some((attribute) => attribute.name === 'contenteditable'));
23049 const slot = node.get_static_attribute_value('slot');
23050 const nearest_inline_component = node.find_nearest(/InlineComponent/);
23051 if (slot && nearest_inline_component) {
23052 renderer.push();
23053 }
23054 renderer.add_string(`<${node.name}`);
23055 const class_expression_list = node.classes.map(class_directive => {
23056 const { expression, name } = class_directive;
23057 const snippet = expression ? expression.node : x `#ctx.${name}`; // TODO is this right?
23058 return x `${snippet} ? "${name}" : ""`;
23059 });
23060 if (node.needs_manual_style_scoping) {
23061 class_expression_list.push(x `"${node.component.stylesheet.id}"`);
23062 }
23063 const class_expression = class_expression_list.length > 0 &&
23064 class_expression_list.reduce((lhs, rhs) => x `${lhs} + ' ' + ${rhs}`);
23065 if (node.attributes.some(attr => attr.is_spread)) {
23066 // TODO dry this out
23067 const args = [];
23068 node.attributes.forEach(attribute => {
23069 if (attribute.is_spread) {
23070 args.push(attribute.expression.node);
23071 }
23072 else {
23073 const name = attribute.name.toLowerCase();
23074 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
23075 node_contents = get_attribute_value(attribute);
23076 }
23077 else if (attribute.is_true) {
23078 args.push(x `{ ${attribute.name}: true }`);
23079 }
23080 else if (boolean_attributes.has(name) &&
23081 attribute.chunks.length === 1 &&
23082 attribute.chunks[0].type !== 'Text') {
23083 // a boolean attribute with one non-Text chunk
23084 args.push(x `{ ${attribute.name}: ${attribute.chunks[0].node} || null }`);
23085 }
23086 else {
23087 args.push(x `{ ${attribute.name}: ${get_attribute_value(attribute)} }`);
23088 }
23089 }
23090 });
23091 renderer.add_expression(x `@spread([${args}], ${class_expression})`);
23092 }
23093 else {
23094 let add_class_attribute = !!class_expression;
23095 node.attributes.forEach(attribute => {
23096 const name = attribute.name.toLowerCase();
23097 if (name === 'value' && node.name.toLowerCase() === 'textarea') {
23098 node_contents = get_attribute_value(attribute);
23099 }
23100 else if (attribute.is_true) {
23101 renderer.add_string(` ${attribute.name}`);
23102 }
23103 else if (boolean_attributes.has(name) &&
23104 attribute.chunks.length === 1 &&
23105 attribute.chunks[0].type !== 'Text') {
23106 // a boolean attribute with one non-Text chunk
23107 renderer.add_string(' ');
23108 renderer.add_expression(x `${attribute.chunks[0].node} ? "${attribute.name}" : ""`);
23109 }
23110 else if (name === 'class' && class_expression) {
23111 add_class_attribute = false;
23112 renderer.add_string(` ${attribute.name}="`);
23113 renderer.add_expression(x `[${get_class_attribute_value(attribute)}, ${class_expression}].join(' ').trim()`);
23114 renderer.add_string('"');
23115 }
23116 else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') {
23117 const snippet = attribute.chunks[0].node;
23118 renderer.add_expression(x `@add_attribute("${attribute.name}", ${snippet}, ${boolean_attributes.has(name) ? 1 : 0})`);
23119 }
23120 else {
23121 renderer.add_string(` ${attribute.name}="`);
23122 renderer.add_expression((name === 'class' ? get_class_attribute_value : get_attribute_value)(attribute));
23123 renderer.add_string('"');
23124 }
23125 });
23126 if (add_class_attribute) {
23127 renderer.add_expression(x `@add_classes([${class_expression}].join(' ').trim())`);
23128 }
23129 }
23130 node.bindings.forEach(binding => {
23131 const { name, expression } = binding;
23132 if (binding.is_readonly) {
23133 return;
23134 }
23135 if (name === 'group') ;
23136 else if (contenteditable && (name === 'textContent' || name === 'innerHTML')) {
23137 node_contents = expression.node;
23138 // TODO where was this used?
23139 // value = name === 'textContent' ? x`@escape($$value)` : x`$$value`;
23140 }
23141 else if (binding.name === 'value' && node.name === 'textarea') {
23142 const snippet = expression.node;
23143 node_contents = x `${snippet} || ""`;
23144 }
23145 else {
23146 const snippet = expression.node;
23147 renderer.add_expression(x `@add_attribute("${name}", ${snippet}, 1)`);
23148 }
23149 });
23150 if (options.hydratable && options.head_id) {
23151 renderer.add_string(` data-svelte="${options.head_id}"`);
23152 }
23153 renderer.add_string('>');
23154 if (node_contents !== undefined) {
23155 if (contenteditable) {
23156 renderer.push();
23157 renderer.render(children, options);
23158 const result = renderer.pop();
23159 renderer.add_expression(x `($$value => $$value === void 0 ? ${result} : $$value)(${node_contents})`);
23160 }
23161 else {
23162 renderer.add_expression(node_contents);
23163 }
23164 if (!is_void(node.name)) {
23165 renderer.add_string(`</${node.name}>`);
23166 }
23167 }
23168 else if (slot && nearest_inline_component) {
23169 renderer.render(children, options);
23170 if (!is_void(node.name)) {
23171 renderer.add_string(`</${node.name}>`);
23172 }
23173 const lets = node.lets;
23174 const seen = new Set(lets.map(l => l.name.name));
23175 nearest_inline_component.lets.forEach(l => {
23176 if (!seen.has(l.name.name))
23177 lets.push(l);
23178 });
23179 options.slot_scopes.set(slot, {
23180 input: get_slot_scope(node.lets),
23181 output: renderer.pop()
23182 });
23183 }
23184 else {
23185 renderer.render(children, options);
23186 if (!is_void(node.name)) {
23187 renderer.add_string(`</${node.name}>`);
23188 }
23189 }
23190 }
23191
23192 function Head (node, renderer, options) {
23193 const head_options = Object.assign(Object.assign({}, options), { head_id: node.id });
23194 renderer.push();
23195 renderer.render(node.children, head_options);
23196 const result = renderer.pop();
23197 renderer.add_expression(x `$$result.head += ${result}, ""`);
23198 }
23199
23200 function HtmlTag (node, renderer, _options) {
23201 renderer.add_expression(node.expression.node);
23202 }
23203
23204 function IfBlock (node, renderer, options) {
23205 const condition = node.expression.node;
23206 renderer.push();
23207 renderer.render(node.children, options);
23208 const consequent = renderer.pop();
23209 renderer.push();
23210 if (node.else)
23211 renderer.render(node.else.children, options);
23212 const alternate = renderer.pop();
23213 renderer.add_expression(x `${condition} ? ${consequent} : ${alternate}`);
23214 }
23215
23216 function get_prop_value(attribute) {
23217 if (attribute.is_true)
23218 return x `true`;
23219 if (attribute.chunks.length === 0)
23220 return x `''`;
23221 return attribute.chunks
23222 .map(chunk => {
23223 if (chunk.type === 'Text')
23224 return string_literal(chunk.data);
23225 return chunk.node;
23226 })
23227 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
23228 }
23229 function InlineComponent (node, renderer, options) {
23230 const binding_props = [];
23231 const binding_fns = [];
23232 node.bindings.forEach(binding => {
23233 renderer.has_bindings = true;
23234 // TODO this probably won't work for contextual bindings
23235 const snippet = binding.expression.node;
23236 binding_props.push(p `${binding.name}: ${snippet}`);
23237 binding_fns.push(p `${binding.name}: $$value => { ${snippet} = $$value; $$settled = false }`);
23238 });
23239 const uses_spread = node.attributes.find(attr => attr.is_spread);
23240 let props;
23241 if (uses_spread) {
23242 props = x `@_Object.assign(${node.attributes
23243 .map(attribute => {
23244 if (attribute.is_spread) {
23245 return attribute.expression.node;
23246 }
23247 else {
23248 return x `{ ${attribute.name}: ${get_prop_value(attribute)} }`;
23249 }
23250 })
23251 .concat(binding_props.map(p => x `{ ${p} }`))})`;
23252 }
23253 else {
23254 props = x `{
23255 ${node.attributes.map(attribute => p `${attribute.name}: ${get_prop_value(attribute)}`)},
23256 ${binding_props}
23257 }`;
23258 }
23259 const bindings = x `{
23260 ${binding_fns}
23261 }`;
23262 const expression = (node.name === 'svelte:self'
23263 ? renderer.name
23264 : node.name === 'svelte:component'
23265 ? x `(${node.expression.node}) || @missing_component`
23266 : node.name.split('.').reduce(((lhs, rhs) => x `${lhs}.${rhs}`)));
23267 const slot_fns = [];
23268 const children = remove_whitespace_children(node.children, node.next);
23269 if (children.length) {
23270 const slot_scopes = new Map();
23271 renderer.push();
23272 renderer.render(children, Object.assign({}, options, {
23273 slot_scopes
23274 }));
23275 slot_scopes.set('default', {
23276 input: get_slot_scope(node.lets),
23277 output: renderer.pop()
23278 });
23279 slot_scopes.forEach(({ input, output }, name) => {
23280 if (!is_empty_template_literal(output)) {
23281 slot_fns.push(p `${name}: (${input}) => ${output}`);
23282 }
23283 });
23284 }
23285 const slots = x `{
23286 ${slot_fns}
23287 }`;
23288 renderer.add_expression(x `@validate_component(${expression}, "${node.name}").$$render($$result, ${props}, ${bindings}, ${slots})`);
23289 }
23290 function is_empty_template_literal(template_literal) {
23291 return (template_literal.expressions.length === 0 &&
23292 template_literal.quasis.length === 1 &&
23293 template_literal.quasis[0].value.raw === '');
23294 }
23295
23296 function KeyBlock (node, renderer, options) {
23297 renderer.render(node.children, options);
23298 }
23299
23300 function Slot (node, renderer, options) {
23301 const slot_data = get_slot_data(node.values);
23302 const slot = node.get_static_attribute_value('slot');
23303 const nearest_inline_component = node.find_nearest(/InlineComponent/);
23304 if (slot && nearest_inline_component) {
23305 renderer.push();
23306 }
23307 renderer.push();
23308 renderer.render(node.children, options);
23309 const result = renderer.pop();
23310 renderer.add_expression(x `
23311 #slots.${node.slot_name}
23312 ? #slots.${node.slot_name}(${slot_data})
23313 : ${result}
23314 `);
23315 if (slot && nearest_inline_component) {
23316 const lets = node.lets;
23317 const seen = new Set(lets.map(l => l.name.name));
23318 nearest_inline_component.lets.forEach(l => {
23319 if (!seen.has(l.name.name))
23320 lets.push(l);
23321 });
23322 options.slot_scopes.set(slot, {
23323 input: get_slot_scope(node.lets),
23324 output: renderer.pop()
23325 });
23326 }
23327 }
23328
23329 function Tag$1 (node, renderer, _options) {
23330 const snippet = node.expression.node;
23331 renderer.add_expression(node.parent &&
23332 node.parent.type === 'Element' &&
23333 node.parent.name === 'style'
23334 ? snippet
23335 : x `@escape(${snippet})`);
23336 }
23337
23338 function Text (node, renderer, _options) {
23339 let text = node.data;
23340 if (!node.parent ||
23341 node.parent.type !== 'Element' ||
23342 (node.parent.name !== 'script' && node.parent.name !== 'style')) {
23343 // unless this Text node is inside a <script> or <style> element, escape &,<,>
23344 text = escape_html(text);
23345 }
23346 renderer.add_string(text);
23347 }
23348
23349 function Title (node, renderer, options) {
23350 renderer.push();
23351 renderer.add_string('<title>');
23352 renderer.render(node.children, options);
23353 renderer.add_string('</title>');
23354 const result = renderer.pop();
23355 renderer.add_expression(x `$$result.title = ${result}, ""`);
23356 }
23357
23358 function noop$1() { }
23359 const handlers$1 = {
23360 AwaitBlock,
23361 Body: noop$1,
23362 Comment: Comment$1,
23363 DebugTag,
23364 EachBlock,
23365 Element,
23366 Head,
23367 IfBlock,
23368 InlineComponent,
23369 KeyBlock,
23370 MustacheTag: Tag$1,
23371 Options: noop$1,
23372 RawMustacheTag: HtmlTag,
23373 Slot,
23374 Text,
23375 Title,
23376 Window: noop$1
23377 };
23378 class Renderer$1 {
23379 constructor({ name }) {
23380 this.has_bindings = false;
23381 this.stack = [];
23382 this.targets = [];
23383 this.name = name;
23384 this.push();
23385 }
23386 add_string(str) {
23387 this.current.value += escape_template(str);
23388 }
23389 add_expression(node) {
23390 this.literal.quasis.push({
23391 type: 'TemplateElement',
23392 value: { raw: this.current.value, cooked: null },
23393 tail: false
23394 });
23395 this.literal.expressions.push(node);
23396 this.current.value = '';
23397 }
23398 push() {
23399 const current = this.current = { value: '' };
23400 const literal = this.literal = {
23401 type: 'TemplateLiteral',
23402 expressions: [],
23403 quasis: []
23404 };
23405 this.stack.push({ current, literal });
23406 }
23407 pop() {
23408 this.literal.quasis.push({
23409 type: 'TemplateElement',
23410 value: { raw: this.current.value, cooked: null },
23411 tail: true
23412 });
23413 const popped = this.stack.pop();
23414 const last = this.stack[this.stack.length - 1];
23415 if (last) {
23416 this.literal = last.literal;
23417 this.current = last.current;
23418 }
23419 return popped.literal;
23420 }
23421 render(nodes, options) {
23422 nodes.forEach(node => {
23423 const handler = handlers$1[node.type];
23424 if (!handler) {
23425 throw new Error(`No handler for '${node.type}' nodes`);
23426 }
23427 handler(node, this, options);
23428 });
23429 }
23430 }
23431
23432 function ssr(component, options) {
23433 const renderer = new Renderer$1({
23434 name: component.name
23435 });
23436 const { name } = component;
23437 // create $$render function
23438 renderer.render(trim(component.fragment.children), Object.assign({
23439 locate: component.locate
23440 }, options));
23441 // TODO put this inside the Renderer class
23442 const literal = renderer.pop();
23443 // TODO concatenate CSS maps
23444 const css = options.customElement ?
23445 { code: null, map: null } :
23446 component.stylesheet.render(options.filename, true);
23447 const uses_rest = component.var_lookup.has('$$restProps');
23448 const props = component.vars.filter(variable => !variable.module && variable.export_name);
23449 const rest = uses_rest ? b `let $$restProps = @compute_rest_props($$props, [${props.map(prop => `"${prop.export_name}"`).join(',')}]);` : null;
23450 const uses_slots = component.var_lookup.has('$$slots');
23451 const slots = uses_slots ? b `let $$slots = @compute_slots(#slots);` : null;
23452 const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
23453 const reactive_store_subscriptions = reactive_stores
23454 .filter(store => {
23455 const variable = component.var_lookup.get(store.name.slice(1));
23456 return !variable || variable.hoistable;
23457 })
23458 .map(({ name }) => {
23459 const store_name = name.slice(1);
23460 return b `
23461 ${component.compile_options.dev && b `@validate_store(${store_name}, '${store_name}');`}
23462 ${`$$unsubscribe_${store_name}`} = @subscribe(${store_name}, #value => ${name} = #value)
23463 ${store_name}.subscribe($$value => ${name} = $$value);
23464 `;
23465 });
23466 const reactive_store_unsubscriptions = reactive_stores.map(({ name }) => b `${`$$unsubscribe_${name.slice(1)}`}()`);
23467 const reactive_store_declarations = reactive_stores
23468 .map(({ name }) => {
23469 const store_name = name.slice(1);
23470 const store = component.var_lookup.get(store_name);
23471 if (store && store.reassigned) {
23472 const unsubscribe = `$$unsubscribe_${store_name}`;
23473 const subscribe = `$$subscribe_${store_name}`;
23474 return b `let ${name}, ${unsubscribe} = @noop, ${subscribe} = () => (${unsubscribe}(), ${unsubscribe} = @subscribe(${store_name}, $$value => ${name} = $$value), ${store_name})`;
23475 }
23476 return b `let ${name}, ${`$$unsubscribe_${store_name}`};`;
23477 });
23478 // instrument get/set store value
23479 if (component.ast.instance) {
23480 let scope = component.instance_scope;
23481 const map = component.instance_scope_map;
23482 walk(component.ast.instance.content, {
23483 enter(node) {
23484 if (map.has(node)) {
23485 scope = map.get(node);
23486 }
23487 },
23488 leave(node) {
23489 if (map.has(node)) {
23490 scope = scope.parent;
23491 }
23492 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
23493 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
23494 const names = new Set(extract_names(assignee));
23495 const to_invalidate = new Set();
23496 for (const name of names) {
23497 const variable = component.var_lookup.get(name);
23498 if (variable &&
23499 !variable.hoistable &&
23500 !variable.global &&
23501 !variable.module &&
23502 (variable.subscribable || variable.name[0] === '$')) {
23503 to_invalidate.add(variable.name);
23504 }
23505 }
23506 if (to_invalidate.size) {
23507 this.replace(invalidate({ component }, scope, node, to_invalidate, true));
23508 }
23509 }
23510 }
23511 });
23512 }
23513 component.rewrite_props(({ name, reassigned }) => {
23514 const value = `$${name}`;
23515 let insert = reassigned
23516 ? b `${`$$subscribe_${name}`}()`
23517 : b `${`$$unsubscribe_${name}`} = @subscribe(${name}, #value => $${value} = #value)`;
23518 if (component.compile_options.dev) {
23519 insert = b `@validate_store(${name}, '${name}'); ${insert}`;
23520 }
23521 return insert;
23522 });
23523 const instance_javascript = component.extract_javascript(component.ast.instance);
23524 // TODO only do this for props with a default value
23525 const parent_bindings = instance_javascript
23526 ? component.vars
23527 .filter(variable => !variable.module && variable.export_name)
23528 .map(prop => {
23529 return b `if ($$props.${prop.export_name} === void 0 && $$bindings.${prop.export_name} && ${prop.name} !== void 0) $$bindings.${prop.export_name}(${prop.name});`;
23530 })
23531 : [];
23532 const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
23533 const variable = component.var_lookup.get(name);
23534 return variable.injected;
23535 });
23536 const reactive_declarations = component.reactive_declarations.map(d => {
23537 const body = d.node.body;
23538 let statement = b `${body}`;
23539 if (!d.declaration) { // TODO do not add label if it's not referenced
23540 statement = b `$: { ${statement} }`;
23541 }
23542 return statement;
23543 });
23544 const main = renderer.has_bindings
23545 ? b `
23546 let $$settled;
23547 let $$rendered;
23548
23549 do {
23550 $$settled = true;
23551
23552 ${reactive_declarations}
23553
23554 $$rendered = ${literal};
23555 } while (!$$settled);
23556
23557 ${reactive_store_unsubscriptions}
23558
23559 return $$rendered;
23560 `
23561 : b `
23562 ${reactive_declarations}
23563
23564 ${reactive_store_unsubscriptions}
23565
23566 return ${literal};`;
23567 const blocks = [
23568 ...injected.map(name => b `let ${name};`),
23569 rest,
23570 slots,
23571 ...reactive_store_declarations,
23572 ...reactive_store_subscriptions,
23573 instance_javascript,
23574 ...parent_bindings,
23575 css.code && b `$$result.css.add(#css);`,
23576 main
23577 ].filter(Boolean);
23578 const js = b `
23579 ${css.code ? b `
23580 const #css = {
23581 code: "${css.code}",
23582 map: ${css.map ? string_literal(css.map.toString()) : 'null'}
23583 };` : null}
23584
23585 ${component.extract_javascript(component.ast.module)}
23586
23587 ${component.fully_hoisted}
23588
23589 const ${name} = @create_ssr_component(($$result, $$props, $$bindings, #slots) => {
23590 ${blocks}
23591 });
23592 `;
23593 return { js, css };
23594 }
23595 function trim(nodes) {
23596 let start = 0;
23597 for (; start < nodes.length; start += 1) {
23598 const node = nodes[start];
23599 if (node.type !== 'Text')
23600 break;
23601 node.data = node.data.replace(/^\s+/, '');
23602 if (node.data)
23603 break;
23604 }
23605 let end = nodes.length;
23606 for (; end > start; end -= 1) {
23607 const node = nodes[end - 1];
23608 if (node.type !== 'Text')
23609 break;
23610 node.data = node.data.replace(/\s+$/, '');
23611 if (node.data)
23612 break;
23613 }
23614 return nodes.slice(start, end);
23615 }
23616
23617 const wrappers$1 = { esm, cjs };
23618 function create_module(program, format, name, banner, sveltePath = 'svelte', helpers, globals, imports, module_exports) {
23619 const internal_path = `${sveltePath}/internal`;
23620 helpers.sort((a, b) => (a.name < b.name) ? -1 : 1);
23621 globals.sort((a, b) => (a.name < b.name) ? -1 : 1);
23622 if (format === 'esm') {
23623 return esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
23624 }
23625 if (format === 'cjs')
23626 return cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);
23627 throw new Error(`options.format is invalid (must be ${list$1(Object.keys(wrappers$1))})`);
23628 }
23629 function edit_source(source, sveltePath) {
23630 return source === 'svelte' || source.startsWith('svelte/')
23631 ? source.replace('svelte', sveltePath)
23632 : source;
23633 }
23634 function get_internal_globals(globals, helpers) {
23635 return globals.length > 0 && {
23636 type: 'VariableDeclaration',
23637 kind: 'const',
23638 declarations: [{
23639 type: 'VariableDeclarator',
23640 id: {
23641 type: 'ObjectPattern',
23642 properties: globals.map(g => ({
23643 type: 'Property',
23644 method: false,
23645 shorthand: false,
23646 computed: false,
23647 key: { type: 'Identifier', name: g.name },
23648 value: g.alias,
23649 kind: 'init'
23650 }))
23651 },
23652 init: helpers.find(({ name }) => name === 'globals').alias
23653 }]
23654 };
23655 }
23656 function esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
23657 const import_declaration = {
23658 type: 'ImportDeclaration',
23659 specifiers: helpers.map(h => ({
23660 type: 'ImportSpecifier',
23661 local: h.alias,
23662 imported: { type: 'Identifier', name: h.name }
23663 })),
23664 source: { type: 'Literal', value: internal_path }
23665 };
23666 const internal_globals = get_internal_globals(globals, helpers);
23667 // edit user imports
23668 imports.forEach(node => {
23669 node.source.value = edit_source(node.source.value, sveltePath);
23670 });
23671 const exports = module_exports.length > 0 && {
23672 type: 'ExportNamedDeclaration',
23673 specifiers: module_exports.map(x => ({
23674 type: 'Specifier',
23675 local: { type: 'Identifier', name: x.name },
23676 exported: { type: 'Identifier', name: x.as }
23677 }))
23678 };
23679 program.body = b `
23680 /* ${banner} */
23681
23682 ${import_declaration}
23683 ${internal_globals}
23684 ${imports}
23685
23686 ${program.body}
23687
23688 export default ${name};
23689 ${exports}
23690 `;
23691 }
23692 function cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports) {
23693 const internal_requires = {
23694 type: 'VariableDeclaration',
23695 kind: 'const',
23696 declarations: [{
23697 type: 'VariableDeclarator',
23698 id: {
23699 type: 'ObjectPattern',
23700 properties: helpers.map(h => ({
23701 type: 'Property',
23702 method: false,
23703 shorthand: false,
23704 computed: false,
23705 key: { type: 'Identifier', name: h.name },
23706 value: h.alias,
23707 kind: 'init'
23708 }))
23709 },
23710 init: x `require("${internal_path}")`
23711 }]
23712 };
23713 const internal_globals = get_internal_globals(globals, helpers);
23714 const user_requires = imports.map(node => {
23715 const init = x `require("${edit_source(node.source.value, sveltePath)}")`;
23716 if (node.specifiers.length === 0) {
23717 return b `${init};`;
23718 }
23719 return {
23720 type: 'VariableDeclaration',
23721 kind: 'const',
23722 declarations: [{
23723 type: 'VariableDeclarator',
23724 id: node.specifiers[0].type === 'ImportNamespaceSpecifier'
23725 ? { type: 'Identifier', name: node.specifiers[0].local.name }
23726 : {
23727 type: 'ObjectPattern',
23728 properties: node.specifiers.map(s => ({
23729 type: 'Property',
23730 method: false,
23731 shorthand: false,
23732 computed: false,
23733 key: s.type === 'ImportSpecifier' ? s.imported : { type: 'Identifier', name: 'default' },
23734 value: s.local,
23735 kind: 'init'
23736 }))
23737 },
23738 init
23739 }]
23740 };
23741 });
23742 const exports = module_exports.map(x => b `exports.${{ type: 'Identifier', name: x.as }} = ${{ type: 'Identifier', name: x.name }};`);
23743 program.body = b `
23744 /* ${banner} */
23745
23746 "use strict";
23747 ${internal_requires}
23748 ${internal_globals}
23749 ${user_requires}
23750
23751 ${program.body}
23752
23753 exports.default = ${name};
23754 ${exports}
23755 `;
23756 }
23757
23758 var Chunk = function Chunk(start, end, content) {
23759 this.start = start;
23760 this.end = end;
23761 this.original = content;
23762
23763 this.intro = '';
23764 this.outro = '';
23765
23766 this.content = content;
23767 this.storeName = false;
23768 this.edited = false;
23769
23770 // we make these non-enumerable, for sanity while debugging
23771 Object.defineProperties(this, {
23772 previous: { writable: true, value: null },
23773 next: { writable: true, value: null }
23774 });
23775 };
23776
23777 Chunk.prototype.appendLeft = function appendLeft (content) {
23778 this.outro += content;
23779 };
23780
23781 Chunk.prototype.appendRight = function appendRight (content) {
23782 this.intro = this.intro + content;
23783 };
23784
23785 Chunk.prototype.clone = function clone () {
23786 var chunk = new Chunk(this.start, this.end, this.original);
23787
23788 chunk.intro = this.intro;
23789 chunk.outro = this.outro;
23790 chunk.content = this.content;
23791 chunk.storeName = this.storeName;
23792 chunk.edited = this.edited;
23793
23794 return chunk;
23795 };
23796
23797 Chunk.prototype.contains = function contains (index) {
23798 return this.start < index && index < this.end;
23799 };
23800
23801 Chunk.prototype.eachNext = function eachNext (fn) {
23802 var chunk = this;
23803 while (chunk) {
23804 fn(chunk);
23805 chunk = chunk.next;
23806 }
23807 };
23808
23809 Chunk.prototype.eachPrevious = function eachPrevious (fn) {
23810 var chunk = this;
23811 while (chunk) {
23812 fn(chunk);
23813 chunk = chunk.previous;
23814 }
23815 };
23816
23817 Chunk.prototype.edit = function edit (content, storeName, contentOnly) {
23818 this.content = content;
23819 if (!contentOnly) {
23820 this.intro = '';
23821 this.outro = '';
23822 }
23823 this.storeName = storeName;
23824
23825 this.edited = true;
23826
23827 return this;
23828 };
23829
23830 Chunk.prototype.prependLeft = function prependLeft (content) {
23831 this.outro = content + this.outro;
23832 };
23833
23834 Chunk.prototype.prependRight = function prependRight (content) {
23835 this.intro = content + this.intro;
23836 };
23837
23838 Chunk.prototype.split = function split (index) {
23839 var sliceIndex = index - this.start;
23840
23841 var originalBefore = this.original.slice(0, sliceIndex);
23842 var originalAfter = this.original.slice(sliceIndex);
23843
23844 this.original = originalBefore;
23845
23846 var newChunk = new Chunk(index, this.end, originalAfter);
23847 newChunk.outro = this.outro;
23848 this.outro = '';
23849
23850 this.end = index;
23851
23852 if (this.edited) {
23853 // TODO is this block necessary?...
23854 newChunk.edit('', false);
23855 this.content = '';
23856 } else {
23857 this.content = originalBefore;
23858 }
23859
23860 newChunk.next = this.next;
23861 if (newChunk.next) { newChunk.next.previous = newChunk; }
23862 newChunk.previous = this;
23863 this.next = newChunk;
23864
23865 return newChunk;
23866 };
23867
23868 Chunk.prototype.toString = function toString () {
23869 return this.intro + this.content + this.outro;
23870 };
23871
23872 Chunk.prototype.trimEnd = function trimEnd (rx) {
23873 this.outro = this.outro.replace(rx, '');
23874 if (this.outro.length) { return true; }
23875
23876 var trimmed = this.content.replace(rx, '');
23877
23878 if (trimmed.length) {
23879 if (trimmed !== this.content) {
23880 this.split(this.start + trimmed.length).edit('', undefined, true);
23881 }
23882 return true;
23883
23884 } else {
23885 this.edit('', undefined, true);
23886
23887 this.intro = this.intro.replace(rx, '');
23888 if (this.intro.length) { return true; }
23889 }
23890 };
23891
23892 Chunk.prototype.trimStart = function trimStart (rx) {
23893 this.intro = this.intro.replace(rx, '');
23894 if (this.intro.length) { return true; }
23895
23896 var trimmed = this.content.replace(rx, '');
23897
23898 if (trimmed.length) {
23899 if (trimmed !== this.content) {
23900 this.split(this.end - trimmed.length);
23901 this.edit('', undefined, true);
23902 }
23903 return true;
23904
23905 } else {
23906 this.edit('', undefined, true);
23907
23908 this.outro = this.outro.replace(rx, '');
23909 if (this.outro.length) { return true; }
23910 }
23911 };
23912
23913 var btoa$2 = function () {
23914 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
23915 };
23916 if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
23917 btoa$2 = function (str) { return window.btoa(unescape(encodeURIComponent(str))); };
23918 } else if (typeof Buffer === 'function') {
23919 btoa$2 = function (str) { return Buffer.from(str, 'utf-8').toString('base64'); };
23920 }
23921
23922 var SourceMap$1 = function SourceMap(properties) {
23923 this.version = 3;
23924 this.file = properties.file;
23925 this.sources = properties.sources;
23926 this.sourcesContent = properties.sourcesContent;
23927 this.names = properties.names;
23928 this.mappings = encode(properties.mappings);
23929 };
23930
23931 SourceMap$1.prototype.toString = function toString () {
23932 return JSON.stringify(this);
23933 };
23934
23935 SourceMap$1.prototype.toUrl = function toUrl () {
23936 return 'data:application/json;charset=utf-8;base64,' + btoa$2(this.toString());
23937 };
23938
23939 function guessIndent(code) {
23940 var lines = code.split('\n');
23941
23942 var tabbed = lines.filter(function (line) { return /^\t+/.test(line); });
23943 var spaced = lines.filter(function (line) { return /^ {2,}/.test(line); });
23944
23945 if (tabbed.length === 0 && spaced.length === 0) {
23946 return null;
23947 }
23948
23949 // More lines tabbed than spaced? Assume tabs, and
23950 // default to tabs in the case of a tie (or nothing
23951 // to go on)
23952 if (tabbed.length >= spaced.length) {
23953 return '\t';
23954 }
23955
23956 // Otherwise, we need to guess the multiple
23957 var min = spaced.reduce(function (previous, current) {
23958 var numSpaces = /^ +/.exec(current)[0].length;
23959 return Math.min(numSpaces, previous);
23960 }, Infinity);
23961
23962 return new Array(min + 1).join(' ');
23963 }
23964
23965 function getRelativePath(from, to) {
23966 var fromParts = from.split(/[/\\]/);
23967 var toParts = to.split(/[/\\]/);
23968
23969 fromParts.pop(); // get dirname
23970
23971 while (fromParts[0] === toParts[0]) {
23972 fromParts.shift();
23973 toParts.shift();
23974 }
23975
23976 if (fromParts.length) {
23977 var i = fromParts.length;
23978 while (i--) { fromParts[i] = '..'; }
23979 }
23980
23981 return fromParts.concat(toParts).join('/');
23982 }
23983
23984 var toString$1 = Object.prototype.toString;
23985
23986 function isObject(thing) {
23987 return toString$1.call(thing) === '[object Object]';
23988 }
23989
23990 function getLocator$1(source) {
23991 var originalLines = source.split('\n');
23992 var lineOffsets = [];
23993
23994 for (var i = 0, pos = 0; i < originalLines.length; i++) {
23995 lineOffsets.push(pos);
23996 pos += originalLines[i].length + 1;
23997 }
23998
23999 return function locate(index) {
24000 var i = 0;
24001 var j = lineOffsets.length;
24002 while (i < j) {
24003 var m = (i + j) >> 1;
24004 if (index < lineOffsets[m]) {
24005 j = m;
24006 } else {
24007 i = m + 1;
24008 }
24009 }
24010 var line = i - 1;
24011 var column = index - lineOffsets[line];
24012 return { line: line, column: column };
24013 };
24014 }
24015
24016 var Mappings = function Mappings(hires) {
24017 this.hires = hires;
24018 this.generatedCodeLine = 0;
24019 this.generatedCodeColumn = 0;
24020 this.raw = [];
24021 this.rawSegments = this.raw[this.generatedCodeLine] = [];
24022 this.pending = null;
24023 };
24024
24025 Mappings.prototype.addEdit = function addEdit (sourceIndex, content, loc, nameIndex) {
24026 if (content.length) {
24027 var segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
24028 if (nameIndex >= 0) {
24029 segment.push(nameIndex);
24030 }
24031 this.rawSegments.push(segment);
24032 } else if (this.pending) {
24033 this.rawSegments.push(this.pending);
24034 }
24035
24036 this.advance(content);
24037 this.pending = null;
24038 };
24039
24040 Mappings.prototype.addUneditedChunk = function addUneditedChunk (sourceIndex, chunk, original, loc, sourcemapLocations) {
24041 var originalCharIndex = chunk.start;
24042 var first = true;
24043
24044 while (originalCharIndex < chunk.end) {
24045 if (this.hires || first || sourcemapLocations[originalCharIndex]) {
24046 this.rawSegments.push([this.generatedCodeColumn, sourceIndex, loc.line, loc.column]);
24047 }
24048
24049 if (original[originalCharIndex] === '\n') {
24050 loc.line += 1;
24051 loc.column = 0;
24052 this.generatedCodeLine += 1;
24053 this.raw[this.generatedCodeLine] = this.rawSegments = [];
24054 this.generatedCodeColumn = 0;
24055 } else {
24056 loc.column += 1;
24057 this.generatedCodeColumn += 1;
24058 }
24059
24060 originalCharIndex += 1;
24061 first = false;
24062 }
24063
24064 this.pending = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
24065 };
24066
24067 Mappings.prototype.advance = function advance (str) {
24068 if (!str) { return; }
24069
24070 var lines = str.split('\n');
24071
24072 if (lines.length > 1) {
24073 for (var i = 0; i < lines.length - 1; i++) {
24074 this.generatedCodeLine++;
24075 this.raw[this.generatedCodeLine] = this.rawSegments = [];
24076 }
24077 this.generatedCodeColumn = 0;
24078 }
24079
24080 this.generatedCodeColumn += lines[lines.length - 1].length;
24081 };
24082
24083 var n = '\n';
24084
24085 var warned = {
24086 insertLeft: false,
24087 insertRight: false,
24088 storeName: false
24089 };
24090
24091 var MagicString = function MagicString(string, options) {
24092 if ( options === void 0 ) options = {};
24093
24094 var chunk = new Chunk(0, string.length, string);
24095
24096 Object.defineProperties(this, {
24097 original: { writable: true, value: string },
24098 outro: { writable: true, value: '' },
24099 intro: { writable: true, value: '' },
24100 firstChunk: { writable: true, value: chunk },
24101 lastChunk: { writable: true, value: chunk },
24102 lastSearchedChunk: { writable: true, value: chunk },
24103 byStart: { writable: true, value: {} },
24104 byEnd: { writable: true, value: {} },
24105 filename: { writable: true, value: options.filename },
24106 indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
24107 sourcemapLocations: { writable: true, value: {} },
24108 storedNames: { writable: true, value: {} },
24109 indentStr: { writable: true, value: guessIndent(string) }
24110 });
24111
24112 this.byStart[0] = chunk;
24113 this.byEnd[string.length] = chunk;
24114 };
24115
24116 MagicString.prototype.addSourcemapLocation = function addSourcemapLocation (char) {
24117 this.sourcemapLocations[char] = true;
24118 };
24119
24120 MagicString.prototype.append = function append (content) {
24121 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
24122
24123 this.outro += content;
24124 return this;
24125 };
24126
24127 MagicString.prototype.appendLeft = function appendLeft (index, content) {
24128 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
24129
24130 this._split(index);
24131
24132 var chunk = this.byEnd[index];
24133
24134 if (chunk) {
24135 chunk.appendLeft(content);
24136 } else {
24137 this.intro += content;
24138 }
24139 return this;
24140 };
24141
24142 MagicString.prototype.appendRight = function appendRight (index, content) {
24143 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
24144
24145 this._split(index);
24146
24147 var chunk = this.byStart[index];
24148
24149 if (chunk) {
24150 chunk.appendRight(content);
24151 } else {
24152 this.outro += content;
24153 }
24154 return this;
24155 };
24156
24157 MagicString.prototype.clone = function clone () {
24158 var cloned = new MagicString(this.original, { filename: this.filename });
24159
24160 var originalChunk = this.firstChunk;
24161 var clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());
24162
24163 while (originalChunk) {
24164 cloned.byStart[clonedChunk.start] = clonedChunk;
24165 cloned.byEnd[clonedChunk.end] = clonedChunk;
24166
24167 var nextOriginalChunk = originalChunk.next;
24168 var nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
24169
24170 if (nextClonedChunk) {
24171 clonedChunk.next = nextClonedChunk;
24172 nextClonedChunk.previous = clonedChunk;
24173
24174 clonedChunk = nextClonedChunk;
24175 }
24176
24177 originalChunk = nextOriginalChunk;
24178 }
24179
24180 cloned.lastChunk = clonedChunk;
24181
24182 if (this.indentExclusionRanges) {
24183 cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
24184 }
24185
24186 Object.keys(this.sourcemapLocations).forEach(function (loc) {
24187 cloned.sourcemapLocations[loc] = true;
24188 });
24189
24190 return cloned;
24191 };
24192
24193 MagicString.prototype.generateDecodedMap = function generateDecodedMap (options) {
24194 var this$1 = this;
24195
24196 options = options || {};
24197
24198 var sourceIndex = 0;
24199 var names = Object.keys(this.storedNames);
24200 var mappings = new Mappings(options.hires);
24201
24202 var locate = getLocator$1(this.original);
24203
24204 if (this.intro) {
24205 mappings.advance(this.intro);
24206 }
24207
24208 this.firstChunk.eachNext(function (chunk) {
24209 var loc = locate(chunk.start);
24210
24211 if (chunk.intro.length) { mappings.advance(chunk.intro); }
24212
24213 if (chunk.edited) {
24214 mappings.addEdit(
24215 sourceIndex,
24216 chunk.content,
24217 loc,
24218 chunk.storeName ? names.indexOf(chunk.original) : -1
24219 );
24220 } else {
24221 mappings.addUneditedChunk(sourceIndex, chunk, this$1.original, loc, this$1.sourcemapLocations);
24222 }
24223
24224 if (chunk.outro.length) { mappings.advance(chunk.outro); }
24225 });
24226
24227 return {
24228 file: options.file ? options.file.split(/[/\\]/).pop() : null,
24229 sources: [options.source ? getRelativePath(options.file || '', options.source) : null],
24230 sourcesContent: options.includeContent ? [this.original] : [null],
24231 names: names,
24232 mappings: mappings.raw
24233 };
24234 };
24235
24236 MagicString.prototype.generateMap = function generateMap (options) {
24237 return new SourceMap$1(this.generateDecodedMap(options));
24238 };
24239
24240 MagicString.prototype.getIndentString = function getIndentString () {
24241 return this.indentStr === null ? '\t' : this.indentStr;
24242 };
24243
24244 MagicString.prototype.indent = function indent (indentStr, options) {
24245 var pattern = /^[^\r\n]/gm;
24246
24247 if (isObject(indentStr)) {
24248 options = indentStr;
24249 indentStr = undefined;
24250 }
24251
24252 indentStr = indentStr !== undefined ? indentStr : this.indentStr || '\t';
24253
24254 if (indentStr === '') { return this; } // noop
24255
24256 options = options || {};
24257
24258 // Process exclusion ranges
24259 var isExcluded = {};
24260
24261 if (options.exclude) {
24262 var exclusions =
24263 typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;
24264 exclusions.forEach(function (exclusion) {
24265 for (var i = exclusion[0]; i < exclusion[1]; i += 1) {
24266 isExcluded[i] = true;
24267 }
24268 });
24269 }
24270
24271 var shouldIndentNextCharacter = options.indentStart !== false;
24272 var replacer = function (match) {
24273 if (shouldIndentNextCharacter) { return ("" + indentStr + match); }
24274 shouldIndentNextCharacter = true;
24275 return match;
24276 };
24277
24278 this.intro = this.intro.replace(pattern, replacer);
24279
24280 var charIndex = 0;
24281 var chunk = this.firstChunk;
24282
24283 while (chunk) {
24284 var end = chunk.end;
24285
24286 if (chunk.edited) {
24287 if (!isExcluded[charIndex]) {
24288 chunk.content = chunk.content.replace(pattern, replacer);
24289
24290 if (chunk.content.length) {
24291 shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';
24292 }
24293 }
24294 } else {
24295 charIndex = chunk.start;
24296
24297 while (charIndex < end) {
24298 if (!isExcluded[charIndex]) {
24299 var char = this.original[charIndex];
24300
24301 if (char === '\n') {
24302 shouldIndentNextCharacter = true;
24303 } else if (char !== '\r' && shouldIndentNextCharacter) {
24304 shouldIndentNextCharacter = false;
24305
24306 if (charIndex === chunk.start) {
24307 chunk.prependRight(indentStr);
24308 } else {
24309 this._splitChunk(chunk, charIndex);
24310 chunk = chunk.next;
24311 chunk.prependRight(indentStr);
24312 }
24313 }
24314 }
24315
24316 charIndex += 1;
24317 }
24318 }
24319
24320 charIndex = chunk.end;
24321 chunk = chunk.next;
24322 }
24323
24324 this.outro = this.outro.replace(pattern, replacer);
24325
24326 return this;
24327 };
24328
24329 MagicString.prototype.insert = function insert () {
24330 throw new Error('magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)');
24331 };
24332
24333 MagicString.prototype.insertLeft = function insertLeft (index, content) {
24334 if (!warned.insertLeft) {
24335 console.warn('magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead'); // eslint-disable-line no-console
24336 warned.insertLeft = true;
24337 }
24338
24339 return this.appendLeft(index, content);
24340 };
24341
24342 MagicString.prototype.insertRight = function insertRight (index, content) {
24343 if (!warned.insertRight) {
24344 console.warn('magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead'); // eslint-disable-line no-console
24345 warned.insertRight = true;
24346 }
24347
24348 return this.prependRight(index, content);
24349 };
24350
24351 MagicString.prototype.move = function move (start, end, index) {
24352 if (index >= start && index <= end) { throw new Error('Cannot move a selection inside itself'); }
24353
24354 this._split(start);
24355 this._split(end);
24356 this._split(index);
24357
24358 var first = this.byStart[start];
24359 var last = this.byEnd[end];
24360
24361 var oldLeft = first.previous;
24362 var oldRight = last.next;
24363
24364 var newRight = this.byStart[index];
24365 if (!newRight && last === this.lastChunk) { return this; }
24366 var newLeft = newRight ? newRight.previous : this.lastChunk;
24367
24368 if (oldLeft) { oldLeft.next = oldRight; }
24369 if (oldRight) { oldRight.previous = oldLeft; }
24370
24371 if (newLeft) { newLeft.next = first; }
24372 if (newRight) { newRight.previous = last; }
24373
24374 if (!first.previous) { this.firstChunk = last.next; }
24375 if (!last.next) {
24376 this.lastChunk = first.previous;
24377 this.lastChunk.next = null;
24378 }
24379
24380 first.previous = newLeft;
24381 last.next = newRight || null;
24382
24383 if (!newLeft) { this.firstChunk = first; }
24384 if (!newRight) { this.lastChunk = last; }
24385 return this;
24386 };
24387
24388 MagicString.prototype.overwrite = function overwrite (start, end, content, options) {
24389 if (typeof content !== 'string') { throw new TypeError('replacement content must be a string'); }
24390
24391 while (start < 0) { start += this.original.length; }
24392 while (end < 0) { end += this.original.length; }
24393
24394 if (end > this.original.length) { throw new Error('end is out of bounds'); }
24395 if (start === end)
24396 { throw new Error('Cannot overwrite a zero-length range – use appendLeft or prependRight instead'); }
24397
24398 this._split(start);
24399 this._split(end);
24400
24401 if (options === true) {
24402 if (!warned.storeName) {
24403 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
24404 warned.storeName = true;
24405 }
24406
24407 options = { storeName: true };
24408 }
24409 var storeName = options !== undefined ? options.storeName : false;
24410 var contentOnly = options !== undefined ? options.contentOnly : false;
24411
24412 if (storeName) {
24413 var original = this.original.slice(start, end);
24414 this.storedNames[original] = true;
24415 }
24416
24417 var first = this.byStart[start];
24418 var last = this.byEnd[end];
24419
24420 if (first) {
24421 if (end > first.end && first.next !== this.byStart[first.end]) {
24422 throw new Error('Cannot overwrite across a split point');
24423 }
24424
24425 first.edit(content, storeName, contentOnly);
24426
24427 if (first !== last) {
24428 var chunk = first.next;
24429 while (chunk !== last) {
24430 chunk.edit('', false);
24431 chunk = chunk.next;
24432 }
24433
24434 chunk.edit('', false);
24435 }
24436 } else {
24437 // must be inserting at the end
24438 var newChunk = new Chunk(start, end, '').edit(content, storeName);
24439
24440 // TODO last chunk in the array may not be the last chunk, if it's moved...
24441 last.next = newChunk;
24442 newChunk.previous = last;
24443 }
24444 return this;
24445 };
24446
24447 MagicString.prototype.prepend = function prepend (content) {
24448 if (typeof content !== 'string') { throw new TypeError('outro content must be a string'); }
24449
24450 this.intro = content + this.intro;
24451 return this;
24452 };
24453
24454 MagicString.prototype.prependLeft = function prependLeft (index, content) {
24455 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
24456
24457 this._split(index);
24458
24459 var chunk = this.byEnd[index];
24460
24461 if (chunk) {
24462 chunk.prependLeft(content);
24463 } else {
24464 this.intro = content + this.intro;
24465 }
24466 return this;
24467 };
24468
24469 MagicString.prototype.prependRight = function prependRight (index, content) {
24470 if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); }
24471
24472 this._split(index);
24473
24474 var chunk = this.byStart[index];
24475
24476 if (chunk) {
24477 chunk.prependRight(content);
24478 } else {
24479 this.outro = content + this.outro;
24480 }
24481 return this;
24482 };
24483
24484 MagicString.prototype.remove = function remove (start, end) {
24485 while (start < 0) { start += this.original.length; }
24486 while (end < 0) { end += this.original.length; }
24487
24488 if (start === end) { return this; }
24489
24490 if (start < 0 || end > this.original.length) { throw new Error('Character is out of bounds'); }
24491 if (start > end) { throw new Error('end must be greater than start'); }
24492
24493 this._split(start);
24494 this._split(end);
24495
24496 var chunk = this.byStart[start];
24497
24498 while (chunk) {
24499 chunk.intro = '';
24500 chunk.outro = '';
24501 chunk.edit('');
24502
24503 chunk = end > chunk.end ? this.byStart[chunk.end] : null;
24504 }
24505 return this;
24506 };
24507
24508 MagicString.prototype.lastChar = function lastChar () {
24509 if (this.outro.length)
24510 { return this.outro[this.outro.length - 1]; }
24511 var chunk = this.lastChunk;
24512 do {
24513 if (chunk.outro.length)
24514 { return chunk.outro[chunk.outro.length - 1]; }
24515 if (chunk.content.length)
24516 { return chunk.content[chunk.content.length - 1]; }
24517 if (chunk.intro.length)
24518 { return chunk.intro[chunk.intro.length - 1]; }
24519 } while (chunk = chunk.previous);
24520 if (this.intro.length)
24521 { return this.intro[this.intro.length - 1]; }
24522 return '';
24523 };
24524
24525 MagicString.prototype.lastLine = function lastLine () {
24526 var lineIndex = this.outro.lastIndexOf(n);
24527 if (lineIndex !== -1)
24528 { return this.outro.substr(lineIndex + 1); }
24529 var lineStr = this.outro;
24530 var chunk = this.lastChunk;
24531 do {
24532 if (chunk.outro.length > 0) {
24533 lineIndex = chunk.outro.lastIndexOf(n);
24534 if (lineIndex !== -1)
24535 { return chunk.outro.substr(lineIndex + 1) + lineStr; }
24536 lineStr = chunk.outro + lineStr;
24537 }
24538
24539 if (chunk.content.length > 0) {
24540 lineIndex = chunk.content.lastIndexOf(n);
24541 if (lineIndex !== -1)
24542 { return chunk.content.substr(lineIndex + 1) + lineStr; }
24543 lineStr = chunk.content + lineStr;
24544 }
24545
24546 if (chunk.intro.length > 0) {
24547 lineIndex = chunk.intro.lastIndexOf(n);
24548 if (lineIndex !== -1)
24549 { return chunk.intro.substr(lineIndex + 1) + lineStr; }
24550 lineStr = chunk.intro + lineStr;
24551 }
24552 } while (chunk = chunk.previous);
24553 lineIndex = this.intro.lastIndexOf(n);
24554 if (lineIndex !== -1)
24555 { return this.intro.substr(lineIndex + 1) + lineStr; }
24556 return this.intro + lineStr;
24557 };
24558
24559 MagicString.prototype.slice = function slice (start, end) {
24560 if ( start === void 0 ) start = 0;
24561 if ( end === void 0 ) end = this.original.length;
24562
24563 while (start < 0) { start += this.original.length; }
24564 while (end < 0) { end += this.original.length; }
24565
24566 var result = '';
24567
24568 // find start chunk
24569 var chunk = this.firstChunk;
24570 while (chunk && (chunk.start > start || chunk.end <= start)) {
24571 // found end chunk before start
24572 if (chunk.start < end && chunk.end >= end) {
24573 return result;
24574 }
24575
24576 chunk = chunk.next;
24577 }
24578
24579 if (chunk && chunk.edited && chunk.start !== start)
24580 { throw new Error(("Cannot use replaced character " + start + " as slice start anchor.")); }
24581
24582 var startChunk = chunk;
24583 while (chunk) {
24584 if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
24585 result += chunk.intro;
24586 }
24587
24588 var containsEnd = chunk.start < end && chunk.end >= end;
24589 if (containsEnd && chunk.edited && chunk.end !== end)
24590 { throw new Error(("Cannot use replaced character " + end + " as slice end anchor.")); }
24591
24592 var sliceStart = startChunk === chunk ? start - chunk.start : 0;
24593 var sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
24594
24595 result += chunk.content.slice(sliceStart, sliceEnd);
24596
24597 if (chunk.outro && (!containsEnd || chunk.end === end)) {
24598 result += chunk.outro;
24599 }
24600
24601 if (containsEnd) {
24602 break;
24603 }
24604
24605 chunk = chunk.next;
24606 }
24607
24608 return result;
24609 };
24610
24611 // TODO deprecate this? not really very useful
24612 MagicString.prototype.snip = function snip (start, end) {
24613 var clone = this.clone();
24614 clone.remove(0, start);
24615 clone.remove(end, clone.original.length);
24616
24617 return clone;
24618 };
24619
24620 MagicString.prototype._split = function _split (index) {
24621 if (this.byStart[index] || this.byEnd[index]) { return; }
24622
24623 var chunk = this.lastSearchedChunk;
24624 var searchForward = index > chunk.end;
24625
24626 while (chunk) {
24627 if (chunk.contains(index)) { return this._splitChunk(chunk, index); }
24628
24629 chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
24630 }
24631 };
24632
24633 MagicString.prototype._splitChunk = function _splitChunk (chunk, index) {
24634 if (chunk.edited && chunk.content.length) {
24635 // zero-length edited chunks are a special case (overlapping replacements)
24636 var loc = getLocator$1(this.original)(index);
24637 throw new Error(
24638 ("Cannot split a chunk that has already been edited (" + (loc.line) + ":" + (loc.column) + " – \"" + (chunk.original) + "\")")
24639 );
24640 }
24641
24642 var newChunk = chunk.split(index);
24643
24644 this.byEnd[index] = chunk;
24645 this.byStart[index] = newChunk;
24646 this.byEnd[newChunk.end] = newChunk;
24647
24648 if (chunk === this.lastChunk) { this.lastChunk = newChunk; }
24649
24650 this.lastSearchedChunk = chunk;
24651 return true;
24652 };
24653
24654 MagicString.prototype.toString = function toString () {
24655 var str = this.intro;
24656
24657 var chunk = this.firstChunk;
24658 while (chunk) {
24659 str += chunk.toString();
24660 chunk = chunk.next;
24661 }
24662
24663 return str + this.outro;
24664 };
24665
24666 MagicString.prototype.isEmpty = function isEmpty () {
24667 var chunk = this.firstChunk;
24668 do {
24669 if (chunk.intro.length && chunk.intro.trim() ||
24670 chunk.content.length && chunk.content.trim() ||
24671 chunk.outro.length && chunk.outro.trim())
24672 { return false; }
24673 } while (chunk = chunk.next);
24674 return true;
24675 };
24676
24677 MagicString.prototype.length = function length () {
24678 var chunk = this.firstChunk;
24679 var length = 0;
24680 do {
24681 length += chunk.intro.length + chunk.content.length + chunk.outro.length;
24682 } while (chunk = chunk.next);
24683 return length;
24684 };
24685
24686 MagicString.prototype.trimLines = function trimLines () {
24687 return this.trim('[\\r\\n]');
24688 };
24689
24690 MagicString.prototype.trim = function trim (charType) {
24691 return this.trimStart(charType).trimEnd(charType);
24692 };
24693
24694 MagicString.prototype.trimEndAborted = function trimEndAborted (charType) {
24695 var rx = new RegExp((charType || '\\s') + '+$');
24696
24697 this.outro = this.outro.replace(rx, '');
24698 if (this.outro.length) { return true; }
24699
24700 var chunk = this.lastChunk;
24701
24702 do {
24703 var end = chunk.end;
24704 var aborted = chunk.trimEnd(rx);
24705
24706 // if chunk was trimmed, we have a new lastChunk
24707 if (chunk.end !== end) {
24708 if (this.lastChunk === chunk) {
24709 this.lastChunk = chunk.next;
24710 }
24711
24712 this.byEnd[chunk.end] = chunk;
24713 this.byStart[chunk.next.start] = chunk.next;
24714 this.byEnd[chunk.next.end] = chunk.next;
24715 }
24716
24717 if (aborted) { return true; }
24718 chunk = chunk.previous;
24719 } while (chunk);
24720
24721 return false;
24722 };
24723
24724 MagicString.prototype.trimEnd = function trimEnd (charType) {
24725 this.trimEndAborted(charType);
24726 return this;
24727 };
24728 MagicString.prototype.trimStartAborted = function trimStartAborted (charType) {
24729 var rx = new RegExp('^' + (charType || '\\s') + '+');
24730
24731 this.intro = this.intro.replace(rx, '');
24732 if (this.intro.length) { return true; }
24733
24734 var chunk = this.firstChunk;
24735
24736 do {
24737 var end = chunk.end;
24738 var aborted = chunk.trimStart(rx);
24739
24740 if (chunk.end !== end) {
24741 // special case...
24742 if (chunk === this.lastChunk) { this.lastChunk = chunk.next; }
24743
24744 this.byEnd[chunk.end] = chunk;
24745 this.byStart[chunk.next.start] = chunk.next;
24746 this.byEnd[chunk.next.end] = chunk.next;
24747 }
24748
24749 if (aborted) { return true; }
24750 chunk = chunk.next;
24751 } while (chunk);
24752
24753 return false;
24754 };
24755
24756 MagicString.prototype.trimStart = function trimStart (charType) {
24757 this.trimStartAborted(charType);
24758 return this;
24759 };
24760
24761 const UNKNOWN = {};
24762 function gather_possible_values(node, set) {
24763 if (node.type === 'Literal') {
24764 set.add(node.value);
24765 }
24766 else if (node.type === 'ConditionalExpression') {
24767 gather_possible_values(node.consequent, set);
24768 gather_possible_values(node.alternate, set);
24769 }
24770 else {
24771 set.add(UNKNOWN);
24772 }
24773 }
24774
24775 var BlockAppliesToNode;
24776 (function (BlockAppliesToNode) {
24777 BlockAppliesToNode[BlockAppliesToNode["NotPossible"] = 0] = "NotPossible";
24778 BlockAppliesToNode[BlockAppliesToNode["Possible"] = 1] = "Possible";
24779 BlockAppliesToNode[BlockAppliesToNode["UnknownSelectorType"] = 2] = "UnknownSelectorType";
24780 })(BlockAppliesToNode || (BlockAppliesToNode = {}));
24781 var NodeExist;
24782 (function (NodeExist) {
24783 NodeExist[NodeExist["Probably"] = 1] = "Probably";
24784 NodeExist[NodeExist["Definitely"] = 2] = "Definitely";
24785 })(NodeExist || (NodeExist = {}));
24786 const whitelist_attribute_selector = new Map([
24787 ['details', new Set(['open'])]
24788 ]);
24789 class Selector$1 {
24790 constructor(node, stylesheet) {
24791 this.node = node;
24792 this.stylesheet = stylesheet;
24793 this.blocks = group_selectors(node);
24794 // take trailing :global(...) selectors out of consideration
24795 let i = this.blocks.length;
24796 while (i > 0) {
24797 if (!this.blocks[i - 1].global)
24798 break;
24799 i -= 1;
24800 }
24801 this.local_blocks = this.blocks.slice(0, i);
24802 this.used = this.local_blocks.length === 0;
24803 }
24804 apply(node) {
24805 const to_encapsulate = [];
24806 apply_selector(this.local_blocks.slice(), node, to_encapsulate);
24807 if (to_encapsulate.length > 0) {
24808 to_encapsulate.forEach(({ node, block }) => {
24809 this.stylesheet.nodes_with_css_class.add(node);
24810 block.should_encapsulate = true;
24811 });
24812 this.used = true;
24813 }
24814 }
24815 minify(code) {
24816 let c = null;
24817 this.blocks.forEach((block, i) => {
24818 if (i > 0) {
24819 if (block.start - c > 1) {
24820 code.overwrite(c, block.start, block.combinator.name || ' ');
24821 }
24822 }
24823 c = block.end;
24824 });
24825 }
24826 transform(code, attr, max_amount_class_specificity_increased) {
24827 const amount_class_specificity_to_increase = max_amount_class_specificity_increased - this.blocks.filter(block => block.should_encapsulate).length;
24828 function encapsulate_block(block, attr) {
24829 let i = block.selectors.length;
24830 while (i--) {
24831 const selector = block.selectors[i];
24832 if (selector.type === 'PseudoElementSelector' || selector.type === 'PseudoClassSelector') {
24833 if (selector.name !== 'root') {
24834 if (i === 0)
24835 code.prependRight(selector.start, attr);
24836 }
24837 continue;
24838 }
24839 if (selector.type === 'TypeSelector' && selector.name === '*') {
24840 code.overwrite(selector.start, selector.end, attr);
24841 }
24842 else {
24843 code.appendLeft(selector.end, attr);
24844 }
24845 break;
24846 }
24847 }
24848 this.blocks.forEach((block, index) => {
24849 if (block.global) {
24850 const selector = block.selectors[0];
24851 const first = selector.children[0];
24852 const last = selector.children[selector.children.length - 1];
24853 code.remove(selector.start, first.start).remove(last.end, selector.end);
24854 }
24855 if (block.should_encapsulate)
24856 encapsulate_block(block, index === this.blocks.length - 1 ? attr.repeat(amount_class_specificity_to_increase + 1) : attr);
24857 });
24858 }
24859 validate(component) {
24860 this.blocks.forEach((block) => {
24861 let i = block.selectors.length;
24862 while (i-- > 1) {
24863 const selector = block.selectors[i];
24864 if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
24865 component.error(selector, {
24866 code: 'css-invalid-global',
24867 message: ':global(...) must be the first element in a compound selector'
24868 });
24869 }
24870 }
24871 });
24872 let start = 0;
24873 let end = this.blocks.length;
24874 for (; start < end; start += 1) {
24875 if (!this.blocks[start].global)
24876 break;
24877 }
24878 for (; end > start; end -= 1) {
24879 if (!this.blocks[end - 1].global)
24880 break;
24881 }
24882 for (let i = start; i < end; i += 1) {
24883 if (this.blocks[i].global) {
24884 component.error(this.blocks[i].selectors[0], {
24885 code: 'css-invalid-global',
24886 message: ':global(...) can be at the start or end of a selector sequence, but not in the middle'
24887 });
24888 }
24889 }
24890 }
24891 get_amount_class_specificity_increased() {
24892 let count = 0;
24893 for (const block of this.blocks) {
24894 if (block.should_encapsulate) {
24895 count++;
24896 }
24897 }
24898 return count;
24899 }
24900 }
24901 function apply_selector(blocks, node, to_encapsulate) {
24902 const block = blocks.pop();
24903 if (!block)
24904 return false;
24905 if (!node) {
24906 return block.global && blocks.every(block => block.global);
24907 }
24908 switch (block_might_apply_to_node(block, node)) {
24909 case BlockAppliesToNode.NotPossible:
24910 return false;
24911 case BlockAppliesToNode.UnknownSelectorType:
24912 // bail. TODO figure out what these could be
24913 to_encapsulate.push({ node, block });
24914 return true;
24915 }
24916 if (block.combinator) {
24917 if (block.combinator.type === 'WhiteSpace') {
24918 for (const ancestor_block of blocks) {
24919 if (ancestor_block.global) {
24920 continue;
24921 }
24922 let parent = node;
24923 while (parent = get_element_parent(parent)) {
24924 if (block_might_apply_to_node(ancestor_block, parent) !== BlockAppliesToNode.NotPossible) {
24925 to_encapsulate.push({ node: parent, block: ancestor_block });
24926 }
24927 }
24928 if (to_encapsulate.length) {
24929 to_encapsulate.push({ node, block });
24930 return true;
24931 }
24932 }
24933 if (blocks.every(block => block.global)) {
24934 to_encapsulate.push({ node, block });
24935 return true;
24936 }
24937 return false;
24938 }
24939 else if (block.combinator.name === '>') {
24940 if (apply_selector(blocks, get_element_parent(node), to_encapsulate)) {
24941 to_encapsulate.push({ node, block });
24942 return true;
24943 }
24944 return false;
24945 }
24946 else if (block.combinator.name === '+' || block.combinator.name === '~') {
24947 const siblings = get_possible_element_siblings(node, block.combinator.name === '+');
24948 let has_match = false;
24949 for (const possible_sibling of siblings.keys()) {
24950 if (apply_selector(blocks.slice(), possible_sibling, to_encapsulate)) {
24951 to_encapsulate.push({ node, block });
24952 has_match = true;
24953 }
24954 }
24955 return has_match;
24956 }
24957 // TODO other combinators
24958 to_encapsulate.push({ node, block });
24959 return true;
24960 }
24961 to_encapsulate.push({ node, block });
24962 return true;
24963 }
24964 function block_might_apply_to_node(block, node) {
24965 let i = block.selectors.length;
24966 while (i--) {
24967 const selector = block.selectors[i];
24968 const name = typeof selector.name === 'string' && selector.name.replace(/\\(.)/g, '$1');
24969 if (selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector') {
24970 continue;
24971 }
24972 if (selector.type === 'PseudoClassSelector' && name === 'global') {
24973 // TODO shouldn't see this here... maybe we should enforce that :global(...)
24974 // cannot be sandwiched between non-global selectors?
24975 return BlockAppliesToNode.NotPossible;
24976 }
24977 if (selector.type === 'ClassSelector') {
24978 if (!attribute_matches(node, 'class', name, '~=', false) && !node.classes.some(c => c.name === name))
24979 return BlockAppliesToNode.NotPossible;
24980 }
24981 else if (selector.type === 'IdSelector') {
24982 if (!attribute_matches(node, 'id', name, '=', false))
24983 return BlockAppliesToNode.NotPossible;
24984 }
24985 else if (selector.type === 'AttributeSelector') {
24986 if (!(whitelist_attribute_selector.has(node.name.toLowerCase()) && whitelist_attribute_selector.get(node.name.toLowerCase()).has(selector.name.name.toLowerCase())) &&
24987 !attribute_matches(node, selector.name.name, selector.value && unquote(selector.value), selector.matcher, selector.flags)) {
24988 return BlockAppliesToNode.NotPossible;
24989 }
24990 }
24991 else if (selector.type === 'TypeSelector') {
24992 if (node.name.toLowerCase() !== name.toLowerCase() && name !== '*')
24993 return BlockAppliesToNode.NotPossible;
24994 }
24995 else {
24996 return BlockAppliesToNode.UnknownSelectorType;
24997 }
24998 }
24999 return BlockAppliesToNode.Possible;
25000 }
25001 function test_attribute(operator, expected_value, case_insensitive, value) {
25002 if (case_insensitive) {
25003 expected_value = expected_value.toLowerCase();
25004 value = value.toLowerCase();
25005 }
25006 switch (operator) {
25007 case '=': return value === expected_value;
25008 case '~=': return value.split(/\s/).includes(expected_value);
25009 case '|=': return `${value}-`.startsWith(`${expected_value}-`);
25010 case '^=': return value.startsWith(expected_value);
25011 case '$=': return value.endsWith(expected_value);
25012 case '*=': return value.includes(expected_value);
25013 default: throw new Error("this shouldn't happen");
25014 }
25015 }
25016 function attribute_matches(node, name, expected_value, operator, case_insensitive) {
25017 const spread = node.attributes.find(attr => attr.type === 'Spread');
25018 if (spread)
25019 return true;
25020 if (node.bindings.some((binding) => binding.name === name))
25021 return true;
25022 const attr = node.attributes.find((attr) => attr.name === name);
25023 if (!attr)
25024 return false;
25025 if (attr.is_true)
25026 return operator === null;
25027 if (!expected_value)
25028 return true;
25029 if (attr.chunks.length === 1) {
25030 const value = attr.chunks[0];
25031 if (!value)
25032 return false;
25033 if (value.type === 'Text')
25034 return test_attribute(operator, expected_value, case_insensitive, value.data);
25035 }
25036 const possible_values = new Set();
25037 let prev_values = [];
25038 for (const chunk of attr.chunks) {
25039 const current_possible_values = new Set();
25040 if (chunk.type === 'Text') {
25041 current_possible_values.add(chunk.data);
25042 }
25043 else {
25044 gather_possible_values(chunk.node, current_possible_values);
25045 }
25046 // impossible to find out all combinations
25047 if (current_possible_values.has(UNKNOWN))
25048 return true;
25049 if (prev_values.length > 0) {
25050 const start_with_space = [];
25051 const remaining = [];
25052 current_possible_values.forEach((current_possible_value) => {
25053 if (/^\s/.test(current_possible_value)) {
25054 start_with_space.push(current_possible_value);
25055 }
25056 else {
25057 remaining.push(current_possible_value);
25058 }
25059 });
25060 if (remaining.length > 0) {
25061 if (start_with_space.length > 0) {
25062 prev_values.forEach(prev_value => possible_values.add(prev_value));
25063 }
25064 const combined = [];
25065 prev_values.forEach((prev_value) => {
25066 remaining.forEach((value) => {
25067 combined.push(prev_value + value);
25068 });
25069 });
25070 prev_values = combined;
25071 start_with_space.forEach((value) => {
25072 if (/\s$/.test(value)) {
25073 possible_values.add(value);
25074 }
25075 else {
25076 prev_values.push(value);
25077 }
25078 });
25079 continue;
25080 }
25081 else {
25082 prev_values.forEach(prev_value => possible_values.add(prev_value));
25083 prev_values = [];
25084 }
25085 }
25086 current_possible_values.forEach((current_possible_value) => {
25087 if (/\s$/.test(current_possible_value)) {
25088 possible_values.add(current_possible_value);
25089 }
25090 else {
25091 prev_values.push(current_possible_value);
25092 }
25093 });
25094 if (prev_values.length < current_possible_values.size) {
25095 prev_values.push(' ');
25096 }
25097 if (prev_values.length > 20) {
25098 // might grow exponentially, bail out
25099 return true;
25100 }
25101 }
25102 prev_values.forEach(prev_value => possible_values.add(prev_value));
25103 if (possible_values.has(UNKNOWN))
25104 return true;
25105 for (const value of possible_values) {
25106 if (test_attribute(operator, expected_value, case_insensitive, value))
25107 return true;
25108 }
25109 return false;
25110 }
25111 function unquote(value) {
25112 if (value.type === 'Identifier')
25113 return value.name;
25114 const str = value.value;
25115 if (str[0] === str[str.length - 1] && str[0] === "'" || str[0] === '"') {
25116 return str.slice(1, str.length - 1);
25117 }
25118 return str;
25119 }
25120 function get_element_parent(node) {
25121 let parent = node;
25122 while ((parent = parent.parent) && parent.type !== 'Element')
25123 ;
25124 return parent;
25125 }
25126 function get_possible_element_siblings(node, adjacent_only) {
25127 const result = new Map();
25128 let prev = node;
25129 while (prev = prev.prev) {
25130 if (prev.type === 'Element') {
25131 if (!prev.attributes.find(attr => attr.type === 'Attribute' && attr.name.toLowerCase() === 'slot')) {
25132 result.set(prev, NodeExist.Definitely);
25133 }
25134 if (adjacent_only) {
25135 break;
25136 }
25137 }
25138 else if (prev.type === 'EachBlock' || prev.type === 'IfBlock' || prev.type === 'AwaitBlock') {
25139 const possible_last_child = get_possible_last_child(prev, adjacent_only);
25140 add_to_map(possible_last_child, result);
25141 if (adjacent_only && has_definite_elements(possible_last_child)) {
25142 return result;
25143 }
25144 }
25145 }
25146 if (!prev || !adjacent_only) {
25147 let parent = node;
25148 let skip_each_for_last_child = node.type === 'ElseBlock';
25149 while ((parent = parent.parent) && (parent.type === 'EachBlock' || parent.type === 'IfBlock' || parent.type === 'ElseBlock' || parent.type === 'AwaitBlock')) {
25150 const possible_siblings = get_possible_element_siblings(parent, adjacent_only);
25151 add_to_map(possible_siblings, result);
25152 if (parent.type === 'EachBlock') {
25153 // first child of each block can select the last child of each block as previous sibling
25154 if (skip_each_for_last_child) {
25155 skip_each_for_last_child = false;
25156 }
25157 else {
25158 add_to_map(get_possible_last_child(parent, adjacent_only), result);
25159 }
25160 }
25161 else if (parent.type === 'ElseBlock') {
25162 skip_each_for_last_child = true;
25163 parent = parent.parent;
25164 }
25165 if (adjacent_only && has_definite_elements(possible_siblings)) {
25166 break;
25167 }
25168 }
25169 }
25170 return result;
25171 }
25172 function get_possible_last_child(block, adjacent_only) {
25173 const result = new Map();
25174 if (block.type === 'EachBlock') {
25175 const each_result = loop_child(block.children, adjacent_only);
25176 const else_result = block.else ? loop_child(block.else.children, adjacent_only) : new Map();
25177 const not_exhaustive = !has_definite_elements(else_result);
25178 if (not_exhaustive) {
25179 mark_as_probably(each_result);
25180 mark_as_probably(else_result);
25181 }
25182 add_to_map(each_result, result);
25183 add_to_map(else_result, result);
25184 }
25185 else if (block.type === 'IfBlock') {
25186 const if_result = loop_child(block.children, adjacent_only);
25187 const else_result = block.else ? loop_child(block.else.children, adjacent_only) : new Map();
25188 const not_exhaustive = !has_definite_elements(if_result) || !has_definite_elements(else_result);
25189 if (not_exhaustive) {
25190 mark_as_probably(if_result);
25191 mark_as_probably(else_result);
25192 }
25193 add_to_map(if_result, result);
25194 add_to_map(else_result, result);
25195 }
25196 else if (block.type === 'AwaitBlock') {
25197 const pending_result = block.pending ? loop_child(block.pending.children, adjacent_only) : new Map();
25198 const then_result = block.then ? loop_child(block.then.children, adjacent_only) : new Map();
25199 const catch_result = block.catch ? loop_child(block.catch.children, adjacent_only) : new Map();
25200 const not_exhaustive = !has_definite_elements(pending_result) || !has_definite_elements(then_result) || !has_definite_elements(catch_result);
25201 if (not_exhaustive) {
25202 mark_as_probably(pending_result);
25203 mark_as_probably(then_result);
25204 mark_as_probably(catch_result);
25205 }
25206 add_to_map(pending_result, result);
25207 add_to_map(then_result, result);
25208 add_to_map(catch_result, result);
25209 }
25210 return result;
25211 }
25212 function has_definite_elements(result) {
25213 if (result.size === 0)
25214 return false;
25215 for (const exist of result.values()) {
25216 if (exist === NodeExist.Definitely) {
25217 return true;
25218 }
25219 }
25220 return false;
25221 }
25222 function add_to_map(from, to) {
25223 from.forEach((exist, element) => {
25224 to.set(element, higher_existance(exist, to.get(element)));
25225 });
25226 }
25227 function higher_existance(exist1, exist2) {
25228 if (exist1 === undefined || exist2 === undefined)
25229 return exist1 || exist2;
25230 return exist1 > exist2 ? exist1 : exist2;
25231 }
25232 function mark_as_probably(result) {
25233 for (const key of result.keys()) {
25234 result.set(key, NodeExist.Probably);
25235 }
25236 }
25237 function loop_child(children, adjacent_only) {
25238 const result = new Map();
25239 for (let i = children.length - 1; i >= 0; i--) {
25240 const child = children[i];
25241 if (child.type === 'Element') {
25242 result.set(child, NodeExist.Definitely);
25243 if (adjacent_only) {
25244 break;
25245 }
25246 }
25247 else if (child.type === 'EachBlock' || child.type === 'IfBlock' || child.type === 'AwaitBlock') {
25248 const child_result = get_possible_last_child(child, adjacent_only);
25249 add_to_map(child_result, result);
25250 if (adjacent_only && has_definite_elements(child_result)) {
25251 break;
25252 }
25253 }
25254 }
25255 return result;
25256 }
25257 class Block$2 {
25258 constructor(combinator) {
25259 this.combinator = combinator;
25260 this.global = false;
25261 this.selectors = [];
25262 this.start = null;
25263 this.end = null;
25264 this.should_encapsulate = false;
25265 }
25266 add(selector) {
25267 if (this.selectors.length === 0) {
25268 this.start = selector.start;
25269 this.global = selector.type === 'PseudoClassSelector' && selector.name === 'global';
25270 }
25271 this.selectors.push(selector);
25272 this.end = selector.end;
25273 }
25274 }
25275 function group_selectors(selector) {
25276 let block = new Block$2(null);
25277 const blocks = [block];
25278 selector.children.forEach((child) => {
25279 if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
25280 block = new Block$2(child);
25281 blocks.push(block);
25282 }
25283 else {
25284 block.add(child);
25285 }
25286 });
25287 return blocks;
25288 }
25289
25290 // https://github.com/darkskyapp/string-hash/blob/master/index.js
25291 function hash(str) {
25292 str = str.replace(/\r/g, '');
25293 let hash = 5381;
25294 let i = str.length;
25295 while (i--)
25296 hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
25297 return (hash >>> 0).toString(36);
25298 }
25299
25300 function remove_css_prefix(name) {
25301 return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, '');
25302 }
25303 const is_keyframes_node = (node) => remove_css_prefix(node.name) === 'keyframes';
25304 const at_rule_has_declaration = ({ block }) => block &&
25305 block.children &&
25306 block.children.find((node) => node.type === 'Declaration');
25307 function minify_declarations(code, start, declarations) {
25308 let c = start;
25309 declarations.forEach((declaration, i) => {
25310 const separator = i > 0 ? ';' : '';
25311 if ((declaration.node.start - c) > separator.length) {
25312 code.overwrite(c, declaration.node.start, separator);
25313 }
25314 declaration.minify(code);
25315 c = declaration.node.end;
25316 });
25317 return c;
25318 }
25319 class Rule$1 {
25320 constructor(node, stylesheet, parent) {
25321 this.node = node;
25322 this.parent = parent;
25323 this.selectors = node.selector.children.map((node) => new Selector$1(node, stylesheet));
25324 this.declarations = node.block.children.map((node) => new Declaration$1(node));
25325 }
25326 apply(node) {
25327 this.selectors.forEach(selector => selector.apply(node)); // TODO move the logic in here?
25328 }
25329 is_used(dev) {
25330 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
25331 return true;
25332 if (this.declarations.length === 0)
25333 return dev;
25334 return this.selectors.some(s => s.used);
25335 }
25336 minify(code, _dev) {
25337 let c = this.node.start;
25338 let started = false;
25339 this.selectors.forEach((selector) => {
25340 if (selector.used) {
25341 const separator = started ? ',' : '';
25342 if ((selector.node.start - c) > separator.length) {
25343 code.overwrite(c, selector.node.start, separator);
25344 }
25345 selector.minify(code);
25346 c = selector.node.end;
25347 started = true;
25348 }
25349 });
25350 code.remove(c, this.node.block.start);
25351 c = this.node.block.start + 1;
25352 c = minify_declarations(code, c, this.declarations);
25353 code.remove(c, this.node.block.end - 1);
25354 }
25355 transform(code, id, keyframes, max_amount_class_specificity_increased) {
25356 if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
25357 return true;
25358 const attr = `.${id}`;
25359 this.selectors.forEach(selector => selector.transform(code, attr, max_amount_class_specificity_increased));
25360 this.declarations.forEach(declaration => declaration.transform(code, keyframes));
25361 }
25362 validate(component) {
25363 this.selectors.forEach(selector => {
25364 selector.validate(component);
25365 });
25366 }
25367 warn_on_unused_selector(handler) {
25368 this.selectors.forEach(selector => {
25369 if (!selector.used)
25370 handler(selector);
25371 });
25372 }
25373 get_max_amount_class_specificity_increased() {
25374 return Math.max(...this.selectors.map(selector => selector.get_amount_class_specificity_increased()));
25375 }
25376 }
25377 class Declaration$1 {
25378 constructor(node) {
25379 this.node = node;
25380 }
25381 transform(code, keyframes) {
25382 const property = this.node.property && remove_css_prefix(this.node.property.toLowerCase());
25383 if (property === 'animation' || property === 'animation-name') {
25384 this.node.value.children.forEach((block) => {
25385 if (block.type === 'Identifier') {
25386 const name = block.name;
25387 if (keyframes.has(name)) {
25388 code.overwrite(block.start, block.end, keyframes.get(name));
25389 }
25390 }
25391 });
25392 }
25393 }
25394 minify(code) {
25395 if (!this.node.property)
25396 return; // @apply, and possibly other weird cases?
25397 const c = this.node.start + this.node.property.length;
25398 const first = this.node.value.children
25399 ? this.node.value.children[0]
25400 : this.node.value;
25401 let start = first.start;
25402 while (/\s/.test(code.original[start]))
25403 start += 1;
25404 if (start - c > 1) {
25405 code.overwrite(c, start, ':');
25406 }
25407 }
25408 }
25409 class Atrule$1 {
25410 constructor(node) {
25411 this.node = node;
25412 this.children = [];
25413 this.declarations = [];
25414 }
25415 apply(node) {
25416 if (this.node.name === 'media' || this.node.name === 'supports') {
25417 this.children.forEach(child => {
25418 child.apply(node);
25419 });
25420 }
25421 else if (is_keyframes_node(this.node)) {
25422 this.children.forEach((rule) => {
25423 rule.selectors.forEach(selector => {
25424 selector.used = true;
25425 });
25426 });
25427 }
25428 }
25429 is_used(_dev) {
25430 return true; // TODO
25431 }
25432 minify(code, dev) {
25433 if (this.node.name === 'media') {
25434 const expression_char = code.original[this.node.expression.start];
25435 let c = this.node.start + (expression_char === '(' ? 6 : 7);
25436 if (this.node.expression.start > c)
25437 code.remove(c, this.node.expression.start);
25438 this.node.expression.children.forEach((query) => {
25439 // TODO minify queries
25440 c = query.end;
25441 });
25442 code.remove(c, this.node.block.start);
25443 }
25444 else if (this.node.name === 'supports') {
25445 let c = this.node.start + 9;
25446 if (this.node.expression.start - c > 1)
25447 code.overwrite(c, this.node.expression.start, ' ');
25448 this.node.expression.children.forEach((query) => {
25449 // TODO minify queries
25450 c = query.end;
25451 });
25452 code.remove(c, this.node.block.start);
25453 }
25454 else {
25455 let c = this.node.start + this.node.name.length + 1;
25456 if (this.node.expression) {
25457 if (this.node.expression.start - c > 1)
25458 code.overwrite(c, this.node.expression.start, ' ');
25459 c = this.node.expression.end;
25460 }
25461 if (this.node.block && this.node.block.start - c > 0) {
25462 code.remove(c, this.node.block.start);
25463 }
25464 }
25465 // TODO other atrules
25466 if (this.node.block) {
25467 let c = this.node.block.start + 1;
25468 if (this.declarations.length) {
25469 c = minify_declarations(code, c, this.declarations);
25470 // if the atrule has children, leave the last declaration semicolon alone
25471 if (this.children.length)
25472 c++;
25473 }
25474 this.children.forEach(child => {
25475 if (child.is_used(dev)) {
25476 code.remove(c, child.node.start);
25477 child.minify(code, dev);
25478 c = child.node.end;
25479 }
25480 });
25481 code.remove(c, this.node.block.end - 1);
25482 }
25483 }
25484 transform(code, id, keyframes, max_amount_class_specificity_increased) {
25485 if (is_keyframes_node(this.node)) {
25486 this.node.expression.children.forEach(({ type, name, start, end }) => {
25487 if (type === 'Identifier') {
25488 if (name.startsWith('-global-')) {
25489 code.remove(start, start + 8);
25490 this.children.forEach((rule) => {
25491 rule.selectors.forEach(selector => {
25492 selector.used = true;
25493 });
25494 });
25495 }
25496 else {
25497 code.overwrite(start, end, keyframes.get(name));
25498 }
25499 }
25500 });
25501 }
25502 this.children.forEach(child => {
25503 child.transform(code, id, keyframes, max_amount_class_specificity_increased);
25504 });
25505 }
25506 validate(component) {
25507 this.children.forEach(child => {
25508 child.validate(component);
25509 });
25510 }
25511 warn_on_unused_selector(handler) {
25512 if (this.node.name !== 'media')
25513 return;
25514 this.children.forEach(child => {
25515 child.warn_on_unused_selector(handler);
25516 });
25517 }
25518 get_max_amount_class_specificity_increased() {
25519 return Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
25520 }
25521 }
25522 class Stylesheet {
25523 constructor(source, ast, filename, dev) {
25524 this.children = [];
25525 this.keyframes = new Map();
25526 this.nodes_with_css_class = new Set();
25527 this.source = source;
25528 this.ast = ast;
25529 this.filename = filename;
25530 this.dev = dev;
25531 if (ast.css && ast.css.children.length) {
25532 this.id = `svelte-${hash(ast.css.content.styles)}`;
25533 this.has_styles = true;
25534 const stack = [];
25535 let depth = 0;
25536 let current_atrule = null;
25537 walk(ast.css, {
25538 enter: (node) => {
25539 if (node.type === 'Atrule') {
25540 const atrule = new Atrule$1(node);
25541 stack.push(atrule);
25542 if (current_atrule) {
25543 current_atrule.children.push(atrule);
25544 }
25545 else if (depth <= 1) {
25546 this.children.push(atrule);
25547 }
25548 if (is_keyframes_node(node)) {
25549 node.expression.children.forEach((expression) => {
25550 if (expression.type === 'Identifier' && !expression.name.startsWith('-global-')) {
25551 this.keyframes.set(expression.name, `${this.id}-${expression.name}`);
25552 }
25553 });
25554 }
25555 else if (at_rule_has_declaration(node)) {
25556 const at_rule_declarations = node.block.children
25557 .filter(node => node.type === 'Declaration')
25558 .map(node => new Declaration$1(node));
25559 atrule.declarations.push(...at_rule_declarations);
25560 }
25561 current_atrule = atrule;
25562 }
25563 if (node.type === 'Rule') {
25564 const rule = new Rule$1(node, this, current_atrule);
25565 if (current_atrule) {
25566 current_atrule.children.push(rule);
25567 }
25568 else if (depth <= 1) {
25569 this.children.push(rule);
25570 }
25571 }
25572 depth += 1;
25573 },
25574 leave: (node) => {
25575 if (node.type === 'Atrule') {
25576 stack.pop();
25577 current_atrule = stack[stack.length - 1];
25578 }
25579 depth -= 1;
25580 }
25581 });
25582 }
25583 else {
25584 this.has_styles = false;
25585 }
25586 }
25587 apply(node) {
25588 if (!this.has_styles)
25589 return;
25590 for (let i = 0; i < this.children.length; i += 1) {
25591 const child = this.children[i];
25592 child.apply(node);
25593 }
25594 }
25595 reify() {
25596 this.nodes_with_css_class.forEach((node) => {
25597 node.add_css_class();
25598 });
25599 }
25600 render(file, should_transform_selectors) {
25601 if (!this.has_styles) {
25602 return { code: null, map: null };
25603 }
25604 const code = new MagicString(this.source);
25605 walk(this.ast.css, {
25606 enter: (node) => {
25607 code.addSourcemapLocation(node.start);
25608 code.addSourcemapLocation(node.end);
25609 }
25610 });
25611 if (should_transform_selectors) {
25612 const max = Math.max(...this.children.map(rule => rule.get_max_amount_class_specificity_increased()));
25613 this.children.forEach((child) => {
25614 child.transform(code, this.id, this.keyframes, max);
25615 });
25616 }
25617 let c = 0;
25618 this.children.forEach(child => {
25619 if (child.is_used(this.dev)) {
25620 code.remove(c, child.node.start);
25621 child.minify(code, this.dev);
25622 c = child.node.end;
25623 }
25624 });
25625 code.remove(c, this.source.length);
25626 return {
25627 code: code.toString(),
25628 map: code.generateMap({
25629 includeContent: true,
25630 source: this.filename,
25631 file
25632 })
25633 };
25634 }
25635 validate(component) {
25636 this.children.forEach(child => {
25637 child.validate(component);
25638 });
25639 }
25640 warn_on_unused_selectors(component) {
25641 this.children.forEach(child => {
25642 child.warn_on_unused_selector((selector) => {
25643 component.warn(selector.node, {
25644 code: 'css-unused-selector',
25645 message: `Unused CSS selector "${this.source.slice(selector.node.start, selector.node.end)}"`
25646 });
25647 });
25648 });
25649 }
25650 }
25651
25652 const test = typeof process !== 'undefined' && process.env.TEST;
25653
25654 class AbstractBlock extends Node$1 {
25655 constructor(component, parent, scope, info) {
25656 super(component, parent, scope, info);
25657 }
25658 warn_if_empty_block() {
25659 if (!this.children || this.children.length > 1)
25660 return;
25661 const child = this.children[0];
25662 if (!child || (child.type === 'Text' && !/[^ \r\n\f\v\t]/.test(child.data))) {
25663 this.component.warn(this, {
25664 code: 'empty-block',
25665 message: 'Empty block'
25666 });
25667 }
25668 }
25669 }
25670
25671 class PendingBlock extends AbstractBlock {
25672 constructor(component, parent, scope, info) {
25673 super(component, parent, scope, info);
25674 this.children = map_children(component, parent, scope, info.children);
25675 if (!info.skip) {
25676 this.warn_if_empty_block();
25677 }
25678 }
25679 }
25680
25681 class ThenBlock extends AbstractBlock {
25682 constructor(component, parent, scope, info) {
25683 super(component, parent, scope, info);
25684 this.scope = scope.child();
25685 if (parent.then_node) {
25686 parent.then_contexts.forEach(context => {
25687 this.scope.add(context.key.name, parent.expression.dependencies, this);
25688 });
25689 }
25690 this.children = map_children(component, parent, this.scope, info.children);
25691 if (!info.skip) {
25692 this.warn_if_empty_block();
25693 }
25694 }
25695 }
25696
25697 class CatchBlock extends AbstractBlock {
25698 constructor(component, parent, scope, info) {
25699 super(component, parent, scope, info);
25700 this.scope = scope.child();
25701 if (parent.catch_node) {
25702 parent.catch_contexts.forEach(context => {
25703 this.scope.add(context.key.name, parent.expression.dependencies, this);
25704 });
25705 }
25706 this.children = map_children(component, parent, this.scope, info.children);
25707 if (!info.skip) {
25708 this.warn_if_empty_block();
25709 }
25710 }
25711 }
25712
25713 function unpack_destructuring(contexts, node, modifier) {
25714 if (!node)
25715 return;
25716 if (node.type === 'Identifier') {
25717 contexts.push({
25718 key: node,
25719 modifier
25720 });
25721 }
25722 else if (node.type === 'RestElement') {
25723 contexts.push({
25724 key: node.argument,
25725 modifier
25726 });
25727 }
25728 else if (node.type === 'ArrayPattern') {
25729 node.elements.forEach((element, i) => {
25730 if (element && element.type === 'RestElement') {
25731 unpack_destructuring(contexts, element, node => x `${modifier(node)}.slice(${i})`);
25732 }
25733 else if (element && element.type === 'AssignmentPattern') {
25734 unpack_destructuring(contexts, element.left, node => x `${modifier(node)}[${i}] !== undefined ? ${modifier(node)}[${i}] : ${element.right}`);
25735 }
25736 else {
25737 unpack_destructuring(contexts, element, node => x `${modifier(node)}[${i}]`);
25738 }
25739 });
25740 }
25741 else if (node.type === 'ObjectPattern') {
25742 const used_properties = [];
25743 node.properties.forEach((property) => {
25744 if (property.type === 'RestElement') {
25745 unpack_destructuring(contexts, property.argument, node => x `@object_without_properties(${modifier(node)}, [${used_properties}])`);
25746 }
25747 else {
25748 const key = property.key;
25749 const value = property.value;
25750 used_properties.push(x `"${key.name}"`);
25751 if (value.type === 'AssignmentPattern') {
25752 unpack_destructuring(contexts, value.left, node => x `${modifier(node)}.${key.name} !== undefined ? ${modifier(node)}.${key.name} : ${value.right}`);
25753 }
25754 else {
25755 unpack_destructuring(contexts, value, node => x `${modifier(node)}.${key.name}`);
25756 }
25757 }
25758 });
25759 }
25760 }
25761
25762 class AwaitBlock$1 extends Node$1 {
25763 constructor(component, parent, scope, info) {
25764 super(component, parent, scope, info);
25765 this.expression = new Expression(component, this, scope, info.expression);
25766 this.then_node = info.value;
25767 this.catch_node = info.error;
25768 if (this.then_node) {
25769 this.then_contexts = [];
25770 unpack_destructuring(this.then_contexts, info.value, node => node);
25771 }
25772 if (this.catch_node) {
25773 this.catch_contexts = [];
25774 unpack_destructuring(this.catch_contexts, info.error, node => node);
25775 }
25776 this.pending = new PendingBlock(component, this, scope, info.pending);
25777 this.then = new ThenBlock(component, this, scope, info.then);
25778 this.catch = new CatchBlock(component, this, scope, info.catch);
25779 }
25780 }
25781
25782 class EventHandler extends Node$1 {
25783 constructor(component, parent, template_scope, info) {
25784 super(component, parent, template_scope, info);
25785 this.uses_context = false;
25786 this.can_make_passive = false;
25787 this.name = info.name;
25788 this.modifiers = new Set(info.modifiers);
25789 if (info.expression) {
25790 this.expression = new Expression(component, this, template_scope, info.expression);
25791 this.uses_context = this.expression.uses_context;
25792 if (/FunctionExpression/.test(info.expression.type) && info.expression.params.length === 0) {
25793 // TODO make this detection more accurate — if `event.preventDefault` isn't called, and
25794 // `event` is passed to another function, we can make it passive
25795 this.can_make_passive = true;
25796 }
25797 else if (info.expression.type === 'Identifier') {
25798 let node = component.node_for_declaration.get(info.expression.name);
25799 if (node) {
25800 if (node.type === 'VariableDeclaration') {
25801 // for `const handleClick = () => {...}`, we want the [arrow] function expression node
25802 const declarator = node.declarations.find(d => d.id.name === info.expression.name);
25803 node = declarator && declarator.init;
25804 }
25805 if (node && (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') && node.params.length === 0) {
25806 this.can_make_passive = true;
25807 }
25808 }
25809 }
25810 }
25811 else {
25812 this.handler_name = component.get_unique_name(`${sanitize(this.name)}_handler`);
25813 }
25814 }
25815 get reassigned() {
25816 if (!this.expression) {
25817 return false;
25818 }
25819 const node = this.expression.node;
25820 if (/FunctionExpression/.test(node.type)) {
25821 return false;
25822 }
25823 return this.expression.dynamic_dependencies().length > 0;
25824 }
25825 }
25826
25827 class Body extends Node$1 {
25828 constructor(component, parent, scope, info) {
25829 super(component, parent, scope, info);
25830 this.handlers = [];
25831 info.attributes.forEach((node) => {
25832 if (node.type === 'EventHandler') {
25833 this.handlers.push(new EventHandler(component, this, scope, node));
25834 }
25835 });
25836 }
25837 }
25838
25839 const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m;
25840 class Comment$2 extends Node$1 {
25841 constructor(component, parent, scope, info) {
25842 super(component, parent, scope, info);
25843 this.data = info.data;
25844 const match = pattern.exec(this.data);
25845 this.ignores = match ? match[1].split(/[^\S]/).map(x => x.trim()).filter(Boolean) : [];
25846 }
25847 }
25848
25849 class ElseBlock extends AbstractBlock {
25850 constructor(component, parent, scope, info) {
25851 super(component, parent, scope, info);
25852 this.children = map_children(component, this, scope, info.children);
25853 this.warn_if_empty_block();
25854 }
25855 }
25856
25857 class EachBlock$1 extends AbstractBlock {
25858 constructor(component, parent, scope, info) {
25859 super(component, parent, scope, info);
25860 this.has_binding = false;
25861 this.has_index_binding = false;
25862 this.expression = new Expression(component, this, scope, info.expression);
25863 this.context = info.context.name || 'each'; // TODO this is used to facilitate binding; currently fails with destructuring
25864 this.context_node = info.context;
25865 this.index = info.index;
25866 this.scope = scope.child();
25867 this.contexts = [];
25868 unpack_destructuring(this.contexts, info.context, node => node);
25869 this.contexts.forEach(context => {
25870 this.scope.add(context.key.name, this.expression.dependencies, this);
25871 });
25872 if (this.index) {
25873 // index can only change if this is a keyed each block
25874 const dependencies = info.key ? this.expression.dependencies : new Set([]);
25875 this.scope.add(this.index, dependencies, this);
25876 }
25877 this.key = info.key
25878 ? new Expression(component, this, this.scope, info.key)
25879 : null;
25880 this.has_animation = false;
25881 this.children = map_children(component, this, this.scope, info.children);
25882 if (this.has_animation) {
25883 if (this.children.length !== 1) {
25884 const child = this.children.find(child => !!child.animation);
25885 component.error(child.animation, {
25886 code: 'invalid-animation',
25887 message: 'An element that uses the animate directive must be the sole child of a keyed each block'
25888 });
25889 }
25890 }
25891 this.warn_if_empty_block();
25892 this.else = info.else
25893 ? new ElseBlock(component, this, this.scope, info.else)
25894 : null;
25895 }
25896 }
25897
25898 class Attribute extends Node$1 {
25899 constructor(component, parent, scope, info) {
25900 super(component, parent, scope, info);
25901 this.scope = scope;
25902 if (info.type === 'Spread') {
25903 this.name = null;
25904 this.is_spread = true;
25905 this.is_true = false;
25906 this.expression = new Expression(component, this, scope, info.expression);
25907 this.dependencies = this.expression.dependencies;
25908 this.chunks = null;
25909 this.is_static = false;
25910 }
25911 else {
25912 this.name = info.name;
25913 this.is_true = info.value === true;
25914 this.is_static = true;
25915 this.dependencies = new Set();
25916 this.chunks = this.is_true
25917 ? []
25918 : info.value.map(node => {
25919 if (node.type === 'Text')
25920 return node;
25921 this.is_static = false;
25922 const expression = new Expression(component, this, scope, node.expression);
25923 add_to_set(this.dependencies, expression.dependencies);
25924 return expression;
25925 });
25926 }
25927 }
25928 get_dependencies() {
25929 if (this.is_spread)
25930 return this.expression.dynamic_dependencies();
25931 const dependencies = new Set();
25932 this.chunks.forEach(chunk => {
25933 if (chunk.type === 'Expression') {
25934 add_to_set(dependencies, chunk.dynamic_dependencies());
25935 }
25936 });
25937 return Array.from(dependencies);
25938 }
25939 get_value(block) {
25940 if (this.is_true)
25941 return x `true`;
25942 if (this.chunks.length === 0)
25943 return x `""`;
25944 if (this.chunks.length === 1) {
25945 return this.chunks[0].type === 'Text'
25946 ? string_literal(this.chunks[0].data)
25947 : this.chunks[0].manipulate(block);
25948 }
25949 let expression = this.chunks
25950 .map(chunk => chunk.type === 'Text' ? string_literal(chunk.data) : chunk.manipulate(block))
25951 .reduce((lhs, rhs) => x `${lhs} + ${rhs}`);
25952 if (this.chunks[0].type !== 'Text') {
25953 expression = x `"" + ${expression}`;
25954 }
25955 return expression;
25956 }
25957 get_static_value() {
25958 if (this.is_spread || this.dependencies.size > 0)
25959 return null;
25960 return this.is_true
25961 ? true
25962 : this.chunks[0]
25963 // method should be called only when `is_static = true`
25964 ? this.chunks[0].data
25965 : '';
25966 }
25967 should_cache() {
25968 return this.is_static
25969 ? false
25970 : this.chunks.length === 1
25971 // @ts-ignore todo: probably error
25972 ? this.chunks[0].node.type !== 'Identifier' || this.scope.names.has(this.chunks[0].node.name)
25973 : true;
25974 }
25975 }
25976
25977 // TODO this should live in a specific binding
25978 const read_only_media_attributes = new Set([
25979 'duration',
25980 'buffered',
25981 'seekable',
25982 'played',
25983 'seeking',
25984 'ended',
25985 'videoHeight',
25986 'videoWidth'
25987 ]);
25988 class Binding extends Node$1 {
25989 constructor(component, parent, scope, info) {
25990 super(component, parent, scope, info);
25991 if (info.expression.type !== 'Identifier' && info.expression.type !== 'MemberExpression') {
25992 component.error(info, {
25993 code: 'invalid-directive-value',
25994 message: 'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
25995 });
25996 }
25997 this.name = info.name;
25998 this.expression = new Expression(component, this, scope, info.expression);
25999 this.raw_expression = JSON.parse(JSON.stringify(info.expression));
26000 const { name } = get_object(this.expression.node);
26001 this.is_contextual = Array.from(this.expression.references).some(name => scope.names.has(name));
26002 // make sure we track this as a mutable ref
26003 if (scope.is_let(name)) {
26004 component.error(this, {
26005 code: 'invalid-binding',
26006 message: 'Cannot bind to a variable declared with the let: directive'
26007 });
26008 }
26009 else if (scope.names.has(name)) {
26010 if (scope.is_await(name)) {
26011 component.error(this, {
26012 code: 'invalid-binding',
26013 message: 'Cannot bind to a variable declared with {#await ... then} or {:catch} blocks'
26014 });
26015 }
26016 scope.dependencies_for_name.get(name).forEach(name => {
26017 const variable = component.var_lookup.get(name);
26018 if (variable) {
26019 variable.mutated = true;
26020 }
26021 });
26022 }
26023 else {
26024 const variable = component.var_lookup.get(name);
26025 if (!variable || variable.global) {
26026 component.error(this.expression.node, {
26027 code: 'binding-undeclared',
26028 message: `${name} is not declared`
26029 });
26030 }
26031 variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
26032 if (info.expression.type === 'Identifier' && !variable.writable) {
26033 component.error(this.expression.node, {
26034 code: 'invalid-binding',
26035 message: 'Cannot bind to a variable which is not writable'
26036 });
26037 }
26038 }
26039 const type = parent.get_static_attribute_value('type');
26040 this.is_readonly =
26041 dimensions.test(this.name) ||
26042 (isElement(parent) &&
26043 ((parent.is_media_node() && read_only_media_attributes.has(this.name)) ||
26044 (parent.name === 'input' && type === 'file')) /* TODO others? */);
26045 }
26046 is_readonly_media_attribute() {
26047 return read_only_media_attributes.has(this.name);
26048 }
26049 }
26050 function isElement(node) {
26051 return !!node.is_media_node;
26052 }
26053
26054 class Transition extends Node$1 {
26055 constructor(component, parent, scope, info) {
26056 super(component, parent, scope, info);
26057 component.warn_if_undefined(info.name, info, scope);
26058 this.name = info.name;
26059 component.add_reference(info.name.split('.')[0]);
26060 this.directive = info.intro && info.outro ? 'transition' : info.intro ? 'in' : 'out';
26061 this.is_local = info.modifiers.includes('local');
26062 if ((info.intro && parent.intro) || (info.outro && parent.outro)) {
26063 const parent_transition = (parent.intro || parent.outro);
26064 const message = this.directive === parent_transition.directive
26065 ? `An element can only have one '${this.directive}' directive`
26066 : `An element cannot have both ${describe(parent_transition)} directive and ${describe(this)} directive`;
26067 component.error(info, {
26068 code: 'duplicate-transition',
26069 message
26070 });
26071 }
26072 this.expression = info.expression
26073 ? new Expression(component, this, scope, info.expression)
26074 : null;
26075 }
26076 }
26077 function describe(transition) {
26078 return transition.directive === 'transition'
26079 ? "a 'transition'"
26080 : `an '${transition.directive}'`;
26081 }
26082
26083 class Animation extends Node$1 {
26084 constructor(component, parent, scope, info) {
26085 super(component, parent, scope, info);
26086 component.warn_if_undefined(info.name, info, scope);
26087 this.name = info.name;
26088 component.add_reference(info.name.split('.')[0]);
26089 if (parent.animation) {
26090 component.error(this, {
26091 code: 'duplicate-animation',
26092 message: "An element can only have one 'animate' directive"
26093 });
26094 }
26095 const block = parent.parent;
26096 if (!block || block.type !== 'EachBlock' || !block.key) {
26097 // TODO can we relax the 'immediate child' rule?
26098 component.error(this, {
26099 code: 'invalid-animation',
26100 message: 'An element that uses the animate directive must be the immediate child of a keyed each block'
26101 });
26102 }
26103 block.has_animation = true;
26104 this.expression = info.expression
26105 ? new Expression(component, this, scope, info.expression, true)
26106 : null;
26107 }
26108 }
26109
26110 class Class extends Node$1 {
26111 constructor(component, parent, scope, info) {
26112 super(component, parent, scope, info);
26113 this.name = info.name;
26114 this.expression = info.expression
26115 ? new Expression(component, this, scope, info.expression)
26116 : null;
26117 }
26118 }
26119
26120 // Whitespace inside one of these elements will not result in
26121 // a whitespace node being created in any circumstances. (This
26122 // list is almost certainly very incomplete)
26123 const elements_without_text = new Set([
26124 'audio',
26125 'datalist',
26126 'dl',
26127 'optgroup',
26128 'select',
26129 'video'
26130 ]);
26131 class Text$1 extends Node$1 {
26132 constructor(component, parent, scope, info) {
26133 super(component, parent, scope, info);
26134 this.data = info.data;
26135 this.synthetic = info.synthetic || false;
26136 }
26137 should_skip() {
26138 if (/\S/.test(this.data))
26139 return false;
26140 const parent_element = this.find_nearest(/(?:Element|InlineComponent|Head)/);
26141 if (!parent_element)
26142 return false;
26143 if (parent_element.type === 'Head')
26144 return true;
26145 if (parent_element.type === 'InlineComponent')
26146 return parent_element.children.length === 1 && this === parent_element.children[0];
26147 // svg namespace exclusions
26148 if (/svg$/.test(parent_element.namespace)) {
26149 if (this.prev && this.prev.type === 'Element' && this.prev.name === 'tspan')
26150 return false;
26151 }
26152 return parent_element.namespace || elements_without_text.has(parent_element.name);
26153 }
26154 }
26155
26156 const applicable = new Set(['Identifier', 'ObjectExpression', 'ArrayExpression', 'Property']);
26157 class Let extends Node$1 {
26158 constructor(component, parent, scope, info) {
26159 super(component, parent, scope, info);
26160 this.names = [];
26161 this.name = { type: 'Identifier', name: info.name };
26162 const { names } = this;
26163 if (info.expression) {
26164 this.value = info.expression;
26165 walk(info.expression, {
26166 enter(node) {
26167 if (!applicable.has(node.type)) {
26168 component.error(node, {
26169 code: 'invalid-let',
26170 message: 'let directive value must be an identifier or an object/array pattern'
26171 });
26172 }
26173 if (node.type === 'Identifier') {
26174 names.push(node.name);
26175 }
26176 // slightly unfortunate hack
26177 if (node.type === 'ArrayExpression') {
26178 node.type = 'ArrayPattern';
26179 }
26180 if (node.type === 'ObjectExpression') {
26181 node.type = 'ObjectPattern';
26182 }
26183 }
26184 });
26185 }
26186 else {
26187 names.push(this.name.name);
26188 }
26189 }
26190 }
26191
26192 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)$/;
26193 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(' ');
26194 const aria_attribute_set = new Set(aria_attributes);
26195 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 graphics-document graphics-object graphics-symbol grid gridcell group heading img link list listbox listitem log main marquee math meter menu menubar menuitem menuitemcheckbox menuitemradio navigation none note option paragraph presentation progressbar radio radiogroup region row rowgroup rowheader scrollbar search searchbox separator slider spinbutton status strong subscript superscript switch tab table tablist tabpanel term textbox time timer toolbar tooltip tree treegrid treeitem'.split(' ');
26196 const aria_role_set = new Set(aria_roles);
26197 const a11y_required_attributes = {
26198 a: ['href'],
26199 area: ['alt', 'aria-label', 'aria-labelledby'],
26200 // html-has-lang
26201 html: ['lang'],
26202 // iframe-has-title
26203 iframe: ['title'],
26204 img: ['alt'],
26205 object: ['title', 'aria-label', 'aria-labelledby']
26206 };
26207 const a11y_distracting_elements = new Set([
26208 'blink',
26209 'marquee'
26210 ]);
26211 const a11y_required_content = new Set([
26212 // anchor-has-content
26213 'a',
26214 // heading-has-content
26215 'h1',
26216 'h2',
26217 'h3',
26218 'h4',
26219 'h5',
26220 'h6'
26221 ]);
26222 const a11y_no_onchange = new Set([
26223 'select',
26224 'option'
26225 ]);
26226 const a11y_labelable = new Set([
26227 'button',
26228 'input',
26229 'keygen',
26230 'meter',
26231 'output',
26232 'progress',
26233 'select',
26234 'textarea'
26235 ]);
26236 const invisible_elements = new Set(['meta', 'html', 'script', 'style']);
26237 const valid_modifiers = new Set([
26238 'preventDefault',
26239 'stopPropagation',
26240 'capture',
26241 'once',
26242 'passive',
26243 'nonpassive',
26244 'self'
26245 ]);
26246 const passive_events = new Set([
26247 'wheel',
26248 'touchstart',
26249 'touchmove',
26250 'touchend',
26251 'touchcancel'
26252 ]);
26253 const react_attributes = new Map([
26254 ['className', 'class'],
26255 ['htmlFor', 'for']
26256 ]);
26257 function get_namespace(parent, element, explicit_namespace) {
26258 const parent_element = parent.find_nearest(/^Element/);
26259 if (!parent_element) {
26260 return explicit_namespace || (svg$1.test(element.name)
26261 ? namespaces.svg
26262 : null);
26263 }
26264 if (svg$1.test(element.name.toLowerCase()))
26265 return namespaces.svg;
26266 if (parent_element.name.toLowerCase() === 'foreignobject')
26267 return null;
26268 return parent_element.namespace;
26269 }
26270 class Element$1 extends Node$1 {
26271 constructor(component, parent, scope, info) {
26272 super(component, parent, scope, info);
26273 this.attributes = [];
26274 this.actions = [];
26275 this.bindings = [];
26276 this.classes = [];
26277 this.handlers = [];
26278 this.lets = [];
26279 this.intro = null;
26280 this.outro = null;
26281 this.animation = null;
26282 this.name = info.name;
26283 this.namespace = get_namespace(parent, this, component.namespace);
26284 if (this.name === 'textarea') {
26285 if (info.children.length > 0) {
26286 const value_attribute = info.attributes.find(node => node.name === 'value');
26287 if (value_attribute) {
26288 component.error(value_attribute, {
26289 code: 'textarea-duplicate-value',
26290 message: 'A <textarea> can have either a value attribute or (equivalently) child content, but not both'
26291 });
26292 }
26293 // this is an egregious hack, but it's the easiest way to get <textarea>
26294 // children treated the same way as a value attribute
26295 info.attributes.push({
26296 type: 'Attribute',
26297 name: 'value',
26298 value: info.children
26299 });
26300 info.children = [];
26301 }
26302 }
26303 if (this.name === 'option') {
26304 // Special case — treat these the same way:
26305 // <option>{foo}</option>
26306 // <option value={foo}>{foo}</option>
26307 const value_attribute = info.attributes.find(attribute => attribute.name === 'value');
26308 if (!value_attribute) {
26309 info.attributes.push({
26310 type: 'Attribute',
26311 name: 'value',
26312 value: info.children,
26313 synthetic: true
26314 });
26315 }
26316 }
26317 const has_let = info.attributes.some(node => node.type === 'Let');
26318 if (has_let) {
26319 scope = scope.child();
26320 }
26321 // Binding relies on Attribute, defer its evaluation
26322 const order = ['Binding']; // everything else is -1
26323 info.attributes.sort((a, b) => order.indexOf(a.type) - order.indexOf(b.type));
26324 info.attributes.forEach(node => {
26325 switch (node.type) {
26326 case 'Action':
26327 this.actions.push(new Action(component, this, scope, node));
26328 break;
26329 case 'Attribute':
26330 case 'Spread':
26331 // special case
26332 if (node.name === 'xmlns')
26333 this.namespace = node.value[0].data;
26334 this.attributes.push(new Attribute(component, this, scope, node));
26335 break;
26336 case 'Binding':
26337 this.bindings.push(new Binding(component, this, scope, node));
26338 break;
26339 case 'Class':
26340 this.classes.push(new Class(component, this, scope, node));
26341 break;
26342 case 'EventHandler':
26343 this.handlers.push(new EventHandler(component, this, scope, node));
26344 break;
26345 case 'Let': {
26346 const l = new Let(component, this, scope, node);
26347 this.lets.push(l);
26348 const dependencies = new Set([l.name.name]);
26349 l.names.forEach(name => {
26350 scope.add(name, dependencies, this);
26351 });
26352 break;
26353 }
26354 case 'Transition':
26355 {
26356 const transition = new Transition(component, this, scope, node);
26357 if (node.intro)
26358 this.intro = transition;
26359 if (node.outro)
26360 this.outro = transition;
26361 break;
26362 }
26363 case 'Animation':
26364 this.animation = new Animation(component, this, scope, node);
26365 break;
26366 default:
26367 throw new Error(`Not implemented: ${node.type}`);
26368 }
26369 });
26370 this.scope = scope;
26371 this.children = map_children(component, this, this.scope, info.children);
26372 this.validate();
26373 component.apply_stylesheet(this);
26374 }
26375 validate() {
26376 if (this.component.var_lookup.has(this.name) && this.component.var_lookup.get(this.name).imported) {
26377 this.component.warn(this, {
26378 code: 'component-name-lowercase',
26379 message: `<${this.name}> will be treated as an HTML element unless it begins with a capital letter`
26380 });
26381 }
26382 if (a11y_distracting_elements.has(this.name)) {
26383 // no-distracting-elements
26384 this.component.warn(this, {
26385 code: 'a11y-distracting-elements',
26386 message: `A11y: Avoid <${this.name}> elements`
26387 });
26388 }
26389 if (this.name === 'figcaption') {
26390 let { parent } = this;
26391 let is_figure_parent = false;
26392 while (parent) {
26393 if (parent.name === 'figure') {
26394 is_figure_parent = true;
26395 break;
26396 }
26397 if (parent.type === 'Element') {
26398 break;
26399 }
26400 parent = parent.parent;
26401 }
26402 if (!is_figure_parent) {
26403 this.component.warn(this, {
26404 code: 'a11y-structure',
26405 message: 'A11y: <figcaption> must be an immediate child of <figure>'
26406 });
26407 }
26408 }
26409 if (this.name === 'figure') {
26410 const children = this.children.filter(node => {
26411 if (node.type === 'Comment')
26412 return false;
26413 if (node.type === 'Text')
26414 return /\S/.test(node.data);
26415 return true;
26416 });
26417 const index = children.findIndex(child => child.name === 'figcaption');
26418 if (index !== -1 && (index !== 0 && index !== children.length - 1)) {
26419 this.component.warn(children[index], {
26420 code: 'a11y-structure',
26421 message: 'A11y: <figcaption> must be first or last child of <figure>'
26422 });
26423 }
26424 }
26425 this.validate_attributes();
26426 this.validate_special_cases();
26427 this.validate_bindings();
26428 this.validate_content();
26429 this.validate_event_handlers();
26430 }
26431 validate_attributes() {
26432 const { component, parent } = this;
26433 const attribute_map = new Map();
26434 this.attributes.forEach(attribute => {
26435 if (attribute.is_spread)
26436 return;
26437 const name = attribute.name.toLowerCase();
26438 // aria-props
26439 if (name.startsWith('aria-')) {
26440 if (invisible_elements.has(this.name)) {
26441 // aria-unsupported-elements
26442 component.warn(attribute, {
26443 code: 'a11y-aria-attributes',
26444 message: `A11y: <${this.name}> should not have aria-* attributes`
26445 });
26446 }
26447 const type = name.slice(5);
26448 if (!aria_attribute_set.has(type)) {
26449 const match = fuzzymatch(type, aria_attributes);
26450 let message = `A11y: Unknown aria attribute 'aria-${type}'`;
26451 if (match)
26452 message += ` (did you mean '${match}'?)`;
26453 component.warn(attribute, {
26454 code: 'a11y-unknown-aria-attribute',
26455 message
26456 });
26457 }
26458 if (name === 'aria-hidden' && /^h[1-6]$/.test(this.name)) {
26459 component.warn(attribute, {
26460 code: 'a11y-hidden',
26461 message: `A11y: <${this.name}> element should not be hidden`
26462 });
26463 }
26464 }
26465 // aria-role
26466 if (name === 'role') {
26467 if (invisible_elements.has(this.name)) {
26468 // aria-unsupported-elements
26469 component.warn(attribute, {
26470 code: 'a11y-misplaced-role',
26471 message: `A11y: <${this.name}> should not have role attribute`
26472 });
26473 }
26474 const value = attribute.get_static_value();
26475 // @ts-ignore
26476 if (value && !aria_role_set.has(value)) {
26477 // @ts-ignore
26478 const match = fuzzymatch(value, aria_roles);
26479 let message = `A11y: Unknown role '${value}'`;
26480 if (match)
26481 message += ` (did you mean '${match}'?)`;
26482 component.warn(attribute, {
26483 code: 'a11y-unknown-role',
26484 message
26485 });
26486 }
26487 }
26488 // no-access-key
26489 if (name === 'accesskey') {
26490 component.warn(attribute, {
26491 code: 'a11y-accesskey',
26492 message: 'A11y: Avoid using accesskey'
26493 });
26494 }
26495 // no-autofocus
26496 if (name === 'autofocus') {
26497 component.warn(attribute, {
26498 code: 'a11y-autofocus',
26499 message: 'A11y: Avoid using autofocus'
26500 });
26501 }
26502 // scope
26503 if (name === 'scope' && this.name !== 'th') {
26504 component.warn(attribute, {
26505 code: 'a11y-misplaced-scope',
26506 message: 'A11y: The scope attribute should only be used with <th> elements'
26507 });
26508 }
26509 // tabindex-no-positive
26510 if (name === 'tabindex') {
26511 const value = attribute.get_static_value();
26512 // @ts-ignore todo is tabindex=true correct case?
26513 if (!isNaN(value) && +value > 0) {
26514 component.warn(attribute, {
26515 code: 'a11y-positive-tabindex',
26516 message: 'A11y: avoid tabindex values above zero'
26517 });
26518 }
26519 }
26520 if (/(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/.test(name)) {
26521 component.error(attribute, {
26522 code: 'illegal-attribute',
26523 message: `'${name}' is not a valid attribute name`
26524 });
26525 }
26526 if (name === 'slot') {
26527 if (!attribute.is_static) {
26528 component.error(attribute, {
26529 code: 'invalid-slot-attribute',
26530 message: 'slot attribute cannot have a dynamic value'
26531 });
26532 }
26533 if (component.slot_outlets.has(name)) {
26534 component.error(attribute, {
26535 code: 'duplicate-slot-attribute',
26536 message: `Duplicate '${name}' slot`
26537 });
26538 component.slot_outlets.add(name);
26539 }
26540 if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
26541 component.error(attribute, {
26542 code: 'invalid-slotted-content',
26543 message: 'Element with a slot=\'...\' attribute must be a child of a component or a descendant of a custom element'
26544 });
26545 }
26546 }
26547 if (name === 'is') {
26548 component.warn(attribute, {
26549 code: 'avoid-is',
26550 message: 'The \'is\' attribute is not supported cross-browser and should be avoided'
26551 });
26552 }
26553 if (react_attributes.has(attribute.name)) {
26554 component.warn(attribute, {
26555 code: 'invalid-html-attribute',
26556 message: `'${attribute.name}' is not a valid HTML attribute. Did you mean '${react_attributes.get(attribute.name)}'?`
26557 });
26558 }
26559 attribute_map.set(attribute.name, attribute);
26560 });
26561 }
26562 validate_special_cases() {
26563 const { component, attributes, handlers } = this;
26564 const attribute_map = new Map();
26565 const handlers_map = new Map();
26566 attributes.forEach(attribute => (attribute_map.set(attribute.name, attribute)));
26567 handlers.forEach(handler => (handlers_map.set(handler.name, handler)));
26568 if (this.name === 'a') {
26569 const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
26570 const id_attribute = attribute_map.get('id');
26571 const name_attribute = attribute_map.get('name');
26572 if (href_attribute) {
26573 const href_value = href_attribute.get_static_value();
26574 if (href_value === '' || href_value === '#' || /^\W*javascript:/i.test(href_value)) {
26575 component.warn(href_attribute, {
26576 code: 'a11y-invalid-attribute',
26577 message: `A11y: '${href_value}' is not a valid ${href_attribute.name} attribute`
26578 });
26579 }
26580 }
26581 else {
26582 const id_attribute_valid = id_attribute && id_attribute.get_static_value() !== '';
26583 const name_attribute_valid = name_attribute && name_attribute.get_static_value() !== '';
26584 if (!id_attribute_valid && !name_attribute_valid) {
26585 component.warn(this, {
26586 code: 'a11y-missing-attribute',
26587 message: 'A11y: <a> element should have an href attribute'
26588 });
26589 }
26590 }
26591 }
26592 else {
26593 const required_attributes = a11y_required_attributes[this.name];
26594 if (required_attributes) {
26595 const has_attribute = required_attributes.some(name => attribute_map.has(name));
26596 if (!has_attribute) {
26597 should_have_attribute(this, required_attributes);
26598 }
26599 }
26600 }
26601 if (this.name === 'input') {
26602 const type = attribute_map.get('type');
26603 if (type && type.get_static_value() === 'image') {
26604 const required_attributes = ['alt', 'aria-label', 'aria-labelledby'];
26605 const has_attribute = required_attributes.some(name => attribute_map.has(name));
26606 if (!has_attribute) {
26607 should_have_attribute(this, required_attributes, 'input type="image"');
26608 }
26609 }
26610 }
26611 if (this.name === 'img') {
26612 const alt_attribute = attribute_map.get('alt');
26613 const aria_hidden_attribute = attribute_map.get('aria-hidden');
26614 const aria_hidden_exist = aria_hidden_attribute && aria_hidden_attribute.get_static_value();
26615 if (alt_attribute && !aria_hidden_exist) {
26616 const alt_value = alt_attribute.get_static_value();
26617 if (/\b(image|picture|photo)\b/i.test(alt_value)) {
26618 component.warn(this, {
26619 code: 'a11y-img-redundant-alt',
26620 message: 'A11y: Screenreaders already announce <img> elements as an image.'
26621 });
26622 }
26623 }
26624 }
26625 if (this.name === 'label') {
26626 const has_input_child = this.children.some(i => (i instanceof Element$1 && a11y_labelable.has(i.name)));
26627 if (!attribute_map.has('for') && !has_input_child) {
26628 component.warn(this, {
26629 code: 'a11y-label-has-associated-control',
26630 message: 'A11y: A form label must be associated with a control.'
26631 });
26632 }
26633 }
26634 if (this.is_media_node()) {
26635 if (attribute_map.has('muted')) {
26636 return;
26637 }
26638 let has_caption;
26639 const track = this.children.find((i) => i.name === 'track');
26640 if (track) {
26641 has_caption = track.attributes.find(a => a.name === 'kind' && a.get_static_value() === 'captions');
26642 }
26643 if (!has_caption) {
26644 component.warn(this, {
26645 code: 'a11y-media-has-caption',
26646 message: 'A11y: Media elements must have a <track kind="captions">'
26647 });
26648 }
26649 }
26650 if (a11y_no_onchange.has(this.name)) {
26651 if (handlers_map.has('change') && !handlers_map.has('blur')) {
26652 component.warn(this, {
26653 code: 'a11y-no-onchange',
26654 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.'
26655 });
26656 }
26657 }
26658 }
26659 validate_bindings() {
26660 const { component } = this;
26661 const check_type_attribute = () => {
26662 const attribute = this.attributes.find((attribute) => attribute.name === 'type');
26663 if (!attribute)
26664 return null;
26665 if (!attribute.is_static) {
26666 component.error(attribute, {
26667 code: 'invalid-type',
26668 message: '\'type\' attribute cannot be dynamic if input uses two-way binding'
26669 });
26670 }
26671 const value = attribute.get_static_value();
26672 if (value === true) {
26673 component.error(attribute, {
26674 code: 'missing-type',
26675 message: '\'type\' attribute must be specified'
26676 });
26677 }
26678 return value;
26679 };
26680 this.bindings.forEach(binding => {
26681 const { name } = binding;
26682 if (name === 'value') {
26683 if (this.name !== 'input' &&
26684 this.name !== 'textarea' &&
26685 this.name !== 'select') {
26686 component.error(binding, {
26687 code: 'invalid-binding',
26688 message: `'value' is not a valid binding on <${this.name}> elements`
26689 });
26690 }
26691 if (this.name === 'select') {
26692 const attribute = this.attributes.find((attribute) => attribute.name === 'multiple');
26693 if (attribute && !attribute.is_static) {
26694 component.error(attribute, {
26695 code: 'dynamic-multiple-attribute',
26696 message: '\'multiple\' attribute cannot be dynamic if select uses two-way binding'
26697 });
26698 }
26699 }
26700 else {
26701 check_type_attribute();
26702 }
26703 }
26704 else if (name === 'checked' || name === 'indeterminate') {
26705 if (this.name !== 'input') {
26706 component.error(binding, {
26707 code: 'invalid-binding',
26708 message: `'${name}' is not a valid binding on <${this.name}> elements`
26709 });
26710 }
26711 const type = check_type_attribute();
26712 if (type !== 'checkbox') {
26713 let message = `'${name}' binding can only be used with <input type="checkbox">`;
26714 if (type === 'radio')
26715 message += ' — for <input type="radio">, use \'group\' binding';
26716 component.error(binding, { code: 'invalid-binding', message });
26717 }
26718 }
26719 else if (name === 'group') {
26720 if (this.name !== 'input') {
26721 component.error(binding, {
26722 code: 'invalid-binding',
26723 message: `'group' is not a valid binding on <${this.name}> elements`
26724 });
26725 }
26726 const type = check_type_attribute();
26727 if (type !== 'checkbox' && type !== 'radio') {
26728 component.error(binding, {
26729 code: 'invalid-binding',
26730 message: '\'group\' binding can only be used with <input type="checkbox"> or <input type="radio">'
26731 });
26732 }
26733 }
26734 else if (name === 'files') {
26735 if (this.name !== 'input') {
26736 component.error(binding, {
26737 code: 'invalid-binding',
26738 message: `'files' is not a valid binding on <${this.name}> elements`
26739 });
26740 }
26741 const type = check_type_attribute();
26742 if (type !== 'file') {
26743 component.error(binding, {
26744 code: 'invalid-binding',
26745 message: '\'files\' binding can only be used with <input type="file">'
26746 });
26747 }
26748 }
26749 else if (name === 'open') {
26750 if (this.name !== 'details') {
26751 component.error(binding, {
26752 code: 'invalid-binding',
26753 message: `'${name}' binding can only be used with <details>`
26754 });
26755 }
26756 }
26757 else if (name === 'currentTime' ||
26758 name === 'duration' ||
26759 name === 'paused' ||
26760 name === 'buffered' ||
26761 name === 'seekable' ||
26762 name === 'played' ||
26763 name === 'volume' ||
26764 name === 'muted' ||
26765 name === 'playbackRate' ||
26766 name === 'seeking' ||
26767 name === 'ended') {
26768 if (this.name !== 'audio' && this.name !== 'video') {
26769 component.error(binding, {
26770 code: 'invalid-binding',
26771 message: `'${name}' binding can only be used with <audio> or <video>`
26772 });
26773 }
26774 }
26775 else if (name === 'videoHeight' ||
26776 name === 'videoWidth') {
26777 if (this.name !== 'video') {
26778 component.error(binding, {
26779 code: 'invalid-binding',
26780 message: `'${name}' binding can only be used with <video>`
26781 });
26782 }
26783 }
26784 else if (dimensions.test(name)) {
26785 if (this.name === 'svg' && (name === 'offsetWidth' || name === 'offsetHeight')) {
26786 component.error(binding, {
26787 code: 'invalid-binding',
26788 message: `'${binding.name}' is not a valid binding on <svg>. Use '${name.replace('offset', 'client')}' instead`
26789 });
26790 }
26791 else if (svg$1.test(this.name)) {
26792 component.error(binding, {
26793 code: 'invalid-binding',
26794 message: `'${binding.name}' is not a valid binding on SVG elements`
26795 });
26796 }
26797 else if (is_void(this.name)) {
26798 component.error(binding, {
26799 code: 'invalid-binding',
26800 message: `'${binding.name}' is not a valid binding on void elements like <${this.name}>. Use a wrapper element instead`
26801 });
26802 }
26803 }
26804 else if (name === 'textContent' ||
26805 name === 'innerHTML') {
26806 const contenteditable = this.attributes.find((attribute) => attribute.name === 'contenteditable');
26807 if (!contenteditable) {
26808 component.error(binding, {
26809 code: 'missing-contenteditable-attribute',
26810 message: '\'contenteditable\' attribute is required for textContent and innerHTML two-way bindings'
26811 });
26812 }
26813 else if (contenteditable && !contenteditable.is_static) {
26814 component.error(contenteditable, {
26815 code: 'dynamic-contenteditable-attribute',
26816 message: '\'contenteditable\' attribute cannot be dynamic if element uses two-way binding'
26817 });
26818 }
26819 }
26820 else if (name !== 'this') {
26821 component.error(binding, {
26822 code: 'invalid-binding',
26823 message: `'${binding.name}' is not a valid binding`
26824 });
26825 }
26826 });
26827 }
26828 validate_content() {
26829 if (!a11y_required_content.has(this.name))
26830 return;
26831 if (this.bindings
26832 .some((binding) => ['textContent', 'innerHTML'].includes(binding.name)))
26833 return;
26834 if (this.children.length === 0) {
26835 this.component.warn(this, {
26836 code: 'a11y-missing-content',
26837 message: `A11y: <${this.name}> element should have child content`
26838 });
26839 }
26840 }
26841 validate_event_handlers() {
26842 const { component } = this;
26843 this.handlers.forEach(handler => {
26844 if (handler.modifiers.has('passive') && handler.modifiers.has('preventDefault')) {
26845 component.error(handler, {
26846 code: 'invalid-event-modifier',
26847 message: 'The \'passive\' and \'preventDefault\' modifiers cannot be used together'
26848 });
26849 }
26850 if (handler.modifiers.has('passive') && handler.modifiers.has('nonpassive')) {
26851 component.error(handler, {
26852 code: 'invalid-event-modifier',
26853 message: 'The \'passive\' and \'nonpassive\' modifiers cannot be used together'
26854 });
26855 }
26856 handler.modifiers.forEach(modifier => {
26857 if (!valid_modifiers.has(modifier)) {
26858 component.error(handler, {
26859 code: 'invalid-event-modifier',
26860 message: `Valid event modifiers are ${list$1(Array.from(valid_modifiers))}`
26861 });
26862 }
26863 if (modifier === 'passive') {
26864 if (passive_events.has(handler.name)) {
26865 if (handler.can_make_passive) {
26866 component.warn(handler, {
26867 code: 'redundant-event-modifier',
26868 message: 'Touch event handlers that don\'t use the \'event\' object are passive by default'
26869 });
26870 }
26871 }
26872 else {
26873 component.warn(handler, {
26874 code: 'redundant-event-modifier',
26875 message: 'The passive modifier only works with wheel and touch events'
26876 });
26877 }
26878 }
26879 if (component.compile_options.legacy && (modifier === 'once' || modifier === 'passive')) {
26880 // TODO this could be supported, but it would need a few changes to
26881 // how event listeners work
26882 component.error(handler, {
26883 code: 'invalid-event-modifier',
26884 message: `The '${modifier}' modifier cannot be used in legacy mode`
26885 });
26886 }
26887 });
26888 if (passive_events.has(handler.name) && handler.can_make_passive && !handler.modifiers.has('preventDefault') && !handler.modifiers.has('nonpassive')) {
26889 // touch/wheel events should be passive by default
26890 handler.modifiers.add('passive');
26891 }
26892 });
26893 }
26894 is_media_node() {
26895 return this.name === 'audio' || this.name === 'video';
26896 }
26897 add_css_class() {
26898 if (this.attributes.some(attr => attr.is_spread)) {
26899 this.needs_manual_style_scoping = true;
26900 return;
26901 }
26902 const { id } = this.component.stylesheet;
26903 const class_attribute = this.attributes.find(a => a.name === 'class');
26904 if (class_attribute && !class_attribute.is_true) {
26905 if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') {
26906 class_attribute.chunks[0].data += ` ${id}`;
26907 }
26908 else {
26909 class_attribute.chunks.push(new Text$1(this.component, this, this.scope, {
26910 type: 'Text',
26911 data: ` ${id}`,
26912 synthetic: true
26913 }));
26914 }
26915 }
26916 else {
26917 this.attributes.push(new Attribute(this.component, this, this.scope, {
26918 type: 'Attribute',
26919 name: 'class',
26920 value: [{ type: 'Text', data: id, synthetic: true }]
26921 }));
26922 }
26923 }
26924 }
26925 function should_have_attribute(node, attributes, name = node.name) {
26926 const article = /^[aeiou]/.test(attributes[0]) ? 'an' : 'a';
26927 const sequence = attributes.length > 1 ?
26928 attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}` :
26929 attributes[0];
26930 node.component.warn(node, {
26931 code: 'a11y-missing-attribute',
26932 message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
26933 });
26934 }
26935 function within_custom_element(parent) {
26936 while (parent) {
26937 if (parent.type === 'InlineComponent')
26938 return false;
26939 if (parent.type === 'Element' && /-/.test(parent.name))
26940 return true;
26941 parent = parent.parent;
26942 }
26943 return false;
26944 }
26945
26946 class Head$1 extends Node$1 {
26947 constructor(component, parent, scope, info) {
26948 super(component, parent, scope, info);
26949 if (info.attributes.length) {
26950 component.error(info.attributes[0], {
26951 code: 'invalid-attribute',
26952 message: '<svelte:head> should not have any attributes or directives'
26953 });
26954 }
26955 this.children = map_children(component, parent, scope, info.children.filter(child => {
26956 return (child.type !== 'Text' || /\S/.test(child.data));
26957 }));
26958 if (this.children.length > 0) {
26959 this.id = `svelte-${hash(this.component.source.slice(this.start, this.end))}`;
26960 }
26961 }
26962 }
26963
26964 class IfBlock$1 extends AbstractBlock {
26965 constructor(component, parent, scope, info) {
26966 super(component, parent, scope, info);
26967 this.expression = new Expression(component, this, scope, info.expression);
26968 this.children = map_children(component, this, scope, info.children);
26969 this.else = info.else
26970 ? new ElseBlock(component, this, scope, info.else)
26971 : null;
26972 this.warn_if_empty_block();
26973 }
26974 }
26975
26976 class InlineComponent$1 extends Node$1 {
26977 constructor(component, parent, scope, info) {
26978 super(component, parent, scope, info);
26979 this.attributes = [];
26980 this.bindings = [];
26981 this.handlers = [];
26982 this.lets = [];
26983 if (info.name !== 'svelte:component' && info.name !== 'svelte:self') {
26984 const name = info.name.split('.')[0]; // accommodate namespaces
26985 component.warn_if_undefined(name, info, scope);
26986 component.add_reference(name);
26987 }
26988 this.name = info.name;
26989 this.expression = this.name === 'svelte:component'
26990 ? new Expression(component, this, scope, info.expression)
26991 : null;
26992 info.attributes.forEach(node => {
26993 /* eslint-disable no-fallthrough */
26994 switch (node.type) {
26995 case 'Action':
26996 component.error(node, {
26997 code: 'invalid-action',
26998 message: 'Actions can only be applied to DOM elements, not components'
26999 });
27000 case 'Attribute':
27001 if (node.name === 'slot') {
27002 component.error(node, {
27003 code: 'invalid-prop',
27004 message: "'slot' is reserved for future use in named slots"
27005 });
27006 }
27007 // fallthrough
27008 case 'Spread':
27009 this.attributes.push(new Attribute(component, this, scope, node));
27010 break;
27011 case 'Binding':
27012 this.bindings.push(new Binding(component, this, scope, node));
27013 break;
27014 case 'Class':
27015 component.error(node, {
27016 code: 'invalid-class',
27017 message: 'Classes can only be applied to DOM elements, not components'
27018 });
27019 case 'EventHandler':
27020 this.handlers.push(new EventHandler(component, this, scope, node));
27021 break;
27022 case 'Let':
27023 this.lets.push(new Let(component, this, scope, node));
27024 break;
27025 case 'Transition':
27026 component.error(node, {
27027 code: 'invalid-transition',
27028 message: 'Transitions can only be applied to DOM elements, not components'
27029 });
27030 default:
27031 throw new Error(`Not implemented: ${node.type}`);
27032 }
27033 /* eslint-enable no-fallthrough */
27034 });
27035 if (this.lets.length > 0) {
27036 this.scope = scope.child();
27037 this.lets.forEach(l => {
27038 const dependencies = new Set([l.name.name]);
27039 l.names.forEach(name => {
27040 this.scope.add(name, dependencies, this);
27041 });
27042 });
27043 }
27044 else {
27045 this.scope = scope;
27046 }
27047 this.handlers.forEach(handler => {
27048 handler.modifiers.forEach(modifier => {
27049 if (modifier !== 'once') {
27050 component.error(handler, {
27051 code: 'invalid-event-modifier',
27052 message: "Event modifiers other than 'once' can only be used on DOM elements"
27053 });
27054 }
27055 });
27056 });
27057 this.children = map_children(component, this, this.scope, info.children);
27058 }
27059 }
27060
27061 class KeyBlock$1 extends AbstractBlock {
27062 constructor(component, parent, scope, info) {
27063 super(component, parent, scope, info);
27064 this.expression = new Expression(component, this, scope, info.expression);
27065 this.children = map_children(component, this, scope, info.children);
27066 this.warn_if_empty_block();
27067 }
27068 }
27069
27070 class Tag$2 extends Node$1 {
27071 constructor(component, parent, scope, info) {
27072 super(component, parent, scope, info);
27073 this.expression = new Expression(component, this, scope, info.expression);
27074 this.should_cache = (info.expression.type !== 'Identifier' ||
27075 (this.expression.dependencies.size && scope.names.has(info.expression.name)));
27076 }
27077 }
27078
27079 class MustacheTag extends Tag$2 {
27080 }
27081
27082 class Options extends Node$1 {
27083 }
27084
27085 class RawMustacheTag extends Tag$2 {
27086 }
27087
27088 class DebugTag$1 extends Node$1 {
27089 constructor(component, parent, scope, info) {
27090 super(component, parent, scope, info);
27091 this.expressions = info.identifiers.map((node) => {
27092 return new Expression(component, parent, scope, node);
27093 });
27094 }
27095 }
27096
27097 class Slot$1 extends Element$1 {
27098 constructor(component, parent, scope, info) {
27099 super(component, parent, scope, info);
27100 this.values = new Map();
27101 info.attributes.forEach(attr => {
27102 if (attr.type !== 'Attribute' && attr.type !== 'Spread') {
27103 component.error(attr, {
27104 code: 'invalid-slot-directive',
27105 message: '<slot> cannot have directives'
27106 });
27107 }
27108 if (attr.name === 'name') {
27109 if (attr.value.length !== 1 || attr.value[0].type !== 'Text') {
27110 component.error(attr, {
27111 code: 'dynamic-slot-name',
27112 message: '<slot> name cannot be dynamic'
27113 });
27114 }
27115 this.slot_name = attr.value[0].data;
27116 if (this.slot_name === 'default') {
27117 component.error(attr, {
27118 code: 'invalid-slot-name',
27119 message: 'default is a reserved word — it cannot be used as a slot name'
27120 });
27121 }
27122 }
27123 this.values.set(attr.name, new Attribute(component, this, scope, attr));
27124 });
27125 if (!this.slot_name)
27126 this.slot_name = 'default';
27127 if (this.slot_name === 'default') {
27128 // if this is the default slot, add our dependencies to any
27129 // other slots (which inherit our slot values) that were
27130 // previously encountered
27131 component.slots.forEach((slot) => {
27132 this.values.forEach((attribute, name) => {
27133 if (!slot.values.has(name)) {
27134 slot.values.set(name, attribute);
27135 }
27136 });
27137 });
27138 }
27139 else if (component.slots.has('default')) {
27140 // otherwise, go the other way — inherit values from
27141 // a previously encountered default slot
27142 const default_slot = component.slots.get('default');
27143 default_slot.values.forEach((attribute, name) => {
27144 if (!this.values.has(name)) {
27145 this.values.set(name, attribute);
27146 }
27147 });
27148 }
27149 component.slots.set(this.slot_name, this);
27150 }
27151 }
27152
27153 class Title$1 extends Node$1 {
27154 constructor(component, parent, scope, info) {
27155 super(component, parent, scope, info);
27156 this.children = map_children(component, parent, scope, info.children);
27157 if (info.attributes.length > 0) {
27158 component.error(info.attributes[0], {
27159 code: 'illegal-attribute',
27160 message: '<title> cannot have attributes'
27161 });
27162 }
27163 info.children.forEach(child => {
27164 if (child.type !== 'Text' && child.type !== 'MustacheTag') {
27165 component.error(child, {
27166 code: 'illegal-structure',
27167 message: '<title> can only contain text and {tags}'
27168 });
27169 }
27170 });
27171 this.should_cache = info.children.length === 1
27172 ? (info.children[0].type !== 'Identifier' ||
27173 scope.names.has(info.children[0].name))
27174 : true;
27175 }
27176 }
27177
27178 const valid_bindings = [
27179 'innerWidth',
27180 'innerHeight',
27181 'outerWidth',
27182 'outerHeight',
27183 'scrollX',
27184 'scrollY',
27185 'online'
27186 ];
27187 class Window extends Node$1 {
27188 constructor(component, parent, scope, info) {
27189 super(component, parent, scope, info);
27190 this.handlers = [];
27191 this.bindings = [];
27192 this.actions = [];
27193 info.attributes.forEach(node => {
27194 if (node.type === 'EventHandler') {
27195 this.handlers.push(new EventHandler(component, this, scope, node));
27196 }
27197 else if (node.type === 'Binding') {
27198 if (node.expression.type !== 'Identifier') {
27199 const { parts } = flatten_reference(node.expression);
27200 // TODO is this constraint necessary?
27201 component.error(node.expression, {
27202 code: 'invalid-binding',
27203 message: `Bindings on <svelte:window> must be to top-level properties, e.g. '${parts[parts.length - 1]}' rather than '${parts.join('.')}'`
27204 });
27205 }
27206 if (!~valid_bindings.indexOf(node.name)) {
27207 const match = (node.name === 'width' ? 'innerWidth' :
27208 node.name === 'height' ? 'innerHeight' :
27209 fuzzymatch(node.name, valid_bindings));
27210 const message = `'${node.name}' is not a valid binding on <svelte:window>`;
27211 if (match) {
27212 component.error(node, {
27213 code: 'invalid-binding',
27214 message: `${message} (did you mean '${match}'?)`
27215 });
27216 }
27217 else {
27218 component.error(node, {
27219 code: 'invalid-binding',
27220 message: `${message} — valid bindings are ${list$1(valid_bindings)}`
27221 });
27222 }
27223 }
27224 this.bindings.push(new Binding(component, this, scope, node));
27225 }
27226 else if (node.type === 'Action') {
27227 this.actions.push(new Action(component, this, scope, node));
27228 }
27229 });
27230 }
27231 }
27232
27233 function get_constructor(type) {
27234 switch (type) {
27235 case 'AwaitBlock': return AwaitBlock$1;
27236 case 'Body': return Body;
27237 case 'Comment': return Comment$2;
27238 case 'EachBlock': return EachBlock$1;
27239 case 'Element': return Element$1;
27240 case 'Head': return Head$1;
27241 case 'IfBlock': return IfBlock$1;
27242 case 'InlineComponent': return InlineComponent$1;
27243 case 'KeyBlock': return KeyBlock$1;
27244 case 'MustacheTag': return MustacheTag;
27245 case 'Options': return Options;
27246 case 'RawMustacheTag': return RawMustacheTag;
27247 case 'DebugTag': return DebugTag$1;
27248 case 'Slot': return Slot$1;
27249 case 'Text': return Text$1;
27250 case 'Title': return Title$1;
27251 case 'Window': return Window;
27252 default: throw new Error(`Not implemented: ${type}`);
27253 }
27254 }
27255 function map_children(component, parent, scope, children) {
27256 let last = null;
27257 let ignores = [];
27258 return children.map(child => {
27259 const constructor = get_constructor(child.type);
27260 const use_ignores = child.type !== 'Text' && child.type !== 'Comment' && ignores.length;
27261 if (use_ignores)
27262 component.push_ignores(ignores);
27263 const node = new constructor(component, parent, scope, child);
27264 if (use_ignores)
27265 component.pop_ignores(), ignores = [];
27266 if (node.type === 'Comment' && node.ignores.length) {
27267 ignores.push(...node.ignores);
27268 }
27269 if (last)
27270 last.next = node;
27271 node.prev = last;
27272 last = node;
27273 return node;
27274 });
27275 }
27276
27277 class TemplateScope {
27278 constructor(parent) {
27279 this.owners = new Map();
27280 this.parent = parent;
27281 this.names = new Set(parent ? parent.names : []);
27282 this.dependencies_for_name = new Map(parent ? parent.dependencies_for_name : []);
27283 }
27284 add(name, dependencies, owner) {
27285 this.names.add(name);
27286 this.dependencies_for_name.set(name, dependencies);
27287 this.owners.set(name, owner);
27288 return this;
27289 }
27290 child() {
27291 const child = new TemplateScope(this);
27292 return child;
27293 }
27294 is_top_level(name) {
27295 return !this.parent || !this.names.has(name) && this.parent.is_top_level(name);
27296 }
27297 get_owner(name) {
27298 return this.owners.get(name) || (this.parent && this.parent.get_owner(name));
27299 }
27300 is_let(name) {
27301 const owner = this.get_owner(name);
27302 return owner && (owner.type === 'Element' || owner.type === 'InlineComponent');
27303 }
27304 is_await(name) {
27305 const owner = this.get_owner(name);
27306 return owner && (owner.type === 'ThenBlock' || owner.type === 'CatchBlock');
27307 }
27308 }
27309
27310 class Fragment extends Node$1 {
27311 constructor(component, info) {
27312 const scope = new TemplateScope();
27313 super(component, null, scope, info);
27314 this.scope = scope;
27315 this.children = map_children(component, this, scope, info.children);
27316 }
27317 }
27318
27319 // This file is automatically generated
27320 var internal_exports = new Set(["HtmlTag", "SvelteComponent", "SvelteComponentDev", "SvelteComponentTyped", "SvelteElement", "action_destroyer", "add_attribute", "add_classes", "add_flush_callback", "add_location", "add_render_callback", "add_resize_listener", "add_transform", "afterUpdate", "append", "append_dev", "assign", "attr", "attr_dev", "attribute_to_object", "beforeUpdate", "bind", "binding_callbacks", "blank_object", "bubble", "check_outros", "children", "claim_component", "claim_element", "claim_space", "claim_text", "clear_loops", "component_subscribe", "compute_rest_props", "compute_slots", "createEventDispatcher", "create_animation", "create_bidirectional_transition", "create_component", "create_in_transition", "create_out_transition", "create_slot", "create_ssr_component", "current_component", "custom_event", "dataset_dev", "debug", "destroy_block", "destroy_component", "destroy_each", "detach", "detach_after_dev", "detach_before_dev", "detach_between_dev", "detach_dev", "dirty_components", "dispatch_dev", "each", "element", "element_is", "empty", "escape", "escaped", "exclude_internal_props", "fix_and_destroy_block", "fix_and_outro_and_destroy_block", "fix_position", "flush", "getContext", "get_binding_group_value", "get_current_component", "get_custom_elements_slots", "get_slot_changes", "get_slot_context", "get_spread_object", "get_spread_update", "get_store_value", "globals", "group_outros", "handle_promise", "hasContext", "has_prop", "identity", "init", "insert", "insert_dev", "intros", "invalid_attribute_name_character", "is_client", "is_crossorigin", "is_empty", "is_function", "is_promise", "listen", "listen_dev", "loop", "loop_guard", "missing_component", "mount_component", "noop", "not_equal", "now", "null_to_empty", "object_without_properties", "onDestroy", "onMount", "once", "outro_and_destroy_block", "prevent_default", "prop_dev", "query_selector_all", "raf", "run", "run_all", "safe_not_equal", "schedule_update", "select_multiple_value", "select_option", "select_options", "select_value", "self", "setContext", "set_attributes", "set_current_component", "set_custom_element_data", "set_data", "set_data_dev", "set_input_type", "set_input_value", "set_now", "set_raf", "set_store_value", "set_style", "set_svg_attributes", "space", "spread", "stop_propagation", "subscribe", "svg_element", "text", "tick", "time_ranges_to_array", "to_number", "toggle_class", "transition_in", "transition_out", "update_keyed_each", "update_slot", "update_slot_spread", "validate_component", "validate_each_argument", "validate_each_keys", "validate_slots", "validate_store", "xlink_attr"]);
27321
27322 function is_used_as_reference(node, parent) {
27323 if (!isReference(node, parent)) {
27324 return false;
27325 }
27326 if (!parent) {
27327 return true;
27328 }
27329 /* eslint-disable no-fallthrough */
27330 switch (parent.type) {
27331 // disregard the `foo` in `const foo = bar`
27332 case 'VariableDeclarator':
27333 return node !== parent.id;
27334 // disregard the `foo`, `bar` in `function foo(bar){}`
27335 case 'FunctionDeclaration':
27336 // disregard the `foo` in `import { foo } from 'foo'`
27337 case 'ImportSpecifier':
27338 // disregard the `foo` in `import foo from 'foo'`
27339 case 'ImportDefaultSpecifier':
27340 // disregard the `foo` in `import * as foo from 'foo'`
27341 case 'ImportNamespaceSpecifier':
27342 // disregard the `foo` in `export { foo }`
27343 case 'ExportSpecifier':
27344 return false;
27345 default:
27346 return true;
27347 }
27348 }
27349
27350 function check_graph_for_cycles(edges) {
27351 const graph = edges.reduce((g, edge) => {
27352 const [u, v] = edge;
27353 if (!g.has(u))
27354 g.set(u, []);
27355 if (!g.has(v))
27356 g.set(v, []);
27357 g.get(u).push(v);
27358 return g;
27359 }, new Map());
27360 const visited = new Set();
27361 const on_stack = new Set();
27362 const cycles = [];
27363 function visit(v) {
27364 visited.add(v);
27365 on_stack.add(v);
27366 graph.get(v).forEach(w => {
27367 if (!visited.has(w)) {
27368 visit(w);
27369 }
27370 else if (on_stack.has(w)) {
27371 cycles.push([...on_stack, w]);
27372 }
27373 });
27374 on_stack.delete(v);
27375 }
27376 graph.forEach((_, v) => {
27377 if (!visited.has(v)) {
27378 visit(v);
27379 }
27380 });
27381 return cycles[0];
27382 }
27383
27384 class Component {
27385 constructor(ast, source, name, compile_options, stats, warnings) {
27386 this.ignore_stack = [];
27387 this.vars = [];
27388 this.var_lookup = new Map();
27389 this.imports = [];
27390 this.hoistable_nodes = new Set();
27391 this.node_for_declaration = new Map();
27392 this.partly_hoisted = [];
27393 this.fully_hoisted = [];
27394 this.reactive_declarations = [];
27395 this.reactive_declaration_nodes = new Set();
27396 this.has_reactive_assignments = false;
27397 this.injected_reactive_declaration_vars = new Set();
27398 this.helpers = new Map();
27399 this.globals = new Map();
27400 this.indirect_dependencies = new Map();
27401 this.elements = [];
27402 this.aliases = new Map();
27403 this.used_names = new Set();
27404 this.globally_used_names = new Set();
27405 this.slots = new Map();
27406 this.slot_outlets = new Set();
27407 this.name = { type: 'Identifier', name };
27408 this.stats = stats;
27409 this.warnings = warnings;
27410 this.ast = ast;
27411 this.source = source;
27412 this.compile_options = compile_options;
27413 // the instance JS gets mutated, so we park
27414 // a copy here for later. TODO this feels gross
27415 this.original_ast = {
27416 html: ast.html,
27417 css: ast.css,
27418 instance: ast.instance && JSON.parse(JSON.stringify(ast.instance)),
27419 module: ast.module
27420 };
27421 this.file =
27422 compile_options.filename &&
27423 (typeof process !== 'undefined'
27424 ? compile_options.filename
27425 .replace(process.cwd(), '')
27426 .replace(/^[/\\]/, '')
27427 : compile_options.filename);
27428 this.locate = getLocator(this.source, { offsetLine: 1 });
27429 // styles
27430 this.stylesheet = new Stylesheet(source, ast, compile_options.filename, compile_options.dev);
27431 this.stylesheet.validate(this);
27432 this.component_options = process_component_options(this, this.ast.html.children);
27433 this.namespace =
27434 namespaces[this.component_options.namespace] ||
27435 this.component_options.namespace;
27436 if (compile_options.customElement) {
27437 if (this.component_options.tag === undefined &&
27438 compile_options.tag === undefined) {
27439 const svelteOptions = ast.html.children.find(child => child.name === 'svelte:options') || { start: 0, end: 0 };
27440 this.warn(svelteOptions, {
27441 code: 'custom-element-no-tag',
27442 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}/>'
27443 });
27444 }
27445 this.tag = this.component_options.tag || compile_options.tag;
27446 }
27447 else {
27448 this.tag = this.name.name;
27449 }
27450 this.walk_module_js();
27451 this.walk_instance_js_pre_template();
27452 this.fragment = new Fragment(this, ast.html);
27453 this.name = this.get_unique_name(name);
27454 this.walk_instance_js_post_template();
27455 this.elements.forEach(element => this.stylesheet.apply(element));
27456 if (!compile_options.customElement)
27457 this.stylesheet.reify();
27458 this.stylesheet.warn_on_unused_selectors(this);
27459 }
27460 add_var(variable) {
27461 this.vars.push(variable);
27462 this.var_lookup.set(variable.name, variable);
27463 }
27464 add_reference(name) {
27465 const variable = this.var_lookup.get(name);
27466 if (variable) {
27467 variable.referenced = true;
27468 }
27469 else if (is_reserved_keyword(name)) {
27470 this.add_var({
27471 name,
27472 injected: true,
27473 referenced: true
27474 });
27475 }
27476 else if (name[0] === '$') {
27477 this.add_var({
27478 name,
27479 injected: true,
27480 referenced: true,
27481 mutated: true,
27482 writable: true
27483 });
27484 const subscribable_name = name.slice(1);
27485 const variable = this.var_lookup.get(subscribable_name);
27486 if (variable) {
27487 variable.referenced = true;
27488 variable.subscribable = true;
27489 }
27490 }
27491 else {
27492 this.used_names.add(name);
27493 }
27494 }
27495 alias(name) {
27496 if (!this.aliases.has(name)) {
27497 this.aliases.set(name, this.get_unique_name(name));
27498 }
27499 return this.aliases.get(name);
27500 }
27501 apply_stylesheet(element) {
27502 this.elements.push(element);
27503 }
27504 global(name) {
27505 const alias = this.alias(name);
27506 this.globals.set(name, alias);
27507 return alias;
27508 }
27509 generate(result) {
27510 let js = null;
27511 let css = null;
27512 if (result) {
27513 const { compile_options, name } = this;
27514 const { format = 'esm' } = compile_options;
27515 const banner = `${this.file ? `${this.file} ` : ''}generated by Svelte v${'3.31.2'}`;
27516 const program = { type: 'Program', body: result.js };
27517 walk(program, {
27518 enter: (node, parent, key) => {
27519 if (node.type === 'Identifier') {
27520 if (node.name[0] === '@') {
27521 if (node.name[1] === '_') {
27522 const alias = this.global(node.name.slice(2));
27523 node.name = alias.name;
27524 }
27525 else {
27526 let name = node.name.slice(1);
27527 if (compile_options.dev) {
27528 if (internal_exports.has(`${name}_dev`)) {
27529 name += '_dev';
27530 }
27531 else if (internal_exports.has(`${name}Dev`)) {
27532 name += 'Dev';
27533 }
27534 }
27535 const alias = this.alias(name);
27536 this.helpers.set(name, alias);
27537 node.name = alias.name;
27538 }
27539 }
27540 else if (node.name[0] !== '#' && !is_valid(node.name)) {
27541 // this hack allows x`foo.${bar}` where bar could be invalid
27542 const literal = { type: 'Literal', value: node.name };
27543 if (parent.type === 'Property' && key === 'key') {
27544 parent.key = literal;
27545 }
27546 else if (parent.type === 'MemberExpression' && key === 'property') {
27547 parent.property = literal;
27548 parent.computed = true;
27549 }
27550 }
27551 }
27552 }
27553 });
27554 const referenced_globals = Array.from(this.globals, ([name, alias]) => name !== alias.name && { name, alias }).filter(Boolean);
27555 if (referenced_globals.length) {
27556 this.helpers.set('globals', this.alias('globals'));
27557 }
27558 const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({
27559 name,
27560 alias
27561 }));
27562 create_module(program, format, name, banner, compile_options.sveltePath, imported_helpers, referenced_globals, this.imports, this.vars
27563 .filter(variable => variable.module && variable.export_name)
27564 .map(variable => ({
27565 name: variable.name,
27566 as: variable.export_name
27567 })));
27568 css = compile_options.customElement
27569 ? { code: null, map: null }
27570 : result.css;
27571 js = print(program, {
27572 sourceMapSource: compile_options.filename
27573 });
27574 js.map.sources = [
27575 compile_options.filename ? get_relative_path(compile_options.outputFilename || '', compile_options.filename) : null
27576 ];
27577 js.map.sourcesContent = [
27578 this.source
27579 ];
27580 js.map = apply_preprocessor_sourcemap(this.file, js.map, compile_options.sourcemap);
27581 }
27582 return {
27583 js,
27584 css,
27585 ast: this.original_ast,
27586 warnings: this.warnings,
27587 vars: this.vars
27588 .filter(v => !v.global && !v.internal)
27589 .map(v => ({
27590 name: v.name,
27591 export_name: v.export_name || null,
27592 injected: v.injected || false,
27593 module: v.module || false,
27594 mutated: v.mutated || false,
27595 reassigned: v.reassigned || false,
27596 referenced: v.referenced || false,
27597 writable: v.writable || false,
27598 referenced_from_script: v.referenced_from_script || false
27599 })),
27600 stats: this.stats.render()
27601 };
27602 }
27603 get_unique_name(name, scope) {
27604 if (test)
27605 name = `${name}$`;
27606 let alias = name;
27607 for (let i = 1; reserved.has(alias) ||
27608 this.var_lookup.has(alias) ||
27609 this.used_names.has(alias) ||
27610 this.globally_used_names.has(alias) ||
27611 (scope && scope.has(alias)); alias = `${name}_${i++}`)
27612 ;
27613 this.used_names.add(alias);
27614 return { type: 'Identifier', name: alias };
27615 }
27616 get_unique_name_maker() {
27617 const local_used_names = new Set();
27618 function add(name) {
27619 local_used_names.add(name);
27620 }
27621 reserved.forEach(add);
27622 internal_exports.forEach(add);
27623 this.var_lookup.forEach((_value, key) => add(key));
27624 return (name) => {
27625 if (test)
27626 name = `${name}$`;
27627 let alias = name;
27628 for (let i = 1; this.used_names.has(alias) || local_used_names.has(alias); alias = `${name}_${i++}`)
27629 ;
27630 local_used_names.add(alias);
27631 this.globally_used_names.add(alias);
27632 return {
27633 type: 'Identifier',
27634 name: alias
27635 };
27636 };
27637 }
27638 error(pos, e) {
27639 error$1(e.message, {
27640 name: 'ValidationError',
27641 code: e.code,
27642 source: this.source,
27643 start: pos.start,
27644 end: pos.end,
27645 filename: this.compile_options.filename
27646 });
27647 }
27648 warn(pos, warning) {
27649 if (this.ignores && this.ignores.has(warning.code)) {
27650 return;
27651 }
27652 const start = this.locate(pos.start);
27653 const end = this.locate(pos.end);
27654 const frame = get_code_frame(this.source, start.line - 1, start.column);
27655 this.warnings.push({
27656 code: warning.code,
27657 message: warning.message,
27658 frame,
27659 start,
27660 end,
27661 pos: pos.start,
27662 filename: this.compile_options.filename,
27663 toString: () => `${warning.message} (${start.line}:${start.column})\n${frame}`
27664 });
27665 }
27666 extract_imports(node) {
27667 this.imports.push(node);
27668 }
27669 extract_exports(node) {
27670 if (node.type === 'ExportDefaultDeclaration') {
27671 this.error(node, {
27672 code: 'default-export',
27673 message: 'A component cannot have a default export'
27674 });
27675 }
27676 if (node.type === 'ExportNamedDeclaration') {
27677 if (node.source) {
27678 this.error(node, {
27679 code: 'not-implemented',
27680 message: 'A component currently cannot have an export ... from'
27681 });
27682 }
27683 if (node.declaration) {
27684 if (node.declaration.type === 'VariableDeclaration') {
27685 node.declaration.declarations.forEach(declarator => {
27686 extract_names(declarator.id).forEach(name => {
27687 const variable = this.var_lookup.get(name);
27688 variable.export_name = name;
27689 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
27690 this.warn(declarator, {
27691 code: 'unused-export-let',
27692 message: `${this.name.name} has unused export property '${name}'. If it is for external reference only, please consider using \`export const ${name}\``
27693 });
27694 }
27695 });
27696 });
27697 }
27698 else {
27699 const { name } = node.declaration.id;
27700 const variable = this.var_lookup.get(name);
27701 variable.export_name = name;
27702 }
27703 return node.declaration;
27704 }
27705 else {
27706 node.specifiers.forEach(specifier => {
27707 const variable = this.var_lookup.get(specifier.local.name);
27708 if (variable) {
27709 variable.export_name = specifier.exported.name;
27710 if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
27711 this.warn(specifier, {
27712 code: 'unused-export-let',
27713 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}\``
27714 });
27715 }
27716 }
27717 });
27718 return null;
27719 }
27720 }
27721 }
27722 extract_javascript(script) {
27723 if (!script)
27724 return null;
27725 return script.content.body.filter(node => {
27726 if (!node)
27727 return false;
27728 if (this.hoistable_nodes.has(node))
27729 return false;
27730 if (this.reactive_declaration_nodes.has(node))
27731 return false;
27732 if (node.type === 'ImportDeclaration')
27733 return false;
27734 if (node.type === 'ExportDeclaration' && node.specifiers.length > 0)
27735 return false;
27736 return true;
27737 });
27738 }
27739 walk_module_js() {
27740 const component = this;
27741 const script = this.ast.module;
27742 if (!script)
27743 return;
27744 walk(script.content, {
27745 enter(node) {
27746 if (node.type === 'LabeledStatement' && node.label.name === '$') {
27747 component.warn(node, {
27748 code: 'module-script-reactive-declaration',
27749 message: '$: has no effect in a module script'
27750 });
27751 }
27752 }
27753 });
27754 const { scope, globals } = create_scopes(script.content);
27755 this.module_scope = scope;
27756 scope.declarations.forEach((node, name) => {
27757 if (name[0] === '$') {
27758 this.error(node, {
27759 code: 'illegal-declaration',
27760 message: 'The $ prefix is reserved, and cannot be used for variable and import names'
27761 });
27762 }
27763 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
27764 this.add_var({
27765 name,
27766 module: true,
27767 hoistable: true,
27768 writable
27769 });
27770 });
27771 globals.forEach((node, name) => {
27772 if (name[0] === '$') {
27773 this.error(node, {
27774 code: 'illegal-subscription',
27775 message: 'Cannot reference store value inside <script context="module">'
27776 });
27777 }
27778 else {
27779 this.add_var({
27780 name,
27781 global: true,
27782 hoistable: true
27783 });
27784 }
27785 });
27786 const { body } = script.content;
27787 let i = body.length;
27788 while (--i >= 0) {
27789 const node = body[i];
27790 if (node.type === 'ImportDeclaration') {
27791 this.extract_imports(node);
27792 body.splice(i, 1);
27793 }
27794 if (/^Export/.test(node.type)) {
27795 const replacement = this.extract_exports(node);
27796 if (replacement) {
27797 body[i] = replacement;
27798 }
27799 else {
27800 body.splice(i, 1);
27801 }
27802 }
27803 }
27804 }
27805 walk_instance_js_pre_template() {
27806 const script = this.ast.instance;
27807 if (!script)
27808 return;
27809 // inject vars for reactive declarations
27810 script.content.body.forEach(node => {
27811 if (node.type !== 'LabeledStatement')
27812 return;
27813 if (node.body.type !== 'ExpressionStatement')
27814 return;
27815 const { expression } = node.body;
27816 if (expression.type !== 'AssignmentExpression')
27817 return;
27818 if (expression.left.type === 'MemberExpression')
27819 return;
27820 extract_names(expression.left).forEach(name => {
27821 if (!this.var_lookup.has(name) && name[0] !== '$') {
27822 this.injected_reactive_declaration_vars.add(name);
27823 }
27824 });
27825 });
27826 const { scope: instance_scope, map, globals } = create_scopes(script.content);
27827 this.instance_scope = instance_scope;
27828 this.instance_scope_map = map;
27829 instance_scope.declarations.forEach((node, name) => {
27830 if (name[0] === '$') {
27831 this.error(node, {
27832 code: 'illegal-declaration',
27833 message: 'The $ prefix is reserved, and cannot be used for variable and import names'
27834 });
27835 }
27836 const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
27837 const imported = node.type.startsWith('Import');
27838 this.add_var({
27839 name,
27840 initialised: instance_scope.initialised_declarations.has(name),
27841 writable,
27842 imported
27843 });
27844 this.node_for_declaration.set(name, node);
27845 });
27846 globals.forEach((node, name) => {
27847 if (this.var_lookup.has(name))
27848 return;
27849 if (this.injected_reactive_declaration_vars.has(name)) {
27850 this.add_var({
27851 name,
27852 injected: true,
27853 writable: true,
27854 reassigned: true,
27855 initialised: true
27856 });
27857 }
27858 else if (is_reserved_keyword(name)) {
27859 this.add_var({
27860 name,
27861 injected: true
27862 });
27863 }
27864 else if (name[0] === '$') {
27865 if (name === '$' || name[1] === '$') {
27866 this.error(node, {
27867 code: 'illegal-global',
27868 message: `${name} is an illegal variable name`
27869 });
27870 }
27871 this.add_var({
27872 name,
27873 injected: true,
27874 mutated: true,
27875 writable: true
27876 });
27877 this.add_reference(name.slice(1));
27878 const variable = this.var_lookup.get(name.slice(1));
27879 if (variable) {
27880 variable.subscribable = true;
27881 variable.referenced_from_script = true;
27882 }
27883 }
27884 else {
27885 this.add_var({
27886 name,
27887 global: true,
27888 hoistable: true
27889 });
27890 }
27891 });
27892 this.track_references_and_mutations();
27893 }
27894 walk_instance_js_post_template() {
27895 const script = this.ast.instance;
27896 if (!script)
27897 return;
27898 this.post_template_walk();
27899 this.hoist_instance_declarations();
27900 this.extract_reactive_declarations();
27901 }
27902 post_template_walk() {
27903 const script = this.ast.instance;
27904 if (!script)
27905 return;
27906 const component = this;
27907 const { content } = script;
27908 const { instance_scope, instance_scope_map: map } = this;
27909 let scope = instance_scope;
27910 const to_remove = [];
27911 const remove = (parent, prop, index) => {
27912 to_remove.unshift([parent, prop, index]);
27913 };
27914 let scope_updated = false;
27915 let generator_count = 0;
27916 walk(content, {
27917 enter(node, parent, prop, index) {
27918 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
27919 generator_count++;
27920 }
27921 if (map.has(node)) {
27922 scope = map.get(node);
27923 }
27924 if (node.type === 'ImportDeclaration') {
27925 component.extract_imports(node);
27926 // TODO: to use actual remove
27927 remove(parent, prop, index);
27928 return this.skip();
27929 }
27930 if (/^Export/.test(node.type)) {
27931 const replacement = component.extract_exports(node);
27932 if (replacement) {
27933 this.replace(replacement);
27934 }
27935 else {
27936 // TODO: to use actual remove
27937 remove(parent, prop, index);
27938 }
27939 return this.skip();
27940 }
27941 component.warn_on_undefined_store_value_references(node, parent, scope);
27942 },
27943 leave(node) {
27944 if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) {
27945 generator_count--;
27946 }
27947 // do it on leave, to prevent infinite loop
27948 if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0 && generator_count <= 0) {
27949 const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout);
27950 if (to_replace_for_loop_protect) {
27951 this.replace(to_replace_for_loop_protect);
27952 scope_updated = true;
27953 }
27954 }
27955 if (map.has(node)) {
27956 scope = scope.parent;
27957 }
27958 }
27959 });
27960 for (const [parent, prop, index] of to_remove) {
27961 if (parent) {
27962 if (index !== null) {
27963 parent[prop].splice(index, 1);
27964 }
27965 else {
27966 delete parent[prop];
27967 }
27968 }
27969 }
27970 if (scope_updated) {
27971 const { scope, map } = create_scopes(script.content);
27972 this.instance_scope = scope;
27973 this.instance_scope_map = map;
27974 }
27975 }
27976 track_references_and_mutations() {
27977 const script = this.ast.instance;
27978 if (!script)
27979 return;
27980 const component = this;
27981 const { content } = script;
27982 const { instance_scope, module_scope, instance_scope_map: map } = this;
27983 let scope = instance_scope;
27984 walk(content, {
27985 enter(node, parent) {
27986 if (map.has(node)) {
27987 scope = map.get(node);
27988 }
27989 if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
27990 const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
27991 const names = extract_names(assignee);
27992 const deep = assignee.type === 'MemberExpression';
27993 names.forEach(name => {
27994 const scope_owner = scope.find_owner(name);
27995 if (scope_owner !== null
27996 ? scope_owner === instance_scope
27997 : module_scope && module_scope.has(name)) {
27998 const variable = component.var_lookup.get(name);
27999 variable[deep ? 'mutated' : 'reassigned'] = true;
28000 }
28001 });
28002 }
28003 if (is_used_as_reference(node, parent)) {
28004 const object = get_object(node);
28005 if (scope.find_owner(object.name) === instance_scope) {
28006 const variable = component.var_lookup.get(object.name);
28007 variable.referenced_from_script = true;
28008 }
28009 }
28010 },
28011 leave(node) {
28012 if (map.has(node)) {
28013 scope = scope.parent;
28014 }
28015 }
28016 });
28017 }
28018 warn_on_undefined_store_value_references(node, parent, scope) {
28019 if (node.type === 'LabeledStatement' &&
28020 node.label.name === '$' &&
28021 parent.type !== 'Program') {
28022 this.warn(node, {
28023 code: 'non-top-level-reactive-declaration',
28024 message: '$: has no effect outside of the top-level'
28025 });
28026 }
28027 if (isReference(node, parent)) {
28028 const object = get_object(node);
28029 const { name } = object;
28030 if (name[0] === '$') {
28031 if (!scope.has(name)) {
28032 this.warn_if_undefined(name, object, null);
28033 }
28034 if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
28035 this.error(node, {
28036 code: 'contextual-store',
28037 message: 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
28038 });
28039 }
28040 }
28041 }
28042 }
28043 loop_protect(node, scope, timeout) {
28044 if (node.type === 'WhileStatement' ||
28045 node.type === 'ForStatement' ||
28046 node.type === 'DoWhileStatement') {
28047 const guard = this.get_unique_name('guard', scope);
28048 this.used_names.add(guard.name);
28049 const before = b `const ${guard} = @loop_guard(${timeout})`;
28050 const inside = b `${guard}();`;
28051 // wrap expression statement with BlockStatement
28052 if (node.body.type !== 'BlockStatement') {
28053 node.body = {
28054 type: 'BlockStatement',
28055 body: [node.body]
28056 };
28057 }
28058 node.body.body.push(inside[0]);
28059 return {
28060 type: 'BlockStatement',
28061 body: [
28062 before[0],
28063 node
28064 ]
28065 };
28066 }
28067 return null;
28068 }
28069 rewrite_props(get_insert) {
28070 if (!this.ast.instance)
28071 return;
28072 const component = this;
28073 const { instance_scope, instance_scope_map: map } = this;
28074 let scope = instance_scope;
28075 walk(this.ast.instance.content, {
28076 enter(node, parent, key, index) {
28077 if (/Function/.test(node.type)) {
28078 return this.skip();
28079 }
28080 if (map.has(node)) {
28081 scope = map.get(node);
28082 }
28083 if (node.type === 'VariableDeclaration') {
28084 if (node.kind === 'var' || scope === instance_scope) {
28085 node.declarations.forEach(declarator => {
28086 if (declarator.id.type !== 'Identifier') {
28087 const inserts = [];
28088 extract_names(declarator.id).forEach(name => {
28089 const variable = component.var_lookup.get(name);
28090 if (variable.export_name) {
28091 // TODO is this still true post-#3539?
28092 component.error(declarator, {
28093 code: 'destructured-prop',
28094 message: 'Cannot declare props in destructured declaration'
28095 });
28096 }
28097 if (variable.subscribable) {
28098 inserts.push(get_insert(variable));
28099 }
28100 });
28101 if (inserts.length) {
28102 parent[key].splice(index + 1, 0, ...inserts);
28103 }
28104 return;
28105 }
28106 const { name } = declarator.id;
28107 const variable = component.var_lookup.get(name);
28108 if (variable.export_name && variable.writable) {
28109 declarator.id = {
28110 type: 'ObjectPattern',
28111 properties: [{
28112 type: 'Property',
28113 method: false,
28114 shorthand: false,
28115 computed: false,
28116 kind: 'init',
28117 key: { type: 'Identifier', name: variable.export_name },
28118 value: declarator.init
28119 ? {
28120 type: 'AssignmentPattern',
28121 left: declarator.id,
28122 right: declarator.init
28123 }
28124 : declarator.id
28125 }]
28126 };
28127 declarator.init = x `$$props`;
28128 }
28129 if (variable.subscribable && declarator.init) {
28130 const insert = get_insert(variable);
28131 parent[key].splice(index + 1, 0, ...insert);
28132 }
28133 });
28134 }
28135 }
28136 },
28137 leave(node, parent, _key, index) {
28138 if (map.has(node)) {
28139 scope = scope.parent;
28140 }
28141 if (node.type === 'ExportNamedDeclaration' && node.declaration) {
28142 parent.body[index] = node.declaration;
28143 }
28144 }
28145 });
28146 }
28147 hoist_instance_declarations() {
28148 // we can safely hoist variable declarations that are
28149 // initialised to literals, and functions that don't
28150 // reference instance variables other than other
28151 // hoistable functions. TODO others?
28152 const { hoistable_nodes, var_lookup, injected_reactive_declaration_vars, imports } = this;
28153 const top_level_function_declarations = new Map();
28154 const { body } = this.ast.instance.content;
28155 for (let i = 0; i < body.length; i += 1) {
28156 const node = body[i];
28157 if (node.type === 'VariableDeclaration') {
28158 const all_hoistable = node.declarations.every(d => {
28159 if (!d.init)
28160 return false;
28161 if (d.init.type !== 'Literal')
28162 return false;
28163 // everything except const values can be changed by e.g. svelte devtools
28164 // which means we can't hoist it
28165 if (node.kind !== 'const' && this.compile_options.dev)
28166 return false;
28167 const { name } = d.id;
28168 const v = this.var_lookup.get(name);
28169 if (v.reassigned)
28170 return false;
28171 if (v.export_name)
28172 return false;
28173 if (this.var_lookup.get(name).reassigned)
28174 return false;
28175 if (this.vars.find(variable => variable.name === name && variable.module)) {
28176 return false;
28177 }
28178 return true;
28179 });
28180 if (all_hoistable) {
28181 node.declarations.forEach(d => {
28182 const variable = this.var_lookup.get(d.id.name);
28183 variable.hoistable = true;
28184 });
28185 hoistable_nodes.add(node);
28186 body.splice(i--, 1);
28187 this.fully_hoisted.push(node);
28188 }
28189 }
28190 if (node.type === 'ExportNamedDeclaration' &&
28191 node.declaration &&
28192 node.declaration.type === 'FunctionDeclaration') {
28193 top_level_function_declarations.set(node.declaration.id.name, node);
28194 }
28195 if (node.type === 'FunctionDeclaration') {
28196 top_level_function_declarations.set(node.id.name, node);
28197 }
28198 }
28199 const checked = new Set();
28200 const walking = new Set();
28201 const is_hoistable = fn_declaration => {
28202 if (fn_declaration.type === 'ExportNamedDeclaration') {
28203 fn_declaration = fn_declaration.declaration;
28204 }
28205 const instance_scope = this.instance_scope;
28206 let scope = this.instance_scope;
28207 const map = this.instance_scope_map;
28208 let hoistable = true;
28209 // handle cycles
28210 walking.add(fn_declaration);
28211 walk(fn_declaration, {
28212 enter(node, parent) {
28213 if (!hoistable)
28214 return this.skip();
28215 if (map.has(node)) {
28216 scope = map.get(node);
28217 }
28218 if (isReference(node, parent)) {
28219 const { name } = flatten_reference(node);
28220 const owner = scope.find_owner(name);
28221 if (injected_reactive_declaration_vars.has(name)) {
28222 hoistable = false;
28223 }
28224 else if (name[0] === '$' && !owner) {
28225 hoistable = false;
28226 }
28227 else if (owner === instance_scope) {
28228 const variable = var_lookup.get(name);
28229 if (variable.reassigned || variable.mutated)
28230 hoistable = false;
28231 if (name === fn_declaration.id.name)
28232 return;
28233 if (variable.hoistable)
28234 return;
28235 if (top_level_function_declarations.has(name)) {
28236 const other_declaration = top_level_function_declarations.get(name);
28237 if (walking.has(other_declaration)) {
28238 hoistable = false;
28239 }
28240 else if (other_declaration.type === 'ExportNamedDeclaration' &&
28241 walking.has(other_declaration.declaration)) {
28242 hoistable = false;
28243 }
28244 else if (!is_hoistable(other_declaration)) {
28245 hoistable = false;
28246 }
28247 }
28248 else {
28249 hoistable = false;
28250 }
28251 }
28252 this.skip();
28253 }
28254 },
28255 leave(node) {
28256 if (map.has(node)) {
28257 scope = scope.parent;
28258 }
28259 }
28260 });
28261 checked.add(fn_declaration);
28262 walking.delete(fn_declaration);
28263 return hoistable;
28264 };
28265 for (const [name, node] of top_level_function_declarations) {
28266 if (is_hoistable(node)) {
28267 const variable = this.var_lookup.get(name);
28268 variable.hoistable = true;
28269 hoistable_nodes.add(node);
28270 const i = body.indexOf(node);
28271 body.splice(i, 1);
28272 this.fully_hoisted.push(node);
28273 }
28274 }
28275 for (const { specifiers } of imports) {
28276 for (const specifier of specifiers) {
28277 const variable = var_lookup.get(specifier.local.name);
28278 if (!variable.mutated || variable.subscribable) {
28279 variable.hoistable = true;
28280 }
28281 }
28282 }
28283 }
28284 extract_reactive_declarations() {
28285 const component = this;
28286 const unsorted_reactive_declarations = [];
28287 this.ast.instance.content.body.forEach(node => {
28288 if (node.type === 'LabeledStatement' && node.label.name === '$') {
28289 this.reactive_declaration_nodes.add(node);
28290 const assignees = new Set();
28291 const assignee_nodes = new Set();
28292 const dependencies = new Set();
28293 let scope = this.instance_scope;
28294 const map = this.instance_scope_map;
28295 walk(node.body, {
28296 enter(node, parent) {
28297 if (map.has(node)) {
28298 scope = map.get(node);
28299 }
28300 if (node.type === 'AssignmentExpression') {
28301 const left = get_object(node.left);
28302 extract_identifiers(left).forEach(node => {
28303 assignee_nodes.add(node);
28304 assignees.add(node.name);
28305 });
28306 if (node.operator !== '=') {
28307 dependencies.add(left.name);
28308 }
28309 }
28310 else if (node.type === 'UpdateExpression') {
28311 const identifier = get_object(node.argument);
28312 assignees.add(identifier.name);
28313 }
28314 else if (isReference(node, parent)) {
28315 const identifier = get_object(node);
28316 if (!assignee_nodes.has(identifier)) {
28317 const { name } = identifier;
28318 const owner = scope.find_owner(name);
28319 const variable = component.var_lookup.get(name);
28320 if (variable)
28321 variable.is_reactive_dependency = true;
28322 const is_writable_or_mutated = variable && (variable.writable || variable.mutated);
28323 if ((!owner || owner === component.instance_scope) &&
28324 (name[0] === '$' || is_writable_or_mutated)) {
28325 dependencies.add(name);
28326 }
28327 }
28328 this.skip();
28329 }
28330 },
28331 leave(node) {
28332 if (map.has(node)) {
28333 scope = scope.parent;
28334 }
28335 }
28336 });
28337 const { expression } = node.body;
28338 const declaration = expression && expression.left;
28339 unsorted_reactive_declarations.push({
28340 assignees,
28341 dependencies,
28342 node,
28343 declaration
28344 });
28345 }
28346 });
28347 const lookup = new Map();
28348 unsorted_reactive_declarations.forEach(declaration => {
28349 declaration.assignees.forEach(name => {
28350 if (!lookup.has(name)) {
28351 lookup.set(name, []);
28352 }
28353 // TODO warn or error if a name is assigned to in
28354 // multiple reactive declarations?
28355 lookup.get(name).push(declaration);
28356 });
28357 });
28358 const cycle = check_graph_for_cycles(unsorted_reactive_declarations.reduce((acc, declaration) => {
28359 declaration.assignees.forEach(v => {
28360 declaration.dependencies.forEach(w => {
28361 if (!declaration.assignees.has(w)) {
28362 acc.push([v, w]);
28363 }
28364 });
28365 });
28366 return acc;
28367 }, []));
28368 if (cycle && cycle.length) {
28369 const declarationList = lookup.get(cycle[0]);
28370 const declaration = declarationList[0];
28371 this.error(declaration.node, {
28372 code: 'cyclical-reactive-declaration',
28373 message: `Cyclical dependency detected: ${cycle.join(' → ')}`
28374 });
28375 }
28376 const add_declaration = declaration => {
28377 if (this.reactive_declarations.includes(declaration))
28378 return;
28379 declaration.dependencies.forEach(name => {
28380 if (declaration.assignees.has(name))
28381 return;
28382 const earlier_declarations = lookup.get(name);
28383 if (earlier_declarations) {
28384 earlier_declarations.forEach(add_declaration);
28385 }
28386 });
28387 this.reactive_declarations.push(declaration);
28388 };
28389 unsorted_reactive_declarations.forEach(add_declaration);
28390 }
28391 warn_if_undefined(name, node, template_scope) {
28392 if (name[0] === '$') {
28393 if (name === '$' || name[1] === '$' && !is_reserved_keyword(name)) {
28394 this.error(node, {
28395 code: 'illegal-global',
28396 message: `${name} is an illegal variable name`
28397 });
28398 }
28399 this.has_reactive_assignments = true; // TODO does this belong here?
28400 if (is_reserved_keyword(name))
28401 return;
28402 name = name.slice(1);
28403 }
28404 if (this.var_lookup.has(name) && !this.var_lookup.get(name).global)
28405 return;
28406 if (template_scope && template_scope.names.has(name))
28407 return;
28408 if (globals.has(name) && node.type !== 'InlineComponent')
28409 return;
28410 let message = `'${name}' is not defined`;
28411 if (!this.ast.instance) {
28412 message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;
28413 }
28414 this.warn(node, {
28415 code: 'missing-declaration',
28416 message
28417 });
28418 }
28419 push_ignores(ignores) {
28420 this.ignores = new Set(this.ignores || []);
28421 add_to_set(this.ignores, ignores);
28422 this.ignore_stack.push(this.ignores);
28423 }
28424 pop_ignores() {
28425 this.ignore_stack.pop();
28426 this.ignores = this.ignore_stack[this.ignore_stack.length - 1];
28427 }
28428 }
28429 function process_component_options(component, nodes) {
28430 const component_options = {
28431 immutable: component.compile_options.immutable || false,
28432 accessors: 'accessors' in component.compile_options
28433 ? component.compile_options.accessors
28434 : !!component.compile_options.customElement,
28435 preserveWhitespace: !!component.compile_options.preserveWhitespace
28436 };
28437 const node = nodes.find(node => node.name === 'svelte:options');
28438 function get_value(attribute, code, message) {
28439 const { value } = attribute;
28440 const chunk = value[0];
28441 if (!chunk)
28442 return true;
28443 if (value.length > 1) {
28444 component.error(attribute, { code, message });
28445 }
28446 if (chunk.type === 'Text')
28447 return chunk.data;
28448 if (chunk.expression.type !== 'Literal') {
28449 component.error(attribute, { code, message });
28450 }
28451 return chunk.expression.value;
28452 }
28453 if (node) {
28454 node.attributes.forEach(attribute => {
28455 if (attribute.type === 'Attribute') {
28456 const { name } = attribute;
28457 switch (name) {
28458 case 'tag': {
28459 const code = 'invalid-tag-attribute';
28460 const message = "'tag' must be a string literal";
28461 const tag = get_value(attribute, code, message);
28462 if (typeof tag !== 'string' && tag !== null) {
28463 component.error(attribute, { code, message });
28464 }
28465 if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
28466 component.error(attribute, {
28467 code: 'invalid-tag-property',
28468 message: "tag name must be two or more words joined by the '-' character"
28469 });
28470 }
28471 if (tag && !component.compile_options.customElement) {
28472 component.warn(attribute, {
28473 code: 'missing-custom-element-compile-options',
28474 message: "The 'tag' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?"
28475 });
28476 }
28477 component_options.tag = tag;
28478 break;
28479 }
28480 case 'namespace': {
28481 const code = 'invalid-namespace-attribute';
28482 const message = "The 'namespace' attribute must be a string literal representing a valid namespace";
28483 const ns = get_value(attribute, code, message);
28484 if (typeof ns !== 'string') {
28485 component.error(attribute, { code, message });
28486 }
28487 if (valid_namespaces.indexOf(ns) === -1) {
28488 const match = fuzzymatch(ns, valid_namespaces);
28489 if (match) {
28490 component.error(attribute, {
28491 code: 'invalid-namespace-property',
28492 message: `Invalid namespace '${ns}' (did you mean '${match}'?)`
28493 });
28494 }
28495 else {
28496 component.error(attribute, {
28497 code: 'invalid-namespace-property',
28498 message: `Invalid namespace '${ns}'`
28499 });
28500 }
28501 }
28502 component_options.namespace = ns;
28503 break;
28504 }
28505 case 'accessors':
28506 case 'immutable':
28507 case 'preserveWhitespace': {
28508 const code = `invalid-${name}-value`;
28509 const message = `${name} attribute must be true or false`;
28510 const value = get_value(attribute, code, message);
28511 if (typeof value !== 'boolean') {
28512 component.error(attribute, { code, message });
28513 }
28514 component_options[name] = value;
28515 break;
28516 }
28517 default:
28518 component.error(attribute, {
28519 code: 'invalid-options-attribute',
28520 message: '<svelte:options> unknown attribute'
28521 });
28522 }
28523 }
28524 else {
28525 component.error(attribute, {
28526 code: 'invalid-options-attribute',
28527 message: "<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes"
28528 });
28529 }
28530 });
28531 }
28532 return component_options;
28533 }
28534 function get_relative_path(from, to) {
28535 const from_parts = from.split(/[/\\]/);
28536 const to_parts = to.split(/[/\\]/);
28537 from_parts.pop(); // get dirname
28538 while (from_parts[0] === to_parts[0]) {
28539 from_parts.shift();
28540 to_parts.shift();
28541 }
28542 if (from_parts.length) {
28543 let i = from_parts.length;
28544 while (i--)
28545 from_parts[i] = '..';
28546 }
28547 return from_parts.concat(to_parts).join('/');
28548 }
28549
28550 function get_name_from_filename(filename) {
28551 if (!filename)
28552 return null;
28553 const parts = filename.split(/[/\\]/).map(encodeURI);
28554 if (parts.length > 1) {
28555 const index_match = parts[parts.length - 1].match(/^index(\.\w+)/);
28556 if (index_match) {
28557 parts.pop();
28558 parts[parts.length - 1] += index_match[1];
28559 }
28560 }
28561 const base = parts.pop()
28562 .replace(/%/g, 'u')
28563 .replace(/\.[^.]+$/, '')
28564 .replace(/[^a-zA-Z_$0-9]+/g, '_')
28565 .replace(/^_/, '')
28566 .replace(/_$/, '')
28567 .replace(/^(\d)/, '_$1');
28568 if (!base) {
28569 throw new Error(`Could not derive component name from file ${filename}`);
28570 }
28571 return base[0].toUpperCase() + base.slice(1);
28572 }
28573
28574 const valid_options = [
28575 'format',
28576 'name',
28577 'filename',
28578 'sourcemap',
28579 'generate',
28580 'outputFilename',
28581 'cssOutputFilename',
28582 'sveltePath',
28583 'dev',
28584 'accessors',
28585 'immutable',
28586 'hydratable',
28587 'legacy',
28588 'customElement',
28589 'tag',
28590 'css',
28591 'loopGuardTimeout',
28592 'preserveComments',
28593 'preserveWhitespace'
28594 ];
28595 function validate_options(options, warnings) {
28596 const { name, filename, loopGuardTimeout, dev } = options;
28597 Object.keys(options).forEach(key => {
28598 if (!valid_options.includes(key)) {
28599 const match = fuzzymatch(key, valid_options);
28600 let message = `Unrecognized option '${key}'`;
28601 if (match)
28602 message += ` (did you mean '${match}'?)`;
28603 throw new Error(message);
28604 }
28605 });
28606 if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) {
28607 throw new Error(`options.name must be a valid identifier (got '${name}')`);
28608 }
28609 if (name && /^[a-z]/.test(name)) {
28610 const message = 'options.name should be capitalised';
28611 warnings.push({
28612 code: 'options-lowercase-name',
28613 message,
28614 filename,
28615 toString: () => message
28616 });
28617 }
28618 if (loopGuardTimeout && !dev) {
28619 const message = 'options.loopGuardTimeout is for options.dev = true only';
28620 warnings.push({
28621 code: 'options-loop-guard-timeout',
28622 message,
28623 filename,
28624 toString: () => message
28625 });
28626 }
28627 }
28628 function compile(source, options = {}) {
28629 options = Object.assign({ generate: 'dom', dev: false }, options);
28630 const stats = new Stats();
28631 const warnings = [];
28632 validate_options(options, warnings);
28633 stats.start('parse');
28634 const ast = parse$3(source, options);
28635 stats.stop('parse');
28636 stats.start('create component');
28637 const component = new Component(ast, source, options.name || get_name_from_filename(options.filename) || 'Component', options, stats, warnings);
28638 stats.stop('create component');
28639 const result = options.generate === false
28640 ? null
28641 : options.generate === 'ssr'
28642 ? ssr(component, options)
28643 : dom(component, options);
28644 return component.generate(result);
28645 }
28646
28647 function parse_attributes(str) {
28648 const attrs = {};
28649 str.split(/\s+/).filter(Boolean).forEach(attr => {
28650 const p = attr.indexOf('=');
28651 if (p === -1) {
28652 attrs[attr] = true;
28653 }
28654 else {
28655 attrs[attr.slice(0, p)] = '\'"'.includes(attr[p + 1]) ?
28656 attr.slice(p + 2, -1) :
28657 attr.slice(p + 1);
28658 }
28659 });
28660 return attrs;
28661 }
28662 function get_file_basename(filename) {
28663 return filename.split(/[/\\]/).pop();
28664 }
28665 async function replace_async(file_basename, source, get_location, re, func) {
28666 const replacements = [];
28667 source.replace(re, (...args) => {
28668 replacements.push(func(...args).then(res => ({
28669 offset: args[args.length - 2],
28670 length: args[0].length,
28671 replacement: res
28672 })));
28673 return '';
28674 });
28675 const out = new StringWithSourcemap();
28676 let last_end = 0;
28677 for (const { offset, length, replacement } of await Promise.all(replacements)) {
28678 // content = unchanged source characters before the replaced segment
28679 const content = StringWithSourcemap.from_source(file_basename, source.slice(last_end, offset), get_location(last_end));
28680 out.concat(content).concat(replacement);
28681 last_end = offset + length;
28682 }
28683 // final_content = unchanged source characters after last replaced segment
28684 const final_content = StringWithSourcemap.from_source(file_basename, source.slice(last_end), get_location(last_end));
28685 return out.concat(final_content);
28686 }
28687 /**
28688 * Import decoded sourcemap from mozilla/source-map/SourceMapGenerator
28689 * Forked from source-map/lib/source-map-generator.js
28690 * from methods _serializeMappings and toJSON.
28691 * We cannot use source-map.d.ts types, because we access hidden properties.
28692 */
28693 function decoded_sourcemap_from_generator(generator) {
28694 let previous_generated_line = 1;
28695 const converted_mappings = [[]];
28696 let result_line;
28697 let result_segment;
28698 let mapping;
28699 const source_idx = generator._sources.toArray()
28700 .reduce((acc, val, idx) => (acc[val] = idx, acc), {});
28701 const name_idx = generator._names.toArray()
28702 .reduce((acc, val, idx) => (acc[val] = idx, acc), {});
28703 const mappings = generator._mappings.toArray();
28704 result_line = converted_mappings[0];
28705 for (let i = 0, len = mappings.length; i < len; i++) {
28706 mapping = mappings[i];
28707 if (mapping.generatedLine > previous_generated_line) {
28708 while (mapping.generatedLine > previous_generated_line) {
28709 converted_mappings.push([]);
28710 previous_generated_line++;
28711 }
28712 result_line = converted_mappings[mapping.generatedLine - 1]; // line is one-based
28713 }
28714 else if (i > 0) {
28715 const previous_mapping = mappings[i - 1];
28716 if (
28717 // sorted by selectivity
28718 mapping.generatedColumn === previous_mapping.generatedColumn &&
28719 mapping.originalColumn === previous_mapping.originalColumn &&
28720 mapping.name === previous_mapping.name &&
28721 mapping.generatedLine === previous_mapping.generatedLine &&
28722 mapping.originalLine === previous_mapping.originalLine &&
28723 mapping.source === previous_mapping.source) {
28724 continue;
28725 }
28726 }
28727 result_line.push([mapping.generatedColumn]);
28728 result_segment = result_line[result_line.length - 1];
28729 if (mapping.source != null) {
28730 result_segment.push(...[
28731 source_idx[mapping.source],
28732 mapping.originalLine - 1,
28733 mapping.originalColumn
28734 ]);
28735 if (mapping.name != null) {
28736 result_segment.push(name_idx[mapping.name]);
28737 }
28738 }
28739 }
28740 const map = {
28741 version: generator._version,
28742 sources: generator._sources.toArray(),
28743 names: generator._names.toArray(),
28744 mappings: converted_mappings
28745 };
28746 if (generator._file != null) {
28747 map.file = generator._file;
28748 }
28749 // not needed: map.sourcesContent and map.sourceRoot
28750 return map;
28751 }
28752 /**
28753 * Convert a preprocessor output and its leading prefix and trailing suffix into StringWithSourceMap
28754 */
28755 function get_replacement(file_basename, offset, get_location, original, processed, prefix, suffix) {
28756 // Convert the unchanged prefix and suffix to StringWithSourcemap
28757 const prefix_with_map = StringWithSourcemap.from_source(file_basename, prefix, get_location(offset));
28758 const suffix_with_map = StringWithSourcemap.from_source(file_basename, suffix, get_location(offset + prefix.length + original.length));
28759 // Convert the preprocessed code and its sourcemap to a StringWithSourcemap
28760 let decoded_map;
28761 if (processed.map) {
28762 decoded_map = typeof processed.map === 'string' ? JSON.parse(processed.map) : processed.map;
28763 if (typeof (decoded_map.mappings) === 'string') {
28764 decoded_map.mappings = decode(decoded_map.mappings);
28765 }
28766 if (decoded_map._mappings && decoded_map.constructor.name === 'SourceMapGenerator') {
28767 // import decoded sourcemap from mozilla/source-map/SourceMapGenerator
28768 decoded_map = decoded_sourcemap_from_generator(decoded_map);
28769 }
28770 // offset only segments pointing at original component source
28771 const source_index = decoded_map.sources.indexOf(file_basename);
28772 if (source_index !== -1) {
28773 sourcemap_add_offset(decoded_map, get_location(offset + prefix.length), source_index);
28774 }
28775 }
28776 const processed_with_map = StringWithSourcemap.from_processed(processed.code, decoded_map);
28777 // Surround the processed code with the prefix and suffix, retaining valid sourcemappings
28778 return prefix_with_map.concat(processed_with_map).concat(suffix_with_map);
28779 }
28780 async function preprocess(source, preprocessor, options) {
28781 // @ts-ignore todo: doublecheck
28782 const filename = (options && options.filename) || preprocessor.filename; // legacy
28783 const dependencies = [];
28784 // preprocess source must be relative to itself or equal null
28785 const file_basename = filename == null ? null : get_file_basename(filename);
28786 const preprocessors = preprocessor
28787 ? Array.isArray(preprocessor) ? preprocessor : [preprocessor]
28788 : [];
28789 const markup = preprocessors.map(p => p.markup).filter(Boolean);
28790 const script = preprocessors.map(p => p.script).filter(Boolean);
28791 const style = preprocessors.map(p => p.style).filter(Boolean);
28792 // sourcemap_list is sorted in reverse order from last map (index 0) to first map (index -1)
28793 // so we use sourcemap_list.unshift() to add new maps
28794 // https://github.com/ampproject/remapping#multiple-transformations-of-a-file
28795 const sourcemap_list = [];
28796 // TODO keep track: what preprocessor generated what sourcemap? to make debugging easier = detect low-resolution sourcemaps in fn combine_mappings
28797 for (const fn of markup) {
28798 // run markup preprocessor
28799 const processed = await fn({
28800 content: source,
28801 filename
28802 });
28803 if (!processed)
28804 continue;
28805 if (processed.dependencies)
28806 dependencies.push(...processed.dependencies);
28807 source = processed.code;
28808 if (processed.map) {
28809 sourcemap_list.unshift(typeof (processed.map) === 'string'
28810 ? JSON.parse(processed.map)
28811 : processed.map);
28812 }
28813 }
28814 async function preprocess_tag_content(tag_name, preprocessor) {
28815 const get_location = getLocator(source);
28816 const tag_regex = tag_name === 'style'
28817 ? /<!--[^]*?-->|<style(\s[^]*?)?(?:>([^]*?)<\/style>|\/>)/gi
28818 : /<!--[^]*?-->|<script(\s[^]*?)?(?:>([^]*?)<\/script>|\/>)/gi;
28819 const res = await replace_async(file_basename, source, get_location, tag_regex, async (match, attributes = '', content = '', offset) => {
28820 const no_change = () => StringWithSourcemap.from_source(file_basename, match, get_location(offset));
28821 if (!attributes && !content) {
28822 return no_change();
28823 }
28824 attributes = attributes || '';
28825 content = content || '';
28826 // run script preprocessor
28827 const processed = await preprocessor({
28828 content,
28829 attributes: parse_attributes(attributes),
28830 filename
28831 });
28832 if (processed && processed.dependencies) {
28833 dependencies.push(...processed.dependencies);
28834 }
28835 if (!processed || !processed.map && processed.code === content) {
28836 return no_change();
28837 }
28838 return get_replacement(file_basename, offset, get_location, content, processed, `<${tag_name}${attributes}>`, `</${tag_name}>`);
28839 });
28840 source = res.string;
28841 sourcemap_list.unshift(res.map);
28842 }
28843 for (const fn of script) {
28844 await preprocess_tag_content('script', fn);
28845 }
28846 for (const fn of style) {
28847 await preprocess_tag_content('style', fn);
28848 }
28849 // Combine all the source maps for each preprocessor function into one
28850 const map = combine_sourcemaps(file_basename, sourcemap_list);
28851 return {
28852 // TODO return separated output, in future version where svelte.compile supports it:
28853 // style: { code: styleCode, map: styleMap },
28854 // script { code: scriptCode, map: scriptMap },
28855 // markup { code: markupCode, map: markupMap },
28856 code: source,
28857 dependencies: [...new Set(dependencies)],
28858 map: map,
28859 toString() {
28860 return source;
28861 }
28862 };
28863 }
28864
28865 const VERSION = '3.31.2';
28866
28867 exports.VERSION = VERSION;
28868 exports.compile = compile;
28869 exports.parse = parse$3;
28870 exports.preprocess = preprocess;
28871 exports.walk = walk;
28872
28873 Object.defineProperty(exports, '__esModule', { value: true });
28874
28875})));
28876//# sourceMappingURL=compiler.js.map