From 3d1e7ac80bed3024e6dc6cbb2f81d97f7e559aa2 Mon Sep 17 00:00:00 2001 From: brendan Date: Wed, 17 Jun 1998 19:37:53 +0000 Subject: [PATCH] - Fix function in with statement to form a closure with the right scope chain on activation (120172, mlm). - Use #ifdef CHECK_RETURN_EXPR to hide CheckFinalReturn as well as its calls. - 80th column tyranny, typedef symmetry, other cosmetics. --- js/ref/jsfun.c | 8 ++++++-- js/ref/jsparse.c | 40 +++++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/js/ref/jsfun.c b/js/ref/jsfun.c index cce955d73ef..7bf4ab809b8 100644 --- a/js/ref/jsfun.c +++ b/js/ref/jsfun.c @@ -282,10 +282,14 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent, /* Splice callobj into the scope chain. */ if (!withobj) { - for (obj = fp->scopeChain; obj; obj = OBJ_GET_PARENT(cx, obj)) { + for (obj = fp->scopeChain; obj; obj = parent) { if (OBJ_GET_CLASS(cx, obj) != &js_WithClass) break; - withobj = obj; + parent = OBJ_GET_PARENT(cx, obj); + if (parent == funobj) { + withobj = obj; + break; + } } } if (withobj) diff --git a/js/ref/jsparse.c b/js/ref/jsparse.c index 737b84b72a1..d0873c2d371 100644 --- a/js/ref/jsparse.c +++ b/js/ref/jsparse.c @@ -65,6 +65,9 @@ typedef JSParseNode * JSParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc); +typedef JSParseNode * +JSMemberParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, + JSBool allowCallSyntax); static JSParser FunctionStmt; #if JS_HAS_LEXICAL_CLOSURE @@ -87,7 +90,7 @@ static JSParser ShiftExpr; static JSParser AddExpr; static JSParser MulExpr; static JSParser UnaryExpr; -static JSParseNode *MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSBool allowCallSyntax); +static JSMemberParser MemberExpr; static JSParser PrimaryExpr; /* @@ -240,6 +243,8 @@ out: return ok; } +#ifdef CHECK_RETURN_EXPR + /* * Insist on a final return before control flows out of pn, but don't be too * smart about loops (do {...; return e2;} while(0) at the end of a function @@ -282,6 +287,8 @@ CheckFinalReturn(JSParseNode *pn) static char badreturn_str[] = "function does not always return a value"; +#endif /* CHECK_RETURN_EXPR */ + static JSParseNode * FunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun, JSTreeContext *tc) @@ -369,10 +376,10 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSAtom *funAtom, *argAtom; JSObject *parent; JSFunction *fun, *outerFun; - JSStmtInfo *topStmt; JSBool ok, named; JSObject *pobj; JSScopeProperty *sprop; + JSTreeContext funtc; jsval junk; /* Make a TOK_FUNCTION node. */ @@ -391,10 +398,6 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, if (!parent) return NULL; - /* Clear tc->topStmt for semantic checking (restore at label out:). */ - topStmt = tc->topStmt; - tc->topStmt = NULL; - #if JS_HAS_LEXICAL_CLOSURE if (!funAtom || cx->fp->scopeChain != parent || InWithStatement(tc)) { /* Don't name the function if enclosed by a with statement or equiv. */ @@ -481,7 +484,8 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, ok = JS_FALSE; goto out); pn->pn_pos.begin = ts->token.pos.begin; - pn2 = FunctionBody(cx, ts, fun, tc); + INIT_TREE_CONTEXT(&funtc); + pn2 = FunctionBody(cx, ts, fun, &funtc); if (!pn2) { ok = JS_FALSE; goto out; @@ -493,7 +497,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, pn->pn_fun = fun; pn->pn_body = pn2; - pn->pn_tryCount = tc->tryCount; + pn->pn_tryCount = funtc.tryCount; #if JS_HAS_LEXICAL_CLOSURE if (outerFun || cx->fp->scopeChain != parent || InWithStatement(tc)) @@ -506,7 +510,6 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, ok = JS_TRUE; out: - tc->topStmt = topStmt; if (!ok) { if (named) (void) OBJ_DELETE_PROPERTY(cx, parent, (jsid)funAtom, &junk); @@ -1001,7 +1004,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) * with an 'in' expression as its initializer, leaving ts->pushback at * the right parenthesis. This condition tests 1, then 3, then 2: */ - if (pn1 && + if (pn1 && (pn1->pn_type == TOK_IN || (pn1->pn_type == TOK_VAR && ts->pushback.type == TOK_RP) || js_MatchToken(cx, ts, TOK_IN))) { @@ -1156,7 +1159,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) PR_ASSERT(0); } break; - case TOK_VAR: + case TOK_VAR: PR_ASSERT(pn4->pn_head->pn_type == TOK_NAME); switch(pn4->pn_head->pn_op) { case JSOP_GETVAR: @@ -1179,7 +1182,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) PR_ASSERT(0); } pn2->pn_left = pn4; - + /* (balance: */ MUST_MATCH_TOKEN(TOK_RP, "missing ) after catch declaration"); pn2->pn_right = Statement(cx, ts, tc); @@ -1361,11 +1364,13 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) pn->pn_kid = NULL; } +#ifdef CHECK_RETURN_EXPR if ((tc->flags & (TCF_RETURN_EXPR | TCF_RETURN_VOID)) == (TCF_RETURN_EXPR | TCF_RETURN_VOID)) { js_ReportCompileError(cx, ts, badreturn_str); return NULL; } +#endif break; case TOK_LC: @@ -1994,7 +1999,8 @@ UnaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) } static JSParseNode * -ArgumentList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSParseNode *listNode) +ArgumentList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, + JSParseNode *listNode) { JSBool matched; @@ -2016,17 +2022,18 @@ ArgumentList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSParseNode *l } static JSParseNode * -MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSBool allowCallSyntax) +MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, + JSBool allowCallSyntax) { JSParseNode *pn, *pn2, *pn3; JSTokenType tt; - /* Check for new expressions */ + /* Check for new expression first. */ ts->flags |= TSF_REGEXP; tt = js_PeekToken(cx, ts); ts->flags &= ~TSF_REGEXP; if (tt == TOK_NEW) { - (void)js_GetToken(cx, ts); + (void) js_GetToken(cx, ts); pn = NewParseNode(cx, &ts->token, PN_LIST); if (!pn) @@ -2046,7 +2053,6 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSBool allowCall return NULL; } pn->pn_pos.end = PN_LAST(pn)->pn_pos.end; - } else { pn = PrimaryExpr(cx, ts, tc); if (!pn)