Issue #1658 - Part 3: Implement support for optional chaining in JS reflection

Partially based on:
Bug 1610447 - Update Reflect to handle Optional Chaining operator
Bug 1657835 - Assertion failure: false, at js/src/builtin/ReflectParse.cpp:3168
This commit is contained in:
FranklinDM 2022-04-27 23:57:55 +08:00 • committed by roytam1
commit efabdc1885
2 changed files with 72 additions and 17 deletions

View file

@ -576,10 +576,11 @@ class NodeBuilder
MutableHandleValue dst); MutableHandleValue dst);
MOZ_MUST_USE bool callExpression(HandleValue callee, NodeVector& args, TokenPos* pos, MOZ_MUST_USE bool callExpression(HandleValue callee, NodeVector& args, TokenPos* pos,
MutableHandleValue dst); MutableHandleValue dst, bool isOptional = false);
MOZ_MUST_USE bool memberExpression(bool computed, HandleValue expr, HandleValue member, MOZ_MUST_USE bool memberExpression(bool computed, HandleValue expr, HandleValue member,
TokenPos* pos, MutableHandleValue dst); TokenPos* pos, MutableHandleValue dst,
bool isOptional = false);
MOZ_MUST_USE bool arrayExpression(NodeVector& elts, TokenPos* pos, MutableHandleValue dst); MOZ_MUST_USE bool arrayExpression(NodeVector& elts, TokenPos* pos, MutableHandleValue dst);
@ -593,6 +594,11 @@ class NodeBuilder
MOZ_MUST_USE bool spreadExpression(HandleValue expr, TokenPos* pos, MutableHandleValue dst); MOZ_MUST_USE bool spreadExpression(HandleValue expr, TokenPos* pos, MutableHandleValue dst);
MOZ_MUST_USE bool optionalExpression(HandleValue expr, TokenPos* pos, MutableHandleValue dst);
MOZ_MUST_USE bool deleteOptionalExpression(HandleValue expr, TokenPos* pos,
MutableHandleValue dst);
MOZ_MUST_USE bool computedName(HandleValue name, TokenPos* pos, MutableHandleValue dst); MOZ_MUST_USE bool computedName(HandleValue name, TokenPos* pos, MutableHandleValue dst);
MOZ_MUST_USE bool objectExpression(NodeVector& elts, TokenPos* pos, MutableHandleValue dst); MOZ_MUST_USE bool objectExpression(NodeVector& elts, TokenPos* pos, MutableHandleValue dst);
@ -1121,7 +1127,7 @@ NodeBuilder::sequenceExpression(NodeVector& elts, TokenPos* pos, MutableHandleVa
bool bool
NodeBuilder::callExpression(HandleValue callee, NodeVector& args, TokenPos* pos, NodeBuilder::callExpression(HandleValue callee, NodeVector& args, TokenPos* pos,
MutableHandleValue dst) MutableHandleValue dst, bool isOptional)
{ {
RootedValue array(cx); RootedValue array(cx);
if (!newArray(args, &array)) if (!newArray(args, &array))
@ -1131,9 +1137,12 @@ NodeBuilder::callExpression(HandleValue callee, NodeVector& args, TokenPos* pos,
if (!cb.isNull()) if (!cb.isNull())
return callback(cb, callee, array, pos, dst); return callback(cb, callee, array, pos, dst);
return newNode(AST_CALL_EXPR, pos, return newNode(isOptional ? AST_OPT_CALL_EXPR : AST_CALL_EXPR,
"callee", callee, pos,
"arguments", array, "callee",
callee,
"arguments",
array,
dst); dst);
} }
@ -1157,7 +1166,7 @@ NodeBuilder::newExpression(HandleValue callee, NodeVector& args, TokenPos* pos,
bool bool
NodeBuilder::memberExpression(bool computed, HandleValue expr, HandleValue member, TokenPos* pos, NodeBuilder::memberExpression(bool computed, HandleValue expr, HandleValue member, TokenPos* pos,
MutableHandleValue dst) MutableHandleValue dst, bool isOptional)
{ {
RootedValue computedVal(cx, BooleanValue(computed)); RootedValue computedVal(cx, BooleanValue(computed));
@ -1165,10 +1174,14 @@ NodeBuilder::memberExpression(bool computed, HandleValue expr, HandleValue membe
if (!cb.isNull()) if (!cb.isNull())
return callback(cb, computedVal, expr, member, pos, dst); return callback(cb, computedVal, expr, member, pos, dst);
return newNode(AST_MEMBER_EXPR, pos, return newNode(isOptional ? AST_OPT_MEMBER_EXPR : AST_MEMBER_EXPR,
"object", expr, pos,
"property", member, "object",
"computed", computedVal, expr,
"property",
member,
"computed",
computedVal,
dst); dst);
} }
@ -1231,6 +1244,22 @@ NodeBuilder::spreadExpression(HandleValue expr, TokenPos* pos, MutableHandleValu
dst); dst);
} }
bool
NodeBuilder::optionalExpression(HandleValue expr, TokenPos* pos, MutableHandleValue dst)
{
return newNode(AST_OPTIONAL_EXPR, pos,
"expression", expr,
dst);
}
bool
NodeBuilder::deleteOptionalExpression(HandleValue expr, TokenPos* pos, MutableHandleValue dst)
{
return newNode(AST_DELETE_OPTIONAL_EXPR, pos,
"expression", expr,
dst);
}
bool bool
NodeBuilder::propertyPattern(HandleValue key, HandleValue patt, bool isShorthand, TokenPos* pos, NodeBuilder::propertyPattern(HandleValue key, HandleValue patt, bool isShorthand, TokenPos* pos,
MutableHandleValue dst) MutableHandleValue dst)
@ -2950,9 +2979,22 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_GENEXP: case PNK_GENEXP:
return generatorExpression(pn->generatorExpr(), dst); return generatorExpression(pn->generatorExpr(), dst);
case PNK_DELETEOPTCHAIN: {
RootedValue expr(cx);
return expression(pn->pn_kid, &expr) &&
builder.deleteOptionalExpression(expr, &pn->pn_pos, dst);
}
case PNK_OPTCHAIN: {
RootedValue expr(cx);
return expression(pn->pn_kid, &expr) &&
builder.optionalExpression(expr, &pn->pn_pos, dst);
}
case PNK_NEW: case PNK_NEW:
case PNK_TAGGED_TEMPLATE: case PNK_TAGGED_TEMPLATE:
case PNK_CALL: case PNK_CALL:
case PNK_OPTCALL:
case PNK_SUPERCALL: case PNK_SUPERCALL:
{ {
ParseNode* next = pn->pn_head; ParseNode* next = pn->pn_head;
@ -2984,13 +3026,15 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
if (pn->getKind() == PNK_TAGGED_TEMPLATE) if (pn->getKind() == PNK_TAGGED_TEMPLATE)
return builder.taggedTemplate(callee, args, &pn->pn_pos, dst); return builder.taggedTemplate(callee, args, &pn->pn_pos, dst);
bool isOptional = pn->isKind(PNK_OPTCALL);
// SUPERCALL is Call(super, args) // SUPERCALL is Call(super, args)
return pn->isKind(PNK_NEW) return pn->isKind(PNK_NEW)
? builder.newExpression(callee, args, &pn->pn_pos, dst) ? builder.newExpression(callee, args, &pn->pn_pos, dst)
: builder.callExpression(callee, args, &pn->pn_pos, dst, isOptional);
: builder.callExpression(callee, args, &pn->pn_pos, dst);
} }
case PNK_OPTDOT:
case PNK_DOT: case PNK_DOT:
{ {
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos)); MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos));
@ -2999,7 +3043,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
RootedValue propname(cx); RootedValue propname(cx);
RootedAtom pnAtom(cx, pn->pn_atom); RootedAtom pnAtom(cx, pn->pn_atom);
if (pn->as<PropertyAccess>().isSuper()) { if (pn->as<PropertyAccessBase>().isSuper()) {
if (!builder.super(&pn->pn_expr->pn_pos, &expr)) if (!builder.super(&pn->pn_expr->pn_pos, &expr))
return false; return false;
} else { } else {
@ -3007,10 +3051,14 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
return false; return false;
} }
bool isOptional = pn->isKind(PNK_OPTDOT);
return identifier(pnAtom, nullptr, &propname) && return identifier(pnAtom, nullptr, &propname) &&
builder.memberExpression(false, expr, propname, &pn->pn_pos, dst); builder.memberExpression(false, expr, propname, &pn->pn_pos,
dst, isOptional);
} }
case PNK_OPTELEM:
case PNK_ELEM: case PNK_ELEM:
{ {
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
@ -3018,7 +3066,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
RootedValue left(cx), right(cx); RootedValue left(cx), right(cx);
if (pn->as<PropertyByValue>().isSuper()) { if (pn->as<PropertyByValueBase>().isSuper()) {
if (!builder.super(&pn->pn_left->pn_pos, &left)) if (!builder.super(&pn->pn_left->pn_pos, &left))
return false; return false;
} else { } else {
@ -3026,8 +3074,11 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
return false; return false;
} }
bool isOptional = pn->isKind(PNK_OPTELEM);
return expression(pn->pn_right, &right) && return expression(pn->pn_right, &right) &&
builder.memberExpression(true, left, right, &pn->pn_pos, dst); builder.memberExpression(true, left, right, &pn->pn_pos, dst,
isOptional);
} }
case PNK_CALLSITEOBJ: case PNK_CALLSITEOBJ:

View file

@ -27,10 +27,14 @@ ASTDEF(AST_LOGICAL_EXPR, "LogicalExpression", "logicalExpr
ASTDEF(AST_UPDATE_EXPR, "UpdateExpression", "updateExpression") ASTDEF(AST_UPDATE_EXPR, "UpdateExpression", "updateExpression")
ASTDEF(AST_NEW_EXPR, "NewExpression", "newExpression") ASTDEF(AST_NEW_EXPR, "NewExpression", "newExpression")
ASTDEF(AST_CALL_EXPR, "CallExpression", "callExpression") ASTDEF(AST_CALL_EXPR, "CallExpression", "callExpression")
ASTDEF(AST_OPT_CALL_EXPR, "OptionalCallExpression", "optionalCallExpression")
ASTDEF(AST_MEMBER_EXPR, "MemberExpression", "memberExpression") ASTDEF(AST_MEMBER_EXPR, "MemberExpression", "memberExpression")
ASTDEF(AST_OPT_MEMBER_EXPR, "OptionalMemberExpression", "optionalMemberExpression")
ASTDEF(AST_FUNC_EXPR, "FunctionExpression", "functionExpression") ASTDEF(AST_FUNC_EXPR, "FunctionExpression", "functionExpression")
ASTDEF(AST_ARROW_EXPR, "ArrowFunctionExpression", "arrowFunctionExpression") ASTDEF(AST_ARROW_EXPR, "ArrowFunctionExpression", "arrowFunctionExpression")
ASTDEF(AST_ARRAY_EXPR, "ArrayExpression", "arrayExpression") 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_SPREAD_EXPR, "SpreadExpression", "spreadExpression")
ASTDEF(AST_OBJECT_EXPR, "ObjectExpression", "objectExpression") ASTDEF(AST_OBJECT_EXPR, "ObjectExpression", "objectExpression")
ASTDEF(AST_THIS_EXPR, "ThisExpression", "thisExpression") ASTDEF(AST_THIS_EXPR, "ThisExpression", "thisExpression")