From 4e0c8bf89d45771b167ddeecdcb3a5c76b28fa86 Mon Sep 17 00:00:00 2001 From: "brendan%mozilla.org" Date: Wed, 13 Sep 2006 07:20:48 +0000 Subject: [PATCH] Fix else-if chains to be unbraced as required by single let declaration consequents (352268, r=mrbkap). git-svn-id: svn://10.0.0.236/trunk@209999 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js/src/js.c | 6 +++++- mozilla/js/src/jsemit.c | 14 ++++++++++---- mozilla/js/src/jsopcode.c | 39 ++++++++++++++++++++++++++++++++------- mozilla/js/src/jsxdrapi.h | 2 +- 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/mozilla/js/src/js.c b/mozilla/js/src/js.c index e0e40654f94..d1dd954034e 100644 --- a/mozilla/js/src/js.c +++ b/mozilla/js/src/js.c @@ -922,8 +922,12 @@ SrcNotes(JSContext *cx, JSScript *script) (uintN) js_GetSrcNoteOffset(sn, 1), (uintN) js_GetSrcNoteOffset(sn, 2)); break; - case SRC_COND: case SRC_IF_ELSE: + fprintf(gOutFile, " else %u elseif %u", + (uintN) js_GetSrcNoteOffset(sn, 0), + (uintN) js_GetSrcNoteOffset(sn, 1)); + break; + case SRC_COND: case SRC_WHILE: case SRC_PCBASE: case SRC_PCDELTA: diff --git a/mozilla/js/src/jsemit.c b/mozilla/js/src/jsemit.c index 169750ca4ba..ce15c965730 100644 --- a/mozilla/js/src/jsemit.c +++ b/mozilla/js/src/jsemit.c @@ -4002,20 +4002,26 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* Emit code for the condition before pushing stmtInfo. */ if (!js_EmitTree(cx, cg, pn->pn_kid1)) return JS_FALSE; + top = CG_OFFSET(cg); if (stmtInfo.type == STMT_IF) { - js_PushStatement(&cg->treeContext, &stmtInfo, STMT_IF, - CG_OFFSET(cg)); + js_PushStatement(&cg->treeContext, &stmtInfo, STMT_IF, top); } else { /* * We came here from the goto further below that detects else-if * chains, so we must mutate stmtInfo back into a STMT_IF record. * Also (see below for why) we need a note offset for SRC_IF_ELSE - * to help the decompiler. + * to help the decompiler. Actually, we need two offsets, one for + * decompiling any else clause and the second for decompiling an + * else-if chain without bracing, overindenting, or incorrectly + * scoping let declarations. */ JS_ASSERT(stmtInfo.type == STMT_ELSE); stmtInfo.type = STMT_IF; + stmtInfo.update = top; if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) return JS_FALSE; + if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 1, top - jmp)) + return JS_FALSE; } /* Emit an annotated branch-if-false around the then part. */ @@ -6251,7 +6257,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[] = { {"null", 0, 0, 0}, {"if", 0, 0, 0}, - {"if-else", 1, 0, 1}, + {"if-else", 2, 0, 1}, {"while", 1, 0, 1}, {"for", 3, 1, 1}, {"continue", 0, 0, 0}, diff --git a/mozilla/js/src/jsopcode.c b/mozilla/js/src/jsopcode.c index 792d2b40c01..41fb291d29c 100644 --- a/mozilla/js/src/jsopcode.c +++ b/mozilla/js/src/jsopcode.c @@ -643,7 +643,7 @@ static void SetDontBrace(JSPrinter *jp) { ptrdiff_t offset; - + /* When not pretty-printing, newline after brace is chopped. */ JS_ASSERT(jp->spaceOffset < 0); offset = jp->sprinter.offset - (jp->pretty ? 3 : 2); @@ -1547,7 +1547,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) #if JS_HAS_BLOCK_SCOPE /* * If a let declaration is the only child of a control - * structure that does not require braces, it must not + * structure that does not require braces, it must not * be braced. If it were braced explicitly, it would * be bracketed by JSOP_ENTERBLOCK/JSOP_LEAVEBLOCK. */ @@ -1917,19 +1917,26 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) case JSOP_IFEQ: case JSOP_IFEQX: + { + JSBool elseif = JS_FALSE; + + if_again: len = GetJumpOffset(pc, pc); sn = js_GetSrcNote(jp->script, pc); switch (sn ? SN_TYPE(sn) : SRC_NULL) { case SRC_IF: case SRC_IF_ELSE: + op = JSOP_NOP; /* turn off parens */ rval = POP_STR(); if (ss->inArrayInit) { LOCAL_ASSERT(SN_TYPE(sn) == SRC_IF); if (Sprint(&ss->sprinter, " if (%s)", rval) < 0) return JS_FALSE; } else { - js_printf(SET_MAYBE_BRACE(jp), "\tif (%s) {\n", rval); + js_printf(SET_MAYBE_BRACE(jp), + elseif ? " if (%s) {\n" : "\tif (%s) {\n", + rval); jp->indent += 4; } @@ -1937,14 +1944,31 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) DECOMPILE_CODE(pc + oplen, len - oplen); } else { LOCAL_ASSERT(!ss->inArrayInit); - len = js_GetSrcNoteOffset(sn, 0); - DECOMPILE_CODE(pc + oplen, len - oplen); + tail = js_GetSrcNoteOffset(sn, 0); + DECOMPILE_CODE(pc + oplen, tail - oplen); jp->indent -= 4; - pc += len; + pc += tail; LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX); oplen = js_CodeSpec[*pc].length; len = GetJumpOffset(pc, pc); js_printf(jp, "\t} else"); + + /* + * If the second offset for sn is non-zero, it tells + * the distance from the goto around the else, to the + * ifeq for the if inside the else that forms an "if + * else if" chain. Thus cond spans the condition of + * the second if, so we simply decompile it and start + * over at label if_again. + */ + cond = js_GetSrcNoteOffset(sn, 1); + if (cond != 0) { + DECOMPILE_CODE(pc + oplen, cond - oplen); + pc += cond; + elseif = JS_TRUE; + goto if_again; + } + js_printf(SET_MAYBE_BRACE(jp), " {\n"); jp->indent += 4; DECOMPILE_CODE(pc + oplen, len - oplen); @@ -1995,6 +2019,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) break; } break; + } case JSOP_IFNE: case JSOP_IFNEX: @@ -2259,7 +2284,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) sn = js_GetSrcNote(jp->script, pc - 1); if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) { todo = Sprint(&ss->sprinter, "%s %s= %s", - lval, + lval, (lastop == JSOP_GETTER) ? js_getter_str : (lastop == JSOP_SETTER) diff --git a/mozilla/js/src/jsxdrapi.h b/mozilla/js/src/jsxdrapi.h index 8762a69db7c..43fdcba4d05 100644 --- a/mozilla/js/src/jsxdrapi.h +++ b/mozilla/js/src/jsxdrapi.h @@ -200,7 +200,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); * before deserialization of bytecode. If the saved version does not match * the current version, abort deserialization and invalidate the file. */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 2) +#define JSXDR_BYTECODE_VERSION (0xb973c0de - 3) /* * Library-private functions.