mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 12:55:46 +00:00
Bug 1220702 - Part 3: Distinguish ES6 generators from legacy generators in Reflect.parse() output. r=Waldo.
--HG-- extra : commitid : EjbmKoUzVHY extra : rebase_source : c9a5d21662ebe9b22a6ea4f6b74de30d5a7979a4
This commit is contained in:
parent
ee1aaa35e1
commit
63c05bf58b
@ -222,6 +222,13 @@ GetPropertyDefault(JSContext* cx, HandleObject obj, HandleId id, HandleValue def
|
||||
return GetProperty(cx, obj, obj, id, result);
|
||||
}
|
||||
|
||||
enum class GeneratorStyle
|
||||
{
|
||||
None,
|
||||
Legacy,
|
||||
ES6
|
||||
};
|
||||
|
||||
/*
|
||||
* Builder class that constructs JavaScript AST node objects. See:
|
||||
*
|
||||
@ -458,8 +465,8 @@ class NodeBuilder
|
||||
|
||||
bool function(ASTType type, TokenPos* pos,
|
||||
HandleValue id, NodeVector& args, NodeVector& defaults,
|
||||
HandleValue body, HandleValue rest, bool isGenerator, bool isExpression,
|
||||
MutableHandleValue dst);
|
||||
HandleValue body, HandleValue rest, GeneratorStyle generatorStyle,
|
||||
bool isExpression, MutableHandleValue dst);
|
||||
|
||||
bool variableDeclarator(HandleValue id, HandleValue init, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
@ -1595,7 +1602,7 @@ bool
|
||||
NodeBuilder::function(ASTType type, TokenPos* pos,
|
||||
HandleValue id, NodeVector& args, NodeVector& defaults,
|
||||
HandleValue body, HandleValue rest,
|
||||
bool isGenerator, bool isExpression,
|
||||
GeneratorStyle generatorStyle, bool isExpression,
|
||||
MutableHandleValue dst)
|
||||
{
|
||||
RootedValue array(cx), defarray(cx);
|
||||
@ -1604,6 +1611,7 @@ NodeBuilder::function(ASTType type, TokenPos* pos,
|
||||
if (!newArray(defaults, &defarray))
|
||||
return false;
|
||||
|
||||
bool isGenerator = generatorStyle != GeneratorStyle::None;
|
||||
RootedValue isGeneratorVal(cx, BooleanValue(isGenerator));
|
||||
RootedValue isExpressionVal(cx, BooleanValue(isExpression));
|
||||
|
||||
@ -1612,6 +1620,27 @@ NodeBuilder::function(ASTType type, TokenPos* pos,
|
||||
return callback(cb, opt(id), array, body, isGeneratorVal, isExpressionVal, pos, dst);
|
||||
}
|
||||
|
||||
if (isGenerator) {
|
||||
// Distinguish ES6 generators from legacy generators.
|
||||
RootedValue styleVal(cx);
|
||||
JSAtom* styleStr = generatorStyle == GeneratorStyle::ES6
|
||||
? Atomize(cx, "es6", 3)
|
||||
: Atomize(cx, "legacy", 6);
|
||||
if (!styleStr)
|
||||
return false;
|
||||
styleVal.setString(styleStr);
|
||||
return newNode(type, pos,
|
||||
"id", id,
|
||||
"params", array,
|
||||
"defaults", defarray,
|
||||
"body", body,
|
||||
"rest", rest,
|
||||
"generator", isGeneratorVal,
|
||||
"style", styleVal,
|
||||
"expression", isExpressionVal,
|
||||
dst);
|
||||
}
|
||||
|
||||
return newNode(type, pos,
|
||||
"id", id,
|
||||
"params", array,
|
||||
@ -3407,8 +3436,12 @@ ASTSerializer::function(ParseNode* pn, ASTType type, MutableHandleValue dst)
|
||||
{
|
||||
RootedFunction func(cx, pn->pn_funbox->function());
|
||||
|
||||
// FIXME: Provide more information (legacy generator vs star generator).
|
||||
bool isGenerator = pn->pn_funbox->isGenerator();
|
||||
GeneratorStyle generatorStyle =
|
||||
pn->pn_funbox->isGenerator()
|
||||
? (pn->pn_funbox->isLegacyGenerator()
|
||||
? GeneratorStyle::Legacy
|
||||
: GeneratorStyle::ES6)
|
||||
: GeneratorStyle::None;
|
||||
|
||||
bool isExpression =
|
||||
#if JS_HAS_EXPR_CLOSURES
|
||||
@ -3432,7 +3465,7 @@ ASTSerializer::function(ParseNode* pn, ASTType type, MutableHandleValue dst)
|
||||
rest.setNull();
|
||||
return functionArgsAndBody(pn->pn_body, args, defaults, &body, &rest) &&
|
||||
builder.function(type, &pn->pn_pos, id, args, defaults, body,
|
||||
rest, isGenerator, isExpression, dst);
|
||||
rest, generatorStyle, isExpression, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -38,13 +38,14 @@ function funDecl(id, params, body, defaults=[], rest=null) {
|
||||
rest: rest,
|
||||
generator: false });
|
||||
}
|
||||
function genFunDecl(id, params, body) {
|
||||
function genFunDecl(style, id, params, body) {
|
||||
return Pattern({ type: "FunctionDeclaration",
|
||||
id: id,
|
||||
params: params,
|
||||
defaults: [],
|
||||
body: body,
|
||||
generator: true });
|
||||
generator: true,
|
||||
style: style });
|
||||
}
|
||||
function varDecl(decls) {
|
||||
return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "var" });
|
||||
@ -157,12 +158,13 @@ function funExpr(id, args, body, gen) {
|
||||
body: body,
|
||||
generator: false });
|
||||
}
|
||||
function genFunExpr(id, args, body) {
|
||||
function genFunExpr(style, id, args, body) {
|
||||
return Pattern({ type: "FunctionExpression",
|
||||
id: id,
|
||||
params: args,
|
||||
body: body,
|
||||
generator: true });
|
||||
generator: true,
|
||||
style: style });
|
||||
}
|
||||
function arrowExpr(args, body) {
|
||||
return Pattern({ type: "ArrowFunctionExpression",
|
||||
|
@ -41,7 +41,7 @@ assertGlobalExpr("({ x: y })", 13, { objectExpression: () => 13 });
|
||||
assertGlobalExpr("this", 14, { thisExpression: () => 14 });
|
||||
assertGlobalExpr("[x for (x in y)]", 17, { comprehensionExpression: () => 17 });
|
||||
assertGlobalExpr("(x for (x in y))", 18, { generatorExpression: () => 18 });
|
||||
assertGlobalExpr("(function() { yield 42 })", genFunExpr(null, [], blockStmt([exprStmt(19)])), { yieldExpression: () => 19 });
|
||||
assertGlobalExpr("(function() { yield 42 })", genFunExpr("legacy", null, [], blockStmt([exprStmt(19)])), { yieldExpression: () => 19 });
|
||||
|
||||
assertGlobalStmt("switch (x) { case y: }", switchStmt(ident("x"), [1]), { switchCase: () => 1 });
|
||||
assertGlobalStmt("try { } catch (e) { }", 2, { tryStatement: (b, g, u, f) => u, catchClause: () => 2 });
|
||||
|
@ -14,10 +14,11 @@ function testClasses() {
|
||||
function methodFun(id, kind, generator, args, body = []) {
|
||||
assertEq(generator && kind === "method", generator);
|
||||
assertEq(typeof id === 'string' || id === null, true);
|
||||
let idN = typeof id === 'string' ? ident(id): null;
|
||||
let methodMaker = generator ? genFunExpr : funExpr;
|
||||
let idN = typeof id === 'string' ? ident(id) : null;
|
||||
let methodName = kind !== "method" ? null : idN;
|
||||
return methodMaker(methodName, args.map(ident), blockStmt(body));
|
||||
return generator
|
||||
? genFunExpr("es6", methodName, args.map(ident), blockStmt(body))
|
||||
: funExpr(methodName, args.map(ident), blockStmt(body));
|
||||
}
|
||||
|
||||
function simpleMethod(id, kind, generator, args=[], isStatic=false) {
|
||||
|
@ -3,10 +3,14 @@ function test() {
|
||||
|
||||
// generators
|
||||
|
||||
assertDecl("function gen(x) { yield }", genFunDecl(ident("gen"), [ident("x")], blockStmt([exprStmt(yieldExpr(null))])));
|
||||
assertExpr("(function(x) { yield })", genFunExpr(null, [ident("x")], blockStmt([exprStmt(yieldExpr(null))])));
|
||||
assertDecl("function gen(x) { yield 42 }", genFunDecl(ident("gen"), [ident("x")], blockStmt([exprStmt(yieldExpr(lit(42)))])));
|
||||
assertExpr("(function(x) { yield 42 })", genFunExpr(null, [ident("x")], blockStmt([exprStmt(yieldExpr(lit(42)))])));
|
||||
assertDecl("function gen(x) { yield }", genFunDecl("legacy", ident("gen"), [ident("x")], blockStmt([exprStmt(yieldExpr(null))])));
|
||||
assertExpr("(function(x) { yield })", genFunExpr("legacy", null, [ident("x")], blockStmt([exprStmt(yieldExpr(null))])));
|
||||
assertDecl("function gen(x) { yield 42 }", genFunDecl("legacy", ident("gen"), [ident("x")], blockStmt([exprStmt(yieldExpr(lit(42)))])));
|
||||
assertExpr("(function(x) { yield 42 })", genFunExpr("legacy", null, [ident("x")], blockStmt([exprStmt(yieldExpr(lit(42)))])));
|
||||
|
||||
assertDecl("function* gen() {}", genFunDecl("es6", ident("gen"), [], blockStmt([])));
|
||||
assertExpr("(function*() {})", genFunExpr("es6", null, [], blockStmt([])));
|
||||
assertExpr("(function* gen() {})", genFunExpr("es6", ident("gen"), [], blockStmt([])));
|
||||
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ assertExpr("b = { a() { } }", aExpr("=", ident("b"),
|
||||
true}])));
|
||||
|
||||
assertExpr("b = { *a() { } }", aExpr("=", ident("b"),
|
||||
objExpr([{ key: ident("a"), value: genFunExpr(ident("a"), [], blockStmt([])), method:
|
||||
objExpr([{ key: ident("a"), value: genFunExpr("es6", ident("a"), [], blockStmt([])), method:
|
||||
true}])));
|
||||
|
||||
// Method definitions without braces
|
||||
@ -28,9 +28,9 @@ assertExpr("({ set x(v) { return 42 } })",
|
||||
|
||||
// Bug 1073809 - Getter/setter syntax with generators
|
||||
assertExpr("({*get() { }})", objExpr([{ type: "Property", key: ident("get"), method: true,
|
||||
value: genFunExpr(ident("get"), [], blockStmt([]))}]));
|
||||
value: genFunExpr("es6", ident("get"), [], blockStmt([]))}]));
|
||||
assertExpr("({*set() { }})", objExpr([{ type: "Property", key: ident("set"), method: true,
|
||||
value: genFunExpr(ident("set"), [], blockStmt([]))}]));
|
||||
value: genFunExpr("es6", ident("set"), [], blockStmt([]))}]));
|
||||
assertError("({*get foo() { }})", SyntaxError);
|
||||
assertError("({*set foo() { }})", SyntaxError);
|
||||
|
||||
|
@ -16,7 +16,7 @@ function testNewTarget() {
|
||||
assertError("(() => new.target))", SyntaxError);
|
||||
|
||||
// valid in generators, too!
|
||||
assertStmt("function *foo() { new.target; }", genFunDecl(ident("foo"), [],
|
||||
assertStmt("function *foo() { new.target; }", genFunDecl("es6", ident("foo"), [],
|
||||
blockStmt([exprStmt(newTarget())])));
|
||||
|
||||
// new.target is a member expression. You should be able to call, invoke, or
|
||||
|
Loading…
Reference in New Issue
Block a user