Improve binding patterns for arrow functions
This commit is contained in:
committed by
Richard van Velzen
parent
947b8750e8
commit
32c2cc33bb
49
lib/ast.js
49
lib/ast.js
@@ -394,8 +394,6 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", {
|
||||
var root = this;
|
||||
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);
|
||||
return new AST_Destructuring({
|
||||
start: ex.start,
|
||||
end: ex.end,
|
||||
@@ -403,12 +401,16 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", {
|
||||
default: default_seen_above,
|
||||
names: ex.properties.map(to_fun_args)
|
||||
});
|
||||
} else if (ex instanceof AST_ObjectKeyVal && ex.shorthand) {
|
||||
return new AST_SymbolFunarg({
|
||||
name: ex.key,
|
||||
start: ex.start,
|
||||
end: ex.end
|
||||
});
|
||||
} else if (ex instanceof AST_ObjectKeyVal ||
|
||||
ex instanceof AST_ObjectComputedKeyVal
|
||||
) {
|
||||
if (ex.key instanceof AST_SymbolRef) {
|
||||
ex.key = to_fun_args(ex.key, 0, [ex.key], ex.default);
|
||||
}
|
||||
ex.value = to_fun_args(ex.value, 0, [ex.key], ex.default);
|
||||
return ex;
|
||||
} else if (ex instanceof AST_Hole) {
|
||||
return ex;
|
||||
} else if (ex instanceof AST_Destructuring) {
|
||||
if (ex.names.length == 0)
|
||||
croak("Invalid destructuring function parameter", ex.start.line, ex.start.col);
|
||||
@@ -424,8 +426,6 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", {
|
||||
} else if (ex instanceof AST_Expansion) {
|
||||
return ex;
|
||||
} else if (ex instanceof AST_Array) {
|
||||
if (ex.elements.length === 0)
|
||||
croak("Invalid destructuring function parameter", ex.start.line, ex.start.col);
|
||||
return new AST_Destructuring({
|
||||
start: ex.start,
|
||||
end: ex.end,
|
||||
@@ -494,6 +494,11 @@ var AST_Defun = DEFNODE("Defun", null, {
|
||||
/* -----[ DESTRUCTURING ]----- */
|
||||
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",
|
||||
$propdoc: {
|
||||
"names": "[AST_Destructuring|AST_Expansion|AST_Hole|AST_ObjectKeyVal|AST_Symbol] Array of properties or elements",
|
||||
"is_array": "[Boolean] Whether the destructuring represents an object or array",
|
||||
"default": "[AST_Node?] Default assign value"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.names.forEach(function(name){
|
||||
@@ -1001,11 +1006,11 @@ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
||||
}
|
||||
});
|
||||
|
||||
var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote shorthand", {
|
||||
var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote default", {
|
||||
$documentation: "A key: value object property",
|
||||
$propdoc: {
|
||||
quote: "[string] the original quote character",
|
||||
shorthand: "[boolean] whether this is a shorthand key:value pair, expressed as just the key."
|
||||
default: "[AST_Expression] The default parameter value, only used when nested inside a binding pattern"
|
||||
}
|
||||
}, AST_ObjectProperty);
|
||||
|
||||
@@ -1068,13 +1073,19 @@ var AST_ClassExpression = DEFNODE("ClassExpression", null, {
|
||||
$documentation: "A class expression."
|
||||
}, AST_Class);
|
||||
|
||||
var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
|
||||
var AST_Symbol = DEFNODE("Symbol", "scope name thedef default", {
|
||||
$propdoc: {
|
||||
name: "[string] name of this symbol",
|
||||
scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
|
||||
thedef: "[SymbolDef/S] the definition of this symbol"
|
||||
thedef: "[SymbolDef/S] the definition of this symbol",
|
||||
default: "[AST_Expression] The default parameter value, only used when nested inside a binding pattern"
|
||||
},
|
||||
$documentation: "Base class for all symbols",
|
||||
_walk: function (visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
if (this.default) this.default._walk(visitor);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var AST_NewTarget = DEFNODE("NewTarget", null, {
|
||||
@@ -1085,17 +1096,11 @@ var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
|
||||
$documentation: "The name of a property accessor (setter/getter function)"
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init default", {
|
||||
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
|
||||
$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.",
|
||||
default: "[AST_Expression] The default for this parameter. For example, `= 6`"
|
||||
init: "[AST_Node*/S] array of initializers for this declaration."
|
||||
},
|
||||
_walk: function (visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
if (this.default) this.default._walk(visitor);
|
||||
});
|
||||
}
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolVar = DEFNODE("SymbolVar", null, {
|
||||
|
||||
@@ -69,11 +69,16 @@ function OutputStream(options) {
|
||||
preamble : null,
|
||||
quote_style : 0,
|
||||
keep_quoted_props: false,
|
||||
shorthand : undefined,
|
||||
ecma : 5,
|
||||
}, true);
|
||||
|
||||
if (typeof options.ascii_identifiers === 'undefined')
|
||||
options.ascii_identifiers = options.ascii_only;
|
||||
|
||||
if (options.shorthand === undefined)
|
||||
options.shorthand = options.ecma > 5;
|
||||
|
||||
var indentation = 0;
|
||||
var current_col = 0;
|
||||
var current_line = 1;
|
||||
@@ -728,9 +733,15 @@ function OutputStream(options) {
|
||||
DEFPRINT(AST_Destructuring, function (self, output) {
|
||||
output.print(self.is_array ? "[" : "{");
|
||||
var first = true;
|
||||
self.names.forEach(function (name) {
|
||||
var len = self.names.length;
|
||||
self.names.forEach(function (name, i) {
|
||||
if (first) first = false; else { output.comma(); output.space(); }
|
||||
name.print(output);
|
||||
// If the final element is a hole, we need to make sure it
|
||||
// doesn't look like a trailing comma, by inserting an actual
|
||||
// trailing comma.
|
||||
if (i === len - 1 && name instanceof AST_Hole)
|
||||
output.comma();
|
||||
})
|
||||
output.print(self.is_array ? "]" : "}");
|
||||
if (self.default) {
|
||||
@@ -739,7 +750,7 @@ function OutputStream(options) {
|
||||
output.space();
|
||||
self.default.print(output)
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
DEFPRINT(AST_Debugger, function(self, output){
|
||||
output.print("debugger");
|
||||
@@ -1444,17 +1455,21 @@ function OutputStream(options) {
|
||||
}
|
||||
});
|
||||
DEFPRINT(AST_ObjectKeyVal, function(self, output){
|
||||
var print_as_shorthand = self.shorthand &&
|
||||
self.value instanceof AST_Symbol &&
|
||||
self.key == self.value.print_to_string();
|
||||
|
||||
if (print_as_shorthand) {
|
||||
output.print_name(self.key);
|
||||
return;
|
||||
function get_name(self) {
|
||||
var def = self.value.definition();
|
||||
return def ? def.mangled_name || def.name : self.value.name;
|
||||
}
|
||||
if (output.option("shorthand") &&
|
||||
self.value instanceof AST_Symbol &&
|
||||
is_identifier_string(self.key) &&
|
||||
get_name(self) === self.key
|
||||
) {
|
||||
self.print_property_name(self.key, self.quote, output);
|
||||
} else {
|
||||
self.print_property_name(self.key, self.quote, output);
|
||||
output.colon();
|
||||
self.value.print(output);
|
||||
}
|
||||
self.print_property_name(self.key, self.quote, output);
|
||||
output.colon();
|
||||
self.value.print(output);
|
||||
if (self.default) {
|
||||
output.space();
|
||||
output.print('=');
|
||||
|
||||
15
lib/parse.js
15
lib/parse.js
@@ -1232,6 +1232,10 @@ function parse($TEXT, options) {
|
||||
};
|
||||
|
||||
var arrow_function = function(args) {
|
||||
if (S.token.nlb) {
|
||||
croak("SyntaxError: Unexpected newline before arrow (=>)");
|
||||
}
|
||||
|
||||
expect_token("arrow", "=>");
|
||||
|
||||
var argnames;
|
||||
@@ -1425,12 +1429,13 @@ function parse($TEXT, options) {
|
||||
if (is("punc")) {
|
||||
switch (S.token.value) {
|
||||
case ",":
|
||||
case "]": // Last element
|
||||
elements.push(new AST_Hole({
|
||||
start: S.token,
|
||||
end: S.token
|
||||
}));
|
||||
continue;
|
||||
case "]": // Trailing comma after last element
|
||||
break;
|
||||
case "[":
|
||||
case "{":
|
||||
elements.push(binding_element(used_parameters, symbol_type));
|
||||
@@ -1560,7 +1565,7 @@ function parse($TEXT, options) {
|
||||
next();
|
||||
a.push(new AST_Expansion({
|
||||
start: prev(),
|
||||
expression: as_symbol(AST_SymbolFunarg),
|
||||
expression: binding_element(undefined, AST_SymbolFunarg),
|
||||
end: S.token,
|
||||
}));
|
||||
if (!is("punc", ")")) {
|
||||
@@ -2011,15 +2016,13 @@ function parse($TEXT, options) {
|
||||
// It's one of those object destructurings, the value is its own name
|
||||
a.push(new AST_ObjectKeyVal({
|
||||
start: start,
|
||||
quote: start.quote,
|
||||
end: start,
|
||||
key: name,
|
||||
value: new AST_SymbolRef({
|
||||
start: start,
|
||||
end: start,
|
||||
end: prev(),
|
||||
name: name
|
||||
}),
|
||||
shorthand: true,
|
||||
end: start,
|
||||
}));
|
||||
} else {
|
||||
expect(":");
|
||||
|
||||
@@ -567,10 +567,12 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
||||
else if (node instanceof AST_With)
|
||||
base54.consider("with");
|
||||
else if (node instanceof AST_ObjectSetter)
|
||||
base54.consider("set" + node.key);
|
||||
base54.consider("set" + (typeof node.key === "string" ? node.key : ""));
|
||||
else if (node instanceof AST_ObjectGetter)
|
||||
base54.consider("get" + node.key);
|
||||
else if (node instanceof AST_ObjectKeyVal)
|
||||
base54.consider("get" + (typeof node.key === "string" ? node.key : ""));
|
||||
else if (node instanceof AST_ObjectKeyVal && typeof node.key === "string")
|
||||
base54.consider(node.key);
|
||||
else if (node instanceof AST_ConciseMethod && typeof node.key === "string")
|
||||
base54.consider(node.key);
|
||||
else if (node instanceof AST_New)
|
||||
base54.consider("new");
|
||||
|
||||
Reference in New Issue
Block a user