summaryrefslogtreecommitdiff
path: root/js/src/frontend/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/frontend/Parser.cpp')
-rw-r--r--js/src/frontend/Parser.cpp88
1 files changed, 78 insertions, 10 deletions
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index a1b669bf91..4e3181e06b 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -438,7 +438,7 @@ UsedNameTracker::rewind(RewindToken token)
r.front().value().resetToScope(token.scriptId, token.scopeId);
}
-FunctionBox::FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead,
+FunctionBox::FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, TraceListNode* traceListHead,
JSFunction* fun, uint32_t toStringStart,
Directives directives, bool extraWarnings,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind)
@@ -882,11 +882,11 @@ Parser<FullParseHandler>::setAwaitHandling(AwaitHandling awaitHandling)
parser->setAwaitHandling(awaitHandling);
}
-template <typename ParseHandler>
-ObjectBox*
-Parser<ParseHandler>::newObjectBox(JSObject* obj)
+template <typename BoxT, typename ArgT>
+BoxT*
+ParserBase::newTraceListNode(ArgT* arg)
{
- MOZ_ASSERT(obj);
+ MOZ_ASSERT(arg);
/*
* We use JSContext.tempLifoAlloc to allocate parsed objects and place them
@@ -896,15 +896,27 @@ Parser<ParseHandler>::newObjectBox(JSObject* obj)
* function.
*/
- ObjectBox* objbox = alloc.new_<ObjectBox>(obj, traceListHead);
- if (!objbox) {
+ BoxT* box = alloc.template new_<BoxT>(arg, traceListHead);
+ if (!box) {
ReportOutOfMemory(context);
return nullptr;
}
- traceListHead = objbox;
+ traceListHead = box;
+
+ return box;
+}
+
+ObjectBox*
+ParserBase::newObjectBox(JSObject* obj)
+{
+ return newTraceListNode<ObjectBox, JSObject>(obj);
+}
- return objbox;
+BigIntBox*
+ParserBase::newBigIntBox(BigInt* val)
+{
+ return newTraceListNode<BigIntBox, BigInt>(val);
}
template <typename ParseHandler>
@@ -8937,6 +8949,15 @@ Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling
if (!tokenStream.getToken(&tok))
return null();
+ // Ensure that if we have a private name lhs we are legally constructing a
+ // `#x in obj` expression:
+ if (handler.isPrivateName(pn)) {
+ if (tok != TOK_IN) {
+ error(JSMSG_ILLEGAL_PRIVATE_NAME);
+ return null();
+ }
+ }
+
ParseNodeKind pnk;
if (tok == TOK_IN ? inHandling == InAllowed : TokenKindIsBinaryOp(tok)) {
// We're definitely not in a destructuring context, so report any
@@ -8973,7 +8994,20 @@ Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling
// If we have not detected a mixing error at this point, record that
// we have an unparenthesized expression, in case we have one later.
unparenthesizedExpression = EnforcedParentheses::CoalesceExpr;
- break;
+ break;
+ case TOK_IN:
+ // if the LHS is a private name, and the operator is In,
+ // ensure we're construcing an ergonomic brand check of
+ // '#x in y', rather than having a higher precedence operator
+ // like + cause a different reduction, such as
+ // 1 + #x in y.
+ if (handler.isPrivateName(pn)) {
+ if (depth > 0 && Precedence(kindStack[depth - 1]) >= Precedence(PNK_IN)) {
+ error(JSMSG_ILLEGAL_PRIVATE_NAME);
+ return null();
+ }
+ }
+ break;
default:
// Do nothing in other cases.
break;
@@ -10579,6 +10613,37 @@ Parser<ParseHandler>::newRegExp()
return handler.newRegExp(reobj, pos(), *this);
}
+template <>
+BigIntLiteral*
+Parser<FullParseHandler>::newBigInt()
+{
+ // The token's charBuffer contains the DecimalIntegerLiteral or
+ // NumericLiteralBase production, and as such does not include the
+ // BigIntLiteralSuffix (the trailing "n"). Note that NumericLiteralBase
+ // productions may start with 0[bBoOxX], indicating binary/octal/hex.
+ const auto& chars = tokenStream.getTokenbuf();
+ mozilla::Range<const char16_t> source(chars.begin(), chars.length());
+
+ BigInt* b = js::ParseBigIntLiteral(context, source);
+ if (!b) {
+ return null();
+ }
+
+ // newBigInt immediately puts "b" in a BigIntBox, which is allocated using
+ // tempLifoAlloc, avoiding any potential GC. Therefore it's OK to pass a
+ // raw pointer.
+ return handler.newBigInt(b, pos(), *this);
+}
+
+template <>
+SyntaxParseHandler::BigIntLiteralType
+Parser<SyntaxParseHandler>::newBigInt()
+{
+ // The tokenizer has already checked the syntax of the bigint.
+
+ return handler.newBigInt();
+}
+
template <typename ParseHandler>
void
Parser<ParseHandler>::checkDestructuringAssignmentTarget(Node expr, TokenPos exprPos,
@@ -11474,6 +11539,9 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
case TOK_NUMBER:
return newNumber(tokenStream.currentToken());
+ case TOK_BIGINT:
+ return newBigInt();
+
case TOK_TRUE:
return handler.newBooleanLiteral(true, pos());
case TOK_FALSE: