Prep patch for 'plan A' (346642, r=mrbkap).
This commit is contained in:
@@ -1584,7 +1584,7 @@ array_extra(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval,
|
|||||||
* First, get or compute our callee, so that we error out consistently
|
* First, get or compute our callee, so that we error out consistently
|
||||||
* when passed a non-callable object.
|
* when passed a non-callable object.
|
||||||
*/
|
*/
|
||||||
callable = js_ValueToCallableObject(cx, &argv[0], 0);
|
callable = js_ValueToCallableObject(cx, &argv[0], JSV2F_SEARCH_STACK);
|
||||||
if (!callable)
|
if (!callable)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
|
|||||||
@@ -1412,18 +1412,14 @@ EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
|
|||||||
if (!EmitNonLocalJumpFixup(cx, cg, toStmt, NULL))
|
if (!EmitNonLocalJumpFixup(cx, cg, toStmt, NULL))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (label) {
|
if (label)
|
||||||
|
index = js_NewSrcNote2(cx, cg, noteType, (ptrdiff_t) ALE_INDEX(label));
|
||||||
|
else if (noteType != SRC_NULL)
|
||||||
index = js_NewSrcNote(cx, cg, noteType);
|
index = js_NewSrcNote(cx, cg, noteType);
|
||||||
|
else
|
||||||
|
index = 0;
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (!js_SetSrcNoteOffset(cx, cg, (uintN)index, 0,
|
|
||||||
(ptrdiff_t) ALE_INDEX(label))) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else if (noteType != SRC_NULL) {
|
|
||||||
if (js_NewSrcNote(cx, cg, noteType) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, lastp);
|
return EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, lastp);
|
||||||
}
|
}
|
||||||
@@ -2269,10 +2265,10 @@ CheckSideEffects(JSContext *cx, JSTreeContext *tc, JSParseNode *pn,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Secret handshake with js_EmitTree's TOK_LP/TOK_NEW case logic, to flag all
|
* Secret handshake with js_EmitTree's TOK_LP/TOK_NEW case logic, to flag all
|
||||||
* uses of JSOP_GETMETHOD that implicitly qualify the method-property name with
|
* uses of JSOP_GETMETHOD that implicitly qualify the method property's name
|
||||||
* a function:: prefix. All other JSOP_GETMETHOD and JSOP_SETMETHOD uses must
|
* with a function:: prefix. All other JSOP_GETMETHOD and JSOP_SETMETHOD uses
|
||||||
* be explicit, so need a distinct source note (SRC_PCDELTA rather than PCBASE)
|
* must be explicit, so we need a distinct source note (SRC_METHODBASE rather
|
||||||
* for round-tripping through the beloved decompiler.
|
* than SRC_PCBASE) for round-tripping through the beloved decompiler.
|
||||||
*/
|
*/
|
||||||
#define JSPROP_IMPLICIT_FUNCTION_NAMESPACE 0x100
|
#define JSPROP_IMPLICIT_FUNCTION_NAMESPACE 0x100
|
||||||
|
|
||||||
@@ -2282,7 +2278,7 @@ SrcNoteForPropOp(JSParseNode *pn, JSOp op)
|
|||||||
return ((op == JSOP_GETMETHOD &&
|
return ((op == JSOP_GETMETHOD &&
|
||||||
!(pn->pn_attrs & JSPROP_IMPLICIT_FUNCTION_NAMESPACE)) ||
|
!(pn->pn_attrs & JSPROP_IMPLICIT_FUNCTION_NAMESPACE)) ||
|
||||||
op == JSOP_SETMETHOD)
|
op == JSOP_SETMETHOD)
|
||||||
? SRC_PCDELTA
|
? SRC_METHODBASE
|
||||||
: SRC_PCBASE;
|
: SRC_PCBASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2843,11 +2839,17 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
pn3->pn_offset = off;
|
pn3->pn_offset = off;
|
||||||
if (beforeCases) {
|
if (beforeCases) {
|
||||||
|
uintN noteCount, noteCountDelta;
|
||||||
|
|
||||||
/* Switch note's second offset is to first JSOP_CASE. */
|
/* Switch note's second offset is to first JSOP_CASE. */
|
||||||
|
noteCount = CG_NOTE_COUNT(cg);
|
||||||
if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1,
|
if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1,
|
||||||
off - top)) {
|
off - top)) {
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
noteCountDelta = CG_NOTE_COUNT(cg) - noteCount;
|
||||||
|
if (noteCountDelta != 0)
|
||||||
|
caseNoteIndex += noteCountDelta;
|
||||||
beforeCases = JS_FALSE;
|
beforeCases = JS_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3330,7 +3332,8 @@ EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
|
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
|
||||||
if (pn2->pn_type == TOK_COMMA) {
|
/* Nullary comma node makes a hole in the array destructurer. */
|
||||||
|
if (pn2->pn_type == TOK_COMMA && pn2->pn_arity == PN_NULLARY) {
|
||||||
JS_ASSERT(pn->pn_type == TOK_RB);
|
JS_ASSERT(pn->pn_type == TOK_RB);
|
||||||
++index;
|
++index;
|
||||||
continue;
|
continue;
|
||||||
@@ -4207,6 +4210,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||||||
|
|
||||||
/* Compile a JSOP_FOR* bytecode based on the left hand side. */
|
/* Compile a JSOP_FOR* bytecode based on the left hand side. */
|
||||||
emitIFEQ = JS_TRUE;
|
emitIFEQ = JS_TRUE;
|
||||||
|
op = JSOP_NOP;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
#if JS_HAS_BLOCK_SCOPE
|
#if JS_HAS_BLOCK_SCOPE
|
||||||
case TOK_LET:
|
case TOK_LET:
|
||||||
@@ -4218,8 +4222,6 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||||||
if (pn3->pn_type == TOK_ASSIGN) {
|
if (pn3->pn_type == TOK_ASSIGN) {
|
||||||
pn3 = pn3->pn_left;
|
pn3 = pn3->pn_left;
|
||||||
JS_ASSERT(pn3->pn_type == TOK_RB || pn3->pn_type == TOK_RC);
|
JS_ASSERT(pn3->pn_type == TOK_RB || pn3->pn_type == TOK_RC);
|
||||||
op = JSOP_NOP;
|
|
||||||
goto destructuring_for;
|
|
||||||
}
|
}
|
||||||
if (pn3->pn_type == TOK_RB || pn3->pn_type == TOK_RC) {
|
if (pn3->pn_type == TOK_RB || pn3->pn_type == TOK_RC) {
|
||||||
op = pn2->pn_left->pn_op;
|
op = pn2->pn_left->pn_op;
|
||||||
@@ -5284,6 +5286,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||||||
|
|
||||||
/* Left parts such as a.b.c and a[b].c need a decompiler note. */
|
/* Left parts such as a.b.c and a[b].c need a decompiler note. */
|
||||||
if (pn2->pn_type != TOK_NAME &&
|
if (pn2->pn_type != TOK_NAME &&
|
||||||
|
#if JS_HAS_DESTRUCTURING
|
||||||
|
pn2->pn_type != TOK_RB &&
|
||||||
|
pn2->pn_type != TOK_RC &&
|
||||||
|
#endif
|
||||||
js_NewSrcNote2(cx, cg, SrcNoteForPropOp(pn2, pn2->pn_op),
|
js_NewSrcNote2(cx, cg, SrcNoteForPropOp(pn2, pn2->pn_op),
|
||||||
CG_OFFSET(cg) - top) < 0) {
|
CG_OFFSET(cg) - top) < 0) {
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
@@ -5311,7 +5317,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||||||
#if JS_HAS_DESTRUCTURING
|
#if JS_HAS_DESTRUCTURING
|
||||||
case TOK_RB:
|
case TOK_RB:
|
||||||
case TOK_RC:
|
case TOK_RC:
|
||||||
if (!EmitDestructuringOps(cx, cg, op, pn2))
|
if (!EmitDestructuringOps(cx, cg, JSOP_NOP, pn2))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -5787,7 +5793,6 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||||||
* statements get braces by default from the decompiler.
|
* statements get braces by default from the decompiler.
|
||||||
*/
|
*/
|
||||||
noteIndex = -1;
|
noteIndex = -1;
|
||||||
tmp = CG_OFFSET(cg);
|
|
||||||
type = pn->pn_expr->pn_type;
|
type = pn->pn_expr->pn_type;
|
||||||
if (type != TOK_CATCH && type != TOK_LET && type != TOK_FOR &&
|
if (type != TOK_CATCH && type != TOK_LET && type != TOK_FOR &&
|
||||||
(!(stmt = stmtInfo.down)
|
(!(stmt = stmtInfo.down)
|
||||||
@@ -5807,19 +5812,26 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||||||
ale = js_IndexAtom(cx, atom, &cg->atomList);
|
ale = js_IndexAtom(cx, atom, &cg->atomList);
|
||||||
if (!ale)
|
if (!ale)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
JS_ASSERT(CG_OFFSET(cg) == top);
|
||||||
EMIT_ATOM_INDEX_OP(JSOP_ENTERBLOCK, ALE_INDEX(ale));
|
EMIT_ATOM_INDEX_OP(JSOP_ENTERBLOCK, ALE_INDEX(ale));
|
||||||
|
|
||||||
if (!js_EmitTree(cx, cg, pn->pn_expr))
|
if (!js_EmitTree(cx, cg, pn->pn_expr))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
|
op = pn->pn_op;
|
||||||
|
if (op == JSOP_LEAVEBLOCKEXPR) {
|
||||||
|
if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
|
||||||
|
return JS_FALSE;
|
||||||
|
} else {
|
||||||
if (noteIndex >= 0 &&
|
if (noteIndex >= 0 &&
|
||||||
!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0,
|
!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0,
|
||||||
CG_OFFSET(cg) - tmp)) {
|
CG_OFFSET(cg) - top)) {
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Emit the JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR opcode. */
|
/* Emit the JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR opcode. */
|
||||||
EMIT_UINT16_IMM_OP(pn->pn_op, count);
|
EMIT_UINT16_IMM_OP(op, count);
|
||||||
cg->stackDepth -= count;
|
cg->stackDepth -= count;
|
||||||
|
|
||||||
ok = js_PopStatementCG(cx, cg);
|
ok = js_PopStatementCG(cx, cg);
|
||||||
@@ -6279,7 +6291,7 @@ JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[] = {
|
|||||||
{"switch", 2, 0, 1},
|
{"switch", 2, 0, 1},
|
||||||
{"funcdef", 1, 0, 0},
|
{"funcdef", 1, 0, 0},
|
||||||
{"catch", 1, 0, 1},
|
{"catch", 1, 0, 1},
|
||||||
{"unused21", 0, 0, 0},
|
{"extended", -1, 0, 0},
|
||||||
{"newline", 0, 0, 0},
|
{"newline", 0, 0, 0},
|
||||||
{"setline", 1, 0, 0},
|
{"setline", 1, 0, 0},
|
||||||
{"xdelta", 0, 0, 0},
|
{"xdelta", 0, 0, 0},
|
||||||
|
|||||||
@@ -80,11 +80,28 @@ typedef enum JSStmtType {
|
|||||||
|
|
||||||
#define STMT_TYPE_IN_RANGE(t,b,e) ((uint)((t) - (b)) <= (uintN)((e) - (b)))
|
#define STMT_TYPE_IN_RANGE(t,b,e) ((uint)((t) - (b)) <= (uintN)((e) - (b)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STMT_TYPE_MAYBE_SCOPE tells whether a statement type is always, or may
|
||||||
|
* become, a lexical scope. It therefore includes block and switch (the two
|
||||||
|
* "maybe" scopes) and excludes with (which has dynamic scope, pending the
|
||||||
|
* "reformed with" in ES4/JS2). It includes all try-catch-finally types.
|
||||||
|
*
|
||||||
|
* STMT_TYPE_LINKS_SCOPE tells whether a JSStmtInfo of the given type eagerly
|
||||||
|
* links to other scoping statement info records. It excludes the two "maybe"
|
||||||
|
* types, block and switch, as well as the try and both finally types, since
|
||||||
|
* try, etc., don't need block scope unless they contain let declarations.
|
||||||
|
*
|
||||||
|
* We treat with as a static scope because it prevents lexical binding from
|
||||||
|
* continuing further up the static scope chain. With the "reformed with"
|
||||||
|
* proposal for JS2, we'll be able to model it statically, too.
|
||||||
|
*/
|
||||||
#define STMT_TYPE_MAYBE_SCOPE(type) \
|
#define STMT_TYPE_MAYBE_SCOPE(type) \
|
||||||
(type != STMT_WITH && \
|
(type != STMT_WITH && \
|
||||||
STMT_TYPE_IN_RANGE(type, STMT_BLOCK, STMT_SUBROUTINE))
|
STMT_TYPE_IN_RANGE(type, STMT_BLOCK, STMT_SUBROUTINE))
|
||||||
|
|
||||||
#define STMT_TYPE_LINKS_SCOPE(type) \
|
#define STMT_TYPE_LINKS_SCOPE(type) \
|
||||||
STMT_TYPE_IN_RANGE(type, STMT_WITH, STMT_CATCH)
|
STMT_TYPE_IN_RANGE(type, STMT_WITH, STMT_CATCH)
|
||||||
|
|
||||||
#define STMT_TYPE_IS_TRYING(type) \
|
#define STMT_TYPE_IS_TRYING(type) \
|
||||||
STMT_TYPE_IN_RANGE(type, STMT_TRY, STMT_SUBROUTINE)
|
STMT_TYPE_IN_RANGE(type, STMT_TRY, STMT_SUBROUTINE)
|
||||||
|
|
||||||
@@ -481,6 +498,17 @@ js_EmitFunctionBody(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body,
|
|||||||
*
|
*
|
||||||
* NB: the js_SrcNoteSpec array in jsemit.c is indexed by this enum, so its
|
* NB: the js_SrcNoteSpec array in jsemit.c is indexed by this enum, so its
|
||||||
* initializers need to match the order here.
|
* initializers need to match the order here.
|
||||||
|
*
|
||||||
|
* Note on adding new source notes: every pair of bytecodes (A, B) where A and
|
||||||
|
* B have disjoint sets of source notes that could apply to each bytecode may
|
||||||
|
* reuse the same note type value for two notes (snA, snB) that have the same
|
||||||
|
* arity, offsetBias, and isSpanDep initializers in js_SrcNoteSpec. This is
|
||||||
|
* why SRC_IF and SRC_INITPROP have the same value below. For bad historical
|
||||||
|
* reasons, some bytecodes below that could be overlayed have not been, but
|
||||||
|
* before using SRC_EXTENDED, consider compressing the existing note types.
|
||||||
|
*
|
||||||
|
* Don't forget to update JSXDR_BYTECODE_VERSION in jsxdrapi.h for all such
|
||||||
|
* incompatible source note or other bytecode changes.
|
||||||
*/
|
*/
|
||||||
typedef enum JSSrcNoteType {
|
typedef enum JSSrcNoteType {
|
||||||
SRC_NULL = 0, /* terminates a note vector */
|
SRC_NULL = 0, /* terminates a note vector */
|
||||||
@@ -495,17 +523,20 @@ typedef enum JSSrcNoteType {
|
|||||||
also used on JSOP_ENDINIT if extra comma
|
also used on JSOP_ENDINIT if extra comma
|
||||||
at end of array literal: [1,2,,] */
|
at end of array literal: [1,2,,] */
|
||||||
SRC_DECL = 6, /* type of a declaration (var, const, let*) */
|
SRC_DECL = 6, /* type of a declaration (var, const, let*) */
|
||||||
SRC_PCDELTA = 7, /* distance from comma-operator to next POP,
|
SRC_PCDELTA = 7, /* distance forward from comma-operator to
|
||||||
or from CONDSWITCH to first CASE opcode --
|
next POP, or from CONDSWITCH to first CASE
|
||||||
or SRC_PCBASE variant for obj.function::foo
|
opcode, etc. -- always a forward delta */
|
||||||
gets and sets */
|
|
||||||
SRC_ASSIGNOP = 8, /* += or another assign-op follows */
|
SRC_ASSIGNOP = 8, /* += or another assign-op follows */
|
||||||
SRC_COND = 9, /* JSOP_IFEQ is from conditional ?: operator */
|
SRC_COND = 9, /* JSOP_IFEQ is from conditional ?: operator */
|
||||||
SRC_BRACE = 10, /* mandatory brace, for scope or to avoid
|
SRC_BRACE = 10, /* mandatory brace, for scope or to avoid
|
||||||
dangling else */
|
dangling else */
|
||||||
SRC_HIDDEN = 11, /* opcode shouldn't be decompiled */
|
SRC_HIDDEN = 11, /* opcode shouldn't be decompiled */
|
||||||
SRC_PCBASE = 12, /* distance back from annotated get- or setprop
|
SRC_PCBASE = 12, /* distance back from annotated getprop or
|
||||||
op to first obj.prop.subprop bytecode */
|
setprop op to left-most obj.prop.subprop
|
||||||
|
bytecode -- always a backward delta */
|
||||||
|
SRC_METHODBASE = 13, /* SRC_PCBASE variant for obj.function::foo
|
||||||
|
gets and sets; disjoint from SRC_LABEL by
|
||||||
|
bytecode to which it applies */
|
||||||
SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */
|
SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */
|
||||||
SRC_LABELBRACE = 14, /* JSOP_NOP for label: {...} begin brace */
|
SRC_LABELBRACE = 14, /* JSOP_NOP for label: {...} begin brace */
|
||||||
SRC_ENDBRACE = 15, /* JSOP_NOP for label: {...} end brace */
|
SRC_ENDBRACE = 15, /* JSOP_NOP for label: {...} end brace */
|
||||||
@@ -515,7 +546,7 @@ typedef enum JSSrcNoteType {
|
|||||||
2nd off to first JSOP_CASE if condswitch */
|
2nd off to first JSOP_CASE if condswitch */
|
||||||
SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */
|
SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */
|
||||||
SRC_CATCH = 20, /* catch block has guard */
|
SRC_CATCH = 20, /* catch block has guard */
|
||||||
SRC_UNUSED21 = 21, /* unused */
|
SRC_EXTENDED = 21, /* extended source note, 32-159, in next byte */
|
||||||
SRC_NEWLINE = 22, /* bytecode follows a source newline */
|
SRC_NEWLINE = 22, /* bytecode follows a source newline */
|
||||||
SRC_SETLINE = 23, /* a file-absolute source line number note */
|
SRC_SETLINE = 23, /* a file-absolute source line number note */
|
||||||
SRC_XDELTA = 24 /* 24-31 are for extended delta notes */
|
SRC_XDELTA = 24 /* 24-31 are for extended delta notes */
|
||||||
|
|||||||
@@ -2234,28 +2234,21 @@ js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags)
|
|||||||
void
|
void
|
||||||
js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags)
|
js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags)
|
||||||
{
|
{
|
||||||
JSType type;
|
JSStackFrame *fp;
|
||||||
JSString *fallback;
|
|
||||||
JSString *str;
|
JSString *str;
|
||||||
JSTempValueRooter tvr;
|
JSTempValueRooter tvr;
|
||||||
const char *bytes, *source;
|
const char *bytes, *source;
|
||||||
|
|
||||||
/*
|
for (fp = cx->fp; fp && !fp->spbase; fp = fp->down)
|
||||||
* We provide the typename as the fallback to handle the case when
|
continue;
|
||||||
* valueOf is not a function, which prevents ValueToString from being
|
|
||||||
* called as the default case inside js_DecompileValueGenerator (and
|
|
||||||
* so recursing back to here).
|
|
||||||
*/
|
|
||||||
type = JS_TypeOfValue(cx, *vp);
|
|
||||||
fallback = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
|
|
||||||
str = js_DecompileValueGenerator(cx,
|
str = js_DecompileValueGenerator(cx,
|
||||||
(flags & JSV2F_SEARCH_STACK)
|
(fp && fp->spbase <= vp && vp < fp->sp)
|
||||||
|
? vp - fp->sp
|
||||||
|
: (flags & JSV2F_SEARCH_STACK)
|
||||||
? JSDVG_SEARCH_STACK
|
? JSDVG_SEARCH_STACK
|
||||||
: cx->fp
|
|
||||||
? vp - cx->fp->sp
|
|
||||||
: JSDVG_IGNORE_STACK,
|
: JSDVG_IGNORE_STACK,
|
||||||
*vp,
|
*vp,
|
||||||
fallback);
|
NULL);
|
||||||
if (str) {
|
if (str) {
|
||||||
JS_PUSH_SINGLE_TEMP_ROOT(cx, str, &tvr);
|
JS_PUSH_SINGLE_TEMP_ROOT(cx, str, &tvr);
|
||||||
bytes = JS_GetStringBytes(str);
|
bytes = JS_GetStringBytes(str);
|
||||||
|
|||||||
@@ -2333,13 +2333,13 @@ interrupt:
|
|||||||
END_CASE(JSOP_POP2)
|
END_CASE(JSOP_POP2)
|
||||||
|
|
||||||
BEGIN_CASE(JSOP_SWAP)
|
BEGIN_CASE(JSOP_SWAP)
|
||||||
/*
|
vp = sp - depth; /* swap generating pc's for the decompiler */
|
||||||
* N.B. JSOP_SWAP doesn't swap the corresponding generating pcs
|
ltmp = vp[-1];
|
||||||
* for the operands it swaps.
|
vp[-1] = vp[-2];
|
||||||
*/
|
|
||||||
ltmp = sp[-1];
|
|
||||||
sp[-1] = sp[-2];
|
|
||||||
sp[-2] = ltmp;
|
sp[-2] = ltmp;
|
||||||
|
rtmp = sp[-1];
|
||||||
|
sp[-1] = sp[-2];
|
||||||
|
sp[-2] = rtmp;
|
||||||
END_CASE(JSOP_SWAP)
|
END_CASE(JSOP_SWAP)
|
||||||
|
|
||||||
BEGIN_CASE(JSOP_POPV)
|
BEGIN_CASE(JSOP_POPV)
|
||||||
@@ -2941,16 +2941,22 @@ interrupt:
|
|||||||
|
|
||||||
BEGIN_CASE(JSOP_DUP)
|
BEGIN_CASE(JSOP_DUP)
|
||||||
JS_ASSERT(sp > fp->spbase);
|
JS_ASSERT(sp > fp->spbase);
|
||||||
rval = sp[-1];
|
vp = sp - 1; /* address top of stack */
|
||||||
PUSH_OPND(rval);
|
rval = *vp;
|
||||||
|
vp -= depth; /* address generating pc */
|
||||||
|
vp[1] = *vp;
|
||||||
|
PUSH(rval);
|
||||||
END_CASE(JSOP_DUP)
|
END_CASE(JSOP_DUP)
|
||||||
|
|
||||||
BEGIN_CASE(JSOP_DUP2)
|
BEGIN_CASE(JSOP_DUP2)
|
||||||
JS_ASSERT(sp - 1 > fp->spbase);
|
JS_ASSERT(sp - 2 >= fp->spbase);
|
||||||
lval = FETCH_OPND(-2);
|
vp = sp - 1; /* address top of stack */
|
||||||
rval = FETCH_OPND(-1);
|
lval = vp[-1];
|
||||||
PUSH_OPND(lval);
|
rval = *vp;
|
||||||
PUSH_OPND(rval);
|
vp -= depth; /* address generating pc */
|
||||||
|
vp[1] = vp[2] = *vp;
|
||||||
|
PUSH(lval);
|
||||||
|
PUSH(rval);
|
||||||
END_CASE(JSOP_DUP2)
|
END_CASE(JSOP_DUP2)
|
||||||
|
|
||||||
#define PROPERTY_OP(n, call) \
|
#define PROPERTY_OP(n, call) \
|
||||||
@@ -3290,6 +3296,7 @@ interrupt:
|
|||||||
END_CASE(JSOP_NEW_NE)
|
END_CASE(JSOP_NEW_NE)
|
||||||
|
|
||||||
BEGIN_CASE(JSOP_CASE)
|
BEGIN_CASE(JSOP_CASE)
|
||||||
|
pc2 = (jsbytecode *) sp[-2-depth];
|
||||||
NEW_EQUALITY_OP(==);
|
NEW_EQUALITY_OP(==);
|
||||||
(void) POP();
|
(void) POP();
|
||||||
if (cond) {
|
if (cond) {
|
||||||
@@ -3297,10 +3304,12 @@ interrupt:
|
|||||||
CHECK_BRANCH(len);
|
CHECK_BRANCH(len);
|
||||||
DO_NEXT_OP(len);
|
DO_NEXT_OP(len);
|
||||||
}
|
}
|
||||||
|
sp[-depth] = (jsval)pc2;
|
||||||
PUSH(lval);
|
PUSH(lval);
|
||||||
END_CASE(JSOP_CASE)
|
END_CASE(JSOP_CASE)
|
||||||
|
|
||||||
BEGIN_CASE(JSOP_CASEX)
|
BEGIN_CASE(JSOP_CASEX)
|
||||||
|
pc2 = (jsbytecode *) sp[-2-depth];
|
||||||
NEW_EQUALITY_OP(==);
|
NEW_EQUALITY_OP(==);
|
||||||
(void) POP();
|
(void) POP();
|
||||||
if (cond) {
|
if (cond) {
|
||||||
@@ -3308,6 +3317,7 @@ interrupt:
|
|||||||
CHECK_BRANCH(len);
|
CHECK_BRANCH(len);
|
||||||
DO_NEXT_OP(len);
|
DO_NEXT_OP(len);
|
||||||
}
|
}
|
||||||
|
sp[-depth] = (jsval)pc2;
|
||||||
PUSH(lval);
|
PUSH(lval);
|
||||||
END_CASE(JSOP_CASEX)
|
END_CASE(JSOP_CASEX)
|
||||||
|
|
||||||
|
|||||||
@@ -3799,10 +3799,10 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
|
|||||||
JSBool
|
JSBool
|
||||||
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
|
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
|
||||||
{
|
{
|
||||||
jsval v;
|
jsval v, save;
|
||||||
JSString *str;
|
JSString *str;
|
||||||
|
|
||||||
v = OBJECT_TO_JSVAL(obj);
|
v = save = OBJECT_TO_JSVAL(obj);
|
||||||
switch (hint) {
|
switch (hint) {
|
||||||
case JSTYPE_STRING:
|
case JSTYPE_STRING:
|
||||||
/*
|
/*
|
||||||
@@ -3846,7 +3846,7 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
|
|||||||
str = NULL;
|
str = NULL;
|
||||||
}
|
}
|
||||||
*vp = OBJECT_TO_JSVAL(obj);
|
*vp = OBJECT_TO_JSVAL(obj);
|
||||||
str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, str);
|
str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, save, str);
|
||||||
if (str) {
|
if (str) {
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||||
JSMSG_CANT_CONVERT_TO,
|
JSMSG_CANT_CONVERT_TO,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -284,7 +284,8 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
|
|||||||
* Decompilers, for script, function, and expression pretty-printing.
|
* Decompilers, for script, function, and expression pretty-printing.
|
||||||
*/
|
*/
|
||||||
extern JSBool
|
extern JSBool
|
||||||
js_DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len);
|
js_DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len,
|
||||||
|
uintN pcdepth);
|
||||||
|
|
||||||
extern JSBool
|
extern JSBool
|
||||||
js_DecompileScript(JSPrinter *jp, JSScript *script);
|
js_DecompileScript(JSPrinter *jp, JSScript *script);
|
||||||
|
|||||||
@@ -321,7 +321,6 @@ OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 0, 0, JOF_BYTE)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Swap the top two stack elements.
|
* Swap the top two stack elements.
|
||||||
* XXX JSOP_SWAP doesn't swap the corresponding pc stack generating pcs.
|
|
||||||
*/
|
*/
|
||||||
OPDEF(JSOP_SWAP, 135,"swap", NULL, 1, 2, 2, 0, JOF_BYTE)
|
OPDEF(JSOP_SWAP, 135,"swap", NULL, 1, 2, 2, 0, JOF_BYTE)
|
||||||
|
|
||||||
|
|||||||
133
js/src/jsparse.c
133
js/src/jsparse.c
@@ -245,9 +245,8 @@ NewParseNode(JSContext *cx, JSTokenStream *ts, JSParseNodeArity arity,
|
|||||||
pn->pn_op = JSOP_NOP;
|
pn->pn_op = JSOP_NOP;
|
||||||
pn->pn_arity = arity;
|
pn->pn_arity = arity;
|
||||||
pn->pn_next = NULL;
|
pn->pn_next = NULL;
|
||||||
#if JS_HAS_XML_SUPPORT
|
|
||||||
pn->pn_ts = ts;
|
pn->pn_ts = ts;
|
||||||
#endif
|
pn->pn_source = NULL;
|
||||||
return pn;
|
return pn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,9 +321,8 @@ NewBinary(JSContext *cx, JSTokenType tt,
|
|||||||
pn->pn_left = left;
|
pn->pn_left = left;
|
||||||
pn->pn_right = right;
|
pn->pn_right = right;
|
||||||
pn->pn_next = NULL;
|
pn->pn_next = NULL;
|
||||||
#if JS_HAS_XML_SUPPORT
|
|
||||||
pn->pn_ts = NULL;
|
pn->pn_ts = NULL;
|
||||||
#endif
|
pn->pn_source = NULL;
|
||||||
return pn;
|
return pn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -852,7 +850,7 @@ js_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun)
|
|||||||
* helper function signature in order to share code among destructuring and
|
* helper function signature in order to share code among destructuring and
|
||||||
* simple variable declaration parsers. In the destructuring case, the binder
|
* simple variable declaration parsers. In the destructuring case, the binder
|
||||||
* function is called indirectly from the variable declaration parser by way
|
* function is called indirectly from the variable declaration parser by way
|
||||||
* of CheckDestructuring and its subroutines.
|
* of CheckDestructuring and its friends.
|
||||||
*/
|
*/
|
||||||
typedef struct BindData BindData;
|
typedef struct BindData BindData;
|
||||||
|
|
||||||
@@ -984,10 +982,9 @@ BindLocalVariable(JSContext *cx, BindData *data, JSAtom *atom)
|
|||||||
/*
|
/*
|
||||||
* Forward declaration to maintain top-down presentation.
|
* Forward declaration to maintain top-down presentation.
|
||||||
*/
|
*/
|
||||||
static JSBool
|
static JSParseNode *
|
||||||
CheckDestructuring(JSContext *cx, BindData *data,
|
DestructuringExpr(JSContext *cx, BindData *data, JSTreeContext *tc,
|
||||||
JSParseNode *left, JSParseNode *right,
|
JSTokenType tt);
|
||||||
JSTreeContext *tc);
|
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom,
|
BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom,
|
||||||
@@ -1197,7 +1194,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||||||
if (!objAtom)
|
if (!objAtom)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Initialize early for possible flags mutation via CheckDestructuring. */
|
/* Initialize early for possible flags mutation via DestructuringExpr. */
|
||||||
TREE_CONTEXT_INIT(&funtc);
|
TREE_CONTEXT_INIT(&funtc);
|
||||||
|
|
||||||
/* Now parse formal argument list and compute fun->nargs. */
|
/* Now parse formal argument list and compute fun->nargs. */
|
||||||
@@ -1222,10 +1219,6 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||||||
JSParseNode *lhs, *rhs;
|
JSParseNode *lhs, *rhs;
|
||||||
jsint slot;
|
jsint slot;
|
||||||
|
|
||||||
lhs = PrimaryExpr(cx, ts, tc, tt, JS_FALSE);
|
|
||||||
if (!lhs)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A destructuring formal parameter turns into one or more
|
* A destructuring formal parameter turns into one or more
|
||||||
* local variables initialized from properties of a single
|
* local variables initialized from properties of a single
|
||||||
@@ -1239,7 +1232,8 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||||||
data.u.var.setter = js_SetLocalVariable;
|
data.u.var.setter = js_SetLocalVariable;
|
||||||
data.u.var.attrs = JSPROP_PERMANENT;
|
data.u.var.attrs = JSPROP_PERMANENT;
|
||||||
|
|
||||||
if (!CheckDestructuring(cx, &data, lhs, NULL, &funtc))
|
lhs = DestructuringExpr(cx, &data, &funtc, tt);
|
||||||
|
if (!lhs)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2141,7 +2135,8 @@ CheckDestructuring(JSContext *cx, BindData *data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pn->pn_type != TOK_COMMA) {
|
/* Nullary comma is an elision; binary comma is an expression.*/
|
||||||
|
if (pn->pn_type != TOK_COMMA || pn->pn_arity != PN_NULLARY) {
|
||||||
if (pn->pn_type == TOK_RB || pn->pn_type == TOK_RC) {
|
if (pn->pn_type == TOK_RB || pn->pn_type == TOK_RC) {
|
||||||
ok = CheckDestructuring(cx, data, pn, pn2, tc);
|
ok = CheckDestructuring(cx, data, pn, pn2, tc);
|
||||||
} else {
|
} else {
|
||||||
@@ -2220,6 +2215,20 @@ no_var_name:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSParseNode *
|
||||||
|
DestructuringExpr(JSContext *cx, BindData *data, JSTreeContext *tc,
|
||||||
|
JSTokenType tt)
|
||||||
|
{
|
||||||
|
JSParseNode *pn;
|
||||||
|
|
||||||
|
pn = PrimaryExpr(cx, data->ts, tc, tt, JS_FALSE);
|
||||||
|
if (!pn)
|
||||||
|
return NULL;
|
||||||
|
if (!CheckDestructuring(cx, data, pn, NULL, tc))
|
||||||
|
return NULL;
|
||||||
|
return pn;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* JS_HAS_DESTRUCTURING */
|
#endif /* JS_HAS_DESTRUCTURING */
|
||||||
|
|
||||||
extern const char js_with_statement_str[];
|
extern const char js_with_statement_str[];
|
||||||
@@ -2344,22 +2353,6 @@ ReturnOrYield(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||||||
return pn;
|
return pn;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JS_HAS_BLOCK_SCOPE
|
|
||||||
static JSStmtInfo *
|
|
||||||
FindMaybeScopeStatement(JSTreeContext *tc)
|
|
||||||
{
|
|
||||||
JSStmtInfo *stmt;
|
|
||||||
|
|
||||||
stmt = tc->topStmt;
|
|
||||||
while (stmt) {
|
|
||||||
if (STMT_MAYBE_SCOPE(stmt))
|
|
||||||
return stmt;
|
|
||||||
stmt = stmt->down;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static JSParseNode *
|
static JSParseNode *
|
||||||
PushLexicalScope(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
PushLexicalScope(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
||||||
JSStmtInfo *stmtInfo)
|
JSStmtInfo *stmtInfo)
|
||||||
@@ -2551,13 +2544,16 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
|||||||
pn2 = Statement(cx, ts, tc);
|
pn2 = Statement(cx, ts, tc);
|
||||||
if (!pn2)
|
if (!pn2)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
ts->flags |= TSF_OPERAND;
|
||||||
if (js_MatchToken(cx, ts, TOK_ELSE)) {
|
if (js_MatchToken(cx, ts, TOK_ELSE)) {
|
||||||
|
ts->flags &= ~TSF_OPERAND;
|
||||||
stmtInfo.type = STMT_ELSE;
|
stmtInfo.type = STMT_ELSE;
|
||||||
pn3 = Statement(cx, ts, tc);
|
pn3 = Statement(cx, ts, tc);
|
||||||
if (!pn3)
|
if (!pn3)
|
||||||
return NULL;
|
return NULL;
|
||||||
pn->pn_pos.end = pn3->pn_pos.end;
|
pn->pn_pos.end = pn3->pn_pos.end;
|
||||||
} else {
|
} else {
|
||||||
|
ts->flags &= ~TSF_OPERAND;
|
||||||
pn3 = NULL;
|
pn3 = NULL;
|
||||||
pn->pn_pos.end = pn2->pn_pos.end;
|
pn->pn_pos.end = pn2->pn_pos.end;
|
||||||
}
|
}
|
||||||
@@ -3056,12 +3052,9 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
|||||||
#if JS_HAS_DESTRUCTURING
|
#if JS_HAS_DESTRUCTURING
|
||||||
case TOK_LB:
|
case TOK_LB:
|
||||||
case TOK_LC:
|
case TOK_LC:
|
||||||
pn3 = PrimaryExpr(cx, ts, tc, tt, JS_FALSE);
|
pn3 = DestructuringExpr(cx, &data, tc, tt);
|
||||||
if (!pn3)
|
if (!pn3)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!CheckDestructuring(cx, &data, pn3, NULL, tc))
|
|
||||||
return NULL;
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -3111,7 +3104,10 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
|||||||
|
|
||||||
PN_APPEND(catchList, pnblock);
|
PN_APPEND(catchList, pnblock);
|
||||||
lastCatch = pn2;
|
lastCatch = pn2;
|
||||||
} while ((tt = js_GetToken(cx, ts)) == TOK_CATCH);
|
ts->flags |= TSF_OPERAND;
|
||||||
|
tt = js_GetToken(cx, ts);
|
||||||
|
ts->flags &= ~TSF_OPERAND;
|
||||||
|
} while (tt == TOK_CATCH);
|
||||||
}
|
}
|
||||||
pn->pn_kid2 = catchList;
|
pn->pn_kid2 = catchList;
|
||||||
|
|
||||||
@@ -3289,6 +3285,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
|||||||
#if JS_HAS_BLOCK_SCOPE
|
#if JS_HAS_BLOCK_SCOPE
|
||||||
case TOK_LET:
|
case TOK_LET:
|
||||||
{
|
{
|
||||||
|
JSStmtInfo **sip;
|
||||||
JSObject *obj;
|
JSObject *obj;
|
||||||
JSAtom *atom;
|
JSAtom *atom;
|
||||||
|
|
||||||
@@ -3306,13 +3303,21 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a let declaration. We must convert the nearest JSStmtInfo
|
* This is a let declaration. We must convert the nearest JSStmtInfo
|
||||||
* to be our scope statement. Further let declarations in this block
|
* that is a block or a switch body to be our scope statement. Further
|
||||||
* will find this scope statement and use the same block object. If we
|
* let declarations in this block will find this scope statement and
|
||||||
* are the first let declaration in this block (i.e., when the nearest
|
* use the same block object. If we are the first let declaration in
|
||||||
* maybe-scope JSStmtInfo isn't a scope statement) then we also need
|
* this block (i.e., when the nearest maybe-scope JSStmtInfo isn't a
|
||||||
* to set tc->blockNode to be our TOK_LEXICALSCOPE.
|
* scope statement) then we also need to set tc->blockNode to be our
|
||||||
|
* TOK_LEXICALSCOPE.
|
||||||
*/
|
*/
|
||||||
stmt = FindMaybeScopeStatement(tc);
|
sip = &tc->topScopeStmt;
|
||||||
|
for (stmt = tc->topStmt; stmt; stmt = stmt->down) {
|
||||||
|
if (STMT_MAYBE_SCOPE(stmt))
|
||||||
|
break;
|
||||||
|
if (stmt == *sip)
|
||||||
|
sip = &stmt->downScope;
|
||||||
|
}
|
||||||
|
|
||||||
if (stmt && (stmt->flags & SIF_SCOPE)) {
|
if (stmt && (stmt->flags & SIF_SCOPE)) {
|
||||||
JS_ASSERT(tc->blockChain == ATOM_TO_OBJECT(stmt->atom));
|
JS_ASSERT(tc->blockChain == ATOM_TO_OBJECT(stmt->atom));
|
||||||
obj = tc->blockChain;
|
obj = tc->blockChain;
|
||||||
@@ -3346,14 +3351,27 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
|||||||
if (!atom)
|
if (!atom)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert stmt on the tc->topScopeStmt/stmtInfo.downScope linked
|
||||||
|
* list stack, if it isn't already there. If it is there, but it
|
||||||
|
* lacks the SIF_SCOPE flag, it must be a try, catch, or finally
|
||||||
|
* block.
|
||||||
|
*/
|
||||||
JS_ASSERT(!(stmt->flags & SIF_SCOPE));
|
JS_ASSERT(!(stmt->flags & SIF_SCOPE));
|
||||||
stmt->flags |= SIF_SCOPE;
|
stmt->flags |= SIF_SCOPE;
|
||||||
if (!stmt->downScope) {
|
if (stmt != *sip) {
|
||||||
stmt->downScope = tc->topScopeStmt;
|
JS_ASSERT(!stmt->downScope);
|
||||||
tc->topScopeStmt = stmt;
|
JS_ASSERT(stmt->type == STMT_BLOCK ||
|
||||||
|
stmt->type == STMT_SWITCH ||
|
||||||
|
stmt->type == STMT_TRY ||
|
||||||
|
stmt->type == STMT_FINALLY);
|
||||||
|
stmt->downScope = *sip;
|
||||||
|
*sip = stmt;
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(stmt == tc->topScopeStmt);
|
JS_ASSERT(stmt->type == STMT_CATCH);
|
||||||
|
JS_ASSERT(stmt->downScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
obj->slots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(tc->blockChain);
|
obj->slots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(tc->blockChain);
|
||||||
tc->blockChain = obj;
|
tc->blockChain = obj;
|
||||||
stmt->atom = atom;
|
stmt->atom = atom;
|
||||||
@@ -3525,7 +3543,9 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
|||||||
|
|
||||||
/* Check termination of this primitive statement. */
|
/* Check termination of this primitive statement. */
|
||||||
if (ON_CURRENT_LINE(ts, pn->pn_pos)) {
|
if (ON_CURRENT_LINE(ts, pn->pn_pos)) {
|
||||||
|
ts->flags |= TSF_OPERAND;
|
||||||
tt = js_PeekTokenSameLine(cx, ts);
|
tt = js_PeekTokenSameLine(cx, ts);
|
||||||
|
ts->flags &= ~TSF_OPERAND;
|
||||||
if (tt == TOK_ERROR)
|
if (tt == TOK_ERROR)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) {
|
if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) {
|
||||||
@@ -3572,12 +3592,12 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
|||||||
|
|
||||||
data.pn = NULL;
|
data.pn = NULL;
|
||||||
data.ts = ts;
|
data.ts = ts;
|
||||||
data.op = CURRENT_TOKEN(ts).t_op;
|
data.op = let ? JSOP_NOP : CURRENT_TOKEN(ts).t_op;
|
||||||
data.binder = let ? BindLet : BindVarOrConst;
|
data.binder = let ? BindLet : BindVarOrConst;
|
||||||
pn = NewParseNode(cx, ts, PN_LIST, tc);
|
pn = NewParseNode(cx, ts, PN_LIST, tc);
|
||||||
if (!pn)
|
if (!pn)
|
||||||
return NULL;
|
return NULL;
|
||||||
pn->pn_op = let ? JSOP_NOP : data.op;
|
pn->pn_op = data.op;
|
||||||
PN_INIT_LIST(pn);
|
PN_INIT_LIST(pn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -4160,7 +4180,9 @@ UnaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
|||||||
|
|
||||||
/* Don't look across a newline boundary for a postfix incop. */
|
/* Don't look across a newline boundary for a postfix incop. */
|
||||||
if (ON_CURRENT_LINE(ts, pn->pn_pos)) {
|
if (ON_CURRENT_LINE(ts, pn->pn_pos)) {
|
||||||
|
ts->flags |= TSF_OPERAND;
|
||||||
tt = js_PeekTokenSameLine(cx, ts);
|
tt = js_PeekTokenSameLine(cx, ts);
|
||||||
|
ts->flags &= ~TSF_OPERAND;
|
||||||
if (tt == TOK_INC || tt == TOK_DEC) {
|
if (tt == TOK_INC || tt == TOK_DEC) {
|
||||||
(void) js_GetToken(cx, ts);
|
(void) js_GetToken(cx, ts);
|
||||||
pn2 = NewParseNode(cx, ts, PN_UNARY, tc);
|
pn2 = NewParseNode(cx, ts, PN_UNARY, tc);
|
||||||
@@ -4260,9 +4282,8 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||||||
pn2->pn_arity = PN_UNARY;
|
pn2->pn_arity = PN_UNARY;
|
||||||
pn2->pn_kid = pn;
|
pn2->pn_kid = pn;
|
||||||
pn2->pn_next = NULL;
|
pn2->pn_next = NULL;
|
||||||
#if JS_HAS_XML_SUPPORT
|
|
||||||
pn2->pn_ts = ts;
|
pn2->pn_ts = ts;
|
||||||
#endif
|
pn2->pn_source = NULL;
|
||||||
pn = pn2;
|
pn = pn2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5098,7 +5119,6 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||||||
JSTokenType tt, JSBool afterDot)
|
JSTokenType tt, JSBool afterDot)
|
||||||
{
|
{
|
||||||
JSParseNode *pn, *pn2, *pn3;
|
JSParseNode *pn, *pn2, *pn3;
|
||||||
JSBool afterComma;
|
|
||||||
JSOp op;
|
JSOp op;
|
||||||
|
|
||||||
#if JS_HAS_SHARP_VARS
|
#if JS_HAS_SHARP_VARS
|
||||||
@@ -5313,13 +5333,10 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||||||
#if JS_HAS_DESTRUCTURING
|
#if JS_HAS_DESTRUCTURING
|
||||||
case TOK_LB:
|
case TOK_LB:
|
||||||
case TOK_LC:
|
case TOK_LC:
|
||||||
pnlet = PrimaryExpr(cx, ts, tc, tt, JS_FALSE);
|
pnlet = DestructuringExpr(cx, &data, tc, tt);
|
||||||
if (!pnlet)
|
if (!pnlet)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!CheckDestructuring(cx, &data, pnlet, NULL, tc))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Destructuring requires [key, value] enumeration. */
|
/* Destructuring requires [key, value] enumeration. */
|
||||||
if (pn2->pn_op != JSOP_FOREACH)
|
if (pn2->pn_op != JSOP_FOREACH)
|
||||||
pn2->pn_op = JSOP_FOREACHKEYVAL;
|
pn2->pn_op = JSOP_FOREACHKEYVAL;
|
||||||
@@ -5408,6 +5425,9 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
case TOK_LC:
|
case TOK_LC:
|
||||||
|
{
|
||||||
|
JSBool afterComma;
|
||||||
|
|
||||||
pn = NewParseNode(cx, ts, PN_LIST, tc);
|
pn = NewParseNode(cx, ts, PN_LIST, tc);
|
||||||
if (!pn)
|
if (!pn)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -5524,6 +5544,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||||||
end_obj_init:
|
end_obj_init:
|
||||||
pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
|
pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
|
||||||
return pn;
|
return pn;
|
||||||
|
}
|
||||||
|
|
||||||
#if JS_HAS_SHARP_VARS
|
#if JS_HAS_SHARP_VARS
|
||||||
case TOK_DEFSHARP:
|
case TOK_DEFSHARP:
|
||||||
|
|||||||
@@ -315,9 +315,8 @@ struct JSParseNode {
|
|||||||
jsdouble dval; /* aligned numeric literal value */
|
jsdouble dval; /* aligned numeric literal value */
|
||||||
} pn_u;
|
} pn_u;
|
||||||
JSParseNode *pn_next; /* to align dval and pn_u on RISCs */
|
JSParseNode *pn_next; /* to align dval and pn_u on RISCs */
|
||||||
#if JS_HAS_XML_SUPPORT
|
JSTokenStream *pn_ts; /* token stream for error reports */
|
||||||
JSTokenStream *pn_ts; /* token stream for XML error reports */
|
JSAtom *pn_source; /* saved source for decompilation */
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define pn_funAtom pn_u.func.funAtom
|
#define pn_funAtom pn_u.func.funAtom
|
||||||
|
|||||||
@@ -190,10 +190,14 @@ GrowTokenBuf(JSStringBuffer *sb, size_t newlength)
|
|||||||
JS_ARENA_ALLOCATE_CAST(base, jschar *, pool, tbsize);
|
JS_ARENA_ALLOCATE_CAST(base, jschar *, pool, tbsize);
|
||||||
} else {
|
} else {
|
||||||
length = PTRDIFF(sb->limit, base, jschar);
|
length = PTRDIFF(sb->limit, base, jschar);
|
||||||
|
if ((size_t)length >= ~(size_t)0 / sizeof(jschar)) {
|
||||||
|
base = NULL;
|
||||||
|
} else {
|
||||||
tbsize = (length + 1) * sizeof(jschar);
|
tbsize = (length + 1) * sizeof(jschar);
|
||||||
length += length + 1;
|
length += length + 1;
|
||||||
JS_ARENA_GROW_CAST(base, jschar *, pool, tbsize, tbsize);
|
JS_ARENA_GROW_CAST(base, jschar *, pool, tbsize, tbsize);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!base) {
|
if (!base) {
|
||||||
JS_ReportOutOfMemory(cx);
|
JS_ReportOutOfMemory(cx);
|
||||||
sb->base = STRING_BUFFER_ERROR_BASE;
|
sb->base = STRING_BUFFER_ERROR_BASE;
|
||||||
@@ -530,9 +534,7 @@ ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags,
|
|||||||
JSString *linestr = NULL;
|
JSString *linestr = NULL;
|
||||||
JSTokenStream *ts = NULL;
|
JSTokenStream *ts = NULL;
|
||||||
JSCodeGenerator *cg = NULL;
|
JSCodeGenerator *cg = NULL;
|
||||||
#if JS_HAS_XML_SUPPORT
|
|
||||||
JSParseNode *pn = NULL;
|
JSParseNode *pn = NULL;
|
||||||
#endif
|
|
||||||
JSErrorReporter onError;
|
JSErrorReporter onError;
|
||||||
JSTokenPos *tp;
|
JSTokenPos *tp;
|
||||||
JSStackFrame *fp;
|
JSStackFrame *fp;
|
||||||
@@ -560,12 +562,10 @@ ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags,
|
|||||||
case JSREPORT_CG:
|
case JSREPORT_CG:
|
||||||
cg = handle;
|
cg = handle;
|
||||||
break;
|
break;
|
||||||
#if JS_HAS_XML_SUPPORT
|
|
||||||
case JSREPORT_PN:
|
case JSREPORT_PN:
|
||||||
pn = handle;
|
pn = handle;
|
||||||
ts = pn->pn_ts;
|
ts = pn->pn_ts;
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ASSERT(!ts || ts->linebuf.limit < ts->linebuf.base + JS_LINE_LIMIT);
|
JS_ASSERT(!ts || ts->linebuf.limit < ts->linebuf.base + JS_LINE_LIMIT);
|
||||||
@@ -579,13 +579,11 @@ ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags,
|
|||||||
do {
|
do {
|
||||||
if (ts) {
|
if (ts) {
|
||||||
report->filename = ts->filename;
|
report->filename = ts->filename;
|
||||||
#if JS_HAS_XML_SUPPORT
|
|
||||||
if (pn) {
|
if (pn) {
|
||||||
report->lineno = pn->pn_pos.begin.lineno;
|
report->lineno = pn->pn_pos.begin.lineno;
|
||||||
if (report->lineno != ts->lineno)
|
if (report->lineno != ts->lineno)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
report->lineno = ts->lineno;
|
report->lineno = ts->lineno;
|
||||||
linestr = js_NewStringCopyN(cx, ts->linebuf.base,
|
linestr = js_NewStringCopyN(cx, ts->linebuf.base,
|
||||||
PTRDIFF(ts->linebuf.limit,
|
PTRDIFF(ts->linebuf.limit,
|
||||||
@@ -596,10 +594,9 @@ ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags,
|
|||||||
? JS_GetStringBytes(linestr)
|
? JS_GetStringBytes(linestr)
|
||||||
: NULL;
|
: NULL;
|
||||||
tp = &ts->tokens[(ts->cursor+ts->lookahead) & NTOKENS_MASK].pos;
|
tp = &ts->tokens[(ts->cursor+ts->lookahead) & NTOKENS_MASK].pos;
|
||||||
#if JS_HAS_XML_SUPPORT
|
|
||||||
if (pn)
|
if (pn)
|
||||||
tp = &pn->pn_pos;
|
tp = &pn->pn_pos;
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* FIXME: What should instead happen here is that we should
|
* FIXME: What should instead happen here is that we should
|
||||||
* find error-tokens in userbuf, if !ts->file. That will
|
* find error-tokens in userbuf, if !ts->file. That will
|
||||||
@@ -629,8 +626,8 @@ ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we can't find out where the error was based on the current frame,
|
* If we can't find out where the error was based on the current
|
||||||
* see if the next frame has a script/pc combo we can use.
|
* frame, see if the next frame has a script/pc combo we can use.
|
||||||
*/
|
*/
|
||||||
for (fp = cx->fp; fp; fp = fp->down) {
|
for (fp = cx->fp; fp; fp = fp->down) {
|
||||||
if (fp->script && fp->pc) {
|
if (fp->script && fp->pc) {
|
||||||
|
|||||||
@@ -1427,8 +1427,12 @@ js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
|
|||||||
* Special case: function definition needs no line number note because
|
* Special case: function definition needs no line number note because
|
||||||
* the function's script contains its starting line number.
|
* the function's script contains its starting line number.
|
||||||
*/
|
*/
|
||||||
if (*pc == JSOP_DEFFUN) {
|
if (*pc == JSOP_DEFFUN ||
|
||||||
atom = GET_ATOM(cx, script, pc);
|
(*pc == JSOP_LITOPX && pc[1 + LITERAL_INDEX_LEN] == JSOP_DEFFUN)) {
|
||||||
|
atom = js_GetAtom(cx, &script->atomMap,
|
||||||
|
(*pc == JSOP_DEFFUN)
|
||||||
|
? GET_ATOM_INDEX(pc)
|
||||||
|
: GET_LITERAL_INDEX(pc));
|
||||||
fun = (JSFunction *) JS_GetPrivate(cx, ATOM_TO_OBJECT(atom));
|
fun = (JSFunction *) JS_GetPrivate(cx, ATOM_TO_OBJECT(atom));
|
||||||
JS_ASSERT(FUN_INTERPRETED(fun));
|
JS_ASSERT(FUN_INTERPRETED(fun));
|
||||||
return fun->u.i.script->lineno;
|
return fun->u.i.script->lineno;
|
||||||
|
|||||||
Reference in New Issue
Block a user