UNPKG

8.91 kBJavaScriptView Raw
1/***********************************************************************
2
3 A JavaScript tokenizer / parser / beautifier / compressor.
4 https://github.com/mishoo/UglifyJS
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
46function characters(str) {
47 return str.split("");
48}
49
50function member(name, array) {
51 return array.indexOf(name) >= 0;
52}
53
54function find_if(func, array) {
55 for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];
56}
57
58function repeat_string(str, i) {
59 if (i <= 0) return "";
60 if (i == 1) return str;
61 var d = repeat_string(str, i >> 1);
62 d += d;
63 return i & 1 ? d + str : d;
64}
65
66function configure_error_stack(fn) {
67 Object.defineProperty(fn.prototype, "stack", {
68 get: function() {
69 var err = new Error(this.message);
70 err.name = this.name;
71 try {
72 throw err;
73 } catch (e) {
74 return e.stack;
75 }
76 }
77 });
78}
79
80function DefaultsError(msg, defs) {
81 this.message = msg;
82 this.defs = defs;
83}
84DefaultsError.prototype = Object.create(Error.prototype);
85DefaultsError.prototype.constructor = DefaultsError;
86DefaultsError.prototype.name = "DefaultsError";
87configure_error_stack(DefaultsError);
88
89function defaults(args, defs, croak) {
90 if (croak) for (var i in args) {
91 if (HOP(args, i) && !HOP(defs, i)) throw new DefaultsError("`" + i + "` is not a supported option", defs);
92 }
93 for (var i in args) {
94 if (HOP(args, i)) defs[i] = args[i];
95 }
96 return defs;
97}
98
99function noop() {}
100function return_false() { return false; }
101function return_true() { return true; }
102function return_this() { return this; }
103function return_null() { return null; }
104
105var List = (function() {
106 function List(a, f) {
107 var ret = [];
108 for (var i = 0; i < a.length; i++) {
109 var val = f(a[i], i);
110 if (val === skip) continue;
111 if (val instanceof Splice) {
112 ret.push.apply(ret, val.v);
113 } else {
114 ret.push(val);
115 }
116 }
117 return ret;
118 }
119 List.is_op = function(val) {
120 return val === skip || val instanceof Splice;
121 };
122 List.splice = function(val) {
123 return new Splice(val);
124 };
125 var skip = List.skip = {};
126 function Splice(val) {
127 this.v = val;
128 }
129 return List;
130})();
131
132function push_uniq(array, el) {
133 if (array.indexOf(el) < 0) return array.push(el);
134}
135
136function string_template(text, props) {
137 return text.replace(/\{([^{}]+)\}/g, function(str, p) {
138 var value = props[p];
139 return value instanceof AST_Node ? value.print_to_string() : value;
140 });
141}
142
143function remove(array, el) {
144 var index = array.indexOf(el);
145 if (index >= 0) array.splice(index, 1);
146}
147
148function makePredicate(words) {
149 if (!Array.isArray(words)) words = words.split(" ");
150 var map = Object.create(null);
151 words.forEach(function(word) {
152 map[word] = true;
153 });
154 return map;
155}
156
157function all(array, predicate) {
158 for (var i = array.length; --i >= 0;)
159 if (!predicate(array[i], i))
160 return false;
161 return true;
162}
163
164function Dictionary() {
165 this.values = Object.create(null);
166}
167Dictionary.prototype = {
168 set: function(key, val) {
169 if (key == "__proto__") {
170 this.proto_value = val;
171 } else {
172 this.values[key] = val;
173 }
174 return this;
175 },
176 add: function(key, val) {
177 var list = this.get(key);
178 if (list) {
179 list.push(val);
180 } else {
181 this.set(key, [ val ]);
182 }
183 return this;
184 },
185 get: function(key) {
186 return key == "__proto__" ? this.proto_value : this.values[key];
187 },
188 del: function(key) {
189 if (key == "__proto__") {
190 delete this.proto_value;
191 } else {
192 delete this.values[key];
193 }
194 return this;
195 },
196 has: function(key) {
197 return key == "__proto__" ? "proto_value" in this : key in this.values;
198 },
199 all: function(predicate) {
200 for (var i in this.values)
201 if (!predicate(this.values[i], i)) return false;
202 if ("proto_value" in this && !predicate(this.proto_value, "__proto__")) return false;
203 return true;
204 },
205 each: function(f) {
206 for (var i in this.values)
207 f(this.values[i], i);
208 if ("proto_value" in this) f(this.proto_value, "__proto__");
209 },
210 size: function() {
211 return Object.keys(this.values).length + ("proto_value" in this);
212 },
213 map: function(f) {
214 var ret = [];
215 for (var i in this.values)
216 ret.push(f(this.values[i], i));
217 if ("proto_value" in this) ret.push(f(this.proto_value, "__proto__"));
218 return ret;
219 },
220 clone: function() {
221 var ret = new Dictionary();
222 this.each(function(value, i) {
223 ret.set(i, value);
224 });
225 return ret;
226 },
227 toObject: function() {
228 var obj = {};
229 this.each(function(value, i) {
230 obj["$" + i] = value;
231 });
232 return obj;
233 },
234};
235Dictionary.fromObject = function(obj) {
236 var dict = new Dictionary();
237 for (var i in obj)
238 if (HOP(obj, i)) dict.set(i.slice(1), obj[i]);
239 return dict;
240};
241
242function HOP(obj, prop) {
243 return Object.prototype.hasOwnProperty.call(obj, prop);
244}
245
246// return true if the node at the top of the stack (that means the
247// innermost node in the current output) is lexically the first in
248// a statement.
249function first_in_statement(stack, arrow, export_default) {
250 var node = stack.parent(-1);
251 for (var i = 0, p; p = stack.parent(i++); node = p) {
252 if (is_arrow(p)) {
253 return arrow && p.value === node;
254 } else if (p instanceof AST_Binary) {
255 if (p.left === node) continue;
256 } else if (p.TYPE == "Call") {
257 if (p.expression === node) continue;
258 } else if (p instanceof AST_Conditional) {
259 if (p.condition === node) continue;
260 } else if (p instanceof AST_ExportDefault) {
261 return export_default;
262 } else if (p instanceof AST_PropAccess) {
263 if (p.expression === node) continue;
264 } else if (p instanceof AST_Sequence) {
265 if (p.expressions[0] === node) continue;
266 } else if (p instanceof AST_SimpleStatement) {
267 return true;
268 } else if (p instanceof AST_Template) {
269 if (p.tag === node) continue;
270 } else if (p instanceof AST_UnaryPostfix) {
271 if (p.expression === node) continue;
272 }
273 return false;
274 }
275}
276
277function DEF_BITPROPS(ctor, props) {
278 if (props.length > 31) throw new Error("Too many properties: " + props.length + "\n" + props.join(", "));
279 props.forEach(function(name, pos) {
280 var mask = 1 << pos;
281 Object.defineProperty(ctor.prototype, name, {
282 get: function() {
283 return !!(this._bits & mask);
284 },
285 set: function(val) {
286 if (val)
287 this._bits |= mask;
288 else
289 this._bits &= ~mask;
290 },
291 });
292 });
293}