@@ -978,12 +978,12 @@ function OutputStream(options) {
|
||||
AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){
|
||||
var self = this;
|
||||
if (!nokeyword) {
|
||||
if (this.async) {
|
||||
if (self.async) {
|
||||
output.print("async");
|
||||
output.space();
|
||||
}
|
||||
output.print("function");
|
||||
if (this.is_generator) {
|
||||
if (self.is_generator) {
|
||||
output.star();
|
||||
}
|
||||
if (self.name) {
|
||||
@@ -1038,6 +1038,10 @@ function OutputStream(options) {
|
||||
var needs_parens = parent instanceof AST_Binary ||
|
||||
parent instanceof AST_Unary ||
|
||||
(parent instanceof AST_Call && self === parent.expression);
|
||||
if (self.async) {
|
||||
output.print("async");
|
||||
output.space();
|
||||
}
|
||||
if (needs_parens) { output.print("(") }
|
||||
if (self.argnames.length === 1 && self.argnames[0] instanceof AST_Symbol) {
|
||||
self.argnames[0].print(output);
|
||||
@@ -1053,9 +1057,9 @@ function OutputStream(options) {
|
||||
output.print('=>');
|
||||
output.space();
|
||||
if (self.body instanceof AST_Node) {
|
||||
this.body.print(output);
|
||||
self.body.print(output);
|
||||
} else {
|
||||
print_bracketed(this.body, output);
|
||||
print_bracketed(self.body, output);
|
||||
}
|
||||
if (needs_parens) { output.print(")") }
|
||||
});
|
||||
|
||||
61
lib/parse.js
61
lib/parse.js
@@ -1281,18 +1281,19 @@ function parse($TEXT, options) {
|
||||
});
|
||||
};
|
||||
|
||||
var arrow_function = function(start, argnames) {
|
||||
var arrow_function = function(start, argnames, is_async) {
|
||||
if (S.token.nlb) {
|
||||
croak("Unexpected newline before arrow (=>)");
|
||||
}
|
||||
|
||||
expect_token("arrow", "=>");
|
||||
|
||||
var body = _function_body(is("punc", "{"));
|
||||
var body = _function_body(is("punc", "{"), false, is_async);
|
||||
|
||||
return new AST_Arrow({
|
||||
start : start,
|
||||
end : body.end,
|
||||
async : is_async,
|
||||
argnames : argnames,
|
||||
body : body
|
||||
});
|
||||
@@ -1989,21 +1990,26 @@ function parse($TEXT, options) {
|
||||
}
|
||||
}
|
||||
|
||||
var expr_atom = function(allow_calls) {
|
||||
var expr_atom = function(allow_calls, allow_arrows) {
|
||||
if (is("operator", "new")) {
|
||||
return new_(allow_calls);
|
||||
}
|
||||
var start = S.token;
|
||||
var async = is("name", "async") && as_atom_node();
|
||||
if (is("punc")) {
|
||||
switch (start.value) {
|
||||
switch (S.token.value) {
|
||||
case "(":
|
||||
if (async && !allow_calls) break;
|
||||
next();
|
||||
var exprs = params_or_seq_();
|
||||
expect(")");
|
||||
if (is("arrow", "=>")) {
|
||||
return arrow_function(start, exprs.map(to_fun_args));
|
||||
if (allow_arrows && is("arrow", "=>")) {
|
||||
return arrow_function(start, exprs.map(to_fun_args), !!async);
|
||||
}
|
||||
var ex = exprs.length == 1 ? exprs[0] : new AST_Sequence({
|
||||
var ex = async ? new AST_Call({
|
||||
expression: async,
|
||||
args: exprs
|
||||
}) : exprs.length == 1 ? exprs[0] : new AST_Sequence({
|
||||
expressions: exprs
|
||||
});
|
||||
ex.start = start;
|
||||
@@ -2014,23 +2020,25 @@ function parse($TEXT, options) {
|
||||
case "{":
|
||||
return subscripts(object_or_destructuring_(), allow_calls);
|
||||
}
|
||||
unexpected();
|
||||
if (!async) unexpected();
|
||||
}
|
||||
if (is("name", "async") && is_token(peek(), "keyword", "function")) {
|
||||
if (allow_arrows && is("name") && is_token(peek(), "arrow")) {
|
||||
var param = new AST_SymbolFunarg({
|
||||
name: S.token.value,
|
||||
start: start,
|
||||
end: start,
|
||||
});
|
||||
next();
|
||||
next();
|
||||
var func = function_(AST_Function, false, true);
|
||||
func.start = start;
|
||||
func.end = prev();
|
||||
return subscripts(func, allow_calls);
|
||||
return arrow_function(start, [param], !!async);
|
||||
}
|
||||
if (is("keyword", "function")) {
|
||||
next();
|
||||
var func = function_(AST_Function);
|
||||
var func = function_(AST_Function, false, !!async);
|
||||
func.start = start;
|
||||
func.end = prev();
|
||||
return subscripts(func, allow_calls);
|
||||
}
|
||||
if (async) return subscripts(async, allow_calls);
|
||||
if (is("keyword", "class")) {
|
||||
next();
|
||||
var cls = class_(AST_ClassExpression);
|
||||
@@ -2619,7 +2627,7 @@ function parse($TEXT, options) {
|
||||
return args;
|
||||
});
|
||||
|
||||
var maybe_unary = function(allow_calls) {
|
||||
var maybe_unary = function(allow_calls, allow_arrows) {
|
||||
var start = S.token;
|
||||
if (start.type == "name" && start.value == "await") {
|
||||
if (is_in_async()) {
|
||||
@@ -2637,8 +2645,9 @@ function parse($TEXT, options) {
|
||||
ex.end = prev();
|
||||
return ex;
|
||||
}
|
||||
var val = expr_atom(allow_calls);
|
||||
var val = expr_atom(allow_calls, allow_arrows);
|
||||
while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
|
||||
if (val instanceof AST_Arrow) unexpected();
|
||||
val = make_unary(AST_UnaryPostfix, S.token, val);
|
||||
val.start = start;
|
||||
val.end = S.token;
|
||||
@@ -2686,7 +2695,7 @@ function parse($TEXT, options) {
|
||||
};
|
||||
|
||||
function expr_ops(no_in) {
|
||||
return expr_op(maybe_unary(true), 0, no_in);
|
||||
return expr_op(maybe_unary(true, true), 0, no_in);
|
||||
};
|
||||
|
||||
var maybe_conditional = function(no_in) {
|
||||
@@ -2767,22 +2776,6 @@ function parse($TEXT, options) {
|
||||
}
|
||||
}
|
||||
|
||||
if (start.type == "punc" && start.value == "(" && peek().value == ")") {
|
||||
next();
|
||||
next();
|
||||
return arrow_function(start, []);
|
||||
}
|
||||
|
||||
if (is("name") && is_token(peek(), "arrow")) {
|
||||
var param = new AST_SymbolFunarg({
|
||||
name: start.value,
|
||||
start: start,
|
||||
end: start,
|
||||
});
|
||||
next();
|
||||
return arrow_function(start, [param]);
|
||||
}
|
||||
|
||||
var left = maybe_conditional(no_in);
|
||||
var val = S.token.value;
|
||||
|
||||
|
||||
@@ -202,3 +202,11 @@ arrow_unused_toplevel: {
|
||||
expect_stdout: [ "0", "1", "2", "9" ]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
no_leading_parentheses: {
|
||||
input: {
|
||||
(x,y) => x(y);
|
||||
async (x,y) => await x(y);
|
||||
}
|
||||
expect_exact: "(x,y)=>x(y);async(x,y)=>await x(y);"
|
||||
}
|
||||
|
||||
@@ -230,16 +230,26 @@ async_shorthand_property: {
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
/* FIXME: add test when supported by parser
|
||||
async_arrow: {
|
||||
input: {
|
||||
let a1 = async x => await foo(x);
|
||||
let a2 = async () => await bar();
|
||||
let a3 = async (x) => await baz(x);
|
||||
let a4 = async (x, y) => { await far(x, y); }
|
||||
let a5 = async ({x = [1], y: z = 2}) => { await wow(x, y); }
|
||||
let a5 = async ({x = [1], y: z = 2}) => { await wow(x, z); }
|
||||
}
|
||||
expect: {
|
||||
let a1 = async x => await foo(x);
|
||||
let a2 = async () => await bar();
|
||||
let a3 = async (x) => await baz(x);
|
||||
let a4 = async (x, y) => { await far(x, y); }
|
||||
let a5 = async ({x = [1], y: z = 2}) => { await wow(x, z); }
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
async_arrow_wait: {
|
||||
input: {
|
||||
var a = async (x, y) => await x(y);
|
||||
}
|
||||
expect_exact: "var a=async(x,y)=>await x(y);"
|
||||
}
|
||||
|
||||
@@ -16,9 +16,12 @@ typeof_arrow_functions: {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = typeof (x) => null;
|
||||
var foo = typeof (x => null);
|
||||
console.log(foo);
|
||||
}
|
||||
expect_exact: "var foo=\"function\";"
|
||||
expect_exact: "var foo=\"function\";console.log(foo);"
|
||||
expect_stdout: "function"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
classes: {
|
||||
|
||||
@@ -62,23 +62,20 @@ describe("Arrow functions", function() {
|
||||
}
|
||||
});
|
||||
it("Should not accept arrow functions in the middle or end of an expression", function() {
|
||||
var tests = [
|
||||
[
|
||||
"0 + x => 0",
|
||||
"0 + async x => 0",
|
||||
"typeof x => 0",
|
||||
"0 + x => 0"
|
||||
];
|
||||
var test = function(code) {
|
||||
return function() {
|
||||
"typeof async x => 0",
|
||||
"typeof (x) => null",
|
||||
"typeof async (x) => null",
|
||||
].forEach(function(code) {
|
||||
assert.throws(function() {
|
||||
uglify.parse(code);
|
||||
}
|
||||
}
|
||||
var error = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
e.message === "Unexpected token: arrow (=>)";
|
||||
}
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(test(tests[i]), error);
|
||||
}
|
||||
}, function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error && /^Unexpected /.test(e.message);
|
||||
}, code);
|
||||
});
|
||||
});
|
||||
|
||||
it("Should parse a function containing default assignment correctly", function() {
|
||||
|
||||
Reference in New Issue
Block a user