WIP: Introducing a version of taggedTuple that doesn't that doesn't provide strings draft
authorDavid Teller <dteller@mozilla.com>
Thu, 27 Jul 2017 14:17:18 +0200
changeset 641346 af1f8f5422fe09e984bf2cced0ebe30fe08de48e
parent 641345 1d6f6c5a2ba53267f710d74d5350300829305494
child 641347 2e984780380a5d2fbf48838b00fdfdf85c82f2a4
push id72504
push userdteller@mozilla.com
push dateSun, 06 Aug 2017 22:28:40 +0000
milestone57.0a1
WIP: Introducing a version of taggedTuple that doesn't that doesn't provide strings MozReview-Commit-ID: 68ow1uFrrvY
js/src/frontend/BinTokenReader.cpp
js/src/frontend/BinTokenReader.h
--- a/js/src/frontend/BinTokenReader.cpp
+++ b/js/src/frontend/BinTokenReader.cpp
@@ -267,16 +267,285 @@ SimpleTokenReader::taggedTuple(std::stri
 
     if (!this->readConst("</head>")) {
         return false;
     }
 
     subReader->init(this->current, this->stop, nullptr, "</tuple>", this);
     return true;
 }
+bool
+SimpleTokenReader::taggedTuple(Kind& tag, SimpleTokenReader::BinFields& fields, SimpleTokenReader* subReader)
+{
+    // Header
+    if (!this->readConst("<tuple>")) {
+        return false;
+    }
+
+    if (!this->readConst("<head>")) {
+        return false;
+    }
+
+    // Name.
+    // Caution: we do not validate the string.
+    Maybe<std::string> maybeName;
+    if (!this->readMaybeString(&maybeName)) {
+        return false;
+    }
+
+    if (!maybeName) {
+        return false;
+    }
+
+    // This would probably be faster with a HashTable, but we don't
+    // really care about the speed of SimpleTokenReader.
+    if (*maybeName == "ArrayExpression") {
+        tag = Kind::array_expression;
+    } else if (*maybeName == "AssignmentExpression") {
+        tag = Kind::assignment_expression;
+    } else if (*maybeName == "AssignmentOperator") {
+        tag = Kind::assignment_operator;
+    } else if (*maybeName == "BinaryExpression") {
+        tag = Kind::binary_expression;
+    } else if (*maybeName == "BinaryOperator") {
+        tag = Kind::binary_operator;
+    } else if (*maybeName == "BINJS:Scope") {
+        tag = Kind::binjs_scope;
+    } else if (*maybeName == "BlockStatement") {
+        tag = Kind::block_statement;
+    } else if (*maybeName == "BooleanLiteral") {
+        tag = Kind::boolean_literal;
+    } else if (*maybeName == "BreakStatement") {
+        tag = Kind::break_statement;
+    } else if (*maybeName == "CallExpression") {
+        tag = Kind::call_expression;
+    } else if (*maybeName == "CatchClause") {
+        tag = Kind::catch_clause;
+    } else if (*maybeName == "ConditionalExpression") {
+        tag = Kind::conditional_expression;
+    } else if (*maybeName == "ContinueStatement") {
+        tag = Kind::continue_statement;
+    } else if (*maybeName == "DebuggerStatement") {
+        tag = Kind::debugger_statement;
+    } else if (*maybeName == "Declaration") {
+        tag = Kind::declaration;
+    } else if (*maybeName == "Directive") {
+        tag = Kind::directive;
+    } else if (*maybeName == "DirectiveLiteral") {
+        tag = Kind::directive_literal;
+    } else if (*maybeName == "DoWhileStatement") {
+        tag = Kind::do_while_statement;
+    } else if (*maybeName == "EmptyStatement") {
+        tag = Kind::empty_statement;
+    } else if (*maybeName == "Expression") {
+        tag = Kind::expression;
+    } else if (*maybeName == "ExpressionStatement") {
+        tag = Kind::expression_statement;
+    } else if (*maybeName == "ForStatement") {
+        tag = Kind::for_statement;
+    } else if (*maybeName == "ForInStatement") {
+        tag = Kind::for_in_statement;
+    } else if (*maybeName == "Function") {
+        tag = Kind::function;
+    } else if (*maybeName == "FunctionExpression") {
+        tag = Kind::function_expression;
+    } else if (*maybeName == "FunctionDeclaration") {
+        tag = Kind::function_declaration;
+    } else if (*maybeName == "Identifier") {
+        tag = Kind::identifier;
+    } else if (*maybeName == "IfStatement") {
+        tag = Kind::if_statement;
+    } else if (*maybeName == "LabeledStatement") {
+        tag = Kind::labeled_statement;
+    } else if (*maybeName == "Literal") {
+        tag = Kind::literal;
+    } else if (*maybeName == "LogicalExpression") {
+        tag = Kind::logical_expression;
+    } else if (*maybeName == "LogicalOperator") {
+        tag = Kind::logical_operator;
+    } else if (*maybeName == "MemberExpression") {
+        tag = Kind::member_expression;
+    } else if (*maybeName == "Node") {
+        tag = Kind::node;
+    } else if (*maybeName == "NewExpression") {
+        tag = Kind::new_expression;
+    } else if (*maybeName == "NullLiteral") {
+        tag = Kind::null_literal;
+    } else if (*maybeName == "NumericLiteral") {
+        tag = Kind::numeric_literal;
+    } else if (*maybeName == "ObjectExpression") {
+        tag = Kind::object_expression;
+    } else if (*maybeName == "ObjectMember") {
+        tag = Kind::object_member;
+    } else if (*maybeName == "ObjectMethod") {
+        tag = Kind::object_method;
+    } else if (*maybeName == "ObjectProperty") {
+        tag = Kind::object_property;
+    } else if (*maybeName == "Pattern") {
+        tag = Kind::pattern;
+    } else if (*maybeName == "Program") {
+        tag = Kind::program;
+    } else if (*maybeName == "PropertyKind") {
+        tag = Kind::property_kind;
+    } else if (*maybeName == "RegExpLiteral") {
+        tag = Kind::regexp_literal;
+    } else if (*maybeName == "ReturnStatement") {
+        tag = Kind::return_statement;
+    } else if (*maybeName == "SequenceExpression") {
+        tag = Kind::sequence_expression;
+    } else if (*maybeName == "StringLiteral") {
+        tag = Kind::string_literal;
+    } else if (*maybeName == "Statement") {
+        tag = Kind::statement;
+    } else if (*maybeName == "SwitchCase") {
+        tag = Kind::switch_case;
+    } else if (*maybeName == "SwitchStatement") {
+        tag = Kind::switch_statement;
+    } else if (*maybeName == "ThisExpression") {
+        tag = Kind::this_expression;
+    } else if (*maybeName == "ThrowStatement") {
+        tag = Kind::throw_statement;
+    } else if (*maybeName == "TryStatement") {
+        tag = Kind::try_statement;
+    } else if (*maybeName == "UnaryExpression") {
+        tag = Kind::unary_expression;
+    } else if (*maybeName == "UnaryOperator") {
+        tag = Kind::unary_operator;
+    } else if (*maybeName == "UpdateExpression") {
+        tag = Kind::update_expression;
+    } else if (*maybeName == "UpdateOperator") {
+        tag = Kind::update_operator;
+    } else if (*maybeName == "VariableDeclaration") {
+        tag = Kind::variable_declaration;
+    } else if (*maybeName == "VariableDeclarator") {
+        tag = Kind::variable_declarator;
+    } else if (*maybeName == "VariableKind") {
+        tag = Kind::variable_kind;
+    } else if (*maybeName == "WhileStatement") {
+        tag = Kind::while_statement;
+    } else if (*maybeName == "WithStatement") {
+        tag = Kind::with_statement;
+    } else {
+        return this->raiseError();
+    }
+
+    // Now fields.
+    uint32_t fieldNum;
+    if (!this->readInternalUint32(&fieldNum)) {
+        return false;
+    }
+
+    fields.clear();
+    if (!fields.reserve(fieldNum)) {
+        return false;
+    }
+    for (uint32_t i = 0; i < fieldNum; ++i) {
+        Maybe<std::string> maybeString;
+        if (!this->readMaybeString(&maybeString)) {
+            return false;
+        }
+        if (maybeString.isNothing()) {
+            return false;
+        }
+
+        // This would probably be faster with a HashTable, but we don't
+        // really care about the speed of SimpleTokenReader.
+        Field field;
+        if (*maybeString == "alternate") {
+            field = Field::alternate;
+        } else if (*maybeString == "argument") {
+            field = Field::argument;
+        } else if (*maybeString == "arguments") {
+            field = Field::arguments;
+        } else if (*maybeString == "BINJS:Scope") {
+            field = Field::binjs_scope;
+        } else if (*maybeString == "block") {
+            field = Field::block;
+        } else if (*maybeString == "callee") {
+            field = Field::callee;
+        } else if (*maybeString == "cases") {
+            field = Field::cases;
+        } else if (*maybeString == "consequent") {
+            field = Field::consequent;
+        } else if (*maybeString == "computed") {
+            field = Field::computed;
+        } else if (*maybeString == "body") {
+            field = Field::body;
+        } else if (*maybeString == "declarations") {
+            field = Field::declarations;
+        } else if (*maybeString == "directives") {
+            field = Field::directives;
+        } else if (*maybeString == "discriminant") {
+            field = Field::discriminant;
+        } else if (*maybeString == "elements") {
+            field = Field::elements;
+        } else if (*maybeString == "expression") {
+            field = Field::expression;
+        } else if (*maybeString == "expressions") {
+            field = Field::expressions;
+        } else if (*maybeString == "finalizer") {
+            field = Field::finalizer;
+        } else if (*maybeString == "flags") {
+            field = Field::flags;
+        } else if (*maybeString == "handler") {
+            field = Field::handler;
+        } else if (*maybeString == "id") {
+            field = Field::id;
+        } else if (*maybeString == "init") {
+            field = Field::init;
+        } else if (*maybeString == "key") {
+            field = Field::key;
+        } else if (*maybeString == "kind") {
+            field = Field::kind;
+        } else if (*maybeString == "label") {
+            field = Field::label;
+        } else if (*maybeString == "left") {
+            field = Field::left;
+        } else if (*maybeString == "name") {
+            field = Field::name;
+        } else if (*maybeString == "object") {
+            field = Field::object;
+        } else if (*maybeString == "operator") {
+            field = Field::operator_;
+        } else if (*maybeString == "param") {
+            field = Field::param;
+        } else if (*maybeString == "params") {
+            field = Field::params;
+        } else if (*maybeString == "pattern") {
+            field = Field::pattern;
+        } else if (*maybeString == "prefix") {
+            field = Field::prefix;
+        } else if (*maybeString == "properties") {
+            field = Field::properties;
+        } else if (*maybeString == "property") {
+            field = Field::property;
+        } else if (*maybeString == "right") {
+            field = Field::right;
+        } else if (*maybeString == "test") {
+            field = Field::test;
+        } else if (*maybeString == "update") {
+            field = Field::update;
+        } else if (*maybeString == "value") {
+            field = Field::value;
+        } else {
+            return this->raiseError();
+        }
+        Unused << fields.append(field); // Already checked.
+    }
+
+    // End of header
+
+    if (!this->readConst("</head>")) {
+        return false;
+    }
+
+    // Body
+    subReader->init(this->current, this->stop, nullptr, "</tuple>", this);
+    return true;
+}
 
 // Untagged tuple:
 // - "<tuple>";
 // - contents (specified by the higher-level grammar);
 // - "</tuple>"
 bool
 SimpleTokenReader::untaggedTuple(SimpleTokenReader* subReader)
 {
--- a/js/src/frontend/BinTokenReader.h
+++ b/js/src/frontend/BinTokenReader.h
@@ -7,24 +7,132 @@
 #include <js/TypeDecls.h>
 
 namespace js {
 namespace frontend {
 
 using namespace mozilla;
 using namespace JS;
 
+enum class Kind {
+    array_expression,
+    assignment_expression,
+    assignment_operator,
+    binary_expression,
+    binary_operator,
+    binjs_scope,
+    block_statement,
+    boolean_literal,
+    break_statement,
+    call_expression,
+    catch_clause,
+    conditional_expression,
+    continue_statement,
+    debugger_statement,
+    declaration,
+    directive,
+    directive_literal,
+    do_while_statement,
+    empty_statement,
+    expression,
+    expression_statement,
+    for_statement,
+    for_in_statement,
+    function,
+    function_expression,
+    function_declaration,
+    identifier,
+    if_statement,
+    labeled_statement,
+    literal,
+    logical_expression,
+    logical_operator,
+    member_expression,
+    node,
+    new_expression,
+    null_literal,
+    numeric_literal,
+    object_expression,
+    object_member,
+    object_method,
+    object_property,
+    pattern,
+    program,
+    property_kind,
+    regexp_literal,
+    return_statement,
+    sequence_expression,
+    string_literal,
+    statement,
+    switch_case,
+    switch_statement,
+    this_expression,
+    throw_statement,
+    try_statement,
+    unary_expression,
+    unary_operator,
+    update_expression,
+    update_operator,
+    variable_declaration,
+    variable_declarator,
+    variable_kind,
+    while_statement,
+    with_statement,
+};
+
+enum class Field {
+    alternate,
+    argument,
+    arguments,
+    binjs_scope,
+    block,
+    callee,
+    cases,
+    consequent,
+    computed,
+    body,
+    declarations,
+    directives,
+    discriminant,
+    elements,
+    expression,
+    expressions,
+    finalizer,
+    flags,
+    handler,
+    id,
+    init,
+    key,
+    kind,
+    label,
+    left,
+    name,
+    object,
+    operator_,
+    param,
+    params,
+    pattern,
+    prefix,
+    properties,
+    property,
+    right,
+    test,
+    update,
+    value,
+};
+
 /**
  * A simple, extremely sub-optimal TokenReader, used as scaffolding for testing
  * the implementation of binary parsing.
  */
 class SimpleTokenReader MOZ_STACK_CLASS
 {
 public:
     using Fields = Vector<std::string, 8>;
+    using BinFields = Vector<Field, 8>;
 public:
     SimpleTokenReader(JSContext* cx_)
         : cx(cx_)
         , initialized(false)
         , parent(nullptr)
         , errored(false)
         , current(nullptr)
         , stop(nullptr)
@@ -180,16 +288,17 @@ public:
      *
      * Before destructing `subReader`, callers MUST reach the end of the
      * tagged tuple. Failure to do so may either raise an error or cause
      * an inconsistent sequence of tokens in the parent.
      *
      * @return out If the header of the tuple is invalid.
      */
     bool taggedTuple(std::string* tag, SimpleTokenReader::Fields *fields, SimpleTokenReader *subReader);
+    bool taggedTuple(Kind& tag, SimpleTokenReader::BinFields& fields, SimpleTokenReader *subReader);
 
     /**
      * Start reading an untagged tuple.
      * @param subReader (OUT) A token reader for the list. It does NOT
      * support `skip()`.
      *
      * Before destructing `subReader`, callers MUST reach the end of the
      * tuple. Failure to do so may either raise an error or cause