Skip to content

Commit

Permalink
Bug 1066238 - Part 1: Parser support for static class methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
rmottola committed Apr 17, 2019
1 parent c06dccc commit 53315d0
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 15 deletions.
6 changes: 3 additions & 3 deletions js/src/frontend/FullParseHandler.h
Expand Up @@ -349,16 +349,16 @@ 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) ||
key->isKind(PNK_OBJECT_PROPERTY_NAME) ||
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);
Expand Down
44 changes: 35 additions & 9 deletions js/src/frontend/Parser.cpp
Expand Up @@ -7923,8 +7923,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) {
Expand Down Expand Up @@ -8037,12 +8048,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();
Expand All @@ -8052,6 +8074,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();
}
}

Expand Down Expand Up @@ -8125,7 +8150,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 {
Expand All @@ -8135,7 +8160,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();
}
}
Expand Down Expand Up @@ -8167,7 +8192,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))
Expand All @@ -8180,7 +8206,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);
Expand Down
3 changes: 2 additions & 1 deletion js/src/frontend/Parser.h
Expand Up @@ -575,7 +575,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.
Expand Down
2 changes: 1 addition & 1 deletion js/src/frontend/SyntaxParseHandler.h
Expand Up @@ -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; }

Expand Down
1 change: 0 additions & 1 deletion js/src/jsatom.cpp
Expand Up @@ -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";
Expand Down
1 change: 1 addition & 0 deletions js/src/vm/CommonPropertyNames.h
Expand Up @@ -193,6 +193,7 @@
macro(source, source, "source") \
macro(stack, stack, "stack") \
macro(startTimestamp, startTimestamp, "startTimestamp") \
macro(static, static_, "static") \
macro(sticky, sticky, "sticky") \
macro(strings, strings, "strings") \
macro(StructType, StructType, "StructType") \
Expand Down

0 comments on commit 53315d0

Please sign in to comment.