Bug 1545751 - In BinAST, pass Context while parsing;r=arai

The Context 0.1 format specifies that the (de)compression of nodes is determined by:
- its node type;
- its parent type;
- the index in the parent node;
- whether the node is an element of an array.

This patch modifies the parser generator to pass the information during parsing.

Differential Revision: https://phabricator.services.mozilla.com/D28534

--HG--
extra : moz-landing-system : lando
This commit is contained in:
David Teller 2019-04-25 08:07:57 +00:00
Родитель 765b073841
Коммит 5f3821de3e
10 изменённых файлов: 1607 добавлений и 1002 удалений

Просмотреть файл

@ -118,6 +118,7 @@ hpp:
using AutoList = typename Tokenizer::AutoList;
using AutoTaggedTuple = typename Tokenizer::AutoTaggedTuple;
using Chars = typename Tokenizer::Chars;
using Context = typename BinASTTokenReaderBase::Context;
public:
// Auto-generated types.
@ -297,6 +298,8 @@ hpp:
#include <stddef.h>
#include "jstypes.h"
/**
* Definition of Binary AST tokens.
*
@ -625,7 +628,7 @@ BreakStatement:
block:
replace: |
RootedAtom label(cx_);
MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom());
MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(fieldContext));
build: |
if (label) {
@ -769,7 +772,7 @@ ContinueStatement:
block:
replace: |
RootedAtom label(cx_);
MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom());
MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(fieldContext));
build: |
if (label) {
@ -1282,7 +1285,7 @@ LiteralRegExpExpression:
block:
replace: |
Chars flags(cx_);
MOZ_TRY(tokenizer_->readChars(flags));
MOZ_TRY(tokenizer_->readChars(flags, fieldContext));
build: |
RegExpFlags reflags = RegExpFlag::NoFlags;
for (auto c : flags) {

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -42,6 +42,7 @@ class BinASTParser : public BinASTParserPerTokenizer<Tok> {
using AutoList = typename Tokenizer::AutoList;
using AutoTaggedTuple = typename Tokenizer::AutoTaggedTuple;
using Chars = typename Tokenizer::Chars;
using Context = typename BinASTTokenReaderBase::Context;
public:
// Auto-generated types.
@ -121,349 +122,486 @@ class BinASTParser : public BinASTParserPerTokenizer<Tok> {
// `ParseNode*` may never be nullptr
JS::Result<Ok> parseAssertedMaybePositionalParameterName(
AssertedScopeKind scopeKind,
MutableHandle<GCVector<JSAtom*>> positionalParams);
JS::Result<ParseNode*> parseAssignmentTarget();
JS::Result<ParseNode*> parseBinding();
JS::Result<ParseNode*> parseExpression();
JS::Result<ParseNode*> parseExpressionOrSuper();
JS::Result<ParseNode*> parseForInOfBindingOrAssignmentTarget();
JS::Result<ParseNode*> parseObjectProperty();
JS::Result<ParseNode*> parseParameter();
JS::Result<ParseNode*> parseProgram();
JS::Result<ParseNode*> parsePropertyName();
JS::Result<ParseNode*> parseSimpleAssignmentTarget();
JS::Result<ParseNode*> parseSpreadElementOrExpression();
JS::Result<ParseNode*> parseStatement();
MutableHandle<GCVector<JSAtom*>> positionalParams,
const Context& context);
JS::Result<ParseNode*> parseAssignmentTarget(const Context& context);
JS::Result<ParseNode*> parseBinding(const Context& context);
JS::Result<ParseNode*> parseExpression(const Context& context);
JS::Result<ParseNode*> parseExpressionOrSuper(const Context& context);
JS::Result<ParseNode*> parseForInOfBindingOrAssignmentTarget(
const Context& context);
JS::Result<ParseNode*> parseObjectProperty(const Context& context);
JS::Result<ParseNode*> parseParameter(const Context& context);
JS::Result<ParseNode*> parseProgram(const Context& context);
JS::Result<ParseNode*> parsePropertyName(const Context& context);
JS::Result<ParseNode*> parseSimpleAssignmentTarget(const Context& context);
JS::Result<ParseNode*> parseSpreadElementOrExpression(const Context& context);
JS::Result<ParseNode*> parseStatement(const Context& context);
JS::Result<Ok> parseSumAssertedMaybePositionalParameterName(
const size_t start, const BinASTKind kind, const BinASTFields& fields,
AssertedScopeKind scopeKind,
MutableHandle<GCVector<JSAtom*>> positionalParams);
MutableHandle<GCVector<JSAtom*>> positionalParams,
const Context& context);
JS::Result<ParseNode*> parseSumAssignmentTarget(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumBinding(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumExpression(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumExpressionOrSuper(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumForInOfBindingOrAssignmentTarget(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumObjectProperty(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumParameter(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumProgram(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumPropertyName(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumSimpleAssignmentTarget(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumSpreadElementOrExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumStatement(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseSumVariableDeclarationOrExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
// ----- Interfaces (by lexicographical order)
// `ParseNode*` may never be nullptr
JS::Result<Ok> parseAssertedBlockScope();
JS::Result<Ok> parseAssertedBoundName(AssertedScopeKind scopeKind);
JS::Result<Ok> parseAssertedBoundNamesScope();
JS::Result<Ok> parseAssertedDeclaredName(AssertedScopeKind scopeKind);
JS::Result<Ok> parseAssertedBlockScope(const Context& context);
JS::Result<Ok> parseAssertedBoundName(AssertedScopeKind scopeKind,
const Context& context);
JS::Result<Ok> parseAssertedBoundNamesScope(const Context& context);
JS::Result<Ok> parseAssertedDeclaredName(AssertedScopeKind scopeKind,
const Context& context);
JS::Result<Ok> parseAssertedParameterScope(
MutableHandle<GCVector<JSAtom*>> positionalParams);
JS::Result<Ok> parseAssertedScriptGlobalScope();
JS::Result<Ok> parseAssertedVarScope();
JS::Result<ParseNode*> parseBindingIdentifier();
JS::Result<ParseNode*> parseBlock();
JS::Result<LexicalScopeNode*> parseCatchClause();
JS::Result<ParseNode*> parseDirective();
JS::Result<ListNode*> parseFormalParameters();
MutableHandle<GCVector<JSAtom*>> positionalParams,
const Context& context);
JS::Result<Ok> parseAssertedScriptGlobalScope(const Context& context);
JS::Result<Ok> parseAssertedVarScope(const Context& context);
JS::Result<ParseNode*> parseBindingIdentifier(const Context& context);
JS::Result<ParseNode*> parseBlock(const Context& context);
JS::Result<LexicalScopeNode*> parseCatchClause(const Context& context);
JS::Result<ParseNode*> parseDirective(const Context& context);
JS::Result<ListNode*> parseFormalParameters(const Context& context);
JS::Result<Ok> parseFunctionExpressionContents(uint32_t funLength,
ListNode** paramsOut,
ListNode** bodyOut);
ListNode** bodyOut,
const Context& context);
JS::Result<Ok> parseFunctionOrMethodContents(uint32_t funLength,
ListNode** paramsOut,
ListNode** bodyOut);
ListNode** bodyOut,
const Context& context);
JS::Result<Ok> parseGetterContents(uint32_t funLength, ListNode** paramsOut,
ListNode** bodyOut);
JS::Result<ParseNode*> parseIdentifierExpression();
ListNode** bodyOut,
const Context& context);
JS::Result<ParseNode*> parseIdentifierExpression(const Context& context);
JS::Result<Ok> parseSetterContents(uint32_t funLength, ListNode** paramsOut,
ListNode** bodyOut);
JS::Result<CaseClause*> parseSwitchCase();
JS::Result<ParseNode*> parseSwitchDefault();
JS::Result<ParseNode*> parseVariableDeclarator();
ListNode** bodyOut,
const Context& context);
JS::Result<CaseClause*> parseSwitchCase(const Context& context);
JS::Result<ParseNode*> parseSwitchDefault(const Context& context);
JS::Result<ParseNode*> parseVariableDeclarator(const Context& context);
JS::Result<ParseNode*> parseInterfaceArrayAssignmentTarget(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceArrayBinding(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceArrayExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<Ok> parseInterfaceAssertedBlockScope(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<Ok> parseInterfaceAssertedBoundName(const size_t start,
const BinASTKind kind,
const BinASTFields& fields,
AssertedScopeKind scopeKind);
AssertedScopeKind scopeKind,
const Context& context);
JS::Result<Ok> parseInterfaceAssertedBoundNamesScope(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
JS::Result<Ok> parseInterfaceAssertedDeclaredName(
const size_t start, const BinASTKind kind, const BinASTFields& fields,
AssertedScopeKind scopeKind);
const Context& context);
JS::Result<Ok> parseInterfaceAssertedDeclaredName(const size_t start,
const BinASTKind kind,
const BinASTFields& fields,
AssertedScopeKind scopeKind,
const Context& context);
JS::Result<Ok> parseInterfaceAssertedParameterScope(
const size_t start, const BinASTKind kind, const BinASTFields& fields,
MutableHandle<GCVector<JSAtom*>> positionalParams);
MutableHandle<GCVector<JSAtom*>> positionalParams,
const Context& context);
JS::Result<Ok> parseInterfaceAssertedPositionalParameterName(
const size_t start, const BinASTKind kind, const BinASTFields& fields,
AssertedScopeKind scopeKind,
MutableHandle<GCVector<JSAtom*>> positionalParams);
MutableHandle<GCVector<JSAtom*>> positionalParams,
const Context& context);
JS::Result<Ok> parseInterfaceAssertedScriptGlobalScope(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<Ok> parseInterfaceAssertedVarScope(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceAssignmentExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceAssignmentTargetIdentifier(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceAwaitExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceBinaryExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceBindingIdentifier(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceBindingWithInitializer(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceBlock(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceBreakStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceCallExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<LexicalScopeNode*> parseInterfaceCatchClause(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceClassDeclaration(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceClassExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceCompoundAssignmentExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceComputedMemberAssignmentTarget(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceComputedMemberExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceComputedPropertyName(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceConditionalExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceContinueStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceDataProperty(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceDebuggerStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceDirective(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceDoWhileStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithFunctionBody(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceEagerFunctionDeclaration(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceEagerFunctionExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceEagerGetter(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceEagerMethod(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceEagerSetter(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceEmptyStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceExpressionStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceForInOfBinding(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceForInStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceForOfStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceForStatement(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ListNode*> parseInterfaceFormalParameters(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<Ok> parseInterfaceFunctionExpressionContents(
const size_t start, const BinASTKind kind, const BinASTFields& fields,
uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut);
uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
const Context& context);
JS::Result<Ok> parseInterfaceFunctionOrMethodContents(
const size_t start, const BinASTKind kind, const BinASTFields& fields,
uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut);
uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
const Context& context);
JS::Result<Ok> parseInterfaceGetterContents(
const size_t start, const BinASTKind kind, const BinASTFields& fields,
uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut);
uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
const Context& context);
JS::Result<ParseNode*> parseInterfaceIdentifierExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceIfStatement(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLabelledStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithFunctionBody(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLazyFunctionDeclaration(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLazyFunctionExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLazyGetter(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLazyMethod(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLazySetter(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLiteralBooleanExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLiteralInfinityExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLiteralNullExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLiteralNumericExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLiteralPropertyName(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLiteralRegExpExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceLiteralStringExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceModule(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
JS::Result<ParseNode*> parseInterfaceNewExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceNewExpression(const size_t start,
const BinASTKind kind,
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceNewTargetExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceObjectAssignmentTarget(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
JS::Result<ParseNode*> parseInterfaceObjectBinding(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceObjectBinding(const size_t start,
const BinASTKind kind,
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceObjectExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceReturnStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceScript(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<Ok> parseInterfaceSetterContents(
const size_t start, const BinASTKind kind, const BinASTFields& fields,
uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut);
uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
const Context& context);
JS::Result<ParseNode*> parseInterfaceShorthandProperty(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
JS::Result<ParseNode*> parseInterfaceSpreadElement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceSpreadElement(const size_t start,
const BinASTKind kind,
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceStaticMemberAssignmentTarget(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceStaticMemberExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceSuper(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<CaseClause*> parseInterfaceSwitchCase(const size_t start,
const BinASTKind kind,
const BinASTFields& fields);
JS::Result<ParseNode*> parseInterfaceSwitchDefault(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceSwitchDefault(const size_t start,
const BinASTKind kind,
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceSwitchStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceSwitchStatementWithDefault(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceTemplateExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceThisExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceThrowStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceTryCatchStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceTryFinallyStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceUnaryExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceUpdateExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceVariableDeclaration(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceVariableDeclarator(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceWhileStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
JS::Result<ParseNode*> parseInterfaceWithStatement(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceWithStatement(const size_t start,
const BinASTKind kind,
const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceYieldExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
JS::Result<ParseNode*> parseInterfaceYieldStarExpression(
const size_t start, const BinASTKind kind, const BinASTFields& fields);
const size_t start, const BinASTKind kind, const BinASTFields& fields,
const Context& context);
// ----- String enums (by lexicographical order)
JS::Result<typename BinASTParser<Tok>::AssertedDeclaredKind>
parseAssertedDeclaredKind();
JS::Result<typename BinASTParser<Tok>::BinaryOperator> parseBinaryOperator();
parseAssertedDeclaredKind(const Context& context);
JS::Result<typename BinASTParser<Tok>::BinaryOperator> parseBinaryOperator(
const Context& context);
JS::Result<typename BinASTParser<Tok>::CompoundAssignmentOperator>
parseCompoundAssignmentOperator();
JS::Result<typename BinASTParser<Tok>::UnaryOperator> parseUnaryOperator();
JS::Result<typename BinASTParser<Tok>::UpdateOperator> parseUpdateOperator();
parseCompoundAssignmentOperator(const Context& context);
JS::Result<typename BinASTParser<Tok>::UnaryOperator> parseUnaryOperator(
const Context& context);
JS::Result<typename BinASTParser<Tok>::UpdateOperator> parseUpdateOperator(
const Context& context);
JS::Result<typename BinASTParser<Tok>::VariableDeclarationKind>
parseVariableDeclarationKind();
parseVariableDeclarationKind(const Context& context);
// ----- Lists (by lexicographical order)
JS::Result<ParseNode*> parseArguments();
JS::Result<ListNode*> parseFunctionBody();
JS::Result<Ok> parseListOfAssertedBoundName(AssertedScopeKind scopeKind);
JS::Result<Ok> parseListOfAssertedDeclaredName(AssertedScopeKind scopeKind);
JS::Result<ParseNode*> parseArguments(const Context& context);
JS::Result<ListNode*> parseFunctionBody(const Context& context);
JS::Result<Ok> parseListOfAssertedBoundName(AssertedScopeKind scopeKind,
const Context& context);
JS::Result<Ok> parseListOfAssertedDeclaredName(AssertedScopeKind scopeKind,
const Context& context);
JS::Result<Ok> parseListOfAssertedMaybePositionalParameterName(
AssertedScopeKind scopeKind,
MutableHandle<GCVector<JSAtom*>> positionalParams);
JS::Result<ListNode*> parseListOfDirective();
JS::Result<ListNode*> parseListOfObjectProperty();
JS::Result<ListNode*> parseListOfOptionalSpreadElementOrExpression();
JS::Result<ListNode*> parseListOfParameter();
JS::Result<ListNode*> parseListOfStatement();
JS::Result<ListNode*> parseListOfSwitchCase();
MutableHandle<GCVector<JSAtom*>> positionalParams,
const Context& context);
JS::Result<ListNode*> parseListOfDirective(const Context& context);
JS::Result<ListNode*> parseListOfObjectProperty(const Context& context);
JS::Result<ListNode*> parseListOfOptionalSpreadElementOrExpression(
const Context& context);
JS::Result<ListNode*> parseListOfParameter(const Context& context);
JS::Result<ListNode*> parseListOfStatement(const Context& context);
JS::Result<ListNode*> parseListOfSwitchCase(const Context& context);
JS::Result<ListNode*> parseListOfVariableDeclarator(
ParseNodeKind declarationListKind);
ParseNodeKind declarationListKind, const Context& context);
// ----- Default values (by lexicographical order)
JS::Result<ParseNode*> parseOptionalBinding();
JS::Result<ParseNode*> parseOptionalBindingIdentifier();
JS::Result<LexicalScopeNode*> parseOptionalCatchClause();
JS::Result<ParseNode*> parseOptionalExpression();
JS::Result<ParseNode*> parseOptionalSpreadElementOrExpression();
JS::Result<ParseNode*> parseOptionalStatement();
JS::Result<ParseNode*> parseOptionalVariableDeclarationOrExpression();
JS::Result<ParseNode*> parseOptionalBinding(const Context& context);
JS::Result<ParseNode*> parseOptionalBindingIdentifier(const Context& context);
JS::Result<LexicalScopeNode*> parseOptionalCatchClause(
const Context& context);
JS::Result<ParseNode*> parseOptionalExpression(const Context& context);
JS::Result<ParseNode*> parseOptionalSpreadElementOrExpression(
const Context& context);
JS::Result<ParseNode*> parseOptionalStatement(const Context& context);
JS::Result<ParseNode*> parseOptionalVariableDeclarationOrExpression(
const Context& context);
};
extern template class BinASTParser<BinASTTokenReaderMultipart>;

Просмотреть файл

@ -132,7 +132,8 @@ JS::Result<ParseNode*> BinASTParserPerTokenizer<Tok>::parseAux(
MOZ_TRY(tokenizer_->readHeader());
ParseNode* result(nullptr);
MOZ_TRY_VAR(result, asFinalParser()->parseProgram());
const Context topContext(Context::topLevel());
MOZ_TRY_VAR(result, asFinalParser()->parseProgram(topContext));
mozilla::Maybe<GlobalScope::Data*> bindings =
NewGlobalScopeData(cx_, varScope, alloc_, pc_);
@ -191,7 +192,12 @@ JS::Result<FunctionNode*> BinASTParserPerTokenizer<Tok>::parseLazyFunction(
ListNode* tmpBody;
auto parseFunc = isExpr ? &FinalParser::parseFunctionExpressionContents
: &FinalParser::parseFunctionOrMethodContents;
MOZ_TRY((asFinalParser()->*parseFunc)(func->nargs(), &params, &tmpBody));
// Inject a toplevel context (i.e. no parent) to parse the lazy content.
// In the future, we may move this to a more specific context.
const Context context(Context::topLevel());
MOZ_TRY(
(asFinalParser()->*parseFunc)(func->nargs(), &params, &tmpBody, context));
BINJS_TRY_DECL(lexicalScopeData,
NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));

Просмотреть файл

@ -56,6 +56,7 @@ class BinASTParserPerTokenizer : public BinASTParserBase,
using AutoTaggedTuple = typename Tokenizer::AutoTaggedTuple;
using BinASTFields = typename Tokenizer::BinASTFields;
using Chars = typename Tokenizer::Chars;
using Context = BinASTTokenReaderBase::Context;
public:
// Auto-generated types.

Просмотреть файл

@ -14,6 +14,8 @@
#include <stddef.h>
#include "jstypes.h"
/**
* Definition of Binary AST tokens.
*
@ -185,7 +187,7 @@ namespace frontend {
F(YieldExpression, "YieldExpression") \
F(YieldStarExpression, "YieldStarExpression")
enum class BinASTKind {
enum class BinASTKind : uint16_t {
#define EMIT_ENUM(name, _) name,
FOR_EACH_BIN_KIND(EMIT_ENUM)
#undef EMIT_ENUM
@ -278,7 +280,7 @@ const size_t BINASTKIND_LIMIT = 120;
F(Update, "update") \
F(Value, "value")
enum class BinASTField {
enum class BinASTField : uint16_t {
#define EMIT_ENUM(name, _) name,
FOR_EACH_BIN_FIELD(EMIT_ENUM)
#undef EMIT_ENUM
@ -354,7 +356,7 @@ const size_t BINASTFIELD_LIMIT = 69;
F(VariableDeclarationKindConst, "const") \
F(VariableDeclarationKindLet, "let")
enum class BinASTVariant {
enum class BinASTVariant : uint16_t {
#define EMIT_ENUM(name, _) name,
FOR_EACH_BIN_VARIANT(EMIT_ENUM)
#undef EMIT_ENUM

Просмотреть файл

@ -25,6 +25,53 @@ class MOZ_STACK_CLASS BinASTTokenReaderBase {
template <typename T>
using ErrorResult = mozilla::GenericErrorResult<T>;
// The context in which we read a token.
struct Context {
// Construct a context for a root node.
constexpr static Context topLevel() {
return Context(BinASTKind::_Null, 0, ElementOf::TaggedTuple);
}
Context arrayElement() const {
return Context(kind, fieldIndex, ElementOf::Array);
}
// Construct a context for a field of a tagged tuple.
constexpr static Context firstField(BinASTKind kind) {
return Context(kind, 0, ElementOf::TaggedTuple);
}
const Context operator++(int) {
MOZ_ASSERT(elementOf == ElementOf::TaggedTuple);
Context result = *this;
fieldIndex++;
return result;
}
// The kind of the tagged tuple containing the token.
//
// If the parent is the root, use `BinASTKind::_Null`.
BinASTKind kind;
// The index of the token as a field of the parent.
uint8_t fieldIndex;
enum class ElementOf {
// This token is an element of an array.
Array,
// This token is a field of a tagged tuple.
TaggedTuple,
};
ElementOf elementOf;
Context() = delete;
private:
constexpr Context(BinASTKind kind, uint8_t fieldIndex, ElementOf elementOf)
: kind(kind), fieldIndex(fieldIndex), elementOf(elementOf) {}
};
// The information needed to skip a subtree.
class SkippableSubTree {
public:

Просмотреть файл

@ -221,7 +221,7 @@ void BinASTTokenReaderMultipart::traceMetadata(JSTracer* trc) {
}
}
JS::Result<bool> BinASTTokenReaderMultipart::readBool() {
JS::Result<bool> BinASTTokenReaderMultipart::readBool(const Context&) {
updateLatestKnownGood();
BINJS_MOZ_TRY_DECL(byte, readByte());
@ -241,7 +241,7 @@ JS::Result<bool> BinASTTokenReaderMultipart::readBool() {
//
// NULL_FLOAT_REPRESENTATION (signaling NaN) => null
// anything other 64 bit sequence => IEEE-764 64-bit floating point number
JS::Result<double> BinASTTokenReaderMultipart::readDouble() {
JS::Result<double> BinASTTokenReaderMultipart::readDouble(const Context&) {
updateLatestKnownGood();
uint8_t bytes[8];
@ -262,7 +262,7 @@ JS::Result<double> BinASTTokenReaderMultipart::readDouble() {
}
// A single atom is represented as an index into the table of strings.
JS::Result<JSAtom*> BinASTTokenReaderMultipart::readMaybeAtom() {
JS::Result<JSAtom*> BinASTTokenReaderMultipart::readMaybeAtom(const Context&) {
updateLatestKnownGood();
BINJS_MOZ_TRY_DECL(index, readInternalUint32());
@ -272,8 +272,9 @@ JS::Result<JSAtom*> BinASTTokenReaderMultipart::readMaybeAtom() {
return metadata_->getAtom(index);
}
JS::Result<JSAtom*> BinASTTokenReaderMultipart::readAtom() {
BINJS_MOZ_TRY_DECL(maybe, readMaybeAtom());
JS::Result<JSAtom*> BinASTTokenReaderMultipart::readAtom(
const Context& context) {
BINJS_MOZ_TRY_DECL(maybe, readMaybeAtom(context));
if (!maybe) {
return raiseError("Empty string");
@ -282,8 +283,9 @@ JS::Result<JSAtom*> BinASTTokenReaderMultipart::readAtom() {
return maybe;
}
JS::Result<JSAtom*> BinASTTokenReaderMultipart::readMaybeIdentifierName() {
BINJS_MOZ_TRY_DECL(result, readMaybeAtom());
JS::Result<JSAtom*> BinASTTokenReaderMultipart::readMaybeIdentifierName(
const Context& context) {
BINJS_MOZ_TRY_DECL(result, readMaybeAtom(context));
if (result) {
if (!IsIdentifier(result)) {
return raiseError("Invalid identifier");
@ -292,19 +294,22 @@ JS::Result<JSAtom*> BinASTTokenReaderMultipart::readMaybeIdentifierName() {
return result;
}
JS::Result<JSAtom*> BinASTTokenReaderMultipart::readIdentifierName() {
BINJS_MOZ_TRY_DECL(result, readAtom());
JS::Result<JSAtom*> BinASTTokenReaderMultipart::readIdentifierName(
const Context& context) {
BINJS_MOZ_TRY_DECL(result, readAtom(context));
if (!IsIdentifier(result)) {
return raiseError("Invalid identifier");
}
return result;
}
JS::Result<JSAtom*> BinASTTokenReaderMultipart::readPropertyKey() {
return readAtom();
JS::Result<JSAtom*> BinASTTokenReaderMultipart::readPropertyKey(
const Context& context) {
return readAtom(context);
}
JS::Result<Ok> BinASTTokenReaderMultipart::readChars(Chars& out) {
JS::Result<Ok> BinASTTokenReaderMultipart::readChars(Chars& out,
const Context&) {
updateLatestKnownGood();
BINJS_MOZ_TRY_DECL(index, readInternalUint32());
@ -316,7 +321,8 @@ JS::Result<Ok> BinASTTokenReaderMultipart::readChars(Chars& out) {
return Ok();
}
JS::Result<BinASTVariant> BinASTTokenReaderMultipart::readVariant() {
JS::Result<BinASTVariant> BinASTTokenReaderMultipart::readVariant(
const Context&) {
updateLatestKnownGood();
BINJS_MOZ_TRY_DECL(index, readInternalUint32());
@ -351,7 +357,7 @@ JS::Result<BinASTVariant> BinASTTokenReaderMultipart::readVariant() {
}
JS::Result<BinASTTokenReaderBase::SkippableSubTree>
BinASTTokenReaderMultipart::readSkippableSubTree() {
BinASTTokenReaderMultipart::readSkippableSubTree(const Context&) {
updateLatestKnownGood();
BINJS_MOZ_TRY_DECL(byteLen, readInternalUint32());
@ -370,7 +376,7 @@ BinASTTokenReaderMultipart::readSkippableSubTree() {
// - uint32_t index in table [grammar];
// - content (specified by the higher-level grammar);
JS::Result<Ok> BinASTTokenReaderMultipart::enterTaggedTuple(
BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields&,
BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields&, const Context&,
AutoTaggedTuple& guard) {
BINJS_MOZ_TRY_DECL(index, readInternalUint32());
if (index >= metadata_->numBinASTKinds()) {
@ -392,6 +398,7 @@ JS::Result<Ok> BinASTTokenReaderMultipart::enterTaggedTuple(
// The total byte length of `number of items` + `contents` must be `byte
// length`.
JS::Result<Ok> BinASTTokenReaderMultipart::enterList(uint32_t& items,
const Context&,
AutoList& guard) {
guard.init();

Просмотреть файл

@ -37,6 +37,7 @@ class MOZ_STACK_CLASS BinASTTokenReaderMultipart
class AutoTaggedTuple;
using CharSlice = BinaryASTSupport::CharSlice;
using Context = BinASTTokenReaderBase::Context;
// This implementation of `BinASTFields` is effectively `void`, as the format
// does not embed field information.
@ -83,44 +84,45 @@ class MOZ_STACK_CLASS BinASTTokenReaderMultipart
/**
* Read a single `true | false` value.
*/
MOZ_MUST_USE JS::Result<bool> readBool();
MOZ_MUST_USE JS::Result<bool> readBool(const Context&);
/**
* Read a single `number` value.
*/
MOZ_MUST_USE JS::Result<double> readDouble();
MOZ_MUST_USE JS::Result<double> readDouble(const Context&);
/**
* Read a single `string | null` value.
*
* Fails if that string is not valid UTF-8.
*/
MOZ_MUST_USE JS::Result<JSAtom*> readMaybeAtom();
MOZ_MUST_USE JS::Result<JSAtom*> readAtom();
MOZ_MUST_USE JS::Result<JSAtom*> readMaybeAtom(const Context&);
MOZ_MUST_USE JS::Result<JSAtom*> readAtom(const Context&);
/**
* Read a single IdentifierName value.
*/
MOZ_MUST_USE JS::Result<JSAtom*> readMaybeIdentifierName();
MOZ_MUST_USE JS::Result<JSAtom*> readIdentifierName();
MOZ_MUST_USE JS::Result<JSAtom*> readMaybeIdentifierName(const Context&);
MOZ_MUST_USE JS::Result<JSAtom*> readIdentifierName(const Context&);
/**
* Read a single PropertyKey value.
*/
MOZ_MUST_USE JS::Result<JSAtom*> readPropertyKey();
MOZ_MUST_USE JS::Result<JSAtom*> readPropertyKey(const Context&);
/**
* Read a single `string | null` value.
*
* MAY check if that string is not valid UTF-8.
*/
MOZ_MUST_USE JS::Result<Ok> readChars(Chars&);
MOZ_MUST_USE JS::Result<Ok> readChars(Chars&, const Context&);
/**
* Read a single `BinASTVariant | null` value.
*/
MOZ_MUST_USE JS::Result<mozilla::Maybe<BinASTVariant>> readMaybeVariant();
MOZ_MUST_USE JS::Result<BinASTVariant> readVariant();
MOZ_MUST_USE JS::Result<mozilla::Maybe<BinASTVariant>> readMaybeVariant(
const Context&);
MOZ_MUST_USE JS::Result<BinASTVariant> readVariant(const Context&);
/**
* Read over a single `[Skippable]` subtree value.
@ -129,7 +131,8 @@ class MOZ_STACK_CLASS BinASTTokenReaderMultipart
* returned `SkippableSubTree` contains the necessary information
* to parse/tokenize the subtree at a later stage
*/
MOZ_MUST_USE JS::Result<SkippableSubTree> readSkippableSubTree();
MOZ_MUST_USE JS::Result<SkippableSubTree> readSkippableSubTree(
const Context&);
// --- Composite values.
//
@ -151,7 +154,8 @@ class MOZ_STACK_CLASS BinASTTokenReaderMultipart
* If the caller has consumed too few/too many bytes, this will be reported
* in the call go `guard.done()`.
*/
MOZ_MUST_USE JS::Result<Ok> enterList(uint32_t& length, AutoList& guard);
MOZ_MUST_USE JS::Result<Ok> enterList(uint32_t& length, const Context&,
AutoList& guard);
/**
* Start reading a tagged tuple.
@ -171,12 +175,12 @@ class MOZ_STACK_CLASS BinASTTokenReaderMultipart
*/
MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields& fields,
AutoTaggedTuple& guard);
const Context&, AutoTaggedTuple& guard);
/**
* Read a single unsigned long.
*/
MOZ_MUST_USE JS::Result<uint32_t> readUnsignedLong() {
MOZ_MUST_USE JS::Result<uint32_t> readUnsignedLong(const Context&) {
return readInternalUint32();
}

Просмотреть файл

@ -835,12 +835,18 @@ impl CPPExporter {
"".to_string()
}
};
format!(" JS::Result<{type_ok}> parse{prefix}{kind}({args}{extra});\n",
format!(" JS::Result<{type_ok}> parse{prefix}{kind}({args}{extra}{before_context}{context});\n",
prefix = prefix,
type_ok = type_ok,
kind = kind,
args = args,
extra = extra,
before_context = if args.len() > 0 || extra_params.is_some() {
", "
} else {
""
},
context = "const Context& context",
)
}
@ -862,7 +868,7 @@ impl CPPExporter {
"".to_string()
}
};
format!("{parser_class_template}JS::Result<{type_ok}>\n{parser_class_name}::parse{prefix}{kind}({args}{extra})",
format!("{parser_class_template}JS::Result<{type_ok}>\n{parser_class_name}::parse{prefix}{kind}({args}{extra}{before_context}{context})",
parser_class_template = self.rules.parser_class_template,
prefix = prefix,
type_ok = type_ok,
@ -870,12 +876,19 @@ impl CPPExporter {
kind = kind,
args = args,
extra = extra,
before_context = if args.len() > 0 || extra_params.is_some() {
", "
} else {
""
},
context = "const Context& context",
)
}
fn get_method_call(&self, var_name: &str, name: &NodeName,
prefix: &str, args: &str,
extra_params: &Option<Rc<String>>,
context_name: &str,
call_kind: MethodCallKind) -> String {
let type_ok_is_ok = match call_kind {
MethodCallKind::Decl | MethodCallKind::Var => {
@ -899,11 +912,18 @@ impl CPPExporter {
"".to_string()
}
};
let call = format!("parse{prefix}{name}({args}{extra})",
let call = format!("parse{prefix}{name}({args}{extra}{before_context}{context})",
prefix = prefix,
name = name.to_class_cases(),
args = args,
extra = extra);
extra = extra,
before_context = if extra_params.is_some() || args.len() > 0 {
", "
} else {
""
},
context = context_name
);
if type_ok_is_ok {
// Special case: `Ok` means that we shouldn't bind the return value.
@ -1248,7 +1268,7 @@ impl CPPExporter {
AutoTaggedTuple guard(*tokenizer_);
const auto start = tokenizer_->offset();
MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
{call}
@ -1259,6 +1279,7 @@ impl CPPExporter {
call = self.get_method_call("result", name,
"Sum", INTERFACE_ARGS,
&extra_args,
"context",
MethodCallKind::AlwaysDecl)
.reindent(" "),
first_line = self.get_method_definition_start(name, "", "",
@ -1293,6 +1314,7 @@ impl CPPExporter {
call = self.get_method_call("result", node,
"Interface", INTERFACE_ARGS,
&extra_args,
"context",
MethodCallKind::AlwaysVar)
.reindent(" "),
variant_name = node.to_cpp_enum_case(),
@ -1378,10 +1400,11 @@ impl CPPExporter {
AutoList guard(*tokenizer_);
const auto start = tokenizer_->offset();
MOZ_TRY(tokenizer_->enterList(length, guard));{empty_check}
MOZ_TRY(tokenizer_->enterList(length, context, guard));{empty_check}
{init}
for (uint32_t i = 0; i < length; ++i) {{
const Context childContext(context.arrayElement());
for (uint8_t i = 0; i < length; ++i) {{
{call}
{append} }}
@ -1403,6 +1426,7 @@ impl CPPExporter {
call = self.get_method_call("item",
&parser.elements, "", "",
&extra_args,
"childContext",
MethodCallKind::Decl)
.reindent(" "),
init = init,
@ -1462,7 +1486,7 @@ impl CPPExporter {
BinASTFields fields(cx_);
AutoTaggedTuple guard(*tokenizer_);
MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
{type_ok} result;
if (kind == BinASTKind::{null}) {{
{none_block}
@ -1485,6 +1509,7 @@ impl CPPExporter {
&parser.elements,
"Interface", INTERFACE_ARGS,
&extra_args,
"context",
MethodCallKind::AlwaysVar)
.reindent(" "),
before = rules_for_this_node.some_before
@ -1515,7 +1540,7 @@ impl CPPExporter {
BinASTFields fields(cx_);
AutoTaggedTuple guard(*tokenizer_);
MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
{type_ok} result;
if (kind == BinASTKind::{null}) {{
{none_block}
@ -1534,6 +1559,7 @@ impl CPPExporter {
call = self.get_method_call("result", &parser.elements,
"Sum", INTERFACE_ARGS,
&extra_args,
"context",
MethodCallKind::AlwaysVar)
.reindent(" "),
before = rules_for_this_node.some_before
@ -1571,7 +1597,7 @@ impl CPPExporter {
} else {
buffer.push_str(&format!("{first_line}
{{
BINJS_MOZ_TRY_DECL(result, tokenizer_->readMaybeAtom());
BINJS_MOZ_TRY_DECL(result, tokenizer_->readMaybeAtom(context));
{build}
@ -1600,7 +1626,7 @@ impl CPPExporter {
} else {
buffer.push_str(&format!("{first_line}
{{
BINJS_MOZ_TRY_DECL(result, tokenizer_->readMaybeIdentifierName());
BINJS_MOZ_TRY_DECL(result, tokenizer_->readMaybeIdentifierName(context));
{build}
@ -1665,7 +1691,7 @@ impl CPPExporter {
BinASTFields fields(cx_);
AutoTaggedTuple guard(*tokenizer_);
MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
if (kind != BinASTKind::{kind}) {{
return raiseInvalidKind(\"{kind}\", kind);
}}
@ -1683,6 +1709,7 @@ impl CPPExporter {
call = self.get_method_call("result", name,
"Interface", INTERFACE_ARGS,
&extra_args,
"context",
MethodCallKind::AlwaysDecl)
.reindent(" ")
));
@ -1707,6 +1734,8 @@ impl CPPExporter {
let mut fields_implem = String::new();
for field in interface.contents().fields() {
let context = "fieldContext++";
let rules_for_this_field = rules_for_this_interface.by_field.get(field.name())
.cloned()
.unwrap_or_default();
@ -1717,37 +1746,53 @@ impl CPPExporter {
Some(IsNullable { is_nullable: false, content: Primitive::Number }) => {
if needs_block {
(Some(format!("double {var_name};", var_name = var_name)),
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readDouble());", var_name = var_name)))
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readDouble({context}));",
var_name = var_name,
context = context)))
} else {
(None,
Some(format!("BINJS_MOZ_TRY_DECL({var_name}, tokenizer_->readDouble());", var_name = var_name)))
Some(format!("BINJS_MOZ_TRY_DECL({var_name}, tokenizer_->readDouble({context}));",
var_name = var_name,
context = context)))
}
}
Some(IsNullable { is_nullable: false, content: Primitive::UnsignedLong }) => {
if needs_block {
(Some(format!("uint32_t {var_name};", var_name = var_name)),
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readUnsignedLong());", var_name = var_name)))
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readUnsignedLong({context}));",
var_name = var_name,
context = context)))
} else {
(None,
Some(format!("BINJS_MOZ_TRY_DECL({var_name}, tokenizer_->readUnsignedLong());", var_name = var_name)))
Some(format!("BINJS_MOZ_TRY_DECL({var_name}, tokenizer_->readUnsignedLong({context}));",
var_name = var_name,
context = context)))
}
}
Some(IsNullable { is_nullable: false, content: Primitive::Boolean }) => {
if needs_block {
(Some(format!("bool {var_name};", var_name = var_name)),
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readBool());", var_name = var_name)))
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readBool({context}));",
var_name = var_name,
context = context)))
} else {
(None,
Some(format!("BINJS_MOZ_TRY_DECL({var_name}, tokenizer_->readBool());", var_name = var_name)))
Some(format!("BINJS_MOZ_TRY_DECL({var_name}, tokenizer_->readBool({context}));",
var_name = var_name,
context = context)))
}
}
Some(IsNullable { is_nullable: false, content: Primitive::Offset }) => {
if needs_block {
(Some(format!("BinASTTokenReaderBase::SkippableSubTree {var_name};", var_name = var_name)),
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readSkippableSubTree());", var_name = var_name)))
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readSkippableSubTree({context}));",
var_name = var_name,
context = context)))
} else {
(None,
Some(format!("BINJS_MOZ_TRY_DECL({var_name}, tokenizer_->readSkippableSubTree());", var_name = var_name)))
Some(format!("BINJS_MOZ_TRY_DECL({var_name}, tokenizer_->readSkippableSubTree({context}));",
var_name = var_name,
context = context)))
}
}
Some(IsNullable { content: Primitive::Void, .. }) => {
@ -1757,23 +1802,33 @@ impl CPPExporter {
}
Some(IsNullable { is_nullable: false, content: Primitive::String }) => {
(Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readAtom());", var_name = var_name)))
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readAtom({context}));",
var_name = var_name,
context = context)))
}
Some(IsNullable { is_nullable: false, content: Primitive::IdentifierName }) => {
(Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readIdentifierName());", var_name = var_name)))
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readIdentifierName({context}));",
var_name = var_name,
context = context)))
}
Some(IsNullable { is_nullable: false, content: Primitive::PropertyKey }) => {
(Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readPropertyKey());", var_name = var_name)))
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readPropertyKey({context}));",
var_name = var_name,
context = context)))
}
Some(IsNullable { is_nullable: true, content: Primitive::String }) => {
(Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readMaybeAtom());", var_name = var_name)))
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readMaybeAtom({context}));",
var_name = var_name,
context = context)))
}
Some(IsNullable { is_nullable: true, content: Primitive::IdentifierName }) => {
(Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readMaybeIdentifierName());", var_name = var_name)))
Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readMaybeIdentifierName({context}));",
var_name = var_name,
context = context)))
}
Some(IsNullable { is_nullable: true, content: Primitive::PropertyKey }) => {
panic!("PropertyKey shouldn't be optional");
@ -1797,6 +1852,7 @@ impl CPPExporter {
(decl_var,
Some(self.get_method_call(var_name.to_str(),
&name, "", "", &field_extra_args,
&context,
call_kind)))
}
};
@ -1823,7 +1879,8 @@ impl CPPExporter {
};
if needs_block {
let parse_var = parse_var.reindent(" ");
format!("{before_field}{decl_var} {{
format!("
{before_field}{decl_var} {{
{block_before_field}{parse_var}{block_after_field}
}}
{after_field}",
@ -1832,7 +1889,8 @@ impl CPPExporter {
block_before_field = rules_for_this_field.block_before_field.reindent(" ").newline_if_not_empty(),
parse_var = parse_var.reindent(" ").newline_if_not_empty(),
block_after_field = rules_for_this_field.block_after_field.reindent(" "),
after_field = after_field.reindent(" "))
after_field = after_field.reindent(" "),
)
} else {
// We have a before_field and an after_field. This will create newlines
// for them.
@ -1878,7 +1936,7 @@ impl CPPExporter {
{{
MOZ_ASSERT(kind == BinASTKind::{kind});
BINJS_TRY(CheckRecursionLimit(cx_));
{check_fields}
{maybe_field_context}{check_fields}
{pre}{fields_implem}
{post} return result;
}}
@ -1890,6 +1948,11 @@ impl CPPExporter {
post = build_result.newline_if_not_empty(),
kind = name.to_cpp_enum_case(),
first_line = first_line,
maybe_field_context = if interface.contents().fields().len() > 0 {
" Context fieldContext = Context::firstField(kind);\n"
} else {
""
},
));
}
}
@ -1967,7 +2030,7 @@ impl CPPExporter {
);
buffer.push_str(&format!("{rendered_doc}{first_line}
{{
BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant());
BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant(context));
{convert}
}}