author | David Teller <dteller@mozilla.com> |
Thu, 27 Jul 2017 14:17:18 +0200 | |
changeset 641346 | af1f8f5422fe09e984bf2cced0ebe30fe08de48e |
parent 641345 | 1d6f6c5a2ba53267f710d74d5350300829305494 |
child 641347 | 2e984780380a5d2fbf48838b00fdfdf85c82f2a4 |
push id | 72504 |
push user | dteller@mozilla.com |
push date | Sun, 06 Aug 2017 22:28:40 +0000 |
milestone | 57.0a1 |
js/src/frontend/BinTokenReader.cpp | file | annotate | diff | comparison | revisions | |
js/src/frontend/BinTokenReader.h | file | annotate | diff | comparison | revisions |
--- 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