You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					311 lines
				
				8.7 KiB
			
		
		
			
		
	
	
					311 lines
				
				8.7 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								/***********************************************************************
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  A JavaScript tokenizer / parser / beautifier / compressor.
							 | 
						||
| 
								 | 
							
								  https://github.com/mishoo/UglifyJS2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  -------------------------------- (C) ---------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                           Author: Mihai Bazon
							 | 
						||
| 
								 | 
							
								                         <mihai.bazon@gmail.com>
							 | 
						||
| 
								 | 
							
								                       http://mihai.bazon.net/blog
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Distributed under the BSD license:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Redistribution and use in source and binary forms, with or without
							 | 
						||
| 
								 | 
							
								    modification, are permitted provided that the following conditions
							 | 
						||
| 
								 | 
							
								    are met:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * Redistributions of source code must retain the above
							 | 
						||
| 
								 | 
							
								          copyright notice, this list of conditions and the following
							 | 
						||
| 
								 | 
							
								          disclaimer.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * Redistributions in binary form must reproduce the above
							 | 
						||
| 
								 | 
							
								          copyright notice, this list of conditions and the following
							 | 
						||
| 
								 | 
							
								          disclaimer in the documentation and/or other materials
							 | 
						||
| 
								 | 
							
								          provided with the distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
							 | 
						||
| 
								 | 
							
								    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
							 | 
						||
| 
								 | 
							
								    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
							 | 
						||
| 
								 | 
							
								    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
							 | 
						||
| 
								 | 
							
								    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
							 | 
						||
| 
								 | 
							
								    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
							 | 
						||
| 
								 | 
							
								    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
							 | 
						||
| 
								 | 
							
								    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
							 | 
						||
| 
								 | 
							
								    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
							 | 
						||
| 
								 | 
							
								    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
							 | 
						||
| 
								 | 
							
								    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
							 | 
						||
| 
								 | 
							
								    SUCH DAMAGE.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								 ***********************************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function characters(str) {
							 | 
						||
| 
								 | 
							
								    return str.split("");
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function member(name, array) {
							 | 
						||
| 
								 | 
							
								    return array.includes(name);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class DefaultsError extends Error {
							 | 
						||
| 
								 | 
							
								    constructor(msg, defs) {
							 | 
						||
| 
								 | 
							
								        super();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        this.name = "DefaultsError";
							 | 
						||
| 
								 | 
							
								        this.message = msg;
							 | 
						||
| 
								 | 
							
								        this.defs = defs;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function defaults(args, defs, croak) {
							 | 
						||
| 
								 | 
							
								    if (args === true) {
							 | 
						||
| 
								 | 
							
								        args = {};
							 | 
						||
| 
								 | 
							
								    } else if (args != null && typeof args === "object") {
							 | 
						||
| 
								 | 
							
								        args = {...args};
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const ret = args || {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (croak) for (const i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
							 | 
						||
| 
								 | 
							
								        throw new DefaultsError("`" + i + "` is not a supported option", defs);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (const i in defs) if (HOP(defs, i)) {
							 | 
						||
| 
								 | 
							
								        if (!args || !HOP(args, i)) {
							 | 
						||
| 
								 | 
							
								            ret[i] = defs[i];
							 | 
						||
| 
								 | 
							
								        } else if (i === "ecma") {
							 | 
						||
| 
								 | 
							
								            let ecma = args[i] | 0;
							 | 
						||
| 
								 | 
							
								            if (ecma > 5 && ecma < 2015) ecma += 2009;
							 | 
						||
| 
								 | 
							
								            ret[i] = ecma;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function noop() {}
							 | 
						||
| 
								 | 
							
								function return_false() { return false; }
							 | 
						||
| 
								 | 
							
								function return_true() { return true; }
							 | 
						||
| 
								 | 
							
								function return_this() { return this; }
							 | 
						||
| 
								 | 
							
								function return_null() { return null; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var MAP = (function() {
							 | 
						||
| 
								 | 
							
								    function MAP(a, f, backwards) {
							 | 
						||
| 
								 | 
							
								        var ret = [], top = [], i;
							 | 
						||
| 
								 | 
							
								        function doit() {
							 | 
						||
| 
								 | 
							
								            var val = f(a[i], i);
							 | 
						||
| 
								 | 
							
								            var is_last = val instanceof Last;
							 | 
						||
| 
								 | 
							
								            if (is_last) val = val.v;
							 | 
						||
| 
								 | 
							
								            if (val instanceof AtTop) {
							 | 
						||
| 
								 | 
							
								                val = val.v;
							 | 
						||
| 
								 | 
							
								                if (val instanceof Splice) {
							 | 
						||
| 
								 | 
							
								                    top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
							 | 
						||
| 
								 | 
							
								                } else {
							 | 
						||
| 
								 | 
							
								                    top.push(val);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            } else if (val !== skip) {
							 | 
						||
| 
								 | 
							
								                if (val instanceof Splice) {
							 | 
						||
| 
								 | 
							
								                    ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
							 | 
						||
| 
								 | 
							
								                } else {
							 | 
						||
| 
								 | 
							
								                    ret.push(val);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            return is_last;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (Array.isArray(a)) {
							 | 
						||
| 
								 | 
							
								            if (backwards) {
							 | 
						||
| 
								 | 
							
								                for (i = a.length; --i >= 0;) if (doit()) break;
							 | 
						||
| 
								 | 
							
								                ret.reverse();
							 | 
						||
| 
								 | 
							
								                top.reverse();
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                for (i = 0; i < a.length; ++i) if (doit()) break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            for (i in a) if (HOP(a, i)) if (doit()) break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return top.concat(ret);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    MAP.at_top = function(val) { return new AtTop(val); };
							 | 
						||
| 
								 | 
							
								    MAP.splice = function(val) { return new Splice(val); };
							 | 
						||
| 
								 | 
							
								    MAP.last = function(val) { return new Last(val); };
							 | 
						||
| 
								 | 
							
								    var skip = MAP.skip = {};
							 | 
						||
| 
								 | 
							
								    function AtTop(val) { this.v = val; }
							 | 
						||
| 
								 | 
							
								    function Splice(val) { this.v = val; }
							 | 
						||
| 
								 | 
							
								    function Last(val) { this.v = val; }
							 | 
						||
| 
								 | 
							
								    return MAP;
							 | 
						||
| 
								 | 
							
								})();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function make_node(ctor, orig, props) {
							 | 
						||
| 
								 | 
							
								    if (!props) props = {};
							 | 
						||
| 
								 | 
							
								    if (orig) {
							 | 
						||
| 
								 | 
							
								        if (!props.start) props.start = orig.start;
							 | 
						||
| 
								 | 
							
								        if (!props.end) props.end = orig.end;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return new ctor(props);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function push_uniq(array, el) {
							 | 
						||
| 
								 | 
							
								    if (!array.includes(el))
							 | 
						||
| 
								 | 
							
								        array.push(el);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function string_template(text, props) {
							 | 
						||
| 
								 | 
							
								    return text.replace(/{(.+?)}/g, function(str, p) {
							 | 
						||
| 
								 | 
							
								        return props && props[p];
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function remove(array, el) {
							 | 
						||
| 
								 | 
							
								    for (var i = array.length; --i >= 0;) {
							 | 
						||
| 
								 | 
							
								        if (array[i] === el) array.splice(i, 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function mergeSort(array, cmp) {
							 | 
						||
| 
								 | 
							
								    if (array.length < 2) return array.slice();
							 | 
						||
| 
								 | 
							
								    function merge(a, b) {
							 | 
						||
| 
								 | 
							
								        var r = [], ai = 0, bi = 0, i = 0;
							 | 
						||
| 
								 | 
							
								        while (ai < a.length && bi < b.length) {
							 | 
						||
| 
								 | 
							
								            cmp(a[ai], b[bi]) <= 0
							 | 
						||
| 
								 | 
							
								                ? r[i++] = a[ai++]
							 | 
						||
| 
								 | 
							
								                : r[i++] = b[bi++];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (ai < a.length) r.push.apply(r, a.slice(ai));
							 | 
						||
| 
								 | 
							
								        if (bi < b.length) r.push.apply(r, b.slice(bi));
							 | 
						||
| 
								 | 
							
								        return r;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    function _ms(a) {
							 | 
						||
| 
								 | 
							
								        if (a.length <= 1)
							 | 
						||
| 
								 | 
							
								            return a;
							 | 
						||
| 
								 | 
							
								        var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
							 | 
						||
| 
								 | 
							
								        left = _ms(left);
							 | 
						||
| 
								 | 
							
								        right = _ms(right);
							 | 
						||
| 
								 | 
							
								        return merge(left, right);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return _ms(array);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function makePredicate(words) {
							 | 
						||
| 
								 | 
							
								    if (!Array.isArray(words)) words = words.split(" ");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return new Set(words.sort());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function map_add(map, key, value) {
							 | 
						||
| 
								 | 
							
								    if (map.has(key)) {
							 | 
						||
| 
								 | 
							
								        map.get(key).push(value);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        map.set(key, [ value ]);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function map_from_object(obj) {
							 | 
						||
| 
								 | 
							
								    var map = new Map();
							 | 
						||
| 
								 | 
							
								    for (var key in obj) {
							 | 
						||
| 
								 | 
							
								        if (HOP(obj, key) && key.charAt(0) === "$") {
							 | 
						||
| 
								 | 
							
								            map.set(key.substr(1), obj[key]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return map;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function map_to_object(map) {
							 | 
						||
| 
								 | 
							
								    var obj = Object.create(null);
							 | 
						||
| 
								 | 
							
								    map.forEach(function (value, key) {
							 | 
						||
| 
								 | 
							
								        obj["$" + key] = value;
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    return obj;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function HOP(obj, prop) {
							 | 
						||
| 
								 | 
							
								    return Object.prototype.hasOwnProperty.call(obj, prop);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function keep_name(keep_setting, name) {
							 | 
						||
| 
								 | 
							
								    return keep_setting === true
							 | 
						||
| 
								 | 
							
								        || (keep_setting instanceof RegExp && keep_setting.test(name));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var lineTerminatorEscape = {
							 | 
						||
| 
								 | 
							
								    "\0": "0",
							 | 
						||
| 
								 | 
							
								    "\n": "n",
							 | 
						||
| 
								 | 
							
								    "\r": "r",
							 | 
						||
| 
								 | 
							
								    "\u2028": "u2028",
							 | 
						||
| 
								 | 
							
								    "\u2029": "u2029",
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								function regexp_source_fix(source) {
							 | 
						||
| 
								 | 
							
								    // V8 does not escape line terminators in regexp patterns in node 12
							 | 
						||
| 
								 | 
							
								    // We'll also remove literal \0
							 | 
						||
| 
								 | 
							
								    return source.replace(/[\0\n\r\u2028\u2029]/g, function (match, offset) {
							 | 
						||
| 
								 | 
							
								        var escaped = source[offset - 1] == "\\"
							 | 
						||
| 
								 | 
							
								            && (source[offset - 2] != "\\"
							 | 
						||
| 
								 | 
							
								            || /(?:^|[^\\])(?:\\{2})*$/.test(source.slice(0, offset - 1)));
							 | 
						||
| 
								 | 
							
								        return (escaped ? "" : "\\") + lineTerminatorEscape[match];
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Subset of regexps that is not going to cause regexp based DDOS
							 | 
						||
| 
								 | 
							
								// https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
							 | 
						||
| 
								 | 
							
								const re_safe_regexp = /^[\\/|\0\s\w^$.[\]()]*$/;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Check if the regexp is safe for Terser to create without risking a RegExp DOS */
							 | 
						||
| 
								 | 
							
								export const regexp_is_safe = (source) => re_safe_regexp.test(source);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const all_flags = "dgimsuy";
							 | 
						||
| 
								 | 
							
								function sort_regexp_flags(flags) {
							 | 
						||
| 
								 | 
							
								    const existing_flags = new Set(flags.split(""));
							 | 
						||
| 
								 | 
							
								    let out = "";
							 | 
						||
| 
								 | 
							
								    for (const flag of all_flags) {
							 | 
						||
| 
								 | 
							
								        if (existing_flags.has(flag)) {
							 | 
						||
| 
								 | 
							
								            out += flag;
							 | 
						||
| 
								 | 
							
								            existing_flags.delete(flag);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (existing_flags.size) {
							 | 
						||
| 
								 | 
							
								        // Flags Terser doesn't know about
							 | 
						||
| 
								 | 
							
								        existing_flags.forEach(flag => { out += flag; });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return out;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function has_annotation(node, annotation) {
							 | 
						||
| 
								 | 
							
								    return node._annotations & annotation;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function set_annotation(node, annotation) {
							 | 
						||
| 
								 | 
							
								    node._annotations |= annotation;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export {
							 | 
						||
| 
								 | 
							
								    characters,
							 | 
						||
| 
								 | 
							
								    defaults,
							 | 
						||
| 
								 | 
							
								    HOP,
							 | 
						||
| 
								 | 
							
								    keep_name,
							 | 
						||
| 
								 | 
							
								    make_node,
							 | 
						||
| 
								 | 
							
								    makePredicate,
							 | 
						||
| 
								 | 
							
								    map_add,
							 | 
						||
| 
								 | 
							
								    map_from_object,
							 | 
						||
| 
								 | 
							
								    map_to_object,
							 | 
						||
| 
								 | 
							
								    MAP,
							 | 
						||
| 
								 | 
							
								    member,
							 | 
						||
| 
								 | 
							
								    mergeSort,
							 | 
						||
| 
								 | 
							
								    noop,
							 | 
						||
| 
								 | 
							
								    push_uniq,
							 | 
						||
| 
								 | 
							
								    regexp_source_fix,
							 | 
						||
| 
								 | 
							
								    remove,
							 | 
						||
| 
								 | 
							
								    return_false,
							 | 
						||
| 
								 | 
							
								    return_null,
							 | 
						||
| 
								 | 
							
								    return_this,
							 | 
						||
| 
								 | 
							
								    return_true,
							 | 
						||
| 
								 | 
							
								    sort_regexp_flags,
							 | 
						||
| 
								 | 
							
								    string_template,
							 | 
						||
| 
								 | 
							
								    has_annotation,
							 | 
						||
| 
								 | 
							
								    set_annotation
							 | 
						||
| 
								 | 
							
								};
							 |