summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorGaming4JC <g4jc@hyperbola.info>2019-07-14 13:39:17 -0400
committerGaming4JC <g4jc@hyperbola.info>2019-07-18 22:38:45 -0400
commitaf6b4ab1a22c87e8a29bad74ca0e2522f6f48a41 (patch)
tree08fc210678866596e1a9e38d7b7bc3c0651306c0 /js
parent9529bf4ae15626fe39b731da3fa5dc60e2e8a123 (diff)
downloaduxp-af6b4ab1a22c87e8a29bad74ca0e2522f6f48a41.tar.gz
1303703 - Part 3: Syntax parse destructuring assignment patterns.
Diffstat (limited to 'js')
-rw-r--r--js/src/frontend/FullParseHandler.h6
-rw-r--r--js/src/frontend/Parser.cpp333
-rw-r--r--js/src/frontend/Parser.h53
-rw-r--r--js/src/frontend/SyntaxParseHandler.h6
-rw-r--r--js/src/js.msg2
5 files changed, 202 insertions, 198 deletions
diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h
index 7ddd8d3068..c7a7e0843a 100644
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -878,6 +878,10 @@ class FullParseHandler
return node->isKind(PNK_NAME);
}
+ bool isArgumentsAnyParentheses(ParseNode* node, ExclusiveContext* cx) {
+ return node->isKind(PNK_NAME) && node->pn_atom == cx->names().arguments;
+ }
+
bool isEvalAnyParentheses(ParseNode* node, ExclusiveContext* cx) {
return node->isKind(PNK_NAME) && node->pn_atom == cx->names().eval;
}
@@ -888,7 +892,7 @@ class FullParseHandler
if (isEvalAnyParentheses(node, cx))
return js_eval_str;
- if (node->pn_atom == cx->names().arguments)
+ if (isArgumentsAnyParentheses(node, cx))
return js_arguments_str;
return nullptr;
}
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 16eb7d85c0..c1e165db52 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -690,6 +690,19 @@ ParserBase::extraWarning(unsigned errorNumber, ...)
}
bool
+ParserBase::extraWarningAt(uint32_t offset, unsigned errorNumber, ...)
+{
+ va_list args;
+ va_start(args, errorNumber);
+
+ bool result =
+ tokenStream.reportExtraWarningErrorNumberVA(nullptr, offset, errorNumber, args);
+
+ va_end(args);
+ return result;
+}
+
+bool
ParserBase::strictModeError(unsigned errorNumber, ...)
{
va_list args;
@@ -745,14 +758,6 @@ ParserBase::reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumb
template <>
bool
-Parser<FullParseHandler>::abortIfSyntaxParser()
-{
- handler.disableSyntaxParser();
- return true;
-}
-
-template <>
-bool
Parser<SyntaxParseHandler>::abortIfSyntaxParser()
{
abortedSyntaxParse = true;
@@ -4128,8 +4133,17 @@ Parser<ParseHandler>::PossibleError::error(ErrorKind kind)
{
if (kind == ErrorKind::Expression)
return exprError_;
- MOZ_ASSERT(kind == ErrorKind::Destructuring);
- return destructuringError_;
+ if (kind == ErrorKind::Destructuring)
+ return destructuringError_;
+ MOZ_ASSERT(kind == ErrorKind::DestructuringWarning);
+ return destructuringWarning_;
+}
+
+template <typename ParseHandler>
+bool
+Parser<ParseHandler>::PossibleError::hasPendingDestructuringError()
+{
+ return hasError(ErrorKind::Destructuring);
}
template <typename ParseHandler>
@@ -4173,6 +4187,14 @@ Parser<ParseHandler>::PossibleError::setPendingDestructuringErrorAt(const TokenP
template <typename ParseHandler>
void
+Parser<ParseHandler>::PossibleError::setPendingDestructuringWarningAt(const TokenPos& pos,
+ unsigned errorNumber)
+{
+ setPending(ErrorKind::DestructuringWarning, pos, errorNumber);
+}
+
+template <typename ParseHandler>
+void
Parser<ParseHandler>::PossibleError::setPendingExpressionErrorAt(const TokenPos& pos,
unsigned errorNumber)
{
@@ -4193,23 +4215,36 @@ Parser<ParseHandler>::PossibleError::checkForError(ErrorKind kind)
template <typename ParseHandler>
bool
-Parser<ParseHandler>::PossibleError::checkForDestructuringError()
+Parser<ParseHandler>::PossibleError::checkForWarning(ErrorKind kind)
+{
+ if (!hasError(kind))
+ return true;
+
+ Error& err = error(kind);
+ return parser_.extraWarningAt(err.offset_, err.errorNumber_);
+}
+
+template <typename ParseHandler>
+bool
+Parser<ParseHandler>::PossibleError::checkForDestructuringErrorOrWarning()
{
// Clear pending expression error, because we're definitely not in an
// expression context.
setResolved(ErrorKind::Expression);
- // Report any pending destructuring error.
- return checkForError(ErrorKind::Destructuring);
+ // Report any pending destructuring error or warning.
+ return checkForError(ErrorKind::Destructuring) &&
+ checkForWarning(ErrorKind::DestructuringWarning);
}
template <typename ParseHandler>
bool
Parser<ParseHandler>::PossibleError::checkForExpressionError()
{
- // Clear pending destructuring error, because we're definitely not in a
- // destructuring context.
+ // Clear pending destructuring error or warning, because we're definitely
+ // not in a destructuring context.
setResolved(ErrorKind::Destructuring);
+ setResolved(ErrorKind::DestructuringWarning);
// Report any pending expression error.
return checkForError(ErrorKind::Expression);
@@ -4241,150 +4276,6 @@ Parser<ParseHandler>::PossibleError::transferErrorsTo(PossibleError* other)
transferErrorTo(ErrorKind::Expression, other);
}
-template <>
-bool
-Parser<FullParseHandler>::checkDestructuringAssignmentName(ParseNode* expr)
-{
- MOZ_ASSERT(!handler.isUnparenthesizedDestructuringPattern(expr));
-
- // Parentheses are forbidden around destructuring *patterns* (but allowed
- // around names). Use our nicer error message for parenthesized, nested
- // patterns.
- if (handler.isParenthesizedDestructuringPattern(expr)) {
- errorAt(expr->pn_pos.begin, JSMSG_BAD_DESTRUCT_PARENS);
- return false;
- }
-
- // The expression must be a simple assignment target, i.e. either a name
- // or a property accessor.
- if (handler.isNameAnyParentheses(expr)) {
- if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(expr, context)) {
- if (!strictModeErrorAt(expr->pn_pos.begin, JSMSG_BAD_STRICT_ASSIGN, chars))
- return false;
- }
-
- return true;
- }
-
- if (handler.isPropertyAccess(expr))
- return true;
-
- errorAt(expr->pn_pos.begin, JSMSG_BAD_DESTRUCT_TARGET);
- return false;
-}
-
-template <>
-bool
-Parser<FullParseHandler>::checkDestructuringAssignmentPattern(ParseNode* pattern,
- PossibleError* possibleError /* = nullptr */);
-
-template <>
-bool
-Parser<FullParseHandler>::checkDestructuringAssignmentObject(ParseNode* objectPattern)
-{
- MOZ_ASSERT(objectPattern->isKind(PNK_OBJECT));
-
- for (ParseNode* member = objectPattern->pn_head; member; member = member->pn_next) {
- ParseNode* target;
- if (member->isKind(PNK_MUTATEPROTO)) {
- target = member->pn_kid;
- } else {
- MOZ_ASSERT(member->isKind(PNK_COLON) || member->isKind(PNK_SHORTHAND));
- MOZ_ASSERT_IF(member->isKind(PNK_SHORTHAND),
- member->pn_left->isKind(PNK_OBJECT_PROPERTY_NAME) &&
- member->pn_right->isKind(PNK_NAME) &&
- member->pn_left->pn_atom == member->pn_right->pn_atom);
-
- target = member->pn_right;
- }
- if (handler.isUnparenthesizedAssignment(target))
- target = target->pn_left;
-
- if (handler.isUnparenthesizedDestructuringPattern(target)) {
- if (!checkDestructuringAssignmentPattern(target))
- return false;
- } else {
- if (!checkDestructuringAssignmentName(target))
- return false;
- }
- }
-
- return true;
-}
-
-template <>
-bool
-Parser<FullParseHandler>::checkDestructuringAssignmentArray(ParseNode* arrayPattern)
-{
- MOZ_ASSERT(arrayPattern->isKind(PNK_ARRAY));
-
- for (ParseNode* element = arrayPattern->pn_head; element; element = element->pn_next) {
- if (element->isKind(PNK_ELISION))
- continue;
-
- ParseNode* target;
- if (element->isKind(PNK_SPREAD)) {
- if (element->pn_next) {
- errorAt(element->pn_next->pn_pos.begin, JSMSG_PARAMETER_AFTER_REST);
- return false;
- }
- target = element->pn_kid;
- } else if (handler.isUnparenthesizedAssignment(element)) {
- target = element->pn_left;
- } else {
- target = element;
- }
-
- if (handler.isUnparenthesizedDestructuringPattern(target)) {
- if (!checkDestructuringAssignmentPattern(target))
- return false;
- } else {
- if (!checkDestructuringAssignmentName(target))
- return false;
- }
- }
-
- return true;
-}
-
-/*
- * Destructuring patterns can appear in two kinds of contexts:
- *
- * - assignment-like: assignment expressions and |for| loop heads. In
- * these cases, the patterns' property value positions can be
- * arbitrary lvalue expressions; the destructuring is just a fancy
- * assignment.
- *
- * - binding-like: |var| and |let| declarations, functions' formal
- * parameter lists, |catch| clauses, and comprehension tails. In
- * these cases, the patterns' property value positions must be
- * simple names; the destructuring defines them as new variables.
- *
- * In the first case, other code parses the pattern as an arbitrary
- * primaryExpr, and then, here in checkDestructuringAssignmentPattern, verify
- * that the tree is a valid AssignmentPattern.
- */
-template <>
-bool
-Parser<FullParseHandler>::checkDestructuringAssignmentPattern(ParseNode* pattern,
- PossibleError* possibleError /* = nullptr */)
-{
- if (pattern->isKind(PNK_ARRAYCOMP)) {
- errorAt(pattern->pn_pos.begin, JSMSG_ARRAY_COMP_LEFTSIDE);
- return false;
- }
-
- bool isDestructuring = pattern->isKind(PNK_ARRAY)
- ? checkDestructuringAssignmentArray(pattern)
- : checkDestructuringAssignmentObject(pattern);
-
- // Report any pending destructuring error.
- if (isDestructuring && possibleError && !possibleError->checkForDestructuringError())
- return false;
-
- return isDestructuring;
-}
-
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::bindingInitializer(Node lhs, DeclarationKind kind,
@@ -5154,14 +5045,6 @@ Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, Node impor
}
template<>
-bool
-Parser<SyntaxParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet)
-{
- MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
- return false;
-}
-
-template<>
ParseNode*
Parser<FullParseHandler>::importDeclaration()
{
@@ -6182,7 +6065,7 @@ Parser<ParseHandler>::forHeadStart(YieldHandling yieldHandling,
// Verify the left-hand side expression doesn't have a forbidden form.
if (handler.isUnparenthesizedDestructuringPattern(*forInitialPart)) {
- if (!checkDestructuringAssignmentPattern(*forInitialPart, &possibleError))
+ if (!possibleError.checkForDestructuringErrorOrWarning())
return false;
} else if (handler.isNameAnyParentheses(*forInitialPart)) {
const char* chars = handler.nameIsArgumentsEvalAnyParentheses(*forInitialPart, context);
@@ -8148,7 +8031,7 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
if (!tokenStream.getToken(&tt, TokenStream::Operand))
return null();
- uint32_t exprOffset = pos().begin;
+ TokenPos exprPos = pos();
bool endsExpr;
@@ -8354,12 +8237,12 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
return null();
}
- if (!checkDestructuringAssignmentPattern(lhs, &possibleErrorInner))
+ if (!possibleErrorInner.checkForDestructuringErrorOrWarning())
return null();
} else if (handler.isNameAnyParentheses(lhs)) {
if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(lhs, context)) {
// |chars| is "arguments" or "eval" here.
- if (!strictModeErrorAt(exprOffset, JSMSG_BAD_STRICT_ASSIGN, chars))
+ if (!strictModeErrorAt(exprPos.begin, JSMSG_BAD_STRICT_ASSIGN, chars))
return null();
}
@@ -8367,10 +8250,13 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
} else if (handler.isPropertyAccess(lhs)) {
// Permitted: no additional testing/fixup needed.
} else if (handler.isFunctionCall(lhs)) {
- if (!strictModeErrorAt(exprOffset, JSMSG_BAD_LEFTSIDE_OF_ASS))
+ if (!strictModeErrorAt(exprPos.begin, JSMSG_BAD_LEFTSIDE_OF_ASS))
return null();
+
+ if (possibleError)
+ possibleError->setPendingDestructuringErrorAt(exprPos, JSMSG_BAD_DESTRUCT_TARGET);
} else {
- errorAt(exprOffset, JSMSG_BAD_LEFTSIDE_OF_ASS);
+ errorAt(exprPos.begin, JSMSG_BAD_LEFTSIDE_OF_ASS);
return null();
}
@@ -9391,6 +9277,74 @@ Parser<ParseHandler>::newRegExp()
}
template <typename ParseHandler>
+void
+Parser<ParseHandler>::checkDestructuringAssignmentTarget(Node expr, TokenPos exprPos,
+ PossibleError* possibleError)
+{
+ // Return early if a pending destructuring error is already present.
+ if (possibleError->hasPendingDestructuringError())
+ return;
+
+ if (pc->sc()->needStrictChecks()) {
+ if (handler.isArgumentsAnyParentheses(expr, context)) {
+ if (pc->sc()->strict()) {
+ possibleError->setPendingDestructuringErrorAt(exprPos,
+ JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS);
+ } else {
+ possibleError->setPendingDestructuringWarningAt(exprPos,
+ JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS);
+ }
+ return;
+ }
+
+ if (handler.isEvalAnyParentheses(expr, context)) {
+ if (pc->sc()->strict()) {
+ possibleError->setPendingDestructuringErrorAt(exprPos,
+ JSMSG_BAD_STRICT_ASSIGN_EVAL);
+ } else {
+ possibleError->setPendingDestructuringWarningAt(exprPos,
+ JSMSG_BAD_STRICT_ASSIGN_EVAL);
+ }
+ return;
+ }
+ }
+
+ // The expression must be either a simple assignment target, i.e. a name
+ // or a property accessor, or a nested destructuring pattern.
+ if (!handler.isUnparenthesizedDestructuringPattern(expr) &&
+ !handler.isNameAnyParentheses(expr) &&
+ !handler.isPropertyAccess(expr))
+ {
+ // Parentheses are forbidden around destructuring *patterns* (but
+ // allowed around names). Use our nicer error message for
+ // parenthesized, nested patterns.
+ if (handler.isParenthesizedDestructuringPattern(expr))
+ possibleError->setPendingDestructuringErrorAt(exprPos, JSMSG_BAD_DESTRUCT_PARENS);
+ else
+ possibleError->setPendingDestructuringErrorAt(exprPos, JSMSG_BAD_DESTRUCT_TARGET);
+ }
+}
+
+template <typename ParseHandler>
+void
+Parser<ParseHandler>::checkDestructuringAssignmentElement(Node expr, TokenPos exprPos,
+ PossibleError* possibleError)
+{
+ // ES2018 draft rev 0719f44aab93215ed9a626b2f45bd34f36916834
+ // 12.15.5 Destructuring Assignment
+ //
+ // AssignmentElement[Yield, Await]:
+ // DestructuringAssignmentTarget[?Yield, ?Await]
+ // DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]
+
+ // If |expr| is an assignment element with an initializer expression, its
+ // destructuring assignment target was already validated in assignExpr().
+ // Otherwise we need to check that |expr| is a valid destructuring target.
+ if (!handler.isUnparenthesizedAssignment(expr))
+ checkDestructuringAssignmentTarget(expr, exprPos, possibleError);
+}
+
+template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError)
{
@@ -9439,17 +9393,29 @@ Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling, PossibleErro
} else if (tt == TOK_TRIPLEDOT) {
tokenStream.consumeKnownToken(TOK_TRIPLEDOT, TokenStream::Operand);
uint32_t begin = pos().begin;
+
+ TokenPos innerPos;
+ if (!tokenStream.peekTokenPos(&innerPos, TokenStream::Operand))
+ return null();
+
Node inner = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
possibleError);
if (!inner)
return null();
+ if (possibleError)
+ checkDestructuringAssignmentTarget(inner, innerPos, possibleError);
if (!handler.addSpreadElement(literal, begin, inner))
return null();
} else {
+ TokenPos elementPos;
+ if (!tokenStream.peekTokenPos(&elementPos, TokenStream::Operand))
+ return null();
Node element = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
possibleError);
if (!element)
return null();
+ if (possibleError)
+ checkDestructuringAssignmentElement(element, elementPos, possibleError);
if (foldConstants && !FoldConstants(context, &element, this))
return null();
handler.addArrayElement(literal, element);
@@ -9731,6 +9697,9 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
return null();
if (propType == PropertyType::Normal) {
+ TokenPos exprPos;
+ if (!tokenStream.peekTokenPos(&exprPos, TokenStream::Operand))
+ return null();
Node propExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
possibleError);
if (!propExpr)
@@ -9770,6 +9739,9 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
if (!handler.addPropertyDefinition(literal, propName, propExpr))
return null();
}
+
+ if (possibleError)
+ checkDestructuringAssignmentElement(propExpr, exprPos, possibleError);
} else if (propType == PropertyType::Shorthand) {
/*
* Support, e.g., |({x, y} = o)| as destructuring shorthand
@@ -9784,6 +9756,9 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
if (!nameExpr)
return null();
+ if (possibleError)
+ checkDestructuringAssignmentTarget(nameExpr, namePos, possibleError);
+
if (!handler.addShorthand(literal, propName, nameExpr))
return null();
} else if (propType == PropertyType::CoverInitializedName) {
@@ -9820,6 +9795,12 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
possibleError->setPendingExpressionErrorAt(pos(), JSMSG_COLON_AFTER_ID);
}
+ if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(lhs, context)) {
+ // |chars| is "arguments" or "eval" here.
+ if (!strictModeErrorAt(namePos.begin, JSMSG_BAD_STRICT_ASSIGN, chars))
+ return null();
+ }
+
Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
if (!rhs)
return null();
@@ -9832,9 +9813,6 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
if (!handler.addPropertyDefinition(literal, propName, propExpr))
return null();
-
- if (!abortIfSyntaxParser())
- return null();
} else {
RootedAtom funName(context);
if (!tokenStream.isCurrentTokenType(TOK_RB)) {
@@ -9856,6 +9834,9 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
JSOp op = JSOpFromPropertyType(propType);
if (!handler.addObjectMethodDefinition(literal, propName, fn, op))
return null();
+
+ if (possibleError)
+ possibleError->setPendingDestructuringErrorAt(namePos, JSMSG_BAD_DESTRUCT_TARGET);
}
if (!tokenStream.getToken(&tt))
diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
index 8bd691fc4f..88d2dad189 100644
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -877,6 +877,12 @@ class ParserBase : public StrictModeGetter
*/
MOZ_MUST_USE bool extraWarning(unsigned errorNumber, ...);
+ /*
+ * If extra warnings are enabled, report the given warning at the given
+ * offset.
+ */
+ MOZ_MUST_USE bool extraWarningAt(uint32_t offset, unsigned errorNumber, ...);
+
bool isValidStrictBinding(PropertyName* name);
bool warnOnceAboutExprClosure();
@@ -941,7 +947,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
class MOZ_STACK_CLASS PossibleError
{
private:
- enum class ErrorKind { Expression, Destructuring };
+ enum class ErrorKind { Expression, Destructuring, DestructuringWarning };
enum class ErrorState { None, Pending };
@@ -956,11 +962,12 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Parser<ParseHandler>& parser_;
Error exprError_;
Error destructuringError_;
+ Error destructuringWarning_;
// Returns the error report.
Error& error(ErrorKind kind);
- // Return true if an error is pending without reporting
+ // Return true if an error is pending without reporting.
bool hasError(ErrorKind kind);
// Resolve any pending error.
@@ -972,7 +979,11 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
// If there is a pending error, report it and return false, otherwise
// return true.
- bool checkForError(ErrorKind kind);
+ MOZ_MUST_USE bool checkForError(ErrorKind kind);
+
+ // If there is a pending warning, report it and return either false or
+ // true depending on the werror option, otherwise return true.
+ MOZ_MUST_USE bool checkForWarning(ErrorKind kind);
// Transfer an existing error to another instance.
void transferErrorTo(ErrorKind kind, PossibleError* other);
@@ -980,23 +991,33 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
public:
explicit PossibleError(Parser<ParseHandler>& parser);
+ // Return true if a pending destructuring error is present.
+ bool hasPendingDestructuringError();
+
// Set a pending destructuring error. Only a single error may be set
// per instance, i.e. subsequent calls to this method are ignored and
// won't overwrite the existing pending error.
void setPendingDestructuringErrorAt(const TokenPos& pos, unsigned errorNumber);
+ // Set a pending destructuring warning. Only a single warning may be
+ // set per instance, i.e. subsequent calls to this method are ignored
+ // and won't overwrite the existing pending warning.
+ void setPendingDestructuringWarningAt(const TokenPos& pos, unsigned errorNumber);
+
// Set a pending expression error. Only a single error may be set per
// instance, i.e. subsequent calls to this method are ignored and won't
// overwrite the existing pending error.
void setPendingExpressionErrorAt(const TokenPos& pos, unsigned errorNumber);
- // If there is a pending destructuring error, report it and return
- // false, otherwise return true. Clears any pending expression error.
- bool checkForDestructuringError();
+ // If there is a pending destructuring error or warning, report it and
+ // return false, otherwise return true. Clears any pending expression
+ // error.
+ MOZ_MUST_USE bool checkForDestructuringErrorOrWarning();
// If there is a pending expression error, report it and return false,
- // otherwise return true. Clears any pending destructuring error.
- bool checkForExpressionError();
+ // otherwise return true. Clears any pending destructuring error or
+ // warning.
+ MOZ_MUST_USE bool checkForExpressionError();
// Pass pending errors between possible error instances. This is useful
// for extending the lifetime of a pending error beyond the scope of
@@ -1496,18 +1517,10 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Node objectBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
Node arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
- // Top-level entrypoint into destructuring assignment pattern checking and
- // name-analyzing.
- bool checkDestructuringAssignmentPattern(Node pattern,
- PossibleError* possibleError = nullptr);
-
- // Recursive methods for checking/name-analyzing subcomponents of an
- // destructuring assignment pattern. The array/object methods *must* be
- // passed arrays or objects. The name method may be passed anything but
- // will report an error if not passed a name.
- bool checkDestructuringAssignmentArray(Node arrayPattern);
- bool checkDestructuringAssignmentObject(Node objectPattern);
- bool checkDestructuringAssignmentName(Node expr);
+ void checkDestructuringAssignmentTarget(Node expr, TokenPos exprPos,
+ PossibleError* possibleError);
+ void checkDestructuringAssignmentElement(Node expr, TokenPos exprPos,
+ PossibleError* possibleError);
Node newNumber(const Token& tok) {
return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos);
diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h
index 895ba64169..7de6a242ec 100644
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -561,6 +561,10 @@ class SyntaxParseHandler
node == NodeParenthesizedName;
}
+ bool isArgumentsAnyParentheses(Node node, ExclusiveContext* cx) {
+ return node == NodeUnparenthesizedArgumentsName || node == NodeParenthesizedArgumentsName;
+ }
+
bool isEvalAnyParentheses(Node node, ExclusiveContext* cx) {
return node == NodeUnparenthesizedEvalName || node == NodeParenthesizedEvalName;
}
@@ -571,7 +575,7 @@ class SyntaxParseHandler
if (isEvalAnyParentheses(node, cx))
return js_eval_str;
- if (node == NodeUnparenthesizedArgumentsName || node == NodeParenthesizedArgumentsName)
+ if (isArgumentsAnyParentheses(node, cx))
return js_arguments_str;
return nullptr;
}
diff --git a/js/src/js.msg b/js/src/js.msg
index ec49d06c93..f57b36a905 100644
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -211,6 +211,8 @@ MSG_DEF(JSMSG_BAD_POW_LEFTSIDE, 0, JSEXN_SYNTAXERR, "unparenthesized unar
MSG_DEF(JSMSG_BAD_PROP_ID, 0, JSEXN_SYNTAXERR, "invalid property id")
MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 1, JSEXN_SYNTAXERR, "{0} not in function")
MSG_DEF(JSMSG_BAD_STRICT_ASSIGN, 1, JSEXN_SYNTAXERR, "'{0}' can't be defined or assigned to in strict mode code")
+MSG_DEF(JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS, 0, JSEXN_SYNTAXERR, "'arguments' can't be defined or assigned to in strict mode code")
+MSG_DEF(JSMSG_BAD_STRICT_ASSIGN_EVAL, 0, JSEXN_SYNTAXERR, "'eval' can't be defined or assigned to in strict mode code")
MSG_DEF(JSMSG_BAD_SWITCH, 0, JSEXN_SYNTAXERR, "invalid switch statement")
MSG_DEF(JSMSG_BAD_SUPER, 0, JSEXN_SYNTAXERR, "invalid use of keyword 'super'")
MSG_DEF(JSMSG_BAD_SUPERPROP, 1, JSEXN_SYNTAXERR, "use of super {0} accesses only valid within methods or eval code within methods")