UNPKG

8.46 kBJavaScriptView Raw
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
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 (args === true) args = {};
91 var ret = args || {};
92 if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
93 throw new DefaultsError("`" + i + "` is not a supported option", defs);
94 }
95 for (var i in defs) if (HOP(defs, i)) {
96 ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
97 }
98 return ret;
99}
100
101function merge(obj, ext) {
102 var count = 0;
103 for (var i in ext) if (HOP(ext, i)) {
104 obj[i] = ext[i];
105 count++;
106 }
107 return count;
108}
109
110function noop() {}
111function return_false() { return false; }
112function return_true() { return true; }
113function return_this() { return this; }
114function return_null() { return null; }
115
116var MAP = (function() {
117 function MAP(a, f, backwards) {
118 var ret = [], top = [], i;
119 function doit() {
120 var val = f(a[i], i);
121 var is_last = val instanceof Last;
122 if (is_last) val = val.v;
123 if (val instanceof AtTop) {
124 val = val.v;
125 if (val instanceof Splice) {
126 top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
127 } else {
128 top.push(val);
129 }
130 } else if (val !== skip) {
131 if (val instanceof Splice) {
132 ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
133 } else {
134 ret.push(val);
135 }
136 }
137 return is_last;
138 }
139 if (Array.isArray(a)) {
140 if (backwards) {
141 for (i = a.length; --i >= 0;) if (doit()) break;
142 ret.reverse();
143 top.reverse();
144 } else {
145 for (i = 0; i < a.length; ++i) if (doit()) break;
146 }
147 } else {
148 for (i in a) if (HOP(a, i)) if (doit()) break;
149 }
150 return top.concat(ret);
151 }
152 MAP.at_top = function(val) { return new AtTop(val) };
153 MAP.splice = function(val) { return new Splice(val) };
154 MAP.last = function(val) { return new Last(val) };
155 var skip = MAP.skip = {};
156 function AtTop(val) { this.v = val }
157 function Splice(val) { this.v = val }
158 function Last(val) { this.v = val }
159 return MAP;
160})();
161
162function push_uniq(array, el) {
163 if (array.indexOf(el) < 0) return array.push(el);
164}
165
166function string_template(text, props) {
167 return text.replace(/\{(.+?)\}/g, function(str, p) {
168 return props && props[p];
169 });
170}
171
172function remove(array, el) {
173 var index = array.indexOf(el);
174 if (index >= 0) array.splice(index, 1);
175}
176
177function makePredicate(words) {
178 if (!Array.isArray(words)) words = words.split(" ");
179 var map = Object.create(null);
180 words.forEach(function(word) {
181 map[word] = true;
182 });
183 return map;
184}
185
186function all(array, predicate) {
187 for (var i = array.length; --i >= 0;)
188 if (!predicate(array[i]))
189 return false;
190 return true;
191}
192
193function Dictionary() {
194 this._values = Object.create(null);
195 this._size = 0;
196}
197Dictionary.prototype = {
198 set: function(key, val) {
199 if (!this.has(key)) ++this._size;
200 this._values["$" + key] = val;
201 return this;
202 },
203 add: function(key, val) {
204 if (this.has(key)) {
205 this.get(key).push(val);
206 } else {
207 this.set(key, [ val ]);
208 }
209 return this;
210 },
211 get: function(key) { return this._values["$" + key] },
212 del: function(key) {
213 if (this.has(key)) {
214 --this._size;
215 delete this._values["$" + key];
216 }
217 return this;
218 },
219 has: function(key) { return ("$" + key) in this._values },
220 each: function(f) {
221 for (var i in this._values)
222 f(this._values[i], i.substr(1));
223 },
224 size: function() {
225 return this._size;
226 },
227 map: function(f) {
228 var ret = [];
229 for (var i in this._values)
230 ret.push(f(this._values[i], i.substr(1)));
231 return ret;
232 },
233 clone: function() {
234 var ret = new Dictionary();
235 for (var i in this._values)
236 ret._values[i] = this._values[i];
237 ret._size = this._size;
238 return ret;
239 },
240 toObject: function() { return this._values }
241};
242Dictionary.fromObject = function(obj) {
243 var dict = new Dictionary();
244 dict._size = merge(dict._values, obj);
245 return dict;
246};
247
248function HOP(obj, prop) {
249 return Object.prototype.hasOwnProperty.call(obj, prop);
250}
251
252// return true if the node at the top of the stack (that means the
253// innermost node in the current output) is lexically the first in
254// a statement.
255function first_in_statement(stack) {
256 var node = stack.parent(-1);
257 for (var i = 0, p; p = stack.parent(i++); node = p) {
258 if (p.TYPE == "Call") {
259 if (p.expression === node) continue;
260 } else if (p instanceof AST_Binary) {
261 if (p.left === node) continue;
262 } else if (p instanceof AST_Conditional) {
263 if (p.condition === node) continue;
264 } else if (p instanceof AST_PropAccess) {
265 if (p.expression === node) continue;
266 } else if (p instanceof AST_Sequence) {
267 if (p.expressions[0] === node) continue;
268 } else if (p instanceof AST_Statement) {
269 return p.body === node;
270 } else if (p instanceof AST_UnaryPostfix) {
271 if (p.expression === node) continue;
272 }
273 return false;
274 }
275}