1 | /***********************************************************************
|
---|
2 |
|
---|
3 | A JavaScript tokenizer / parser / beautifier / compressor.
|
---|
4 | https://github.com/mishoo/UglifyJS2
|
---|
5 |
|
---|
6 | -------------------------------- (C) ---------------------------------
|
---|
7 |
|
---|
8 | Author: Mihai Bazon
|
---|
9 | <mihai.bazon@gmail.com>
|
---|
10 | http://mihai.bazon.net/blog
|
---|
11 |
|
---|
12 | Distributed under the BSD license:
|
---|
13 |
|
---|
14 | Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
---|
15 |
|
---|
16 | Redistribution and use in source and binary forms, with or without
|
---|
17 | modification, are permitted provided that the following conditions
|
---|
18 | are met:
|
---|
19 |
|
---|
20 | * Redistributions of source code must retain the above
|
---|
21 | copyright notice, this list of conditions and the following
|
---|
22 | disclaimer.
|
---|
23 |
|
---|
24 | * Redistributions in binary form must reproduce the above
|
---|
25 | copyright notice, this list of conditions and the following
|
---|
26 | disclaimer in the documentation and/or other materials
|
---|
27 | provided with the distribution.
|
---|
28 |
|
---|
29 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
---|
30 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
31 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
---|
32 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
---|
33 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
---|
34 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
---|
35 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
---|
36 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
---|
37 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
---|
38 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
---|
39 | THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
---|
40 | SUCH DAMAGE.
|
---|
41 |
|
---|
42 | ***********************************************************************/
|
---|
43 |
|
---|
44 | "use strict";
|
---|
45 |
|
---|
46 | function characters(str) {
|
---|
47 | return str.split("");
|
---|
48 | }
|
---|
49 |
|
---|
50 | function member(name, array) {
|
---|
51 | return array.includes(name);
|
---|
52 | }
|
---|
53 |
|
---|
54 | class DefaultsError extends Error {
|
---|
55 | constructor(msg, defs) {
|
---|
56 | super();
|
---|
57 |
|
---|
58 | this.name = "DefaultsError";
|
---|
59 | this.message = msg;
|
---|
60 | this.defs = defs;
|
---|
61 | }
|
---|
62 | }
|
---|
63 |
|
---|
64 | function defaults(args, defs, croak) {
|
---|
65 | if (args === true) {
|
---|
66 | args = {};
|
---|
67 | } else if (args != null && typeof args === "object") {
|
---|
68 | args = {...args};
|
---|
69 | }
|
---|
70 |
|
---|
71 | const ret = args || {};
|
---|
72 |
|
---|
73 | if (croak) for (const i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
|
---|
74 | throw new DefaultsError("`" + i + "` is not a supported option", defs);
|
---|
75 | }
|
---|
76 |
|
---|
77 | for (const i in defs) if (HOP(defs, i)) {
|
---|
78 | if (!args || !HOP(args, i)) {
|
---|
79 | ret[i] = defs[i];
|
---|
80 | } else if (i === "ecma") {
|
---|
81 | let ecma = args[i] | 0;
|
---|
82 | if (ecma > 5 && ecma < 2015) ecma += 2009;
|
---|
83 | ret[i] = ecma;
|
---|
84 | } else {
|
---|
85 | ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
|
---|
86 | }
|
---|
87 | }
|
---|
88 |
|
---|
89 | return ret;
|
---|
90 | }
|
---|
91 |
|
---|
92 | function noop() {}
|
---|
93 | function return_false() { return false; }
|
---|
94 | function return_true() { return true; }
|
---|
95 | function return_this() { return this; }
|
---|
96 | function return_null() { return null; }
|
---|
97 |
|
---|
98 | var MAP = (function() {
|
---|
99 | function MAP(a, f, backwards) {
|
---|
100 | var ret = [], top = [], i;
|
---|
101 | function doit() {
|
---|
102 | var val = f(a[i], i);
|
---|
103 | var is_last = val instanceof Last;
|
---|
104 | if (is_last) val = val.v;
|
---|
105 | if (val instanceof AtTop) {
|
---|
106 | val = val.v;
|
---|
107 | if (val instanceof Splice) {
|
---|
108 | top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
|
---|
109 | } else {
|
---|
110 | top.push(val);
|
---|
111 | }
|
---|
112 | } else if (val !== skip) {
|
---|
113 | if (val instanceof Splice) {
|
---|
114 | ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
|
---|
115 | } else {
|
---|
116 | ret.push(val);
|
---|
117 | }
|
---|
118 | }
|
---|
119 | return is_last;
|
---|
120 | }
|
---|
121 | if (Array.isArray(a)) {
|
---|
122 | if (backwards) {
|
---|
123 | for (i = a.length; --i >= 0;) if (doit()) break;
|
---|
124 | ret.reverse();
|
---|
125 | top.reverse();
|
---|
126 | } else {
|
---|
127 | for (i = 0; i < a.length; ++i) if (doit()) break;
|
---|
128 | }
|
---|
129 | } else {
|
---|
130 | for (i in a) if (HOP(a, i)) if (doit()) break;
|
---|
131 | }
|
---|
132 | return top.concat(ret);
|
---|
133 | }
|
---|
134 | MAP.at_top = function(val) { return new AtTop(val); };
|
---|
135 | MAP.splice = function(val) { return new Splice(val); };
|
---|
136 | MAP.last = function(val) { return new Last(val); };
|
---|
137 | var skip = MAP.skip = {};
|
---|
138 | function AtTop(val) { this.v = val; }
|
---|
139 | function Splice(val) { this.v = val; }
|
---|
140 | function Last(val) { this.v = val; }
|
---|
141 | return MAP;
|
---|
142 | })();
|
---|
143 |
|
---|
144 | function make_node(ctor, orig, props) {
|
---|
145 | if (!props) props = {};
|
---|
146 | if (orig) {
|
---|
147 | if (!props.start) props.start = orig.start;
|
---|
148 | if (!props.end) props.end = orig.end;
|
---|
149 | }
|
---|
150 | return new ctor(props);
|
---|
151 | }
|
---|
152 |
|
---|
153 | function push_uniq(array, el) {
|
---|
154 | if (!array.includes(el))
|
---|
155 | array.push(el);
|
---|
156 | }
|
---|
157 |
|
---|
158 | function string_template(text, props) {
|
---|
159 | return text.replace(/{(.+?)}/g, function(str, p) {
|
---|
160 | return props && props[p];
|
---|
161 | });
|
---|
162 | }
|
---|
163 |
|
---|
164 | function remove(array, el) {
|
---|
165 | for (var i = array.length; --i >= 0;) {
|
---|
166 | if (array[i] === el) array.splice(i, 1);
|
---|
167 | }
|
---|
168 | }
|
---|
169 |
|
---|
170 | function mergeSort(array, cmp) {
|
---|
171 | if (array.length < 2) return array.slice();
|
---|
172 | function merge(a, b) {
|
---|
173 | var r = [], ai = 0, bi = 0, i = 0;
|
---|
174 | while (ai < a.length && bi < b.length) {
|
---|
175 | cmp(a[ai], b[bi]) <= 0
|
---|
176 | ? r[i++] = a[ai++]
|
---|
177 | : r[i++] = b[bi++];
|
---|
178 | }
|
---|
179 | if (ai < a.length) r.push.apply(r, a.slice(ai));
|
---|
180 | if (bi < b.length) r.push.apply(r, b.slice(bi));
|
---|
181 | return r;
|
---|
182 | }
|
---|
183 | function _ms(a) {
|
---|
184 | if (a.length <= 1)
|
---|
185 | return a;
|
---|
186 | var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
|
---|
187 | left = _ms(left);
|
---|
188 | right = _ms(right);
|
---|
189 | return merge(left, right);
|
---|
190 | }
|
---|
191 | return _ms(array);
|
---|
192 | }
|
---|
193 |
|
---|
194 | function makePredicate(words) {
|
---|
195 | if (!Array.isArray(words)) words = words.split(" ");
|
---|
196 |
|
---|
197 | return new Set(words.sort());
|
---|
198 | }
|
---|
199 |
|
---|
200 | function map_add(map, key, value) {
|
---|
201 | if (map.has(key)) {
|
---|
202 | map.get(key).push(value);
|
---|
203 | } else {
|
---|
204 | map.set(key, [ value ]);
|
---|
205 | }
|
---|
206 | }
|
---|
207 |
|
---|
208 | function map_from_object(obj) {
|
---|
209 | var map = new Map();
|
---|
210 | for (var key in obj) {
|
---|
211 | if (HOP(obj, key) && key.charAt(0) === "$") {
|
---|
212 | map.set(key.substr(1), obj[key]);
|
---|
213 | }
|
---|
214 | }
|
---|
215 | return map;
|
---|
216 | }
|
---|
217 |
|
---|
218 | function map_to_object(map) {
|
---|
219 | var obj = Object.create(null);
|
---|
220 | map.forEach(function (value, key) {
|
---|
221 | obj["$" + key] = value;
|
---|
222 | });
|
---|
223 | return obj;
|
---|
224 | }
|
---|
225 |
|
---|
226 | function HOP(obj, prop) {
|
---|
227 | return Object.prototype.hasOwnProperty.call(obj, prop);
|
---|
228 | }
|
---|
229 |
|
---|
230 | function keep_name(keep_setting, name) {
|
---|
231 | return keep_setting === true
|
---|
232 | || (keep_setting instanceof RegExp && keep_setting.test(name));
|
---|
233 | }
|
---|
234 |
|
---|
235 | var lineTerminatorEscape = {
|
---|
236 | "\0": "0",
|
---|
237 | "\n": "n",
|
---|
238 | "\r": "r",
|
---|
239 | "\u2028": "u2028",
|
---|
240 | "\u2029": "u2029",
|
---|
241 | };
|
---|
242 | function regexp_source_fix(source) {
|
---|
243 | // V8 does not escape line terminators in regexp patterns in node 12
|
---|
244 | // We'll also remove literal \0
|
---|
245 | return source.replace(/[\0\n\r\u2028\u2029]/g, function (match, offset) {
|
---|
246 | var escaped = source[offset - 1] == "\\"
|
---|
247 | && (source[offset - 2] != "\\"
|
---|
248 | || /(?:^|[^\\])(?:\\{2})*$/.test(source.slice(0, offset - 1)));
|
---|
249 | return (escaped ? "" : "\\") + lineTerminatorEscape[match];
|
---|
250 | });
|
---|
251 | }
|
---|
252 | const all_flags = "gimuy";
|
---|
253 | function sort_regexp_flags(flags) {
|
---|
254 | const existing_flags = new Set(flags.split(""));
|
---|
255 | let out = "";
|
---|
256 | for (const flag of all_flags) {
|
---|
257 | if (existing_flags.has(flag)) {
|
---|
258 | out += flag;
|
---|
259 | existing_flags.delete(flag);
|
---|
260 | }
|
---|
261 | }
|
---|
262 | if (existing_flags.size) {
|
---|
263 | // Flags Terser doesn't know about
|
---|
264 | existing_flags.forEach(flag => { out += flag; });
|
---|
265 | }
|
---|
266 | return out;
|
---|
267 | }
|
---|
268 |
|
---|
269 | function has_annotation(node, annotation) {
|
---|
270 | return node._annotations & annotation;
|
---|
271 | }
|
---|
272 |
|
---|
273 | function set_annotation(node, annotation) {
|
---|
274 | node._annotations |= annotation;
|
---|
275 | }
|
---|
276 |
|
---|
277 | export {
|
---|
278 | characters,
|
---|
279 | defaults,
|
---|
280 | HOP,
|
---|
281 | keep_name,
|
---|
282 | make_node,
|
---|
283 | makePredicate,
|
---|
284 | map_add,
|
---|
285 | map_from_object,
|
---|
286 | map_to_object,
|
---|
287 | MAP,
|
---|
288 | member,
|
---|
289 | mergeSort,
|
---|
290 | noop,
|
---|
291 | push_uniq,
|
---|
292 | regexp_source_fix,
|
---|
293 | remove,
|
---|
294 | return_false,
|
---|
295 | return_null,
|
---|
296 | return_this,
|
---|
297 | return_true,
|
---|
298 | sort_regexp_flags,
|
---|
299 | string_template,
|
---|
300 | has_annotation,
|
---|
301 | set_annotation
|
---|
302 | };
|
---|