зеркало из https://github.com/mozilla/pjs.git
Fixed bugs 76103 and 122787: parsing of new-expressions
This commit is contained in:
Родитель
e0cf8a1dad
Коммит
1e7311af09
149
js/ref/jsparse.c
149
js/ref/jsparse.c
|
@ -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;
|
||||
|
||||
pn = PrimaryExpr(cx, ts, tc);
|
||||
if (!pn)
|
||||
return NULL;
|
||||
/* 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)
|
||||
return NULL;
|
||||
PN_APPEND(pn2, pn3);
|
||||
} while (js_MatchToken(cx, ts, TOK_COMMA));
|
||||
|
||||
/* (balance: */
|
||||
MUST_MATCH_TOKEN(TOK_RP, "missing ) after argument list");
|
||||
}
|
||||
|
||||
pn2 = ArgumentList(cx, ts, tc, pn2);
|
||||
if (!pn2)
|
||||
return NULL;
|
||||
if (pn2->pn_count - 1 >= ARGC_LIMIT) {
|
||||
JS_ReportError(cx, "too many function arguments");
|
||||
return NULL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче