зеркало из https://github.com/mozilla/gecko-dev.git
Track ES4 proposal by restricting let declaration to be direct child of block (408957, r=mrbkap).
This commit is contained in:
Родитель
810fc6c19f
Коммит
9744f8528f
|
@ -302,3 +302,4 @@ MSG_DEF(JSMSG_NON_LIST_XML_METHOD, 219, 2, JSEXN_TYPEERR, "cannot call {0} me
|
||||||
MSG_DEF(JSMSG_BAD_DELETE_OPERAND, 220, 0, JSEXN_SYNTAXERR, "invalid delete operand")
|
MSG_DEF(JSMSG_BAD_DELETE_OPERAND, 220, 0, JSEXN_SYNTAXERR, "invalid delete operand")
|
||||||
MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 221, 0, JSEXN_SYNTAXERR, "invalid increment/decrement operand")
|
MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 221, 0, JSEXN_SYNTAXERR, "invalid increment/decrement operand")
|
||||||
MSG_DEF(JSMSG_NULL_OR_UNDEFINED, 222, 2, JSEXN_TYPEERR, "{0} is {1}")
|
MSG_DEF(JSMSG_NULL_OR_UNDEFINED, 222, 2, JSEXN_TYPEERR, "{0} is {1}")
|
||||||
|
MSG_DEF(JSMSG_LET_DECL_NOT_IN_BLOCK, 223, 0, JSEXN_SYNTAXERR, "let declaration not directly within block")
|
||||||
|
|
|
@ -56,7 +56,7 @@ JS_BEGIN_EXTERN_C
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NB: If you add enumerators for scope statements, add them between STMT_WITH
|
* NB: If you add enumerators for scope statements, add them between STMT_WITH
|
||||||
* and STMT_CATCH, or you will break the STMT_TYPE_IS_SCOPE macro. If you add
|
* and STMT_CATCH, or you will break the STMT_TYPE_IS_SCOPE macro. If you add
|
||||||
* non-looping statement enumerators, add them before STMT_DO_LOOP or you will
|
* non-looping statement enumerators, add them before STMT_DO_LOOP or you will
|
||||||
* break the STMT_TYPE_IS_LOOP macro.
|
* break the STMT_TYPE_IS_LOOP macro.
|
||||||
*
|
*
|
||||||
|
@ -66,10 +66,10 @@ typedef enum JSStmtType {
|
||||||
STMT_LABEL, /* labeled statement: L: s */
|
STMT_LABEL, /* labeled statement: L: s */
|
||||||
STMT_IF, /* if (then) statement */
|
STMT_IF, /* if (then) statement */
|
||||||
STMT_ELSE, /* else clause of if statement */
|
STMT_ELSE, /* else clause of if statement */
|
||||||
|
STMT_SWITCH, /* switch statement */
|
||||||
STMT_BODY, /* synthetic body of function with
|
STMT_BODY, /* synthetic body of function with
|
||||||
destructuring formal parameters */
|
destructuring formal parameters */
|
||||||
STMT_BLOCK, /* compound statement: { s1[;... sN] } */
|
STMT_BLOCK, /* compound statement: { s1[;... sN] } */
|
||||||
STMT_SWITCH, /* switch statement */
|
|
||||||
STMT_WITH, /* with statement */
|
STMT_WITH, /* with statement */
|
||||||
STMT_CATCH, /* catch block */
|
STMT_CATCH, /* catch block */
|
||||||
STMT_TRY, /* try block */
|
STMT_TRY, /* try block */
|
||||||
|
@ -87,19 +87,17 @@ typedef enum JSStmtType {
|
||||||
* A comment on the encoding of the JSStmtType enum and type-testing macros:
|
* A comment on the encoding of the JSStmtType enum and type-testing macros:
|
||||||
*
|
*
|
||||||
* STMT_TYPE_MAYBE_SCOPE tells whether a statement type is always, or may
|
* 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
|
* become, a lexical scope. Per the proposed JS2/ES4 spec, it includes only
|
||||||
* low-numbered "maybe" scope types) and excludes with (with has dynamic scope
|
* syntactic blocks: block statements and try/catch/finally statements.
|
||||||
* pending the "reformed with" in ES4/JS2). It includes all try-catch-finally
|
|
||||||
* types, which are high-numbered maybe-scope types.
|
|
||||||
*
|
*
|
||||||
* STMT_TYPE_LINKS_SCOPE tells whether a JSStmtInfo of the given type eagerly
|
* STMT_TYPE_LINKS_SCOPE tells whether a JSStmtInfo of the given type eagerly
|
||||||
* links to other scoping statement info records. It excludes the two early
|
* links to other scoping statement info records. It excludes the the "maybe"
|
||||||
* "maybe" types, block and switch, as well as the try and both finally types,
|
* type, block, as well as the try and both finally types, since try and the
|
||||||
* since try and the other trailing maybe-scope types don't need block scope
|
* other trailing maybe-scope types don't need block scope unless they contain
|
||||||
* unless they contain let declarations.
|
* let declarations.
|
||||||
*
|
*
|
||||||
* We treat with as a static scope because it prevents lexical binding from
|
* We treat WITH as a static scope because it prevents lexical binding from
|
||||||
* continuing further up the static scope chain. With the "reformed with"
|
* continuing further up the static scope chain. With the "reformed with"
|
||||||
* proposal for JS2, we'll be able to model it statically, too.
|
* proposal for JS2, we'll be able to model it statically, too.
|
||||||
*/
|
*/
|
||||||
#define STMT_TYPE_MAYBE_SCOPE(type) \
|
#define STMT_TYPE_MAYBE_SCOPE(type) \
|
||||||
|
@ -141,8 +139,8 @@ struct JSStmtInfo {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To reuse space in JSStmtInfo, rename breaks and continues for use during
|
* To reuse space in JSStmtInfo, rename breaks and continues for use during
|
||||||
* try/catch/finally code generation and backpatching. To match most common
|
* try/catch/finally code generation and backpatching. To match most common
|
||||||
* use cases, the macro argument is a struct, not a struct pointer. Only a
|
* use cases, the macro argument is a struct, not a struct pointer. Only a
|
||||||
* loop, switch, or label statement info record can have breaks and continues,
|
* loop, switch, or label statement info record can have breaks and continues,
|
||||||
* and only a for loop has an update backpatch chain, so it's safe to overlay
|
* and only a for loop has an update backpatch chain, so it's safe to overlay
|
||||||
* these for the "trying" JSStmtTypes.
|
* these for the "trying" JSStmtTypes.
|
||||||
|
@ -373,7 +371,7 @@ js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, JSParseContext *pc,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release cg->codePool, cg->notePool, and cx->tempPool to marks set by
|
* Release cg->codePool, cg->notePool, and cx->tempPool to marks set by
|
||||||
* js_InitCodeGenerator. Note that cgs are magic: they own the arena pool
|
* js_InitCodeGenerator. Note that cgs are magic: they own the arena pool
|
||||||
* "tops-of-stack" space above their codeMark, noteMark, and tempMark points.
|
* "tops-of-stack" space above their codeMark, noteMark, and tempMark points.
|
||||||
* This means you cannot alloc from tempPool and save the pointer beyond the
|
* This means you cannot alloc from tempPool and save the pointer beyond the
|
||||||
* next JS_FinishCodeGenerator.
|
* next JS_FinishCodeGenerator.
|
||||||
|
@ -445,7 +443,7 @@ js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
|
||||||
ptrdiff_t top);
|
ptrdiff_t top);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Push a block scope statement and link blockObj into tc->blockChain. To pop
|
* Push a block scope statement and link blockObj into tc->blockChain. To pop
|
||||||
* this statement info record, use js_PopStatement as usual, or if appropriate
|
* this statement info record, use js_PopStatement as usual, or if appropriate
|
||||||
* (if generating code), js_PopStatementCG.
|
* (if generating code), js_PopStatementCG.
|
||||||
*/
|
*/
|
||||||
|
@ -454,7 +452,7 @@ js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObject *blockObj,
|
||||||
ptrdiff_t top);
|
ptrdiff_t top);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pop tc->topStmt. If the top JSStmtInfo struct is not stack-allocated, it
|
* Pop tc->topStmt. If the top JSStmtInfo struct is not stack-allocated, it
|
||||||
* is up to the caller to free it.
|
* is up to the caller to free it.
|
||||||
*/
|
*/
|
||||||
extern void
|
extern void
|
||||||
|
@ -472,10 +470,10 @@ js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg);
|
||||||
* Define and lookup a primitive jsval associated with the const named by atom.
|
* Define and lookup a primitive jsval associated with the const named by atom.
|
||||||
* js_DefineCompileTimeConstant analyzes the constant-folded initializer at pn
|
* js_DefineCompileTimeConstant analyzes the constant-folded initializer at pn
|
||||||
* and saves the const's value in cg->constList, if it can be used at compile
|
* and saves the const's value in cg->constList, if it can be used at compile
|
||||||
* time. It returns true unless an error occurred.
|
* time. It returns true unless an error occurred.
|
||||||
*
|
*
|
||||||
* If the initializer's value could not be saved, js_DefineCompileTimeConstant
|
* If the initializer's value could not be saved, js_DefineCompileTimeConstant
|
||||||
* calls will return the undefined value. js_DefineCompileTimeConstant tries
|
* calls will return the undefined value. js_DefineCompileTimeConstant tries
|
||||||
* to find a const value memorized for atom, returning true with *vp set to a
|
* to find a const value memorized for atom, returning true with *vp set to a
|
||||||
* value other than undefined if the constant was found, true with *vp set to
|
* value other than undefined if the constant was found, true with *vp set to
|
||||||
* JSVAL_VOID if not found, and false on error.
|
* JSVAL_VOID if not found, and false on error.
|
||||||
|
@ -489,14 +487,14 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
|
||||||
* comprehension) named by atom, looking in tc's compile-time scopes.
|
* comprehension) named by atom, looking in tc's compile-time scopes.
|
||||||
*
|
*
|
||||||
* If a WITH statement is reached along the scope stack, return its statement
|
* If a WITH statement is reached along the scope stack, return its statement
|
||||||
* info record, so callers can tell that atom is ambiguous. If slotp is not
|
* info record, so callers can tell that atom is ambiguous. If slotp is not
|
||||||
* null, then if atom is found, set *slotp to its stack slot, otherwise to -1.
|
* null, then if atom is found, set *slotp to its stack slot, otherwise to -1.
|
||||||
* This means that if slotp is not null, all the block objects on the lexical
|
* This means that if slotp is not null, all the block objects on the lexical
|
||||||
* scope chain must have had their depth slots computed by the code generator,
|
* scope chain must have had their depth slots computed by the code generator,
|
||||||
* so the caller must be under js_EmitTree.
|
* so the caller must be under js_EmitTree.
|
||||||
*
|
*
|
||||||
* In any event, directly return the statement info record in which atom was
|
* In any event, directly return the statement info record in which atom was
|
||||||
* found. Otherwise return null.
|
* found. Otherwise return null.
|
||||||
*/
|
*/
|
||||||
extern JSStmtInfo *
|
extern JSStmtInfo *
|
||||||
js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp,
|
js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp,
|
||||||
|
@ -517,9 +515,9 @@ js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body);
|
||||||
/*
|
/*
|
||||||
* Source notes generated along with bytecode for decompiling and debugging.
|
* Source notes generated along with bytecode for decompiling and debugging.
|
||||||
* A source note is a uint8 with 5 bits of type and 3 of offset from the pc of
|
* A source note is a uint8 with 5 bits of type and 3 of offset from the pc of
|
||||||
* the previous note. If 3 bits of offset aren't enough, extended delta notes
|
* the previous note. If 3 bits of offset aren't enough, extended delta notes
|
||||||
* (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits
|
* (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits
|
||||||
* are emitted before the next note. Some notes have operand offsets encoded
|
* are emitted before the next note. Some notes have operand offsets encoded
|
||||||
* immediately after them, in note bytes or byte-triples.
|
* immediately after them, in note bytes or byte-triples.
|
||||||
*
|
*
|
||||||
* Source Note Extended Delta
|
* Source Note Extended Delta
|
||||||
|
@ -536,8 +534,8 @@ js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body);
|
||||||
* Note on adding new source notes: every pair of bytecodes (A, B) where A and
|
* 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
|
* 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
|
* 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
|
* arity, offsetBias, and isSpanDep initializers in js_SrcNoteSpec. This is
|
||||||
* why SRC_IF and SRC_INITPROP have the same value below. For bad historical
|
* 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
|
* reasons, some bytecodes below that could be overlayed have not been, but
|
||||||
* before using SRC_EXTENDED, consider compressing the existing note types.
|
* before using SRC_EXTENDED, consider compressing the existing note types.
|
||||||
*
|
*
|
||||||
|
@ -588,7 +586,7 @@ typedef enum JSSrcNoteType {
|
||||||
} JSSrcNoteType;
|
} JSSrcNoteType;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constants for the SRC_DECL source note. Note that span-dependent bytecode
|
* Constants for the SRC_DECL source note. Note that span-dependent bytecode
|
||||||
* selection means that any SRC_DECL offset greater than SRC_DECL_LET may need
|
* selection means that any SRC_DECL offset greater than SRC_DECL_LET may need
|
||||||
* to be adjusted, but these "offsets" are too small to span a span-dependent
|
* to be adjusted, but these "offsets" are too small to span a span-dependent
|
||||||
* instruction, so can be used to denote distinct declaration syntaxes to the
|
* instruction, so can be used to denote distinct declaration syntaxes to the
|
||||||
|
@ -662,8 +660,8 @@ extern JS_FRIEND_API(uintN) js_SrcNoteLength(jssrcnote *sn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Append a new source note of the given type (and therefore size) to cg's
|
* Append a new source note of the given type (and therefore size) to cg's
|
||||||
* notes dynamic array, updating cg->noteCount. Return the new note's index
|
* notes dynamic array, updating cg->noteCount. Return the new note's index
|
||||||
* within the array pointed at by cg->current->notes. Return -1 if out of
|
* within the array pointed at by cg->current->notes. Return -1 if out of
|
||||||
* memory.
|
* memory.
|
||||||
*/
|
*/
|
||||||
extern intN
|
extern intN
|
||||||
|
@ -696,11 +694,11 @@ js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finish taking source notes in cx's notePool, copying final notes to the new
|
* Finish taking source notes in cx's notePool, copying final notes to the new
|
||||||
* stable store allocated by the caller and passed in via notes. Return false
|
* stable store allocated by the caller and passed in via notes. Return false
|
||||||
* on malloc failure, which means this function reported an error.
|
* on malloc failure, which means this function reported an error.
|
||||||
*
|
*
|
||||||
* To compute the number of jssrcnotes to allocate and pass in via notes, use
|
* To compute the number of jssrcnotes to allocate and pass in via notes, use
|
||||||
* the CG_COUNT_FINAL_SRCNOTES macro. This macro knows a lot about details of
|
* the CG_COUNT_FINAL_SRCNOTES macro. This macro knows a lot about details of
|
||||||
* js_FinishTakingSrcNotes, SO DON'T CHANGE jsemit.c's js_FinishTakingSrcNotes
|
* js_FinishTakingSrcNotes, SO DON'T CHANGE jsemit.c's js_FinishTakingSrcNotes
|
||||||
* FUNCTION WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES!
|
* FUNCTION WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES!
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -607,14 +607,6 @@ js_QuoteString(JSContext *cx, JSString *str, jschar quote)
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
#if JS_HAS_BLOCK_SCOPE
|
|
||||||
typedef enum JSBraceState {
|
|
||||||
ALWAYS_BRACE,
|
|
||||||
MAYBE_BRACE,
|
|
||||||
DONT_BRACE
|
|
||||||
} JSBraceState;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct JSPrinter {
|
struct JSPrinter {
|
||||||
Sprinter sprinter; /* base class state */
|
Sprinter sprinter; /* base class state */
|
||||||
JSArenaPool pool; /* string allocation pool */
|
JSArenaPool pool; /* string allocation pool */
|
||||||
|
@ -625,10 +617,6 @@ struct JSPrinter {
|
||||||
jsbytecode *dvgfence; /* js_DecompileValueGenerator fencepost */
|
jsbytecode *dvgfence; /* js_DecompileValueGenerator fencepost */
|
||||||
JSFunction *fun; /* interpreted function */
|
JSFunction *fun; /* interpreted function */
|
||||||
JSAtom **localNames; /* argument and variable names */
|
JSAtom **localNames; /* argument and variable names */
|
||||||
#if JS_HAS_BLOCK_SCOPE
|
|
||||||
JSBraceState braceState; /* remove braces around let declaration */
|
|
||||||
ptrdiff_t spaceOffset; /* -1 or offset of space before maybe-{ */
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -655,10 +643,6 @@ JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
|
||||||
jp->grouped = (indent & JS_IN_GROUP_CONTEXT) != 0;
|
jp->grouped = (indent & JS_IN_GROUP_CONTEXT) != 0;
|
||||||
jp->script = NULL;
|
jp->script = NULL;
|
||||||
jp->dvgfence = NULL;
|
jp->dvgfence = NULL;
|
||||||
#if JS_HAS_BLOCK_SCOPE
|
|
||||||
jp->braceState = ALWAYS_BRACE;
|
|
||||||
jp->spaceOffset = -1;
|
|
||||||
#endif
|
|
||||||
jp->fun = fun;
|
jp->fun = fun;
|
||||||
if (!fun || !FUN_INTERPRETED(fun) || fun->nargs + fun->u.i.nvars == 0) {
|
if (!fun || !FUN_INTERPRETED(fun) || fun->nargs + fun->u.i.nvars == 0) {
|
||||||
jp->localNames = NULL;
|
jp->localNames = NULL;
|
||||||
|
@ -712,55 +696,6 @@ VarPrefix(jssrcnote *sn)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !JS_HAS_BLOCK_SCOPE
|
|
||||||
# define SET_MAYBE_BRACE(jp) jp
|
|
||||||
# define CLEAR_MAYBE_BRACE(jp) jp
|
|
||||||
# define MAYBE_SET_DONT_BRACE(jp,pc,endpc,rval) /* nothing */
|
|
||||||
#else
|
|
||||||
# define SET_MAYBE_BRACE(jp) ((jp)->braceState = MAYBE_BRACE, (jp))
|
|
||||||
# define CLEAR_MAYBE_BRACE(jp) ((jp)->braceState = ALWAYS_BRACE, (jp))
|
|
||||||
# define MAYBE_SET_DONT_BRACE MaybeSetDontBrace
|
|
||||||
|
|
||||||
static void
|
|
||||||
SetDontBrace(JSPrinter *jp)
|
|
||||||
{
|
|
||||||
ptrdiff_t offset;
|
|
||||||
const char *bp;
|
|
||||||
|
|
||||||
/* When not pretty-printing, newline after brace is chopped. */
|
|
||||||
JS_ASSERT(jp->spaceOffset < 0);
|
|
||||||
offset = jp->sprinter.offset - (jp->pretty ? 3 : 2);
|
|
||||||
|
|
||||||
/* The shortest case is "if (x) {". */
|
|
||||||
JS_ASSERT(offset >= 6);
|
|
||||||
bp = jp->sprinter.base;
|
|
||||||
if (bp[offset+0] == ' ' && bp[offset+1] == '{') {
|
|
||||||
JS_ASSERT(!jp->pretty || bp[offset+2] == '\n');
|
|
||||||
jp->spaceOffset = offset;
|
|
||||||
jp->braceState = DONT_BRACE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If a let declaration is the only child of a control structure that does not
|
|
||||||
* require braces, it must not be braced. If it were braced explicitly, then it
|
|
||||||
* would be bracketed by JSOP_ENTERBLOCK/JSOP_LEAVEBLOCK.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
MaybeSetDontBrace(JSPrinter *jp, jsbytecode *pc, jsbytecode *endpc,
|
|
||||||
const char *rval)
|
|
||||||
{
|
|
||||||
JS_ASSERT(*pc == JSOP_POP || *pc == JSOP_POPV || *pc == JSOP_POPN);
|
|
||||||
|
|
||||||
if (jp->braceState == MAYBE_BRACE &&
|
|
||||||
pc + js_CodeSpec[*pc].length == endpc &&
|
|
||||||
!strncmp(rval, var_prefix[SRC_DECL_LET], 4) &&
|
|
||||||
rval[4] != '(') {
|
|
||||||
SetDontBrace(jp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
int
|
||||||
js_printf(JSPrinter *jp, const char *format, ...)
|
js_printf(JSPrinter *jp, const char *format, ...)
|
||||||
{
|
{
|
||||||
|
@ -776,46 +711,6 @@ js_printf(JSPrinter *jp, const char *format, ...)
|
||||||
/* If pretty-printing, expand magic tab into a run of jp->indent spaces. */
|
/* If pretty-printing, expand magic tab into a run of jp->indent spaces. */
|
||||||
if (*format == '\t') {
|
if (*format == '\t') {
|
||||||
format++;
|
format++;
|
||||||
|
|
||||||
#if JS_HAS_BLOCK_SCOPE
|
|
||||||
if (*format == '}' && jp->braceState != ALWAYS_BRACE) {
|
|
||||||
JSBraceState braceState;
|
|
||||||
|
|
||||||
braceState = jp->braceState;
|
|
||||||
jp->braceState = ALWAYS_BRACE;
|
|
||||||
if (braceState == DONT_BRACE) {
|
|
||||||
ptrdiff_t offset, delta, from;
|
|
||||||
|
|
||||||
JS_ASSERT(format[1] == '\n' || format[1] == ' ');
|
|
||||||
offset = jp->spaceOffset;
|
|
||||||
JS_ASSERT(offset >= 6);
|
|
||||||
|
|
||||||
/* Replace " {\n" at the end of jp->sprinter with "\n". */
|
|
||||||
bp = jp->sprinter.base;
|
|
||||||
if (bp[offset+0] == ' ' && bp[offset+1] == '{') {
|
|
||||||
delta = 2;
|
|
||||||
if (jp->pretty) {
|
|
||||||
/* If pretty, we don't have to worry about 'else'. */
|
|
||||||
JS_ASSERT(bp[offset+2] == '\n');
|
|
||||||
} else if (bp[offset-1] != ')') {
|
|
||||||
/* Must keep ' ' to avoid 'dolet' or 'elselet'. */
|
|
||||||
++offset;
|
|
||||||
delta = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
from = offset + delta;
|
|
||||||
memmove(bp + offset, bp + from, jp->sprinter.offset - from);
|
|
||||||
jp->sprinter.offset -= delta;
|
|
||||||
jp->spaceOffset = -1;
|
|
||||||
|
|
||||||
format += 2;
|
|
||||||
if (*format == '\0')
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (jp->pretty && Sprint(&jp->sprinter, "%*s", jp->indent, "") < 0)
|
if (jp->pretty && Sprint(&jp->sprinter, "%*s", jp->indent, "") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1081,7 +976,7 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
|
||||||
off = isCondSwitch ? GetOff(ss, ss->top-1) : PopOff(ss, JSOP_NOP);
|
off = isCondSwitch ? GetOff(ss, ss->top-1) : PopOff(ss, JSOP_NOP);
|
||||||
lval = OFF2STR(&ss->sprinter, off);
|
lval = OFF2STR(&ss->sprinter, off);
|
||||||
|
|
||||||
js_printf(CLEAR_MAYBE_BRACE(jp), "\tswitch (%s) {\n", lval);
|
js_printf(jp, "\tswitch (%s) {\n", lval);
|
||||||
|
|
||||||
if (tableLength) {
|
if (tableLength) {
|
||||||
diff = table[0].offset - defaultOffset;
|
diff = table[0].offset - defaultOffset;
|
||||||
|
@ -1970,7 +1865,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
tail = js_GetSrcNoteOffset(sn, 0) - 1;
|
tail = js_GetSrcNoteOffset(sn, 0) - 1;
|
||||||
LOCAL_ASSERT(pc[tail] == JSOP_IFNE ||
|
LOCAL_ASSERT(pc[tail] == JSOP_IFNE ||
|
||||||
pc[tail] == JSOP_IFNEX);
|
pc[tail] == JSOP_IFNEX);
|
||||||
js_printf(SET_MAYBE_BRACE(jp), "\tdo {\n");
|
js_printf(jp, "\tdo {\n");
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
DECOMPILE_CODE(pc, tail);
|
DECOMPILE_CODE(pc, tail);
|
||||||
jp->indent -= 4;
|
jp->indent -= 4;
|
||||||
|
@ -2012,7 +1907,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do the loop body. */
|
/* Do the loop body. */
|
||||||
js_printf(SET_MAYBE_BRACE(jp), ") {\n");
|
js_printf(jp, ") {\n");
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
oplen = (cond) ? js_CodeSpec[pc[cond]].length : 0;
|
oplen = (cond) ? js_CodeSpec[pc[cond]].length : 0;
|
||||||
DECOMPILE_CODE(pc + cond + oplen, next - cond - oplen);
|
DECOMPILE_CODE(pc + cond + oplen, next - cond - oplen);
|
||||||
|
@ -2030,7 +1925,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
if (!rval)
|
if (!rval)
|
||||||
return NULL;
|
return NULL;
|
||||||
RETRACT(&ss->sprinter, rval);
|
RETRACT(&ss->sprinter, rval);
|
||||||
js_printf(CLEAR_MAYBE_BRACE(jp), "\t%s:\n", rval);
|
js_printf(jp, "\t%s:\n", rval);
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2040,7 +1935,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
if (!rval)
|
if (!rval)
|
||||||
return NULL;
|
return NULL;
|
||||||
RETRACT(&ss->sprinter, rval);
|
RETRACT(&ss->sprinter, rval);
|
||||||
js_printf(CLEAR_MAYBE_BRACE(jp), "\t%s: {\n", rval);
|
js_printf(jp, "\t%s: {\n", rval);
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2069,7 +1964,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SRC_BRACE:
|
case SRC_BRACE:
|
||||||
js_printf(CLEAR_MAYBE_BRACE(jp), "\t{\n");
|
js_printf(jp, "\t{\n");
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
len = js_GetSrcNoteOffset(sn, 0);
|
len = js_GetSrcNoteOffset(sn, 0);
|
||||||
DECOMPILE_CODE(pc + oplen, len - oplen);
|
DECOMPILE_CODE(pc + oplen, len - oplen);
|
||||||
|
@ -2138,14 +2033,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JSOP_TRY:
|
case JSOP_TRY:
|
||||||
js_printf(CLEAR_MAYBE_BRACE(jp), "\ttry {\n");
|
js_printf(jp, "\ttry {\n");
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
todo = -2;
|
todo = -2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JSOP_FINALLY:
|
case JSOP_FINALLY:
|
||||||
jp->indent -= 4;
|
jp->indent -= 4;
|
||||||
js_printf(CLEAR_MAYBE_BRACE(jp), "\t} finally {\n");
|
js_printf(jp, "\t} finally {\n");
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2296,10 +2191,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
* If control flow reaches this point with todo still -2,
|
* If control flow reaches this point with todo still -2,
|
||||||
* just print rval as an expression statement.
|
* just print rval as an expression statement.
|
||||||
*/
|
*/
|
||||||
if (todo == -2) {
|
if (todo == -2)
|
||||||
MAYBE_SET_DONT_BRACE(jp, pc, endpc, rval);
|
|
||||||
js_printf(jp, "\t%s;\n", rval);
|
js_printf(jp, "\t%s;\n", rval);
|
||||||
}
|
|
||||||
end_popn:
|
end_popn:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2378,8 +2271,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
#endif
|
#endif
|
||||||
len = js_GetSrcNoteOffset(sn, 0);
|
len = js_GetSrcNoteOffset(sn, 0);
|
||||||
if (pc[len] == JSOP_LEAVEBLOCK) {
|
if (pc[len] == JSOP_LEAVEBLOCK) {
|
||||||
js_printf(CLEAR_MAYBE_BRACE(jp), "\tlet (%s) {\n",
|
js_printf(jp, "\tlet (%s) {\n", POP_STR());
|
||||||
POP_STR());
|
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
DECOMPILE_CODE(pc, len);
|
DECOMPILE_CODE(pc, len);
|
||||||
jp->indent -= 4;
|
jp->indent -= 4;
|
||||||
|
@ -2422,7 +2314,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
* not appear in the decompiler's output.
|
* not appear in the decompiler's output.
|
||||||
*/
|
*/
|
||||||
if (*rval != '\0' && (rval[0] != '/' || rval[1] != '*')) {
|
if (*rval != '\0' && (rval[0] != '/' || rval[1] != '*')) {
|
||||||
MAYBE_SET_DONT_BRACE(jp, pc, endpc, rval);
|
|
||||||
js_printf(jp,
|
js_printf(jp,
|
||||||
(*rval == '{' ||
|
(*rval == '{' ||
|
||||||
(strncmp(rval, js_function_str, 8) == 0 &&
|
(strncmp(rval, js_function_str, 8) == 0 &&
|
||||||
|
@ -2451,7 +2342,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
case JSOP_ENTERWITH:
|
case JSOP_ENTERWITH:
|
||||||
LOCAL_ASSERT(!js_GetSrcNote(jp->script, pc));
|
LOCAL_ASSERT(!js_GetSrcNote(jp->script, pc));
|
||||||
rval = POP_STR();
|
rval = POP_STR();
|
||||||
js_printf(SET_MAYBE_BRACE(jp), "\twith (%s) {\n", rval);
|
js_printf(jp, "\twith (%s) {\n", rval);
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
todo = Sprint(&ss->sprinter, with_cookie);
|
todo = Sprint(&ss->sprinter, with_cookie);
|
||||||
break;
|
break;
|
||||||
|
@ -2505,7 +2396,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
|
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
|
||||||
#if JS_HAS_BLOCK_SCOPE
|
#if JS_HAS_BLOCK_SCOPE
|
||||||
case SRC_BRACE:
|
case SRC_BRACE:
|
||||||
js_printf(CLEAR_MAYBE_BRACE(jp), "\t{\n");
|
js_printf(jp, "\t{\n");
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
len = js_GetSrcNoteOffset(sn, 0);
|
len = js_GetSrcNoteOffset(sn, 0);
|
||||||
ok = Decompile(ss, pc + oplen, len - oplen, JSOP_NOP)
|
ok = Decompile(ss, pc + oplen, len - oplen, JSOP_NOP)
|
||||||
|
@ -2519,7 +2410,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
|
|
||||||
case SRC_CATCH:
|
case SRC_CATCH:
|
||||||
jp->indent -= 4;
|
jp->indent -= 4;
|
||||||
js_printf(CLEAR_MAYBE_BRACE(jp), "\t} catch (");
|
js_printf(jp, "\t} catch (");
|
||||||
|
|
||||||
pc2 = pc;
|
pc2 = pc;
|
||||||
pc += oplen;
|
pc += oplen;
|
||||||
|
@ -2862,7 +2753,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
tail = js_GetSrcNoteOffset(sn, 0);
|
tail = js_GetSrcNoteOffset(sn, 0);
|
||||||
DECOMPILE_CODE(pc + cond, tail - cond);
|
DECOMPILE_CODE(pc + cond, tail - cond);
|
||||||
rval = POP_STR();
|
rval = POP_STR();
|
||||||
js_printf(SET_MAYBE_BRACE(jp), "\twhile (%s) {\n", rval);
|
js_printf(jp, "\twhile (%s) {\n", rval);
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
DECOMPILE_CODE(pc + oplen, cond - oplen);
|
DECOMPILE_CODE(pc + oplen, cond - oplen);
|
||||||
jp->indent -= 4;
|
jp->indent -= 4;
|
||||||
|
@ -2926,7 +2817,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
return NULL;
|
return NULL;
|
||||||
AddParenSlop(ss);
|
AddParenSlop(ss);
|
||||||
} else {
|
} else {
|
||||||
js_printf(SET_MAYBE_BRACE(jp),
|
js_printf(jp,
|
||||||
elseif ? " if (%s) {\n" : "\tif (%s) {\n",
|
elseif ? " if (%s) {\n" : "\tif (%s) {\n",
|
||||||
rval);
|
rval);
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
|
@ -2961,7 +2852,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
goto if_again;
|
goto if_again;
|
||||||
}
|
}
|
||||||
|
|
||||||
js_printf(SET_MAYBE_BRACE(jp), " {\n");
|
js_printf(jp, " {\n");
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
DECOMPILE_CODE(pc + oplen, len - oplen);
|
DECOMPILE_CODE(pc + oplen, len - oplen);
|
||||||
}
|
}
|
||||||
|
@ -3155,8 +3046,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
AddParenSlop(ss);
|
AddParenSlop(ss);
|
||||||
DECOMPILE_CODE(pc + oplen, tail - oplen);
|
DECOMPILE_CODE(pc + oplen, tail - oplen);
|
||||||
} else {
|
} else {
|
||||||
js_printf(SET_MAYBE_BRACE(jp), "\t%s in %s) {\n",
|
js_printf(jp, "\t%s in %s) {\n", lval, rval);
|
||||||
lval, rval);
|
|
||||||
jp->indent += 4;
|
jp->indent += 4;
|
||||||
DECOMPILE_CODE(pc + oplen, tail - oplen);
|
DECOMPILE_CODE(pc + oplen, tail - oplen);
|
||||||
jp->indent -= 4;
|
jp->indent -= 4;
|
||||||
|
|
|
@ -2254,7 +2254,7 @@ PushLexicalScope(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
||||||
{
|
{
|
||||||
JSParseNode *pn;
|
JSParseNode *pn;
|
||||||
JSObject *obj;
|
JSObject *obj;
|
||||||
JSParsedObjectBox *blockPob;
|
JSParsedObjectBox *blockpob;
|
||||||
|
|
||||||
pn = NewParseNode(cx, ts, PN_NAME, tc);
|
pn = NewParseNode(cx, ts, PN_NAME, tc);
|
||||||
if (!pn)
|
if (!pn)
|
||||||
|
@ -2264,14 +2264,14 @@ PushLexicalScope(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
blockPob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
|
blockpob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
|
||||||
if (!blockPob)
|
if (!blockpob)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
js_PushBlockScope(tc, stmtInfo, obj, -1);
|
js_PushBlockScope(tc, stmtInfo, obj, -1);
|
||||||
pn->pn_type = TOK_LEXICALSCOPE;
|
pn->pn_type = TOK_LEXICALSCOPE;
|
||||||
pn->pn_op = JSOP_LEAVEBLOCK;
|
pn->pn_op = JSOP_LEAVEBLOCK;
|
||||||
pn->pn_pob = blockPob;
|
pn->pn_pob = blockpob;
|
||||||
pn->pn_slot = -1;
|
pn->pn_slot = -1;
|
||||||
return pn;
|
return pn;
|
||||||
}
|
}
|
||||||
|
@ -3174,9 +3174,8 @@ 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;
|
||||||
JSParsedObjectBox *blockPob;
|
JSParsedObjectBox *blockpob;
|
||||||
|
|
||||||
/* Check for a let statement or let expression. */
|
/* Check for a let statement or let expression. */
|
||||||
if (js_PeekToken(cx, ts) == TOK_LP) {
|
if (js_PeekToken(cx, ts) == TOK_LP) {
|
||||||
|
@ -3199,12 +3198,11 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
||||||
* scope statement) then we also need to set tc->blockNode to be our
|
* scope statement) then we also need to set tc->blockNode to be our
|
||||||
* TOK_LEXICALSCOPE.
|
* TOK_LEXICALSCOPE.
|
||||||
*/
|
*/
|
||||||
sip = &tc->topScopeStmt;
|
stmt = tc->topStmt;
|
||||||
for (stmt = tc->topStmt; stmt; stmt = stmt->down) {
|
if (stmt && !STMT_MAYBE_SCOPE(stmt)) {
|
||||||
if (STMT_MAYBE_SCOPE(stmt))
|
js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
|
||||||
break;
|
JSMSG_LET_DECL_NOT_IN_BLOCK);
|
||||||
if (stmt == *sip)
|
return NULL;
|
||||||
sip = &stmt->downScope;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stmt && (stmt->flags & SIF_SCOPE)) {
|
if (stmt && (stmt->flags & SIF_SCOPE)) {
|
||||||
|
@ -3236,8 +3234,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
||||||
obj = js_NewBlockObject(cx);
|
obj = js_NewBlockObject(cx);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return NULL;
|
return NULL;
|
||||||
blockPob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
|
blockpob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
|
||||||
if (!blockPob)
|
if (!blockpob)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3248,14 +3246,13 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
||||||
*/
|
*/
|
||||||
JS_ASSERT(!(stmt->flags & SIF_SCOPE));
|
JS_ASSERT(!(stmt->flags & SIF_SCOPE));
|
||||||
stmt->flags |= SIF_SCOPE;
|
stmt->flags |= SIF_SCOPE;
|
||||||
if (stmt != *sip) {
|
if (stmt != tc->topScopeStmt) {
|
||||||
JS_ASSERT(!stmt->downScope);
|
JS_ASSERT(!stmt->downScope);
|
||||||
JS_ASSERT(stmt->type == STMT_BLOCK ||
|
JS_ASSERT(stmt->type == STMT_BLOCK ||
|
||||||
stmt->type == STMT_SWITCH ||
|
|
||||||
stmt->type == STMT_TRY ||
|
stmt->type == STMT_TRY ||
|
||||||
stmt->type == STMT_FINALLY);
|
stmt->type == STMT_FINALLY);
|
||||||
stmt->downScope = *sip;
|
stmt->downScope = tc->topScopeStmt;
|
||||||
*sip = stmt;
|
tc->topScopeStmt = stmt;
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(stmt->type == STMT_CATCH);
|
JS_ASSERT(stmt->type == STMT_CATCH);
|
||||||
JS_ASSERT(stmt->downScope);
|
JS_ASSERT(stmt->downScope);
|
||||||
|
@ -3278,7 +3275,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
||||||
pn1->pn_type = TOK_LEXICALSCOPE;
|
pn1->pn_type = TOK_LEXICALSCOPE;
|
||||||
pn1->pn_op = JSOP_LEAVEBLOCK;
|
pn1->pn_op = JSOP_LEAVEBLOCK;
|
||||||
pn1->pn_pos = tc->blockNode->pn_pos;
|
pn1->pn_pos = tc->blockNode->pn_pos;
|
||||||
pn1->pn_pob = blockPob;
|
pn1->pn_pob = blockpob;
|
||||||
pn1->pn_expr = tc->blockNode;
|
pn1->pn_expr = tc->blockNode;
|
||||||
pn1->pn_slot = -1;
|
pn1->pn_slot = -1;
|
||||||
tc->blockNode = pn1;
|
tc->blockNode = pn1;
|
||||||
|
|
|
@ -560,7 +560,8 @@ js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
|
||||||
goto report;
|
goto report;
|
||||||
tp = &pn->pn_pos;
|
tp = &pn->pn_pos;
|
||||||
} else {
|
} else {
|
||||||
tp = &ts->tokens[(ts->cursor+ts->lookahead) & NTOKENS_MASK].pos;
|
/* Point to the current token, not the next one to get. */
|
||||||
|
tp = &ts->tokens[ts->cursor].pos;
|
||||||
}
|
}
|
||||||
report.lineno = ts->lineno;
|
report.lineno = ts->lineno;
|
||||||
linelength = PTRDIFF(ts->linebuf.limit, ts->linebuf.base, jschar);
|
linelength = PTRDIFF(ts->linebuf.limit, ts->linebuf.base, jschar);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче