Parse and compress destructuring VarDefs
This commit is contained in:
committed by
Richard van Velzen
parent
824ecfb8a2
commit
c44c2d6c21
@@ -665,9 +665,12 @@ var AST_Const = DEFNODE("Const", null, {
|
||||
var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
|
||||
name: "[AST_SymbolVar|AST_SymbolConst|AST_Destructuring] name of the variable",
|
||||
value: "[AST_Node?] initializer, or null of there's no initializer"
|
||||
},
|
||||
is_destructuring: function() {
|
||||
return this.name instanceof AST_Destructuring;
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.name._walk(visitor);
|
||||
|
||||
@@ -1056,6 +1056,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
if (node instanceof AST_Definitions && scope === self) {
|
||||
node.definitions.forEach(function(def){
|
||||
if (def.is_destructuring()) return; /* Destructurings are type assertions! */
|
||||
if (def.value) {
|
||||
initializations.add(def.name.name, def.value);
|
||||
if (def.value.has_side_effects(compressor)) {
|
||||
@@ -1142,6 +1143,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
|
||||
var def = node.definitions.filter(function(def){
|
||||
if (def.is_destructuring()) return true;
|
||||
if (member(def.name.definition(), in_use)) return true;
|
||||
var w = {
|
||||
name : def.name.name,
|
||||
@@ -1262,6 +1264,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
if (node instanceof AST_Var && hoist_vars) {
|
||||
node.definitions.forEach(function(def){
|
||||
if (def.is_destructuring()) { return; }
|
||||
vars.set(def.name.name, def);
|
||||
++vars_found;
|
||||
});
|
||||
@@ -1702,13 +1705,23 @@ merge(Compressor.prototype, {
|
||||
|
||||
AST_Definitions.DEFMETHOD("to_assignments", function(){
|
||||
var assignments = this.definitions.reduce(function(a, def){
|
||||
if (def.value) {
|
||||
if (def.value && !def.is_destructuring()) {
|
||||
var name = make_node(AST_SymbolRef, def.name, def.name);
|
||||
a.push(make_node(AST_Assign, def, {
|
||||
operator : "=",
|
||||
left : name,
|
||||
right : def.value
|
||||
}));
|
||||
} else if (def.value) {
|
||||
// Because it's a destructuring, do not turn into an assignment.
|
||||
var varDef = make_node(AST_VarDef, def, {
|
||||
name: def.name,
|
||||
value: def.value
|
||||
});
|
||||
var var_ = make_node(AST_Var, def, {
|
||||
definitions: [ varDef ]
|
||||
});
|
||||
a.push(var_);
|
||||
}
|
||||
return a;
|
||||
}, []);
|
||||
|
||||
33
lib/parse.js
33
lib/parse.js
@@ -1180,13 +1180,24 @@ function parse($TEXT, options) {
|
||||
|
||||
function vardefs(no_in, in_const) {
|
||||
var a = [];
|
||||
var def;
|
||||
for (;;) {
|
||||
a.push(new AST_VarDef({
|
||||
start : S.token,
|
||||
name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
|
||||
value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
|
||||
end : prev()
|
||||
}));
|
||||
if (is("punc", "{") || is("punc", "[")) {
|
||||
def = new AST_VarDef({
|
||||
start: S.token,
|
||||
name: destructuring_(),
|
||||
value: (expect_token("operator", "="), expression(false, no_in)),
|
||||
end: prev()
|
||||
});
|
||||
} else {
|
||||
def = new AST_VarDef({
|
||||
start : S.token,
|
||||
name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
|
||||
value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
|
||||
end : prev()
|
||||
})
|
||||
}
|
||||
a.push(def);
|
||||
if (!is("punc", ","))
|
||||
break;
|
||||
next();
|
||||
@@ -1194,6 +1205,16 @@ function parse($TEXT, options) {
|
||||
return a;
|
||||
};
|
||||
|
||||
var destructuring_ = embed_tokens(function () {
|
||||
var is_array = is("punc", "[");
|
||||
var closing = is_array ? ']' : '}';
|
||||
next()
|
||||
return new AST_Destructuring({
|
||||
names: expr_list(closing),
|
||||
is_array: is_array
|
||||
})
|
||||
});
|
||||
|
||||
var var_ = function(no_in) {
|
||||
return new AST_Var({
|
||||
start : prev(),
|
||||
|
||||
19
test/compress/destructuring.js
Normal file
19
test/compress/destructuring.js
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
destructuring_arrays: {
|
||||
input: {
|
||||
var [aa, bb] = cc;
|
||||
}
|
||||
expect: {
|
||||
var[aa,bb]=cc;
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_objects: {
|
||||
input: {
|
||||
var {aa, bb} = {aa:1, bb:2};
|
||||
}
|
||||
expect: {
|
||||
var{aa,bb}={aa:1,bb:2};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +164,21 @@ used_var_in_catch: {
|
||||
}
|
||||
}
|
||||
|
||||
unused_keep_harmony_destructuring: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
var {x, y} = foo;
|
||||
var a = foo;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
var {x, y} = foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keep_fnames: {
|
||||
options = { unused: true, keep_fnames: true, unsafe: true };
|
||||
input: {
|
||||
|
||||
@@ -65,3 +65,21 @@ hoist_no_destructurings: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dont_hoist_var_destructurings: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
hoist_funs: true
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
// If foo is null or undefined, this should be an exception
|
||||
var {x,y} = foo;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
var {x,y} = foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,14 @@ module.exports = function () {
|
||||
UglifyJS.parse('(function [a] { })');
|
||||
});
|
||||
|
||||
// Destructuring variable declaration
|
||||
|
||||
var decls = UglifyJS.parse('var {a,b} = foo, { c, d } = bar');
|
||||
|
||||
ok.equal(decls.body[0].TYPE, 'Var');
|
||||
ok.equal(decls.body[0].definitions.length, 2);
|
||||
ok.equal(decls.body[0].definitions[0].name.TYPE, 'Destructuring');
|
||||
|
||||
ok.throws(function () {
|
||||
// Note: this *is* a valid destructuring, but before we implement
|
||||
// destructuring (right now it's only destructuring *arguments*),
|
||||
|
||||
Reference in New Issue
Block a user