Adding arrow functions
This commit is contained in:
@@ -142,7 +142,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
|||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
function walk_body(node, visitor) {
|
function walk_body(node, visitor) {
|
||||||
if (node.body instanceof AST_Statement) {
|
if (node.body instanceof AST_Node) {
|
||||||
node.body._walk(visitor);
|
node.body._walk(visitor);
|
||||||
}
|
}
|
||||||
else node.body.forEach(function(stat){
|
else node.body.forEach(function(stat){
|
||||||
|
|||||||
@@ -1019,6 +1019,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_Block, function(self, compressor){
|
OPT(AST_Block, function(self, compressor){
|
||||||
|
if (self.body instanceof AST_Node) { return self; }
|
||||||
self.body = tighten_body(self.body, compressor);
|
self.body = tighten_body(self.body, compressor);
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
@@ -1225,6 +1226,7 @@ merge(Compressor.prototype, {
|
|||||||
var hoist_funs = compressor.option("hoist_funs");
|
var hoist_funs = compressor.option("hoist_funs");
|
||||||
var hoist_vars = compressor.option("hoist_vars");
|
var hoist_vars = compressor.option("hoist_vars");
|
||||||
var self = this;
|
var self = this;
|
||||||
|
if (!(self.body instanceof Array)) { return self; } // Hoisting makes no sense in an arrow func
|
||||||
if (hoist_funs || hoist_vars) {
|
if (hoist_funs || hoist_vars) {
|
||||||
var dirs = [];
|
var dirs = [];
|
||||||
var hoisted = [];
|
var hoisted = [];
|
||||||
|
|||||||
@@ -763,6 +763,34 @@ function OutputStream(options) {
|
|||||||
self._do_print(output);
|
self._do_print(output);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AST_Arrow.DEFMETHOD("_do_print", function(output){
|
||||||
|
var self = this;
|
||||||
|
var parent = output.parent();
|
||||||
|
var needs_parens = parent instanceof AST_Binary ||
|
||||||
|
parent instanceof AST_Unary ||
|
||||||
|
parent instanceof AST_Call;
|
||||||
|
if (needs_parens) { output.print("(") }
|
||||||
|
if (self.argnames.length === 1 && self.argnames[0] instanceof AST_Symbol) {
|
||||||
|
self.argnames[0].print(output);
|
||||||
|
} else {
|
||||||
|
output.with_parens(function(){
|
||||||
|
self.argnames.forEach(function(arg, i){
|
||||||
|
if (i) output.comma();
|
||||||
|
arg.print(output);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
output.space();
|
||||||
|
output.print('=>');
|
||||||
|
output.space();
|
||||||
|
if (self.body instanceof AST_Node) {
|
||||||
|
this.body.print(output);
|
||||||
|
} else {
|
||||||
|
print_bracketed(this.body, output);
|
||||||
|
}
|
||||||
|
if (needs_parens) { output.print(")") }
|
||||||
|
});
|
||||||
|
|
||||||
/* -----[ exits ]----- */
|
/* -----[ exits ]----- */
|
||||||
AST_Exit.DEFMETHOD("_do_print", function(output, kind){
|
AST_Exit.DEFMETHOD("_do_print", function(output, kind){
|
||||||
output.print(kind);
|
output.print(kind);
|
||||||
|
|||||||
56
lib/parse.js
56
lib/parse.js
@@ -510,6 +510,16 @@ function tokenizer($TEXT, filename, html5_comments) {
|
|||||||
return S.regex_allowed ? read_regexp("") : read_operator("/");
|
return S.regex_allowed ? read_regexp("") : read_operator("/");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function handle_eq_sign() {
|
||||||
|
next();
|
||||||
|
if (peek() === ">") {
|
||||||
|
next();
|
||||||
|
return token("arrow", "=>");
|
||||||
|
} else {
|
||||||
|
return read_operator("=");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function handle_dot() {
|
function handle_dot() {
|
||||||
next();
|
next();
|
||||||
return is_digit(peek().charCodeAt(0))
|
return is_digit(peek().charCodeAt(0))
|
||||||
@@ -559,6 +569,7 @@ function tokenizer($TEXT, filename, html5_comments) {
|
|||||||
case 34: case 39: return read_string(ch);
|
case 34: case 39: return read_string(ch);
|
||||||
case 46: return handle_dot();
|
case 46: return handle_dot();
|
||||||
case 47: return handle_slash();
|
case 47: return handle_slash();
|
||||||
|
case 61: return handle_eq_sign();
|
||||||
}
|
}
|
||||||
if (is_digit(code)) return read_num();
|
if (is_digit(code)) return read_num();
|
||||||
if (PUNC_CHARS(ch)) return token("punc", next());
|
if (PUNC_CHARS(ch)) return token("punc", next());
|
||||||
@@ -975,6 +986,41 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var arrow_function = function(args) {
|
||||||
|
expect_token("arrow", "=>");
|
||||||
|
|
||||||
|
if (args instanceof AST_SymbolRef) {
|
||||||
|
args = [args];
|
||||||
|
} else if (args instanceof AST_Seq) {
|
||||||
|
args = args.to_array();
|
||||||
|
} else if (args instanceof AST_Node) {
|
||||||
|
croak("Invalid syntax", args.start.line, args.start.col);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < args.length; i++) {
|
||||||
|
if (!(args[i] instanceof AST_SymbolRef)) {
|
||||||
|
croak("Invalid parameter for an arrow function", args[i].start.line, args[i].start.col);
|
||||||
|
}
|
||||||
|
|
||||||
|
args[i] = new AST_SymbolFunarg({
|
||||||
|
name: args[i].name,
|
||||||
|
start: args[i].start,
|
||||||
|
end: args[i].end
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AST_Arrow({
|
||||||
|
argnames: args,
|
||||||
|
body: (function(){
|
||||||
|
if (is("punc", "{")) {
|
||||||
|
return _function_body();
|
||||||
|
} else {
|
||||||
|
return expression(true);
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var function_ = function(ctor) {
|
var function_ = function(ctor) {
|
||||||
var start = S.token
|
var start = S.token
|
||||||
|
|
||||||
@@ -1486,6 +1532,13 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
var maybe_assign = function(no_in) {
|
var maybe_assign = function(no_in) {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
|
|
||||||
|
if (start.value == "(" && peek().value == ")") {
|
||||||
|
next(); // (
|
||||||
|
next(); // )
|
||||||
|
return arrow_function([]);
|
||||||
|
}
|
||||||
|
|
||||||
var left = maybe_conditional(no_in), val = S.token.value;
|
var left = maybe_conditional(no_in), val = S.token.value;
|
||||||
if (is("operator") && ASSIGNMENT(val)) {
|
if (is("operator") && ASSIGNMENT(val)) {
|
||||||
if (is_assignable(left)) {
|
if (is_assignable(left)) {
|
||||||
@@ -1500,6 +1553,9 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
croak("Invalid assignment");
|
croak("Invalid assignment");
|
||||||
}
|
}
|
||||||
|
if (is("arrow")) {
|
||||||
|
return arrow_function(left)
|
||||||
|
}
|
||||||
return left;
|
return left;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -166,7 +166,11 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
_(AST_Lambda, function(self, tw){
|
_(AST_Lambda, function(self, tw){
|
||||||
if (self.name) self.name = self.name.transform(tw);
|
if (self.name) self.name = self.name.transform(tw);
|
||||||
self.argnames = do_list(self.argnames, tw);
|
self.argnames = do_list(self.argnames, tw);
|
||||||
|
if (self.body instanceof AST_Node) {
|
||||||
|
self.body = self.body.transform(tw);
|
||||||
|
} else {
|
||||||
self.body = do_list(self.body, tw);
|
self.body = do_list(self.body, tw);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_(AST_Call, function(self, tw){
|
_(AST_Call, function(self, tw){
|
||||||
|
|||||||
37
test/compress/harmony.js
Normal file
37
test/compress/harmony.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
arrow_functions: {
|
||||||
|
input: {
|
||||||
|
(a) => b; // 1 args
|
||||||
|
(a, b) => c; // n args
|
||||||
|
() => b; // 0 args
|
||||||
|
(a) => (b) => c; // func returns func returns func
|
||||||
|
(a) => ((b) => c); // So these parens are dropped
|
||||||
|
() => (b,c) => d; // func returns func returns func
|
||||||
|
a=>{return b;}
|
||||||
|
a => 'lel'; // Dropping the parens
|
||||||
|
}
|
||||||
|
expect_exact: "a=>b;(a,b)=>c;()=>b;a=>b=>c;a=>b=>c;()=>(b,c)=>d;a=>{return b};a=>\"lel\";"
|
||||||
|
}
|
||||||
|
|
||||||
|
arrow_function_parens: {
|
||||||
|
input: {
|
||||||
|
something && (() => {});
|
||||||
|
}
|
||||||
|
expect_exact: "something&&(()=>{});"
|
||||||
|
}
|
||||||
|
arrow_function_parens_2: {
|
||||||
|
input: {
|
||||||
|
(() => null)();
|
||||||
|
}
|
||||||
|
expect_exact: "(()=>null)();"
|
||||||
|
}
|
||||||
|
|
||||||
|
regression_arrow_functions_and_hoist: {
|
||||||
|
options = {
|
||||||
|
hoist_vars: true,
|
||||||
|
hoist_funs: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(a) => b;
|
||||||
|
}
|
||||||
|
expect_exact: "a=>b;"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user