mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 07:18:39 +09:00
Issue #2173 - Add a new PNK_ARGUMENTS node type for call argument lists
Also change PNK_GENEXP (not supported by upstream) to a PN_BINARY node Based-on: m-c 1378808/1
This commit is contained in:
parent
0b2e8c4818
commit
924140d400
12 changed files with 249 additions and 163 deletions
|
|
@ -3025,24 +3025,25 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
case PNK_OPTCALL:
|
||||
case PNK_SUPERCALL:
|
||||
{
|
||||
ParseNode* next = pn->pn_head;
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
ParseNode* pn_callee = pn->pn_left;
|
||||
ParseNode* pn_args = pn->pn_right;
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn_callee->pn_pos));
|
||||
|
||||
RootedValue callee(cx);
|
||||
if (pn->isKind(PNK_SUPERCALL)) {
|
||||
MOZ_ASSERT(next->isKind(PNK_SUPERBASE));
|
||||
if (!builder.super(&next->pn_pos, &callee))
|
||||
MOZ_ASSERT(pn_callee->isKind(PNK_SUPERBASE));
|
||||
if (!builder.super(&pn_callee->pn_pos, &callee))
|
||||
return false;
|
||||
} else {
|
||||
if (!expression(next, &callee))
|
||||
if (!expression(pn_callee, &callee))
|
||||
return false;
|
||||
}
|
||||
|
||||
NodeVector args(cx);
|
||||
if (!args.reserve(pn->pn_count - 1))
|
||||
if (!args.reserve(pn_args->pn_count))
|
||||
return false;
|
||||
|
||||
for (next = next->pn_next; next; next = next->pn_next) {
|
||||
for (ParseNode* next = pn_args->pn_head; next; next = next->pn_next) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
|
||||
RootedValue arg(cx);
|
||||
|
|
|
|||
|
|
@ -74,20 +74,6 @@ ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn)
|
|||
return pn->getKind() == PNK_WHILE || pn->getKind() == PNK_FOR;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetCallArgsAndCount(ParseNode* callNode, ParseNode** argumentNode)
|
||||
{
|
||||
// XXX This helper function exists to make ports less error-prone.
|
||||
// The current parse tree splits the information between callNode and callee.
|
||||
// A later refactor has a ListNode instead, with slightly different storage.
|
||||
// (See also the "what is stored where" table in ParseNode.h)
|
||||
ParseNode* calleeNode = callNode->pn_head;
|
||||
if (argumentNode && calleeNode) {
|
||||
*argumentNode = calleeNode->pn_next;
|
||||
}
|
||||
return callNode->pn_count - 1;
|
||||
}
|
||||
|
||||
// Class for emitting bytecode for optional expressions.
|
||||
class MOZ_RAII OptionalEmitter
|
||||
{
|
||||
|
|
@ -1353,13 +1339,18 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
case PNK_OPTCALL:
|
||||
case PNK_TAGGED_TEMPLATE:
|
||||
case PNK_SUPERCALL:
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
*answer = true;
|
||||
return true;
|
||||
|
||||
// Function arg lists can contain arbitrary expressions. Technically
|
||||
// this only causes side-effects if one of the arguments does, but since
|
||||
// the call being made will always trigger side-effects, it isn't needed.
|
||||
// the call being made will always trigger side-effects, it isn't needed.
|
||||
case PNK_ARGUMENTS:
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
*answer = true;
|
||||
return true;
|
||||
|
||||
case PNK_OPTCHAIN:
|
||||
MOZ_ASSERT(pn->isArity(PN_UNARY));
|
||||
*answer = true;
|
||||
|
|
@ -1417,7 +1408,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
|
||||
// Generator expressions have no side effects on their own.
|
||||
case PNK_GENEXP:
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
*answer = false;
|
||||
return true;
|
||||
|
||||
|
|
@ -4809,7 +4800,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
|
|||
bool allowSelfHostedIter = false;
|
||||
if (emitterMode == BytecodeEmitter::SelfHosting &&
|
||||
forHeadExpr->isKind(PNK_CALL) &&
|
||||
forHeadExpr->pn_head->name() == cx->names().allowContentIter)
|
||||
forHeadExpr->pn_left->name() == cx->names().allowContentIter)
|
||||
{
|
||||
allowSelfHostedIter = true;
|
||||
}
|
||||
|
|
@ -6989,10 +6980,12 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
|
|||
//
|
||||
// argc is set to the amount of actually emitted args and the
|
||||
// emitting of args below is disabled by setting emitArgs to false.
|
||||
ParseNode* pn2 = pn->pn_head;
|
||||
const char* errorName = SelfHostedCallFunctionName(pn2->name(), cx);
|
||||
ParseNode* pn_callee = pn->pn_left;
|
||||
ParseNode* pn_args = pn->pn_right;
|
||||
|
||||
if (pn->pn_count < 3) {
|
||||
const char* errorName = SelfHostedCallFunctionName(pn_callee->name(), cx);
|
||||
|
||||
if (pn_args->pn_count < 2) {
|
||||
reportError(pn, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -7003,8 +6996,8 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool constructing = pn2->name() == cx->names().constructContentFunction;
|
||||
ParseNode* funNode = pn2->pn_next;
|
||||
bool constructing = pn_callee->name() == cx->names().constructContentFunction;
|
||||
ParseNode* funNode = pn_args->pn_head;
|
||||
if (constructing)
|
||||
callOp = JSOP_NEW;
|
||||
else if (funNode->getKind() == PNK_NAME && funNode->name() == cx->names().std_Function_apply)
|
||||
|
|
@ -7015,7 +7008,7 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
|
|||
|
||||
#ifdef DEBUG
|
||||
if (emitterMode == BytecodeEmitter::SelfHosting &&
|
||||
pn2->name() == cx->names().callFunction)
|
||||
pn_callee->name() == cx->names().callFunction)
|
||||
{
|
||||
if (!emit1(JSOP_DEBUGCHECKSELFHOSTED))
|
||||
return false;
|
||||
|
|
@ -7044,7 +7037,7 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t argc = pn->pn_count - 3;
|
||||
uint32_t argc = pn_args->pn_count - 2;
|
||||
if (!emitCall(callOp, argc))
|
||||
return false;
|
||||
|
||||
|
|
@ -7055,15 +7048,15 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
|
|||
bool
|
||||
BytecodeEmitter::emitSelfHostedResumeGenerator(ParseNode* pn)
|
||||
{
|
||||
ParseNode* pn_args = pn->pn_right;
|
||||
|
||||
// Syntax: resumeGenerator(gen, value, 'next'|'throw'|'close')
|
||||
if (pn->pn_count != 4) {
|
||||
if (pn_args->pn_count != 3) {
|
||||
reportError(pn, JSMSG_MORE_ARGS_NEEDED, "resumeGenerator", "1", "s");
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode* funNode = pn->pn_head; // The resumeGenerator node.
|
||||
|
||||
ParseNode* genNode = funNode->pn_next;
|
||||
ParseNode* genNode = pn_args->pn_head;
|
||||
if (!emitTree(genNode))
|
||||
return false;
|
||||
|
||||
|
|
@ -7095,13 +7088,15 @@ BytecodeEmitter::emitSelfHostedForceInterpreter(ParseNode* pn)
|
|||
bool
|
||||
BytecodeEmitter::emitSelfHostedAllowContentIter(ParseNode* pn)
|
||||
{
|
||||
if (pn->pn_count != 2) {
|
||||
ParseNode* pn_args = pn->pn_right;
|
||||
|
||||
if (pn_args->pn_count != 1) {
|
||||
reportError(pn, JSMSG_MORE_ARGS_NEEDED, "allowContentIter", "1", "");
|
||||
return false;
|
||||
}
|
||||
|
||||
// We're just here as a sentinel. Pass the value through directly.
|
||||
return emitTree(pn->pn_head->pn_next);
|
||||
return emitTree(pn_args->pn_head);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -7117,9 +7112,10 @@ BytecodeEmitter::isRestParameter(ParseNode* pn)
|
|||
|
||||
if (!pn->isKind(PNK_NAME)) {
|
||||
if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(PNK_CALL)) {
|
||||
ParseNode* pn2 = pn->pn_head;
|
||||
if (pn2->getKind() == PNK_NAME && pn2->name() == cx->names().allowContentIter)
|
||||
return isRestParameter(pn2->pn_next);
|
||||
ParseNode* pn_callee = pn->pn_left;
|
||||
if (pn_callee->getKind() == PNK_NAME &&
|
||||
pn_callee->name() == cx->names().allowContentIter)
|
||||
return isRestParameter(pn->pn_right->pn_head);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -7289,16 +7285,16 @@ BytecodeEmitter::emitOptionalCall(
|
|||
OptionalEmitter& oe,
|
||||
ValueUsage valueUsage)
|
||||
{
|
||||
ParseNode* calleeNode = callNode->pn_head;
|
||||
ParseNode* calleeNode = callNode->pn_left;
|
||||
ParseNode* argsList = callNode->pn_right;
|
||||
bool isCall = true;
|
||||
bool isSpread = IsSpreadOp(callNode->getOp());
|
||||
ParseNode* firstArg = nullptr;
|
||||
uint32_t argc = GetCallArgsAndCount(callNode, &firstArg);
|
||||
uint32_t argc = argsList->pn_count;
|
||||
JSOp op = callNode->getOp();
|
||||
|
||||
CallOrNewEmitter cone(this, op,
|
||||
isSpread && (argc == 1) &&
|
||||
isRestParameter(firstArg->pn_kid)
|
||||
isRestParameter(argsList->pn_head->pn_kid)
|
||||
? CallOrNewEmitter::ArgumentsKind::SingleSpreadRest
|
||||
: CallOrNewEmitter::ArgumentsKind::Other,
|
||||
valueUsage);
|
||||
|
|
@ -7315,12 +7311,12 @@ BytecodeEmitter::emitOptionalCall(
|
|||
}
|
||||
}
|
||||
|
||||
if (!emitArguments(firstArg, argc, /* isCall = */ true, isSpread, cone)) {
|
||||
if (!emitArguments(argsList, /* isCall = */ true, isSpread, cone)) {
|
||||
// [stack] CALLEE THIS ARGS...
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode* coordNode = getCoordNode(callNode, calleeNode, firstArg);
|
||||
ParseNode* coordNode = getCoordNode(callNode, calleeNode, argsList);
|
||||
if (!cone.emitEnd(argc, Some(coordNode->pn_pos.begin))) {
|
||||
// [stack] RVAL
|
||||
return false;
|
||||
|
|
@ -7331,17 +7327,14 @@ BytecodeEmitter::emitOptionalCall(
|
|||
|
||||
ParseNode* BytecodeEmitter::getCoordNode(ParseNode* pn,
|
||||
ParseNode* calleeNode,
|
||||
ParseNode* firstArg) {
|
||||
ParseNode* argsList) {
|
||||
ParseNode* coordNode = pn;
|
||||
if (pn->isOp(JSOP_CALL) || pn->isOp(JSOP_SPREADCALL) || pn->isOp(JSOP_FUNCALL) ||
|
||||
pn->isOp(JSOP_FUNAPPLY)) {
|
||||
// Default to using the location of the `(` itself.
|
||||
// obj[expr]() // expression
|
||||
// ^ // column coord
|
||||
if (firstArg) {
|
||||
// XXX In our version, firstArg points to the first argument and may be null if there are none
|
||||
coordNode = firstArg;
|
||||
}
|
||||
coordNode = argsList;
|
||||
|
||||
switch (calleeNode->getKind()) {
|
||||
case PNK_DOT:
|
||||
|
|
@ -7369,9 +7362,11 @@ ParseNode* BytecodeEmitter::getCoordNode(ParseNode* pn,
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitArguments(ParseNode* firstArgNode, uint32_t argc, bool isCall, bool isSpread,
|
||||
BytecodeEmitter::emitArguments(ParseNode* pn, bool isCall, bool isSpread,
|
||||
CallOrNewEmitter& cone)
|
||||
{
|
||||
uint32_t argc = pn->pn_count;
|
||||
|
||||
if (argc >= ARGC_LIMIT) {
|
||||
parser->tokenStream.reportError(isCall
|
||||
? JSMSG_TOO_MANY_FUN_ARGS
|
||||
|
|
@ -7382,21 +7377,21 @@ BytecodeEmitter::emitArguments(ParseNode* firstArgNode, uint32_t argc, bool isCa
|
|||
if (!cone.prepareForNonSpreadArguments()) { // CALLEE THIS
|
||||
return false;
|
||||
}
|
||||
for (ParseNode* arg = firstArgNode; arg; arg = arg->pn_next) {
|
||||
for (ParseNode* arg = pn->pn_head; arg; arg = arg->pn_next) {
|
||||
if (!emitTree(arg)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (cone.wantSpreadOperand()) {
|
||||
if (!emitTree(firstArgNode->pn_kid)) { // CALLEE THIS ARG0
|
||||
if (!emitTree(pn->pn_head->pn_kid)) { // CALLEE THIS ARG0
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!cone.emitSpreadArgumentsTest()) { // CALLEE THIS
|
||||
return false;
|
||||
}
|
||||
if (!emitArray(firstArgNode, argc, JSOP_SPREADCALLARRAY)) { // CALLEE THIS ARR
|
||||
if (!emitArray(pn->pn_head, argc, JSOP_SPREADCALLARRAY)) { // CALLEE THIS ARR
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -7424,11 +7419,11 @@ BytecodeEmitter::emitCallOrNew(
|
|||
* value required for calls (which non-strict mode functions
|
||||
* will box into the global object).
|
||||
*/
|
||||
ParseNode* calleeNode = callNode->pn_head;
|
||||
bool isCall = callNode->isKind(PNK_CALL) || callNode->isKind(PNK_TAGGED_TEMPLATE);
|
||||
ParseNode* calleeNode = callNode->pn_left;
|
||||
ParseNode* argsList = callNode->pn_right;
|
||||
|
||||
bool isSpread = IsSpreadOp(callNode->getOp());
|
||||
ParseNode* firstArg = nullptr;
|
||||
uint32_t argc = GetCallArgsAndCount(callNode, &firstArg);
|
||||
|
||||
if (calleeNode->isKind(PNK_NAME) &&
|
||||
emitterMode == BytecodeEmitter::SelfHosting &&
|
||||
|
|
@ -7452,21 +7447,22 @@ BytecodeEmitter::emitCallOrNew(
|
|||
// Fall through.
|
||||
}
|
||||
|
||||
uint32_t argc = argsList->pn_count;
|
||||
JSOp op = callNode->getOp();
|
||||
CallOrNewEmitter cone(this, op,
|
||||
isSpread && (argc == 1) &&
|
||||
isRestParameter(firstArg->pn_kid)
|
||||
isRestParameter(argsList->pn_head->pn_kid)
|
||||
? CallOrNewEmitter::ArgumentsKind::SingleSpreadRest
|
||||
: CallOrNewEmitter::ArgumentsKind::Other,
|
||||
valueUsage);
|
||||
if (!emitCalleeAndThis(callNode, calleeNode, cone)) { // CALLEE THIS
|
||||
return false;
|
||||
}
|
||||
if (!emitArguments(firstArg, argc, isCall, isSpread, cone)) {
|
||||
if (!emitArguments(argsList, isCall, isSpread, cone)) {
|
||||
return false; // CALLEE THIS ARGS...
|
||||
}
|
||||
|
||||
ParseNode* coordNode = getCoordNode(callNode, calleeNode, firstArg);
|
||||
ParseNode* coordNode = getCoordNode(callNode, calleeNode, argsList);
|
||||
|
||||
if (!cone.emitEnd(argc, Some(coordNode->pn_pos.begin))) {
|
||||
return false; // RVAL
|
||||
|
|
@ -8091,7 +8087,7 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
|
|||
|
||||
if (emitterMode == BytecodeEmitter::SelfHosting &&
|
||||
expr->isKind(PNK_CALL) &&
|
||||
expr->pn_head->name() == cx->names().allowContentIter)
|
||||
expr->pn_left->name() == cx->names().allowContentIter)
|
||||
{
|
||||
allowSelfHostedIter = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -751,8 +751,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
|
||||
MOZ_MUST_USE ParseNode* getCoordNode(ParseNode* callNode, ParseNode* calleeNode,
|
||||
ParseNode* firstArgNode);
|
||||
MOZ_MUST_USE bool emitArguments(ParseNode* firstArgNode, uint32_t argc,
|
||||
bool isCall, bool isSpread,
|
||||
MOZ_MUST_USE bool emitArguments(ParseNode* argsList, bool isCall, bool isSpread,
|
||||
CallOrNewEmitter& cone);
|
||||
MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn,
|
||||
ValueUsage valueUsage = ValueUsage::WantValue);
|
||||
|
|
|
|||
|
|
@ -369,6 +369,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
case PNK_OBJECT:
|
||||
case PNK_DOT:
|
||||
case PNK_ELEM:
|
||||
case PNK_ARGUMENTS:
|
||||
case PNK_CALL:
|
||||
case PNK_OPTCHAIN:
|
||||
case PNK_OPTDOT:
|
||||
|
|
@ -1549,8 +1550,9 @@ FoldCall(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser
|
|||
MOZ_ASSERT(node->isKind(PNK_CALL) ||
|
||||
node->isKind(PNK_OPTCALL) ||
|
||||
node->isKind(PNK_SUPERCALL) ||
|
||||
node->isKind(PNK_NEW) ||
|
||||
node->isKind(PNK_TAGGED_TEMPLATE));
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
MOZ_ASSERT(node->isArity(PN_BINARY));
|
||||
|
||||
// Don't fold a parenthesized callable component in an invocation, as this
|
||||
// might cause a different |this| value to be used, changing semantics:
|
||||
|
|
@ -1563,9 +1565,27 @@ FoldCall(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser
|
|||
// assertEq(obj.f``, "obj");
|
||||
//
|
||||
// See bug 537673 and bug 1182373.
|
||||
ParseNode** pn_callee = &node->pn_left;
|
||||
if (node->isKind(PNK_NEW) || !(*pn_callee)->isInParens()) {
|
||||
if (!Fold(cx, pn_callee, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode** pn_args = &node->pn_right;
|
||||
if (!Fold(cx, pn_args, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
FoldArguments(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_ARGUMENTS));
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
|
||||
ParseNode** listp = &node->pn_head;
|
||||
if ((*listp)->isInParens())
|
||||
listp = &(*listp)->pn_next;
|
||||
|
||||
for (; *listp; listp = &(*listp)->pn_next) {
|
||||
if (!Fold(cx, listp, parser, inGenexpLambda))
|
||||
|
|
@ -1739,6 +1759,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
return Fold(cx, &pn->pn_kid, parser, inGenexpLambda);
|
||||
|
||||
case PNK_EXPORT_DEFAULT:
|
||||
case PNK_GENEXP:
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
return Fold(cx, &pn->pn_left, parser, inGenexpLambda);
|
||||
|
||||
|
|
@ -1790,7 +1811,6 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
case PNK_INSTANCEOF:
|
||||
case PNK_IN:
|
||||
case PNK_COMMA:
|
||||
case PNK_NEW:
|
||||
case PNK_ARRAY:
|
||||
case PNK_OBJECT:
|
||||
case PNK_ARRAYCOMP:
|
||||
|
|
@ -1805,7 +1825,6 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
case PNK_CALLSITEOBJ:
|
||||
case PNK_EXPORT_SPEC_LIST:
|
||||
case PNK_IMPORT_SPEC_LIST:
|
||||
case PNK_GENEXP:
|
||||
return FoldList(cx, pn, parser, inGenexpLambda);
|
||||
|
||||
case PNK_INITIALYIELD:
|
||||
|
|
@ -1847,10 +1866,14 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
|
||||
case PNK_CALL:
|
||||
case PNK_OPTCALL:
|
||||
case PNK_NEW:
|
||||
case PNK_SUPERCALL:
|
||||
case PNK_TAGGED_TEMPLATE:
|
||||
return FoldCall(cx, pn, parser, inGenexpLambda);
|
||||
|
||||
case PNK_ARGUMENTS:
|
||||
return FoldArguments(cx, pn, parser, inGenexpLambda);
|
||||
|
||||
case PNK_SWITCH:
|
||||
case PNK_COLON:
|
||||
case PNK_ASSIGN:
|
||||
|
|
|
|||
|
|
@ -331,16 +331,28 @@ class FullParseHandler
|
|||
literal->append(element);
|
||||
}
|
||||
|
||||
ParseNode* newCall() {
|
||||
return newList(PNK_CALL, JSOP_CALL);
|
||||
ParseNode* newCall(ParseNode* callee, ParseNode* args) {
|
||||
return new_<BinaryNode>(PNK_CALL, JSOP_CALL, callee, args);
|
||||
}
|
||||
|
||||
ParseNode* newOptionalCall() {
|
||||
return newList(PNK_OPTCALL, JSOP_CALL);
|
||||
ParseNode* newOptionalCall(ParseNode* callee, ParseNode* args) {
|
||||
return new_<BinaryNode>(PNK_OPTCALL, JSOP_CALL, callee, args);
|
||||
}
|
||||
|
||||
ParseNode* newTaggedTemplate() {
|
||||
return newList(PNK_TAGGED_TEMPLATE, JSOP_CALL);
|
||||
ParseNode* newArguments(const TokenPos& pos) {
|
||||
return new_<ListNode>(PNK_ARGUMENTS, JSOP_NOP, pos);
|
||||
}
|
||||
|
||||
ParseNode* newSuperCall(ParseNode* callee, ParseNode* args) {
|
||||
return new_<BinaryNode>(PNK_SUPERCALL, JSOP_SUPERCALL, callee, args);
|
||||
}
|
||||
|
||||
ParseNode* newTaggedTemplate(ParseNode* tag, ParseNode* args) {
|
||||
return new_<BinaryNode>(PNK_TAGGED_TEMPLATE, JSOP_CALL, tag, args);
|
||||
}
|
||||
|
||||
ParseNode* newGenExp(ParseNode* callee, ParseNode* args) {
|
||||
return new_<BinaryNode>(PNK_GENEXP, JSOP_CALL, callee, args);
|
||||
}
|
||||
|
||||
ParseNode* newObjectLiteral(uint32_t begin) {
|
||||
|
|
@ -765,6 +777,10 @@ class FullParseHandler
|
|||
return new_<CodeNode>(PNK_MODULE, JSOP_NOP, pos());
|
||||
}
|
||||
|
||||
Node newNewExpression(uint32_t begin, ParseNode* ctor, ParseNode* args) {
|
||||
return new_<BinaryNode>(PNK_NEW, JSOP_NEW, TokenPos(begin, args->pn_pos.end), ctor, args);
|
||||
}
|
||||
|
||||
ParseNode* newLexicalScope(LexicalScope::Data* bindings, ParseNode* body) {
|
||||
return new_<LexicalScopeNode>(bindings, body);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -307,17 +307,17 @@ class NameResolver
|
|||
bool resolveTaggedTemplate(ParseNode* node, HandleAtom prefix) {
|
||||
MOZ_ASSERT(node->isKind(PNK_TAGGED_TEMPLATE));
|
||||
|
||||
ParseNode* element = node->pn_head;
|
||||
ParseNode* tag = node->pn_left;
|
||||
|
||||
// The list head is a leading expression, e.g. |tag| in |tag`foo`|,
|
||||
// The leading expression, e.g. |tag| in |tag`foo`|,
|
||||
// that might contain functions.
|
||||
if (!resolve(element, prefix))
|
||||
if (!resolve(tag, prefix))
|
||||
return false;
|
||||
|
||||
// Next is the callsite object node. This node only contains
|
||||
// The callsite object node is first. This node only contains
|
||||
// internal strings or undefined and an array -- no user-controlled
|
||||
// expressions.
|
||||
element = element->pn_next;
|
||||
ParseNode* element = node->pn_right->pn_head;
|
||||
#ifdef DEBUG
|
||||
{
|
||||
MOZ_ASSERT(element->isKind(PNK_CALLSITEOBJ));
|
||||
|
|
@ -689,10 +689,6 @@ class NameResolver
|
|||
case PNK_MOD:
|
||||
case PNK_POW:
|
||||
case PNK_COMMA:
|
||||
case PNK_NEW:
|
||||
case PNK_CALL:
|
||||
case PNK_SUPERCALL:
|
||||
case PNK_GENEXP:
|
||||
case PNK_ARRAY:
|
||||
case PNK_STATEMENTLIST:
|
||||
case PNK_PARAMSBODY:
|
||||
|
|
@ -739,11 +735,33 @@ class NameResolver
|
|||
break;
|
||||
|
||||
case PNK_TAGGED_TEMPLATE:
|
||||
MOZ_ASSERT(cur->isArity(PN_LIST));
|
||||
MOZ_ASSERT(cur->isArity(PN_BINARY));
|
||||
if (!resolveTaggedTemplate(cur, prefix))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case PNK_NEW:
|
||||
case PNK_CALL:
|
||||
case PNK_GENEXP:
|
||||
case PNK_SUPERCALL:
|
||||
MOZ_ASSERT(cur->isArity(PN_BINARY));
|
||||
if (!resolve(cur->pn_left, prefix))
|
||||
return false;
|
||||
if (!resolve(cur->pn_right, prefix))
|
||||
return false;
|
||||
break;
|
||||
|
||||
// Handles the arguments for new/call/supercall, but does _not_ handle
|
||||
// the Arguments node used by tagged template literals, since that is
|
||||
// special-cased inside of resolveTaggedTemplate.
|
||||
case PNK_ARGUMENTS:
|
||||
MOZ_ASSERT(cur->isArity(PN_LIST));
|
||||
for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
|
||||
if (!resolve(element, prefix))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
// Import/export spec lists contain import/export specs containing
|
||||
// only pairs of names. Alternatively, an export spec lists may
|
||||
// contain a single export batch specifier.
|
||||
|
|
|
|||
|
|
@ -264,6 +264,12 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
case PNK_DOWHILE:
|
||||
case PNK_WHILE:
|
||||
case PNK_SWITCH:
|
||||
case PNK_NEW:
|
||||
case PNK_OPTCALL:
|
||||
case PNK_CALL:
|
||||
case PNK_SUPERCALL:
|
||||
case PNK_TAGGED_TEMPLATE:
|
||||
case PNK_GENEXP:
|
||||
case PNK_CLASSMETHOD:
|
||||
case PNK_NEWTARGET:
|
||||
case PNK_SETTHIS:
|
||||
|
|
@ -452,19 +458,14 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
case PNK_MOD:
|
||||
case PNK_POW:
|
||||
case PNK_COMMA:
|
||||
case PNK_NEW:
|
||||
case PNK_OPTCALL:
|
||||
case PNK_CALL:
|
||||
case PNK_SUPERCALL:
|
||||
case PNK_GENEXP:
|
||||
case PNK_ARRAY:
|
||||
case PNK_OBJECT:
|
||||
case PNK_TEMPLATE_STRING_LIST:
|
||||
case PNK_TAGGED_TEMPLATE:
|
||||
case PNK_CALLSITEOBJ:
|
||||
case PNK_VAR:
|
||||
case PNK_CONST:
|
||||
case PNK_LET:
|
||||
case PNK_ARGUMENTS:
|
||||
case PNK_CATCHLIST:
|
||||
case PNK_STATEMENTLIST:
|
||||
case PNK_IMPORT_SPEC_LIST:
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class ObjectBox;
|
|||
F(LABEL) \
|
||||
F(OBJECT) \
|
||||
F(CALL) \
|
||||
F(ARGUMENTS) \
|
||||
F(NAME) \
|
||||
F(OBJECT_PROPERTY_NAME) \
|
||||
F(COMPUTED_NAME) \
|
||||
|
|
@ -372,9 +373,8 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* PNK_POSTINCREMENT,
|
||||
* PNK_PREDECREMENT,
|
||||
* PNK_POSTDECREMENT
|
||||
* PNK_NEW list pn_head: list of ctor, arg1, arg2, ... argN
|
||||
* pn_count: 1 + N (where N is number of args)
|
||||
* ctor is a MEMBER expr
|
||||
* PNK_NEW binary pn_left: ctor expression on the left of the (
|
||||
* pn_right: Arguments
|
||||
* PNK_DELETENAME unary pn_kid: PNK_NAME expr
|
||||
* PNK_DELETEPROP unary pn_kid: PNK_DOT expr
|
||||
* PNK_DELETEELEM unary pn_kid: PNK_ELEM expr
|
||||
|
|
@ -410,10 +410,11 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* pn_atom: name to right of .
|
||||
* PNK_ELEM binary pn_left: MEMBER expr to left of [
|
||||
* pn_right: expr between [ and ]
|
||||
* PNK_CALL list pn_head: list of call, arg1, arg2, ... argN
|
||||
* pn_count: 1 + N (where N is number of args)
|
||||
* call is a MEMBER expr naming a callable object
|
||||
* PNK_GENEXP list Exactly like PNK_CALL, used for the implicit call
|
||||
* PNK_CALL binary pn_left: callee expression on the left of the (
|
||||
* pn_right: Arguments
|
||||
* PNK_ARGUMENTS list pn_head: list of arg1, arg2, ... argN
|
||||
* pn_count: N (where N is number of args)
|
||||
* PNK_GENEXP binary Exactly like PNK_CALL, used for the implicit call
|
||||
* in the desugaring of a generator-expression.
|
||||
* PNK_ARRAY list pn_head: list of pn_count array element exprs
|
||||
* [,,] holes are represented by PNK_ELISION nodes
|
||||
|
|
@ -434,8 +435,8 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* list
|
||||
* PNK_TEMPLATE_STRING pn_atom: template string atom
|
||||
nullary pn_op: JSOP_NOP
|
||||
* PNK_TAGGED_TEMPLATE pn_head: list of call, call site object, arg1, arg2, ... argN
|
||||
* list pn_count: 2 + N (N is the number of substitutions)
|
||||
* PNK_TAGGED_TEMPLATE pn_left: tag expression
|
||||
* binary pn_right: Arguments, with the first being the call site object, then arg1, arg2, ... argN
|
||||
* PNK_CALLSITEOBJ list pn_head: a PNK_ARRAY node followed by
|
||||
* list of pn_count - 1 PNK_TEMPLATE_STRING nodes
|
||||
* PNK_REGEXP nullary pn_objbox: RegExp model object
|
||||
|
|
@ -448,6 +449,8 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* PNK_THIS, unary pn_kid: '.this' Name if function `this`, else nullptr
|
||||
* PNK_SUPERBASE unary pn_kid: '.this' Name
|
||||
*
|
||||
* PNK_SUPERCALL binary pn_left: SuperBase pn_right: Arguments
|
||||
*
|
||||
* PNK_SETTHIS binary pn_left: '.this' Name, pn_right: SuperCall
|
||||
*
|
||||
* PNK_LEXICALSCOPE scope pn_u.scope.bindings: scope bindings
|
||||
|
|
@ -744,7 +747,7 @@ class ParseNode
|
|||
ParseNode* generatorExpr() const {
|
||||
MOZ_ASSERT(isKind(PNK_GENEXP));
|
||||
|
||||
ParseNode* callee = this->pn_head;
|
||||
ParseNode* callee = this->pn_left;
|
||||
MOZ_ASSERT(callee->isKind(PNK_FUNCTION));
|
||||
|
||||
ParseNode* paramsBody = callee->pn_body;
|
||||
|
|
|
|||
|
|
@ -3268,12 +3268,12 @@ Parser<ParseHandler>::addExprAndGetNextTemplStrToken(YieldHandling yieldHandling
|
|||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::taggedTemplate(YieldHandling yieldHandling, Node nodeList, TokenKind tt)
|
||||
Parser<ParseHandler>::taggedTemplate(YieldHandling yieldHandling, Node tagArgsList, TokenKind tt)
|
||||
{
|
||||
Node callSiteObjNode = handler.newCallSiteObject(pos().begin);
|
||||
if (!callSiteObjNode)
|
||||
return false;
|
||||
handler.addList(nodeList, callSiteObjNode);
|
||||
handler.addList(tagArgsList, callSiteObjNode);
|
||||
|
||||
while (true) {
|
||||
if (!appendToCallSiteObj(callSiteObjNode))
|
||||
|
|
@ -3281,10 +3281,10 @@ Parser<ParseHandler>::taggedTemplate(YieldHandling yieldHandling, Node nodeList,
|
|||
if (tt != TOK_TEMPLATE_HEAD)
|
||||
break;
|
||||
|
||||
if (!addExprAndGetNextTemplStrToken(yieldHandling, nodeList, &tt))
|
||||
if (!addExprAndGetNextTemplStrToken(yieldHandling, tagArgsList, &tt))
|
||||
return false;
|
||||
}
|
||||
handler.setEndPosition(nodeList, callSiteObjNode);
|
||||
handler.setEndPosition(tagArgsList, callSiteObjNode);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -9037,7 +9037,13 @@ Parser<ParseHandler>::generatorComprehension(uint32_t begin)
|
|||
if (!genfn)
|
||||
return null();
|
||||
|
||||
Node result = handler.newList(PNK_GENEXP, genfn, JSOP_CALL);
|
||||
// Create a dummy argsList so that PNK_GENEXP can be handled as a full PN_BINARY call node
|
||||
Node argsList = handler.newArguments(pos());
|
||||
if (!argsList)
|
||||
return null();
|
||||
handler.setBeginPosition(argsList, pos().end);
|
||||
|
||||
Node result = handler.newGenExp(genfn, argsList);
|
||||
if (!result)
|
||||
return null();
|
||||
handler.setBeginPosition(result, begin);
|
||||
|
|
@ -9067,23 +9073,27 @@ Parser<ParseHandler>::assignExprWithoutYieldOrAwait(YieldHandling yieldHandling)
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::argumentList(YieldHandling yieldHandling, Node listNode, bool* isSpread,
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::argumentList(YieldHandling yieldHandling, bool* isSpread,
|
||||
PossibleError* possibleError /* = nullptr */)
|
||||
{
|
||||
Node argsList = handler.newArguments(pos());
|
||||
if (!argsList)
|
||||
return null();
|
||||
|
||||
bool matched;
|
||||
if (!tokenStream.matchToken(&matched, TOK_RP, TokenStream::Operand))
|
||||
return false;
|
||||
return null();
|
||||
if (matched) {
|
||||
handler.setEndPosition(listNode, pos().end);
|
||||
return true;
|
||||
handler.setEndPosition(argsList, pos().end);
|
||||
return argsList;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
bool spread = false;
|
||||
uint32_t begin = 0;
|
||||
if (!tokenStream.matchToken(&matched, TOK_TRIPLEDOT, TokenStream::Operand))
|
||||
return false;
|
||||
return null();
|
||||
if (matched) {
|
||||
spread = true;
|
||||
begin = pos().begin;
|
||||
|
|
@ -9092,18 +9102,18 @@ Parser<ParseHandler>::argumentList(YieldHandling yieldHandling, Node listNode, b
|
|||
|
||||
Node argNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited, possibleError);
|
||||
if (!argNode)
|
||||
return false;
|
||||
return null();
|
||||
if (spread) {
|
||||
argNode = handler.newSpread(begin, argNode);
|
||||
if (!argNode)
|
||||
return false;
|
||||
return null();
|
||||
}
|
||||
|
||||
handler.addList(listNode, argNode);
|
||||
handler.addList(argsList, argNode);
|
||||
|
||||
bool matched;
|
||||
if (!tokenStream.matchToken(&matched, TOK_COMMA))
|
||||
return false;
|
||||
return null();
|
||||
if (!matched)
|
||||
break;
|
||||
|
||||
|
|
@ -9118,8 +9128,8 @@ Parser<ParseHandler>::argumentList(YieldHandling yieldHandling, Node listNode, b
|
|||
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_ARGS);
|
||||
|
||||
handler.setEndPosition(listNode, pos().end);
|
||||
return true;
|
||||
handler.setEndPosition(argsList, pos().end);
|
||||
return argsList;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
|
@ -9155,10 +9165,6 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
if (newTarget) {
|
||||
lhs = newTarget;
|
||||
} else {
|
||||
lhs = handler.newList(PNK_NEW, newBegin, JSOP_NEW);
|
||||
if (!lhs)
|
||||
return null();
|
||||
|
||||
// Gotten by tryNewTarget
|
||||
tt = tokenStream.currentToken().type;
|
||||
Node ctorExpr = memberExpr(yieldHandling, TripledotProhibited, tt,
|
||||
|
|
@ -9167,8 +9173,6 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
if (!ctorExpr)
|
||||
return null();
|
||||
|
||||
handler.addList(lhs, ctorExpr);
|
||||
|
||||
// If we have encountered an optional chain, in the form of `new
|
||||
// ClassName?.()` then we need to throw, as this is disallowed
|
||||
// by the spec.
|
||||
|
|
@ -9184,13 +9188,24 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
bool matched;
|
||||
if (!tokenStream.matchToken(&matched, TOK_LP))
|
||||
return null();
|
||||
|
||||
bool isSpread = false;
|
||||
Node args;
|
||||
if (matched) {
|
||||
bool isSpread = false;
|
||||
if (!argumentList(yieldHandling, lhs, &isSpread))
|
||||
return null();
|
||||
if (isSpread)
|
||||
handler.setOp(lhs, JSOP_SPREADNEW);
|
||||
args = argumentList(yieldHandling, &isSpread);
|
||||
} else {
|
||||
args = handler.newArguments(pos());
|
||||
}
|
||||
|
||||
if (!args)
|
||||
return null();
|
||||
|
||||
lhs = handler.newNewExpression(newBegin, ctorExpr, args);
|
||||
if (!lhs)
|
||||
return null();
|
||||
|
||||
if (isSpread)
|
||||
handler.setOp(lhs, JSOP_SPREADNEW);
|
||||
}
|
||||
} else if (tt == TOK_SUPER) {
|
||||
Node thisName = newThisName();
|
||||
|
|
@ -9244,15 +9259,16 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
return null();
|
||||
}
|
||||
|
||||
nextMember = handler.newList(PNK_SUPERCALL, lhs, JSOP_SUPERCALL);
|
||||
if (!nextMember)
|
||||
return null();
|
||||
|
||||
// Despite the fact that it's impossible to have |super()| in a
|
||||
// generator, we still inherit the yieldHandling of the
|
||||
// memberExpression, per spec. Curious.
|
||||
bool isSpread = false;
|
||||
if (!argumentList(yieldHandling, nextMember, &isSpread))
|
||||
Node args = argumentList(yieldHandling, &isSpread);
|
||||
if (!args)
|
||||
return null();
|
||||
|
||||
nextMember = handler.newSuperCall(lhs, args);
|
||||
if (!nextMember)
|
||||
return null();
|
||||
|
||||
if (isSpread)
|
||||
|
|
@ -9368,17 +9384,6 @@ Parser<ParseHandler>::memberCall(
|
|||
tt == TOK_NO_SUBS_TEMPLATE,
|
||||
"Unexpected token kind for member call");
|
||||
|
||||
Node nextMember;
|
||||
if (tt == TOK_LP) {
|
||||
if (optionalKind == OptionalKind::Optional) {
|
||||
nextMember = handler.newOptionalCall();
|
||||
} else {
|
||||
nextMember = handler.newCall();
|
||||
}
|
||||
} else {
|
||||
nextMember = handler.newTaggedTemplate();
|
||||
}
|
||||
|
||||
JSOp op = JSOP_CALL;
|
||||
bool maybeAsyncArrow = false;
|
||||
if (PropertyName* prop = handler.maybeDottedProperty(lhs)) {
|
||||
|
|
@ -9422,16 +9427,15 @@ Parser<ParseHandler>::memberCall(
|
|||
}
|
||||
}
|
||||
|
||||
handler.setBeginPosition(nextMember, lhs);
|
||||
handler.addList(nextMember, lhs);
|
||||
|
||||
Node nextMember;
|
||||
if (tt == TOK_LP) {
|
||||
bool isSpread = false;
|
||||
PossibleError* asyncPossibleError = maybeAsyncArrow ?
|
||||
possibleError :
|
||||
nullptr;
|
||||
|
||||
if (!argumentList(yieldHandling, nextMember, &isSpread, asyncPossibleError)) {
|
||||
Node args = argumentList(yieldHandling, &isSpread, asyncPossibleError);
|
||||
if (!args) {
|
||||
return null();
|
||||
}
|
||||
|
||||
|
|
@ -9444,14 +9448,30 @@ Parser<ParseHandler>::memberCall(
|
|||
op = JSOP_SPREADCALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (optionalKind == OptionalKind::Optional) {
|
||||
nextMember = handler.newOptionalCall(lhs, args);
|
||||
} else {
|
||||
nextMember = handler.newCall(lhs, args);
|
||||
}
|
||||
if (!nextMember)
|
||||
return null();
|
||||
} else {
|
||||
if (!taggedTemplate(yieldHandling, nextMember, tt)) {
|
||||
Node args = handler.newArguments(pos());
|
||||
if (!args)
|
||||
return null();
|
||||
|
||||
if (!taggedTemplate(yieldHandling, args, tt)) {
|
||||
return null();
|
||||
}
|
||||
if (optionalKind == OptionalKind::Optional) {
|
||||
error(JSMSG_BAD_OPTIONAL_TEMPLATE);
|
||||
return null();
|
||||
}
|
||||
|
||||
nextMember = handler.newTaggedTemplate(lhs, args);
|
||||
if (!nextMember)
|
||||
return null();
|
||||
}
|
||||
handler.setOp(nextMember, op);
|
||||
|
||||
|
|
|
|||
|
|
@ -1374,7 +1374,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
Node arrayComprehension(uint32_t begin);
|
||||
Node generatorComprehension(uint32_t begin);
|
||||
|
||||
bool argumentList(YieldHandling yieldHandling, Node listNode, bool* isSpread,
|
||||
Node argumentList(YieldHandling yieldHandling, bool* isSpread,
|
||||
PossibleError* possibleError = nullptr);
|
||||
Node destructuringDeclaration(DeclarationKind kind, YieldHandling yieldHandling,
|
||||
TokenKind tt);
|
||||
|
|
|
|||
|
|
@ -289,9 +289,12 @@ class SyntaxParseHandler
|
|||
MOZ_MUST_USE bool addSpreadElement(Node literal, uint32_t begin, Node inner) { return true; }
|
||||
void addArrayElement(Node literal, Node element) { }
|
||||
|
||||
Node newCall() { return NodeFunctionCall; }
|
||||
Node newOptionalCall() { return NodeOptionalFunctionCall; }
|
||||
Node newTaggedTemplate() { return NodeGeneric; }
|
||||
Node newCall(Node callee, Node args) { return NodeFunctionCall; }
|
||||
Node newOptionalCall(Node callee, Node args) { return NodeOptionalFunctionCall; }
|
||||
Node newArguments(const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newSuperCall(Node callee, Node args) { return NodeGeneric; }
|
||||
Node newTaggedTemplate(Node callee, Node args) { return NodeGeneric; }
|
||||
Node newGenExp(Node callee, Node args) { return NodeGeneric; }
|
||||
|
||||
Node newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
|
||||
Node newClassMethodList(uint32_t begin) { return NodeGeneric; }
|
||||
|
|
@ -491,6 +494,11 @@ class SyntaxParseHandler
|
|||
list == NodeOptionalFunctionCall);
|
||||
}
|
||||
|
||||
|
||||
Node newNewExpression(uint32_t begin, Node ctor, Node args) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) {
|
||||
if (kind == PNK_ASSIGN)
|
||||
return NodeUnparenthesizedAssignment;
|
||||
|
|
|
|||
|
|
@ -465,22 +465,21 @@ static inline ParseNode*
|
|||
CallCallee(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_CALL));
|
||||
return ListHead(pn);
|
||||
return BinaryLeft(pn);
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
CallArgListLength(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_CALL));
|
||||
MOZ_ASSERT(ListLength(pn) >= 1);
|
||||
return ListLength(pn) - 1;
|
||||
return ListLength(BinaryRight(pn));
|
||||
}
|
||||
|
||||
static inline ParseNode*
|
||||
CallArgList(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_CALL));
|
||||
return NextNode(ListHead(pn));
|
||||
return ListHead(BinaryRight(pn));
|
||||
}
|
||||
|
||||
static inline ParseNode*
|
||||
|
|
@ -3433,9 +3432,11 @@ IsArrayViewCtorName(ModuleValidator& m, PropertyName* name, Scalar::Type* type)
|
|||
}
|
||||
|
||||
static bool
|
||||
CheckNewArrayViewArgs(ModuleValidator& m, ParseNode* ctorExpr, PropertyName* bufferName)
|
||||
CheckNewArrayViewArgs(ModuleValidator& m, ParseNode* newExpr, PropertyName* bufferName)
|
||||
{
|
||||
ParseNode* bufArg = NextNode(ctorExpr);
|
||||
ParseNode* ctorExpr = BinaryLeft(newExpr);
|
||||
ParseNode* ctorArgs = BinaryRight(newExpr);
|
||||
ParseNode* bufArg = ListHead(ctorArgs);
|
||||
if (!bufArg || NextNode(bufArg) != nullptr)
|
||||
return m.fail(ctorExpr, "array view constructor takes exactly one argument");
|
||||
|
||||
|
|
@ -3456,7 +3457,7 @@ CheckNewArrayView(ModuleValidator& m, PropertyName* varName, ParseNode* newExpr)
|
|||
if (!bufferName)
|
||||
return m.fail(newExpr, "cannot create array view without an asm.js heap parameter");
|
||||
|
||||
ParseNode* ctorExpr = ListHead(newExpr);
|
||||
ParseNode* ctorExpr = BinaryLeft(newExpr);
|
||||
|
||||
PropertyName* field;
|
||||
Scalar::Type type;
|
||||
|
|
@ -3485,7 +3486,7 @@ CheckNewArrayView(ModuleValidator& m, PropertyName* varName, ParseNode* newExpr)
|
|||
type = global->viewType();
|
||||
}
|
||||
|
||||
if (!CheckNewArrayViewArgs(m, ctorExpr, bufferName))
|
||||
if (!CheckNewArrayViewArgs(m, newExpr, bufferName))
|
||||
return false;
|
||||
|
||||
return m.addArrayView(varName, type, field);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue