From 565273c02b88bfe43ba15498dbbb454525543aff Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Thu, 3 Sep 2015 00:16:32 +0900 Subject: [PATCH] Bug 1196041 - Disallow getter/setter with expression closure in class declaration. r=efaust --HG-- extra : rebase_source : 0aa2c3b94ce864a27750c94c8ade5dea8df828c0 --- js/src/frontend/ParseNode.h | 16 +++++++++- js/src/frontend/Parser.cpp | 30 ++++++++++++++----- js/src/frontend/Parser.h | 2 ++ .../tests/ecma_6/Class/geterNoExprClosure.js | 24 +++++++++++++++ 4 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 js/src/tests/ecma_6/Class/geterNoExprClosure.js diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 6a14ec935cec..b54f8accf933 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -1716,7 +1716,9 @@ enum FunctionSyntaxKind ClassConstructor, DerivedClassConstructor, Getter, - Setter + GetterNoExpressionClosure, + Setter, + SetterNoExpressionClosure }; static inline bool @@ -1725,6 +1727,18 @@ IsConstructorKind(FunctionSyntaxKind kind) return kind == ClassConstructor || kind == DerivedClassConstructor; } +static inline bool +IsGetterKind(FunctionSyntaxKind kind) +{ + return kind == Getter || kind == GetterNoExpressionClosure; +} + +static inline bool +IsSetterKind(FunctionSyntaxKind kind) +{ + return kind == Setter || kind == SetterNoExpressionClosure; +} + static inline ParseNode* FunctionArgsList(ParseNode* fn, unsigned* numFormals) { diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index f2a2f33c5569..99d5f0af9dd7 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1431,10 +1431,12 @@ Parser::newFunction(HandleAtom atom, FunctionSyntaxKind kind, allocKind = gc::AllocKind::FUNCTION_EXTENDED; break; case Getter: + case GetterNoExpressionClosure: flags = JSFunction::INTERPRETED_GETTER; allocKind = gc::AllocKind::FUNCTION_EXTENDED; break; case Setter: + case SetterNoExpressionClosure: flags = JSFunction::INTERPRETED_SETTER; allocKind = gc::AllocKind::FUNCTION_EXTENDED; break; @@ -1860,7 +1862,7 @@ Parser::functionArguments(YieldHandling yieldHandling, FunctionSyn Node duplicatedArg = null(); bool disallowDuplicateArgs = kind == Arrow || kind == Method || kind == ClassConstructor; - if (kind == Getter) { + if (IsGetterKind(kind)) { report(ParseError, false, null(), JSMSG_ACCESSOR_WRONG_ARGS, "getter", "no", "s"); return false; } @@ -1926,7 +1928,7 @@ Parser::functionArguments(YieldHandling yieldHandling, FunctionSyn case TOK_TRIPLEDOT: { - if (kind == Setter) { + if (IsSetterKind(kind)) { report(ParseError, false, null(), JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", ""); return false; @@ -2003,7 +2005,7 @@ Parser::functionArguments(YieldHandling yieldHandling, FunctionSyn return false; } - if (parenFreeArrow || kind == Setter) + if (parenFreeArrow || IsSetterKind(kind)) break; if (!tokenStream.matchToken(&matched, TOK_COMMA)) @@ -2017,7 +2019,7 @@ Parser::functionArguments(YieldHandling yieldHandling, FunctionSyn if (!tokenStream.getToken(&tt)) return false; if (tt != TOK_RP) { - if (kind == Setter) { + if (IsSetterKind(kind)) { report(ParseError, false, null(), JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", ""); return false; @@ -2030,7 +2032,7 @@ Parser::functionArguments(YieldHandling yieldHandling, FunctionSyn if (!hasDefaults) funbox->length = pc->numArgs() - *hasRest; - } else if (kind == Setter) { + } else if (IsSetterKind(kind)) { report(ParseError, false, null(), JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", ""); return false; } @@ -2781,7 +2783,9 @@ Parser::functionArgsAndBodyGeneric(InHandling inHandling, if (!tokenStream.getToken(&tt, TokenStream::Operand)) return false; if (tt != TOK_LC) { - if (funbox->isStarGenerator() || kind == Method || IsConstructorKind(kind)) { + if (funbox->isStarGenerator() || kind == Method || + kind == GetterNoExpressionClosure || kind == SetterNoExpressionClosure || + IsConstructorKind(kind)) { report(ParseError, false, null(), JSMSG_CURLY_BEFORE_BODY); return false; } @@ -6319,8 +6323,10 @@ JSOpFromPropertyType(PropertyType propType) { switch (propType) { case PropertyType::Getter: + case PropertyType::GetterNoExpressionClosure: return JSOP_INITPROP_GETTER; case PropertyType::Setter: + case PropertyType::SetterNoExpressionClosure: return JSOP_INITPROP_SETTER; case PropertyType::Normal: case PropertyType::Method: @@ -6339,8 +6345,12 @@ FunctionSyntaxKindFromPropertyType(PropertyType propType) switch (propType) { case PropertyType::Getter: return Getter; + case PropertyType::GetterNoExpressionClosure: + return GetterNoExpressionClosure; case PropertyType::Setter: return Setter; + case PropertyType::SetterNoExpressionClosure: + return SetterNoExpressionClosure; case PropertyType::Method: return Method; case PropertyType::GeneratorMethod: @@ -6474,6 +6484,10 @@ Parser::classDefinition(YieldHandling yieldHandling, return null(); } + if (propType == PropertyType::Getter) + propType = PropertyType::GetterNoExpressionClosure; + if (propType == PropertyType::Setter) + propType = PropertyType::SetterNoExpressionClosure; if (!isStatic && propAtom == context->names().constructor) { if (propType != PropertyType::Method) { report(ParseError, false, propName, JSMSG_BAD_METHOD_DEF); @@ -6494,8 +6508,8 @@ Parser::classDefinition(YieldHandling yieldHandling, // (bug 883377). RootedPropertyName funName(context); switch (propType) { - case PropertyType::Getter: - case PropertyType::Setter: + case PropertyType::GetterNoExpressionClosure: + case PropertyType::SetterNoExpressionClosure: funName = nullptr; break; case PropertyType::Constructor: diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 7a7079ad80ec..9ba7884d6110 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -358,7 +358,9 @@ enum class PropertyType { Normal, Shorthand, Getter, + GetterNoExpressionClosure, Setter, + SetterNoExpressionClosure, Method, GeneratorMethod, Constructor, diff --git a/js/src/tests/ecma_6/Class/geterNoExprClosure.js b/js/src/tests/ecma_6/Class/geterNoExprClosure.js new file mode 100644 index 000000000000..b447d08576d0 --- /dev/null +++ b/js/src/tests/ecma_6/Class/geterNoExprClosure.js @@ -0,0 +1,24 @@ +// getter/setter with expression closure is allowed only in object literal. + +function test() { + assertThrowsInstanceOf(() => eval(` +class foo { + constructor() {} + + get a() 1 +} +`), SyntaxError); + assertThrowsInstanceOf(() => eval(` +class foo { + constructor() {} + + set a(v) 1 +} +`), SyntaxError); +} + +if (classesEnabled()) + test(); + +if (typeof reportCompare === 'function') + reportCompare(0,0,"OK");