summaryrefslogtreecommitdiffstats
path: root/src/dom/js/jsopcode.c
diff options
context:
space:
mode:
authorBob Jamison <ishmalius@gmail.com>2007-03-05 10:34:59 +0000
committerishmal <ishmal@users.sourceforge.net>2007-03-05 10:34:59 +0000
commit33837efd4b94c4ebb80f95b3d9dbb6efd5499a98 (patch)
treede482d7687b3bffa97cc78608ba75a8ad7e52b60 /src/dom/js/jsopcode.c
parentAdding optional dialog preview. Implments RFE [ 1435276 ] switch preview on/o... (diff)
downloadinkscape-33837efd4b94c4ebb80f95b3d9dbb6efd5499a98.tar.gz
inkscape-33837efd4b94c4ebb80f95b3d9dbb6efd5499a98.zip
update JS
(bzr r2555)
Diffstat (limited to 'src/dom/js/jsopcode.c')
-rw-r--r--src/dom/js/jsopcode.c675
1 files changed, 556 insertions, 119 deletions
diff --git a/src/dom/js/jsopcode.c b/src/dom/js/jsopcode.c
index e751103a0..80c7eb4dd 100644
--- a/src/dom/js/jsopcode.c
+++ b/src/dom/js/jsopcode.c
@@ -1,4 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -82,6 +83,7 @@ const char js_null_str[] = "null";
const char js_this_str[] = "this";
const char js_false_str[] = "false";
const char js_true_str[] = "true";
+const char js_default_str[] = "default";
const char *js_incop_str[] = {"++", "--"};
@@ -111,7 +113,7 @@ static ptrdiff_t
GetJumpOffset(jsbytecode *pc, jsbytecode *pc2)
{
uint32 type;
-
+
type = (js_CodeSpec[*pc].format & JOF_TYPEMASK);
if (JOF_TYPE_IS_EXTENDED_JUMP(type))
return GET_JUMPX_OFFSET(pc2);
@@ -120,7 +122,7 @@ GetJumpOffset(jsbytecode *pc, jsbytecode *pc2)
#ifdef DEBUG
-JS_FRIEND_API(void)
+JS_FRIEND_API(JSBool)
js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp)
{
jsbytecode *pc, *end;
@@ -135,9 +137,10 @@ js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp)
PTRDIFF(pc, script->code, jsbytecode),
lines, fp);
if (!len)
- return;
+ return JS_FALSE;
pc += len;
}
+ return JS_TRUE;
}
JS_FRIEND_API(uintN)
@@ -150,7 +153,6 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
uint32 type;
JSAtom *atom;
JSString *str;
- char *cstr;
op = (JSOp)*pc;
if (op >= JSOP_LIMIT) {
@@ -189,11 +191,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
str = js_ValueToSource(cx, ATOM_KEY(atom));
if (!str)
return 0;
- cstr = js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
- if (!cstr)
- return 0;
- fprintf(fp, " %s", cstr);
- JS_free(cx, cstr);
+ fprintf(fp, " %s", JS_GetStringBytes(str));
break;
case JOF_UINT16:
@@ -249,12 +247,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
str = js_ValueToSource(cx, ATOM_KEY(atom));
if (!str)
return 0;
- cstr = js_DeflateString(cx, JSSTRING_CHARS(str),
- JSSTRING_LENGTH(str));
- if (!cstr)
- return 0;
- fprintf(fp, "\n\t%s: %d", cstr, off);
- JS_free(cx, cstr);
+ fprintf(fp, "\n\t%s: %d", JS_GetStringBytes(str), off);
npairs--;
}
len = 1 + pc2 - pc;
@@ -271,21 +264,59 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
break;
#if JS_HAS_LEXICAL_CLOSURE
- case JOF_DEFLOCALVAR:
+ case JOF_INDEXCONST:
fprintf(fp, " %u", GET_VARNO(pc));
pc += VARNO_LEN;
atom = GET_ATOM(cx, script, pc);
str = js_ValueToSource(cx, ATOM_KEY(atom));
if (!str)
return 0;
- cstr = js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
- if (!cstr)
- return 0;
- fprintf(fp, " %s", cstr);
- JS_free(cx, cstr);
+ fprintf(fp, " %s", JS_GetStringBytes(str));
break;
#endif
+ case JOF_UINT24:
+ if (op == JSOP_FINDNAME) {
+ /* Special case to avoid a JOF_FINDNAME just for this op. */
+ atom = js_GetAtom(cx, &script->atomMap, GET_LITERAL_INDEX(pc));
+ str = js_ValueToSource(cx, ATOM_KEY(atom));
+ if (!str)
+ return 0;
+ fprintf(fp, " %s", JS_GetStringBytes(str));
+ break;
+ }
+
+ JS_ASSERT(op == JSOP_UINT24 || op == JSOP_LITERAL);
+ fprintf(fp, " %u", GET_LITERAL_INDEX(pc));
+ break;
+
+ case JOF_LITOPX:
+ atom = js_GetAtom(cx, &script->atomMap, GET_LITERAL_INDEX(pc));
+ str = js_ValueToSource(cx, ATOM_KEY(atom));
+ if (!str)
+ return 0;
+
+ /*
+ * Bytecode: JSOP_LITOPX <uint24> op [<varno> if JSOP_DEFLOCALFUN].
+ * Advance pc to point at op.
+ */
+ pc += 1 + LITERAL_INDEX_LEN;
+ op = *pc;
+ cs = &js_CodeSpec[op];
+ fprintf(fp, " %s op %s", JS_GetStringBytes(str), cs->name);
+#if JS_HAS_LEXICAL_CLOSURE
+ if ((cs->format & JOF_TYPEMASK) == JOF_INDEXCONST)
+ fprintf(fp, " %u", GET_VARNO(pc));
+#endif
+
+ /*
+ * Set len to advance pc to skip op and any other immediates (namely,
+ * <varno> if JSOP_DEFLOCALFUN).
+ */
+ JS_ASSERT(cs->length > ATOM_INDEX_LEN);
+ len = cs->length - ATOM_INDEX_LEN;
+ break;
+
default: {
char numBuf[12];
JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format);
@@ -365,7 +396,7 @@ Sprint(Sprinter *sp, const char *format, ...)
ptrdiff_t offset;
va_start(ap, format);
- bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */
+ bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */
va_end(ap);
if (!bp) {
JS_ReportOutOfMemory(sp->context);
@@ -432,10 +463,36 @@ QuoteString(Sprinter *sp, JSString *str, jschar quote)
break;
/* Use js_EscapeMap, \u, or \x only if necessary. */
- if ((u = js_strchr(js_EscapeMap, c)) != NULL)
+ if ((u = js_strchr(js_EscapeMap, c)) != NULL) {
ok = Sprint(sp, "\\%c", (char)u[1]) >= 0;
- else
+ } else {
+#ifdef JS_C_STRINGS_ARE_UTF8
+ /* If this is a surrogate pair, make sure to print the pair. */
+ if (c >= 0xD800 && c <= 0xDBFF) {
+ jschar buffer[3];
+ buffer[0] = c;
+ buffer[1] = *++t;
+ buffer[2] = 0;
+ if (t == z) {
+ char numbuf[10];
+ JS_snprintf(numbuf, sizeof numbuf, "0x%x", c);
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_BAD_SURROGATE_CHAR,
+ numbuf);
+ ok = JS_FALSE;
+ break;
+ }
+ ok = Sprint(sp, "%hs", buffer) >= 0;
+ } else {
+ /* Print as UTF-8 string. */
+ ok = Sprint(sp, "%hc", c) >= 0;
+ }
+#else
+ /* Use \uXXXX or \xXX if the string can't be displayed as UTF-8. */
ok = Sprint(sp, (c >> 8) ? "\\u%04X" : "\\x%02X", c) >= 0;
+#endif
+ }
if (!ok)
return NULL;
}
@@ -443,6 +500,13 @@ QuoteString(Sprinter *sp, JSString *str, jschar quote)
/* Sprint the closing quote and return the quoted string. */
if (quote && Sprint(sp, "%c", (char)quote) < 0)
return NULL;
+
+ /*
+ * If we haven't Sprint'd anything yet, Sprint an empty string so that
+ * the OFF2STR below gives a valid result.
+ */
+ if (off == sp->offset && Sprint(sp, "") < 0)
+ return NULL;
return OFF2STR(sp, off);
}
@@ -545,7 +609,7 @@ js_printf(JSPrinter *jp, const char *format, ...)
/* Suppress newlines (must be once per format, at the end) if not pretty. */
fp = NULL;
- if (!jp->pretty && format[cc = strlen(format)-1] == '\n') {
+ if (!jp->pretty && format[cc = strlen(format) - 1] == '\n') {
fp = JS_strdup(jp->sprinter.context, format);
if (!fp)
return -1;
@@ -554,7 +618,7 @@ js_printf(JSPrinter *jp, const char *format, ...)
}
/* Allocate temp space, convert format, and put. */
- bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */
+ bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */
if (fp) {
JS_free(jp->sprinter.context, fp);
format = NULL;
@@ -590,7 +654,7 @@ typedef struct SprintStack {
} SprintStack;
/* Gap between stacked strings to allow for insertion of parens and commas. */
-#define PAREN_SLOP (2 + 1)
+#define PAREN_SLOP (2 + 1)
/*
* These pseudo-ops help js_DecompileValueGenerator decompile JSOP_SETNAME,
@@ -701,7 +765,7 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
diff = table[0].offset - defaultOffset;
if (diff > 0) {
jp->indent += 2;
- js_printf(jp, "\tdefault:\n");
+ js_printf(jp, "\t%s:\n", js_default_str);
jp->indent += 2;
if (!Decompile(ss, pc + defaultOffset, diff))
return JS_FALSE;
@@ -751,7 +815,7 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
return JS_FALSE;
}
rval = QuoteString(&ss->sprinter, str,
- JSVAL_IS_STRING(key) ? (jschar)'"' : 0);
+ (jschar)(JSVAL_IS_STRING(key) ? '"' : 0));
if (!rval)
return JS_FALSE;
RETRACT(&ss->sprinter, rval);
@@ -768,7 +832,7 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
off = defaultOffset;
}
jp->indent -= 2;
- js_printf(jp, "\tdefault:\n");
+ js_printf(jp, "\t%s:\n", js_default_str);
jp->indent += 2;
}
if (!Decompile(ss, pc + off, off2 - off))
@@ -779,7 +843,7 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
if (defaultOffset == switchLength) {
jp->indent += 2;
- js_printf(jp, "\tdefault:;\n");
+ js_printf(jp, "\t%s:;\n", js_default_str);
jp->indent -= 2;
}
js_printf(jp, "\t}\n");
@@ -800,9 +864,9 @@ GetSlotAtom(JSPrinter *jp, JSPropertyOp getter, uintN slot)
if (sprop->getter != getter)
continue;
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
- JS_ASSERT(!JSVAL_IS_INT(sprop->id));
+ JS_ASSERT(JSID_IS_ATOM(sprop->id));
if ((uintN) sprop->shortid == slot)
- return (JSAtom *) sprop->id;
+ return JSID_TO_ATOM(sprop->id);
}
obj = scope->object;
if (!obj)
@@ -818,20 +882,13 @@ GetSlotAtom(JSPrinter *jp, JSPropertyOp getter, uintN slot)
static const char *
VarPrefix(jssrcnote *sn)
{
- const char *kw;
- static char buf[8];
-
- kw = NULL;
if (sn) {
if (SN_TYPE(sn) == SRC_VAR)
- kw = js_var_str;
- else if (SN_TYPE(sn) == SRC_CONST)
- kw = js_const_str;
+ return "var ";
+ if (SN_TYPE(sn) == SRC_CONST)
+ return "const ";
}
- if (!kw)
- return "";
- JS_snprintf(buf, sizeof buf, "%s ", kw);
- return buf;
+ return "";
}
static JSBool
@@ -847,21 +904,28 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
const char *lval, *rval, *xval, *fmt;
jsint i, argc;
char **argv;
+ jsatomid atomIndex;
JSAtom *atom;
JSObject *obj;
JSFunction *fun;
JSString *str;
JSBool ok;
+#if JS_HAS_XML_SUPPORT
+ JSBool foreach, inXML, quoteAttr;
+#else
+#define inXML JS_FALSE
+#endif
jsval val;
+ int stackDummy;
static const char catch_cookie[] = "/*CATCH*/";
static const char with_cookie[] = "/*WITH*/";
/*
* Local macros
*/
-#define DECOMPILE_CODE(pc,nb) if (!Decompile(ss, pc, nb)) return JS_FALSE
-#define POP_STR() OFF2STR(&ss->sprinter, PopOff(ss, op))
-#define LOCAL_ASSERT(expr) JS_ASSERT(expr); if (!(expr)) return JS_FALSE
+#define DECOMPILE_CODE(pc,nb) if (!Decompile(ss, pc, nb)) return JS_FALSE
+#define POP_STR() OFF2STR(&ss->sprinter, PopOff(ss, op))
+#define LOCAL_ASSERT(expr) JS_ASSERT(expr); if (!(expr)) return JS_FALSE
/*
* Callers know that ATOM_IS_STRING(atom), and we leave it to the optimizer to
@@ -871,13 +935,13 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
(!ATOM_KEYWORD(atom) && js_IsIdentifier(ATOM_TO_STRING(atom)))
/*
- * Get atom from script's atom map, quote/escape its string appropriately into
- * rval, and select fmt from the quoted and unquoted alternatives.
+ * Given an atom already fetched from jp->script's atom map, quote/escape its
+ * string appropriately into rval, and select fmt from the quoted and unquoted
+ * alternatives.
*/
-#define GET_ATOM_QUOTE_AND_FMT(qfmt, ufmt, rval) \
+#define GET_QUOTE_AND_FMT(qfmt, ufmt, rval) \
JS_BEGIN_MACRO \
jschar quote_; \
- atom = GET_ATOM(cx, jp->script, pc); \
if (!ATOM_IS_IDENTIFIER(atom)) { \
quote_ = '\''; \
fmt = qfmt; \
@@ -890,15 +954,33 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
return JS_FALSE; \
JS_END_MACRO
+/*
+ * Get atom from jp->script's atom map, quote/escape its string appropriately
+ * into rval, and select fmt from the quoted and unquoted alternatives.
+ */
+#define GET_ATOM_QUOTE_AND_FMT(qfmt, ufmt, rval) \
+ JS_BEGIN_MACRO \
+ atom = GET_ATOM(cx, jp->script, pc); \
+ GET_QUOTE_AND_FMT(qfmt, ufmt, rval); \
+ JS_END_MACRO
+
cx = ss->sprinter.context;
+ if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);
+ return JS_FALSE;
+ }
+
jp = ss->printer;
endpc = pc + nb;
forelem_tail = forelem_done = NULL;
tail = -1;
- todo = -2; /* NB: different from Sprint() error return. */
+ todo = -2; /* NB: different from Sprint() error return. */
op = JSOP_NOP;
sn = NULL;
rval = NULL;
+#if JS_HAS_XML_SUPPORT
+ foreach = inXML = quoteAttr = JS_FALSE;
+#endif
while (pc < endpc) {
lastop = op;
@@ -926,9 +1008,13 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
/* Print only the right operand of the assignment-op. */
todo = SprintPut(&ss->sprinter, rval, strlen(rval));
- } else {
+ } else if (!inXML) {
todo = Sprint(&ss->sprinter, "%s %s %s",
lval, cs->token, rval);
+ } else {
+ /* In XML, just concatenate the two operands. */
+ JS_ASSERT(op == JSOP_ADD);
+ todo = Sprint(&ss->sprinter, "%s%s", lval, rval);
}
break;
@@ -938,12 +1024,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
case 0:
-#if JS_HAS_GETTER_SETTER
- if (op == JSOP_GETTER || op == JSOP_SETTER) {
- todo = -2;
- break;
- }
-#endif
todo = SprintPut(&ss->sprinter, cs->token, strlen(cs->token));
break;
@@ -953,6 +1033,15 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
}
} else {
switch (op) {
+#define BEGIN_LITOPX_CASE(OP) \
+ case OP: \
+ atomIndex = GET_ATOM_INDEX(pc); \
+ do_##OP: \
+ atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
+
+#define END_LITOPX_CASE \
+ break;
+
case JSOP_NOP:
/*
* Check for a do-while loop, a for-loop with an empty
@@ -1054,14 +1143,22 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
pc += js_CodeSpec[JSOP_NEWINIT].length;
LOCAL_ASSERT(*pc == JSOP_EXCEPTION);
pc += js_CodeSpec[JSOP_EXCEPTION].length;
- LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR);
- atom = GET_ATOM(cx, jp->script, pc);
+ if (*pc == JSOP_LITOPX) {
+ atomIndex = GET_LITERAL_INDEX(pc);
+ pc += 1 + LITERAL_INDEX_LEN;
+ LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR);
+ ++pc;
+ } else {
+ LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR);
+ atomIndex = GET_ATOM_INDEX(pc);
+ pc += js_CodeSpec[JSOP_INITCATCHVAR].length;
+ }
+ atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!rval)
return JS_FALSE;
RETRACT(&ss->sprinter, rval);
js_printf(jp, "%s", rval);
- pc += js_CodeSpec[JSOP_INITCATCHVAR].length;
LOCAL_ASSERT(*pc == JSOP_ENTERWITH);
pc += js_CodeSpec[JSOP_ENTERWITH].length;
@@ -1093,12 +1190,20 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
if (!jp2)
return JS_FALSE;
jp2->scope = jp->scope;
- if (js_DecompileFunction(jp2, fun)) {
+ js_puts(jp2, "\n");
+ ok = js_DecompileFunction(jp2, fun);
+ if (ok) {
+ js_puts(jp2, "\n");
str = js_GetPrinterOutput(jp2);
if (str)
js_printf(jp, "%s\n", JS_GetStringBytes(str));
+ else
+ ok = JS_FALSE;
}
js_DestroyPrinter(jp2);
+ if (!ok)
+ return JS_FALSE;
+
break;
default:;
@@ -1122,6 +1227,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_PUSH:
case JSOP_PUSHOBJ:
case JSOP_BINDNAME:
+ do_JSOP_BINDNAME:
todo = Sprint(&ss->sprinter, "");
break;
@@ -1133,7 +1239,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
{
- static const char finally_cookie[] = "/*FINALLY*/";
+ static const char exception_cookie[] = "/*EXCEPTION*/";
+ static const char retsub_pc_cookie[] = "/*RETSUB_PC*/";
case JSOP_FINALLY:
jp->indent -= 4;
@@ -1145,12 +1252,17 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
* address, popped by JSOP_RETSUB and counted by script->depth
* but not by ss->top (see JSOP_SETSP, below).
*/
- todo = Sprint(&ss->sprinter, finally_cookie);
+ todo = Sprint(&ss->sprinter, exception_cookie);
+ if (todo < 0 || !PushOff(ss, todo, op))
+ return JS_FALSE;
+ todo = Sprint(&ss->sprinter, retsub_pc_cookie);
break;
case JSOP_RETSUB:
rval = POP_STR();
- LOCAL_ASSERT(strcmp(rval, finally_cookie) == 0);
+ LOCAL_ASSERT(strcmp(rval, retsub_pc_cookie) == 0);
+ lval = POP_STR();
+ LOCAL_ASSERT(strcmp(lval, exception_cookie) == 0);
todo = -2;
break;
}
@@ -1285,6 +1397,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
#if JS_HAS_EXCEPTIONS
+ case JSOP_THROWING:
+ todo = -2;
+ break;
+
case JSOP_THROW:
sn = js_GetSrcNote(jp->script, pc);
todo = -2;
@@ -1489,15 +1605,26 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
tail = js_GetSrcNoteOffset(sn2, 0);
do_forinbody:
- js_printf(jp, "\tfor (%s%s", VarPrefix(sn), lval);
+#if JS_HAS_XML_SUPPORT
+ if (foreach) {
+ foreach = JS_FALSE;
+ js_printf(jp, "\tfor %s (%s%s",
+ js_each_str, VarPrefix(sn), lval);
+ } else
+#endif
+ js_printf(jp, "\tfor (%s%s", VarPrefix(sn), lval);
if (atom) {
xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!xval)
return JS_FALSE;
RETRACT(&ss->sprinter, xval);
js_printf(jp, *lval ? ".%s" : "%s", xval);
- } else if (xval) {
- js_printf(jp, "[%s]", xval);
+ } else if (xval && *xval) {
+ js_printf(jp,
+ (js_CodeSpec[lastop].format & JOF_XMLNAME)
+ ? ".%s"
+ : "[%s]",
+ xval);
}
rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]);
js_printf(jp, " in %s) {\n", rval);
@@ -1559,6 +1686,13 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
forelem_done = NULL;
goto do_forinbody;
+#if JS_HAS_GETTER_SETTER
+ case JSOP_GETTER:
+ case JSOP_SETTER:
+ todo = -2;
+ break;
+#endif
+
case JSOP_DUP2:
rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-2]);
todo = SprintPut(&ss->sprinter, rval, strlen(rval));
@@ -1585,7 +1719,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_SETCONST:
case JSOP_SETNAME:
case JSOP_SETGVAR:
- atom = GET_ATOM(cx, jp->script, pc);
+ atomIndex = GET_ATOM_INDEX(pc);
+
+ do_JSOP_SETCONST:
+ atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
+
do_setname:
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!lval)
@@ -1593,6 +1731,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
rval = POP_STR();
if (op == JSOP_SETNAME)
(void) PopOff(ss, op);
+
do_setlval:
sn = js_GetSrcNote(jp->script, pc - 1);
if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
@@ -1694,10 +1833,22 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_DELELEM:
xval = POP_STR();
lval = POP_STR();
- todo = Sprint(&ss->sprinter, "%s %s[%s]",
+ todo = Sprint(&ss->sprinter,
+ (js_CodeSpec[lastop].format & JOF_XMLNAME)
+ ? "%s %s.%s"
+ : "%s %s[%s]",
js_delete_str, lval, xval);
break;
+#if JS_HAS_XML_SUPPORT
+ case JSOP_DELDESC:
+ xval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s %s..%s",
+ js_delete_str, lval, xval);
+ break;
+#endif
+
case JSOP_TYPEOF:
case JSOP_VOID:
rval = POP_STR();
@@ -1743,9 +1894,17 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_DECELEM:
xval = POP_STR();
lval = POP_STR();
- todo = Sprint(&ss->sprinter, "%s%s[%s]",
- js_incop_str[!(cs->format & JOF_INC)],
- lval, xval);
+ if (*xval != '\0') {
+ todo = Sprint(&ss->sprinter,
+ (js_CodeSpec[lastop].format & JOF_XMLNAME)
+ ? "%s%s.%s"
+ : "%s%s[%s]",
+ js_incop_str[!(cs->format & JOF_INC)],
+ lval, xval);
+ } else {
+ todo = Sprint(&ss->sprinter, "%s%s",
+ js_incop_str[!(cs->format & JOF_INC)], lval);
+ }
break;
case JSOP_ARGINC:
@@ -1787,9 +1946,17 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_ELEMDEC:
xval = POP_STR();
lval = POP_STR();
- todo = Sprint(&ss->sprinter, "%s[%s]%s",
- lval, xval,
- js_incop_str[!(cs->format & JOF_INC)]);
+ if (*xval != '\0') {
+ todo = Sprint(&ss->sprinter,
+ (js_CodeSpec[lastop].format & JOF_XMLNAME)
+ ? "%s.%s%s"
+ : "%s[%s]%s",
+ lval, xval,
+ js_incop_str[!(cs->format & JOF_INC)]);
+ } else {
+ todo = Sprint(&ss->sprinter, "%s%s",
+ lval, js_incop_str[!(cs->format & JOF_INC)]);
+ }
break;
case JSOP_GETPROP2:
@@ -1798,13 +1965,41 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
/* FALL THROUGH */
case JSOP_GETPROP:
- GET_ATOM_QUOTE_AND_FMT("%s[%s]", "%s.%s", rval);
+ atom = GET_ATOM(cx, jp->script, pc);
+
+ do_getprop:
+ GET_QUOTE_AND_FMT("%s[%s]", "%s.%s", rval);
+
+ do_getprop_lval:
lval = POP_STR();
todo = Sprint(&ss->sprinter, fmt, lval, rval);
break;
+#if JS_HAS_XML_SUPPORT
+ BEGIN_LITOPX_CASE(JSOP_GETMETHOD)
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_PCBASE)
+ goto do_getprop;
+ GET_QUOTE_AND_FMT("%s.function::[%s]", "%s.function::%s", rval);
+ goto do_getprop_lval;
+
+ BEGIN_LITOPX_CASE(JSOP_SETMETHOD)
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_PCBASE)
+ goto do_setprop;
+ GET_QUOTE_AND_FMT("%s.function::[%s] %s= %s",
+ "%s.function::%s %s= %s",
+ xval);
+ goto do_setprop_rval;
+#endif
+
case JSOP_SETPROP:
- GET_ATOM_QUOTE_AND_FMT("%s[%s] %s= %s", "%s.%s %s= %s", xval);
+ atom = GET_ATOM(cx, jp->script, pc);
+
+ do_setprop:
+ GET_QUOTE_AND_FMT("%s[%s] %s= %s", "%s.%s %s= %s", xval);
+
+ do_setprop_rval:
rval = POP_STR();
lval = POP_STR();
sn = js_GetSrcNote(jp->script, pc - 1);
@@ -1825,10 +2020,15 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
xval = POP_STR();
op = JSOP_GETELEM;
lval = POP_STR();
- if (*xval == '\0')
+ if (*xval == '\0') {
todo = Sprint(&ss->sprinter, "%s", lval);
- else
- todo = Sprint(&ss->sprinter, "%s[%s]", lval, xval);
+ } else {
+ todo = Sprint(&ss->sprinter,
+ (js_CodeSpec[lastop].format & JOF_XMLNAME)
+ ? "%s.%s"
+ : "%s[%s]",
+ lval, xval);
+ }
break;
case JSOP_SETELEM:
@@ -1840,7 +2040,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
if (*xval == '\0')
goto do_setlval;
sn = js_GetSrcNote(jp->script, pc - 1);
- todo = Sprint(&ss->sprinter, "%s[%s] %s= %s",
+ todo = Sprint(&ss->sprinter,
+ (js_CodeSpec[lastop].format & JOF_XMLNAME)
+ ? "%s.%s %s= %s"
+ : "%s[%s] %s= %s",
lval, xval,
(sn && SN_TYPE(sn) == SRC_ASSIGNOP)
? js_CodeSpec[lastop].token
@@ -1883,11 +2086,62 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_UINT16:
i = (jsint) GET_ATOM_INDEX(pc);
+ goto do_sprint_int;
+
+ case JSOP_UINT24:
+ i = (jsint) GET_LITERAL_INDEX(pc);
+ do_sprint_int:
todo = Sprint(&ss->sprinter, "%u", (unsigned) i);
break;
- case JSOP_NUMBER:
- atom = GET_ATOM(cx, jp->script, pc);
+ case JSOP_LITERAL:
+ atomIndex = GET_LITERAL_INDEX(pc);
+ goto do_JSOP_STRING;
+
+ case JSOP_FINDNAME:
+ atomIndex = GET_LITERAL_INDEX(pc);
+ todo = Sprint(&ss->sprinter, "");
+ if (todo < 0 || !PushOff(ss, todo, op))
+ return JS_FALSE;
+ atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
+ goto do_name;
+
+ case JSOP_LITOPX:
+ atomIndex = GET_LITERAL_INDEX(pc);
+ op = pc[1 + LITERAL_INDEX_LEN];
+ switch (op) {
+ case JSOP_ANONFUNOBJ: goto do_JSOP_ANONFUNOBJ;
+ case JSOP_BINDNAME: goto do_JSOP_BINDNAME;
+ case JSOP_CLOSURE: goto do_JSOP_CLOSURE;
+#if JS_HAS_EXPORT_IMPORT
+ case JSOP_EXPORTNAME: goto do_JSOP_EXPORTNAME;
+#endif
+#if JS_HAS_XML_SUPPORT
+ case JSOP_GETMETHOD: goto do_JSOP_GETMETHOD;
+ case JSOP_SETMETHOD: goto do_JSOP_SETMETHOD;
+#endif
+ case JSOP_NAMEDFUNOBJ: goto do_JSOP_NAMEDFUNOBJ;
+ case JSOP_NUMBER: goto do_JSOP_NUMBER;
+ case JSOP_OBJECT: goto do_JSOP_OBJECT;
+#if JS_HAS_XML_SUPPORT
+ case JSOP_QNAMECONST: goto do_JSOP_QNAMECONST;
+ case JSOP_QNAMEPART: goto do_JSOP_QNAMEPART;
+#endif
+ case JSOP_REGEXP: goto do_JSOP_REGEXP;
+ case JSOP_SETCONST: goto do_JSOP_SETCONST;
+ case JSOP_STRING: goto do_JSOP_STRING;
+#if JS_HAS_XML_SUPPORT
+ case JSOP_XMLCDATA: goto do_JSOP_XMLCDATA;
+ case JSOP_XMLCOMMENT: goto do_JSOP_XMLCOMMENT;
+ case JSOP_XMLOBJECT: goto do_JSOP_XMLOBJECT;
+ case JSOP_XMLPI: goto do_JSOP_XMLPI;
+#endif
+ default: JS_ASSERT(0);
+ }
+ /* NOTREACHED */
+ break;
+
+ BEGIN_LITOPX_CASE(JSOP_NUMBER)
val = ATOM_KEY(atom);
if (JSVAL_IS_INT(val)) {
long ival = (long)JSVAL_TO_INT(val);
@@ -1902,22 +2156,27 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
}
todo = Sprint(&ss->sprinter, numStr);
}
- break;
+ END_LITOPX_CASE
- case JSOP_STRING:
- atom = GET_ATOM(cx, jp->script, pc);
+ BEGIN_LITOPX_CASE(JSOP_STRING)
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
- (jschar)'"');
+ inXML ? 0 : (jschar)'"');
if (!rval)
return JS_FALSE;
todo = STR2OFF(&ss->sprinter, rval);
- break;
+ END_LITOPX_CASE
case JSOP_OBJECT:
case JSOP_REGEXP:
case JSOP_ANONFUNOBJ:
case JSOP_NAMEDFUNOBJ:
- atom = GET_ATOM(cx, jp->script, pc);
+ atomIndex = GET_ATOM_INDEX(pc);
+
+ do_JSOP_OBJECT:
+ do_JSOP_REGEXP:
+ do_JSOP_ANONFUNOBJ:
+ do_JSOP_NAMEDFUNOBJ:
+ atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
if (op == JSOP_OBJECT || op == JSOP_REGEXP) {
if (!js_regexp_toString(cx, ATOM_TO_OBJECT(atom), 0, NULL,
&val)) {
@@ -1946,7 +2205,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
jsbytecode *pc2;
ptrdiff_t jmplen, off, off2;
jsint j, n, low, high;
- TableEntry *table;
+ TableEntry *table, pivot;
sn = js_GetSrcNote(jp->script, pc);
JS_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
@@ -1989,7 +2248,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
}
pc2 += jmplen;
}
- js_HeapSort(table, (size_t) j, sizeof(TableEntry),
+ js_HeapSort(table, (size_t) j, &pivot, sizeof(TableEntry),
CompareOffsets, NULL);
}
@@ -2149,19 +2408,20 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
lval,
(op == JSOP_NEW_EQ) ? '=' : '!',
#if JS_HAS_TRIPLE_EQOPS
- JSVERSION_IS_ECMA(cx->version) ? "==" :
+ JS_VERSION_IS_ECMA(cx) ? "==" :
#endif
"=",
rval);
break;
-#endif /* !JS_BUG_FALLIBLE_EQOPS */
+#endif
#if JS_HAS_LEXICAL_CLOSURE
- case JSOP_CLOSURE:
- atom = GET_ATOM(cx, jp->script, pc);
+ BEGIN_LITOPX_CASE(JSOP_CLOSURE)
JS_ASSERT(ATOM_IS_OBJECT(atom));
+ todo = -2;
goto do_function;
-#endif /* JS_HAS_LEXICAL_CLOSURE */
+ END_LITOPX_CASE
+#endif
#if JS_HAS_EXPORT_IMPORT
case JSOP_EXPORTALL:
@@ -2169,15 +2429,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
todo = -2;
break;
- case JSOP_EXPORTNAME:
- atom = GET_ATOM(cx, jp->script, pc);
+ BEGIN_LITOPX_CASE(JSOP_EXPORTNAME)
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!rval)
return JS_FALSE;
RETRACT(&ss->sprinter, rval);
js_printf(jp, "\texport %s\n", rval);
todo = -2;
- break;
+ END_LITOPX_CASE
case JSOP_IMPORTALL:
lval = POP_STR();
@@ -2186,6 +2445,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
case JSOP_IMPORTPROP:
+ do_importprop:
GET_ATOM_QUOTE_AND_FMT("\timport %s[%s]\n", "\timport %s.%s\n",
rval);
lval = POP_STR();
@@ -2196,6 +2456,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_IMPORTELEM:
xval = POP_STR();
op = JSOP_GETELEM;
+ if (js_CodeSpec[lastop].format & JOF_XMLNAME)
+ goto do_importprop;
lval = POP_STR();
js_printf(jp, "\timport %s[%s]\n", lval, xval);
todo = -2;
@@ -2246,10 +2508,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
case JSOP_INITPROP:
- case JSOP_INITCATCHVAR:
atom = GET_ATOM(cx, jp->script, pc);
xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
- ATOM_IS_IDENTIFIER(atom) ? 0 : '\'');
+ (jschar)
+ (ATOM_IS_IDENTIFIER(atom) ? 0 : '\''));
if (!xval)
return JS_FALSE;
rval = POP_STR();
@@ -2268,13 +2530,15 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
rval);
#else
if (lastop == JSOP_GETTER || lastop == JSOP_SETTER) {
- todo = Sprint(&ss->sprinter, "%s%s%s %s%s",
+ rval += strlen(js_function_str) + 1;
+ todo = Sprint(&ss->sprinter, "%s%s%s %s%.*s",
lval,
(lval[1] != '\0') ? ", " : "",
(lastop == JSOP_GETTER)
? js_get_str : js_set_str,
xval,
- rval + strlen(js_function_str) + 1);
+ strlen(rval) - 1,
+ rval);
} else {
todo = Sprint(&ss->sprinter, "%s%s%s:%s",
lval,
@@ -2319,9 +2583,166 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
#endif /* JS_HAS_DEBUGGER_KEYWORD */
+#if JS_HAS_XML_SUPPORT
+ case JSOP_STARTXML:
+ case JSOP_STARTXMLEXPR:
+ inXML = op == JSOP_STARTXML;
+ todo = -2;
+ break;
+
+ case JSOP_DEFXMLNS:
+ rval = POP_STR();
+ js_printf(jp, "\t%s %s %s = %s;\n",
+ js_default_str, js_xml_str, js_namespace_str, rval);
+ todo = -2;
+ break;
+
+ case JSOP_ANYNAME:
+ todo = SprintPut(&ss->sprinter, "*", 1);
+ break;
+
+ BEGIN_LITOPX_CASE(JSOP_QNAMEPART)
+ goto do_name;
+ END_LITOPX_CASE
+
+ BEGIN_LITOPX_CASE(JSOP_QNAMECONST)
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return JS_FALSE;
+ RETRACT(&ss->sprinter, rval);
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s::%s", lval, rval);
+ END_LITOPX_CASE
+
+ case JSOP_QNAME:
+ rval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s::[%s]", lval, rval);
+ break;
+
+ case JSOP_TOATTRNAME:
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "@%s", rval);
+ break;
+
+ case JSOP_TOATTRVAL:
+ todo = -2;
+ break;
+
+ case JSOP_ADDATTRNAME:
+ rval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s %s", lval, rval);
+ /* This gets reset by all XML tag expressions. */
+ quoteAttr = JS_TRUE;
+ break;
+
+ case JSOP_ADDATTRVAL:
+ rval = POP_STR();
+ lval = POP_STR();
+ if (quoteAttr)
+ todo = Sprint(&ss->sprinter, "%s=\"%s\"", lval, rval);
+ else
+ todo = Sprint(&ss->sprinter, "%s=%s", lval, rval);
+ break;
+
+ case JSOP_BINDXMLNAME:
+ /* Leave the name stacked and push a dummy string. */
+ todo = Sprint(&ss->sprinter, "");
+ break;
+
+ case JSOP_SETXMLNAME:
+ /* Pop the r.h.s., the dummy string, and the name. */
+ rval = POP_STR();
+ (void) PopOff(ss, op);
+ lval = POP_STR();
+ goto do_setlval;
+
+ case JSOP_XMLELTEXPR:
+ case JSOP_XMLTAGEXPR:
+ todo = Sprint(&ss->sprinter, "{%s}", POP_STR());
+ inXML = JS_TRUE;
+ /* If we're an attribute value, we shouldn't quote this. */
+ quoteAttr = JS_FALSE;
+ break;
+
+ case JSOP_TOXMLLIST:
+ todo = Sprint(&ss->sprinter, "<>%s</>", POP_STR());
+ inXML = JS_FALSE;
+ break;
+
+ case JSOP_FOREACH:
+ foreach = JS_TRUE;
+ todo = -2;
+ break;
+
+ case JSOP_TOXML:
+ inXML = JS_FALSE;
+ /* FALL THROUGH */
+
+ case JSOP_XMLNAME:
+ case JSOP_FILTER:
+ /* Conversion and prefix ops do nothing in the decompiler. */
+ todo = -2;
+ break;
+
+ case JSOP_ENDFILTER:
+ rval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s.(%s)", lval, rval);
+ break;
+
+ case JSOP_DESCENDANTS:
+ rval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s..%s", lval, rval);
+ break;
+
+ BEGIN_LITOPX_CASE(JSOP_XMLOBJECT)
+ atom = GET_ATOM(cx, jp->script, pc);
+ todo = Sprint(&ss->sprinter, "<xml address='%p'>",
+ ATOM_TO_OBJECT(atom));
+ END_LITOPX_CASE
+
+ BEGIN_LITOPX_CASE(JSOP_XMLCDATA)
+ todo = SprintPut(&ss->sprinter, "<![CDATA[", 9);
+ if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
+ return JS_FALSE;
+ SprintPut(&ss->sprinter, "]]>", 3);
+ END_LITOPX_CASE
+
+ BEGIN_LITOPX_CASE(JSOP_XMLCOMMENT)
+ todo = SprintPut(&ss->sprinter, "<!--", 4);
+ if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
+ return JS_FALSE;
+ SprintPut(&ss->sprinter, "-->", 3);
+ END_LITOPX_CASE
+
+ BEGIN_LITOPX_CASE(JSOP_XMLPI)
+ rval = JS_strdup(cx, POP_STR());
+ if (!rval)
+ return JS_FALSE;
+ todo = SprintPut(&ss->sprinter, "<?", 2);
+ ok = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0) &&
+ SprintPut(&ss->sprinter, " ", 1) >= 0 &&
+ SprintPut(&ss->sprinter, rval, strlen(rval));
+ JS_free(cx, (char *)rval);
+ if (!ok)
+ return JS_FALSE;
+ SprintPut(&ss->sprinter, "?>", 2);
+ END_LITOPX_CASE
+
+ case JSOP_GETFUNNS:
+ todo = SprintPut(&ss->sprinter, js_function_str, 8);
+ break;
+#endif /* JS_HAS_XML_SUPPORT */
+
default:
todo = -2;
break;
+
+#undef BEGIN_LITOPX_CASE
+#undef END_LITOPX_CASE
}
}
@@ -2339,10 +2760,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
/*
* Undefine local macros.
*/
+#undef inXML
#undef DECOMPILE_CODE
#undef POP_STR
#undef LOCAL_ASSERT
#undef ATOM_IS_IDENTIFIER
+#undef GET_QUOTE_AND_FMT
#undef GET_ATOM_QUOTE_AND_FMT
return JS_TRUE;
@@ -2443,7 +2866,6 @@ js_DecompileFunction(JSPrinter *jp, JSFunction *fun)
* an expression by parenthesizing.
*/
if (jp->pretty) {
- js_puts(jp, "\n");
js_printf(jp, "\t");
} else {
if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
@@ -2460,6 +2882,8 @@ js_DecompileFunction(JSPrinter *jp, JSFunction *fun)
js_puts(jp, "(");
if (fun->interpreted && fun->object) {
+ size_t paramsize;
+
/*
* Print the parameters.
*
@@ -2473,20 +2897,21 @@ js_DecompileFunction(JSPrinter *jp, JSFunction *fun)
cx = jp->sprinter.context;
nargs = fun->nargs;
mark = JS_ARENA_MARK(&cx->tempPool);
- JS_ARENA_ALLOCATE_CAST(params, JSAtom **, &cx->tempPool,
- nargs * sizeof(JSAtom *));
+ paramsize = nargs * sizeof(JSAtom *);
+ JS_ARENA_ALLOCATE_CAST(params, JSAtom **, &cx->tempPool, paramsize);
if (!params) {
JS_ReportOutOfMemory(cx);
return JS_FALSE;
}
+ memset(params, 0, paramsize);
scope = OBJ_SCOPE(fun->object);
for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
if (sprop->getter != js_GetArgument)
continue;
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
- JS_ASSERT((uintN) sprop->shortid < nargs);
- JS_ASSERT(!JSVAL_IS_INT(sprop->id));
- params[(uintN) sprop->shortid] = (JSAtom *) sprop->id;
+ JS_ASSERT((uint16) sprop->shortid < nargs);
+ JS_ASSERT(JSID_IS_ATOM(sprop->id));
+ params[(uint16) sprop->shortid] = JSID_TO_ATOM(sprop->id);
}
for (i = 0; i < nargs; i++) {
if (i > 0)
@@ -2519,9 +2944,7 @@ js_DecompileFunction(JSPrinter *jp, JSFunction *fun)
jp->indent -= 4;
js_printf(jp, "\t}");
- if (jp->pretty) {
- js_puts(jp, "\n");
- } else {
+ if (!jp->pretty) {
if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
js_puts(jp, ")");
}
@@ -2538,14 +2961,15 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
JSScript *script;
JSOp op;
const JSCodeSpec *cs;
- uint32 format, mode;
+ uint32 format, mode, type;
intN depth;
jssrcnote *sn;
uintN len, off;
JSPrinter *jp;
JSString *name;
- fp = cx->fp;
+ for (fp = cx->fp; fp && !fp->script; fp = fp->down)
+ continue;
if (!fp)
goto do_fallback;
@@ -2657,8 +3081,11 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
begin = pc;
} else {
sn = js_GetSrcNote(script, pc);
- if (!sn || SN_TYPE(sn) != SRC_PCBASE)
+ if (!sn || (SN_TYPE(sn) != SRC_PCBASE && SN_TYPE(sn) != SRC_PCDELTA)) {
+ if (cs->token)
+ return JS_NewStringCopyZ(cx, cs->token);
goto do_fallback;
+ }
begin = pc - js_GetSrcNoteOffset(sn, 0);
}
end = pc + cs->length;
@@ -2670,7 +3097,17 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
return NULL;
memcpy(tmp, begin, len * sizeof(jsbytecode));
if (mode == JOF_NAME) {
- tmp[0] = JSOP_NAME;
+ /*
+ * JOF_NAME does not imply JOF_CONST, so we must check for the
+ * QARG and QVAR format types and translate those to JSOP_GETARG
+ * or JSOP_GETVAR appropriately, instead of JSOP_NAME.
+ */
+ type = format & JOF_TYPEMASK;
+ tmp[0] = (type == JOF_QARG)
+ ? JSOP_GETARG
+ : (type == JOF_QVAR)
+ ? JSOP_GETVAR
+ : JSOP_NAME;
} else {
/*
* We must replace the faulting pc's bytecode with a corresponding
@@ -2719,8 +3156,8 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
}
if (js_DecompileCode(jp, script, begin, len))
name = js_GetPrinterOutput(jp);
+ js_DestroyPrinter(jp);
}
- js_DestroyPrinter(jp);
if (tmp)
JS_free(cx, tmp);
return name;