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