diff --git a/lib/parse.js b/lib/parse.js index a0717c1f..8f57bfca 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -753,7 +753,7 @@ function parse($TEXT, options) { function embed_tokens(parser) { return function() { var start = S.token; - var expr = parser(); + var expr = parser.apply(null, arguments); var end = prev(); expr.start = start; expr.end = end; @@ -1182,17 +1182,18 @@ function parse($TEXT, options) { var a = []; var def; for (;;) { + var sym_type = in_const ? AST_SymbolConst : AST_SymbolVar; if (is("punc", "{") || is("punc", "[")) { def = new AST_VarDef({ start: S.token, - name: destructuring_(), + name: destructuring_(sym_type), 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), + name : as_symbol(sym_type), value : is("operator", "=") ? (next(), expression(false, no_in)) : null, end : prev() }) @@ -1205,12 +1206,31 @@ function parse($TEXT, options) { return a; }; - var destructuring_ = embed_tokens(function () { + var destructuring_ = embed_tokens(function (sym_type) { var is_array = is("punc", "["); var closing = is_array ? ']' : '}'; + var sym_type = sym_type || AST_SymbolRef; + + next(); + + var first = true, children = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (is("punc", closing)) break; + if (is("punc", ",")) { + children.push(new AST_Hole({ start: S.token, end: S.token })); + } else if (is("punc", "[") || is("punc", "{")) { + children.push(destructuring_(sym_type)); + } else if (is("name")) { + children.push(_make_symbol(sym_type)); + next(); + } else { + children.push(expression()); + } + } next() return new AST_Destructuring({ - names: expr_list(closing), + names: children, is_array: is_array }) }); diff --git a/test/compress/destructuring.js b/test/compress/destructuring.js index 58a77cd4..b667c9ea 100644 --- a/test/compress/destructuring.js +++ b/test/compress/destructuring.js @@ -17,3 +17,9 @@ destructuring_objects: { } } +nested_destructuring_objects: { + input: { + var [{a},b] = c; + } + expect_exact: 'var[{a},b]=c;'; +} diff --git a/test/parser.js b/test/parser.js index 85c2e23e..125f76c2 100644 --- a/test/parser.js +++ b/test/parser.js @@ -101,6 +101,17 @@ module.exports = function () { 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.equal(decls.body[0].definitions[0].value.TYPE, 'SymbolRef'); + + var nested_def = UglifyJS.parse('var [{x}] = foo').body[0].definitions[0]; + + ok.equal(nested_def.name.names[0].names[0].TYPE, 'SymbolVar') + ok.equal(nested_def.name.names[0].names[0].name, 'x') + + var holey_def = UglifyJS.parse('const [,,third] = [1,2,3]').body[0].definitions[0]; + + ok.equal(holey_def.name.names[0].TYPE, 'Hole') + ok.equal(holey_def.name.names[2].TYPE, 'SymbolConst') ok.throws(function () { // Note: this *is* a valid destructuring, but before we implement