зеркало из https://github.com/mozilla/pjs.git
Final js1.8 feature: sugar for object destructuring (404734, r=mrbkap).
This commit is contained in:
Родитель
ad19ea8cb7
Коммит
3928a49838
|
@ -303,3 +303,4 @@ MSG_DEF(JSMSG_BAD_DELETE_OPERAND, 220, 0, JSEXN_SYNTAXERR, "invalid delete o
|
|||
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_LET_DECL_NOT_IN_BLOCK, 223, 0, JSEXN_SYNTAXERR, "let declaration not directly within block")
|
||||
MSG_DEF(JSMSG_BAD_OBJECT_INIT, 224, 0, JSEXN_SYNTAXERR, "invalid object initializer")
|
||||
|
|
|
@ -230,7 +230,7 @@
|
|||
#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */
|
||||
#define JS_HAS_GENERATORS 1 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 1 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
#define JS_HAS_DESTRUCTURING 2 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
#define JS_HAS_GENERATOR_EXPRS 1 /* has (expr for (lhs in iterable)) */
|
||||
#define JS_HAS_EXPR_CLOSURES 1 /* has function (formals) listexpr */
|
||||
|
||||
|
@ -244,3 +244,5 @@
|
|||
#define JS_HAS_RESERVED_JAVA_KEYWORDS 1
|
||||
#define JS_HAS_RESERVED_ECMA_KEYWORDS 1
|
||||
|
||||
/* Feature-test macro for evolving destructuring support. */
|
||||
#define JS_HAS_DESTRUCTURING_SHORTHAND (JS_HAS_DESTRUCTURING == 2)
|
||||
|
|
|
@ -6141,6 +6141,13 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
break;
|
||||
|
||||
case TOK_RC:
|
||||
#if JS_HAS_DESTRUCTURING_SHORTHAND
|
||||
if (pn->pn_extra & PNX_SHORTHAND) {
|
||||
js_ReportCompileErrorNumber(cx, CG_TS(cg), pn, JSREPORT_ERROR,
|
||||
JSMSG_BAD_OBJECT_INIT);
|
||||
return JS_FALSE;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Emit code for {p:a, '%q':b, 2:c} of the form:
|
||||
* t = new Object; t.p = a; t['%q'] = b; t[2] = c; t;
|
||||
|
|
|
@ -1307,7 +1307,7 @@ DecompileDestructuringLHS(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
|
|||
static jsbytecode *
|
||||
DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
|
||||
{
|
||||
ptrdiff_t head, todo;
|
||||
ptrdiff_t head;
|
||||
JSContext *cx;
|
||||
JSPrinter *jp;
|
||||
JSOp op, saveop;
|
||||
|
@ -1341,6 +1341,10 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
|
|||
lasti = -1;
|
||||
|
||||
while (pc < endpc) {
|
||||
#if JS_HAS_DESTRUCTURING_SHORTHAND
|
||||
ptrdiff_t nameoff = -1;
|
||||
#endif
|
||||
|
||||
LOAD_OP_DATA(pc);
|
||||
saveop = op;
|
||||
|
||||
|
@ -1393,6 +1397,9 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
|
|||
*OFF2STR(&ss->sprinter, head) = '{';
|
||||
GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom);
|
||||
str = ATOM_TO_STRING(atom);
|
||||
#if JS_HAS_DESTRUCTURING_SHORTHAND
|
||||
nameoff = ss->sprinter.offset;
|
||||
#endif
|
||||
if (!QuoteString(&ss->sprinter, str,
|
||||
js_IsIdentifier(str) ? 0 : (jschar)'\'')) {
|
||||
return NULL;
|
||||
|
@ -1417,6 +1424,37 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
|
|||
pc = DecompileDestructuringLHS(ss, pc, endpc, &hole);
|
||||
if (!pc)
|
||||
return NULL;
|
||||
|
||||
#if JS_HAS_DESTRUCTURING_SHORTHAND
|
||||
if (nameoff >= 0) {
|
||||
ptrdiff_t offset, initlen;
|
||||
|
||||
offset = ss->sprinter.offset;
|
||||
LOCAL_ASSERT(*OFF2STR(&ss->sprinter, offset) == '\0');
|
||||
initlen = offset - nameoff;
|
||||
LOCAL_ASSERT(initlen >= 4);
|
||||
|
||||
/* Early check to rule out odd "name: lval" length. */
|
||||
if (((size_t)initlen & 1) == 0) {
|
||||
size_t namelen;
|
||||
const char *name;
|
||||
|
||||
/*
|
||||
* Even "name: lval" string length: check for "x: x" and the
|
||||
* like, and apply the shorthand if we can.
|
||||
*/
|
||||
namelen = (size_t)(initlen - 2) >> 1;
|
||||
name = OFF2STR(&ss->sprinter, nameoff);
|
||||
if (!strncmp(name + namelen, ": ", 2) &&
|
||||
!strncmp(name, name + namelen + 2, namelen)) {
|
||||
offset -= namelen + 2;
|
||||
*OFF2STR(&ss->sprinter, offset) = '\0';
|
||||
ss->sprinter.offset = offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pc == endpc || *pc != JSOP_DUP)
|
||||
break;
|
||||
|
||||
|
@ -1437,8 +1475,7 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
|
|||
|
||||
out:
|
||||
lval = OFF2STR(&ss->sprinter, head);
|
||||
todo = SprintPut(&ss->sprinter, (*lval == '[') ? "]" : "}", 1);
|
||||
if (todo < 0)
|
||||
if (SprintPut(&ss->sprinter, (*lval == '[') ? "]" : "}", 1) < 0)
|
||||
return NULL;
|
||||
return pc;
|
||||
}
|
||||
|
@ -3504,7 +3541,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
atom = GetSlotAtom(ss->printer, op == JSOP_GETARGPROP,
|
||||
GET_UINT16(pc));
|
||||
LOCAL_ASSERT(atom);
|
||||
JS_ASSERT(ATOM_IS_STRING(atom));
|
||||
LOCAL_ASSERT(ATOM_IS_STRING(atom));
|
||||
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
||||
if (!lval || !PushOff(ss, STR2OFF(&ss->sprinter, lval), op))
|
||||
return NULL;
|
||||
|
@ -3669,7 +3706,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
case JSOP_DOUBLE:
|
||||
LOAD_ATOM(0);
|
||||
val = ATOM_KEY(atom);
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE(val));
|
||||
LOCAL_ASSERT(JSVAL_IS_DOUBLE(val));
|
||||
todo = SprintDoubleValue(&ss->sprinter, val, &saveop);
|
||||
break;
|
||||
|
||||
|
@ -3820,7 +3857,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
|
||||
case JSOP_OBJECT:
|
||||
LOAD_OBJECT(0);
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
|
||||
LOCAL_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
|
||||
goto do_regexp;
|
||||
|
||||
case JSOP_REGEXP:
|
||||
|
@ -4104,7 +4141,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
case JSOP_NEWINIT:
|
||||
{
|
||||
i = GET_INT8(pc);
|
||||
JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
|
||||
LOCAL_ASSERT(i == JSProto_Array || i == JSProto_Object);
|
||||
|
||||
todo = ss->sprinter.offset;
|
||||
#if JS_HAS_SHARP_VARS
|
||||
|
|
|
@ -5447,6 +5447,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||
case TOK_LC:
|
||||
{
|
||||
JSBool afterComma;
|
||||
JSParseNode *pnval;
|
||||
|
||||
pn = NewParseNode(cx, ts, PN_LIST, tc);
|
||||
if (!pn)
|
||||
|
@ -5535,13 +5536,38 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tt != TOK_COLON) {
|
||||
js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
|
||||
JSMSG_COLON_AFTER_ID);
|
||||
return NULL;
|
||||
#if JS_HAS_DESTRUCTURING_SHORTHAND
|
||||
if (tt != TOK_COMMA && tt != TOK_RC) {
|
||||
#endif
|
||||
js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
|
||||
JSMSG_COLON_AFTER_ID);
|
||||
return NULL;
|
||||
#if JS_HAS_DESTRUCTURING_SHORTHAND
|
||||
}
|
||||
|
||||
/*
|
||||
* Support, e.g., |var {x, y} = o| as destructuring shorthand
|
||||
* for |var {x: x, y: y} = o|, per proposed JS2/ES4 for JS1.8.
|
||||
*/
|
||||
js_UngetToken(ts);
|
||||
pn->pn_extra |= PNX_SHORTHAND;
|
||||
pnval = pn3;
|
||||
if (pnval->pn_type == TOK_NAME) {
|
||||
pnval->pn_arity = PN_NAME;
|
||||
pnval->pn_expr = NULL;
|
||||
pnval->pn_slot = -1;
|
||||
pnval->pn_const = JS_FALSE;
|
||||
}
|
||||
op = JSOP_NOP;
|
||||
#endif
|
||||
} else {
|
||||
op = CURRENT_TOKEN(ts).t_op;
|
||||
pnval = AssignExpr(cx, ts, tc);
|
||||
}
|
||||
op = CURRENT_TOKEN(ts).t_op;
|
||||
pn2 = NewBinary(cx, TOK_COLON, op, pn3, AssignExpr(cx, ts, tc), tc);
|
||||
|
||||
pn2 = NewBinary(cx, TOK_COLON, op, pn3, pnval, tc);
|
||||
#if JS_HAS_GETTER_SETTER
|
||||
skip:
|
||||
#endif
|
||||
|
|
|
@ -177,6 +177,9 @@ JS_BEGIN_EXTERN_C
|
|||
* TOK_RC list pn_head: list of pn_count TOK_COLON nodes where
|
||||
* each has pn_left: property id, pn_right: value
|
||||
* #n={...} produces TOK_DEFSHARP at head of list
|
||||
* var {x} = object destructuring shorthand shares
|
||||
* PN_NAME node for x on left and right of TOK_COLON
|
||||
* node in TOK_RC's list, has PNX_SHORTHAND flag
|
||||
* TOK_DEFSHARP unary pn_num: jsint value of n in #n=
|
||||
* pn_kid: null for #n=[...] and #n={...}, primary
|
||||
* if #n=primary for function, paren, name, object
|
||||
|
@ -309,7 +312,7 @@ struct JSParseNode {
|
|||
JSAtom *atom; /* name or label atom, null if slot */
|
||||
JSParseNode *expr; /* object or initializer */
|
||||
jsint slot; /* -1 or arg or local var slot */
|
||||
JSBool constslot; /* true for const names */
|
||||
JSBool isconst; /* true for const names */
|
||||
} name;
|
||||
struct { /* lexical scope. */
|
||||
JSParsedObjectBox *pob; /* block object */
|
||||
|
@ -349,7 +352,7 @@ struct JSParseNode {
|
|||
#define pn_atom pn_u.name.atom
|
||||
#define pn_expr pn_u.name.expr
|
||||
#define pn_slot pn_u.name.slot
|
||||
#define pn_const pn_u.name.constslot
|
||||
#define pn_const pn_u.name.isconst
|
||||
#define pn_dval pn_u.dval
|
||||
#define pn_atom2 pn_u.apair.atom2
|
||||
#define pn_pob pn_u.object.pob
|
||||
|
@ -366,6 +369,9 @@ struct JSParseNode {
|
|||
#define PNX_NEEDBRACES 0x80 /* braces necessary due to closure */
|
||||
#define PNX_FUNCDEFS 0x100 /* contains top-level function
|
||||
statements */
|
||||
#define PNX_SHORTHAND 0x200 /* shorthand syntax used, at present
|
||||
object destructuring ({x,y}) only */
|
||||
|
||||
/*
|
||||
* Move pn2 into pn, preserving pn->pn_pos and pn->pn_offset and handing off
|
||||
* any kids in pn2->pn_u, by clearing pn2.
|
||||
|
|
Загрузка…
Ссылка в новой задаче