From 0b2fd976f564bb93e0b75daffb01e0753d63c726 Mon Sep 17 00:00:00 2001 From: waldemar Date: Tue, 2 Jun 1998 01:54:31 +0000 Subject: [PATCH] Fixed bugs 76103 and 122787: parsing of new-expressions --- js/ref/jsparse.c | 149 ++++++++++++++++++++--------------------------- 1 file changed, 64 insertions(+), 85 deletions(-) diff --git a/js/ref/jsparse.c b/js/ref/jsparse.c index 53dffd62cab9..a2388a2ff607 100644 --- a/js/ref/jsparse.c +++ b/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;