feat: implement harmony generators and yield
Uses #716's implementation and adds tests. Fixes #716.
This commit is contained in:
parent
2827fa8699
commit
81c788e8ab
|
|
@ -437,9 +437,10 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", {
|
|||
}
|
||||
});
|
||||
|
||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments isgenerator", {
|
||||
$documentation: "Base class for functions",
|
||||
$propdoc: {
|
||||
isgenerator: "is generatorFn or not",
|
||||
name: "[AST_SymbolDeclaration?] the name of this function",
|
||||
argnames: "[AST_SymbolFunarg|AST_Destructuring|AST_Expansion*] array of function arguments, destructurings, or expanding arguments",
|
||||
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
|
||||
|
|
|
|||
|
|
@ -226,6 +226,10 @@ function OutputStream(options) {
|
|||
OUTPUT += str;
|
||||
};
|
||||
|
||||
var star = function(){
|
||||
print("*");
|
||||
}
|
||||
|
||||
var space = options.beautify ? function() {
|
||||
print(" ");
|
||||
} : function() {
|
||||
|
|
@ -343,6 +347,7 @@ function OutputStream(options) {
|
|||
should_break : function() { return options.width && this.current_width() >= options.width },
|
||||
newline : newline,
|
||||
print : print,
|
||||
star : star,
|
||||
space : space,
|
||||
comma : comma,
|
||||
colon : colon,
|
||||
|
|
@ -783,6 +788,9 @@ function OutputStream(options) {
|
|||
var self = this;
|
||||
if (!nokeyword) {
|
||||
output.print("function");
|
||||
if (this.isgenerator) {
|
||||
output.star();
|
||||
}
|
||||
if (self.name) {
|
||||
output.space();
|
||||
}
|
||||
|
|
@ -1141,8 +1149,13 @@ function OutputStream(options) {
|
|||
output.print(self.operator);
|
||||
});
|
||||
DEFPRINT(AST_Binary, function(self, output){
|
||||
var isYield = (self.left.operator == "yield" || self.left.operator === "yield*");
|
||||
var op = self.operator;
|
||||
|
||||
isYield && output.print("(");
|
||||
self.left.print(output);
|
||||
isYield && output.print(")");
|
||||
|
||||
if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
|
||||
&& self.left instanceof AST_UnaryPostfix
|
||||
&& self.left.operator == "--") {
|
||||
|
|
@ -1152,7 +1165,12 @@ function OutputStream(options) {
|
|||
// the space is optional depending on "beautify"
|
||||
output.space();
|
||||
}
|
||||
|
||||
isYield = (self.right.operator == "yield" || self.right.operator === "yield*");
|
||||
isYield && output.print("(");
|
||||
output.print(op);
|
||||
isYield && output.print(")");
|
||||
|
||||
if ((op == "<" || op == "<<")
|
||||
&& self.right instanceof AST_UnaryPrefix
|
||||
&& self.right.operator == "!"
|
||||
|
|
|
|||
14
lib/parse.js
14
lib/parse.js
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var KEYWORDS = 'break case catch class const continue debugger default delete do else extends finally for function if in instanceof new return switch throw try typeof var let void while with';
|
||||
var KEYWORDS = 'break case catch class const continue debugger default delete do else extends finally for function if in instanceof new return yield switch throw try typeof var let void while with';
|
||||
var KEYWORDS_ATOM = 'false null true';
|
||||
var RESERVED_WORDS = 'abstract boolean byte char double enum export final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield'
|
||||
+ " " + KEYWORDS_ATOM + " " + KEYWORDS;
|
||||
|
|
@ -68,6 +68,7 @@ var OPERATORS = makePredicate([
|
|||
"instanceof",
|
||||
"typeof",
|
||||
"new",
|
||||
"yield",
|
||||
"void",
|
||||
"delete",
|
||||
"++",
|
||||
|
|
@ -627,6 +628,7 @@ var UNARY_PREFIX = makePredicate([
|
|||
"typeof",
|
||||
"void",
|
||||
"delete",
|
||||
"yield",
|
||||
"--",
|
||||
"++",
|
||||
"!",
|
||||
|
|
@ -1050,6 +1052,11 @@ function parse($TEXT, options) {
|
|||
var start = S.token
|
||||
|
||||
var in_statement = ctor === AST_Defun;
|
||||
var isgenerator = is("operator", "*");
|
||||
if (isgenerator) {
|
||||
next();
|
||||
}
|
||||
|
||||
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
|
||||
if (in_statement && !name)
|
||||
unexpected();
|
||||
|
|
@ -1059,6 +1066,7 @@ function parse($TEXT, options) {
|
|||
return new ctor({
|
||||
start : args.start,
|
||||
end : body.end,
|
||||
isgenerator: isgenerator,
|
||||
name : name,
|
||||
argnames: args,
|
||||
body : body
|
||||
|
|
@ -1716,6 +1724,10 @@ function parse($TEXT, options) {
|
|||
var start = S.token;
|
||||
if (is("operator") && UNARY_PREFIX(start.value)) {
|
||||
next();
|
||||
if (start.type === "operator" && start.value === "yield" && is("operator", "*")) {
|
||||
start.value = "yield*";
|
||||
next();
|
||||
}
|
||||
handle_regexp();
|
||||
var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
|
||||
ex.start = start;
|
||||
|
|
|
|||
|
|
@ -321,3 +321,19 @@ regression_cannot_use_of: {
|
|||
foo(); /* Label statement missing? No prob. */
|
||||
}
|
||||
}
|
||||
|
||||
generators: {
|
||||
input: {
|
||||
function* fn() {};
|
||||
}
|
||||
expect_exact: "function*fn(){}"
|
||||
}
|
||||
|
||||
generators_yield: {
|
||||
input: {
|
||||
function* fn() {
|
||||
yield remote();
|
||||
}
|
||||
}
|
||||
expect_exact: "function*fn(){yield remote()}"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,17 @@ module.exports = function () {
|
|||
ok.equal(expanding_def.name.names[0].TYPE, 'SymbolVar');
|
||||
ok.equal(expanding_def.name.names[1].TYPE, 'Expansion');
|
||||
ok.equal(expanding_def.name.names[1].symbol.TYPE, 'SymbolVar');
|
||||
|
||||
// generators
|
||||
var generators_def = UglifyJS.parse('function* fn() {}').body[0];
|
||||
ok.equal(generators_def.isgenerator, true);
|
||||
|
||||
ok.throws(function () {
|
||||
UglifyJS.parse('function* (){ }');
|
||||
});
|
||||
|
||||
var generators_yield_def = UglifyJS.parse('function* fn() {\nyield remote();\}').body[0].body[0];
|
||||
ok.equal(generators_yield_def.body.operator, 'yield');
|
||||
}
|
||||
|
||||
// Run standalone
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user