First class block scope
- Make let, const, and class symbols be declared in a block scope. - Piggy back on existing catch symbol implementation to get block-aware mangling working - Make sure unused block-scoped declarations can be dropped - Don't eliminate a block if it has a block-scoped declaration - Remove silly empty anonymous blocks left over from drop_unused - AST_Toplevel now gets to call drop_unused too, since block-scoped variables aren't global! - Don't consider block declarations global
This commit is contained in:
committed by
Richard van Velzen
parent
6702cae918
commit
634f231b78
@@ -190,6 +190,14 @@ merge(Compressor.prototype, {
|
||||
return false;
|
||||
};
|
||||
|
||||
function can_be_evicted_from_block(node) {
|
||||
return !(
|
||||
node instanceof AST_DefClass ||
|
||||
node instanceof AST_Let ||
|
||||
node instanceof AST_Const
|
||||
);
|
||||
}
|
||||
|
||||
function loop_body(x) {
|
||||
if (x instanceof AST_Switch) return x;
|
||||
if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
|
||||
@@ -311,7 +319,7 @@ merge(Compressor.prototype, {
|
||||
function eliminate_spurious_blocks(statements) {
|
||||
var seen_dirs = [];
|
||||
return statements.reduce(function(a, stat){
|
||||
if (stat instanceof AST_BlockStatement) {
|
||||
if (stat instanceof AST_BlockStatement && all(stat.body, can_be_evicted_from_block)) {
|
||||
CHANGED = true;
|
||||
a.push.apply(a, eliminate_spurious_blocks(stat.body));
|
||||
} else if (stat instanceof AST_EmptyStatement) {
|
||||
@@ -633,7 +641,7 @@ merge(Compressor.prototype, {
|
||||
function extract_declarations_from_unreachable_code(compressor, stat, target) {
|
||||
compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
|
||||
stat.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_Definitions) {
|
||||
if (node instanceof AST_Var) {
|
||||
compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
|
||||
node.remove_initializers();
|
||||
target.push(node);
|
||||
@@ -957,6 +965,8 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
def(AST_Defun, function(compressor){ return true });
|
||||
def(AST_Function, function(compressor){ return false });
|
||||
def(AST_Class, function(compressor){ return false });
|
||||
def(AST_DefClass, function(compressor){ return true });
|
||||
def(AST_Binary, function(compressor){
|
||||
return this.left.has_side_effects(compressor)
|
||||
|| this.right.has_side_effects(compressor);
|
||||
@@ -1067,7 +1077,11 @@ merge(Compressor.prototype, {
|
||||
OPT(AST_BlockStatement, function(self, compressor){
|
||||
self.body = tighten_body(self.body, compressor);
|
||||
switch (self.body.length) {
|
||||
case 1: return self.body[0];
|
||||
case 1:
|
||||
if (can_be_evicted_from_block(self.body[0])) {
|
||||
return self.body[0];
|
||||
}
|
||||
break;
|
||||
case 0: return make_node(AST_EmptyStatement, self);
|
||||
}
|
||||
return self;
|
||||
@@ -1077,7 +1091,6 @@ merge(Compressor.prototype, {
|
||||
var self = this;
|
||||
if (compressor.has_directive("use asm")) return self;
|
||||
if (compressor.option("unused")
|
||||
&& !(self instanceof AST_Toplevel)
|
||||
&& !self.uses_eval
|
||||
) {
|
||||
var in_use = [];
|
||||
@@ -1166,8 +1179,11 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node instanceof AST_Defun && node !== self) {
|
||||
if (!member(node.name.definition(), in_use)) {
|
||||
if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
|
||||
var keep =
|
||||
member(node.name.definition(), in_use) ||
|
||||
node.name.definition().global;
|
||||
if (!keep) {
|
||||
compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", {
|
||||
name : node.name.name,
|
||||
file : node.name.start.file,
|
||||
@@ -1182,6 +1198,7 @@ merge(Compressor.prototype, {
|
||||
var def = node.definitions.filter(function(def){
|
||||
if (def.is_destructuring()) return true;
|
||||
if (member(def.name.definition(), in_use)) return true;
|
||||
if (def.name.definition().global) return true;
|
||||
var w = {
|
||||
name : def.name.name,
|
||||
file : def.name.start.file,
|
||||
@@ -1260,6 +1277,12 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
}
|
||||
}
|
||||
if (node instanceof AST_BlockStatement) {
|
||||
descend(node, this);
|
||||
if (in_list && all(node.body, can_be_evicted_from_block)) {
|
||||
return MAP.splice(node.body);
|
||||
}
|
||||
}
|
||||
if (node instanceof AST_Scope && node !== self)
|
||||
return node;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user