summaryrefslogtreecommitdiff
path: root/node_modules/terser/lib/compress/common.js
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2023-10-31 15:37:35 +0800
committerlittleblack111 <littleblack11111@gmail.com>2023-10-31 15:37:35 +0800
commitd5f14083061f2ce6a42313188443a42e30796320 (patch)
treecc6a9889e08b29595a76a33b9e7b4ef84866468b /node_modules/terser/lib/compress/common.js
parentb1a6ea021f29f182b62f9f81024a3d8ac8621b7f (diff)
added make browserlist(autoprefixer) work fixed
Diffstat (limited to 'node_modules/terser/lib/compress/common.js')
-rw-r--r--node_modules/terser/lib/compress/common.js348
1 files changed, 348 insertions, 0 deletions
diff --git a/node_modules/terser/lib/compress/common.js b/node_modules/terser/lib/compress/common.js
new file mode 100644
index 00000000..0b6cac51
--- /dev/null
+++ b/node_modules/terser/lib/compress/common.js
@@ -0,0 +1,348 @@
+/***********************************************************************
+
+ 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.
+
+ ***********************************************************************/
+
+import {
+ AST_Array,
+ AST_Arrow,
+ AST_BlockStatement,
+ AST_Call,
+ AST_Chain,
+ AST_Class,
+ AST_Const,
+ AST_Constant,
+ AST_DefClass,
+ AST_Defun,
+ AST_EmptyStatement,
+ AST_Export,
+ AST_False,
+ AST_Function,
+ AST_Import,
+ AST_Infinity,
+ AST_LabeledStatement,
+ AST_Lambda,
+ AST_Let,
+ AST_LoopControl,
+ AST_NaN,
+ AST_Node,
+ AST_Null,
+ AST_Number,
+ AST_Object,
+ AST_ObjectKeyVal,
+ AST_PropAccess,
+ AST_RegExp,
+ AST_Scope,
+ AST_Sequence,
+ AST_SimpleStatement,
+ AST_Statement,
+ AST_String,
+ AST_SymbolRef,
+ AST_True,
+ AST_UnaryPrefix,
+ AST_Undefined,
+
+ TreeWalker,
+ walk,
+ walk_abort,
+ walk_parent,
+} from "../ast.js";
+import { make_node, regexp_source_fix, string_template, makePredicate } from "../utils/index.js";
+import { first_in_statement } from "../utils/first_in_statement.js";
+import { has_flag, TOP } from "./compressor-flags.js";
+
+export function merge_sequence(array, node) {
+ if (node instanceof AST_Sequence) {
+ array.push(...node.expressions);
+ } else {
+ array.push(node);
+ }
+ return array;
+}
+
+export function make_sequence(orig, expressions) {
+ if (expressions.length == 1) return expressions[0];
+ if (expressions.length == 0) throw new Error("trying to create a sequence with length zero!");
+ return make_node(AST_Sequence, orig, {
+ expressions: expressions.reduce(merge_sequence, [])
+ });
+}
+
+export function make_node_from_constant(val, orig) {
+ switch (typeof val) {
+ case "string":
+ return make_node(AST_String, orig, {
+ value: val
+ });
+ case "number":
+ if (isNaN(val)) return make_node(AST_NaN, orig);
+ if (isFinite(val)) {
+ return 1 / val < 0 ? make_node(AST_UnaryPrefix, orig, {
+ operator: "-",
+ expression: make_node(AST_Number, orig, { value: -val })
+ }) : make_node(AST_Number, orig, { value: val });
+ }
+ return val < 0 ? make_node(AST_UnaryPrefix, orig, {
+ operator: "-",
+ expression: make_node(AST_Infinity, orig)
+ }) : make_node(AST_Infinity, orig);
+ case "boolean":
+ return make_node(val ? AST_True : AST_False, orig);
+ case "undefined":
+ return make_node(AST_Undefined, orig);
+ default:
+ if (val === null) {
+ return make_node(AST_Null, orig, { value: null });
+ }
+ if (val instanceof RegExp) {
+ return make_node(AST_RegExp, orig, {
+ value: {
+ source: regexp_source_fix(val.source),
+ flags: val.flags
+ }
+ });
+ }
+ throw new Error(string_template("Can't handle constant of type: {type}", {
+ type: typeof val
+ }));
+ }
+}
+
+export function best_of_expression(ast1, ast2) {
+ return ast1.size() > ast2.size() ? ast2 : ast1;
+}
+
+export function best_of_statement(ast1, ast2) {
+ return best_of_expression(
+ make_node(AST_SimpleStatement, ast1, {
+ body: ast1
+ }),
+ make_node(AST_SimpleStatement, ast2, {
+ body: ast2
+ })
+ ).body;
+}
+
+/** Find which node is smaller, and return that */
+export function best_of(compressor, ast1, ast2) {
+ if (first_in_statement(compressor)) {
+ return best_of_statement(ast1, ast2);
+ } else {
+ return best_of_expression(ast1, ast2);
+ }
+}
+
+/** Simplify an object property's key, if possible */
+export function get_simple_key(key) {
+ if (key instanceof AST_Constant) {
+ return key.getValue();
+ }
+ if (key instanceof AST_UnaryPrefix
+ && key.operator == "void"
+ && key.expression instanceof AST_Constant) {
+ return;
+ }
+ return key;
+}
+
+export function read_property(obj, key) {
+ key = get_simple_key(key);
+ if (key instanceof AST_Node) return;
+
+ var value;
+ if (obj instanceof AST_Array) {
+ var elements = obj.elements;
+ if (key == "length") return make_node_from_constant(elements.length, obj);
+ if (typeof key == "number" && key in elements) value = elements[key];
+ } else if (obj instanceof AST_Object) {
+ key = "" + key;
+ var props = obj.properties;
+ for (var i = props.length; --i >= 0;) {
+ var prop = props[i];
+ if (!(prop instanceof AST_ObjectKeyVal)) return;
+ if (!value && props[i].key === key) value = props[i].value;
+ }
+ }
+
+ return value instanceof AST_SymbolRef && value.fixed_value() || value;
+}
+
+export function has_break_or_continue(loop, parent) {
+ var found = false;
+ var tw = new TreeWalker(function(node) {
+ if (found || node instanceof AST_Scope) return true;
+ if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === loop) {
+ return found = true;
+ }
+ });
+ if (parent instanceof AST_LabeledStatement) tw.push(parent);
+ tw.push(loop);
+ loop.body.walk(tw);
+ return found;
+}
+
+// we shouldn't compress (1,func)(something) to
+// func(something) because that changes the meaning of
+// the func (becomes lexical instead of global).
+export function maintain_this_binding(parent, orig, val) {
+ if (
+ parent instanceof AST_UnaryPrefix && parent.operator == "delete"
+ || parent instanceof AST_Call && parent.expression === orig
+ && (
+ val instanceof AST_Chain
+ || val instanceof AST_PropAccess
+ || val instanceof AST_SymbolRef && val.name == "eval"
+ )
+ ) {
+ const zero = make_node(AST_Number, orig, { value: 0 });
+ return make_sequence(orig, [ zero, val ]);
+ } else {
+ return val;
+ }
+}
+
+export function is_func_expr(node) {
+ return node instanceof AST_Arrow || node instanceof AST_Function;
+}
+
+/**
+ * Used to determine whether the node can benefit from negation.
+ * Not the case with arrow functions (you need an extra set of parens). */
+export function is_iife_call(node) {
+ if (node.TYPE != "Call") return false;
+ return node.expression instanceof AST_Function || is_iife_call(node.expression);
+}
+
+export function is_empty(thing) {
+ if (thing === null) return true;
+ if (thing instanceof AST_EmptyStatement) return true;
+ if (thing instanceof AST_BlockStatement) return thing.body.length == 0;
+ return false;
+}
+
+export const identifier_atom = makePredicate("Infinity NaN undefined");
+export function is_identifier_atom(node) {
+ return node instanceof AST_Infinity
+ || node instanceof AST_NaN
+ || node instanceof AST_Undefined;
+}
+
+/** Check if this is a SymbolRef node which has one def of a certain AST type */
+export function is_ref_of(ref, type) {
+ if (!(ref instanceof AST_SymbolRef)) return false;
+ var orig = ref.definition().orig;
+ for (var i = orig.length; --i >= 0;) {
+ if (orig[i] instanceof type) return true;
+ }
+}
+
+/**Can we turn { block contents... } into just the block contents ?
+ * Not if one of these is inside.
+ **/
+export function can_be_evicted_from_block(node) {
+ return !(
+ node instanceof AST_DefClass ||
+ node instanceof AST_Defun ||
+ node instanceof AST_Let ||
+ node instanceof AST_Const ||
+ node instanceof AST_Export ||
+ node instanceof AST_Import
+ );
+}
+
+export function as_statement_array(thing) {
+ if (thing === null) return [];
+ if (thing instanceof AST_BlockStatement) return thing.body;
+ if (thing instanceof AST_EmptyStatement) return [];
+ if (thing instanceof AST_Statement) return [ thing ];
+ throw new Error("Can't convert thing to statement array");
+}
+
+export function is_reachable(scope_node, defs) {
+ const find_ref = node => {
+ if (node instanceof AST_SymbolRef && defs.includes(node.definition())) {
+ return walk_abort;
+ }
+ };
+
+ return walk_parent(scope_node, (node, info) => {
+ if (node instanceof AST_Scope && node !== scope_node) {
+ var parent = info.parent();
+
+ if (
+ parent instanceof AST_Call
+ && parent.expression === node
+ // Async/Generators aren't guaranteed to sync evaluate all of
+ // their body steps, so it's possible they close over the variable.
+ && !(node.async || node.is_generator)
+ ) {
+ return;
+ }
+
+ if (walk(node, find_ref)) return walk_abort;
+
+ return true;
+ }
+ });
+}
+
+/** Check if a ref refers to the name of a function/class it's defined within */
+export function is_recursive_ref(compressor, def) {
+ var node;
+ for (var i = 0; node = compressor.parent(i); i++) {
+ if (node instanceof AST_Lambda || node instanceof AST_Class) {
+ var name = node.name;
+ if (name && name.definition() === def) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// TODO this only works with AST_Defun, shouldn't it work for other ways of defining functions?
+export function retain_top_func(fn, compressor) {
+ return compressor.top_retain
+ && fn instanceof AST_Defun
+ && has_flag(fn, TOP)
+ && fn.name
+ && compressor.top_retain(fn.name.definition());
+}