dina-agi
Version:
DINA AGI - Dynamic Intelligence Network Architecture. 128 Autonomous Agents with Claude Flow, Swarms, and 300+ MCPs. True AGI System.
1,203 lines (1,142 loc) • 654 kB
JavaScript
/***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS
-------------------------------- (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 Compressor(options, false_by_default) {
if (!(this instanceof Compressor))
return new Compressor(options, false_by_default);
TreeTransformer.call(this, this.before, this.after);
this.options = defaults(options, {
annotations : !false_by_default,
arguments : !false_by_default,
arrows : !false_by_default,
assignments : !false_by_default,
awaits : !false_by_default,
booleans : !false_by_default,
collapse_vars : !false_by_default,
comparisons : !false_by_default,
conditionals : !false_by_default,
dead_code : !false_by_default,
default_values : !false_by_default,
directives : !false_by_default,
drop_console : false,
drop_debugger : !false_by_default,
evaluate : !false_by_default,
expression : false,
functions : !false_by_default,
global_defs : false,
hoist_exports : !false_by_default,
hoist_funs : false,
hoist_props : !false_by_default,
hoist_vars : false,
ie : false,
if_return : !false_by_default,
imports : !false_by_default,
inline : !false_by_default,
join_vars : !false_by_default,
keep_fargs : false_by_default,
keep_fnames : false,
keep_infinity : false,
loops : !false_by_default,
merge_vars : !false_by_default,
module : false,
negate_iife : !false_by_default,
objects : !false_by_default,
optional_chains : !false_by_default,
passes : 1,
properties : !false_by_default,
pure_funcs : null,
pure_getters : !false_by_default && "strict",
reduce_funcs : !false_by_default,
reduce_vars : !false_by_default,
rests : !false_by_default,
sequences : !false_by_default,
side_effects : !false_by_default,
spreads : !false_by_default,
strings : !false_by_default,
switches : !false_by_default,
templates : !false_by_default,
top_retain : null,
toplevel : !!(options && !options["expression"] && options["top_retain"]),
typeofs : !false_by_default,
unsafe : false,
unsafe_comps : false,
unsafe_Function : false,
unsafe_math : false,
unsafe_proto : false,
unsafe_regexp : false,
unsafe_undefined: false,
unused : !false_by_default,
varify : !false_by_default,
webkit : false,
yields : !false_by_default,
}, true);
var evaluate = this.options["evaluate"];
this.eval_threshold = /eager/.test(evaluate) ? 1 / 0 : +evaluate;
var global_defs = this.options["global_defs"];
if (typeof global_defs == "object") for (var key in global_defs) {
if (/^@/.test(key) && HOP(global_defs, key)) {
global_defs[key.slice(1)] = parse(global_defs[key], { expression: true });
}
}
if (this.options["inline"] === true) this.options["inline"] = 4;
this.drop_fargs = this.options["keep_fargs"] ? return_false : function(lambda, parent) {
if (lambda.length_read) return false;
var name = lambda.name;
if (!name) return parent && parent.TYPE == "Call" && parent.expression === lambda;
if (name.fixed_value() !== lambda) return false;
var def = name.definition();
if (def.direct_access) return false;
var escaped = def.escaped;
return escaped && escaped.depth != 1;
};
if (this.options["module"]) this.directives["use strict"] = true;
var pure_funcs = this.options["pure_funcs"];
if (typeof pure_funcs == "function") {
this.pure_funcs = pure_funcs;
} else if (typeof pure_funcs == "string") {
this.pure_funcs = function(node) {
var expr;
if (node instanceof AST_Call) {
expr = node.expression;
} else if (node instanceof AST_Template) {
expr = node.tag;
}
return !(expr && pure_funcs === expr.print_to_string());
};
} else if (Array.isArray(pure_funcs)) {
this.pure_funcs = function(node) {
var expr;
if (node instanceof AST_Call) {
expr = node.expression;
} else if (node instanceof AST_Template) {
expr = node.tag;
}
return !(expr && member(expr.print_to_string(), pure_funcs));
};
} else {
this.pure_funcs = return_true;
}
var sequences = this.options["sequences"];
this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
var top_retain = this.options["top_retain"];
if (top_retain instanceof RegExp) {
this.top_retain = function(def) {
return top_retain.test(def.name);
};
} else if (typeof top_retain == "function") {
this.top_retain = top_retain;
} else if (top_retain) {
if (typeof top_retain == "string") {
top_retain = top_retain.split(/,/);
}
this.top_retain = function(def) {
return member(def.name, top_retain);
};
}
var toplevel = this.options["toplevel"];
this.toplevel = typeof toplevel == "string" ? {
funcs: /funcs/.test(toplevel),
vars: /vars/.test(toplevel)
} : {
funcs: toplevel,
vars: toplevel
};
}
Compressor.prototype = new TreeTransformer(function(node, descend) {
if (node._squeezed) return node;
var is_scope = node instanceof AST_Scope;
if (is_scope) {
if (this.option("arrows") && is_arrow(node) && node.value) {
node.body = [ node.first_statement() ];
node.value = null;
}
node.hoist_properties(this);
node.hoist_declarations(this);
node.process_returns(this);
}
// Before https://github.com/mishoo/UglifyJS/pull/1602 AST_Node.optimize()
// would call AST_Node.transform() if a different instance of AST_Node is
// produced after OPT().
// This corrupts TreeWalker.stack, which cause AST look-ups to malfunction.
// Migrate and defer all children's AST_Node.transform() to below, which
// will now happen after this parent AST_Node has been properly substituted
// thus gives a consistent AST snapshot.
descend(node, this);
// Existing code relies on how AST_Node.optimize() worked, and omitting the
// following replacement call would result in degraded efficiency of both
// output and performance.
descend(node, this);
var opt = node.optimize(this);
if (is_scope) {
if (opt === node && !this.has_directive("use asm") && !opt.pinned()) {
opt.drop_unused(this);
if (opt.merge_variables(this)) opt.drop_unused(this);
descend(opt, this);
}
if (this.option("arrows") && is_arrow(opt) && opt.body.length == 1) {
var stat = opt.body[0];
if (stat instanceof AST_Return) {
opt.body.length = 0;
opt.value = stat.value;
}
}
}
if (opt === node) opt._squeezed = true;
return opt;
});
Compressor.prototype.option = function(key) {
return this.options[key];
};
Compressor.prototype.exposed = function(def) {
if (def.exported) return true;
if (def.undeclared) return true;
if (!(def.global || def.scope.resolve() instanceof AST_Toplevel)) return false;
var toplevel = this.toplevel;
return !all(def.orig, function(sym) {
return toplevel[sym instanceof AST_SymbolDefun ? "funcs" : "vars"];
});
};
Compressor.prototype.compress = function(node) {
node = node.resolve_defines(this);
node.hoist_exports(this);
if (this.option("expression")) node.process_expression(true);
var merge_vars = this.options.merge_vars;
var passes = +this.options.passes || 1;
var min_count = 1 / 0;
var stopping = false;
var mangle = { ie: this.option("ie") };
for (var pass = 0; pass < passes; pass++) {
node.figure_out_scope(mangle);
if (pass > 0 || this.option("reduce_vars"))
node.reset_opt_flags(this);
this.options.merge_vars = merge_vars && (stopping || pass == passes - 1);
node = node.transform(this);
if (passes > 1) {
var count = 0;
node.walk(new TreeWalker(function() {
count++;
}));
AST_Node.info("pass {pass}: last_count: {min_count}, count: {count}", {
pass: pass,
min_count: min_count,
count: count,
});
if (count < min_count) {
min_count = count;
stopping = false;
} else if (stopping) {
break;
} else {
stopping = true;
}
}
}
if (this.option("expression")) node.process_expression(false);
return node;
};
(function(OPT) {
OPT(AST_Node, function(self) {
return self;
});
AST_Toplevel.DEFMETHOD("hoist_exports", function(compressor) {
if (!compressor.option("hoist_exports")) return;
var body = this.body, props = [];
for (var i = 0; i < body.length; i++) {
var stat = body[i];
if (stat instanceof AST_ExportDeclaration) {
body[i] = stat = stat.body;
if (stat instanceof AST_Definitions) {
stat.definitions.forEach(function(defn) {
defn.name.match_symbol(export_symbol, true);
});
} else {
export_symbol(stat.name);
}
} else if (stat instanceof AST_ExportReferences) {
body.splice(i--, 1);
[].push.apply(props, stat.properties);
}
}
if (props.length) body.push(make_node(AST_ExportReferences, this, { properties: props }));
function export_symbol(sym) {
if (!(sym instanceof AST_SymbolDeclaration)) return;
var node = make_node(AST_SymbolExport, sym);
node.alias = make_node(AST_String, node, { value: node.name });
props.push(node);
}
});
AST_Scope.DEFMETHOD("process_expression", function(insert, transform) {
var self = this;
var tt = new TreeTransformer(function(node) {
if (insert) {
if (node instanceof AST_Directive) node = make_node(AST_SimpleStatement, node, {
body: make_node(AST_String, node),
});
if (node instanceof AST_SimpleStatement) {
return transform ? transform(node) : make_node(AST_Return, node, { value: node.body });
}
} else if (node instanceof AST_Return) {
if (transform) return transform(node);
var value = node.value;
if (value instanceof AST_String) return make_node(AST_Directive, value);
return make_node(AST_SimpleStatement, node, {
body: value || make_node(AST_UnaryPrefix, node, {
operator: "void",
expression: make_node(AST_Number, node, { value: 0 }),
}),
});
}
if (node instanceof AST_Block) {
if (node instanceof AST_Lambda) {
if (node !== self) return node;
} else if (insert === "awaits" && node instanceof AST_Try) {
if (node.bfinally) return node;
}
for (var index = node.body.length; --index >= 0;) {
var stat = node.body[index];
if (!is_declaration(stat, true)) {
node.body[index] = stat.transform(tt);
break;
}
}
} else if (node instanceof AST_If) {
node.body = node.body.transform(tt);
if (node.alternative) node.alternative = node.alternative.transform(tt);
} else if (node instanceof AST_With) {
node.body = node.body.transform(tt);
}
return node;
});
self.transform(tt);
});
AST_Toplevel.DEFMETHOD("unwrap_expression", function() {
var self = this;
switch (self.body.length) {
case 0:
return make_node(AST_UnaryPrefix, self, {
operator: "void",
expression: make_node(AST_Number, self, { value: 0 }),
});
case 1:
var stat = self.body[0];
if (stat instanceof AST_Directive) return make_node(AST_String, stat);
if (stat instanceof AST_SimpleStatement) return stat.body;
default:
return make_node(AST_Call, self, {
expression: make_node(AST_Function, self, {
argnames: [],
body: self.body,
}).init_vars(self, self),
args: [],
});
}
});
AST_Node.DEFMETHOD("wrap_expression", function() {
var self = this;
if (!is_statement(self)) self = make_node(AST_SimpleStatement, self, { body: self });
if (!(self instanceof AST_Toplevel)) self = make_node(AST_Toplevel, self, { body: [ self ] });
return self;
});
function read_property(obj, node) {
var key = node.get_property();
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_Lambda) {
if (key == "length") {
obj.length_read = true;
return make_node_from_constant(obj.argnames.length, obj);
}
} else if (obj instanceof AST_Object) {
key = "" + key;
var props = obj.properties;
for (var i = props.length; --i >= 0;) {
var prop = props[i];
if (!can_hoist_property(prop)) return;
if (!value && props[i].key === key) value = props[i].value;
}
}
return value instanceof AST_SymbolRef && value.fixed_value() || value;
}
function is_read_only_fn(value, name) {
if (value instanceof AST_Boolean) return native_fns.Boolean[name];
if (value instanceof AST_Number) return native_fns.Number[name];
if (value instanceof AST_String) return native_fns.String[name];
if (name == "valueOf") return false;
if (value instanceof AST_Array) return native_fns.Array[name];
if (value instanceof AST_Lambda) return native_fns.Function[name];
if (value instanceof AST_Object) return native_fns.Object[name];
if (value instanceof AST_RegExp) return native_fns.RegExp[name] && !value.value.global;
}
function is_modified(compressor, tw, node, value, level, immutable, recursive) {
var parent = tw.parent(level);
if (compressor.option("unsafe") && parent instanceof AST_Dot && is_read_only_fn(value, parent.property)) {
return;
}
var lhs = is_lhs(node, parent);
if (lhs) return lhs;
if (level == 0 && value && value.is_constant()) return;
if (parent instanceof AST_Array) return is_modified(compressor, tw, parent, parent, level + 1);
if (parent instanceof AST_Assign) switch (parent.operator) {
case "=":
return is_modified(compressor, tw, parent, value, level + 1, immutable, recursive);
case "&&=":
case "||=":
case "??=":
return is_modified(compressor, tw, parent, parent, level + 1);
default:
return;
}
if (parent instanceof AST_Binary) {
if (!lazy_op[parent.operator]) return;
return is_modified(compressor, tw, parent, parent, level + 1);
}
if (parent instanceof AST_Call) {
return !immutable
&& parent.expression === node
&& !parent.is_expr_pure(compressor)
&& (!(value instanceof AST_LambdaExpression) || !(parent instanceof AST_New) && value.contains_this());
}
if (parent instanceof AST_Conditional) {
if (parent.condition === node) return;
return is_modified(compressor, tw, parent, parent, level + 1);
}
if (parent instanceof AST_ForEnumeration) return parent.init === node;
if (parent instanceof AST_ObjectKeyVal) {
if (parent.value !== node) return;
var obj = tw.parent(level + 1);
return is_modified(compressor, tw, obj, obj, level + 2);
}
if (parent instanceof AST_PropAccess) {
if (parent.expression !== node) return;
var prop = read_property(value, parent);
return (!immutable || recursive) && is_modified(compressor, tw, parent, prop, level + 1);
}
if (parent instanceof AST_Sequence) {
if (parent.tail_node() !== node) return;
return is_modified(compressor, tw, parent, value, level + 1, immutable, recursive);
}
}
function is_lambda(node) {
return node instanceof AST_Class || node instanceof AST_Lambda;
}
function safe_for_extends(node) {
return node instanceof AST_Class || node instanceof AST_Defun || node instanceof AST_Function;
}
function is_arguments(def) {
return def.name == "arguments" && def.scope.uses_arguments;
}
function cross_scope(def, sym) {
do {
if (def === sym) return false;
if (sym instanceof AST_Scope) return true;
} while (sym = sym.parent_scope);
}
function can_drop_symbol(ref, compressor, keep_lambda) {
var def = ref.redef || ref.definition();
if (ref.in_arg && is_funarg(def)) return false;
return all(def.orig, function(sym) {
if (sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet) {
if (sym instanceof AST_SymbolImport) return true;
return compressor && safe_from_tdz(compressor, sym);
}
return !(keep_lambda && sym instanceof AST_SymbolLambda);
});
}
function has_escaped(d, scope, node, parent) {
if (parent instanceof AST_Assign) return parent.operator == "=" && parent.right === node;
if (parent instanceof AST_Call) return parent.expression !== node || parent instanceof AST_New;
if (parent instanceof AST_ClassField) return parent.value === node && !parent.static;
if (parent instanceof AST_Exit) return parent.value === node && scope.resolve() !== d.scope.resolve();
if (parent instanceof AST_VarDef) return parent.value === node;
}
function make_ref(ref, fixed) {
var node = make_node(AST_SymbolRef, ref);
node.fixed = fixed || make_node(AST_Undefined, ref);
return node;
}
function replace_ref(resolve, fixed) {
return function(node) {
var ref = resolve(node);
var node = make_ref(ref, fixed);
var def = ref.definition();
def.references.push(node);
def.replaced++;
return node;
};
}
var RE_POSITIVE_INTEGER = /^(0|[1-9][0-9]*)$/;
(function(def) {
def(AST_Node, noop);
function reset_def(tw, compressor, def) {
def.assignments = 0;
def.bool_return = 0;
def.cross_loop = false;
def.direct_access = false;
def.drop_return = 0;
def.escaped = [];
def.first_decl = null;
def.fixed = !def.const_redefs
&& !def.scope.pinned()
&& !compressor.exposed(def)
&& !(def.init instanceof AST_LambdaExpression && def.init !== def.scope)
&& def.init;
def.reassigned = 0;
def.recursive_refs = 0;
def.references = [];
def.single_use = undefined;
}
function reset_block_variables(tw, compressor, scope) {
scope.variables.each(function(def) {
reset_def(tw, compressor, def);
});
}
function reset_variables(tw, compressor, scope) {
scope.fn_defs = [];
scope.variables.each(function(def) {
reset_def(tw, compressor, def);
var init = def.init;
if (init instanceof AST_LambdaDefinition) {
scope.fn_defs.push(init);
init.safe_ids = null;
}
if (def.fixed === null) {
def.safe_ids = tw.safe_ids;
mark(tw, def);
} else if (def.fixed) {
tw.loop_ids[def.id] = tw.in_loop;
mark(tw, def);
}
});
scope.may_call_this = function() {
scope.may_call_this = scope.contains_this() ? return_true : return_false;
};
if (scope.uses_arguments) scope.each_argname(function(node) {
node.definition().last_ref = false;
});
if (compressor.option("ie")) scope.variables.each(function(def) {
var d = def.orig[0].definition();
if (d !== def) d.fixed = false;
});
}
function safe_to_visit(tw, fn) {
var marker = fn.safe_ids;
return marker === undefined || marker === tw.safe_ids;
}
function walk_fn_def(tw, fn) {
var was_scanning = tw.fn_scanning;
tw.fn_scanning = fn;
fn.walk(tw);
tw.fn_scanning = was_scanning;
}
function revisit_fn_def(tw, fn) {
fn.enclosed.forEach(function(d) {
if (fn.variables.get(d.name) === d) return;
if (safe_to_read(tw, d)) return;
d.single_use = false;
var fixed = d.fixed;
if (typeof fixed == "function") fixed = fixed();
if (fixed instanceof AST_Lambda) {
var safe_ids = fixed.safe_ids;
switch (safe_ids) {
case null:
case false:
return;
default:
if (safe_ids && safe_ids.seq !== tw.safe_ids.seq) return;
}
}
d.fixed = false;
});
}
function mark_fn_def(tw, def, fn) {
var marker = fn.safe_ids;
if (marker === undefined) return;
if (marker === false) return;
if (fn.parent_scope.resolve().may_call_this === return_true) {
if (member(fn, tw.fn_visited)) revisit_fn_def(tw, fn);
} else if (marker) {
var visited = member(fn, tw.fn_visited);
if (marker === tw.safe_ids) {
if (!visited) walk_fn_def(tw, fn);
} else if (visited) {
revisit_fn_def(tw, fn);
} else {
fn.safe_ids = false;
}
} else if (tw.fn_scanning && tw.fn_scanning !== def.scope.resolve()) {
fn.safe_ids = false;
} else {
fn.safe_ids = tw.safe_ids;
walk_fn_def(tw, fn);
}
}
function pop_scope(tw, scope) {
pop(tw);
var fn_defs = scope.fn_defs;
fn_defs.forEach(function(fn) {
fn.safe_ids = tw.safe_ids;
walk_fn_def(tw, fn);
});
fn_defs.forEach(function(fn) {
fn.safe_ids = undefined;
});
scope.fn_defs = undefined;
scope.may_call_this = undefined;
}
function push(tw, sequential, conditional) {
var defined_ids = Object.create(tw.defined_ids);
if (!sequential || conditional) defined_ids.seq = Object.create(null);
tw.defined_ids = defined_ids;
var safe_ids = Object.create(tw.safe_ids);
if (!sequential) safe_ids.seq = {};
if (conditional) safe_ids.cond = true;
tw.safe_ids = safe_ids;
}
function pop(tw) {
tw.defined_ids = Object.getPrototypeOf(tw.defined_ids);
tw.safe_ids = Object.getPrototypeOf(tw.safe_ids);
}
function access(tw, def) {
var seq = tw.defined_ids.seq;
tw.defined_ids[def.id] = seq;
seq[def.id] = true;
}
function assign(tw, def) {
var seq = tw.defined_ids.seq;
tw.assigned_ids[def.id] = seq;
seq[def.id] = false;
}
function safe_to_access(tw, def) {
var seq = tw.defined_ids.seq;
var defined = tw.defined_ids[def.id];
if (defined !== seq) return false;
if (!defined[def.id]) return false;
var assigned = tw.assigned_ids[def.id];
return !assigned || assigned === seq;
}
function mark(tw, def) {
tw.safe_ids[def.id] = {};
}
function push_ref(def, ref) {
def.references.push(ref);
if (def.last_ref !== false) def.last_ref = ref;
}
function safe_to_read(tw, def) {
if (def.single_use == "m") return false;
var safe = tw.safe_ids[def.id];
if (safe) {
var in_order = HOP(tw.safe_ids, def.id);
if (!in_order) {
var seq = tw.safe_ids.seq;
if (!safe.read) {
safe.read = seq;
} else if (safe.read !== seq) {
safe.read = true;
}
}
if (def.fixed == null) {
if (is_arguments(def)) return false;
if (def.global && def.name == "arguments") return false;
tw.loop_ids[def.id] = null;
def.fixed = make_node(AST_Undefined, def.orig[0]);
if (in_order) def.safe_ids = undefined;
return true;
}
return !safe.assign || safe.assign === tw.safe_ids;
}
return def.fixed instanceof AST_LambdaDefinition;
}
function safe_to_assign(tw, def, declare) {
if (!declare) {
if (is_funarg(def) && def.scope.uses_arguments && !tw.has_directive("use strict")) return false;
if (!all(def.orig, function(sym) {
return !(sym instanceof AST_SymbolConst);
})) return false;
}
if (def.fixed === undefined) return declare || all(def.orig, function(sym) {
return !(sym instanceof AST_SymbolLet);
});
if (def.fixed === false || def.fixed === 0) return false;
var safe = tw.safe_ids[def.id];
if (def.safe_ids) {
def.safe_ids[def.id] = false;
def.safe_ids = undefined;
return def.fixed === null || HOP(tw.safe_ids, def.id) && !safe.read;
}
if (!HOP(tw.safe_ids, def.id)) {
if (!safe) return false;
if (safe.read || tw.in_loop) {
var scope = tw.find_parent(AST_BlockScope);
if (scope instanceof AST_Class) return false;
if (def.scope.resolve() !== scope.resolve()) return false;
}
safe.assign = safe.assign && safe.assign !== tw.safe_ids ? true : tw.safe_ids;
}
if (def.fixed != null && safe.read) {
if (safe.read !== tw.safe_ids.seq) return false;
if (tw.loop_ids[def.id] !== tw.in_loop) return false;
}
return safe_to_read(tw, def) && all(def.orig, function(sym) {
return !(sym instanceof AST_SymbolLambda);
});
}
function ref_once(compressor, def) {
return compressor.option("unused")
&& !def.scope.pinned()
&& def.single_use !== false
&& def.references.length - def.recursive_refs == 1
&& !(is_funarg(def) && def.scope.uses_arguments);
}
function is_immutable(value) {
if (!value) return false;
if (value instanceof AST_Assign) {
var op = value.operator;
return op == "=" ? is_immutable(value.right) : !lazy_op[op.slice(0, -1)];
}
if (value instanceof AST_Sequence) return is_immutable(value.tail_node());
return value.is_constant() || is_lambda(value) || value instanceof AST_ObjectIdentity;
}
function value_in_use(node, parent) {
if (parent instanceof AST_Array) return true;
if (parent instanceof AST_Binary) return lazy_op[parent.operator];
if (parent instanceof AST_Conditional) return parent.condition !== node;
if (parent instanceof AST_Sequence) return parent.tail_node() === node;
if (parent instanceof AST_Spread) return true;
}
function mark_escaped(tw, d, scope, node, value, level, depth) {
var parent = tw.parent(level);
if (value && value.is_constant()) return;
if (has_escaped(d, scope, node, parent)) {
d.escaped.push(parent);
if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1;
if (!d.escaped.depth || d.escaped.depth > depth) d.escaped.depth = depth;
if (d.scope.resolve() !== scope.resolve()) d.escaped.cross_scope = true;
if (d.fixed) d.fixed.escaped = d.escaped;
return;
} else if (value_in_use(node, parent)) {
mark_escaped(tw, d, scope, parent, parent, level + 1, depth);
} else if (parent instanceof AST_ObjectKeyVal && parent.value === node) {
var obj = tw.parent(level + 1);
mark_escaped(tw, d, scope, obj, obj, level + 2, depth);
} else if (parent instanceof AST_PropAccess && parent.expression === node) {
value = read_property(value, parent);
mark_escaped(tw, d, scope, parent, value, level + 1, depth + 1);
if (value) return;
}
if (level > 0) return;
if (parent instanceof AST_Call && parent.expression === node) return;
if (parent instanceof AST_Sequence && parent.tail_node() !== node) return;
if (parent instanceof AST_SimpleStatement) return;
if (parent instanceof AST_Unary && !unary_side_effects[parent.operator]) return;
d.direct_access = true;
if (d.fixed) d.fixed.direct_access = true;
}
function mark_assignment_to_arguments(node) {
if (!(node instanceof AST_Sub)) return;
var expr = node.expression;
if (!(expr instanceof AST_SymbolRef)) return;
var def = expr.definition();
if (!is_arguments(def)) return;
var key = node.property;
if (key.is_constant()) key = key.value;
if (!(key instanceof AST_Node) && !RE_POSITIVE_INTEGER.test(key)) return;
def.reassigned++;
(key instanceof AST_Node ? def.scope.argnames : [ def.scope.argnames[key] ]).forEach(function(argname) {
if (argname instanceof AST_SymbolFunarg) argname.definition().fixed = false;
});
}
function make_fixed(save, fn) {
var prev_save, prev_value;
return function() {
var current = save();
if (prev_save !== current) {
prev_save = current;
prev_value = fn(current);
}
return prev_value;
};
}
function make_fixed_default(compressor, node, save) {
var prev_save, prev_seq;
return function() {
if (prev_seq === node) return node;
var current = save();
var ev = fuzzy_eval(compressor, current, true);
if (ev instanceof AST_Node) {
prev_seq = node;
} else if (prev_save !== current) {
prev_save = current;
prev_seq = ev === undefined ? make_sequence(node, [ current, node.value ]) : current;
}
return prev_seq;
};
}
function scan_declaration(tw, compressor, lhs, fixed, visit) {
var scanner = new TreeWalker(function(node) {
if (node instanceof AST_DefaultValue) {
reset_flags(node);
push(tw, true, true);
node.value.walk(tw);
pop(tw);
var save = fixed;
if (save) fixed = make_fixed_default(compressor, node, save);
node.name.walk(scanner);
fixed = save;
return true;
}
if (node instanceof AST_DestructuredArray) {
reset_flags(node);
var save = fixed;
node.elements.forEach(function(node, index) {
if (node instanceof AST_Hole) return reset_flags(node);
if (save) fixed = make_fixed(save, function(value) {
return make_node(AST_Sub, node, {
expression: value,
property: make_node(AST_Number, node, { value: index }),
});
});
node.walk(scanner);
});
if (node.rest) {
var fixed_node;
if (save) fixed = compressor.option("rests") && make_fixed(save, function(value) {
if (!(value instanceof AST_Array)) return node;
for (var i = 0, len = node.elements.length; i < len; i++) {
if (value.elements[i] instanceof AST_Spread) return node;
}
if (!fixed_node) fixed_node = make_node(AST_Array, node, {});
fixed_node.elements = value.elements.slice(len);
return fixed_node;
});
node.rest.walk(scanner);
}
fixed = save;
return true;
}
if (node instanceof AST_DestructuredObject) {
reset_flags(node);
var save = fixed;
node.properties.forEach(function(node) {
reset_flags(node);
if (node.key instanceof AST_Node) {
push(tw);
node.key.walk(tw);
pop(tw);
}
if (save) fixed = make_fixed(save, function(value) {
var key = node.key;
var type = AST_Sub;
if (typeof key == "string") {
if (is_identifier_string(key)) {
type = AST_Dot;
} else {
key = make_node_from_constant(key, node);
}
}
return make_node(type, node, {
expression: value,
property: key,
});
});
node.value.walk(scanner);
});
if (node.rest) {
fixed = false;
node.rest.walk(scanner);
}
fixed = save;
return true;
}
visit(node, fixed, function() {
var save_len = tw.stack.length;
for (var i = 0, len = scanner.stack.length - 1; i < len; i++) {
tw.stack.push(scanner.stack[i]);
}
node.walk(tw);
tw.stack.length = save_len;
});
return true;
});
lhs.walk(scanner);
}
function reduce_iife(tw, descend, compressor) {
var fn = this;
fn.inlined = false;
var iife = tw.parent();
var sequential = !is_async(fn) && !is_generator(fn);
var hit = !sequential;
var aborts = false;
fn.walk(new TreeWalker(function(node) {
if (hit) return aborts = true;
if (node instanceof AST_Return) return hit = true;
if (node instanceof AST_Scope && node !== fn) return true;
}));
if (aborts) push(tw, sequential);
reset_variables(tw, compressor, fn);
// Virtually turn IIFE parameters into variable definitions:
// (function(a,b) {...})(c,d) ---> (function() {var a=c,b=d; ...})()
// So existing transformation rules can work on them.
var safe = !fn.uses_arguments || tw.has_directive("use strict");
fn.argnames.forEach(function(argname, i) {
var value = iife.args[i];
scan_declaration(tw, compressor, argname, function() {
var j = fn.argnames.indexOf(argname);
var arg = j < 0 ? value : iife.args[j];
if (arg instanceof AST_Sequence && arg.expressions.length < 2) arg = arg.expressions[0];
return arg || make_node(AST_Undefined, iife);
}, visit);
});
var rest = fn.rest, fixed_node;
if (rest) scan_declaration(tw, compressor, rest, compressor.option("rests") && function() {
if (fn.rest !== rest) return rest;
if (!fixed_node) fixed_node = make_node(AST_Array, fn, {});
fixed_node.elements = iife.args.slice(fn.argnames.length);
return fixed_node;
}, visit);
walk_lambda(fn, tw);
var defined_ids = tw.defined_ids;
var safe_ids = tw.safe_ids;
pop_scope(tw, fn);
if (!aborts) {
tw.defined_ids = defined_ids;
tw.safe_ids = safe_ids;
}
return true;
function visit(node, fixed) {
var d = node.definition();
if (!d.first_decl && d.references.length == 0) d.first_decl = node;
if (fixed && safe && d.fixed === undefined) {
mark(tw, d);
tw.loop_ids[d.id] = tw.in_loop;
d.fixed = fixed;
d.fixed.assigns = [ node ];
} else {
d.fixed = false;
}
}
}
def(AST_Assign, function(tw, descend, compressor) {
var node = this;
var left = node.left;
var right = node.right;
var ld = left instanceof AST_SymbolRef && left.definition();
var scan = ld || left instanceof AST_Destructured;
switch (node.operator) {
case "=":
if (left.equals(right) && !left.has_side_effects(compressor)) {
right.walk(tw);
walk_prop(left);
return true;
}
if (ld && right instanceof AST_LambdaExpression) {
walk_assign();
right.parent_scope.resolve().fn_defs.push(right);
right.safe_ids = null;
if (!ld.fixed || !node.write_only || tw.safe_ids.cond) mark_fn_def(tw, ld, right);
return true;
}
if (scan) {
right.walk(tw);
walk_assign();
return true;
}
mark_assignment_to_arguments(left);
return;
case "&&=":
case "||=":
case "??=":
var lazy = true;
default:
if (!scan) {
mark_assignment_to_arguments(left);
return walk_lazy();
}
assign(tw, ld);
ld.assignments++;
var fixed = ld.fixed;
if (is_modified(compressor, tw, node, node, 0)) {
ld.fixed = false;
return walk_lazy();
}
var safe = safe_to_read(tw, ld);
if (lazy) push(tw, true, true);
right.walk(tw);
if (lazy) pop(tw);
if (safe && !left.in_arg && safe_to_assign(tw, ld)) {
push_ref(ld, left);
mark(tw, ld);
if (ld.single_use) ld.single_use = false;
left.fixed = ld.fixed = function() {
return make_node(AST_Binary, node, {
operator: node.operator.slice(0, -1),
left: make_ref(left, fixed),
right: node.right,
});
};
left.fixed.assigns = !fixed || !fixed.assigns ? [ ld.orig[0] ] : fixed.assigns.slice();
left.fixed.assigns.push(node);
left.fixed.to_binary = replace_ref(function(node) {
return node.left;
}, fixed);
} else {
left.walk(tw);
ld.fixed = false;
}
return true;
}
function walk_prop(lhs) {
reset_flags(lhs);
if (lhs instanceof AST_Dot) {
walk_prop(lhs.expression);
} else if (lhs instanceof AST_Sub) {
walk_prop(lhs.expression);
lhs.property.walk(tw);
} else if (lhs instanceof AST_SymbolRef) {
var d = lhs.definition();
push_ref(d, lhs);
if (d.fixed) {
lhs.fixed = d.fixed;
if (lhs.fixed.assigns) {
lhs.fixed.assigns.push(node);
} else {
lhs.fixed.assigns = [ node ];
}
}
} else {
lhs.walk(tw);
}
}
function walk_assign() {
var recursive = ld && recursive_ref(tw, ld);
var modified = is_modified(compressor, tw, node, right, 0, is_immutable(right), recursive);
scan_declaration(tw, compressor, left, function() {
return node.right;
}, function(sym, fixed, walk) {
if (!(sym instanceof AST_SymbolRef)) {
mark_assignment_to_arguments(sym);
walk();
return;
}
var d = sym.definition();
assign(tw, d);
d.assignments++;
if (!fixed || sym.in_arg || !safe_to_assign(tw, d)) {
walk();
d.fixed = false;
} else {
push_ref(d, sym);
mark(tw, d);
if (left instanceof AST_Destructured
|| d.orig.length == 1 && d.orig[0] instanceof AST_SymbolDefun) {
d.single_use = false;
}
tw.loop_ids[d.id] = tw.in_loop;
d.fixed = modified ? 0 : fixed;
sym.fixed = fixed;
sym.fixed.assigns = [ node ];
mark_escaped(tw, d, sym.scope, node, right, 0, 1);
}
});
}
function walk_lazy() {
if (!lazy) return;
left.walk(tw);
push(tw, true, true);
right.walk(tw);
pop(tw);
return true;
}
});
def(AST_Binary, function(tw) {
if (!lazy_op[this.operator]) return;
this.left.walk(tw);
push(tw, true, true);
this.right.walk(tw);
pop(tw);
return true;
});
def(AST_BlockScope, function(tw, descend, compressor) {
reset_block_variables(tw, compressor, this);
});
def(AST_Call, function(tw) {
var node = this;
var exp = node.expression;
if (exp instanceof AST_LambdaExpression) {
var iife = is_iife_single(node);
node.args.forEach(function(arg) {
arg.walk(tw);
if (arg instanceof AST_Spread) iife = false;
});
if (iife) exp.reduce_vars = reduce_iife;
exp.walk(tw);
if (iife) delete exp.reduce_vars;
return true;
}
if (node.TYPE == "Call") switch (tw.in_boolean_context()) {
case "d":
var drop = true;
case true:
mark_refs(exp, drop);
}
exp.walk(tw);
var optional = node.optional;
if (optional) push(tw, true, true);
node.args.forEach(function(arg) {
arg.walk(tw);
});
if (optional) pop(tw);
var fixed = exp instanceof AST_SymbolRef && exp.fixed_value();
if (fixed instanceof AST_Lambda) {
mark_fn_def(tw, exp.definition(), fixed);
} else {
tw.defined_ids.seq = {};
tw.find_parent(AST_Scope).may_call_this();
}
return true;
function mark_refs(node, drop) {
if (node instanceof AST_Assign) {
if (node.operator != "=") return;
mark_refs(node.left, drop);
mark_refs(node.right, drop);
} else if (node instanceof AST_Binary) {
if (!lazy_op[node.operator]) return;
mark_refs(node.left, drop);
mark_refs(node.right, drop);
} else if (node instanceof AST_Conditional) {
mark_refs(node.consequent, drop);
mark_refs(node.alternative, drop);
} else if (node instan