mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 22:05:44 +00:00
Bug 1418235 - Simplify tracking of parenthesized names in SyntaxParseHandler. r=arai
--HG-- extra : rebase_source : 7154d041e14f24fb5894d2b255e7cb77432505d4 extra : histedit_source : 23250bc47ae3dce24339c5f05b4c1a69f2d3d08b
This commit is contained in:
parent
045ffa33ce
commit
f4de88858a
@ -797,29 +797,18 @@ class FullParseHandler
|
||||
return pn->isConstant();
|
||||
}
|
||||
|
||||
bool isNameAnyParentheses(ParseNode* node) {
|
||||
bool isName(ParseNode* node) {
|
||||
return node->isKind(PNK_NAME);
|
||||
}
|
||||
|
||||
bool isArgumentsAnyParentheses(ParseNode* node, JSContext* cx) {
|
||||
bool isArgumentsName(ParseNode* node, JSContext* cx) {
|
||||
return node->isKind(PNK_NAME) && node->pn_atom == cx->names().arguments;
|
||||
}
|
||||
|
||||
bool isEvalAnyParentheses(ParseNode* node, JSContext* cx) {
|
||||
bool isEvalName(ParseNode* node, JSContext* cx) {
|
||||
return node->isKind(PNK_NAME) && node->pn_atom == cx->names().eval;
|
||||
}
|
||||
|
||||
const char* nameIsArgumentsEvalAnyParentheses(ParseNode* node, JSContext* cx) {
|
||||
MOZ_ASSERT(isNameAnyParentheses(node),
|
||||
"must only call this function on known names");
|
||||
|
||||
if (isEvalAnyParentheses(node, cx))
|
||||
return js_eval_str;
|
||||
if (isArgumentsAnyParentheses(node, cx))
|
||||
return js_arguments_str;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool isAsyncKeyword(ParseNode* node, JSContext* cx) {
|
||||
return node->isKind(PNK_NAME) &&
|
||||
node->pn_pos.begin + strlen("async") == node->pn_pos.end &&
|
||||
|
@ -6141,9 +6141,8 @@ Parser<ParseHandler, CharT>::forHeadStart(YieldHandling yieldHandling,
|
||||
if (handler.isUnparenthesizedDestructuringPattern(*forInitialPart)) {
|
||||
if (!possibleError.checkForDestructuringErrorOrWarning())
|
||||
return false;
|
||||
} else if (handler.isNameAnyParentheses(*forInitialPart)) {
|
||||
const char* chars = handler.nameIsArgumentsEvalAnyParentheses(*forInitialPart, context);
|
||||
if (chars) {
|
||||
} else if (handler.isName(*forInitialPart)) {
|
||||
if (const char* chars = nameIsArgumentsOrEval(*forInitialPart)) {
|
||||
// |chars| is "arguments" or "eval" here.
|
||||
if (!strictModeErrorAt(exprOffset, JSMSG_BAD_STRICT_ASSIGN, chars))
|
||||
return false;
|
||||
@ -8135,8 +8134,8 @@ Parser<ParseHandler, CharT>::assignExpr(InHandling inHandling, YieldHandling yie
|
||||
|
||||
if (!possibleErrorInner.checkForDestructuringErrorOrWarning())
|
||||
return null();
|
||||
} else if (handler.isNameAnyParentheses(lhs)) {
|
||||
if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(lhs, context)) {
|
||||
} else if (handler.isName(lhs)) {
|
||||
if (const char* chars = nameIsArgumentsOrEval(lhs)) {
|
||||
// |chars| is "arguments" or "eval" here.
|
||||
if (!strictModeErrorAt(exprPos.begin, JSMSG_BAD_STRICT_ASSIGN, chars))
|
||||
return null();
|
||||
@ -8178,11 +8177,11 @@ Parser<ParseHandler, CharT>::isValidSimpleAssignmentTarget(Node node,
|
||||
// error for the various syntaxes that fail this, and warning for the
|
||||
// various syntaxes that "pass" this but should not, occurs elsewhere.
|
||||
|
||||
if (handler.isNameAnyParentheses(node)) {
|
||||
if (handler.isName(node)) {
|
||||
if (!pc->sc()->strict())
|
||||
return true;
|
||||
|
||||
return !handler.nameIsArgumentsEvalAnyParentheses(node, context);
|
||||
return !nameIsArgumentsOrEval(node);
|
||||
}
|
||||
|
||||
if (handler.isPropertyAccess(node))
|
||||
@ -8196,12 +8195,25 @@ Parser<ParseHandler, CharT>::isValidSimpleAssignmentTarget(Node node,
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class ParseHandler, typename CharT>
|
||||
const char*
|
||||
Parser<ParseHandler, CharT>::nameIsArgumentsOrEval(Node node)
|
||||
{
|
||||
MOZ_ASSERT(handler.isName(node), "must only call this function on known names");
|
||||
|
||||
if (handler.isEvalName(node, context))
|
||||
return js_eval_str;
|
||||
if (handler.isArgumentsName(node, context))
|
||||
return js_arguments_str;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class ParseHandler, typename CharT>
|
||||
bool
|
||||
Parser<ParseHandler, CharT>::checkIncDecOperand(Node operand, uint32_t operandOffset)
|
||||
{
|
||||
if (handler.isNameAnyParentheses(operand)) {
|
||||
if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(operand, context)) {
|
||||
if (handler.isName(operand)) {
|
||||
if (const char* chars = nameIsArgumentsOrEval(operand)) {
|
||||
if (!strictModeErrorAt(operandOffset, JSMSG_BAD_STRICT_ASSIGN, chars))
|
||||
return false;
|
||||
}
|
||||
@ -8307,7 +8319,7 @@ Parser<ParseHandler, CharT>::unaryExpr(YieldHandling yieldHandling,
|
||||
|
||||
// Per spec, deleting any unary expression is valid -- it simply
|
||||
// returns true -- except for one case that is illegal in strict mode.
|
||||
if (handler.isNameAnyParentheses(expr)) {
|
||||
if (handler.isName(expr)) {
|
||||
if (!strictModeErrorAt(exprOffset, JSMSG_DEPRECATED_DELETE_OPERAND))
|
||||
return null();
|
||||
|
||||
@ -8607,7 +8619,7 @@ Parser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling,
|
||||
// part of the CoverCallExpressionAndAsyncArrowHead
|
||||
// syntax when the initial name is "async".
|
||||
maybeAsyncArrow = true;
|
||||
} else if (handler.isEvalAnyParentheses(lhs, context)) {
|
||||
} else if (handler.isEvalName(lhs, context)) {
|
||||
// Select the right EVAL op and flag pc as having a
|
||||
// direct eval.
|
||||
op = pc->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
|
||||
@ -8916,7 +8928,7 @@ Parser<ParseHandler, CharT>::checkDestructuringAssignmentTarget(Node expr, Token
|
||||
if (possibleError->hasPendingDestructuringError())
|
||||
return true;
|
||||
|
||||
if (handler.isNameAnyParentheses(expr)) {
|
||||
if (handler.isName(expr)) {
|
||||
checkDestructuringAssignmentName(expr, exprPos, possibleError);
|
||||
return true;
|
||||
}
|
||||
@ -8946,14 +8958,14 @@ void
|
||||
Parser<ParseHandler, CharT>::checkDestructuringAssignmentName(Node name, TokenPos namePos,
|
||||
PossibleError* possibleError)
|
||||
{
|
||||
MOZ_ASSERT(handler.isNameAnyParentheses(name));
|
||||
MOZ_ASSERT(handler.isName(name));
|
||||
|
||||
// Return early if a pending destructuring error is already present.
|
||||
if (possibleError->hasPendingDestructuringError())
|
||||
return;
|
||||
|
||||
if (pc->sc()->needStrictChecks()) {
|
||||
if (handler.isArgumentsAnyParentheses(name, context)) {
|
||||
if (handler.isArgumentsName(name, context)) {
|
||||
if (pc->sc()->strict()) {
|
||||
possibleError->setPendingDestructuringErrorAt(namePos,
|
||||
JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS);
|
||||
@ -8964,7 +8976,7 @@ Parser<ParseHandler, CharT>::checkDestructuringAssignmentName(Node name, TokenPo
|
||||
return;
|
||||
}
|
||||
|
||||
if (handler.isEvalAnyParentheses(name, context)) {
|
||||
if (handler.isEvalName(name, context)) {
|
||||
if (pc->sc()->strict()) {
|
||||
possibleError->setPendingDestructuringErrorAt(namePos,
|
||||
JSMSG_BAD_STRICT_ASSIGN_EVAL);
|
||||
@ -9499,7 +9511,7 @@ Parser<ParseHandler, CharT>::objectLiteral(YieldHandling yieldHandling,
|
||||
possibleError->setPendingExpressionErrorAt(pos(), JSMSG_COLON_AFTER_ID);
|
||||
}
|
||||
|
||||
if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(lhs, context)) {
|
||||
if (const char* chars = nameIsArgumentsOrEval(lhs)) {
|
||||
// |chars| is "arguments" or "eval" here.
|
||||
if (!strictModeErrorAt(namePos.begin, JSMSG_BAD_STRICT_ASSIGN, chars))
|
||||
return null();
|
||||
|
@ -861,6 +861,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
||||
FunctionCallBehavior behavior = ForbidAssignmentToFunctionCalls);
|
||||
|
||||
private:
|
||||
const char* nameIsArgumentsOrEval(Node node);
|
||||
bool checkIncDecOperand(Node operand, uint32_t operandOffset);
|
||||
bool checkStrictAssignment(Node lhs);
|
||||
|
||||
|
@ -59,23 +59,17 @@ class SyntaxParseHandler
|
||||
// noticed).
|
||||
NodeFunctionCall,
|
||||
|
||||
// Nodes representing *parenthesized* IsValidSimpleAssignmentTarget
|
||||
// nodes. We can't simply treat all such parenthesized nodes
|
||||
// identically, because in assignment and increment/decrement contexts
|
||||
// ES6 says that parentheses constitute a syntax error.
|
||||
//
|
||||
// var obj = {};
|
||||
// var val;
|
||||
// (val) = 3; (obj.prop) = 4; // okay per ES5's little mind
|
||||
// [(a)] = [3]; [(obj.prop)] = [4]; // invalid ES6 syntax
|
||||
// // ...and so on for the other IsValidSimpleAssignmentTarget nodes
|
||||
//
|
||||
// We don't know in advance in the current parser when we're parsing
|
||||
// in a place where name parenthesization changes meaning, so we must
|
||||
// have multiple node values for these cases.
|
||||
NodeParenthesizedArgumentsName,
|
||||
NodeParenthesizedEvalName,
|
||||
NodeParenthesizedName,
|
||||
// Node representing normal names which don't require any special
|
||||
// casing.
|
||||
NodeName,
|
||||
|
||||
// Nodes representing the names "arguments" and "eval".
|
||||
NodeArgumentsName,
|
||||
NodeEvalName,
|
||||
|
||||
// Node representing the "async" name, which may actually be a
|
||||
// contextual keyword.
|
||||
NodePotentialAsyncKeyword,
|
||||
|
||||
NodeDottedProperty,
|
||||
NodeElement,
|
||||
@ -93,15 +87,6 @@ class SyntaxParseHandler
|
||||
// is{Unp,P}arenthesized*(Node), parenthesize(Node), and the various
|
||||
// functions that deal in NodeUnparenthesized* below.
|
||||
|
||||
// Nodes representing unparenthesized names.
|
||||
NodeUnparenthesizedArgumentsName,
|
||||
NodeUnparenthesizedEvalName,
|
||||
NodeUnparenthesizedName,
|
||||
|
||||
// Node representing the "async" name, which may actually be a
|
||||
// contextual keyword.
|
||||
NodePotentialAsyncKeyword,
|
||||
|
||||
// Valuable for recognizing potential destructuring patterns.
|
||||
NodeUnparenthesizedArray,
|
||||
NodeUnparenthesizedObject,
|
||||
@ -168,12 +153,12 @@ class SyntaxParseHandler
|
||||
Node newName(PropertyName* name, const TokenPos& pos, JSContext* cx) {
|
||||
lastAtom = name;
|
||||
if (name == cx->names().arguments)
|
||||
return NodeUnparenthesizedArgumentsName;
|
||||
return NodeArgumentsName;
|
||||
if (pos.begin + strlen("async") == pos.end && name == cx->names().async)
|
||||
return NodePotentialAsyncKeyword;
|
||||
if (name == cx->names().eval)
|
||||
return NodeUnparenthesizedEvalName;
|
||||
return NodeUnparenthesizedName;
|
||||
return NodeEvalName;
|
||||
return NodeName;
|
||||
}
|
||||
|
||||
Node newComputedName(Node expr, uint32_t start, uint32_t end) {
|
||||
@ -181,7 +166,7 @@ class SyntaxParseHandler
|
||||
}
|
||||
|
||||
Node newObjectLiteralPropertyName(JSAtom* atom, const TokenPos& pos) {
|
||||
return NodeUnparenthesizedName;
|
||||
return NodeName;
|
||||
}
|
||||
|
||||
Node newNumber(double value, DecimalPoint decimalPoint, const TokenPos& pos) { return NodeGeneric; }
|
||||
@ -409,9 +394,9 @@ class SyntaxParseHandler
|
||||
// parsing would *already* have aborted when it saw a destructuring
|
||||
// pattern. So we can just say any old thing here, because the only
|
||||
// time we'll be wrong is a case that syntax parsing has already
|
||||
// rejected. Use NodeUnparenthesizedName so the SyntaxParseHandler
|
||||
// rejected. Use NodeName so the SyntaxParseHandler
|
||||
// Parser::cloneLeftHandSide can assert it sees only this.
|
||||
return NodeUnparenthesizedName;
|
||||
return NodeName;
|
||||
}
|
||||
|
||||
Node newCatchList(const TokenPos& pos) {
|
||||
@ -468,13 +453,6 @@ class SyntaxParseHandler
|
||||
// A number of nodes have different behavior upon parenthesization, but
|
||||
// only in some circumstances. Convert these nodes to special
|
||||
// parenthesized forms.
|
||||
if (node == NodeUnparenthesizedArgumentsName)
|
||||
return NodeParenthesizedArgumentsName;
|
||||
if (node == NodeUnparenthesizedEvalName)
|
||||
return NodeParenthesizedEvalName;
|
||||
if (node == NodeUnparenthesizedName || node == NodePotentialAsyncKeyword)
|
||||
return NodeParenthesizedName;
|
||||
|
||||
if (node == NodeUnparenthesizedArray)
|
||||
return NodeParenthesizedArray;
|
||||
if (node == NodeUnparenthesizedObject)
|
||||
@ -489,6 +467,10 @@ class SyntaxParseHandler
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
// Convert parenthesized |async| to a normal name node.
|
||||
if (node == NodePotentialAsyncKeyword)
|
||||
return NodeName;
|
||||
|
||||
// In all other cases, the parenthesized form of |node| is equivalent
|
||||
// to the unparenthesized form: return |node| unchanged.
|
||||
return node;
|
||||
@ -500,33 +482,19 @@ class SyntaxParseHandler
|
||||
|
||||
bool isConstant(Node pn) { return false; }
|
||||
|
||||
bool isNameAnyParentheses(Node node) {
|
||||
return node == NodeUnparenthesizedArgumentsName ||
|
||||
node == NodeUnparenthesizedEvalName ||
|
||||
node == NodeUnparenthesizedName ||
|
||||
node == NodePotentialAsyncKeyword ||
|
||||
node == NodeParenthesizedArgumentsName ||
|
||||
node == NodeParenthesizedEvalName ||
|
||||
node == NodeParenthesizedName;
|
||||
bool isName(Node node) {
|
||||
return node == NodeName ||
|
||||
node == NodeArgumentsName ||
|
||||
node == NodeEvalName ||
|
||||
node == NodePotentialAsyncKeyword;
|
||||
}
|
||||
|
||||
bool isArgumentsAnyParentheses(Node node, JSContext* cx) {
|
||||
return node == NodeUnparenthesizedArgumentsName || node == NodeParenthesizedArgumentsName;
|
||||
bool isArgumentsName(Node node, JSContext* cx) {
|
||||
return node == NodeArgumentsName;
|
||||
}
|
||||
|
||||
bool isEvalAnyParentheses(Node node, JSContext* cx) {
|
||||
return node == NodeUnparenthesizedEvalName || node == NodeParenthesizedEvalName;
|
||||
}
|
||||
|
||||
const char* nameIsArgumentsEvalAnyParentheses(Node node, JSContext* cx) {
|
||||
MOZ_ASSERT(isNameAnyParentheses(node),
|
||||
"must only call this method on known names");
|
||||
|
||||
if (isEvalAnyParentheses(node, cx))
|
||||
return js_eval_str;
|
||||
if (isArgumentsAnyParentheses(node, cx))
|
||||
return js_arguments_str;
|
||||
return nullptr;
|
||||
bool isEvalName(Node node, JSContext* cx) {
|
||||
return node == NodeEvalName;
|
||||
}
|
||||
|
||||
bool isAsyncKeyword(Node node, JSContext* cx) {
|
||||
|
Loading…
Reference in New Issue
Block a user