From 63c05bf58bc98455cc2fc17091c90122f992d899 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 3 Nov 2015 14:53:44 -0600 Subject: [PATCH] Bug 1220702 - Part 3: Distinguish ES6 generators from legacy generators in Reflect.parse() output. r=Waldo. --HG-- extra : commitid : EjbmKoUzVHY extra : rebase_source : c9a5d21662ebe9b22a6ea4f6b74de30d5a7979a4 --- js/src/builtin/ReflectParse.cpp | 45 ++++++++++++++++--- .../js1_8_5/reflect-parse/PatternBuilders.js | 10 +++-- .../js1_8_5/reflect-parse/basicBuilder.js | 2 +- js/src/tests/js1_8_5/reflect-parse/classes.js | 7 +-- .../tests/js1_8_5/reflect-parse/generators.js | 12 +++-- .../tests/js1_8_5/reflect-parse/methodDefn.js | 6 +-- .../tests/js1_8_5/reflect-parse/newTarget.js | 2 +- 7 files changed, 62 insertions(+), 22 deletions(-) diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index 58899931dafb..03c41310b1b1 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -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 diff --git a/js/src/tests/js1_8_5/reflect-parse/PatternBuilders.js b/js/src/tests/js1_8_5/reflect-parse/PatternBuilders.js index abc2155bd250..765fa3a9757c 100644 --- a/js/src/tests/js1_8_5/reflect-parse/PatternBuilders.js +++ b/js/src/tests/js1_8_5/reflect-parse/PatternBuilders.js @@ -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", diff --git a/js/src/tests/js1_8_5/reflect-parse/basicBuilder.js b/js/src/tests/js1_8_5/reflect-parse/basicBuilder.js index 5d25e98a7217..007d983d1420 100644 --- a/js/src/tests/js1_8_5/reflect-parse/basicBuilder.js +++ b/js/src/tests/js1_8_5/reflect-parse/basicBuilder.js @@ -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 }); diff --git a/js/src/tests/js1_8_5/reflect-parse/classes.js b/js/src/tests/js1_8_5/reflect-parse/classes.js index 44fcd4081cc5..9a230be8db01 100644 --- a/js/src/tests/js1_8_5/reflect-parse/classes.js +++ b/js/src/tests/js1_8_5/reflect-parse/classes.js @@ -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) { diff --git a/js/src/tests/js1_8_5/reflect-parse/generators.js b/js/src/tests/js1_8_5/reflect-parse/generators.js index 18da38155dbc..eafdb1cbc0ef 100644 --- a/js/src/tests/js1_8_5/reflect-parse/generators.js +++ b/js/src/tests/js1_8_5/reflect-parse/generators.js @@ -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([]))); } diff --git a/js/src/tests/js1_8_5/reflect-parse/methodDefn.js b/js/src/tests/js1_8_5/reflect-parse/methodDefn.js index 090a0844fb80..fb3986179ef2 100644 --- a/js/src/tests/js1_8_5/reflect-parse/methodDefn.js +++ b/js/src/tests/js1_8_5/reflect-parse/methodDefn.js @@ -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); diff --git a/js/src/tests/js1_8_5/reflect-parse/newTarget.js b/js/src/tests/js1_8_5/reflect-parse/newTarget.js index 45cf527ec677..3db2c2726d01 100644 --- a/js/src/tests/js1_8_5/reflect-parse/newTarget.js +++ b/js/src/tests/js1_8_5/reflect-parse/newTarget.js @@ -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