From f07ab4666fdc2358e342c2037f7ad94f97a205d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Santos?= Date: Sun, 22 Nov 2015 17:40:05 +0000 Subject: [PATCH 1/4] Non-destructuring default parameters --- lib/ast.js | 17 ++++++++++++++++- lib/output.js | 18 +++++++++++++++--- test/compress/harmony.js | 8 ++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/ast.js b/lib/ast.js index 8dadf21c..281912f7 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -422,6 +422,13 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", { is_array: true, names: ex.elements.map(to_fun_args) }); + } else if (ex instanceof AST_Assign && ex.left instanceof AST_Symbol) { + return new AST_SymbolFunarg({ + name: ex.left.name, + default: ex.right, + start: ex.start, + end: ex.end + }); } else { croak("Invalid function parameter", ex.start.line, ex.start.col); } @@ -983,8 +990,16 @@ var AST_SymbolConst = DEFNODE("SymbolConst", null, { $documentation: "A constant declaration" }, AST_SymbolDeclaration); -var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { +var AST_SymbolFunarg = DEFNODE("SymbolFunarg", "default", { $documentation: "Symbol naming a function argument", + $propdoc: { + default: "[AST_Expression] The default for this parameter. For example, `= 6`" + }, + _walk: function (visitor) { + return visitor._visit(this, function() { + if (this.default) this.default._walk(visitor); + }); + } }, AST_SymbolVar); var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { diff --git a/lib/output.js b/lib/output.js index b0dc64ce..f1dc1ad1 100644 --- a/lib/output.js +++ b/lib/output.js @@ -1225,9 +1225,21 @@ function OutputStream(options) { output.space(); self.value.print(output); }); - DEFPRINT(AST_Symbol, function(self, output){ - var def = self.definition(); - output.print_name(def ? def.mangled_name || def.name : self.name); + AST_Symbol.DEFMETHOD("_do_print", function(output){ + var def = this.definition(); + output.print_name(def ? def.mangled_name || def.name : this.name); + }); + DEFPRINT(AST_Symbol, function (self, output) { + self._do_print(output); + }); + DEFPRINT(AST_SymbolFunarg, function(self, output){ + self._do_print(output); + if (self.default) { + output.space(); + output.print('='); + output.space(); + self.default.print(output) + } }); DEFPRINT(AST_ObjectSymbol, function(self, output){ var name = self.mangled_key || self.symbol.name; diff --git a/test/compress/harmony.js b/test/compress/harmony.js index 731976f3..90836e5e 100644 --- a/test/compress/harmony.js +++ b/test/compress/harmony.js @@ -132,6 +132,14 @@ destructuring_arguments: { } } +default_arguments: { + input: { + function x(a = 6) { } + function x(a = (6 + 5)) { } + } + expect_exact: "function x(a=6){}function x(a=6+5){}" +} + concise_methods: { input: { x = { From cbcb3ac44e4fe5a56135aae358c3da6e849502d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Santos?= Date: Sun, 22 Nov 2015 18:02:35 +0000 Subject: [PATCH 2/4] Destructuring parameters with defaults. `function x({ foo, bar } = {}) { }` --- lib/ast.js | 16 +++++++--------- lib/output.js | 6 ++++++ test/compress/harmony.js | 3 ++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/ast.js b/lib/ast.js index 281912f7..e58dcba2 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -384,7 +384,7 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", { as_params: function (croak) { // We don't want anything which doesn't belong in a destructuring var root = this; - return this.expressions.map(function to_fun_args(ex) { + return this.expressions.map(function to_fun_args(ex, _, __, default_seen_above) { if (ex instanceof AST_Object) { if (ex.properties.length == 0) croak("Invalid destructuring function parameter", ex.start.line, ex.start.col); @@ -392,6 +392,7 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", { start: ex.start, end: ex.end, is_array: false, + default: default_seen_above, names: ex.properties.map(to_fun_args) }); } else if (ex instanceof AST_ObjectSymbol) { @@ -408,6 +409,7 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", { } else if (ex instanceof AST_SymbolRef) { return new AST_SymbolFunarg({ name: ex.name, + default: default_seen_above, start: ex.start, end: ex.end }); @@ -420,15 +422,11 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", { start: ex.start, end: ex.end, is_array: true, + default: default_seen_above, names: ex.elements.map(to_fun_args) }); - } else if (ex instanceof AST_Assign && ex.left instanceof AST_Symbol) { - return new AST_SymbolFunarg({ - name: ex.left.name, - default: ex.right, - start: ex.start, - end: ex.end - }); + } else if (ex instanceof AST_Assign) { + return to_fun_args(ex.left, undefined, undefined, ex.right); } else { croak("Invalid function parameter", ex.start.line, ex.start.col); } @@ -489,7 +487,7 @@ var AST_Defun = DEFNODE("Defun", null, { }, AST_Lambda); /* -----[ DESTRUCTURING ]----- */ -var AST_Destructuring = DEFNODE("Destructuring", "names is_array", { +var AST_Destructuring = DEFNODE("Destructuring", "names is_array default", { $documentation: "A destructuring of several names. Used in destructuring assignment and with destructuring function argument names", _walk: function(visitor) { return visitor._visit(this, function(){ diff --git a/lib/output.js b/lib/output.js index f1dc1ad1..b2f34720 100644 --- a/lib/output.js +++ b/lib/output.js @@ -631,6 +631,12 @@ function OutputStream(options) { name.print(output); }) output.print(self.is_array ? "]" : "}"); + if (self.default) { + output.space(); + output.print('='); + output.space(); + self.default.print(output) + } }) DEFPRINT(AST_Debugger, function(self, output){ diff --git a/test/compress/harmony.js b/test/compress/harmony.js index 90836e5e..986dcd18 100644 --- a/test/compress/harmony.js +++ b/test/compress/harmony.js @@ -136,8 +136,9 @@ default_arguments: { input: { function x(a = 6) { } function x(a = (6 + 5)) { } + function x({ foo } = {}, [ bar ] = [ 1 ]) { } } - expect_exact: "function x(a=6){}function x(a=6+5){}" + expect_exact: "function x(a=6){}function x(a=6+5){}function x({foo}={},[bar]=[1]){}" } concise_methods: { From 59e999597ee84c889e78fbd9c29ae81c0dc21bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Santos?= Date: Sun, 22 Nov 2015 19:00:54 +0000 Subject: [PATCH 3/4] Move the idea of a symbol having a default value up the class chain. --- lib/ast.js | 20 +++++++++----------- lib/output.js | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/ast.js b/lib/ast.js index e58dcba2..e0f5fa75 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -973,10 +973,16 @@ var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, { $documentation: "The name of a property accessor (setter/getter function)" }, AST_Symbol); -var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", { +var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init default", { $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)", $propdoc: { - init: "[AST_Node*/S] array of initializers for this declaration." + init: "[AST_Node*/S] array of initializers for this declaration.", + default: "[AST_Expression] The default for this parameter. For example, `= 6`" + }, + _walk: function (visitor) { + return visitor._visit(this, function() { + if (this.default) this.default._walk(visitor); + }); } }, AST_Symbol); @@ -988,16 +994,8 @@ var AST_SymbolConst = DEFNODE("SymbolConst", null, { $documentation: "A constant declaration" }, AST_SymbolDeclaration); -var AST_SymbolFunarg = DEFNODE("SymbolFunarg", "default", { +var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { $documentation: "Symbol naming a function argument", - $propdoc: { - default: "[AST_Expression] The default for this parameter. For example, `= 6`" - }, - _walk: function (visitor) { - return visitor._visit(this, function() { - if (this.default) this.default._walk(visitor); - }); - } }, AST_SymbolVar); var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { diff --git a/lib/output.js b/lib/output.js index b2f34720..a4b02725 100644 --- a/lib/output.js +++ b/lib/output.js @@ -1238,7 +1238,7 @@ function OutputStream(options) { DEFPRINT(AST_Symbol, function (self, output) { self._do_print(output); }); - DEFPRINT(AST_SymbolFunarg, function(self, output){ + DEFPRINT(AST_SymbolDeclaration, function(self, output){ self._do_print(output); if (self.default) { output.space(); From 8220dbbea0d2438931d17b1c8581f644606ad122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Santos?= Date: Sun, 22 Nov 2015 19:04:42 +0000 Subject: [PATCH 4/4] Default values inside destructurings --- lib/parse.js | 24 +++++++++++++++++++++--- test/compress/harmony.js | 10 ++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/parse.js b/lib/parse.js index 4ed32863..237977ee 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1249,8 +1249,12 @@ function parse($TEXT, options) { })); next(); } else if (is("name")) { - children.push(_make_symbol(sym_type)); - next(); + children.push(new (sym_type)({ + name : String(S.token.value), + start : S.token, + default: (next(), is("operator", "=")) ? (next(), expression(false)) : undefined, + end : S.token + })); } else { children.push(expression()); } @@ -1485,7 +1489,21 @@ function parse($TEXT, options) { continue; } - if (!is("punc", ":")) { + if (is("operator", "=")) { + next(); + a.push(new AST_Assign({ + start: start, + // Symbol class doesn't matter. This is only meant to carry the symbol name into .as_params() since this is not normally valid. + left: new AST_SymbolRef({ + start: start, + end: start, + name: name + }), + operator: "=", + right: expression(false), + end: prev() + })); + } else if (!is("punc", ":")) { // It's one of those object destructurings, the value is its own name a.push(new AST_ObjectSymbol({ start: start, diff --git a/test/compress/harmony.js b/test/compress/harmony.js index 986dcd18..a3910ac6 100644 --- a/test/compress/harmony.js +++ b/test/compress/harmony.js @@ -141,6 +141,16 @@ default_arguments: { expect_exact: "function x(a=6){}function x(a=6+5){}function x({foo}={},[bar]=[1]){}" } +default_values_in_destructurings: { + input: { + function x({a=(4), b}) {} + function x([b, c=(12)]) {} + var { x = (6), y } = x; + var [ x, y = (6) ] = x; + } + expect_exact: "function x({a=4,b}){}function x([b,c=12]){}var{x=6,y}=x;var[x,y=6]=x;" +} + concise_methods: { input: { x = {