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", {
|
var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||||
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
||||||
$propdoc: {
|
$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"
|
value: "[AST_Node?] initializer, or null of there's no initializer"
|
||||||
},
|
},
|
||||||
|
is_destructuring: function() {
|
||||||
|
return this.name instanceof AST_Destructuring;
|
||||||
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
this.name._walk(visitor);
|
this.name._walk(visitor);
|
||||||
|
|||||||
@@ -1056,6 +1056,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_Definitions && scope === self) {
|
if (node instanceof AST_Definitions && scope === self) {
|
||||||
node.definitions.forEach(function(def){
|
node.definitions.forEach(function(def){
|
||||||
|
if (def.is_destructuring()) return; /* Destructurings are type assertions! */
|
||||||
if (def.value) {
|
if (def.value) {
|
||||||
initializations.add(def.name.name, def.value);
|
initializations.add(def.name.name, def.value);
|
||||||
if (def.value.has_side_effects(compressor)) {
|
if (def.value.has_side_effects(compressor)) {
|
||||||
@@ -1142,6 +1143,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
|
if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
|
||||||
var def = node.definitions.filter(function(def){
|
var def = node.definitions.filter(function(def){
|
||||||
|
if (def.is_destructuring()) return true;
|
||||||
if (member(def.name.definition(), in_use)) return true;
|
if (member(def.name.definition(), in_use)) return true;
|
||||||
var w = {
|
var w = {
|
||||||
name : def.name.name,
|
name : def.name.name,
|
||||||
@@ -1262,6 +1264,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_Var && hoist_vars) {
|
if (node instanceof AST_Var && hoist_vars) {
|
||||||
node.definitions.forEach(function(def){
|
node.definitions.forEach(function(def){
|
||||||
|
if (def.is_destructuring()) { return; }
|
||||||
vars.set(def.name.name, def);
|
vars.set(def.name.name, def);
|
||||||
++vars_found;
|
++vars_found;
|
||||||
});
|
});
|
||||||
@@ -1702,13 +1705,23 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
AST_Definitions.DEFMETHOD("to_assignments", function(){
|
AST_Definitions.DEFMETHOD("to_assignments", function(){
|
||||||
var assignments = this.definitions.reduce(function(a, def){
|
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);
|
var name = make_node(AST_SymbolRef, def.name, def.name);
|
||||||
a.push(make_node(AST_Assign, def, {
|
a.push(make_node(AST_Assign, def, {
|
||||||
operator : "=",
|
operator : "=",
|
||||||
left : name,
|
left : name,
|
||||||
right : def.value
|
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;
|
return a;
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
25
lib/parse.js
25
lib/parse.js
@@ -1180,13 +1180,24 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
function vardefs(no_in, in_const) {
|
function vardefs(no_in, in_const) {
|
||||||
var a = [];
|
var a = [];
|
||||||
|
var def;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
a.push(new AST_VarDef({
|
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,
|
start : S.token,
|
||||||
name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
|
name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
|
||||||
value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
|
value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
|
||||||
end : prev()
|
end : prev()
|
||||||
}));
|
})
|
||||||
|
}
|
||||||
|
a.push(def);
|
||||||
if (!is("punc", ","))
|
if (!is("punc", ","))
|
||||||
break;
|
break;
|
||||||
next();
|
next();
|
||||||
@@ -1194,6 +1205,16 @@ function parse($TEXT, options) {
|
|||||||
return a;
|
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) {
|
var var_ = function(no_in) {
|
||||||
return new AST_Var({
|
return new AST_Var({
|
||||||
start : prev(),
|
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: {
|
keep_fnames: {
|
||||||
options = { unused: true, keep_fnames: true, unsafe: true };
|
options = { unused: true, keep_fnames: true, unsafe: true };
|
||||||
input: {
|
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] { })');
|
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 () {
|
ok.throws(function () {
|
||||||
// Note: this *is* a valid destructuring, but before we implement
|
// Note: this *is* a valid destructuring, but before we implement
|
||||||
// destructuring (right now it's only destructuring *arguments*),
|
// destructuring (right now it's only destructuring *arguments*),
|
||||||
|
|||||||
Reference in New Issue
Block a user