Fixed bugs 76103 and 122787: parsing of new-expressions

This commit is contained in:
waldemar 1998-06-02 01:54:31 +00:00
Родитель e0cf8a1dad
Коммит 1e7311af09
1 изменённых файлов: 64 добавлений и 85 удалений

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

@ -87,7 +87,7 @@ static JSParser ShiftExpr;
static JSParser AddExpr;
static JSParser MulExpr;
static JSParser UnaryExpr;
static JSParser MemberExpr;
static JSParseNode *MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSBool allowCallSyntax);
static JSParser PrimaryExpr;
/*
@ -1905,7 +1905,7 @@ static JSParseNode *
UnaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{
JSTokenType tt;
JSParseNode *pn, *pn2, *pn3;
JSParseNode *pn, *pn2;
ts->flags |= TSF_REGEXP;
tt = js_GetToken(cx, ts);
@ -1932,7 +1932,7 @@ UnaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn = NewParseNode(cx, &ts->token, PN_UNARY);
if (!pn)
return NULL;
pn2 = MemberExpr(cx, ts, tc);
pn2 = MemberExpr(cx, ts, tc, JS_TRUE);
if (!pn2)
return NULL;
if (!SetIncOpKid(cx, ts, tc, pn, pn2, tt, JS_TRUE))
@ -1940,69 +1940,11 @@ UnaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn->pn_pos.end = pn2->pn_pos.end;
break;
case TOK_NEW:
/* Allow 'new this.ctor(...)' constructor expressions. */
pn = NewParseNode(cx, &ts->token, PN_LIST);
if (!pn)
return NULL;
tt = js_GetToken(cx, ts);
pn2 = NewParseNode(cx, &ts->token, PN_NULLARY);
if (!pn2)
return NULL;
switch (tt) {
case TOK_NAME:
pn2->pn_op = JSOP_NAME;
pn2->pn_atom = ts->token.t_atom;
pn2->pn_slot = -1;
break;
case TOK_PRIMARY:
if (ts->token.t_op == JSOP_THIS) {
pn2->pn_op = JSOP_THIS;
break;
}
/* FALL THROUGH */
default:
js_ReportCompileError(cx, ts, "missing name after new operator");
return NULL;
}
while (js_MatchToken(cx, ts, TOK_DOT)) {
pn3 = NewParseNode(cx, &ts->token, PN_NAME);
if (!pn3)
return NULL;
MUST_MATCH_TOKEN(TOK_NAME,
"missing name in constructor expression");
pn3->pn_pos.begin = pn2->pn_pos.begin;
pn3->pn_pos.end = ts->token.pos.end;
pn3->pn_op = JSOP_GETPROP;
pn3->pn_expr = pn2;
pn3->pn_atom = ts->token.t_atom;
pn2 = pn3;
}
PN_INIT_LIST_1(pn, pn2);
if (js_MatchToken(cx, ts, TOK_LP) && !js_MatchToken(cx, ts, TOK_RP)) {
do {
pn2 = AssignExpr(cx, ts, tc);
if (!pn2)
return NULL;
PN_APPEND(pn, pn2);
} while (js_MatchToken(cx, ts, TOK_COMMA));
/* (balance: */
MUST_MATCH_TOKEN(TOK_RP,
"missing ) after constructor argument list");
}
if (pn->pn_count - 1 >= ARGC_LIMIT) {
JS_ReportError(cx, "too many constructor arguments");
return NULL;
}
pn->pn_pos.end = PN_LAST(pn)->pn_pos.end;
break;
case TOK_DELETE:
pn = NewParseNode(cx, &ts->token, PN_UNARY);
if (!pn)
return NULL;
pn2 = MemberExpr(cx, ts, tc);
pn2 = UnaryExpr(cx, ts, tc);
if (!pn2)
return NULL;
if (!SetLvalKid(cx, ts, pn, pn2, js_delete_str))
@ -2015,7 +1957,7 @@ UnaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
default:
js_UngetToken(ts);
pn = MemberExpr(cx, ts, tc);
pn = MemberExpr(cx, ts, tc, JS_TRUE);
if (!pn)
return NULL;
@ -2039,15 +1981,64 @@ UnaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
}
static JSParseNode *
MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
ArgumentList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSParseNode *listNode)
{
JSBool matched;
ts->flags |= TSF_REGEXP;
matched = js_MatchToken(cx, ts, TOK_RP);
ts->flags &= ~TSF_REGEXP;
if (!matched) {
do {
JSParseNode *argNode = AssignExpr(cx, ts, tc);
if (!argNode)
return NULL;
PN_APPEND(listNode, argNode);
} while (js_MatchToken(cx, ts, TOK_COMMA));
/* (balance: */
MUST_MATCH_TOKEN(TOK_RP, "missing ) after argument list");
}
return listNode;
}
static JSParseNode *
MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSBool allowCallSyntax)
{
JSParseNode *pn, *pn2, *pn3;
JSTokenType tt;
JSBool matched;
/* Check for new expressions */
ts->flags |= TSF_REGEXP;
tt = js_PeekToken(cx, ts);
ts->flags &= ~TSF_REGEXP;
if (tt == TOK_NEW) {
(void)js_GetToken(cx, ts);
pn = NewParseNode(cx, &ts->token, PN_LIST);
if (!pn)
return NULL;
pn2 = MemberExpr(cx, ts, tc, JS_FALSE);
if (!pn2)
return NULL;
PN_INIT_LIST_1(pn, pn2);
if (js_MatchToken(cx, ts, TOK_LP)) {
pn = ArgumentList(cx, ts, tc, pn);
if (!pn)
return NULL;
}
if (pn->pn_count - 1 >= ARGC_LIMIT) {
JS_ReportError(cx, "too many constructor arguments");
return NULL;
}
pn->pn_pos.end = PN_LAST(pn)->pn_pos.end;
} else {
pn = PrimaryExpr(cx, ts, tc);
if (!pn)
return NULL;
}
while ((tt = js_GetToken(cx, ts)) > TOK_EOF) {
if (tt == TOK_DOT) {
@ -2085,28 +2076,16 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn2->pn_left = pn;
pn2->pn_right = pn3;
}
} else if (tt == TOK_LP) {
} else if (allowCallSyntax && tt == TOK_LP) {
pn2 = NewParseNode(cx, &ts->token, PN_LIST);
if (!pn2)
return NULL;
PN_INIT_LIST_1(pn2, pn);
pn2->pn_op = JSOP_CALL;
PN_INIT_LIST_1(pn2, pn);
ts->flags |= TSF_REGEXP;
matched = js_MatchToken(cx, ts, TOK_RP);
ts->flags &= ~TSF_REGEXP;
if (!matched) {
do {
pn3 = AssignExpr(cx, ts, tc);
if (!pn3)
pn2 = ArgumentList(cx, ts, tc, pn2);
if (!pn2)
return NULL;
PN_APPEND(pn2, pn3);
} while (js_MatchToken(cx, ts, TOK_COMMA));
/* (balance: */
MUST_MATCH_TOKEN(TOK_RP, "missing ) after argument list");
}
if (pn2->pn_count - 1 >= ARGC_LIMIT) {
JS_ReportError(cx, "too many function arguments");
return NULL;