},
}, AST_Statement);
-var AST_BlockScope = DEFNODE("BlockScope", "enclosed functions make_def parent_scope variables", {
+var AST_BlockScope = DEFNODE("BlockScope", "_var_names enclosed functions make_def parent_scope variables", {
$documentation: "Base class for all statements introducing a lexical scope",
$propdoc: {
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
/* -----[ scope and functions ]----- */
-var AST_Scope = DEFNODE("Scope", "uses_eval uses_with", {
+var AST_Scope = DEFNODE("Scope", "fn_defs may_call_this uses_eval uses_with", {
$documentation: "Base class for all statements introducing a lexical scope",
$propdoc: {
uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
}
}, AST_Scope);
-var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest uses_arguments", {
+var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest safe_ids uses_arguments", {
$documentation: "Base class for functions",
$propdoc: {
argnames: "[(AST_DefaultValue|AST_Destructured|AST_SymbolFunarg)*] array of function arguments and/or destructured literals",
$documentation: "Symbol defining a variable",
}, AST_SymbolDeclaration);
-var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
+var AST_SymbolFunarg = DEFNODE("SymbolFunarg", "unused", {
$documentation: "Symbol naming a function argument",
}, AST_SymbolVar);
});
}
+ 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;
d.single_use = false;
var fixed = d.fixed;
if (typeof fixed == "function") fixed = fixed();
- if (fixed instanceof AST_Lambda && HOP(fixed, "safe_ids")) return;
+ if (fixed instanceof AST_Lambda && fixed.safe_ids !== undefined) return;
d.fixed = false;
});
}
function mark_fn_def(tw, def, fn) {
- if (!HOP(fn, "safe_ids")) return;
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);
walk_fn_def(tw, fn);
});
fn_defs.forEach(function(fn) {
- delete fn.safe_ids;
+ fn.safe_ids = undefined;
});
- delete scope.fn_defs;
- delete scope.may_call_this;
+ scope.fn_defs = undefined;
+ scope.may_call_this = undefined;
}
function push(tw) {
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) delete def.safe_ids;
+ if (in_order) def.safe_ids = undefined;
return true;
}
return !safe.assign || safe.assign === tw.safe_ids;
var safe = tw.safe_ids[def.id];
if (def.safe_ids) {
def.safe_ids[def.id] = false;
- delete def.safe_ids;
+ def.safe_ids = undefined;
return def.fixed === null || HOP(tw.safe_ids, def.id) && !safe.read;
}
if (!HOP(tw.safe_ids, def.id)) {
});
def(AST_Lambda, function(tw, descend, compressor) {
var fn = this;
- if (HOP(fn, "safe_ids") && fn.safe_ids !== tw.safe_ids) return true;
+ if (!safe_to_visit(tw, fn)) return true;
if (!push_uniq(tw.fn_visited, fn)) return true;
fn.inlined = false;
push(tw);
var def = fn.name.definition();
var parent = tw.parent();
if (parent instanceof AST_ExportDeclaration || parent instanceof AST_ExportDefault) def.single_use = false;
- if (HOP(fn, "safe_ids") && fn.safe_ids !== tw.safe_ids) return true;
+ if (!safe_to_visit(tw, fn)) return true;
if (!push_uniq(tw.fn_visited, fn)) return true;
fn.inlined = false;
push(tw);
function reset_flags(node) {
node._squeezed = false;
node._optimized = false;
- delete node.fixed;
- if (node instanceof AST_Scope) delete node._var_names;
+ if (node instanceof AST_BlockScope) node._var_names = undefined;
+ if (node instanceof AST_SymbolRef) node.fixed = undefined;
}
AST_Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) {
argnames.pop();
} else if (i > default_length) {
log(sym.name, "Dropping unused default argument assignment {name}");
- sym.name.__unused = true;
+ sym.name.unused = true;
argnames[i] = sym.name;
} else {
log(sym.name, "Dropping unused default argument value {name}");
var def = sym.definition();
if (def.id in in_use_ids) {
trim = false;
- if (indexOf_assign(def, sym) < 0) sym.__unused = null;
+ if (indexOf_assign(def, sym) < 0) sym.unused = null;
} else if (trim) {
log(sym, "Dropping unused function argument {name}");
argnames.pop();
} else {
- sym.__unused = true;
+ sym.unused = true;
}
}
fns_with_marked_args.push(node);
var value = node.value.drop_side_effect_free(compressor);
if (!value) return null;
log(node.name, "Side effects in default value of unused variable {name}");
- node.name.__unused = null;
+ node.name.unused = null;
node.value = value;
}
return node;
}
return make_node(AST_DestructuredObject, node, { properties: [] });
}
- node.__unused = null;
+ node.unused = null;
return node;
}
}
if (argname instanceof AST_DestructuredObject) {
return argname.properties.length == 0 && !argname.rest && arg && !arg.may_throw_on_access(compressor);
}
- return argname.__unused;
+ return argname.unused;
} : return_false;
var side_effects = [];
for (var i = 0; i < args.length; i++) {
if (drop_defaults && argname instanceof AST_DefaultValue && args[i].is_defined(compressor)) {
argnames[i] = argname = argname.name;
}
- if (!argname || "__unused" in argname) {
+ if (!argname || argname.unused !== undefined) {
var node = args[i].drop_side_effect_free(compressor);
if (drop_fargs(argname)) {
if (argname) argnames.splice(i, 1);
var abort = false;
fn.each_argname(function(arg) {
if (abort) return;
- if (arg.__unused) return;
+ if (arg.unused) return;
if (!safe_to_inject || var_exists(defined, arg.name)) return abort = true;
arg_used.set(arg.name, true);
if (in_loop) in_loop.push(arg.definition());
name = argname;
}
var value = self.args[i];
- if (name.__unused || scope.var_names().has(name.name)) {
+ if (name.unused || scope.var_names().has(name.name)) {
if (value) expressions.push(value);
} else {
var symbol = make_node(AST_SymbolVar, name, name);
name.definition().orig.push(symbol);
- if ("__unused" in name) {
+ if (name.unused !== undefined) {
append_var(decls, expressions, symbol);
if (value) expressions.push(value);
} else {
expressions.reverse();
for (i = default_args.length; --i >= 0;) {
var node = default_args[i];
- if ("__unused" in node.name) {
+ if (node.name.unused !== undefined) {
expressions.push(node.value);
} else {
var sym = make_node(AST_SymbolRef, node.name, node.name);
operator: "=",
left: make_node(AST_DestructuredArray, self, {
elements: fn.argnames.map(function(argname) {
- if (argname.__unused) return make_node(AST_Hole, argname);
+ if (argname.unused) return make_node(AST_Hole, argname);
return argname.convert_symbol(AST_SymbolRef, process);
}),
rest: fn.rest && fn.rest.convert_symbol(AST_SymbolRef, process),
if (assigned) def.reassigned--;
var sym = make_node(AST_SymbolRef, self, argname);
sym.reference();
- delete argname.__unused;
+ argname.unused = undefined;
return sym;
}
}