diff options
Diffstat (limited to 'js/src/frontend/Parser.cpp')
-rw-r--r-- | js/src/frontend/Parser.cpp | 88 |
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: |