Skip to content

Commit

Permalink
take class executed bits into account in collapse_vars. closes #617
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiosantoscode committed Mar 29, 2020
1 parent 67aa5c4 commit 0e40b8d
Show file tree
Hide file tree
Showing 9 changed files with 305 additions and 98 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,10 @@ If you happen to need the source map as a raw object, set `sourceMap.asObject` t

## Compress options

- `defaults` (default: `true`) -- Pass `false` to disable most default
enabled `compress` transforms. Useful when you only want to enable a few
`compress` options while disabling the rest.

- `arrows` (default: `true`) -- Class and object literal methods are converted
will also be converted to arrow expressions if the resultant code is shorter:
`m(){return x}` becomes `m:()=>x`. To do this to regular ES5 functions which
Expand Down Expand Up @@ -715,10 +719,6 @@ If you happen to need the source map as a raw object, set `sourceMap.asObject` t

- `dead_code` (default: `true`) -- remove unreachable code

- `defaults` (default: `true`) -- Pass `false` to disable most default
enabled `compress` transforms. Useful when you only want to enable a few
`compress` options while disabling the rest.

- `directives` (default: `true`) -- remove redundant or non-standard directives

- `drop_console` (default: `false`) -- Pass `true` to discard calls to
Expand Down
23 changes: 18 additions & 5 deletions lib/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,8 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
}, AST_Statement);

function walk_body(node, visitor) {
var body = node.body;
if (body instanceof AST_Node) {
body._walk(visitor);
} else for (var i = 0, len = body.length; i < len; i++) {
const body = node.body;
for (var i = 0, len = body.length; i < len; i++) {
body[i]._walk(visitor);
}
}
Expand Down Expand Up @@ -1125,6 +1123,9 @@ var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", {
$documentation: "A key: value object property",
$propdoc: {
quote: "[string] the original quote character"
},
computed_key() {
return this.key instanceof AST_Node;
}
}, AST_ObjectProperty);

Expand All @@ -1134,6 +1135,9 @@ var AST_ObjectSetter = DEFNODE("ObjectSetter", "quote static", {
static: "[boolean] whether this is a static setter (classes only)"
},
$documentation: "An object setter property",
computed_key() {
return !(this.key instanceof AST_SymbolMethod);
}
}, AST_ObjectProperty);

var AST_ObjectGetter = DEFNODE("ObjectGetter", "quote static", {
Expand All @@ -1142,6 +1146,9 @@ var AST_ObjectGetter = DEFNODE("ObjectGetter", "quote static", {
static: "[boolean] whether this is a static getter (classes only)"
},
$documentation: "An object getter property",
computed_key() {
return !(this.key instanceof AST_SymbolMethod);
}
}, AST_ObjectProperty);

var AST_ConciseMethod = DEFNODE("ConciseMethod", "quote static is_generator async", {
Expand All @@ -1151,7 +1158,10 @@ var AST_ConciseMethod = DEFNODE("ConciseMethod", "quote static is_generator asyn
is_generator: "[boolean] is this a generator method",
async: "[boolean] is this method async",
},
$documentation: "An ES6 concise method inside an object or class"
$documentation: "An ES6 concise method inside an object or class",
computed_key() {
return !(this.key instanceof AST_SymbolMethod);
}
}, AST_ObjectProperty);

var AST_Class = DEFNODE("Class", "name extends properties", {
Expand Down Expand Up @@ -1198,6 +1208,9 @@ var AST_ClassProperty = DEFNODE("ClassProperty", "static quote", {
if (this.value instanceof AST_Node) push(this.value);
if (this.key instanceof AST_Node) push(this.key);
},
computed_key() {
return !(this.key instanceof AST_SymbolClassProperty);
}
}, AST_ObjectProperty);

var AST_DefClass = DEFNODE("DefClass", null, {
Expand Down
104 changes: 70 additions & 34 deletions lib/compress/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ import {
AST_ObjectGetter,
AST_ObjectKeyVal,
AST_ObjectProperty,
AST_ObjectSetter,
AST_PrefixedTemplateString,
AST_PropAccess,
AST_RegExp,
Expand Down Expand Up @@ -1505,7 +1506,22 @@ function tighten_body(statements, compressor) {

function handle_custom_scan_order(node) {
// Skip (non-executed) functions
if (node instanceof AST_Scope) return node;
if (node instanceof AST_Lambda) return node;

// Skip the bits of classes that aren't executed immediately
if (node instanceof AST_Class) {
if (node.extends) node.extends = node.extends.transform(scanner);
for (const prop of node.properties) {
if (prop.computed_key()) {
prop.key = prop.key.transform(scanner);
}
if (prop.static && prop.value) {
prop.value = prop.value.transform(scanner);
}
}
return node;
}

// Scan case expressions first in a switch statement
if (node instanceof AST_Switch) {
node.expression = node.expression.transform(scanner);
Expand Down Expand Up @@ -3299,16 +3315,25 @@ const pure_prop_access_globals = new Set([
return any(this.properties, compressor);
});
def_has_side_effects(AST_ObjectProperty, function(compressor) {
const computed_key = this instanceof AST_ObjectKeyVal && this.key instanceof AST_Node;
if (computed_key && this.key.has_side_effects(compressor)) {
return true;
}
return this.value.has_side_effects(compressor);
return (
this.computed_key() && this.key.has_side_effects(compressor)
|| this.value.has_side_effects(compressor)
);
});
def_has_side_effects(AST_ClassProperty, function(compressor) {
if (!this.static) return false;
return this.value && this.value.has_side_effects(compressor)
|| this.key.has_side_effects(compressor);
return (
this.computed_key() && this.key.has_side_effects(compressor)
|| this.static && this.value && this.value.has_side_effects(compressor)
);
});
def_has_side_effects(AST_ConciseMethod, function(compressor) {
return this.computed_key() && this.key.has_side_effects(compressor);
});
def_has_side_effects(AST_ObjectGetter, function(compressor) {
return this.computed_key() && this.key.has_side_effects(compressor);
});
def_has_side_effects(AST_ObjectSetter, function(compressor) {
return this.computed_key() && this.key.has_side_effects(compressor);
});
def_has_side_effects(AST_Array, function(compressor) {
return any(this.elements, compressor);
Expand Down Expand Up @@ -3415,13 +3440,23 @@ const pure_prop_access_globals = new Set([
return any(this.properties, compressor);
});
def_may_throw(AST_ObjectProperty, function(compressor) {
// TODO key may throw too
return this.value.may_throw(compressor);
});
def_may_throw(AST_ClassProperty, function(compressor) {
return this.static
&& (
this.value && this.value.may_throw(compressor)
|| this.key.may_throw(compressor));
return (
this.computed_key() && this.key.may_throw(compressor)
|| this.static && this.value && this.value.may_throw(compressor)
);
});
def_may_throw(AST_ConciseMethod, function(compressor) {
return this.computed_key() && this.key.may_throw(compressor);
});
def_may_throw(AST_ObjectGetter, function(compressor) {
return this.computed_key() && this.key.may_throw(compressor);
});
def_may_throw(AST_ObjectSetter, function(compressor) {
return this.computed_key() && this.key.may_throw(compressor);
});
def_may_throw(AST_Return, function(compressor) {
return this.value && this.value.may_throw(compressor);
Expand Down Expand Up @@ -4356,19 +4391,22 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
return key || value;
});
def_drop_side_effect_free(AST_ClassProperty, function (compressor) {
if (!this.static) return null;
const key = this.computed_key() && this.key.drop_side_effect_free(compressor);

const key = this.key instanceof AST_SymbolClassProperty
? null
: this.key.drop_side_effect_free(compressor);

const value = this.value
const value = this.static && this.value
&& this.value.drop_side_effect_free(compressor);

if (key && value) {
return make_sequence(this, [key, value]);
}
return key || value;
if (key && value) return make_sequence(this, [key, value]);
return key || value || null;
});
def_drop_side_effect_free(AST_ConciseMethod, function () {
return this.computed_key() ? this.key : null;
});
def_drop_side_effect_free(AST_ObjectGetter, function () {
return this.computed_key() ? this.key : null;
});
def_drop_side_effect_free(AST_ObjectSetter, function () {
return this.computed_key() ? this.key : null;
});
def_drop_side_effect_free(AST_Array, function(compressor, first_in_statement) {
var values = trim(this.elements, compressor, first_in_statement);
Expand Down Expand Up @@ -6414,24 +6452,22 @@ def_optimize(AST_NaN, function(self, compressor) {
});

function is_reachable(self, defs) {
var reachable = false;
var find_ref = new TreeWalker(function(node) {
if (reachable) return true;
const find_ref = node => {
if (node instanceof AST_SymbolRef && member(node.definition(), defs)) {
return reachable = true;
return walk_abort;
}
});
var scan_scope = new TreeWalker(function(node) {
if (reachable) return true;
};

return walk(self, (node, info) => {
if (node instanceof AST_Scope && node !== self) {
var parent = scan_scope.parent();
var parent = info.parent();
if (parent instanceof AST_Call && parent.expression === node) return;
node.walk(find_ref);
if (walk(node, find_ref)) {
return walk_abort;
}
return true;
}
});
self.walk(scan_scope);
return reachable;
}

const ASSIGN_OPS = makePredicate("+ - / * % >> << >>> | ^ &");
Expand Down
13 changes: 7 additions & 6 deletions lib/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -2449,7 +2449,7 @@ function parse($TEXT, options) {
}

function concise_method_or_getset(name, start, is_class) {
var get_ast = function(name, start) {
var get_method_name_ast = function(name, start) {
if (typeof name === "string" || typeof name === "number") {
return new AST_SymbolMethod({
start,
Expand All @@ -2461,7 +2461,7 @@ function parse($TEXT, options) {
}
return name;
};
const get_class_property_ast = (name) => {
const get_class_property_key_ast = (name) => {
if (typeof name === "string" || typeof name === "number") {
return new AST_SymbolClassProperty({
start: property_token,
Expand Down Expand Up @@ -2496,7 +2496,7 @@ function parse($TEXT, options) {
}
}
if (is("punc", "(")) {
name = get_ast(name, start);
name = get_method_name_ast(name, start);
var node = new AST_ConciseMethod({
start : start,
static : is_static,
Expand All @@ -2513,7 +2513,7 @@ function parse($TEXT, options) {
const setter_token = S.token;
if (name == "get") {
if (!is("punc") || is("punc", "[")) {
name = get_ast(as_property_name(), start);
name = get_method_name_ast(as_property_name(), start);
return new AST_ObjectGetter({
start : start,
static: is_static,
Expand All @@ -2526,7 +2526,7 @@ function parse($TEXT, options) {
}
} else if (name == "set") {
if (!is("punc") || is("punc", "[")) {
name = get_ast(as_property_name(), start);
name = get_method_name_ast(as_property_name(), start);
return new AST_ObjectSetter({
start : start,
static: is_static,
Expand All @@ -2539,7 +2539,7 @@ function parse($TEXT, options) {
}
}
if (is_class) {
const key = get_class_property_ast(name, property_token);
const key = get_class_property_key_ast(name, property_token);
const quote = key instanceof AST_SymbolClassProperty
? property_token.quote
: undefined;
Expand Down Expand Up @@ -2779,6 +2779,7 @@ function parse($TEXT, options) {
if (!["delete", "in", "instanceof", "new", "typeof", "void"].includes(tmp.value)) {
unexpected(tmp);
}
/* falls through */
case "name":
if (tmp.value == "yield") {
if (is_in_generator()) {
Expand Down

0 comments on commit 0e40b8d

Please sign in to comment.