Bug 1800629: Remove custom builders from Reflect.parse r=arai

Differential Revision: https://phabricator.services.mozilla.com/D167215
This commit is contained in:
Iain Ireland 2023-01-19 18:41:23 +00:00
Родитель 7a0e2975cb
Коммит 05efdc5e45
6 изменённых файлов: 87 добавлений и 785 удалений

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

@ -46,7 +46,7 @@ using mozilla::DebugOnly;
enum ASTType {
AST_ERROR = -1,
#define ASTDEF(ast, str, method) ast,
#define ASTDEF(ast, str) ast,
#include "jsast.tbl"
#undef ASTDEF
AST_LIMIT
@ -205,13 +205,7 @@ static const char* const unopNames[] = {
};
static const char* const nodeTypeNames[] = {
#define ASTDEF(ast, str, method) str,
#include "jsast.tbl"
#undef ASTDEF
nullptr};
static const char* const callbackNames[] = {
#define ASTDEF(ast, str, method) method,
#define ASTDEF(ast, str) str,
#include "jsast.tbl"
#undef ASTDEF
nullptr};
@ -264,11 +258,7 @@ static bool GetPropertyDefault(JSContext* cx, HandleObject obj, HandleId id,
enum class GeneratorStyle { None, ES6 };
/*
* Builder class that constructs JavaScript AST node objects. See:
*
* https://developer.mozilla.org/en/SpiderMonkey/Parser_API
*
* Bug 569487: generalize builder interface
* Builder class that constructs JavaScript AST node objects.
*/
class NodeBuilder {
using CallbackArray = RootedValueArray<AST_LIMIT>;
@ -276,24 +266,15 @@ class NodeBuilder {
JSContext* cx;
FrontendContext* fc;
frontend::Parser<frontend::FullParseHandler, char16_t>* parser;
bool saveLoc; /* save source location information? */
char const* src; /* source filename or null */
RootedValue srcval; /* source filename JS value or null */
CallbackArray callbacks; /* user-specified callbacks */
RootedValue userv; /* user-specified builder object or null */
bool saveLoc; /* save source location information? */
char const* src; /* source filename or null */
RootedValue srcval; /* source filename JS value or null */
public:
NodeBuilder(JSContext* c, FrontendContext* f, bool l, char const* s)
: cx(c),
fc(f),
parser(nullptr),
saveLoc(l),
src(s),
srcval(c),
callbacks(cx),
userv(c) {}
: cx(c), fc(f), parser(nullptr), saveLoc(l), src(s), srcval(c) {}
[[nodiscard]] bool init(HandleObject userobj = nullptr) {
[[nodiscard]] bool init() {
if (src) {
if (!atomValue(src, &srcval)) {
return false;
@ -302,43 +283,6 @@ class NodeBuilder {
srcval.setNull();
}
if (!userobj) {
userv.setNull();
for (unsigned i = 0; i < AST_LIMIT; i++) {
callbacks[i].setNull();
}
return true;
}
userv.setObject(*userobj);
RootedValue nullVal(cx, NullValue());
RootedValue funv(cx);
for (unsigned i = 0; i < AST_LIMIT; i++) {
const char* name = callbackNames[i];
Rooted<JSAtom*> atom(cx, Atomize(cx, name, strlen(name)));
if (!atom) {
return false;
}
RootedId id(cx, AtomToId(atom));
if (!GetPropertyDefault(cx, userobj, id, nullVal, &funv)) {
return false;
}
if (funv.isNullOrUndefined()) {
callbacks[i].setNull();
continue;
}
if (!funv.isObject() || !funv.toObject().is<JSFunction>()) {
ReportValueError(cx, JSMSG_NOT_FUNCTION, JSDVG_SEARCH_STACK, funv,
nullptr);
return false;
}
callbacks[i].set(funv);
}
return true;
}
@ -347,56 +291,6 @@ class NodeBuilder {
}
private:
[[nodiscard]] bool callbackHelper(HandleValue fun, const InvokeArgs& args,
size_t i, TokenPos* pos,
MutableHandleValue dst) {
// The end of the implementation of callback(). All arguments except
// loc have already been stored in range [0, i).
if (saveLoc) {
if (!newNodeLoc(pos, args[i])) {
return false;
}
}
return js::Call(cx, fun, userv, args, dst);
}
// Helper function for callback(). Note that all Arguments must be types
// that convert to HandleValue, so this isn't as template-y as it seems,
// just variadic.
template <typename... Arguments>
[[nodiscard]] bool callbackHelper(HandleValue fun, const InvokeArgs& args,
size_t i, HandleValue head,
Arguments&&... tail) {
// Recursive loop to store the arguments into args. This eventually
// bottoms out in a call to the non-template callbackHelper() above.
args[i].set(head);
return callbackHelper(fun, args, i + 1, std::forward<Arguments>(tail)...);
}
// Invoke a user-defined callback. The actual signature is:
//
// bool callback(HandleValue fun, HandleValue... args, TokenPos* pos,
// MutableHandleValue dst);
template <typename... Arguments>
[[nodiscard]] bool callback(HandleValue fun, Arguments&&... args) {
InvokeArgs iargs(cx);
if (!iargs.init(cx, sizeof...(args) - 2 + size_t(saveLoc))) {
return false;
}
return callbackHelper(fun, iargs, 0, std::forward<Arguments>(args)...);
}
// WARNING: Returning a Handle is non-standard, but it works in this case
// because both |v| and |UndefinedHandleValue| are definitely rooted on a
// previous stack frame (i.e. we're just choosing between two
// already-rooted values).
HandleValue opt(HandleValue v) {
MOZ_ASSERT_IF(v.isMagic(), v.whyMagic() == JS_SERIALIZE_NO_NODE);
return v.isMagic(JS_SERIALIZE_NO_NODE) ? JS::UndefinedHandleValue : v;
}
[[nodiscard]] bool atomValue(const char* s, MutableHandleValue dst) {
/*
* Bug 575416: instead of Atomize, lookup constant atoms in tbl file
@ -465,11 +359,6 @@ class NodeBuilder {
return false;
}
RootedValue cb(cx, callbacks[type]);
if (!cb.isNull()) {
return callback(cb, array, pos, dst);
}
return newNode(type, pos, propName, array, dst);
}
@ -892,93 +781,48 @@ bool NodeBuilder::blockStatement(NodeVector& elts, TokenPos* pos,
bool NodeBuilder::expressionStatement(HandleValue expr, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_EXPR_STMT]);
if (!cb.isNull()) {
return callback(cb, expr, pos, dst);
}
return newNode(AST_EXPR_STMT, pos, "expression", expr, dst);
}
bool NodeBuilder::emptyStatement(TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_EMPTY_STMT]);
if (!cb.isNull()) {
return callback(cb, pos, dst);
}
return newNode(AST_EMPTY_STMT, pos, dst);
}
bool NodeBuilder::ifStatement(HandleValue test, HandleValue cons,
HandleValue alt, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_IF_STMT]);
if (!cb.isNull()) {
return callback(cb, test, cons, opt(alt), pos, dst);
}
return newNode(AST_IF_STMT, pos, "test", test, "consequent", cons,
"alternate", alt, dst);
}
bool NodeBuilder::breakStatement(HandleValue label, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_BREAK_STMT]);
if (!cb.isNull()) {
return callback(cb, opt(label), pos, dst);
}
return newNode(AST_BREAK_STMT, pos, "label", label, dst);
}
bool NodeBuilder::continueStatement(HandleValue label, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_CONTINUE_STMT]);
if (!cb.isNull()) {
return callback(cb, opt(label), pos, dst);
}
return newNode(AST_CONTINUE_STMT, pos, "label", label, dst);
}
bool NodeBuilder::labeledStatement(HandleValue label, HandleValue stmt,
TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_LAB_STMT]);
if (!cb.isNull()) {
return callback(cb, label, stmt, pos, dst);
}
return newNode(AST_LAB_STMT, pos, "label", label, "body", stmt, dst);
}
bool NodeBuilder::throwStatement(HandleValue arg, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_THROW_STMT]);
if (!cb.isNull()) {
return callback(cb, arg, pos, dst);
}
return newNode(AST_THROW_STMT, pos, "argument", arg, dst);
}
bool NodeBuilder::returnStatement(HandleValue arg, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_RETURN_STMT]);
if (!cb.isNull()) {
return callback(cb, opt(arg), pos, dst);
}
return newNode(AST_RETURN_STMT, pos, "argument", arg, dst);
}
bool NodeBuilder::forStatement(HandleValue init, HandleValue test,
HandleValue update, HandleValue stmt,
TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_FOR_STMT]);
if (!cb.isNull()) {
return callback(cb, opt(init), opt(test), opt(update), stmt, pos, dst);
}
return newNode(AST_FOR_STMT, pos, "init", init, "test", test, "update",
update, "body", stmt, dst);
}
@ -986,13 +830,6 @@ bool NodeBuilder::forStatement(HandleValue init, HandleValue test,
bool NodeBuilder::forInStatement(HandleValue var, HandleValue expr,
HandleValue stmt, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_FOR_IN_STMT]);
if (!cb.isNull()) {
RootedValue isForEach(
cx, JS::FalseValue()); // obsolete E4X `for each` statement
return callback(cb, var, expr, stmt, isForEach, pos, dst);
}
return newNode(AST_FOR_IN_STMT, pos, "left", var, "right", expr, "body", stmt,
dst);
}
@ -1000,42 +837,22 @@ bool NodeBuilder::forInStatement(HandleValue var, HandleValue expr,
bool NodeBuilder::forOfStatement(HandleValue var, HandleValue expr,
HandleValue stmt, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_FOR_OF_STMT]);
if (!cb.isNull()) {
return callback(cb, var, expr, stmt, pos, dst);
}
return newNode(AST_FOR_OF_STMT, pos, "left", var, "right", expr, "body", stmt,
dst);
}
bool NodeBuilder::withStatement(HandleValue expr, HandleValue stmt,
TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_WITH_STMT]);
if (!cb.isNull()) {
return callback(cb, expr, stmt, pos, dst);
}
return newNode(AST_WITH_STMT, pos, "object", expr, "body", stmt, dst);
}
bool NodeBuilder::whileStatement(HandleValue test, HandleValue stmt,
TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_WHILE_STMT]);
if (!cb.isNull()) {
return callback(cb, test, stmt, pos, dst);
}
return newNode(AST_WHILE_STMT, pos, "test", test, "body", stmt, dst);
}
bool NodeBuilder::doWhileStatement(HandleValue stmt, HandleValue test,
TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_DO_STMT]);
if (!cb.isNull()) {
return callback(cb, stmt, test, pos, dst);
}
return newNode(AST_DO_STMT, pos, "body", stmt, "test", test, dst);
}
@ -1048,12 +865,6 @@ bool NodeBuilder::switchStatement(HandleValue disc, NodeVector& elts,
}
RootedValue lexicalVal(cx, BooleanValue(lexical));
RootedValue cb(cx, callbacks[AST_SWITCH_STMT]);
if (!cb.isNull()) {
return callback(cb, disc, array, lexicalVal, pos, dst);
}
return newNode(AST_SWITCH_STMT, pos, "discriminant", disc, "cases", array,
"lexical", lexicalVal, dst);
}
@ -1061,21 +872,11 @@ bool NodeBuilder::switchStatement(HandleValue disc, NodeVector& elts,
bool NodeBuilder::tryStatement(HandleValue body, HandleValue handler,
HandleValue finally, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_TRY_STMT]);
if (!cb.isNull()) {
return callback(cb, body, handler, opt(finally), pos, dst);
}
return newNode(AST_TRY_STMT, pos, "block", body, "handler", handler,
"finalizer", finally, dst);
}
bool NodeBuilder::debuggerStatement(TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_DEBUGGER_STMT]);
if (!cb.isNull()) {
return callback(cb, pos, dst);
}
return newNode(AST_DEBUGGER_STMT, pos, dst);
}
@ -1089,11 +890,6 @@ bool NodeBuilder::binaryExpression(BinaryOperator op, HandleValue left,
return false;
}
RootedValue cb(cx, callbacks[AST_BINARY_EXPR]);
if (!cb.isNull()) {
return callback(cb, opName, left, right, pos, dst);
}
return newNode(AST_BINARY_EXPR, pos, "operator", opName, "left", left,
"right", right, dst);
}
@ -1107,11 +903,6 @@ bool NodeBuilder::unaryExpression(UnaryOperator unop, HandleValue expr,
return false;
}
RootedValue cb(cx, callbacks[AST_UNARY_EXPR]);
if (!cb.isNull()) {
return callback(cb, opName, expr, pos, dst);
}
RootedValue trueVal(cx, BooleanValue(true));
return newNode(AST_UNARY_EXPR, pos, "operator", opName, "argument", expr,
"prefix", trueVal, dst);
@ -1127,11 +918,6 @@ bool NodeBuilder::assignmentExpression(AssignmentOperator aop, HandleValue lhs,
return false;
}
RootedValue cb(cx, callbacks[AST_ASSIGN_EXPR]);
if (!cb.isNull()) {
return callback(cb, opName, lhs, rhs, pos, dst);
}
return newNode(AST_ASSIGN_EXPR, pos, "operator", opName, "left", lhs, "right",
rhs, dst);
}
@ -1145,11 +931,6 @@ bool NodeBuilder::updateExpression(HandleValue expr, bool incr, bool prefix,
RootedValue prefixVal(cx, BooleanValue(prefix));
RootedValue cb(cx, callbacks[AST_UPDATE_EXPR]);
if (!cb.isNull()) {
return callback(cb, expr, opName, prefixVal, pos, dst);
}
return newNode(AST_UPDATE_EXPR, pos, "operator", opName, "argument", expr,
"prefix", prefixVal, dst);
}
@ -1178,11 +959,6 @@ bool NodeBuilder::logicalExpression(ParseNodeKind pnk, HandleValue left,
MOZ_CRASH("Unexpected ParseNodeKind: Must be `Or`, `And`, or `Coalesce`");
}
RootedValue cb(cx, callbacks[AST_LOGICAL_EXPR]);
if (!cb.isNull()) {
return callback(cb, opName, left, right, pos, dst);
}
return newNode(AST_LOGICAL_EXPR, pos, "operator", opName, "left", left,
"right", right, dst);
}
@ -1190,11 +966,6 @@ bool NodeBuilder::logicalExpression(ParseNodeKind pnk, HandleValue left,
bool NodeBuilder::conditionalExpression(HandleValue test, HandleValue cons,
HandleValue alt, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_COND_EXPR]);
if (!cb.isNull()) {
return callback(cb, test, cons, alt, pos, dst);
}
return newNode(AST_COND_EXPR, pos, "test", test, "consequent", cons,
"alternate", alt, dst);
}
@ -1212,11 +983,6 @@ bool NodeBuilder::callExpression(HandleValue callee, NodeVector& args,
return false;
}
RootedValue cb(cx, callbacks[AST_CALL_EXPR]);
if (!cb.isNull()) {
return callback(cb, callee, array, pos, dst);
}
return newNode(isOptional ? AST_OPT_CALL_EXPR : AST_CALL_EXPR, pos, "callee",
callee, "arguments", array, dst);
}
@ -1228,11 +994,6 @@ bool NodeBuilder::newExpression(HandleValue callee, NodeVector& args,
return false;
}
RootedValue cb(cx, callbacks[AST_NEW_EXPR]);
if (!cb.isNull()) {
return callback(cb, callee, array, pos, dst);
}
return newNode(AST_NEW_EXPR, pos, "callee", callee, "arguments", array, dst);
}
@ -1242,11 +1003,6 @@ bool NodeBuilder::memberExpression(bool computed, HandleValue expr,
bool isOptional /* = false */) {
RootedValue computedVal(cx, BooleanValue(computed));
RootedValue cb(cx, callbacks[AST_MEMBER_EXPR]);
if (!cb.isNull()) {
return callback(cb, computedVal, expr, member, pos, dst);
}
return newNode(isOptional ? AST_OPT_MEMBER_EXPR : AST_MEMBER_EXPR, pos,
"object", expr, "property", member, "computed", computedVal,
dst);
@ -1319,22 +1075,12 @@ bool NodeBuilder::propertyPattern(HandleValue key, HandleValue patt,
RootedValue isShorthandVal(cx, BooleanValue(isShorthand));
RootedValue cb(cx, callbacks[AST_PROP_PATT]);
if (!cb.isNull()) {
return callback(cb, key, patt, pos, dst);
}
return newNode(AST_PROP_PATT, pos, "key", key, "value", patt, "kind",
kindName, "shorthand", isShorthandVal, dst);
}
bool NodeBuilder::prototypeMutation(HandleValue val, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_PROTOTYPEMUTATION]);
if (!cb.isNull()) {
return callback(cb, val, pos, dst);
}
return newNode(AST_PROTOTYPEMUTATION, pos, "value", val, dst);
}
@ -1353,11 +1099,6 @@ bool NodeBuilder::propertyInitializer(HandleValue key, HandleValue val,
RootedValue isShorthandVal(cx, BooleanValue(isShorthand));
RootedValue isMethodVal(cx, BooleanValue(isMethod));
RootedValue cb(cx, callbacks[AST_PROPERTY]);
if (!cb.isNull()) {
return callback(cb, kindName, key, val, pos, dst);
}
return newNode(AST_PROPERTY, pos, "key", key, "value", val, "kind", kindName,
"method", isMethodVal, "shorthand", isShorthandVal, dst);
}
@ -1380,19 +1121,12 @@ bool NodeBuilder::tupleExpression(NodeVector& elts, TokenPos* pos,
#endif
bool NodeBuilder::thisExpression(TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_THIS_EXPR]);
if (!cb.isNull()) {
return callback(cb, pos, dst);
}
return newNode(AST_THIS_EXPR, pos, dst);
}
bool NodeBuilder::yieldExpression(HandleValue arg, YieldKind kind,
TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_YIELD_EXPR]);
RootedValue delegateVal(cx);
switch (kind) {
case Delegating:
delegateVal = BooleanValue(true);
@ -1401,10 +1135,6 @@ bool NodeBuilder::yieldExpression(HandleValue arg, YieldKind kind,
delegateVal = BooleanValue(false);
break;
}
if (!cb.isNull()) {
return callback(cb, opt(arg), delegateVal, pos, dst);
}
return newNode(AST_YIELD_EXPR, pos, "argument", arg, "delegate", delegateVal,
dst);
}
@ -1416,22 +1146,12 @@ bool NodeBuilder::moduleRequest(HandleValue moduleSpec, NodeVector& assertions,
return false;
}
RootedValue cb(cx, callbacks[AST_MODULE_REQUEST]);
if (!cb.isNull()) {
return callback(cb, array, moduleSpec, pos, dst);
}
return newNode(AST_MODULE_REQUEST, pos, "source", moduleSpec, "assertions",
array, dst);
}
bool NodeBuilder::importAssertion(HandleValue key, HandleValue value,
TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_IMPORT_ASSERTION]);
if (!cb.isNull()) {
return callback(cb, key, value, pos, dst);
}
return newNode(AST_IMPORT_ASSERTION, pos, "key", key, "value", value, dst);
}
@ -1442,11 +1162,6 @@ bool NodeBuilder::importDeclaration(NodeVector& elts, HandleValue moduleRequest,
return false;
}
RootedValue cb(cx, callbacks[AST_IMPORT_DECL]);
if (!cb.isNull()) {
return callback(cb, array, moduleRequest, pos, dst);
}
return newNode(AST_IMPORT_DECL, pos, "specifiers", array, "moduleRequest",
moduleRequest, dst);
}
@ -1454,11 +1169,6 @@ bool NodeBuilder::importDeclaration(NodeVector& elts, HandleValue moduleRequest,
bool NodeBuilder::importSpecifier(HandleValue importName,
HandleValue bindingName, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_IMPORT_SPEC]);
if (!cb.isNull()) {
return callback(cb, importName, bindingName, pos, dst);
}
return newNode(AST_IMPORT_SPEC, pos, "id", importName, "name", bindingName,
dst);
}
@ -1466,11 +1176,6 @@ bool NodeBuilder::importSpecifier(HandleValue importName,
bool NodeBuilder::importNamespaceSpecifier(HandleValue bindingName,
TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_IMPORT_NAMESPACE_SPEC]);
if (!cb.isNull()) {
return callback(cb, bindingName, pos, dst);
}
return newNode(AST_IMPORT_NAMESPACE_SPEC, pos, "name", bindingName, dst);
}
@ -1483,12 +1188,6 @@ bool NodeBuilder::exportDeclaration(HandleValue decl, NodeVector& elts,
return false;
}
RootedValue cb(cx, callbacks[AST_EXPORT_DECL]);
if (!cb.isNull()) {
return callback(cb, decl, array, moduleRequest, pos, dst);
}
return newNode(AST_EXPORT_DECL, pos, "declaration", decl, "specifiers", array,
"moduleRequest", moduleRequest, "isDefault", isDefault, dst);
}
@ -1496,11 +1195,6 @@ bool NodeBuilder::exportDeclaration(HandleValue decl, NodeVector& elts,
bool NodeBuilder::exportSpecifier(HandleValue bindingName,
HandleValue exportName, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_EXPORT_SPEC]);
if (!cb.isNull()) {
return callback(cb, bindingName, exportName, pos, dst);
}
return newNode(AST_EXPORT_SPEC, pos, "id", bindingName, "name", exportName,
dst);
}
@ -1508,20 +1202,10 @@ bool NodeBuilder::exportSpecifier(HandleValue bindingName,
bool NodeBuilder::exportNamespaceSpecifier(HandleValue exportName,
TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_EXPORT_NAMESPACE_SPEC]);
if (!cb.isNull()) {
return callback(cb, exportName, pos, dst);
}
return newNode(AST_EXPORT_NAMESPACE_SPEC, pos, "name", exportName, dst);
}
bool NodeBuilder::exportBatchSpecifier(TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_EXPORT_BATCH_SPEC]);
if (!cb.isNull()) {
return callback(cb, pos, dst);
}
return newNode(AST_EXPORT_BATCH_SPEC, pos, dst);
}
@ -1537,22 +1221,12 @@ bool NodeBuilder::variableDeclaration(NodeVector& elts, VarDeclKind kind,
return false;
}
RootedValue cb(cx, callbacks[AST_VAR_DECL]);
if (!cb.isNull()) {
return callback(cb, kindName, array, pos, dst);
}
return newNode(AST_VAR_DECL, pos, "kind", kindName, "declarations", array,
dst);
}
bool NodeBuilder::variableDeclarator(HandleValue id, HandleValue init,
TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_VAR_DTOR]);
if (!cb.isNull()) {
return callback(cb, id, opt(init), pos, dst);
}
return newNode(AST_VAR_DTOR, pos, "id", id, "init", init, dst);
}
@ -1563,41 +1237,21 @@ bool NodeBuilder::switchCase(HandleValue expr, NodeVector& elts, TokenPos* pos,
return false;
}
RootedValue cb(cx, callbacks[AST_CASE]);
if (!cb.isNull()) {
return callback(cb, opt(expr), array, pos, dst);
}
return newNode(AST_CASE, pos, "test", expr, "consequent", array, dst);
}
bool NodeBuilder::catchClause(HandleValue var, HandleValue body, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_CATCH]);
if (!cb.isNull()) {
return callback(cb, opt(var), body, pos, dst);
}
return newNode(AST_CATCH, pos, "param", var, "body", body, dst);
}
bool NodeBuilder::literal(HandleValue val, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_LITERAL]);
if (!cb.isNull()) {
return callback(cb, val, pos, dst);
}
return newNode(AST_LITERAL, pos, "value", val, dst);
}
bool NodeBuilder::identifier(HandleValue name, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_IDENTIFIER]);
if (!cb.isNull()) {
return callback(cb, name, pos, dst);
}
return newNode(AST_IDENTIFIER, pos, "name", name, dst);
}
@ -1629,12 +1283,6 @@ bool NodeBuilder::function(ASTType type, TokenPos* pos, HandleValue id,
RootedValue isAsyncVal(cx, BooleanValue(isAsync));
RootedValue isExpressionVal(cx, BooleanValue(isExpression));
RootedValue cb(cx, callbacks[type]);
if (!cb.isNull()) {
return callback(cb, opt(id), array, body, isGeneratorVal, isExpressionVal,
pos, dst);
}
if (isGenerator) {
MOZ_ASSERT(generatorStyle == GeneratorStyle::ES6);
JSAtom* styleStr = Atomize(cx, "es6", 3);
@ -1665,32 +1313,17 @@ bool NodeBuilder::classMethod(HandleValue name, HandleValue body, PropKind kind,
}
RootedValue isStaticVal(cx, BooleanValue(isStatic));
RootedValue cb(cx, callbacks[AST_CLASS_METHOD]);
if (!cb.isNull()) {
return callback(cb, kindName, name, body, isStaticVal, pos, dst);
}
return newNode(AST_CLASS_METHOD, pos, "name", name, "body", body, "kind",
kindName, "static", isStaticVal, dst);
}
bool NodeBuilder::classField(HandleValue name, HandleValue initializer,
TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_CLASS_FIELD]);
if (!cb.isNull()) {
return callback(cb, name, initializer, pos, dst);
}
return newNode(AST_CLASS_FIELD, pos, "name", name, "init", initializer, dst);
}
bool NodeBuilder::staticClassBlock(HandleValue body, TokenPos* pos,
MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_STATIC_CLASS_BLOCK]);
if (!cb.isNull()) {
return callback(cb, body, pos, dst);
}
return newNode(AST_STATIC_CLASS_BLOCK, pos, "body", body, dst);
}
@ -1702,22 +1335,12 @@ bool NodeBuilder::classDefinition(bool expr, HandleValue name,
HandleValue heritage, HandleValue block,
TokenPos* pos, MutableHandleValue dst) {
ASTType type = expr ? AST_CLASS_EXPR : AST_CLASS_STMT;
RootedValue cb(cx, callbacks[type]);
if (!cb.isNull()) {
return callback(cb, name, heritage, block, pos, dst);
}
return newNode(type, pos, "id", name, "superClass", heritage, "body", block,
dst);
}
bool NodeBuilder::metaProperty(HandleValue meta, HandleValue property,
TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_METAPROPERTY]);
if (!cb.isNull()) {
return callback(cb, meta, property, pos, dst);
}
return newNode(AST_METAPROPERTY, pos, "meta", meta, "property", property,
dst);
}
@ -1729,20 +1352,10 @@ bool NodeBuilder::callImportExpression(HandleValue ident, NodeVector& args,
return false;
}
RootedValue cb(cx, callbacks[AST_CALL_IMPORT]);
if (!cb.isNull()) {
return callback(cb, ident, array, pos, dst);
}
return newNode(AST_CALL_IMPORT, pos, "ident", ident, "arguments", array, dst);
}
bool NodeBuilder::super(TokenPos* pos, MutableHandleValue dst) {
RootedValue cb(cx, callbacks[AST_SUPER]);
if (!cb.isNull()) {
return callback(cb, pos, dst);
}
return newNode(AST_SUPER, pos, dst);
}
@ -1875,7 +1488,7 @@ class ASTSerializer {
{
}
bool init(HandleObject userobj) { return builder.init(userobj); }
bool init() { return builder.init(); }
void setParser(frontend::Parser<frontend::FullParseHandler, char16_t>* p) {
parser = p;
@ -3991,7 +3604,6 @@ static bool reflect_parse(JSContext* cx, uint32_t argc, Value* vp) {
UniqueChars filename;
uint32_t lineno = 1;
bool loc = true;
RootedObject builder(cx);
ParseGoal target = ParseGoal::Script;
RootedValue arg(cx, args.get(1));
@ -4045,22 +3657,6 @@ static bool reflect_parse(JSContext* cx, uint32_t argc, Value* vp) {
}
}
/* config.builder */
RootedId builderId(cx, NameToId(cx->names().builder));
RootedValue nullVal(cx, NullValue());
if (!GetPropertyDefault(cx, config, builderId, nullVal, &prop)) {
return false;
}
if (!prop.isNullOrUndefined()) {
if (!prop.isObject()) {
ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_SEARCH_STACK, prop,
nullptr, "not an object");
return false;
}
builder = &prop.toObject();
}
/* config.target */
RootedId targetId(cx, NameToId(cx->names().target));
RootedValue scriptVal(cx, StringValue(cx->names().script));
@ -4096,10 +3692,9 @@ static bool reflect_parse(JSContext* cx, uint32_t argc, Value* vp) {
}
}
/* Extract the builder methods first to report errors before parsing. */
AutoReportFrontendContext fc(cx);
ASTSerializer serialize(cx, &fc, loc, filename.get(), lineno);
if (!serialize.init(builder)) {
if (!serialize.init()) {
return false;
}

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

@ -6,90 +6,90 @@
/* AST_ERROR = -1 */
ASTDEF(AST_PROGRAM, "Program", "program")
ASTDEF(AST_PROGRAM, "Program")
ASTDEF(AST_IDENTIFIER, "Identifier", "identifier")
ASTDEF(AST_LITERAL, "Literal", "literal")
ASTDEF(AST_PROPERTY, "Property", "property")
ASTDEF(AST_PROTOTYPEMUTATION, "PrototypeMutation", "prototypeMutation")
ASTDEF(AST_IDENTIFIER, "Identifier")
ASTDEF(AST_LITERAL, "Literal")
ASTDEF(AST_PROPERTY, "Property")
ASTDEF(AST_PROTOTYPEMUTATION, "PrototypeMutation")
ASTDEF(AST_MODULE_DECL, "ModuleDeclaration", "moduleDeclaration")
ASTDEF(AST_FUNC_DECL, "FunctionDeclaration", "functionDeclaration")
ASTDEF(AST_VAR_DECL, "VariableDeclaration", "variableDeclaration")
ASTDEF(AST_VAR_DTOR, "VariableDeclarator", "variableDeclarator")
ASTDEF(AST_MODULE_DECL, "ModuleDeclaration")
ASTDEF(AST_FUNC_DECL, "FunctionDeclaration")
ASTDEF(AST_VAR_DECL, "VariableDeclaration")
ASTDEF(AST_VAR_DTOR, "VariableDeclarator")
ASTDEF(AST_LIST_EXPR, "SequenceExpression", "sequenceExpression")
ASTDEF(AST_COND_EXPR, "ConditionalExpression", "conditionalExpression")
ASTDEF(AST_UNARY_EXPR, "UnaryExpression", "unaryExpression")
ASTDEF(AST_BINARY_EXPR, "BinaryExpression", "binaryExpression")
ASTDEF(AST_ASSIGN_EXPR, "AssignmentExpression", "assignmentExpression")
ASTDEF(AST_LOGICAL_EXPR, "LogicalExpression", "logicalExpression")
ASTDEF(AST_UPDATE_EXPR, "UpdateExpression", "updateExpression")
ASTDEF(AST_NEW_EXPR, "NewExpression", "newExpression")
ASTDEF(AST_CALL_EXPR, "CallExpression", "callExpression")
ASTDEF(AST_OPT_CALL_EXPR, "OptionalCallExpression", "optionalCallExpression")
ASTDEF(AST_MEMBER_EXPR, "MemberExpression", "memberExpression")
ASTDEF(AST_OPT_MEMBER_EXPR, "OptionalMemberExpression", "optionalMemberExpression")
ASTDEF(AST_FUNC_EXPR, "FunctionExpression", "functionExpression")
ASTDEF(AST_ARROW_EXPR, "ArrowFunctionExpression", "arrowFunctionExpression")
ASTDEF(AST_ARRAY_EXPR, "ArrayExpression", "arrayExpression")
ASTDEF(AST_DELETE_OPTIONAL_EXPR, "DeleteOptionalExpression", "deleteOptionalExpression")
ASTDEF(AST_OPTIONAL_EXPR, "OptionalExpression", "optionalExpression")
ASTDEF(AST_SPREAD_EXPR, "SpreadExpression", "spreadExpression")
ASTDEF(AST_OBJECT_EXPR, "ObjectExpression", "objectExpression")
ASTDEF(AST_THIS_EXPR, "ThisExpression", "thisExpression")
ASTDEF(AST_YIELD_EXPR, "YieldExpression", "yieldExpression")
ASTDEF(AST_CLASS_EXPR, "ClassExpression", "classExpression")
ASTDEF(AST_METAPROPERTY, "MetaProperty", "metaProperty")
ASTDEF(AST_SUPER, "Super", "super")
ASTDEF(AST_CALL_IMPORT, "CallImport", "callImport")
ASTDEF(AST_LIST_EXPR, "SequenceExpression")
ASTDEF(AST_COND_EXPR, "ConditionalExpression")
ASTDEF(AST_UNARY_EXPR, "UnaryExpression")
ASTDEF(AST_BINARY_EXPR, "BinaryExpression")
ASTDEF(AST_ASSIGN_EXPR, "AssignmentExpression")
ASTDEF(AST_LOGICAL_EXPR, "LogicalExpression")
ASTDEF(AST_UPDATE_EXPR, "UpdateExpression")
ASTDEF(AST_NEW_EXPR, "NewExpression")
ASTDEF(AST_CALL_EXPR, "CallExpression")
ASTDEF(AST_OPT_CALL_EXPR, "OptionalCallExpression")
ASTDEF(AST_MEMBER_EXPR, "MemberExpression")
ASTDEF(AST_OPT_MEMBER_EXPR, "OptionalMemberExpression")
ASTDEF(AST_FUNC_EXPR, "FunctionExpression")
ASTDEF(AST_ARROW_EXPR, "ArrowFunctionExpression")
ASTDEF(AST_ARRAY_EXPR, "ArrayExpression")
ASTDEF(AST_DELETE_OPTIONAL_EXPR, "DeleteOptionalExpression")
ASTDEF(AST_OPTIONAL_EXPR, "OptionalExpression")
ASTDEF(AST_SPREAD_EXPR, "SpreadExpression")
ASTDEF(AST_OBJECT_EXPR, "ObjectExpression")
ASTDEF(AST_THIS_EXPR, "ThisExpression")
ASTDEF(AST_YIELD_EXPR, "YieldExpression")
ASTDEF(AST_CLASS_EXPR, "ClassExpression")
ASTDEF(AST_METAPROPERTY, "MetaProperty")
ASTDEF(AST_SUPER, "Super")
ASTDEF(AST_CALL_IMPORT, "CallImport")
#ifdef ENABLE_RECORD_TUPLE
ASTDEF(AST_RECORD_EXPR, "RecordExpression", "recordExpression")
ASTDEF(AST_TUPLE_EXPR, "TupleExpression", "tupleExpression")
ASTDEF(AST_RECORD_EXPR, "RecordExpression")
ASTDEF(AST_TUPLE_EXPR, "TupleExpression")
#endif
ASTDEF(AST_EMPTY_STMT, "EmptyStatement", "emptyStatement")
ASTDEF(AST_BLOCK_STMT, "BlockStatement", "blockStatement")
ASTDEF(AST_EXPR_STMT, "ExpressionStatement", "expressionStatement")
ASTDEF(AST_LAB_STMT, "LabeledStatement", "labeledStatement")
ASTDEF(AST_IF_STMT, "IfStatement", "ifStatement")
ASTDEF(AST_SWITCH_STMT, "SwitchStatement", "switchStatement")
ASTDEF(AST_WHILE_STMT, "WhileStatement", "whileStatement")
ASTDEF(AST_DO_STMT, "DoWhileStatement", "doWhileStatement")
ASTDEF(AST_FOR_STMT, "ForStatement", "forStatement")
ASTDEF(AST_FOR_IN_STMT, "ForInStatement", "forInStatement")
ASTDEF(AST_FOR_OF_STMT, "ForOfStatement", "forOfStatement")
ASTDEF(AST_BREAK_STMT, "BreakStatement", "breakStatement")
ASTDEF(AST_CONTINUE_STMT, "ContinueStatement", "continueStatement")
ASTDEF(AST_WITH_STMT, "WithStatement", "withStatement")
ASTDEF(AST_RETURN_STMT, "ReturnStatement", "returnStatement")
ASTDEF(AST_TRY_STMT, "TryStatement", "tryStatement")
ASTDEF(AST_THROW_STMT, "ThrowStatement", "throwStatement")
ASTDEF(AST_DEBUGGER_STMT, "DebuggerStatement", "debuggerStatement")
ASTDEF(AST_LET_STMT, "LetStatement", "letStatement")
ASTDEF(AST_MODULE_REQUEST, "ModuleRequest", "moduleRequest")
ASTDEF(AST_IMPORT_ASSERTION, "ImportAssertion", "importAssertion")
ASTDEF(AST_IMPORT_DECL, "ImportDeclaration", "importDeclaration")
ASTDEF(AST_IMPORT_SPEC, "ImportSpecifier", "importSpecifier")
ASTDEF(AST_IMPORT_NAMESPACE_SPEC, "ImportNamespaceSpecifier", "importNamespaceSpecifier")
ASTDEF(AST_EXPORT_DECL, "ExportDeclaration", "exportDeclaration")
ASTDEF(AST_EXPORT_SPEC, "ExportSpecifier", "exportSpecifier")
ASTDEF(AST_EXPORT_NAMESPACE_SPEC, "ExportNamespaceSpecifier", "exportNamespaceSpecifier")
ASTDEF(AST_EXPORT_BATCH_SPEC, "ExportBatchSpecifier", "exportBatchSpecifier")
ASTDEF(AST_EMPTY_STMT, "EmptyStatement")
ASTDEF(AST_BLOCK_STMT, "BlockStatement")
ASTDEF(AST_EXPR_STMT, "ExpressionStatement")
ASTDEF(AST_LAB_STMT, "LabeledStatement")
ASTDEF(AST_IF_STMT, "IfStatement")
ASTDEF(AST_SWITCH_STMT, "SwitchStatement")
ASTDEF(AST_WHILE_STMT, "WhileStatement")
ASTDEF(AST_DO_STMT, "DoWhileStatement")
ASTDEF(AST_FOR_STMT, "ForStatement")
ASTDEF(AST_FOR_IN_STMT, "ForInStatement")
ASTDEF(AST_FOR_OF_STMT, "ForOfStatement")
ASTDEF(AST_BREAK_STMT, "BreakStatement")
ASTDEF(AST_CONTINUE_STMT, "ContinueStatement")
ASTDEF(AST_WITH_STMT, "WithStatement")
ASTDEF(AST_RETURN_STMT, "ReturnStatement")
ASTDEF(AST_TRY_STMT, "TryStatement")
ASTDEF(AST_THROW_STMT, "ThrowStatement")
ASTDEF(AST_DEBUGGER_STMT, "DebuggerStatement")
ASTDEF(AST_LET_STMT, "LetStatement")
ASTDEF(AST_MODULE_REQUEST, "ModuleRequest")
ASTDEF(AST_IMPORT_ASSERTION, "ImportAssertion")
ASTDEF(AST_IMPORT_DECL, "ImportDeclaration")
ASTDEF(AST_IMPORT_SPEC, "ImportSpecifier")
ASTDEF(AST_IMPORT_NAMESPACE_SPEC, "ImportNamespaceSpecifier")
ASTDEF(AST_EXPORT_DECL, "ExportDeclaration")
ASTDEF(AST_EXPORT_SPEC, "ExportSpecifier")
ASTDEF(AST_EXPORT_NAMESPACE_SPEC, "ExportNamespaceSpecifier")
ASTDEF(AST_EXPORT_BATCH_SPEC, "ExportBatchSpecifier")
ASTDEF(AST_CASE, "SwitchCase", "switchCase")
ASTDEF(AST_CATCH, "CatchClause", "catchClause")
ASTDEF(AST_CASE, "SwitchCase")
ASTDEF(AST_CATCH, "CatchClause")
ASTDEF(AST_ARRAY_PATT, "ArrayPattern", "arrayPattern")
ASTDEF(AST_OBJECT_PATT, "ObjectPattern", "objectPattern")
ASTDEF(AST_PROP_PATT, "Property", "propertyPattern")
ASTDEF(AST_TEMPLATE_LITERAL, "TemplateLiteral", "templateLiteral")
ASTDEF(AST_TAGGED_TEMPLATE, "TaggedTemplate", "taggedTemplate")
ASTDEF(AST_CALL_SITE_OBJ, "CallSiteObject", "callSiteObject")
ASTDEF(AST_COMPUTED_NAME, "ComputedName", "computedName")
ASTDEF(AST_ARRAY_PATT, "ArrayPattern")
ASTDEF(AST_OBJECT_PATT, "ObjectPattern")
ASTDEF(AST_PROP_PATT, "Property")
ASTDEF(AST_TEMPLATE_LITERAL, "TemplateLiteral")
ASTDEF(AST_TAGGED_TEMPLATE, "TaggedTemplate")
ASTDEF(AST_CALL_SITE_OBJ, "CallSiteObject")
ASTDEF(AST_COMPUTED_NAME, "ComputedName")
ASTDEF(AST_CLASS_STMT, "ClassStatement", "classStatement")
ASTDEF(AST_CLASS_METHOD, "ClassMethod", "classMethod")
ASTDEF(AST_CLASS_FIELD, "ClassField", "classField")
ASTDEF(AST_STATIC_CLASS_BLOCK, "StaticClassBlock", "staticClassBlock")
ASTDEF(AST_CLASS_STMT, "ClassStatement")
ASTDEF(AST_CLASS_METHOD, "ClassMethod")
ASTDEF(AST_CLASS_FIELD, "ClassField")
ASTDEF(AST_STATIC_CLASS_BLOCK, "StaticClassBlock")
/* AST_LIMIT = last + 1 */

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

@ -1,215 +0,0 @@
// |reftest| skip-if(!xulRuntime.shell)
// A simple proof-of-concept that the builder API can be used to generate other
// formats, such as JsonMLAst:
//
// http://code.google.com/p/es-lab/wiki/JsonMLASTFormat
//
// It's incomplete (e.g., it doesn't convert source-location information and
// doesn't use all the direct-eval rules), but I think it proves the point.
function test() {
var JsonMLAst = (function() {
function reject() {
throw new SyntaxError("node type not supported");
}
function isDirectEval(expr) {
// an approximation to the actual rules. you get the idea
return (expr[0] === "IdExpr" && expr[1].name === "eval");
}
function functionNode(type) {
return function(id, args, body, isGenerator, isExpression) {
if (isExpression)
body = ["ReturnStmt", {}, body];
if (!id)
id = ["Empty"];
// Patch up the argument node types: s/IdExpr/IdPatt/g
for (var i = 0; i < args.length; i++) {
args[i][0] = "IdPatt";
}
args.unshift("ParamDecl", {});
return [type, {}, id, args, body];
}
}
return {
program: function(stmts) {
stmts.unshift("Program", {});
return stmts;
},
identifier: function(name) {
return ["IdExpr", { name: name }];
},
literal: function(val) {
return ["LiteralExpr", { value: val }];
},
expressionStatement: expr => expr,
conditionalExpression: function(test, cons, alt) {
return ["ConditionalExpr", {}, test, cons, alt];
},
unaryExpression: function(op, expr) {
return ["UnaryExpr", {op: op}, expr];
},
binaryExpression: function(op, left, right) {
return ["BinaryExpr", {op: op}, left, right];
},
property: function(kind, key, val) {
return [kind === "init"
? "DataProp"
: kind === "get"
? "GetterProp"
: "SetterProp",
{name: key[1].name}, val];
},
functionDeclaration: functionNode("FunctionDecl"),
variableDeclaration: function(kind, elts) {
if (kind === "let" || kind === "const")
throw new SyntaxError("let and const not supported");
elts.unshift("VarDecl", {});
return elts;
},
variableDeclarator: function(id, init) {
id[0] = "IdPatt";
if (!init)
return id;
return ["InitPatt", {}, id, init];
},
sequenceExpression: function(exprs) {
var length = exprs.length;
var result = ["BinaryExpr", {op:","}, exprs[exprs.length - 2], exprs[exprs.length - 1]];
for (var i = exprs.length - 3; i >= 0; i--) {
result = ["BinaryExpr", {op:","}, exprs[i], result];
}
return result;
},
assignmentExpression: function(op, lhs, expr) {
return ["AssignExpr", {op: op}, lhs, expr];
},
logicalExpression: function(op, left, right) {
return [op === "&&" ? "LogicalAndExpr" : "LogicalOrExpr", {}, left, right];
},
updateExpression: function(expr, op, isPrefix) {
return ["CountExpr", {isPrefix:isPrefix, op:op}, expr];
},
newExpression: function(callee, args) {
args.unshift("NewExpr", {}, callee);
return args;
},
callExpression: function(callee, args) {
args.unshift(isDirectEval(callee) ? "EvalExpr" : "CallExpr", {}, callee);
return args;
},
memberExpression: function(isComputed, expr, member) {
return ["MemberExpr", {}, expr, isComputed ? member : ["LiteralExpr", {type: "string", value: member[1].name}]];
},
functionExpression: functionNode("FunctionExpr"),
arrayExpression: function(elts) {
for (var i = 0; i < elts.length; i++) {
if (!elts[i])
elts[i] = ["Empty"];
}
elts.unshift("ArrayExpr", {});
return elts;
},
objectExpression: function(props) {
props.unshift("ObjectExpr", {});
return props;
},
thisExpression: function() {
return ["ThisExpr", {}];
},
templateLiteral: function(elts) {
for (var i = 0; i < elts.length; i++) {
if (!elts[i])
elts[i] = ["Empty"];
}
elts.unshift("TemplateLit", {});
return elts;
},
yieldExpression: reject,
emptyStatement: () => ["EmptyStmt", {}],
blockStatement: function(stmts) {
stmts.unshift("BlockStmt", {});
return stmts;
},
labeledStatement: function(lab, stmt) {
return ["LabelledStmt", {label: lab}, stmt];
},
ifStatement: function(test, cons, alt) {
return ["IfStmt", {}, test, cons, alt || ["EmptyStmt", {}]];
},
switchStatement: function(test, clauses, isLexical) {
clauses.unshift("SwitchStmt", {}, test);
return clauses;
},
whileStatement: function(expr, stmt) {
return ["WhileStmt", {}, expr, stmt];
},
doWhileStatement: function(stmt, expr) {
return ["DoWhileStmt", {}, stmt, expr];
},
forStatement: function(init, test, update, body) {
return ["ForStmt", {}, init || ["Empty"], test || ["Empty"], update || ["Empty"], body];
},
forInStatement: function(lhs, rhs, body) {
return ["ForInStmt", {}, lhs, rhs, body];
},
breakStatement: function(lab) {
return lab ? ["BreakStmt", {}, lab] : ["BreakStmt", {}];
},
continueStatement: function(lab) {
return lab ? ["ContinueStmt", {}, lab] : ["ContinueStmt", {}];
},
withStatement: function(expr, stmt) {
return ["WithStmt", {}, expr, stmt];
},
returnStatement: function(expr) {
return expr ? ["ReturnStmt", {}, expr] : ["ReturnStmt", {}];
},
tryStatement: function(body, handler, fin) {
var node = ["TryStmt", body, handler];
if (fin)
node.push(fin);
return node;
},
throwStatement: function(expr) {
return ["ThrowStmt", {}, expr];
},
debuggerStatement: () => ["DebuggerStmt", {}],
letStatement: reject,
switchCase: function(expr, stmts) {
if (expr)
stmts.unshift("SwitchCase", {}, expr);
else
stmts.unshift("DefaultCase", {});
return stmts;
},
catchClause: function(param, body) {
param[0] = "IdPatt";
return ["CatchClause", {}, param, body];
},
arrayPattern: reject,
objectPattern: reject,
propertyPattern: reject,
};
})();
Pattern(["Program", {},
["BinaryExpr", {op: "+"},
["LiteralExpr", {value: 2}],
["BinaryExpr", {op: "*"},
["UnaryExpr", {op: "-"}, ["IdExpr", {name: "x"}]],
["IdExpr", {name: "y"}]]]]).match(Reflect.parse("2 + (-x * y)", {loc: false, builder: JsonMLAst}));
}
runtest(test);

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

@ -1,54 +0,0 @@
// |reftest| skip-if(!xulRuntime.shell)
function test() {
// Builder tests
Pattern("program").match(Reflect.parse("42", {builder:{program:() => "program"}}));
assertGlobalStmt("throw 42", 1, { throwStatement: () => 1 });
assertGlobalStmt("for (;;);", 2, { forStatement: () => 2 });
assertGlobalStmt("for (x in y);", 3, { forInStatement: () => 3 });
assertGlobalStmt("{ }", 4, { blockStatement: () => 4 });
assertGlobalStmt("foo: { }", 5, { labeledStatement: () => 5 });
assertGlobalStmt("with (o) { }", 6, { withStatement: () => 6 });
assertGlobalStmt("while (x) { }", 7, { whileStatement: () => 7 });
assertGlobalStmt("do { } while(false);", 8, { doWhileStatement: () => 8 });
assertGlobalStmt("switch (x) { }", 9, { switchStatement: () => 9 });
assertGlobalStmt("try { } catch(e) { }", 10, { tryStatement: () => 10 });
assertGlobalStmt(";", 11, { emptyStatement: () => 11 });
assertGlobalStmt("debugger;", 12, { debuggerStatement: () => 12 });
assertGlobalStmt("42;", 13, { expressionStatement: () => 13 });
assertGlobalStmt("for (;;) break", forStmt(null, null, null, 14), { breakStatement: () => 14 });
assertGlobalStmt("for (;;) continue", forStmt(null, null, null, 15), { continueStatement: () => 15 });
assertBlockDecl("var x", "var", { variableDeclaration: kind => kind });
assertBlockDecl("let x", "let", { variableDeclaration: kind => kind });
assertBlockDecl("const x = undefined", "const", { variableDeclaration: kind => kind });
assertBlockDecl("function f() { }", "function", { functionDeclaration: () => "function" });
assertGlobalExpr("(x,y,z)", 1, { sequenceExpression: () => 1 });
assertGlobalExpr("(x ? y : z)", 2, { conditionalExpression: () => 2 });
assertGlobalExpr("x + y", 3, { binaryExpression: () => 3 });
assertGlobalExpr("delete x", 4, { unaryExpression: () => 4 });
assertGlobalExpr("x = y", 5, { assignmentExpression: () => 5 });
assertGlobalExpr("x || y", 6, { logicalExpression: () => 6 });
assertGlobalExpr("x++", 7, { updateExpression: () => 7 });
assertGlobalExpr("new x", 8, { newExpression: () => 8 });
assertGlobalExpr("x()", 9, { callExpression: () => 9 });
assertGlobalExpr("x.y", 10, { memberExpression: () => 10 });
assertGlobalExpr("(function() { })", 11, { functionExpression: () => 11 });
assertGlobalExpr("[1,2,3]", 12, { arrayExpression: () => 12 });
assertGlobalExpr("({ x: y })", 13, { objectExpression: () => 13 });
assertGlobalExpr("this", 14, { thisExpression: () => 14 });
assertGlobalExpr("(function*() { yield 42 })", genFunExpr("es6", null, [], blockStmt([exprStmt(19)])), { yieldExpression: () => 19 });
assertGlobalStmt("switch (x) { case y: }", switchStmt(ident("x"), [1]), { switchCase: () => 1 });
assertGlobalStmt("try { } catch (e) { }", 2, { tryStatement: (b, h, f) => h, catchClause: () => 2 });
assertGlobalStmt("try { } catch (e) { }", tryStmt(blockStmt([]), 2, null), { catchClause: () => 2 });
assertGlobalExpr("({ x: y } = z)", aExpr("=", 1, ident("z")), { objectPattern: () => 1 });
assertGlobalExpr("({ x: y } = z)", aExpr("=", objPatt([2]), ident("z")), { propertyPattern: () => 2 });
assertGlobalExpr("[ x ] = y", aExpr("=", 3, ident("y")), { arrayPattern: () => 3 });
}
runtest(test);

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

@ -1,15 +0,0 @@
// |reftest| skip-if(!xulRuntime.shell)
// Ensure that exceptions thrown by builder methods propagate.
var thrown = false;
try {
Reflect.parse("42", { builder: { program: function() { throw "expected" } } });
} catch (e) {
if (e !== "expected")
throw e;
thrown = true;
}
if (!thrown)
throw new Error("builder exception not propagated");
if (typeof reportCompare === 'function')
reportCompare(true, true);

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

@ -10,13 +10,4 @@ assertEq(Reflect.parse("0;", opts).loc !== null, true);
delete opts.loc;
assertEq(Reflect.parse("0;", opts).loc !== null, true); // default is true
// Proxy builder
var builder = {
program: function (body) { return body.join(); },
expressionStatement: function (expr) { return expr + ";" },
literal: function (val) { return "" + val; }
};
opts = {builder: new Proxy(builder, {})};
assertEq(Reflect.parse("0xff;", opts), "255;");
reportCompare(0, 0, 'ok');