Bug 1066238 - Part 1: Parser support for static class methods. (r=jorendorff)

This commit is contained in:
Eric Faust 2015-02-26 15:05:23 -08:00
parent d854c9ca30
commit 6e6508aeeb
6 changed files with 42 additions and 15 deletions

View File

@ -349,7 +349,8 @@ class FullParseHandler
return true;
}
bool addClassMethodDefinition(ParseNode *methodList, ParseNode *key, ParseNode *fn, JSOp op)
bool addClassMethodDefinition(ParseNode *methodList, ParseNode *key, ParseNode *fn, JSOp op,
bool isStatic)
{
MOZ_ASSERT(methodList->isKind(PNK_CLASSMETHODLIST));
MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
@ -357,8 +358,7 @@ class FullParseHandler
key->isKind(PNK_STRING) ||
key->isKind(PNK_COMPUTED_NAME));
// For now, there's no such thing as static methods.
ParseNode *classMethod = new_<ClassMethod>(key, fn, op, false);
ParseNode *classMethod = new_<ClassMethod>(key, fn, op, isStatic);
if (!classMethod)
return false;
methodList->append(classMethod);

View File

@ -8029,8 +8029,19 @@ Parser<ParseHandler>::propertyList(PropListType type)
if (ltok == TOK_RC)
break;
if (type == ClassBody && ltok == TOK_SEMI)
continue;
bool isStatic = false;
if (type == ClassBody) {
if (ltok == TOK_SEMI)
continue;
if (ltok == TOK_NAME &&
tokenStream.currentName() == context->names().static_)
{
isStatic = true;
if (!tokenStream.getToken(&ltok, TokenStream::KeywordIsName))
return null();
}
}
bool isGenerator = false;
if (ltok == TOK_MUL) {
@ -8143,12 +8154,23 @@ Parser<ParseHandler>::propertyList(PropListType type)
}
default:
report(ParseError, false, null(), JSMSG_BAD_PROP_ID);
return null();
// There is never a case in which |static *(| can make a meaningful method definition.
if (isStatic && !isGenerator) {
// Turns out it wasn't static. Put it back and pretend it was a name all along.
isStatic = false;
tokenStream.ungetToken();
atom = tokenStream.currentName();
propname = handler.newObjectLiteralPropertyName(atom->asPropertyName(), pos());
if (!propname)
return null();
} else {
report(ParseError, false, null(), JSMSG_BAD_PROP_ID);
return null();
}
}
if (type == ClassBody) {
if (atom == context->names().constructor) {
if (!isStatic && atom == context->names().constructor) {
if (isGenerator || op != JSOP_INITPROP) {
report(ParseError, false, propname, JSMSG_BAD_METHOD_DEF);
return null();
@ -8158,6 +8180,9 @@ Parser<ParseHandler>::propertyList(PropListType type)
return null();
}
seenConstructor = true;
} else if (isStatic && atom == context->names().prototype) {
report(ParseError, false, propname, JSMSG_BAD_METHOD_DEF);
return null();
}
}
@ -8231,7 +8256,7 @@ Parser<ParseHandler>::propertyList(PropListType type)
} else if (tt == TOK_LP) {
tokenStream.ungetToken();
if (!methodDefinition(type, propList, propname, Normal, Method,
isGenerator ? StarGenerator : NotGenerator, op)) {
isGenerator ? StarGenerator : NotGenerator, isStatic, op)) {
return null();
}
} else {
@ -8241,7 +8266,7 @@ Parser<ParseHandler>::propertyList(PropListType type)
} else {
/* NB: Getter function in { get x(){} } is unnamed. */
if (!methodDefinition(type, propList, propname, op == JSOP_INITPROP_GETTER ? Getter : Setter,
Expression, NotGenerator, op)) {
Expression, NotGenerator, isStatic, op)) {
return null();
}
}
@ -8273,7 +8298,8 @@ template <typename ParseHandler>
bool
Parser<ParseHandler>::methodDefinition(PropListType listType, Node propList, Node propname,
FunctionType type, FunctionSyntaxKind kind,
GeneratorKind generatorKind, JSOp op)
GeneratorKind generatorKind,
bool isStatic, JSOp op)
{
RootedPropertyName funName(context);
if (kind == Method && tokenStream.isCurrentTokenType(TOK_NAME))
@ -8286,7 +8312,7 @@ Parser<ParseHandler>::methodDefinition(PropListType listType, Node propList, Nod
return false;
if (listType == ClassBody)
return handler.addClassMethodDefinition(propList, propname, fn, op);
return handler.addClassMethodDefinition(propList, propname, fn, op, isStatic);
MOZ_ASSERT(listType == ObjectLiteral);
return handler.addObjectMethodDefinition(propList, propname, fn, op);

View File

@ -577,7 +577,8 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
Node exprInParens();
bool methodDefinition(PropListType listType, Node propList, Node propname, FunctionType type,
FunctionSyntaxKind kind, GeneratorKind generatorKind, JSOp Op);
FunctionSyntaxKind kind, GeneratorKind generatorKind,
bool isStatic, JSOp Op);
/*
* Additional JS parsers.

View File

@ -191,7 +191,7 @@ class SyntaxParseHandler
bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
bool addShorthand(Node literal, Node name, Node expr) { return true; }
bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeUnparenthesizedYieldExpr; }
Node newYieldStarExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }

View File

@ -83,7 +83,6 @@ const char js_protected_str[] = "protected";
const char js_public_str[] = "public";
const char js_send_str[] = "send";
const char js_setter_str[] = "setter";
const char js_static_str[] = "static";
const char js_super_str[] = "super";
const char js_switch_str[] = "switch";
const char js_this_str[] = "this";

View File

@ -180,6 +180,7 @@
macro(signMask, signMask, "signMask") \
macro(source, source, "source") \
macro(stack, stack, "stack") \
macro(static, static_, "static") \
macro(sticky, sticky, "sticky") \
macro(strings, strings, "strings") \
macro(StructType, StructType, "StructType") \