зеркало из https://github.com/mozilla/gecko-dev.git
Bug 699227 - Change ParseNode::getKind() to use a type separate from TokenKind, for greater clarity. r=jorendorff
--HG-- extra : rebase_source : a7a0f9028f6094a29f013aafd1eeea4b22d08fa2
This commit is contained in:
Родитель
86a6e932ad
Коммит
3486aea238
|
@ -295,7 +295,7 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
if (!pn->isKind(TOK_SEMI) || !pn->pn_kid || !TreeTypeIsXML(pn->pn_kid->getKind()))
|
if (!pn->isKind(PNK_SEMI) || !pn->pn_kid || !pn->pn_kid->isXMLItem())
|
||||||
onlyXML = false;
|
onlyXML = false;
|
||||||
#endif
|
#endif
|
||||||
bce.freeTree(pn);
|
bce.freeTree(pn);
|
||||||
|
@ -403,8 +403,7 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* FIXME: make Function format the source for a function definition. */
|
/* FIXME: make Function format the source for a function definition. */
|
||||||
tokenStream.mungeCurrentToken(TOK_NAME);
|
ParseNode *fn = FunctionNode::create(PNK_NAME, &funbce);
|
||||||
ParseNode *fn = FunctionNode::create(&funbce);
|
|
||||||
if (fn) {
|
if (fn) {
|
||||||
fn->pn_body = NULL;
|
fn->pn_body = NULL;
|
||||||
fn->pn_cookie.makeFree();
|
fn->pn_cookie.makeFree();
|
||||||
|
@ -451,7 +450,7 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin
|
||||||
pn = NULL;
|
pn = NULL;
|
||||||
} else {
|
} else {
|
||||||
if (fn->pn_body) {
|
if (fn->pn_body) {
|
||||||
JS_ASSERT(fn->pn_body->isKind(TOK_ARGSBODY));
|
JS_ASSERT(fn->pn_body->isKind(PNK_ARGSBODY));
|
||||||
fn->pn_body->append(pn);
|
fn->pn_body->append(pn);
|
||||||
fn->pn_body->pn_pos = pn->pn_pos;
|
fn->pn_body->pn_pos = pn->pn_pos;
|
||||||
pn = fn->pn_body;
|
pn = fn->pn_body;
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -52,30 +52,25 @@
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
static ParseNode *
|
static ParseNode *
|
||||||
ContainsStmt(ParseNode *pn, TokenKind tt)
|
ContainsStmt(ParseNode *pn, ParseNodeKind kind)
|
||||||
{
|
{
|
||||||
ParseNode *pn2, *pnt;
|
|
||||||
|
|
||||||
if (!pn)
|
if (!pn)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (pn->isKind(tt))
|
if (pn->isKind(kind))
|
||||||
return pn;
|
return pn;
|
||||||
switch (pn->getArity()) {
|
switch (pn->getArity()) {
|
||||||
case PN_LIST:
|
case PN_LIST:
|
||||||
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
|
for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
|
||||||
pnt = ContainsStmt(pn2, tt);
|
if (ParseNode *pnt = ContainsStmt(pn2, kind))
|
||||||
if (pnt)
|
|
||||||
return pnt;
|
return pnt;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PN_TERNARY:
|
case PN_TERNARY:
|
||||||
pnt = ContainsStmt(pn->pn_kid1, tt);
|
if (ParseNode *pnt = ContainsStmt(pn->pn_kid1, kind))
|
||||||
if (pnt)
|
|
||||||
return pnt;
|
return pnt;
|
||||||
pnt = ContainsStmt(pn->pn_kid2, tt);
|
if (ParseNode *pnt = ContainsStmt(pn->pn_kid2, kind))
|
||||||
if (pnt)
|
|
||||||
return pnt;
|
return pnt;
|
||||||
return ContainsStmt(pn->pn_kid3, tt);
|
return ContainsStmt(pn->pn_kid3, kind);
|
||||||
case PN_BINARY:
|
case PN_BINARY:
|
||||||
/*
|
/*
|
||||||
* Limit recursion if pn is a binary expression, which can't contain a
|
* Limit recursion if pn is a binary expression, which can't contain a
|
||||||
|
@ -83,18 +78,17 @@ ContainsStmt(ParseNode *pn, TokenKind tt)
|
||||||
*/
|
*/
|
||||||
if (!pn->isOp(JSOP_NOP))
|
if (!pn->isOp(JSOP_NOP))
|
||||||
return NULL;
|
return NULL;
|
||||||
pnt = ContainsStmt(pn->pn_left, tt);
|
if (ParseNode *pnt = ContainsStmt(pn->pn_left, kind))
|
||||||
if (pnt)
|
|
||||||
return pnt;
|
return pnt;
|
||||||
return ContainsStmt(pn->pn_right, tt);
|
return ContainsStmt(pn->pn_right, kind);
|
||||||
case PN_UNARY:
|
case PN_UNARY:
|
||||||
if (!pn->isOp(JSOP_NOP))
|
if (!pn->isOp(JSOP_NOP))
|
||||||
return NULL;
|
return NULL;
|
||||||
return ContainsStmt(pn->pn_kid, tt);
|
return ContainsStmt(pn->pn_kid, kind);
|
||||||
case PN_NAME:
|
case PN_NAME:
|
||||||
return ContainsStmt(pn->maybeExpr(), tt);
|
return ContainsStmt(pn->maybeExpr(), kind);
|
||||||
case PN_NAMESET:
|
case PN_NAMESET:
|
||||||
return ContainsStmt(pn->pn_tree, tt);
|
return ContainsStmt(pn->pn_tree, kind);
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -105,30 +99,30 @@ ContainsStmt(ParseNode *pn, TokenKind tt)
|
||||||
* XXX handles only strings and numbers for now
|
* XXX handles only strings and numbers for now
|
||||||
*/
|
*/
|
||||||
static JSBool
|
static JSBool
|
||||||
FoldType(JSContext *cx, ParseNode *pn, TokenKind type)
|
FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
|
||||||
{
|
{
|
||||||
if (!pn->isKind(type)) {
|
if (!pn->isKind(kind)) {
|
||||||
switch (type) {
|
switch (kind) {
|
||||||
case TOK_NUMBER:
|
case PNK_NUMBER:
|
||||||
if (pn->isKind(TOK_STRING)) {
|
if (pn->isKind(PNK_STRING)) {
|
||||||
jsdouble d;
|
jsdouble d;
|
||||||
if (!ToNumber(cx, StringValue(pn->pn_atom), &d))
|
if (!ToNumber(cx, StringValue(pn->pn_atom), &d))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
pn->pn_dval = d;
|
pn->pn_dval = d;
|
||||||
pn->setKind(TOK_NUMBER);
|
pn->setKind(PNK_NUMBER);
|
||||||
pn->setOp(JSOP_DOUBLE);
|
pn->setOp(JSOP_DOUBLE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_STRING:
|
case PNK_STRING:
|
||||||
if (pn->isKind(TOK_NUMBER)) {
|
if (pn->isKind(PNK_NUMBER)) {
|
||||||
JSString *str = js_NumberToString(cx, pn->pn_dval);
|
JSString *str = js_NumberToString(cx, pn->pn_dval);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
pn->pn_atom = js_AtomizeString(cx, str);
|
pn->pn_atom = js_AtomizeString(cx, str);
|
||||||
if (!pn->pn_atom)
|
if (!pn->pn_atom)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
pn->setKind(TOK_STRING);
|
pn->setKind(PNK_STRING);
|
||||||
pn->setOp(JSOP_STRING);
|
pn->setOp(JSOP_STRING);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -151,7 +145,7 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
|
||||||
jsdouble d, d2;
|
jsdouble d, d2;
|
||||||
int32 i, j;
|
int32 i, j;
|
||||||
|
|
||||||
JS_ASSERT(pn1->isKind(TOK_NUMBER) && pn2->isKind(TOK_NUMBER));
|
JS_ASSERT(pn1->isKind(PNK_NUMBER) && pn2->isKind(PNK_NUMBER));
|
||||||
d = pn1->pn_dval;
|
d = pn1->pn_dval;
|
||||||
d2 = pn2->pn_dval;
|
d2 = pn2->pn_dval;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -216,7 +210,7 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
|
||||||
tc->freeTree(pn1);
|
tc->freeTree(pn1);
|
||||||
if (pn2 != pn)
|
if (pn2 != pn)
|
||||||
tc->freeTree(pn2);
|
tc->freeTree(pn2);
|
||||||
pn->setKind(TOK_NUMBER);
|
pn->setKind(PNK_NUMBER);
|
||||||
pn->setOp(JSOP_DOUBLE);
|
pn->setOp(JSOP_DOUBLE);
|
||||||
pn->setArity(PN_NULLARY);
|
pn->setArity(PN_NULLARY);
|
||||||
pn->pn_dval = d;
|
pn->pn_dval = d;
|
||||||
|
@ -228,61 +222,58 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
|
||||||
static JSBool
|
static JSBool
|
||||||
FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
|
FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
|
||||||
{
|
{
|
||||||
TokenKind tt;
|
|
||||||
ParseNode **pnp, *pn1, *pn2;
|
|
||||||
JSString *accum, *str;
|
|
||||||
uint32 i, j;
|
|
||||||
|
|
||||||
JS_ASSERT(pn->isArity(PN_LIST));
|
JS_ASSERT(pn->isArity(PN_LIST));
|
||||||
tt = pn->getKind();
|
ParseNodeKind kind = pn->getKind();
|
||||||
pnp = &pn->pn_head;
|
ParseNode **pnp = &pn->pn_head;
|
||||||
pn1 = *pnp;
|
ParseNode *pn1 = *pnp;
|
||||||
accum = NULL;
|
JSString *accum = NULL;
|
||||||
str = NULL;
|
JSString *str = NULL;
|
||||||
if ((pn->pn_xflags & PNX_CANTFOLD) == 0) {
|
if ((pn->pn_xflags & PNX_CANTFOLD) == 0) {
|
||||||
if (tt == TOK_XMLETAGO)
|
if (kind == PNK_XMLETAGO)
|
||||||
accum = cx->runtime->atomState.etagoAtom;
|
accum = cx->runtime->atomState.etagoAtom;
|
||||||
else if (tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC)
|
else if (kind == PNK_XMLSTAGO || kind == PNK_XMLPTAGC)
|
||||||
accum = cx->runtime->atomState.stagoAtom;
|
accum = cx->runtime->atomState.stagoAtom;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GC Rooting here is tricky: for most of the loop, |accum| is safe via
|
* GC Rooting here is tricky: for most of the loop, |accum| is safe via
|
||||||
* the newborn string root. However, when |pn2->pn_type| is TOK_XMLCDATA,
|
* the newborn string root. However, when |pn2->getKind()| is PNK_XMLCDATA,
|
||||||
* TOK_XMLCOMMENT, or TOK_XMLPI it is knocked out of the newborn root.
|
* PNK_XMLCOMMENT, or PNK_XMLPI it is knocked out of the newborn root.
|
||||||
* Therefore, we have to add additonal protection from GC nesting under
|
* Therefore, we have to add additonal protection from GC nesting under
|
||||||
* js_ConcatStrings.
|
* js_ConcatStrings.
|
||||||
*/
|
*/
|
||||||
|
ParseNode *pn2;
|
||||||
|
uint32 i, j;
|
||||||
for (pn2 = pn1, i = j = 0; pn2; pn2 = pn2->pn_next, i++) {
|
for (pn2 = pn1, i = j = 0; pn2; pn2 = pn2->pn_next, i++) {
|
||||||
/* The parser already rejected end-tags with attributes. */
|
/* The parser already rejected end-tags with attributes. */
|
||||||
JS_ASSERT(tt != TOK_XMLETAGO || i == 0);
|
JS_ASSERT(kind != PNK_XMLETAGO || i == 0);
|
||||||
switch (pn2->getKind()) {
|
switch (pn2->getKind()) {
|
||||||
case TOK_XMLATTR:
|
case PNK_XMLATTR:
|
||||||
if (!accum)
|
if (!accum)
|
||||||
goto cantfold;
|
goto cantfold;
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case TOK_XMLNAME:
|
case PNK_XMLNAME:
|
||||||
case TOK_XMLSPACE:
|
case PNK_XMLSPACE:
|
||||||
case TOK_XMLTEXT:
|
case PNK_XMLTEXT:
|
||||||
case TOK_STRING:
|
case PNK_STRING:
|
||||||
if (pn2->isArity(PN_LIST))
|
if (pn2->isArity(PN_LIST))
|
||||||
goto cantfold;
|
goto cantfold;
|
||||||
str = pn2->pn_atom;
|
str = pn2->pn_atom;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_XMLCDATA:
|
case PNK_XMLCDATA:
|
||||||
str = js_MakeXMLCDATAString(cx, pn2->pn_atom);
|
str = js_MakeXMLCDATAString(cx, pn2->pn_atom);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_XMLCOMMENT:
|
case PNK_XMLCOMMENT:
|
||||||
str = js_MakeXMLCommentString(cx, pn2->pn_atom);
|
str = js_MakeXMLCommentString(cx, pn2->pn_atom);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_XMLPI:
|
case PNK_XMLPI:
|
||||||
str = js_MakeXMLPIString(cx, pn2->pn_pitarget, pn2->pn_pidata);
|
str = js_MakeXMLPIString(cx, pn2->pn_pitarget, pn2->pn_pidata);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
@ -291,7 +282,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
|
||||||
cantfold:
|
cantfold:
|
||||||
default:
|
default:
|
||||||
JS_ASSERT(*pnp == pn1);
|
JS_ASSERT(*pnp == pn1);
|
||||||
if ((tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC) &&
|
if ((kind == PNK_XMLSTAGO || kind == PNK_XMLPTAGC) &&
|
||||||
(i & 1) ^ (j & 1)) {
|
(i & 1) ^ (j & 1)) {
|
||||||
#ifdef DEBUG_brendanXXX
|
#ifdef DEBUG_brendanXXX
|
||||||
printf("1: %d, %d => ", i, j);
|
printf("1: %d, %d => ", i, j);
|
||||||
|
@ -306,7 +297,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
|
||||||
pn1 = tc->freeTree(pn1);
|
pn1 = tc->freeTree(pn1);
|
||||||
--pn->pn_count;
|
--pn->pn_count;
|
||||||
}
|
}
|
||||||
pn1->setKind(TOK_XMLTEXT);
|
pn1->setKind(PNK_XMLTEXT);
|
||||||
pn1->setOp(JSOP_STRING);
|
pn1->setOp(JSOP_STRING);
|
||||||
pn1->setArity(PN_NULLARY);
|
pn1->setArity(PN_NULLARY);
|
||||||
pn1->pn_atom = js_AtomizeString(cx, accum);
|
pn1->pn_atom = js_AtomizeString(cx, accum);
|
||||||
|
@ -324,7 +315,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
|
||||||
if (accum) {
|
if (accum) {
|
||||||
{
|
{
|
||||||
AutoStringRooter tvr(cx, accum);
|
AutoStringRooter tvr(cx, accum);
|
||||||
str = ((tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC) && i != 0)
|
str = ((kind == PNK_XMLSTAGO || kind == PNK_XMLPTAGC) && i != 0)
|
||||||
? js_AddAttributePart(cx, i & 1, accum, str)
|
? js_AddAttributePart(cx, i & 1, accum, str)
|
||||||
: js_ConcatStrings(cx, accum, str);
|
: js_ConcatStrings(cx, accum, str);
|
||||||
}
|
}
|
||||||
|
@ -343,9 +334,9 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
|
||||||
if (accum) {
|
if (accum) {
|
||||||
str = NULL;
|
str = NULL;
|
||||||
if ((pn->pn_xflags & PNX_CANTFOLD) == 0) {
|
if ((pn->pn_xflags & PNX_CANTFOLD) == 0) {
|
||||||
if (tt == TOK_XMLPTAGC)
|
if (kind == PNK_XMLPTAGC)
|
||||||
str = cx->runtime->atomState.ptagcAtom;
|
str = cx->runtime->atomState.ptagcAtom;
|
||||||
else if (tt == TOK_XMLSTAGO || tt == TOK_XMLETAGO)
|
else if (kind == PNK_XMLSTAGO || kind == PNK_XMLETAGO)
|
||||||
str = cx->runtime->atomState.tagcAtom;
|
str = cx->runtime->atomState.tagcAtom;
|
||||||
}
|
}
|
||||||
if (str) {
|
if (str) {
|
||||||
|
@ -359,7 +350,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
|
||||||
pn1 = tc->freeTree(pn1);
|
pn1 = tc->freeTree(pn1);
|
||||||
--pn->pn_count;
|
--pn->pn_count;
|
||||||
}
|
}
|
||||||
pn1->setKind(TOK_XMLTEXT);
|
pn1->setKind(PNK_XMLTEXT);
|
||||||
pn1->setOp(JSOP_STRING);
|
pn1->setOp(JSOP_STRING);
|
||||||
pn1->setArity(PN_NULLARY);
|
pn1->setArity(PN_NULLARY);
|
||||||
pn1->pn_atom = js_AtomizeString(cx, accum);
|
pn1->pn_atom = js_AtomizeString(cx, accum);
|
||||||
|
@ -374,13 +365,13 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
|
||||||
* Only one node under pn, and it has been folded: move pn1 onto pn
|
* Only one node under pn, and it has been folded: move pn1 onto pn
|
||||||
* unless pn is an XML root (in which case we need it to tell the code
|
* unless pn is an XML root (in which case we need it to tell the code
|
||||||
* generator to emit a JSOP_TOXML or JSOP_TOXMLLIST op). If pn is an
|
* generator to emit a JSOP_TOXML or JSOP_TOXMLLIST op). If pn is an
|
||||||
* XML root *and* it's a point-tag, rewrite it to TOK_XMLELEM to avoid
|
* XML root *and* it's a point-tag, rewrite it to PNK_XMLELEM to avoid
|
||||||
* extra "<" and "/>" bracketing at runtime.
|
* extra "<" and "/>" bracketing at runtime.
|
||||||
*/
|
*/
|
||||||
if (!(pn->pn_xflags & PNX_XMLROOT)) {
|
if (!(pn->pn_xflags & PNX_XMLROOT)) {
|
||||||
pn->become(pn1);
|
pn->become(pn1);
|
||||||
} else if (tt == TOK_XMLPTAGC) {
|
} else if (kind == PNK_XMLPTAGC) {
|
||||||
pn->setKind(TOK_XMLELEM);
|
pn->setKind(PNK_XMLELEM);
|
||||||
pn->setOp(JSOP_TOXML);
|
pn->setOp(JSOP_TOXML);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,7 +403,7 @@ Boolish(ParseNode *pn)
|
||||||
if (pn->pn_count != 1)
|
if (pn->pn_count != 1)
|
||||||
return Unknown;
|
return Unknown;
|
||||||
ParseNode *pn2 = pn->pn_head;
|
ParseNode *pn2 = pn->pn_head;
|
||||||
if (!pn2->isKind(TOK_FUNCTION))
|
if (!pn2->isKind(PNK_FUNCTION))
|
||||||
return Unknown;
|
return Unknown;
|
||||||
if (!(pn2->pn_funbox->tcflags & TCF_GENEXP_LAMBDA))
|
if (!(pn2->pn_funbox->tcflags & TCF_GENEXP_LAMBDA))
|
||||||
return Unknown;
|
return Unknown;
|
||||||
|
@ -460,11 +451,11 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
case PN_LIST:
|
case PN_LIST:
|
||||||
{
|
{
|
||||||
/* Propagate inCond through logical connectives. */
|
/* Propagate inCond through logical connectives. */
|
||||||
bool cond = inCond && (pn->isKind(TOK_OR) || pn->isKind(TOK_AND));
|
bool cond = inCond && (pn->isKind(PNK_OR) || pn->isKind(PNK_AND));
|
||||||
|
|
||||||
/* Don't fold a parenthesized call expression. See bug 537673. */
|
/* Don't fold a parenthesized call expression. See bug 537673. */
|
||||||
pn1 = pn2 = pn->pn_head;
|
pn1 = pn2 = pn->pn_head;
|
||||||
if ((pn->isKind(TOK_LP) || pn->isKind(TOK_NEW)) && pn2->isInParens())
|
if ((pn->isKind(PNK_LP) || pn->isKind(PNK_NEW)) && pn2->isInParens())
|
||||||
pn2 = pn2->pn_next;
|
pn2 = pn2->pn_next;
|
||||||
|
|
||||||
/* Save the list head in pn1 for later use. */
|
/* Save the list head in pn1 for later use. */
|
||||||
|
@ -480,12 +471,12 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
pn1 = pn->pn_kid1;
|
pn1 = pn->pn_kid1;
|
||||||
pn2 = pn->pn_kid2;
|
pn2 = pn->pn_kid2;
|
||||||
pn3 = pn->pn_kid3;
|
pn3 = pn->pn_kid3;
|
||||||
if (pn1 && !FoldConstants(cx, pn1, tc, pn->isKind(TOK_IF)))
|
if (pn1 && !FoldConstants(cx, pn1, tc, pn->isKind(PNK_IF)))
|
||||||
return false;
|
return false;
|
||||||
if (pn2) {
|
if (pn2) {
|
||||||
if (!FoldConstants(cx, pn2, tc, pn->isKind(TOK_FORHEAD)))
|
if (!FoldConstants(cx, pn2, tc, pn->isKind(PNK_FORHEAD)))
|
||||||
return false;
|
return false;
|
||||||
if (pn->isKind(TOK_FORHEAD) && pn2->isOp(JSOP_TRUE)) {
|
if (pn->isKind(PNK_FORHEAD) && pn2->isOp(JSOP_TRUE)) {
|
||||||
tc->freeTree(pn2);
|
tc->freeTree(pn2);
|
||||||
pn->pn_kid2 = NULL;
|
pn->pn_kid2 = NULL;
|
||||||
}
|
}
|
||||||
|
@ -499,7 +490,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
pn2 = pn->pn_right;
|
pn2 = pn->pn_right;
|
||||||
|
|
||||||
/* Propagate inCond through logical connectives. */
|
/* Propagate inCond through logical connectives. */
|
||||||
if (pn->isKind(TOK_OR) || pn->isKind(TOK_AND)) {
|
if (pn->isKind(PNK_OR) || pn->isKind(PNK_AND)) {
|
||||||
if (!FoldConstants(cx, pn1, tc, inCond))
|
if (!FoldConstants(cx, pn1, tc, inCond))
|
||||||
return false;
|
return false;
|
||||||
if (!FoldConstants(cx, pn2, tc, inCond))
|
if (!FoldConstants(cx, pn2, tc, inCond))
|
||||||
|
@ -508,9 +499,9 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First kid may be null (for default case in switch). */
|
/* First kid may be null (for default case in switch). */
|
||||||
if (pn1 && !FoldConstants(cx, pn1, tc, pn->isKind(TOK_WHILE)))
|
if (pn1 && !FoldConstants(cx, pn1, tc, pn->isKind(PNK_WHILE)))
|
||||||
return false;
|
return false;
|
||||||
if (!FoldConstants(cx, pn2, tc, pn->isKind(TOK_DO)))
|
if (!FoldConstants(cx, pn2, tc, pn->isKind(PNK_DO)))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -526,7 +517,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
* null. This assumption does not hold true for other unary
|
* null. This assumption does not hold true for other unary
|
||||||
* expressions.
|
* expressions.
|
||||||
*/
|
*/
|
||||||
if (pn->isOp(JSOP_TYPEOF) && !pn1->isKind(TOK_NAME))
|
if (pn->isOp(JSOP_TYPEOF) && !pn1->isKind(PNK_NAME))
|
||||||
pn->setOp(JSOP_TYPEOFEXPR);
|
pn->setOp(JSOP_TYPEOFEXPR);
|
||||||
|
|
||||||
if (pn1 && !FoldConstants(cx, pn1, tc, pn->isOp(JSOP_NOT)))
|
if (pn1 && !FoldConstants(cx, pn1, tc, pn->isOp(JSOP_NOT)))
|
||||||
|
@ -560,26 +551,26 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pn->getKind()) {
|
switch (pn->getKind()) {
|
||||||
case TOK_IF:
|
case PNK_IF:
|
||||||
if (ContainsStmt(pn2, TOK_VAR) || ContainsStmt(pn3, TOK_VAR))
|
if (ContainsStmt(pn2, PNK_VAR) || ContainsStmt(pn3, PNK_VAR))
|
||||||
break;
|
break;
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
|
|
||||||
case TOK_HOOK:
|
case PNK_HOOK:
|
||||||
/* Reduce 'if (C) T; else E' into T for true C, E for false. */
|
/* Reduce 'if (C) T; else E' into T for true C, E for false. */
|
||||||
switch (pn1->getKind()) {
|
switch (pn1->getKind()) {
|
||||||
case TOK_NUMBER:
|
case PNK_NUMBER:
|
||||||
if (pn1->pn_dval == 0 || JSDOUBLE_IS_NaN(pn1->pn_dval))
|
if (pn1->pn_dval == 0 || JSDOUBLE_IS_NaN(pn1->pn_dval))
|
||||||
pn2 = pn3;
|
pn2 = pn3;
|
||||||
break;
|
break;
|
||||||
case TOK_STRING:
|
case PNK_STRING:
|
||||||
if (pn1->pn_atom->length() == 0)
|
if (pn1->pn_atom->length() == 0)
|
||||||
pn2 = pn3;
|
pn2 = pn3;
|
||||||
break;
|
break;
|
||||||
case TOK_TRUE:
|
case PNK_TRUE:
|
||||||
break;
|
break;
|
||||||
case TOK_FALSE:
|
case PNK_FALSE:
|
||||||
case TOK_NULL:
|
case PNK_NULL:
|
||||||
pn2 = pn3;
|
pn2 = pn3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -595,15 +586,15 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
|
|
||||||
if (pn2 && !pn2->isDefn())
|
if (pn2 && !pn2->isDefn())
|
||||||
pn->become(pn2);
|
pn->become(pn2);
|
||||||
if (!pn2 || (pn->isKind(TOK_SEMI) && !pn->pn_kid)) {
|
if (!pn2 || (pn->isKind(PNK_SEMI) && !pn->pn_kid)) {
|
||||||
/*
|
/*
|
||||||
* False condition and no else, or an empty then-statement was
|
* False condition and no else, or an empty then-statement was
|
||||||
* moved up over pn. Either way, make pn an empty block (not an
|
* moved up over pn. Either way, make pn an empty block (not an
|
||||||
* empty statement, which does not decompile, even when labeled).
|
* empty statement, which does not decompile, even when labeled).
|
||||||
* NB: pn must be a TOK_IF as TOK_HOOK can never have a null kid
|
* NB: pn must be a PNK_IF as PNK_HOOK can never have a null kid
|
||||||
* or an empty statement for a child.
|
* or an empty statement for a child.
|
||||||
*/
|
*/
|
||||||
pn->setKind(TOK_LC);
|
pn->setKind(PNK_LC);
|
||||||
pn->setArity(PN_LIST);
|
pn->setArity(PN_LIST);
|
||||||
pn->makeEmpty();
|
pn->makeEmpty();
|
||||||
}
|
}
|
||||||
|
@ -612,8 +603,8 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
tc->freeTree(pn3);
|
tc->freeTree(pn3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_OR:
|
case PNK_OR:
|
||||||
case TOK_AND:
|
case PNK_AND:
|
||||||
if (inCond) {
|
if (inCond) {
|
||||||
if (pn->isArity(PN_LIST)) {
|
if (pn->isArity(PN_LIST)) {
|
||||||
ParseNode **pnp = &pn->pn_head;
|
ParseNode **pnp = &pn->pn_head;
|
||||||
|
@ -624,7 +615,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
pnp = &pn1->pn_next;
|
pnp = &pn1->pn_next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((t == Truthy) == pn->isKind(TOK_OR)) {
|
if ((t == Truthy) == pn->isKind(PNK_OR)) {
|
||||||
for (pn2 = pn1->pn_next; pn2; pn2 = pn3) {
|
for (pn2 = pn1->pn_next; pn2; pn2 = pn3) {
|
||||||
pn3 = pn2->pn_next;
|
pn3 = pn2->pn_next;
|
||||||
tc->freeTree(pn2);
|
tc->freeTree(pn2);
|
||||||
|
@ -633,7 +624,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
pn1->pn_next = NULL;
|
pn1->pn_next = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
JS_ASSERT((t == Truthy) == pn->isKind(TOK_AND));
|
JS_ASSERT((t == Truthy) == pn->isKind(PNK_AND));
|
||||||
if (pn->pn_count == 1)
|
if (pn->pn_count == 1)
|
||||||
break;
|
break;
|
||||||
*pnp = pn1->pn_next;
|
*pnp = pn1->pn_next;
|
||||||
|
@ -657,11 +648,11 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
} else {
|
} else {
|
||||||
Truthiness t = Boolish(pn1);
|
Truthiness t = Boolish(pn1);
|
||||||
if (t != Unknown) {
|
if (t != Unknown) {
|
||||||
if ((t == Truthy) == pn->isKind(TOK_OR)) {
|
if ((t == Truthy) == pn->isKind(PNK_OR)) {
|
||||||
tc->freeTree(pn2);
|
tc->freeTree(pn2);
|
||||||
pn->become(pn1);
|
pn->become(pn1);
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT((t == Truthy) == pn->isKind(TOK_AND));
|
JS_ASSERT((t == Truthy) == pn->isKind(PNK_AND));
|
||||||
tc->freeTree(pn1);
|
tc->freeTree(pn1);
|
||||||
pn->become(pn2);
|
pn->become(pn2);
|
||||||
}
|
}
|
||||||
|
@ -670,16 +661,16 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_SUBASSIGN:
|
case PNK_SUBASSIGN:
|
||||||
case TOK_BITORASSIGN:
|
case PNK_BITORASSIGN:
|
||||||
case TOK_BITXORASSIGN:
|
case PNK_BITXORASSIGN:
|
||||||
case TOK_BITANDASSIGN:
|
case PNK_BITANDASSIGN:
|
||||||
case TOK_LSHASSIGN:
|
case PNK_LSHASSIGN:
|
||||||
case TOK_RSHASSIGN:
|
case PNK_RSHASSIGN:
|
||||||
case TOK_URSHASSIGN:
|
case PNK_URSHASSIGN:
|
||||||
case TOK_MULASSIGN:
|
case PNK_MULASSIGN:
|
||||||
case TOK_DIVASSIGN:
|
case PNK_DIVASSIGN:
|
||||||
case TOK_MODASSIGN:
|
case PNK_MODASSIGN:
|
||||||
/*
|
/*
|
||||||
* Compound operators such as *= should be subject to folding, in case
|
* Compound operators such as *= should be subject to folding, in case
|
||||||
* the left-hand side is constant, and so that the decompiler produces
|
* the left-hand side is constant, and so that the decompiler produces
|
||||||
|
@ -689,10 +680,10 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
*/
|
*/
|
||||||
goto do_binary_op;
|
goto do_binary_op;
|
||||||
|
|
||||||
case TOK_ADDASSIGN:
|
case PNK_ADDASSIGN:
|
||||||
JS_ASSERT(pn->isOp(JSOP_ADD));
|
JS_ASSERT(pn->isOp(JSOP_ADD));
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case TOK_PLUS:
|
case PNK_PLUS:
|
||||||
if (pn->isArity(PN_UNARY))
|
if (pn->isArity(PN_UNARY))
|
||||||
goto unary_plusminus;
|
goto unary_plusminus;
|
||||||
if (pn->isArity(PN_LIST)) {
|
if (pn->isArity(PN_LIST)) {
|
||||||
|
@ -710,10 +701,10 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
/* Ok, we're concatenating: convert non-string constant operands. */
|
/* Ok, we're concatenating: convert non-string constant operands. */
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
|
for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
|
||||||
if (!FoldType(cx, pn2, TOK_STRING))
|
if (!FoldType(cx, pn2, PNK_STRING))
|
||||||
return false;
|
return false;
|
||||||
/* XXX fold only if all operands convert to string */
|
/* XXX fold only if all operands convert to string */
|
||||||
if (!pn2->isKind(TOK_STRING))
|
if (!pn2->isKind(PNK_STRING))
|
||||||
return true;
|
return true;
|
||||||
length += pn2->pn_atom->length();
|
length += pn2->pn_atom->length();
|
||||||
}
|
}
|
||||||
|
@ -742,7 +733,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
pn->pn_atom = js_AtomizeString(cx, str);
|
pn->pn_atom = js_AtomizeString(cx, str);
|
||||||
if (!pn->pn_atom)
|
if (!pn->pn_atom)
|
||||||
return false;
|
return false;
|
||||||
pn->setKind(TOK_STRING);
|
pn->setKind(PNK_STRING);
|
||||||
pn->setOp(JSOP_STRING);
|
pn->setOp(JSOP_STRING);
|
||||||
pn->setArity(PN_NULLARY);
|
pn->setArity(PN_NULLARY);
|
||||||
break;
|
break;
|
||||||
|
@ -750,12 +741,12 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
|
|
||||||
/* Handle a binary string concatenation. */
|
/* Handle a binary string concatenation. */
|
||||||
JS_ASSERT(pn->isArity(PN_BINARY));
|
JS_ASSERT(pn->isArity(PN_BINARY));
|
||||||
if (pn1->isKind(TOK_STRING) || pn2->isKind(TOK_STRING)) {
|
if (pn1->isKind(PNK_STRING) || pn2->isKind(PNK_STRING)) {
|
||||||
JSString *left, *right, *str;
|
JSString *left, *right, *str;
|
||||||
|
|
||||||
if (!FoldType(cx, !pn1->isKind(TOK_STRING) ? pn1 : pn2, TOK_STRING))
|
if (!FoldType(cx, !pn1->isKind(PNK_STRING) ? pn1 : pn2, PNK_STRING))
|
||||||
return false;
|
return false;
|
||||||
if (!pn1->isKind(TOK_STRING) || !pn2->isKind(TOK_STRING))
|
if (!pn1->isKind(PNK_STRING) || !pn2->isKind(PNK_STRING))
|
||||||
return true;
|
return true;
|
||||||
left = pn1->pn_atom;
|
left = pn1->pn_atom;
|
||||||
right = pn2->pn_atom;
|
right = pn2->pn_atom;
|
||||||
|
@ -765,7 +756,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
pn->pn_atom = js_AtomizeString(cx, str);
|
pn->pn_atom = js_AtomizeString(cx, str);
|
||||||
if (!pn->pn_atom)
|
if (!pn->pn_atom)
|
||||||
return false;
|
return false;
|
||||||
pn->setKind(TOK_STRING);
|
pn->setKind(PNK_STRING);
|
||||||
pn->setOp(JSOP_STRING);
|
pn->setOp(JSOP_STRING);
|
||||||
pn->setArity(PN_NULLARY);
|
pn->setArity(PN_NULLARY);
|
||||||
tc->freeTree(pn1);
|
tc->freeTree(pn1);
|
||||||
|
@ -776,26 +767,26 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
/* Can't concatenate string literals, let's try numbers. */
|
/* Can't concatenate string literals, let's try numbers. */
|
||||||
goto do_binary_op;
|
goto do_binary_op;
|
||||||
|
|
||||||
case TOK_MINUS:
|
case PNK_MINUS:
|
||||||
if (pn->isArity(PN_UNARY))
|
if (pn->isArity(PN_UNARY))
|
||||||
goto unary_plusminus;
|
goto unary_plusminus;
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case TOK_STAR:
|
case PNK_STAR:
|
||||||
case TOK_LSH:
|
case PNK_LSH:
|
||||||
case TOK_RSH:
|
case PNK_RSH:
|
||||||
case TOK_URSH:
|
case PNK_URSH:
|
||||||
case TOK_DIV:
|
case PNK_DIV:
|
||||||
case TOK_MOD:
|
case PNK_MOD:
|
||||||
do_binary_op:
|
do_binary_op:
|
||||||
if (pn->isArity(PN_LIST)) {
|
if (pn->isArity(PN_LIST)) {
|
||||||
JS_ASSERT(pn->pn_count > 2);
|
JS_ASSERT(pn->pn_count > 2);
|
||||||
for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
|
for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
|
||||||
if (!FoldType(cx, pn2, TOK_NUMBER))
|
if (!FoldType(cx, pn2, PNK_NUMBER))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
|
for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
|
||||||
/* XXX fold only if all operands convert to number */
|
/* XXX fold only if all operands convert to number */
|
||||||
if (!pn2->isKind(TOK_NUMBER))
|
if (!pn2->isKind(PNK_NUMBER))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!pn2) {
|
if (!pn2) {
|
||||||
|
@ -813,23 +804,23 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(pn->isArity(PN_BINARY));
|
JS_ASSERT(pn->isArity(PN_BINARY));
|
||||||
if (!FoldType(cx, pn1, TOK_NUMBER) ||
|
if (!FoldType(cx, pn1, PNK_NUMBER) ||
|
||||||
!FoldType(cx, pn2, TOK_NUMBER)) {
|
!FoldType(cx, pn2, PNK_NUMBER)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (pn1->isKind(TOK_NUMBER) && pn2->isKind(TOK_NUMBER)) {
|
if (pn1->isKind(PNK_NUMBER) && pn2->isKind(PNK_NUMBER)) {
|
||||||
if (!FoldBinaryNumeric(cx, pn->getOp(), pn1, pn2, pn, tc))
|
if (!FoldBinaryNumeric(cx, pn->getOp(), pn1, pn2, pn, tc))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_TYPEOF:
|
case PNK_TYPEOF:
|
||||||
case TOK_VOID:
|
case PNK_VOID:
|
||||||
case TOK_NOT:
|
case PNK_NOT:
|
||||||
case TOK_BITNOT:
|
case PNK_BITNOT:
|
||||||
unary_plusminus:
|
unary_plusminus:
|
||||||
if (pn1->isKind(TOK_NUMBER)) {
|
if (pn1->isKind(PNK_NUMBER)) {
|
||||||
jsdouble d;
|
jsdouble d;
|
||||||
|
|
||||||
/* Operate on one numeric constant. */
|
/* Operate on one numeric constant. */
|
||||||
|
@ -848,32 +839,32 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
|
|
||||||
case JSOP_NOT:
|
case JSOP_NOT:
|
||||||
if (d == 0 || JSDOUBLE_IS_NaN(d)) {
|
if (d == 0 || JSDOUBLE_IS_NaN(d)) {
|
||||||
pn->setKind(TOK_TRUE);
|
pn->setKind(PNK_TRUE);
|
||||||
pn->setOp(JSOP_TRUE);
|
pn->setOp(JSOP_TRUE);
|
||||||
} else {
|
} else {
|
||||||
pn->setKind(TOK_FALSE);
|
pn->setKind(PNK_FALSE);
|
||||||
pn->setOp(JSOP_FALSE);
|
pn->setOp(JSOP_FALSE);
|
||||||
}
|
}
|
||||||
pn->setArity(PN_NULLARY);
|
pn->setArity(PN_NULLARY);
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Return early to dodge the common TOK_NUMBER code. */
|
/* Return early to dodge the common PNK_NUMBER code. */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
pn->setKind(TOK_NUMBER);
|
pn->setKind(PNK_NUMBER);
|
||||||
pn->setOp(JSOP_DOUBLE);
|
pn->setOp(JSOP_DOUBLE);
|
||||||
pn->setArity(PN_NULLARY);
|
pn->setArity(PN_NULLARY);
|
||||||
pn->pn_dval = d;
|
pn->pn_dval = d;
|
||||||
tc->freeTree(pn1);
|
tc->freeTree(pn1);
|
||||||
} else if (pn1->isKind(TOK_TRUE) || pn1->isKind(TOK_FALSE)) {
|
} else if (pn1->isKind(PNK_TRUE) || pn1->isKind(PNK_FALSE)) {
|
||||||
if (pn->isOp(JSOP_NOT)) {
|
if (pn->isOp(JSOP_NOT)) {
|
||||||
pn->become(pn1);
|
pn->become(pn1);
|
||||||
if (pn->isKind(TOK_TRUE)) {
|
if (pn->isKind(PNK_TRUE)) {
|
||||||
pn->setKind(TOK_FALSE);
|
pn->setKind(PNK_FALSE);
|
||||||
pn->setOp(JSOP_FALSE);
|
pn->setOp(JSOP_FALSE);
|
||||||
} else {
|
} else {
|
||||||
pn->setKind(TOK_TRUE);
|
pn->setKind(PNK_TRUE);
|
||||||
pn->setOp(JSOP_TRUE);
|
pn->setOp(JSOP_TRUE);
|
||||||
}
|
}
|
||||||
tc->freeTree(pn1);
|
tc->freeTree(pn1);
|
||||||
|
@ -882,21 +873,21 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
case TOK_XMLELEM:
|
case PNK_XMLELEM:
|
||||||
case TOK_XMLLIST:
|
case PNK_XMLLIST:
|
||||||
case TOK_XMLPTAGC:
|
case PNK_XMLPTAGC:
|
||||||
case TOK_XMLSTAGO:
|
case PNK_XMLSTAGO:
|
||||||
case TOK_XMLETAGO:
|
case PNK_XMLETAGO:
|
||||||
case TOK_XMLNAME:
|
case PNK_XMLNAME:
|
||||||
if (pn->isArity(PN_LIST)) {
|
if (pn->isArity(PN_LIST)) {
|
||||||
JS_ASSERT(pn->isKind(TOK_XMLLIST) || pn->pn_count != 0);
|
JS_ASSERT(pn->isKind(PNK_XMLLIST) || pn->pn_count != 0);
|
||||||
if (!FoldXMLConstants(cx, pn, tc))
|
if (!FoldXMLConstants(cx, pn, tc))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_AT:
|
case PNK_AT:
|
||||||
if (pn1->isKind(TOK_XMLNAME)) {
|
if (pn1->isKind(PNK_XMLNAME)) {
|
||||||
Value v = StringValue(pn1->pn_atom);
|
Value v = StringValue(pn1->pn_atom);
|
||||||
if (!js_ToAttributeName(cx, &v))
|
if (!js_ToAttributeName(cx, &v))
|
||||||
return false;
|
return false;
|
||||||
|
@ -906,7 +897,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
if (!xmlbox)
|
if (!xmlbox)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pn->setKind(TOK_XMLNAME);
|
pn->setKind(PNK_XMLNAME);
|
||||||
pn->setOp(JSOP_OBJECT);
|
pn->setOp(JSOP_OBJECT);
|
||||||
pn->setArity(PN_NULLARY);
|
pn->setArity(PN_NULLARY);
|
||||||
pn->pn_objbox = xmlbox;
|
pn->pn_objbox = xmlbox;
|
||||||
|
@ -929,10 +920,10 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
|
||||||
*/
|
*/
|
||||||
tc->parser->allocator.prepareNodeForMutation(pn);
|
tc->parser->allocator.prepareNodeForMutation(pn);
|
||||||
if (t == Truthy) {
|
if (t == Truthy) {
|
||||||
pn->setKind(TOK_TRUE);
|
pn->setKind(PNK_TRUE);
|
||||||
pn->setOp(JSOP_TRUE);
|
pn->setOp(JSOP_TRUE);
|
||||||
} else {
|
} else {
|
||||||
pn->setKind(TOK_FALSE);
|
pn->setKind(PNK_FALSE);
|
||||||
pn->setOp(JSOP_FALSE);
|
pn->setOp(JSOP_FALSE);
|
||||||
}
|
}
|
||||||
pn->setArity(PN_NULLARY);
|
pn->setArity(PN_NULLARY);
|
||||||
|
|
|
@ -50,14 +50,14 @@ inline bool
|
||||||
ParseNode::isConstant()
|
ParseNode::isConstant()
|
||||||
{
|
{
|
||||||
switch (pn_type) {
|
switch (pn_type) {
|
||||||
case TOK_NUMBER:
|
case PNK_NUMBER:
|
||||||
case TOK_STRING:
|
case PNK_STRING:
|
||||||
case TOK_NULL:
|
case PNK_NULL:
|
||||||
case TOK_FALSE:
|
case PNK_FALSE:
|
||||||
case TOK_TRUE:
|
case PNK_TRUE:
|
||||||
return true;
|
return true;
|
||||||
case TOK_RB:
|
case PNK_RB:
|
||||||
case TOK_RC:
|
case PNK_RC:
|
||||||
return isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST);
|
return isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -84,7 +84,7 @@ ParseNode::become(ParseNode *pn2)
|
||||||
* If any pointers are pointing to pn2, change them to point to this
|
* If any pointers are pointing to pn2, change them to point to this
|
||||||
* instead, since pn2 will be cleared and probably recycled.
|
* instead, since pn2 will be cleared and probably recycled.
|
||||||
*/
|
*/
|
||||||
if (this->isKind(TOK_FUNCTION) && isArity(PN_FUNC)) {
|
if (this->isKind(PNK_FUNCTION) && isArity(PN_FUNC)) {
|
||||||
/* Function node: fix up the pn_funbox->node back-pointer. */
|
/* Function node: fix up the pn_funbox->node back-pointer. */
|
||||||
JS_ASSERT(pn_funbox->node == pn2);
|
JS_ASSERT(pn_funbox->node == pn2);
|
||||||
pn_funbox->node = this;
|
pn_funbox->node = this;
|
||||||
|
@ -101,7 +101,7 @@ ParseNode::become(ParseNode *pn2)
|
||||||
void
|
void
|
||||||
ParseNode::clear()
|
ParseNode::clear()
|
||||||
{
|
{
|
||||||
pn_type = TOK_EOF;
|
pn_type = PNK_LIMIT;
|
||||||
setOp(JSOP_NOP);
|
setOp(JSOP_NOP);
|
||||||
pn_used = pn_defn = false;
|
pn_used = pn_defn = false;
|
||||||
pn_arity = PN_NULLARY;
|
pn_arity = PN_NULLARY;
|
||||||
|
@ -384,20 +384,20 @@ ParseNodeAllocator::allocNode()
|
||||||
/* used only by static create methods of subclasses */
|
/* used only by static create methods of subclasses */
|
||||||
|
|
||||||
ParseNode *
|
ParseNode *
|
||||||
ParseNode::create(ParseNodeArity arity, TreeContext *tc)
|
ParseNode::create(ParseNodeKind kind, ParseNodeArity arity, TreeContext *tc)
|
||||||
{
|
{
|
||||||
Parser *parser = tc->parser;
|
Parser *parser = tc->parser;
|
||||||
const Token &tok = parser->tokenStream.currentToken();
|
const Token &tok = parser->tokenStream.currentToken();
|
||||||
return parser->new_<ParseNode>(tok.type, JSOP_NOP, arity, tok.pos);
|
return parser->new_<ParseNode>(kind, JSOP_NOP, arity, tok.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseNode *
|
ParseNode *
|
||||||
ParseNode::append(TokenKind tt, JSOp op, ParseNode *left, ParseNode *right)
|
ParseNode::append(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right)
|
||||||
{
|
{
|
||||||
if (!left || !right)
|
if (!left || !right)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
JS_ASSERT(left->isKind(tt) && left->isOp(op) && (js_CodeSpec[op].format & JOF_LEFTASSOC));
|
JS_ASSERT(left->isKind(kind) && left->isOp(op) && (js_CodeSpec[op].format & JOF_LEFTASSOC));
|
||||||
|
|
||||||
if (left->pn_arity != PN_LIST) {
|
if (left->pn_arity != PN_LIST) {
|
||||||
ParseNode *pn1 = left->pn_left, *pn2 = left->pn_right;
|
ParseNode *pn1 = left->pn_left, *pn2 = left->pn_right;
|
||||||
|
@ -405,23 +405,23 @@ ParseNode::append(TokenKind tt, JSOp op, ParseNode *left, ParseNode *right)
|
||||||
left->pn_parens = false;
|
left->pn_parens = false;
|
||||||
left->initList(pn1);
|
left->initList(pn1);
|
||||||
left->append(pn2);
|
left->append(pn2);
|
||||||
if (tt == TOK_PLUS) {
|
if (kind == PNK_PLUS) {
|
||||||
if (pn1->isKind(TOK_STRING))
|
if (pn1->isKind(PNK_STRING))
|
||||||
left->pn_xflags |= PNX_STRCAT;
|
left->pn_xflags |= PNX_STRCAT;
|
||||||
else if (!pn1->isKind(TOK_NUMBER))
|
else if (!pn1->isKind(PNK_NUMBER))
|
||||||
left->pn_xflags |= PNX_CANTFOLD;
|
left->pn_xflags |= PNX_CANTFOLD;
|
||||||
if (pn2->isKind(TOK_STRING))
|
if (pn2->isKind(PNK_STRING))
|
||||||
left->pn_xflags |= PNX_STRCAT;
|
left->pn_xflags |= PNX_STRCAT;
|
||||||
else if (!pn2->isKind(TOK_NUMBER))
|
else if (!pn2->isKind(PNK_NUMBER))
|
||||||
left->pn_xflags |= PNX_CANTFOLD;
|
left->pn_xflags |= PNX_CANTFOLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
left->append(right);
|
left->append(right);
|
||||||
left->pn_pos.end = right->pn_pos.end;
|
left->pn_pos.end = right->pn_pos.end;
|
||||||
if (tt == TOK_PLUS) {
|
if (kind == PNK_PLUS) {
|
||||||
if (right->isKind(TOK_STRING))
|
if (right->isKind(PNK_STRING))
|
||||||
left->pn_xflags |= PNX_STRCAT;
|
left->pn_xflags |= PNX_STRCAT;
|
||||||
else if (!right->isKind(TOK_NUMBER))
|
else if (!right->isKind(PNK_NUMBER))
|
||||||
left->pn_xflags |= PNX_CANTFOLD;
|
left->pn_xflags |= PNX_CANTFOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +429,7 @@ ParseNode::append(TokenKind tt, JSOp op, ParseNode *left, ParseNode *right)
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseNode *
|
ParseNode *
|
||||||
ParseNode::newBinaryOrAppend(TokenKind tt, JSOp op, ParseNode *left, ParseNode *right,
|
ParseNode::newBinaryOrAppend(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right,
|
||||||
TreeContext *tc)
|
TreeContext *tc)
|
||||||
{
|
{
|
||||||
if (!left || !right)
|
if (!left || !right)
|
||||||
|
@ -439,8 +439,8 @@ ParseNode::newBinaryOrAppend(TokenKind tt, JSOp op, ParseNode *left, ParseNode *
|
||||||
* Flatten a left-associative (left-heavy) tree of a given operator into
|
* Flatten a left-associative (left-heavy) tree of a given operator into
|
||||||
* a list, to reduce js_FoldConstants and js_EmitTree recursion.
|
* a list, to reduce js_FoldConstants and js_EmitTree recursion.
|
||||||
*/
|
*/
|
||||||
if (left->isKind(tt) && left->isOp(op) && (js_CodeSpec[op].format & JOF_LEFTASSOC))
|
if (left->isKind(kind) && left->isOp(op) && (js_CodeSpec[op].format & JOF_LEFTASSOC))
|
||||||
return append(tt, op, left, right);
|
return append(kind, op, left, right);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fold constant addition immediately, to conserve node space and, what's
|
* Fold constant addition immediately, to conserve node space and, what's
|
||||||
|
@ -449,9 +449,9 @@ ParseNode::newBinaryOrAppend(TokenKind tt, JSOp op, ParseNode *left, ParseNode *
|
||||||
* generated for expressions such as 1 + 2 + "pt" (which should evaluate
|
* generated for expressions such as 1 + 2 + "pt" (which should evaluate
|
||||||
* to "3pt", not "12pt").
|
* to "3pt", not "12pt").
|
||||||
*/
|
*/
|
||||||
if (tt == TOK_PLUS &&
|
if (kind == PNK_PLUS &&
|
||||||
left->isKind(TOK_NUMBER) &&
|
left->isKind(PNK_NUMBER) &&
|
||||||
right->isKind(TOK_NUMBER) &&
|
right->isKind(PNK_NUMBER) &&
|
||||||
tc->parser->foldConstants)
|
tc->parser->foldConstants)
|
||||||
{
|
{
|
||||||
left->pn_dval += right->pn_dval;
|
left->pn_dval += right->pn_dval;
|
||||||
|
@ -460,13 +460,13 @@ ParseNode::newBinaryOrAppend(TokenKind tt, JSOp op, ParseNode *left, ParseNode *
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tc->parser->new_<BinaryNode>(tt, op, left, right);
|
return tc->parser->new_<BinaryNode>(kind, op, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
NameNode *
|
NameNode *
|
||||||
NameNode::create(JSAtom *atom, TreeContext *tc)
|
NameNode::create(ParseNodeKind kind, JSAtom *atom, TreeContext *tc)
|
||||||
{
|
{
|
||||||
ParseNode *pn = ParseNode::create(PN_NAME, tc);
|
ParseNode *pn = ParseNode::create(kind, PN_NAME, tc);
|
||||||
if (pn) {
|
if (pn) {
|
||||||
pn->pn_atom = atom;
|
pn->pn_atom = atom;
|
||||||
((NameNode *)pn)->initCommon(tc);
|
((NameNode *)pn)->initCommon(tc);
|
||||||
|
@ -619,13 +619,13 @@ js::CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
|
||||||
|
|
||||||
#if JS_HAS_DESTRUCTURING
|
#if JS_HAS_DESTRUCTURING
|
||||||
if (opn->isArity(PN_LIST)) {
|
if (opn->isArity(PN_LIST)) {
|
||||||
JS_ASSERT(opn->isKind(TOK_RB) || opn->isKind(TOK_RC));
|
JS_ASSERT(opn->isKind(PNK_RB) || opn->isKind(PNK_RC));
|
||||||
pn->makeEmpty();
|
pn->makeEmpty();
|
||||||
for (ParseNode *opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) {
|
for (ParseNode *opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) {
|
||||||
ParseNode *pn2;
|
ParseNode *pn2;
|
||||||
if (opn->isKind(TOK_RC)) {
|
if (opn->isKind(PNK_RC)) {
|
||||||
JS_ASSERT(opn2->isArity(PN_BINARY));
|
JS_ASSERT(opn2->isArity(PN_BINARY));
|
||||||
JS_ASSERT(opn2->isKind(TOK_COLON));
|
JS_ASSERT(opn2->isKind(PNK_COLON));
|
||||||
|
|
||||||
ParseNode *tag = CloneParseTree(opn2->pn_left, tc);
|
ParseNode *tag = CloneParseTree(opn2->pn_left, tc);
|
||||||
if (!tag)
|
if (!tag)
|
||||||
|
@ -634,9 +634,9 @@ js::CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
|
||||||
if (!target)
|
if (!target)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pn2 = tc->parser->new_<BinaryNode>(TOK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target);
|
pn2 = tc->parser->new_<BinaryNode>(PNK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target);
|
||||||
} else if (opn2->isArity(PN_NULLARY)) {
|
} else if (opn2->isArity(PN_NULLARY)) {
|
||||||
JS_ASSERT(opn2->isKind(TOK_COMMA));
|
JS_ASSERT(opn2->isKind(PNK_COMMA));
|
||||||
pn2 = CloneParseTree(opn2, tc);
|
pn2 = CloneParseTree(opn2, tc);
|
||||||
} else {
|
} else {
|
||||||
pn2 = CloneLeftHandSide(opn2, tc);
|
pn2 = CloneLeftHandSide(opn2, tc);
|
||||||
|
@ -652,7 +652,7 @@ js::CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JS_ASSERT(opn->isArity(PN_NAME));
|
JS_ASSERT(opn->isArity(PN_NAME));
|
||||||
JS_ASSERT(opn->isKind(TOK_NAME));
|
JS_ASSERT(opn->isKind(PNK_NAME));
|
||||||
|
|
||||||
/* If opn is a definition or use, make pn a use. */
|
/* If opn is a definition or use, make pn a use. */
|
||||||
pn->pn_u.name = opn->pn_u.name;
|
pn->pn_u.name = opn->pn_u.name;
|
||||||
|
|
|
@ -53,81 +53,219 @@ namespace js {
|
||||||
* not a concrete syntax tree in all respects (for example, || and && are left
|
* not a concrete syntax tree in all respects (for example, || and && are left
|
||||||
* associative, but (A && B && C) translates into the right-associated tree
|
* associative, but (A && B && C) translates into the right-associated tree
|
||||||
* <A && <B && C>> so that code generation can emit a left-associative branch
|
* <A && <B && C>> so that code generation can emit a left-associative branch
|
||||||
* around <B && C> when A is false). Nodes are labeled by token type, with a
|
* around <B && C> when A is false). Nodes are labeled by kind, with a
|
||||||
* JSOp secondary label when needed:
|
* secondary JSOp label when needed.
|
||||||
*
|
*
|
||||||
|
* The long comment after this enum block describes the kinds in detail.
|
||||||
|
*/
|
||||||
|
enum ParseNodeKind {
|
||||||
|
PNK_SEMI,
|
||||||
|
PNK_COMMA,
|
||||||
|
PNK_HOOK,
|
||||||
|
PNK_COLON,
|
||||||
|
PNK_OR,
|
||||||
|
PNK_AND,
|
||||||
|
PNK_BITOR,
|
||||||
|
PNK_BITXOR,
|
||||||
|
PNK_BITAND,
|
||||||
|
PNK_PLUS,
|
||||||
|
PNK_MINUS,
|
||||||
|
PNK_STAR,
|
||||||
|
PNK_DIV,
|
||||||
|
PNK_MOD,
|
||||||
|
PNK_INC,
|
||||||
|
PNK_DEC,
|
||||||
|
PNK_DOT,
|
||||||
|
PNK_LB,
|
||||||
|
PNK_RB,
|
||||||
|
PNK_LC,
|
||||||
|
PNK_RC,
|
||||||
|
PNK_LP,
|
||||||
|
PNK_RP,
|
||||||
|
PNK_NAME,
|
||||||
|
PNK_NUMBER,
|
||||||
|
PNK_STRING,
|
||||||
|
PNK_REGEXP,
|
||||||
|
PNK_TRUE,
|
||||||
|
PNK_FALSE,
|
||||||
|
PNK_NULL,
|
||||||
|
PNK_THIS,
|
||||||
|
PNK_FUNCTION,
|
||||||
|
PNK_IF,
|
||||||
|
PNK_ELSE,
|
||||||
|
PNK_SWITCH,
|
||||||
|
PNK_CASE,
|
||||||
|
PNK_DEFAULT,
|
||||||
|
PNK_WHILE,
|
||||||
|
PNK_DO,
|
||||||
|
PNK_FOR,
|
||||||
|
PNK_BREAK,
|
||||||
|
PNK_CONTINUE,
|
||||||
|
PNK_IN,
|
||||||
|
PNK_VAR,
|
||||||
|
PNK_WITH,
|
||||||
|
PNK_RETURN,
|
||||||
|
PNK_NEW,
|
||||||
|
PNK_DELETE,
|
||||||
|
PNK_DEFSHARP,
|
||||||
|
PNK_USESHARP,
|
||||||
|
PNK_TRY,
|
||||||
|
PNK_CATCH,
|
||||||
|
PNK_CATCHLIST,
|
||||||
|
PNK_FINALLY,
|
||||||
|
PNK_THROW,
|
||||||
|
PNK_INSTANCEOF,
|
||||||
|
PNK_DEBUGGER,
|
||||||
|
PNK_XMLSTAGO,
|
||||||
|
PNK_XMLETAGO,
|
||||||
|
PNK_XMLPTAGC,
|
||||||
|
PNK_XMLTAGC,
|
||||||
|
PNK_XMLNAME,
|
||||||
|
PNK_XMLATTR,
|
||||||
|
PNK_XMLSPACE,
|
||||||
|
PNK_XMLTEXT,
|
||||||
|
PNK_XMLCOMMENT,
|
||||||
|
PNK_XMLCDATA,
|
||||||
|
PNK_XMLPI,
|
||||||
|
PNK_AT,
|
||||||
|
PNK_DBLCOLON,
|
||||||
|
PNK_ANYNAME,
|
||||||
|
PNK_DBLDOT,
|
||||||
|
PNK_FILTER,
|
||||||
|
PNK_XMLELEM,
|
||||||
|
PNK_XMLLIST,
|
||||||
|
PNK_YIELD,
|
||||||
|
PNK_ARRAYCOMP,
|
||||||
|
PNK_ARRAYPUSH,
|
||||||
|
PNK_LEXICALSCOPE,
|
||||||
|
PNK_LET,
|
||||||
|
PNK_SEQ,
|
||||||
|
PNK_FORHEAD,
|
||||||
|
PNK_ARGSBODY,
|
||||||
|
PNK_UPVARS,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following parse node kinds occupy contiguous ranges to enable easy
|
||||||
|
* range-testing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Equality operators. */
|
||||||
|
PNK_STRICTEQ,
|
||||||
|
PNK_EQ,
|
||||||
|
PNK_STRICTNE,
|
||||||
|
PNK_NE,
|
||||||
|
|
||||||
|
/* Unary operators. */
|
||||||
|
PNK_TYPEOF,
|
||||||
|
PNK_VOID,
|
||||||
|
PNK_NOT,
|
||||||
|
PNK_BITNOT,
|
||||||
|
|
||||||
|
/* Relational operators (< <= > >=). */
|
||||||
|
PNK_LT,
|
||||||
|
PNK_LE,
|
||||||
|
PNK_GT,
|
||||||
|
PNK_GE,
|
||||||
|
|
||||||
|
/* Shift operators (<< >> >>>). */
|
||||||
|
PNK_LSH,
|
||||||
|
PNK_RSH,
|
||||||
|
PNK_URSH,
|
||||||
|
|
||||||
|
/* Assignment operators (= += -= etc.). */
|
||||||
|
PNK_ASSIGN,
|
||||||
|
PNK_ASSIGNMENT_START = PNK_ASSIGN,
|
||||||
|
PNK_ADDASSIGN,
|
||||||
|
PNK_SUBASSIGN,
|
||||||
|
PNK_BITORASSIGN,
|
||||||
|
PNK_BITXORASSIGN,
|
||||||
|
PNK_BITANDASSIGN,
|
||||||
|
PNK_LSHASSIGN,
|
||||||
|
PNK_RSHASSIGN,
|
||||||
|
PNK_URSHASSIGN,
|
||||||
|
PNK_MULASSIGN,
|
||||||
|
PNK_DIVASSIGN,
|
||||||
|
PNK_MODASSIGN,
|
||||||
|
PNK_ASSIGNMENT_LAST = PNK_MODASSIGN,
|
||||||
|
|
||||||
|
PNK_LIMIT /* domain size */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
* Label Variant Members
|
* Label Variant Members
|
||||||
* ----- ------- -------
|
* ----- ------- -------
|
||||||
* <Definitions>
|
* <Definitions>
|
||||||
* TOK_FUNCTION name pn_funbox: ptr to js::FunctionBox holding function
|
* PNK_FUNCTION name pn_funbox: ptr to js::FunctionBox holding function
|
||||||
* object containing arg and var properties. We
|
* object containing arg and var properties. We
|
||||||
* create the function object at parse (not emit)
|
* create the function object at parse (not emit)
|
||||||
* time to specialize arg and var bytecodes early.
|
* time to specialize arg and var bytecodes early.
|
||||||
* pn_body: TOK_UPVARS if the function's source body
|
* pn_body: PNK_UPVARS if the function's source body
|
||||||
* depends on outer names, else TOK_ARGSBODY
|
* depends on outer names, else PNK_ARGSBODY
|
||||||
* if formal parameters, else TOK_LC node for
|
* if formal parameters, else PNK_LC node for
|
||||||
* function body statements, else TOK_RETURN
|
* function body statements, else PNK_RETURN
|
||||||
* for expression closure, else TOK_SEQ for
|
* for expression closure, else PNK_SEQ for
|
||||||
* expression closure with destructured
|
* expression closure with destructured
|
||||||
* formal parameters
|
* formal parameters
|
||||||
* pn_cookie: static level and var index for function
|
* pn_cookie: static level and var index for function
|
||||||
* pn_dflags: PND_* definition/use flags (see below)
|
* pn_dflags: PND_* definition/use flags (see below)
|
||||||
* pn_blockid: block id number
|
* pn_blockid: block id number
|
||||||
* TOK_ARGSBODY list list of formal parameters followed by TOK_LC node
|
* PNK_ARGSBODY list list of formal parameters followed by PNK_LC node
|
||||||
* for function body statements as final element
|
* for function body statements as final element
|
||||||
* pn_count: 1 + number of formal parameters
|
* pn_count: 1 + number of formal parameters
|
||||||
* TOK_UPVARS nameset pn_names: lexical dependencies (js::Definitions)
|
* PNK_UPVARS nameset pn_names: lexical dependencies (js::Definitions)
|
||||||
* defined in enclosing scopes, or ultimately not
|
* defined in enclosing scopes, or ultimately not
|
||||||
* defined (free variables, either global property
|
* defined (free variables, either global property
|
||||||
* references or reference errors).
|
* references or reference errors).
|
||||||
* pn_tree: TOK_ARGSBODY or TOK_LC node
|
* pn_tree: PNK_ARGSBODY or PNK_LC node
|
||||||
*
|
*
|
||||||
* <Statements>
|
* <Statements>
|
||||||
* TOK_LC list pn_head: list of pn_count statements
|
* PNK_LC list pn_head: list of pn_count statements
|
||||||
* TOK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
|
* PNK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
|
||||||
* In body of a comprehension or desugared generator
|
* In body of a comprehension or desugared generator
|
||||||
* expression, pn_kid2 is TOK_YIELD, TOK_ARRAYPUSH,
|
* expression, pn_kid2 is PNK_YIELD, PNK_ARRAYPUSH,
|
||||||
* or (if the push was optimized away) empty TOK_LC.
|
* or (if the push was optimized away) empty PNK_LC.
|
||||||
* TOK_SWITCH binary pn_left: discriminant
|
* PNK_SWITCH binary pn_left: discriminant
|
||||||
* pn_right: list of TOK_CASE nodes, with at most one
|
* pn_right: list of PNK_CASE nodes, with at most one
|
||||||
* TOK_DEFAULT node, or if there are let bindings
|
* PNK_DEFAULT node, or if there are let bindings
|
||||||
* in the top level of the switch body's cases, a
|
* in the top level of the switch body's cases, a
|
||||||
* TOK_LEXICALSCOPE node that contains the list of
|
* PNK_LEXICALSCOPE node that contains the list of
|
||||||
* TOK_CASE nodes.
|
* PNK_CASE nodes.
|
||||||
* TOK_CASE, binary pn_left: case expr or null if TOK_DEFAULT
|
* PNK_CASE, binary pn_left: case expr
|
||||||
* TOK_DEFAULT pn_right: TOK_LC node for this case's statements
|
* pn_right: PNK_LC node for this case's statements
|
||||||
|
* PNK_DEFAULT binary pn_left: null
|
||||||
|
* pn_right: PNK_LC node for this default's statements
|
||||||
* pn_val: constant value if lookup or table switch
|
* pn_val: constant value if lookup or table switch
|
||||||
* TOK_WHILE binary pn_left: cond, pn_right: body
|
* PNK_WHILE binary pn_left: cond, pn_right: body
|
||||||
* TOK_DO binary pn_left: body, pn_right: cond
|
* PNK_DO binary pn_left: body, pn_right: cond
|
||||||
* TOK_FOR binary pn_left: either
|
* PNK_FOR binary pn_left: either
|
||||||
* for/in loop: a ternary TOK_IN node with
|
* for/in loop: a ternary PNK_IN node with
|
||||||
* pn_kid1: TOK_VAR to left of 'in', or NULL
|
* pn_kid1: PNK_VAR to left of 'in', or NULL
|
||||||
* its pn_xflags may have PNX_POPVAR
|
* its pn_xflags may have PNX_POPVAR
|
||||||
* and PNX_FORINVAR bits set
|
* and PNX_FORINVAR bits set
|
||||||
* pn_kid2: TOK_NAME or destructuring expr
|
* pn_kid2: PNK_NAME or destructuring expr
|
||||||
* to left of 'in'; if pn_kid1, then this
|
* to left of 'in'; if pn_kid1, then this
|
||||||
* is a clone of pn_kid1->pn_head
|
* is a clone of pn_kid1->pn_head
|
||||||
* pn_kid3: object expr to right of 'in'
|
* pn_kid3: object expr to right of 'in'
|
||||||
* for(;;) loop: a ternary TOK_RESERVED node with
|
* for(;;) loop: a ternary PNK_FORHEAD node with
|
||||||
* pn_kid1: init expr before first ';'
|
* pn_kid1: init expr before first ';'
|
||||||
* pn_kid2: cond expr before second ';'
|
* pn_kid2: cond expr before second ';'
|
||||||
* pn_kid3: update expr after second ';'
|
* pn_kid3: update expr after second ';'
|
||||||
* any kid may be null
|
* any kid may be null
|
||||||
* pn_right: body
|
* pn_right: body
|
||||||
* TOK_THROW unary pn_op: JSOP_THROW, pn_kid: exception
|
* PNK_THROW unary pn_op: JSOP_THROW, pn_kid: exception
|
||||||
* TOK_TRY ternary pn_kid1: try block
|
* PNK_TRY ternary pn_kid1: try block
|
||||||
* pn_kid2: null or TOK_RESERVED list of
|
* pn_kid2: null or PNK_CATCHLIST list of
|
||||||
* TOK_LEXICALSCOPE nodes, each with pn_expr pointing
|
* PNK_LEXICALSCOPE nodes, each with pn_expr pointing
|
||||||
* to a TOK_CATCH node
|
* to a PNK_CATCH node
|
||||||
* pn_kid3: null or finally block
|
* pn_kid3: null or finally block
|
||||||
* TOK_CATCH ternary pn_kid1: TOK_NAME, TOK_RB, or TOK_RC catch var node
|
* PNK_CATCH ternary pn_kid1: PNK_NAME, PNK_RB, or PNK_RC catch var node
|
||||||
* (TOK_RB or TOK_RC if destructuring)
|
* (PNK_RB or PNK_RC if destructuring)
|
||||||
* pn_kid2: null or the catch guard expression
|
* pn_kid2: null or the catch guard expression
|
||||||
* pn_kid3: catch block statements
|
* pn_kid3: catch block statements
|
||||||
* TOK_BREAK name pn_atom: label or null
|
* PNK_BREAK name pn_atom: label or null
|
||||||
* TOK_CONTINUE name pn_atom: label or null
|
* PNK_CONTINUE name pn_atom: label or null
|
||||||
* TOK_WITH binary pn_left: head expr, pn_right: body
|
* PNK_WITH binary pn_left: head expr, pn_right: body
|
||||||
* TOK_VAR list pn_head: list of TOK_NAME or TOK_ASSIGN nodes
|
* PNK_VAR list pn_head: list of PNK_NAME or PNK_ASSIGN nodes
|
||||||
* each name node has either
|
* each name node has either
|
||||||
* pn_used: false
|
* pn_used: false
|
||||||
* pn_atom: variable name
|
* pn_atom: variable name
|
||||||
|
@ -137,142 +275,142 @@ namespace js {
|
||||||
* pn_atom: variable name
|
* pn_atom: variable name
|
||||||
* pn_lexdef: def node
|
* pn_lexdef: def node
|
||||||
* each assignment node has
|
* each assignment node has
|
||||||
* pn_left: TOK_NAME with pn_used true and
|
* pn_left: PNK_NAME with pn_used true and
|
||||||
* pn_lexdef (NOT pn_expr) set
|
* pn_lexdef (NOT pn_expr) set
|
||||||
* pn_right: initializer
|
* pn_right: initializer
|
||||||
* TOK_RETURN unary pn_kid: return expr or null
|
* PNK_RETURN unary pn_kid: return expr or null
|
||||||
* TOK_SEMI unary pn_kid: expr or null statement
|
* PNK_SEMI unary pn_kid: expr or null statement
|
||||||
* pn_prologue: true if Directive Prologue member
|
* pn_prologue: true if Directive Prologue member
|
||||||
* in original source, not introduced via
|
* in original source, not introduced via
|
||||||
* constant folding or other tree rewriting
|
* constant folding or other tree rewriting
|
||||||
* TOK_COLON name pn_atom: label, pn_expr: labeled statement
|
* PNK_COLON name pn_atom: label, pn_expr: labeled statement
|
||||||
*
|
*
|
||||||
* <Expressions>
|
* <Expressions>
|
||||||
* All left-associated binary trees of the same type are optimized into lists
|
* All left-associated binary trees of the same type are optimized into lists
|
||||||
* to avoid recursion when processing expression chains.
|
* to avoid recursion when processing expression chains.
|
||||||
* TOK_COMMA list pn_head: list of pn_count comma-separated exprs
|
* PNK_COMMA list pn_head: list of pn_count comma-separated exprs
|
||||||
* TOK_ASSIGN binary pn_left: lvalue, pn_right: rvalue
|
* PNK_ASSIGN binary pn_left: lvalue, pn_right: rvalue
|
||||||
* TOK_ADDASSIGN, binary pn_left: lvalue, pn_right: rvalue
|
* PNK_ADDASSIGN, binary pn_left: lvalue, pn_right: rvalue
|
||||||
* TOK_SUBASSIGN, pn_op: JSOP_ADD for +=, etc.
|
* PNK_SUBASSIGN, pn_op: JSOP_ADD for +=, etc.
|
||||||
* TOK_BITORASSIGN,
|
* PNK_BITORASSIGN,
|
||||||
* TOK_BITXORASSIGN,
|
* PNK_BITXORASSIGN,
|
||||||
* TOK_BITANDASSIGN,
|
* PNK_BITANDASSIGN,
|
||||||
* TOK_LSHASSIGN,
|
* PNK_LSHASSIGN,
|
||||||
* TOK_RSHASSIGN,
|
* PNK_RSHASSIGN,
|
||||||
* TOK_URSHASSIGN,
|
* PNK_URSHASSIGN,
|
||||||
* TOK_MULASSIGN,
|
* PNK_MULASSIGN,
|
||||||
* TOK_DIVASSIGN,
|
* PNK_DIVASSIGN,
|
||||||
* TOK_MODASSIGN
|
* PNK_MODASSIGN
|
||||||
* TOK_HOOK ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else
|
* PNK_HOOK ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else
|
||||||
* TOK_OR binary pn_left: first in || chain, pn_right: rest of chain
|
* PNK_OR binary pn_left: first in || chain, pn_right: rest of chain
|
||||||
* TOK_AND binary pn_left: first in && chain, pn_right: rest of chain
|
* PNK_AND binary pn_left: first in && chain, pn_right: rest of chain
|
||||||
* TOK_BITOR binary pn_left: left-assoc | expr, pn_right: ^ expr
|
* PNK_BITOR binary pn_left: left-assoc | expr, pn_right: ^ expr
|
||||||
* TOK_BITXOR binary pn_left: left-assoc ^ expr, pn_right: & expr
|
* PNK_BITXOR binary pn_left: left-assoc ^ expr, pn_right: & expr
|
||||||
* TOK_BITAND binary pn_left: left-assoc & expr, pn_right: EQ expr
|
* PNK_BITAND binary pn_left: left-assoc & expr, pn_right: EQ expr
|
||||||
*
|
*
|
||||||
* TOK_EQ, binary pn_left: left-assoc EQ expr, pn_right: REL expr
|
* PNK_EQ, binary pn_left: left-assoc EQ expr, pn_right: REL expr
|
||||||
* TOK_NE,
|
* PNK_NE,
|
||||||
* TOK_STRICTEQ,
|
* PNK_STRICTEQ,
|
||||||
* TOK_STRICTNE
|
* PNK_STRICTNE
|
||||||
* TOK_LT, binary pn_left: left-assoc REL expr, pn_right: SH expr
|
* PNK_LT, binary pn_left: left-assoc REL expr, pn_right: SH expr
|
||||||
* TOK_LE,
|
* PNK_LE,
|
||||||
* TOK_GT,
|
* PNK_GT,
|
||||||
* TOK_GE
|
* PNK_GE
|
||||||
* TOK_LSH, binary pn_left: left-assoc SH expr, pn_right: ADD expr
|
* PNK_LSH, binary pn_left: left-assoc SH expr, pn_right: ADD expr
|
||||||
* TOK_RSH,
|
* PNK_RSH,
|
||||||
* TOK_URSH
|
* PNK_URSH
|
||||||
* TOK_PLUS, binary pn_left: left-assoc ADD expr, pn_right: MUL expr
|
* PNK_PLUS, binary pn_left: left-assoc ADD expr, pn_right: MUL expr
|
||||||
* pn_xflags: if a left-associated binary TOK_PLUS
|
* pn_xflags: if a left-associated binary PNK_PLUS
|
||||||
* tree has been flattened into a list (see above
|
* tree has been flattened into a list (see above
|
||||||
* under <Expressions>), pn_xflags will contain
|
* under <Expressions>), pn_xflags will contain
|
||||||
* PNX_STRCAT if at least one list element is a
|
* PNX_STRCAT if at least one list element is a
|
||||||
* string literal (TOK_STRING); if such a list has
|
* string literal (PNK_STRING); if such a list has
|
||||||
* any non-string, non-number term, pn_xflags will
|
* any non-string, non-number term, pn_xflags will
|
||||||
* contain PNX_CANTFOLD.
|
* contain PNX_CANTFOLD.
|
||||||
* pn_
|
* pn_
|
||||||
* TOK_MINUS pn_op: JSOP_ADD, JSOP_SUB
|
* PNK_MINUS pn_op: JSOP_ADD, JSOP_SUB
|
||||||
* TOK_STAR, binary pn_left: left-assoc MUL expr, pn_right: UNARY expr
|
* PNK_STAR, binary pn_left: left-assoc MUL expr, pn_right: UNARY expr
|
||||||
* TOK_DIV, pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
|
* PNK_DIV, pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
|
||||||
* TOK_MOD
|
* PNK_MOD
|
||||||
* TOK_TYPEOF, unary pn_kid: UNARY expr
|
* PNK_TYPEOF, unary pn_kid: UNARY expr
|
||||||
* TOK_VOID,
|
* PNK_VOID,
|
||||||
* TOK_NOT,
|
* PNK_NOT,
|
||||||
* TOK_BITNOT
|
* PNK_BITNOT
|
||||||
* TOK_INC, unary pn_kid: MEMBER expr
|
* PNK_INC, unary pn_kid: MEMBER expr
|
||||||
* TOK_DEC
|
* PNK_DEC
|
||||||
* TOK_NEW list pn_head: list of ctor, arg1, arg2, ... argN
|
* PNK_NEW list pn_head: list of ctor, arg1, arg2, ... argN
|
||||||
* pn_count: 1 + N (where N is number of args)
|
* pn_count: 1 + N (where N is number of args)
|
||||||
* ctor is a MEMBER expr
|
* ctor is a MEMBER expr
|
||||||
* TOK_DELETE unary pn_kid: MEMBER expr
|
* PNK_DELETE unary pn_kid: MEMBER expr
|
||||||
* TOK_DOT, name pn_expr: MEMBER expr to left of .
|
* PNK_DOT, name pn_expr: MEMBER expr to left of .
|
||||||
* TOK_DBLDOT pn_atom: name to right of .
|
* PNK_DBLDOT pn_atom: name to right of .
|
||||||
* TOK_LB binary pn_left: MEMBER expr to left of [
|
* PNK_LB binary pn_left: MEMBER expr to left of [
|
||||||
* pn_right: expr between [ and ]
|
* pn_right: expr between [ and ]
|
||||||
* TOK_LP list pn_head: list of call, arg1, arg2, ... argN
|
* PNK_LP list pn_head: list of call, arg1, arg2, ... argN
|
||||||
* pn_count: 1 + N (where N is number of args)
|
* pn_count: 1 + N (where N is number of args)
|
||||||
* call is a MEMBER expr naming a callable object
|
* call is a MEMBER expr naming a callable object
|
||||||
* TOK_RB list pn_head: list of pn_count array element exprs
|
* PNK_RB list pn_head: list of pn_count array element exprs
|
||||||
* [,,] holes are represented by TOK_COMMA nodes
|
* [,,] holes are represented by PNK_COMMA nodes
|
||||||
* pn_xflags: PN_ENDCOMMA if extra comma at end
|
* pn_xflags: PN_ENDCOMMA if extra comma at end
|
||||||
* TOK_RC list pn_head: list of pn_count binary TOK_COLON nodes
|
* PNK_RC list pn_head: list of pn_count binary PNK_COLON nodes
|
||||||
* TOK_COLON binary key-value pair in object initializer or
|
* PNK_COLON binary key-value pair in object initializer or
|
||||||
* destructuring lhs
|
* destructuring lhs
|
||||||
* pn_left: property id, pn_right: value
|
* pn_left: property id, pn_right: value
|
||||||
* var {x} = object destructuring shorthand shares
|
* var {x} = object destructuring shorthand shares
|
||||||
* PN_NAME node for x on left and right of TOK_COLON
|
* PN_NAME node for x on left and right of PNK_COLON
|
||||||
* node in TOK_RC's list, has PNX_DESTRUCT flag
|
* node in PNK_RC's list, has PNX_DESTRUCT flag
|
||||||
* TOK_DEFSHARP unary pn_num: jsint value of n in #n=
|
* PNK_DEFSHARP unary pn_num: jsint value of n in #n=
|
||||||
* pn_kid: primary function, paren, name, object or
|
* pn_kid: primary function, paren, name, object or
|
||||||
* array literal expressions
|
* array literal expressions
|
||||||
* TOK_USESHARP nullary pn_num: jsint value of n in #n#
|
* PNK_USESHARP nullary pn_num: jsint value of n in #n#
|
||||||
* TOK_NAME, name pn_atom: name, string, or object atom
|
* PNK_NAME, name pn_atom: name, string, or object atom
|
||||||
* TOK_STRING, pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or
|
* PNK_STRING, pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or
|
||||||
* JSOP_REGEXP
|
* JSOP_REGEXP
|
||||||
* TOK_REGEXP If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
|
* PNK_REGEXP If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
|
||||||
* with pn_cookie telling (staticLevel, slot) (see
|
* with pn_cookie telling (staticLevel, slot) (see
|
||||||
* jsscript.h's UPVAR macros) and pn_dflags telling
|
* jsscript.h's UPVAR macros) and pn_dflags telling
|
||||||
* const-ness and static analysis results
|
* const-ness and static analysis results
|
||||||
* TOK_NAME name If pn_used, TOK_NAME uses the lexdef member instead
|
* PNK_NAME name If pn_used, PNK_NAME uses the lexdef member instead
|
||||||
* of the expr member it overlays
|
* of the expr member it overlays
|
||||||
* TOK_NUMBER dval pn_dval: double value of numeric literal
|
* PNK_NUMBER dval pn_dval: double value of numeric literal
|
||||||
* TOK_TRUE, nullary pn_op: JSOp bytecode
|
* PNK_TRUE, nullary pn_op: JSOp bytecode
|
||||||
* TOK_FALSE,
|
* PNK_FALSE,
|
||||||
* TOK_NULL,
|
* PNK_NULL,
|
||||||
* TOK_THIS
|
* PNK_THIS
|
||||||
*
|
*
|
||||||
* <E4X node descriptions>
|
* <E4X node descriptions>
|
||||||
* TOK_DEFAULT name pn_atom: default XML namespace string literal
|
* PNK_DEFAULT name pn_atom: default XML namespace string literal
|
||||||
* TOK_FILTER binary pn_left: container expr, pn_right: filter expr
|
* PNK_FILTER binary pn_left: container expr, pn_right: filter expr
|
||||||
* TOK_DBLDOT binary pn_left: container expr, pn_right: selector expr
|
* PNK_DBLDOT binary pn_left: container expr, pn_right: selector expr
|
||||||
* TOK_ANYNAME nullary pn_op: JSOP_ANYNAME
|
* PNK_ANYNAME nullary pn_op: JSOP_ANYNAME
|
||||||
* pn_atom: cx->runtime->atomState.starAtom
|
* pn_atom: cx->runtime->atomState.starAtom
|
||||||
* TOK_AT unary pn_op: JSOP_TOATTRNAME; pn_kid attribute id/expr
|
* PNK_AT unary pn_op: JSOP_TOATTRNAME; pn_kid attribute id/expr
|
||||||
* TOK_DBLCOLON binary pn_op: JSOP_QNAME
|
* PNK_DBLCOLON binary pn_op: JSOP_QNAME
|
||||||
* pn_left: TOK_ANYNAME or TOK_NAME node
|
* pn_left: PNK_ANYNAME or PNK_NAME node
|
||||||
* pn_right: TOK_STRING "*" node, or expr within []
|
* pn_right: PNK_STRING "*" node, or expr within []
|
||||||
* name pn_op: JSOP_QNAMECONST
|
* name pn_op: JSOP_QNAMECONST
|
||||||
* pn_expr: TOK_ANYNAME or TOK_NAME left operand
|
* pn_expr: PNK_ANYNAME or PNK_NAME left operand
|
||||||
* pn_atom: name on right of ::
|
* pn_atom: name on right of ::
|
||||||
* TOK_XMLELEM list XML element node
|
* PNK_XMLELEM list XML element node
|
||||||
* pn_head: start tag, content1, ... contentN, end tag
|
* pn_head: start tag, content1, ... contentN, end tag
|
||||||
* pn_count: 2 + N where N is number of content nodes
|
* pn_count: 2 + N where N is number of content nodes
|
||||||
* N may be > x.length() if {expr} embedded
|
* N may be > x.length() if {expr} embedded
|
||||||
* After constant folding, these contents may be
|
* After constant folding, these contents may be
|
||||||
* concatenated into string nodes.
|
* concatenated into string nodes.
|
||||||
* TOK_XMLLIST list XML list node
|
* PNK_XMLLIST list XML list node
|
||||||
* pn_head: content1, ... contentN
|
* pn_head: content1, ... contentN
|
||||||
* TOK_XMLSTAGO, list XML start, end, and point tag contents
|
* PNK_XMLSTAGO, list XML start, end, and point tag contents
|
||||||
* TOK_XMLETAGO, pn_head: tag name or {expr}, ... XML attrs ...
|
* PNK_XMLETAGO, pn_head: tag name or {expr}, ... XML attrs ...
|
||||||
* TOK_XMLPTAGC
|
* PNK_XMLPTAGC
|
||||||
* TOK_XMLNAME nullary pn_atom: XML name, with no {expr} embedded
|
* PNK_XMLNAME nullary pn_atom: XML name, with no {expr} embedded
|
||||||
* TOK_XMLNAME list pn_head: tag name or {expr}, ... name or {expr}
|
* PNK_XMLNAME list pn_head: tag name or {expr}, ... name or {expr}
|
||||||
* TOK_XMLATTR, nullary pn_atom: attribute value string; pn_op: JSOP_STRING
|
* PNK_XMLATTR, nullary pn_atom: attribute value string; pn_op: JSOP_STRING
|
||||||
* TOK_XMLCDATA,
|
* PNK_XMLCDATA,
|
||||||
* TOK_XMLCOMMENT
|
* PNK_XMLCOMMENT
|
||||||
* TOK_XMLPI nullary pn_pitarget: XML processing instruction target
|
* PNK_XMLPI nullary pn_pitarget: XML processing instruction target
|
||||||
* pn_pidata: XML PI data, or null if no data
|
* pn_pidata: XML PI data, or null if no data
|
||||||
* TOK_XMLTEXT nullary pn_atom: marked-up text, or null if empty string
|
* PNK_XMLTEXT nullary pn_atom: marked-up text, or null if empty string
|
||||||
* TOK_LC unary {expr} in XML tag or content; pn_kid is expr
|
* PNK_LC unary {expr} in XML tag or content; pn_kid is expr
|
||||||
*
|
*
|
||||||
* So an XML tag with no {expr} and three attributes is a list with the form:
|
* So an XML tag with no {expr} and three attributes is a list with the form:
|
||||||
*
|
*
|
||||||
|
@ -287,10 +425,10 @@ namespace js {
|
||||||
* ((name1 {expr1}) (name2 {expr2} name3) {expr3})
|
* ((name1 {expr1}) (name2 {expr2} name3) {expr3})
|
||||||
*
|
*
|
||||||
* where () bracket a list with elements separated by spaces, and {expr} is a
|
* where () bracket a list with elements separated by spaces, and {expr} is a
|
||||||
* TOK_LC unary node with expr as its kid.
|
* PNK_LC unary node with expr as its kid.
|
||||||
*
|
*
|
||||||
* Thus, the attribute name/value pairs occupy successive odd and even list
|
* Thus, the attribute name/value pairs occupy successive odd and even list
|
||||||
* locations, where pn_head is the TOK_XMLNAME node at list location 0. The
|
* locations, where pn_head is the PNK_XMLNAME node at list location 0. The
|
||||||
* parser builds the same sort of structures for elements:
|
* parser builds the same sort of structures for elements:
|
||||||
*
|
*
|
||||||
* <a x={x}>Hi there!<b y={y}>How are you?</b><answer>{x + y}</answer></a>
|
* <a x={x}>Hi there!<b y={y}>How are you?</b><answer>{x + y}</answer></a>
|
||||||
|
@ -303,14 +441,14 @@ namespace js {
|
||||||
*
|
*
|
||||||
* Label Variant Members
|
* Label Variant Members
|
||||||
* ----- ------- -------
|
* ----- ------- -------
|
||||||
* TOK_LEXICALSCOPE name pn_op: JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR
|
* PNK_LEXICALSCOPE name pn_op: JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR
|
||||||
* pn_objbox: block object in ObjectBox holder
|
* pn_objbox: block object in ObjectBox holder
|
||||||
* pn_expr: block body
|
* pn_expr: block body
|
||||||
* TOK_ARRAYCOMP list pn_count: 1
|
* PNK_ARRAYCOMP list pn_count: 1
|
||||||
* pn_head: list of 1 element, which is block
|
* pn_head: list of 1 element, which is block
|
||||||
* enclosing for loop(s) and optionally
|
* enclosing for loop(s) and optionally
|
||||||
* if-guarded TOK_ARRAYPUSH
|
* if-guarded PNK_ARRAYPUSH
|
||||||
* TOK_ARRAYPUSH unary pn_op: JSOP_ARRAYCOMP
|
* PNK_ARRAYPUSH unary pn_op: JSOP_ARRAYCOMP
|
||||||
* pn_kid: array comprehension expression
|
* pn_kid: array comprehension expression
|
||||||
*/
|
*/
|
||||||
enum ParseNodeArity {
|
enum ParseNodeArity {
|
||||||
|
@ -328,7 +466,7 @@ struct Definition;
|
||||||
|
|
||||||
struct ParseNode {
|
struct ParseNode {
|
||||||
private:
|
private:
|
||||||
uint32 pn_type : 16, /* TOK_* type, see frontend/TokenStream.h */
|
uint32 pn_type : 16, /* PNK_* type */
|
||||||
pn_op : 8, /* see JSOp enum and jsopcode.tbl */
|
pn_op : 8, /* see JSOp enum and jsopcode.tbl */
|
||||||
pn_arity : 5, /* see ParseNodeArity enum */
|
pn_arity : 5, /* see ParseNodeArity enum */
|
||||||
pn_parens : 1, /* this expr was enclosed in parens */
|
pn_parens : 1, /* this expr was enclosed in parens */
|
||||||
|
@ -336,10 +474,11 @@ struct ParseNode {
|
||||||
pn_defn : 1; /* this node is a Definition */
|
pn_defn : 1; /* this node is a Definition */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ParseNode(TokenKind type, JSOp op, ParseNodeArity arity)
|
ParseNode(ParseNodeKind kind, JSOp op, ParseNodeArity arity)
|
||||||
: pn_type(type), pn_op(op), pn_arity(arity), pn_parens(0), pn_used(0), pn_defn(0),
|
: pn_type(kind), pn_op(op), pn_arity(arity), pn_parens(0), pn_used(0), pn_defn(0),
|
||||||
pn_offset(0), pn_next(NULL), pn_link(NULL)
|
pn_offset(0), pn_next(NULL), pn_link(NULL)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(kind < PNK_LIMIT);
|
||||||
pn_pos.begin.index = 0;
|
pn_pos.begin.index = 0;
|
||||||
pn_pos.begin.lineno = 0;
|
pn_pos.begin.lineno = 0;
|
||||||
pn_pos.end.index = 0;
|
pn_pos.end.index = 0;
|
||||||
|
@ -347,27 +486,51 @@ struct ParseNode {
|
||||||
memset(&pn_u, 0, sizeof pn_u);
|
memset(&pn_u, 0, sizeof pn_u);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseNode(TokenKind type, JSOp op, ParseNodeArity arity, const TokenPos &pos)
|
ParseNode(ParseNodeKind kind, JSOp op, ParseNodeArity arity, const TokenPos &pos)
|
||||||
: pn_type(type), pn_op(op), pn_arity(arity), pn_parens(0), pn_used(0), pn_defn(0),
|
: pn_type(kind), pn_op(op), pn_arity(arity), pn_parens(0), pn_used(0), pn_defn(0),
|
||||||
pn_pos(pos), pn_offset(0), pn_next(NULL), pn_link(NULL)
|
pn_pos(pos), pn_offset(0), pn_next(NULL), pn_link(NULL)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(kind < PNK_LIMIT);
|
||||||
memset(&pn_u, 0, sizeof pn_u);
|
memset(&pn_u, 0, sizeof pn_u);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSOp getOp() const { return JSOp(pn_op); }
|
JSOp getOp() const { return JSOp(pn_op); }
|
||||||
void setOp(JSOp op) { pn_op = op; }
|
void setOp(JSOp op) { pn_op = op; }
|
||||||
bool isOp(JSOp op) const { return getOp() == op; }
|
bool isOp(JSOp op) const { return getOp() == op; }
|
||||||
TokenKind getKind() const { return TokenKind(pn_type); }
|
|
||||||
void setKind(TokenKind kind) { pn_type = kind; }
|
ParseNodeKind getKind() const {
|
||||||
bool isKind(TokenKind kind) const { return getKind() == kind; }
|
JS_ASSERT(pn_type < PNK_LIMIT);
|
||||||
|
return ParseNodeKind(pn_type);
|
||||||
|
}
|
||||||
|
void setKind(ParseNodeKind kind) {
|
||||||
|
JS_ASSERT(kind < PNK_LIMIT);
|
||||||
|
pn_type = kind;
|
||||||
|
}
|
||||||
|
bool isKind(ParseNodeKind kind) const { return getKind() == kind; }
|
||||||
|
|
||||||
ParseNodeArity getArity() const { return ParseNodeArity(pn_arity); }
|
ParseNodeArity getArity() const { return ParseNodeArity(pn_arity); }
|
||||||
bool isArity(ParseNodeArity a) const { return getArity() == a; }
|
bool isArity(ParseNodeArity a) const { return getArity() == a; }
|
||||||
void setArity(ParseNodeArity a) { pn_arity = a; }
|
void setArity(ParseNodeArity a) { pn_arity = a; }
|
||||||
|
|
||||||
bool isEquality() const { return TokenKindIsEquality(getKind()); }
|
bool isXMLNameOp() const {
|
||||||
bool isUnaryOp() const { return TokenKindIsUnaryOp(getKind()); }
|
ParseNodeKind kind = getKind();
|
||||||
bool isXMLNameOp() const { return TokenKindIsXML(getKind()); }
|
return kind == PNK_ANYNAME || kind == PNK_AT || kind == PNK_DBLCOLON;
|
||||||
bool isAssignment() const { return TokenKindIsAssignment(getKind()); }
|
}
|
||||||
|
bool isAssignment() const {
|
||||||
|
ParseNodeKind kind = getKind();
|
||||||
|
return PNK_ASSIGNMENT_START <= kind && kind <= PNK_ASSIGNMENT_LAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isXMLPropertyIdentifier() const {
|
||||||
|
ParseNodeKind kind = getKind();
|
||||||
|
return kind == PNK_ANYNAME || kind == PNK_AT || kind == PNK_DBLCOLON;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isXMLItem() const {
|
||||||
|
ParseNodeKind kind = getKind();
|
||||||
|
return kind == PNK_XMLCOMMENT || kind == PNK_XMLCDATA || kind == PNK_XMLPI ||
|
||||||
|
kind == PNK_XMLELEM || kind == PNK_XMLLIST;
|
||||||
|
}
|
||||||
|
|
||||||
/* Boolean attributes. */
|
/* Boolean attributes. */
|
||||||
bool isInParens() const { return pn_parens; }
|
bool isInParens() const { return pn_parens; }
|
||||||
|
@ -401,7 +564,7 @@ struct ParseNode {
|
||||||
ParseNode *left;
|
ParseNode *left;
|
||||||
ParseNode *right;
|
ParseNode *right;
|
||||||
Value *pval; /* switch case value */
|
Value *pval; /* switch case value */
|
||||||
uintN iflags; /* JSITER_* flags for TOK_FOR node */
|
uintN iflags; /* JSITER_* flags for PNK_FOR node */
|
||||||
} binary;
|
} binary;
|
||||||
struct { /* one kid if unary */
|
struct { /* one kid if unary */
|
||||||
ParseNode *kid;
|
ParseNode *kid;
|
||||||
|
@ -418,7 +581,7 @@ struct ParseNode {
|
||||||
};
|
};
|
||||||
union {
|
union {
|
||||||
ParseNode *expr; /* function body, var initializer, or
|
ParseNode *expr; /* function body, var initializer, or
|
||||||
base object of TOK_DOT */
|
base object of PNK_DOT */
|
||||||
Definition *lexdef; /* lexical definition for this use */
|
Definition *lexdef; /* lexical definition for this use */
|
||||||
};
|
};
|
||||||
UpvarCookie cookie; /* upvar cookie with absolute frame
|
UpvarCookie cookie; /* upvar cookie with absolute frame
|
||||||
|
@ -482,7 +645,7 @@ struct ParseNode {
|
||||||
pn_next = pn_link = NULL;
|
pn_next = pn_link = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ParseNode *create(ParseNodeArity arity, TreeContext *tc);
|
static ParseNode *create(ParseNodeKind kind, ParseNodeArity arity, TreeContext *tc);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*
|
/*
|
||||||
|
@ -490,7 +653,7 @@ struct ParseNode {
|
||||||
* kind and op, and op must be left-associative.
|
* kind and op, and op must be left-associative.
|
||||||
*/
|
*/
|
||||||
static ParseNode *
|
static ParseNode *
|
||||||
append(TokenKind tt, JSOp op, ParseNode *left, ParseNode *right);
|
append(ParseNodeKind tt, JSOp op, ParseNode *left, ParseNode *right);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Either append right to left, if left meets the conditions necessary to
|
* Either append right to left, if left meets the conditions necessary to
|
||||||
|
@ -498,7 +661,8 @@ struct ParseNode {
|
||||||
* left.
|
* left.
|
||||||
*/
|
*/
|
||||||
static ParseNode *
|
static ParseNode *
|
||||||
newBinaryOrAppend(TokenKind tt, JSOp op, ParseNode *left, ParseNode *right, TreeContext *tc);
|
newBinaryOrAppend(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right,
|
||||||
|
TreeContext *tc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The pn_expr and lexdef members are arms of an unsafe union. Unless you
|
* The pn_expr and lexdef members are arms of an unsafe union. Unless you
|
||||||
|
@ -542,11 +706,11 @@ struct ParseNode {
|
||||||
#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_FUNARG | PND_CLOSED)
|
#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_FUNARG | PND_CLOSED)
|
||||||
|
|
||||||
/* PN_LIST pn_xflags bits. */
|
/* PN_LIST pn_xflags bits. */
|
||||||
#define PNX_STRCAT 0x01 /* TOK_PLUS list has string term */
|
#define PNX_STRCAT 0x01 /* PNK_PLUS list has string term */
|
||||||
#define PNX_CANTFOLD 0x02 /* TOK_PLUS list has unfoldable term */
|
#define PNX_CANTFOLD 0x02 /* PNK_PLUS list has unfoldable term */
|
||||||
#define PNX_POPVAR 0x04 /* TOK_VAR last result needs popping */
|
#define PNX_POPVAR 0x04 /* PNK_VAR last result needs popping */
|
||||||
#define PNX_FORINVAR 0x08 /* TOK_VAR is left kid of TOK_IN node,
|
#define PNX_FORINVAR 0x08 /* PNK_VAR is left kid of PNK_IN node,
|
||||||
which is left kid of TOK_FOR */
|
which is left kid of PNK_FOR */
|
||||||
#define PNX_ENDCOMMA 0x10 /* array literal has comma at end */
|
#define PNX_ENDCOMMA 0x10 /* array literal has comma at end */
|
||||||
#define PNX_XMLROOT 0x20 /* top-most node in XML literal tree */
|
#define PNX_XMLROOT 0x20 /* top-most node in XML literal tree */
|
||||||
#define PNX_GROUPINIT 0x40 /* var [a, b] = [c, d]; unit list */
|
#define PNX_GROUPINIT 0x40 /* var [a, b] = [c, d]; unit list */
|
||||||
|
@ -606,11 +770,11 @@ struct ParseNode {
|
||||||
|
|
||||||
/* True if pn is a parsenode representing a literal constant. */
|
/* True if pn is a parsenode representing a literal constant. */
|
||||||
bool isLiteral() const {
|
bool isLiteral() const {
|
||||||
return isKind(TOK_NUMBER) ||
|
return isKind(PNK_NUMBER) ||
|
||||||
isKind(TOK_STRING) ||
|
isKind(PNK_STRING) ||
|
||||||
isKind(TOK_TRUE) ||
|
isKind(PNK_TRUE) ||
|
||||||
isKind(TOK_FALSE) ||
|
isKind(PNK_FALSE) ||
|
||||||
isKind(TOK_NULL);
|
isKind(PNK_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -629,28 +793,28 @@ struct ParseNode {
|
||||||
* a directive.
|
* a directive.
|
||||||
*/
|
*/
|
||||||
bool isStringExprStatement() const {
|
bool isStringExprStatement() const {
|
||||||
if (getKind() == TOK_SEMI) {
|
if (getKind() == PNK_SEMI) {
|
||||||
JS_ASSERT(pn_arity == PN_UNARY);
|
JS_ASSERT(pn_arity == PN_UNARY);
|
||||||
ParseNode *kid = pn_kid;
|
ParseNode *kid = pn_kid;
|
||||||
return kid && kid->getKind() == TOK_STRING && !kid->pn_parens;
|
return kid && kid->getKind() == PNK_STRING && !kid->pn_parens;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if this node, known to be a string literal, could be the
|
* Return true if this node, known to be an unparenthesized string literal,
|
||||||
* string of a directive in a Directive Prologue. Directive strings never
|
* could be the string of a directive in a Directive Prologue. Directive
|
||||||
* contain escape sequences or line continuations.
|
* strings never contain escape sequences or line continuations.
|
||||||
*/
|
*/
|
||||||
bool isEscapeFreeStringLiteral() const {
|
bool isEscapeFreeStringLiteral() const {
|
||||||
JS_ASSERT(pn_type == TOK_STRING && !pn_parens);
|
JS_ASSERT(isKind(PNK_STRING) && !pn_parens);
|
||||||
JSString *str = pn_atom;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the string's length in the source code is its length as a value,
|
* If the string's length in the source code is its length as a value,
|
||||||
* accounting for the quotes, then it must not contain any escape
|
* accounting for the quotes, then it must not contain any escape
|
||||||
* sequences or line continuations.
|
* sequences or line continuations.
|
||||||
*/
|
*/
|
||||||
|
JSString *str = pn_atom;
|
||||||
return (pn_pos.begin.lineno == pn_pos.end.lineno &&
|
return (pn_pos.begin.lineno == pn_pos.end.lineno &&
|
||||||
pn_pos.begin.index + str->length() + 2 == pn_pos.end.index);
|
pn_pos.begin.index + str->length() + 2 == pn_pos.end.index);
|
||||||
}
|
}
|
||||||
|
@ -663,13 +827,13 @@ struct ParseNode {
|
||||||
* True if this node is a desugared generator expression.
|
* True if this node is a desugared generator expression.
|
||||||
*/
|
*/
|
||||||
bool isGeneratorExpr() const {
|
bool isGeneratorExpr() const {
|
||||||
if (getKind() == TOK_LP) {
|
if (getKind() == PNK_LP) {
|
||||||
ParseNode *callee = this->pn_head;
|
ParseNode *callee = this->pn_head;
|
||||||
if (callee->getKind() == TOK_FUNCTION) {
|
if (callee->getKind() == PNK_FUNCTION) {
|
||||||
ParseNode *body = (callee->pn_body->getKind() == TOK_UPVARS)
|
ParseNode *body = (callee->pn_body->getKind() == PNK_UPVARS)
|
||||||
? callee->pn_body->pn_tree
|
? callee->pn_body->pn_tree
|
||||||
: callee->pn_body;
|
: callee->pn_body;
|
||||||
if (body->getKind() == TOK_LEXICALSCOPE)
|
if (body->getKind() == PNK_LEXICALSCOPE)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -679,10 +843,10 @@ struct ParseNode {
|
||||||
ParseNode *generatorExpr() const {
|
ParseNode *generatorExpr() const {
|
||||||
JS_ASSERT(isGeneratorExpr());
|
JS_ASSERT(isGeneratorExpr());
|
||||||
ParseNode *callee = this->pn_head;
|
ParseNode *callee = this->pn_head;
|
||||||
ParseNode *body = callee->pn_body->getKind() == TOK_UPVARS
|
ParseNode *body = callee->pn_body->getKind() == PNK_UPVARS
|
||||||
? callee->pn_body->pn_tree
|
? callee->pn_body->pn_tree
|
||||||
: callee->pn_body;
|
: callee->pn_body;
|
||||||
JS_ASSERT(body->getKind() == TOK_LEXICALSCOPE);
|
JS_ASSERT(body->getKind() == PNK_LEXICALSCOPE);
|
||||||
return body->pn_expr;
|
return body->pn_expr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -727,46 +891,46 @@ struct ParseNode {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NullaryNode : public ParseNode {
|
struct NullaryNode : public ParseNode {
|
||||||
static inline NullaryNode *create(TreeContext *tc) {
|
static inline NullaryNode *create(ParseNodeKind kind, TreeContext *tc) {
|
||||||
return (NullaryNode *)ParseNode::create(PN_NULLARY, tc);
|
return (NullaryNode *)ParseNode::create(kind, PN_NULLARY, tc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UnaryNode : public ParseNode {
|
struct UnaryNode : public ParseNode {
|
||||||
UnaryNode(TokenKind type, JSOp op, const TokenPos &pos, ParseNode *kid)
|
UnaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *kid)
|
||||||
: ParseNode(type, op, PN_UNARY, pos)
|
: ParseNode(kind, op, PN_UNARY, pos)
|
||||||
{
|
{
|
||||||
pn_kid = kid;
|
pn_kid = kid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline UnaryNode *create(TreeContext *tc) {
|
static inline UnaryNode *create(ParseNodeKind kind, TreeContext *tc) {
|
||||||
return (UnaryNode *)ParseNode::create(PN_UNARY, tc);
|
return (UnaryNode *)ParseNode::create(kind, PN_UNARY, tc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BinaryNode : public ParseNode {
|
struct BinaryNode : public ParseNode {
|
||||||
BinaryNode(TokenKind type, JSOp op, const TokenPos &pos, ParseNode *left, ParseNode *right)
|
BinaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *left, ParseNode *right)
|
||||||
: ParseNode(type, op, PN_BINARY, pos)
|
: ParseNode(kind, op, PN_BINARY, pos)
|
||||||
{
|
{
|
||||||
pn_left = left;
|
pn_left = left;
|
||||||
pn_right = right;
|
pn_right = right;
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryNode(TokenKind type, JSOp op, ParseNode *left, ParseNode *right)
|
BinaryNode(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right)
|
||||||
: ParseNode(type, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos))
|
: ParseNode(kind, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos))
|
||||||
{
|
{
|
||||||
pn_left = left;
|
pn_left = left;
|
||||||
pn_right = right;
|
pn_right = right;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline BinaryNode *create(TreeContext *tc) {
|
static inline BinaryNode *create(ParseNodeKind kind, TreeContext *tc) {
|
||||||
return (BinaryNode *)ParseNode::create(PN_BINARY, tc);
|
return (BinaryNode *)ParseNode::create(kind, PN_BINARY, tc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TernaryNode : public ParseNode {
|
struct TernaryNode : public ParseNode {
|
||||||
TernaryNode(TokenKind type, JSOp op, ParseNode *kid1, ParseNode *kid2, ParseNode *kid3)
|
TernaryNode(ParseNodeKind kind, JSOp op, ParseNode *kid1, ParseNode *kid2, ParseNode *kid3)
|
||||||
: ParseNode(type, op, PN_TERNARY,
|
: ParseNode(kind, op, PN_TERNARY,
|
||||||
TokenPos::make((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin,
|
TokenPos::make((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin,
|
||||||
(kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end))
|
(kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end))
|
||||||
{
|
{
|
||||||
|
@ -775,38 +939,38 @@ struct TernaryNode : public ParseNode {
|
||||||
pn_kid3 = kid3;
|
pn_kid3 = kid3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline TernaryNode *create(TreeContext *tc) {
|
static inline TernaryNode *create(ParseNodeKind kind, TreeContext *tc) {
|
||||||
return (TernaryNode *)ParseNode::create(PN_TERNARY, tc);
|
return (TernaryNode *)ParseNode::create(kind, PN_TERNARY, tc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ListNode : public ParseNode {
|
struct ListNode : public ParseNode {
|
||||||
static inline ListNode *create(TreeContext *tc) {
|
static inline ListNode *create(ParseNodeKind kind, TreeContext *tc) {
|
||||||
return (ListNode *)ParseNode::create(PN_LIST, tc);
|
return (ListNode *)ParseNode::create(kind, PN_LIST, tc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FunctionNode : public ParseNode {
|
struct FunctionNode : public ParseNode {
|
||||||
static inline FunctionNode *create(TreeContext *tc) {
|
static inline FunctionNode *create(ParseNodeKind kind, TreeContext *tc) {
|
||||||
return (FunctionNode *)ParseNode::create(PN_FUNC, tc);
|
return (FunctionNode *)ParseNode::create(kind, PN_FUNC, tc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NameNode : public ParseNode {
|
struct NameNode : public ParseNode {
|
||||||
static NameNode *create(JSAtom *atom, TreeContext *tc);
|
static NameNode *create(ParseNodeKind kind, JSAtom *atom, TreeContext *tc);
|
||||||
|
|
||||||
inline void initCommon(TreeContext *tc);
|
inline void initCommon(TreeContext *tc);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NameSetNode : public ParseNode {
|
struct NameSetNode : public ParseNode {
|
||||||
static inline NameSetNode *create(TreeContext *tc) {
|
static inline NameSetNode *create(ParseNodeKind kind, TreeContext *tc) {
|
||||||
return (NameSetNode *)ParseNode::create(PN_NAMESET, tc);
|
return (NameSetNode *)ParseNode::create(kind, PN_NAMESET, tc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LexicalScopeNode : public ParseNode {
|
struct LexicalScopeNode : public ParseNode {
|
||||||
static inline LexicalScopeNode *create(TreeContext *tc) {
|
static inline LexicalScopeNode *create(ParseNodeKind kind, TreeContext *tc) {
|
||||||
return (LexicalScopeNode *)ParseNode::create(PN_NAME, tc);
|
return (LexicalScopeNode *)ParseNode::create(kind, PN_NAME, tc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -817,7 +981,7 @@ CloneLeftHandSide(ParseNode *opn, TreeContext *tc);
|
||||||
* js::Definition is a degenerate subtype of the PN_FUNC and PN_NAME variants
|
* js::Definition is a degenerate subtype of the PN_FUNC and PN_NAME variants
|
||||||
* of js::ParseNode, allocated only for function, var, const, and let
|
* of js::ParseNode, allocated only for function, var, const, and let
|
||||||
* declarations that define truly lexical bindings. This means that a child of
|
* declarations that define truly lexical bindings. This means that a child of
|
||||||
* a TOK_VAR list may be a Definition instead of a ParseNode. The pn_defn
|
* a PNK_VAR list may be a Definition instead of a ParseNode. The pn_defn
|
||||||
* bit is set for all Definitions, clear otherwise.
|
* bit is set for all Definitions, clear otherwise.
|
||||||
*
|
*
|
||||||
* In an upvars list, defn->resolve() is the outermost definition the
|
* In an upvars list, defn->resolve() is the outermost definition the
|
||||||
|
@ -861,7 +1025,7 @@ CloneLeftHandSide(ParseNode *opn, TreeContext *tc);
|
||||||
* map x to dn via tc->decls;
|
* map x to dn via tc->decls;
|
||||||
* pn = dn;
|
* pn = dn;
|
||||||
* }
|
* }
|
||||||
* insert pn into its parent TOK_VAR list;
|
* insert pn into its parent PNK_VAR list;
|
||||||
* } else {
|
* } else {
|
||||||
* pn = allocate a ParseNode for this reference to x;
|
* pn = allocate a ParseNode for this reference to x;
|
||||||
* dn = lookup x in tc's lexical scope chain;
|
* dn = lookup x in tc's lexical scope chain;
|
||||||
|
@ -973,9 +1137,9 @@ struct Definition : public ParseNode
|
||||||
static const char *kindString(Kind kind);
|
static const char *kindString(Kind kind);
|
||||||
|
|
||||||
Kind kind() {
|
Kind kind() {
|
||||||
if (getKind() == TOK_FUNCTION)
|
if (getKind() == PNK_FUNCTION)
|
||||||
return FUNCTION;
|
return FUNCTION;
|
||||||
JS_ASSERT(getKind() == TOK_NAME);
|
JS_ASSERT(getKind() == PNK_NAME);
|
||||||
if (isOp(JSOP_NOP))
|
if (isOp(JSOP_NOP))
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
if (isOp(JSOP_GETARG))
|
if (isOp(JSOP_GETARG))
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -141,6 +141,12 @@ struct Parser : private AutoGCRooter
|
||||||
return allocator.allocNode();
|
return allocator.allocNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a parse node with the given kind and op using the current token's
|
||||||
|
* atom.
|
||||||
|
*/
|
||||||
|
ParseNode *atomNode(ParseNodeKind kind, JSOp op);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ParseNode *freeTree(ParseNode *pn) { return allocator.freeTree(pn); }
|
ParseNode *freeTree(ParseNode *pn) { return allocator.freeTree(pn); }
|
||||||
void prepareNodeForMutation(ParseNode *pn) { return allocator.prepareNodeForMutation(pn); }
|
void prepareNodeForMutation(ParseNode *pn) { return allocator.prepareNodeForMutation(pn); }
|
||||||
|
@ -218,9 +224,11 @@ struct Parser : private AutoGCRooter
|
||||||
|
|
||||||
ParseNode *functionDef(PropertyName *name, FunctionType type, FunctionSyntaxKind kind);
|
ParseNode *functionDef(PropertyName *name, FunctionType type, FunctionSyntaxKind kind);
|
||||||
|
|
||||||
|
ParseNode *unaryOpExpr(ParseNodeKind kind, JSOp op);
|
||||||
|
|
||||||
ParseNode *condition();
|
ParseNode *condition();
|
||||||
ParseNode *comprehensionTail(ParseNode *kid, uintN blockid, bool isGenexp,
|
ParseNode *comprehensionTail(ParseNode *kid, uintN blockid, bool isGenexp,
|
||||||
TokenKind type = TOK_SEMI, JSOp op = JSOP_NOP);
|
ParseNodeKind kind = PNK_SEMI, JSOp op = JSOP_NOP);
|
||||||
ParseNode *generatorExpr(ParseNode *kid);
|
ParseNode *generatorExpr(ParseNode *kid);
|
||||||
JSBool argumentList(ParseNode *listNode);
|
JSBool argumentList(ParseNode *listNode);
|
||||||
ParseNode *bracketedExpr();
|
ParseNode *bracketedExpr();
|
||||||
|
@ -236,9 +244,8 @@ struct Parser : private AutoGCRooter
|
||||||
ParseNode *qualifiedIdentifier();
|
ParseNode *qualifiedIdentifier();
|
||||||
ParseNode *attributeIdentifier();
|
ParseNode *attributeIdentifier();
|
||||||
ParseNode *xmlExpr(JSBool inTag);
|
ParseNode *xmlExpr(JSBool inTag);
|
||||||
ParseNode *xmlAtomNode();
|
|
||||||
ParseNode *xmlNameExpr();
|
ParseNode *xmlNameExpr();
|
||||||
ParseNode *xmlTagContent(TokenKind tagtype, JSAtom **namep);
|
ParseNode *xmlTagContent(ParseNodeKind tagkind, JSAtom **namep);
|
||||||
JSBool xmlElementContent(ParseNode *pn);
|
JSBool xmlElementContent(ParseNode *pn);
|
||||||
ParseNode *xmlElementOrList(JSBool allowList);
|
ParseNode *xmlElementOrList(JSBool allowList);
|
||||||
ParseNode *xmlElementOrListRoot(JSBool allowList);
|
ParseNode *xmlElementOrListRoot(JSBool allowList);
|
||||||
|
|
|
@ -194,7 +194,7 @@ FindFunArgs(FunctionBox *funbox, int level, FunctionBoxQueue *queue)
|
||||||
uintN skipmin = UpvarCookie::FREE_LEVEL;
|
uintN skipmin = UpvarCookie::FREE_LEVEL;
|
||||||
ParseNode *pn = fn->pn_body;
|
ParseNode *pn = fn->pn_body;
|
||||||
|
|
||||||
if (pn->isKind(TOK_UPVARS)) {
|
if (pn->isKind(PNK_UPVARS)) {
|
||||||
AtomDefnMapPtr &upvars = pn->pn_names;
|
AtomDefnMapPtr &upvars = pn->pn_names;
|
||||||
JS_ASSERT(upvars->count() != 0);
|
JS_ASSERT(upvars->count() != 0);
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ MarkFunArgs(JSContext *cx, FunctionBox *funbox, uint32 functionCount)
|
||||||
JS_ASSERT(fn->isFunArg());
|
JS_ASSERT(fn->isFunArg());
|
||||||
|
|
||||||
ParseNode *pn = fn->pn_body;
|
ParseNode *pn = fn->pn_body;
|
||||||
if (pn->isKind(TOK_UPVARS)) {
|
if (pn->isKind(PNK_UPVARS)) {
|
||||||
AtomDefnMapPtr upvars = pn->pn_names;
|
AtomDefnMapPtr upvars = pn->pn_names;
|
||||||
JS_ASSERT(!upvars->empty());
|
JS_ASSERT(!upvars->empty());
|
||||||
|
|
||||||
|
@ -528,11 +528,11 @@ ConsiderUnbranding(FunctionBox *funbox)
|
||||||
#if JS_HAS_EXPR_CLOSURES
|
#if JS_HAS_EXPR_CLOSURES
|
||||||
{
|
{
|
||||||
ParseNode *pn2 = funbox->node->pn_body;
|
ParseNode *pn2 = funbox->node->pn_body;
|
||||||
if (pn2->isKind(TOK_UPVARS))
|
if (pn2->isKind(PNK_UPVARS))
|
||||||
pn2 = pn2->pn_tree;
|
pn2 = pn2->pn_tree;
|
||||||
if (pn2->isKind(TOK_ARGSBODY))
|
if (pn2->isKind(PNK_ARGSBODY))
|
||||||
pn2 = pn2->last();
|
pn2 = pn2->last();
|
||||||
if (!pn2->isKind(TOK_LC))
|
if (!pn2->isKind(PNK_LC))
|
||||||
returnsExpr = true;
|
returnsExpr = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -585,7 +585,7 @@ SetFunctionKinds(FunctionBox *funbox, uint32 *tcflags, bool isDirectEval)
|
||||||
bool hasUpvars = false;
|
bool hasUpvars = false;
|
||||||
bool canFlatten = true;
|
bool canFlatten = true;
|
||||||
|
|
||||||
if (pn->isKind(TOK_UPVARS)) {
|
if (pn->isKind(PNK_UPVARS)) {
|
||||||
AtomDefnMapPtr upvars = pn->pn_names;
|
AtomDefnMapPtr upvars = pn->pn_names;
|
||||||
JS_ASSERT(!upvars->empty());
|
JS_ASSERT(!upvars->empty());
|
||||||
|
|
||||||
|
@ -630,13 +630,13 @@ SetFunctionKinds(FunctionBox *funbox, uint32 *tcflags, bool isDirectEval)
|
||||||
fn->setOp(JSOP_LAMBDA_FC);
|
fn->setOp(JSOP_LAMBDA_FC);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* js_EmitTree's case TOK_FUNCTION: will select op. */
|
/* js::frontend::EmitTree's PNK_FUNCTION case sets op. */
|
||||||
JS_ASSERT(fn->isOp(JSOP_NOP));
|
JS_ASSERT(fn->isOp(JSOP_NOP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fun->kind() == JSFUN_INTERPRETED && pn->isKind(TOK_UPVARS)) {
|
if (fun->kind() == JSFUN_INTERPRETED && pn->isKind(PNK_UPVARS)) {
|
||||||
/*
|
/*
|
||||||
* One or more upvars cannot be safely snapshot into a flat
|
* One or more upvars cannot be safely snapshot into a flat
|
||||||
* closure's non-reserved slot (see JSOP_GETFCSLOT), so we loop
|
* closure's non-reserved slot (see JSOP_GETFCSLOT), so we loop
|
||||||
|
|
|
@ -2282,14 +2282,8 @@ TokenKindToString(TokenKind tt)
|
||||||
case TOK_XMLELEM: return "TOK_XMLELEM";
|
case TOK_XMLELEM: return "TOK_XMLELEM";
|
||||||
case TOK_XMLLIST: return "TOK_XMLLIST";
|
case TOK_XMLLIST: return "TOK_XMLLIST";
|
||||||
case TOK_YIELD: return "TOK_YIELD";
|
case TOK_YIELD: return "TOK_YIELD";
|
||||||
case TOK_ARRAYCOMP: return "TOK_ARRAYCOMP";
|
|
||||||
case TOK_ARRAYPUSH: return "TOK_ARRAYPUSH";
|
|
||||||
case TOK_LEXICALSCOPE: return "TOK_LEXICALSCOPE";
|
case TOK_LEXICALSCOPE: return "TOK_LEXICALSCOPE";
|
||||||
case TOK_LET: return "TOK_LET";
|
case TOK_LET: return "TOK_LET";
|
||||||
case TOK_SEQ: return "TOK_SEQ";
|
|
||||||
case TOK_FORHEAD: return "TOK_FORHEAD";
|
|
||||||
case TOK_ARGSBODY: return "TOK_ARGSBODY";
|
|
||||||
case TOK_UPVARS: return "TOK_UPVARS";
|
|
||||||
case TOK_RESERVED: return "TOK_RESERVED";
|
case TOK_RESERVED: return "TOK_RESERVED";
|
||||||
case TOK_STRICT_RESERVED: return "TOK_STRICT_RESERVED";
|
case TOK_STRICT_RESERVED: return "TOK_STRICT_RESERVED";
|
||||||
case TOK_STRICTEQ: return "TOK_STRICTEQ";
|
case TOK_STRICTEQ: return "TOK_STRICTEQ";
|
||||||
|
|
|
@ -136,17 +136,8 @@ enum TokenKind {
|
||||||
TOK_XMLELEM, /* XML element node type (no token) */
|
TOK_XMLELEM, /* XML element node type (no token) */
|
||||||
TOK_XMLLIST, /* XML list node type (no token) */
|
TOK_XMLLIST, /* XML list node type (no token) */
|
||||||
TOK_YIELD, /* yield from generator function */
|
TOK_YIELD, /* yield from generator function */
|
||||||
TOK_ARRAYCOMP, /* array comprehension initialiser */
|
|
||||||
TOK_ARRAYPUSH, /* array push within comprehension */
|
|
||||||
TOK_LEXICALSCOPE, /* block scope AST node label */
|
TOK_LEXICALSCOPE, /* block scope AST node label */
|
||||||
TOK_LET, /* let keyword */
|
TOK_LET, /* let keyword */
|
||||||
TOK_SEQ, /* synthetic sequence of statements, not a
|
|
||||||
block */
|
|
||||||
TOK_FORHEAD, /* head of for(;;)-style loop */
|
|
||||||
TOK_ARGSBODY, /* formal args in list + body at end */
|
|
||||||
TOK_UPVARS, /* lexical dependencies as JSAtomDefnMap of
|
|
||||||
definitions paired with a parse tree full
|
|
||||||
of uses of those names */
|
|
||||||
TOK_RESERVED, /* reserved keywords */
|
TOK_RESERVED, /* reserved keywords */
|
||||||
TOK_STRICT_RESERVED, /* reserved keywords in strict mode */
|
TOK_STRICT_RESERVED, /* reserved keywords in strict mode */
|
||||||
|
|
||||||
|
@ -163,13 +154,11 @@ enum TokenKind {
|
||||||
TOK_NE,
|
TOK_NE,
|
||||||
TOK_EQUALITY_LAST = TOK_NE,
|
TOK_EQUALITY_LAST = TOK_NE,
|
||||||
|
|
||||||
/* Unary operation tokens, per TokenKindIsUnaryOp */
|
/* Unary operation tokens */
|
||||||
TOK_TYPEOF,
|
TOK_TYPEOF,
|
||||||
TOK_UNARYOP_START = TOK_TYPEOF,
|
|
||||||
TOK_VOID,
|
TOK_VOID,
|
||||||
TOK_NOT,
|
TOK_NOT,
|
||||||
TOK_BITNOT,
|
TOK_BITNOT,
|
||||||
TOK_UNARYOP_LAST = TOK_BITNOT,
|
|
||||||
|
|
||||||
/* Relational ops (< <= > >=), per TokenKindIsRelational */
|
/* Relational ops (< <= > >=), per TokenKindIsRelational */
|
||||||
TOK_LT,
|
TOK_LT,
|
||||||
|
@ -202,7 +191,6 @@ enum TokenKind {
|
||||||
TOK_MODASSIGN,
|
TOK_MODASSIGN,
|
||||||
TOK_ASSIGNMENT_LAST = TOK_MODASSIGN,
|
TOK_ASSIGNMENT_LAST = TOK_MODASSIGN,
|
||||||
|
|
||||||
|
|
||||||
TOK_LIMIT /* domain size */
|
TOK_LIMIT /* domain size */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -212,12 +200,6 @@ TokenKindIsEquality(TokenKind tt)
|
||||||
return TOK_EQUALITY_START <= tt && tt <= TOK_EQUALITY_LAST;
|
return TOK_EQUALITY_START <= tt && tt <= TOK_EQUALITY_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
|
||||||
TokenKindIsUnaryOp(TokenKind tt)
|
|
||||||
{
|
|
||||||
return TOK_UNARYOP_START <= tt && tt <= TOK_UNARYOP_LAST;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
TokenKindIsXML(TokenKind tt)
|
TokenKindIsXML(TokenKind tt)
|
||||||
{
|
{
|
||||||
|
@ -242,13 +224,6 @@ TokenKindIsAssignment(TokenKind tt)
|
||||||
return TOK_ASSIGNMENT_START <= tt && tt <= TOK_ASSIGNMENT_LAST;
|
return TOK_ASSIGNMENT_START <= tt && tt <= TOK_ASSIGNMENT_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
|
||||||
TreeTypeIsXML(TokenKind tt)
|
|
||||||
{
|
|
||||||
return tt == TOK_XMLCOMMENT || tt == TOK_XMLCDATA || tt == TOK_XMLPI ||
|
|
||||||
tt == TOK_XMLELEM || tt == TOK_XMLLIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
TokenKindIsDecl(TokenKind tt)
|
TokenKindIsDecl(TokenKind tt)
|
||||||
{
|
{
|
||||||
|
@ -542,10 +517,6 @@ class TokenStream
|
||||||
return TokenKindIsEquality(currentToken().type);
|
return TokenKindIsEquality(currentToken().type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCurrentTokenUnaryOp() const {
|
|
||||||
return TokenKindIsUnaryOp(currentToken().type);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isCurrentTokenRelational() const {
|
bool isCurrentTokenRelational() const {
|
||||||
return TokenKindIsRelational(currentToken().type);
|
return TokenKindIsRelational(currentToken().type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1607,8 +1607,8 @@ class ASTSerializer
|
||||||
return StringValue(atom ? atom : cx->runtime->atomState.emptyAtom);
|
return StringValue(atom ? atom : cx->runtime->atomState.emptyAtom);
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryOperator binop(TokenKind tk, JSOp op);
|
BinaryOperator binop(ParseNodeKind kind, JSOp op);
|
||||||
UnaryOperator unop(TokenKind tk, JSOp op);
|
UnaryOperator unop(ParseNodeKind kind, JSOp op);
|
||||||
AssignmentOperator aop(JSOp op);
|
AssignmentOperator aop(JSOp op);
|
||||||
|
|
||||||
bool statements(ParseNode *pn, NodeVector &elts);
|
bool statements(ParseNode *pn, NodeVector &elts);
|
||||||
|
@ -1730,9 +1730,9 @@ ASTSerializer::aop(JSOp op)
|
||||||
}
|
}
|
||||||
|
|
||||||
UnaryOperator
|
UnaryOperator
|
||||||
ASTSerializer::unop(TokenKind tk, JSOp op)
|
ASTSerializer::unop(ParseNodeKind kind, JSOp op)
|
||||||
{
|
{
|
||||||
if (tk == TOK_DELETE)
|
if (kind == PNK_DELETE)
|
||||||
return UNOP_DELETE;
|
return UNOP_DELETE;
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -1755,52 +1755,52 @@ ASTSerializer::unop(TokenKind tk, JSOp op)
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryOperator
|
BinaryOperator
|
||||||
ASTSerializer::binop(TokenKind tk, JSOp op)
|
ASTSerializer::binop(ParseNodeKind kind, JSOp op)
|
||||||
{
|
{
|
||||||
switch (tk) {
|
switch (kind) {
|
||||||
case TOK_LSH:
|
case PNK_LSH:
|
||||||
return BINOP_LSH;
|
return BINOP_LSH;
|
||||||
case TOK_RSH:
|
case PNK_RSH:
|
||||||
return BINOP_RSH;
|
return BINOP_RSH;
|
||||||
case TOK_URSH:
|
case PNK_URSH:
|
||||||
return BINOP_URSH;
|
return BINOP_URSH;
|
||||||
case TOK_LT:
|
case PNK_LT:
|
||||||
return BINOP_LT;
|
return BINOP_LT;
|
||||||
case TOK_LE:
|
case PNK_LE:
|
||||||
return BINOP_LE;
|
return BINOP_LE;
|
||||||
case TOK_GT:
|
case PNK_GT:
|
||||||
return BINOP_GT;
|
return BINOP_GT;
|
||||||
case TOK_GE:
|
case PNK_GE:
|
||||||
return BINOP_GE;
|
return BINOP_GE;
|
||||||
case TOK_EQ:
|
case PNK_EQ:
|
||||||
return BINOP_EQ;
|
return BINOP_EQ;
|
||||||
case TOK_NE:
|
case PNK_NE:
|
||||||
return BINOP_NE;
|
return BINOP_NE;
|
||||||
case TOK_STRICTEQ:
|
case PNK_STRICTEQ:
|
||||||
return BINOP_STRICTEQ;
|
return BINOP_STRICTEQ;
|
||||||
case TOK_STRICTNE:
|
case PNK_STRICTNE:
|
||||||
return BINOP_STRICTNE;
|
return BINOP_STRICTNE;
|
||||||
case TOK_PLUS:
|
case PNK_PLUS:
|
||||||
return BINOP_PLUS;
|
return BINOP_PLUS;
|
||||||
case TOK_MINUS:
|
case PNK_MINUS:
|
||||||
return BINOP_MINUS;
|
return BINOP_MINUS;
|
||||||
case TOK_STAR:
|
case PNK_STAR:
|
||||||
return BINOP_STAR;
|
return BINOP_STAR;
|
||||||
case TOK_DIV:
|
case PNK_DIV:
|
||||||
return BINOP_DIV;
|
return BINOP_DIV;
|
||||||
case TOK_MOD:
|
case PNK_MOD:
|
||||||
return BINOP_MOD;
|
return BINOP_MOD;
|
||||||
case TOK_BITOR:
|
case PNK_BITOR:
|
||||||
return BINOP_BITOR;
|
return BINOP_BITOR;
|
||||||
case TOK_BITXOR:
|
case PNK_BITXOR:
|
||||||
return BINOP_BITXOR;
|
return BINOP_BITXOR;
|
||||||
case TOK_BITAND:
|
case PNK_BITAND:
|
||||||
return BINOP_BITAND;
|
return BINOP_BITAND;
|
||||||
case TOK_IN:
|
case PNK_IN:
|
||||||
return BINOP_IN;
|
return BINOP_IN;
|
||||||
case TOK_INSTANCEOF:
|
case PNK_INSTANCEOF:
|
||||||
return BINOP_INSTANCEOF;
|
return BINOP_INSTANCEOF;
|
||||||
case TOK_DBLDOT:
|
case PNK_DBLDOT:
|
||||||
return BINOP_DBLDOT;
|
return BINOP_DBLDOT;
|
||||||
default:
|
default:
|
||||||
return BINOP_ERR;
|
return BINOP_ERR;
|
||||||
|
@ -1810,7 +1810,7 @@ ASTSerializer::binop(TokenKind tk, JSOp op)
|
||||||
bool
|
bool
|
||||||
ASTSerializer::statements(ParseNode *pn, NodeVector &elts)
|
ASTSerializer::statements(ParseNode *pn, NodeVector &elts)
|
||||||
{
|
{
|
||||||
JS_ASSERT(pn->isKind(TOK_LC) && pn->isArity(PN_LIST));
|
JS_ASSERT(pn->isKind(PNK_LC) && pn->isArity(PN_LIST));
|
||||||
|
|
||||||
if (!elts.reserve(pn->pn_count))
|
if (!elts.reserve(pn->pn_count))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1860,7 +1860,7 @@ ASTSerializer::xmls(ParseNode *pn, NodeVector &elts)
|
||||||
bool
|
bool
|
||||||
ASTSerializer::blockStatement(ParseNode *pn, Value *dst)
|
ASTSerializer::blockStatement(ParseNode *pn, Value *dst)
|
||||||
{
|
{
|
||||||
JS_ASSERT(pn->isKind(TOK_LC));
|
JS_ASSERT(pn->isKind(PNK_LC));
|
||||||
|
|
||||||
NodeVector stmts(cx);
|
NodeVector stmts(cx);
|
||||||
return statements(pn, stmts) &&
|
return statements(pn, stmts) &&
|
||||||
|
@ -1887,17 +1887,17 @@ ASTSerializer::sourceElement(ParseNode *pn, Value *dst)
|
||||||
bool
|
bool
|
||||||
ASTSerializer::declaration(ParseNode *pn, Value *dst)
|
ASTSerializer::declaration(ParseNode *pn, Value *dst)
|
||||||
{
|
{
|
||||||
JS_ASSERT(pn->isKind(TOK_FUNCTION) || pn->isKind(TOK_VAR) || pn->isKind(TOK_LET));
|
JS_ASSERT(pn->isKind(PNK_FUNCTION) || pn->isKind(PNK_VAR) || pn->isKind(PNK_LET));
|
||||||
|
|
||||||
switch (pn->getKind()) {
|
switch (pn->getKind()) {
|
||||||
case TOK_FUNCTION:
|
case PNK_FUNCTION:
|
||||||
return function(pn, AST_FUNC_DECL, dst);
|
return function(pn, AST_FUNC_DECL, dst);
|
||||||
|
|
||||||
case TOK_VAR:
|
case PNK_VAR:
|
||||||
return variableDeclaration(pn, false, dst);
|
return variableDeclaration(pn, false, dst);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
JS_ASSERT(pn->isKind(TOK_LET));
|
JS_ASSERT(pn->isKind(PNK_LET));
|
||||||
return variableDeclaration(pn, true, dst);
|
return variableDeclaration(pn, true, dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1905,7 +1905,7 @@ ASTSerializer::declaration(ParseNode *pn, Value *dst)
|
||||||
bool
|
bool
|
||||||
ASTSerializer::variableDeclaration(ParseNode *pn, bool let, Value *dst)
|
ASTSerializer::variableDeclaration(ParseNode *pn, bool let, Value *dst)
|
||||||
{
|
{
|
||||||
JS_ASSERT(let ? pn->isKind(TOK_LET) : pn->isKind(TOK_VAR));
|
JS_ASSERT(let ? pn->isKind(PNK_LET) : pn->isKind(PNK_VAR));
|
||||||
|
|
||||||
/* Later updated to VARDECL_CONST if we find a PND_CONST declarator. */
|
/* Later updated to VARDECL_CONST if we find a PND_CONST declarator. */
|
||||||
VarDeclKind kind = let ? VARDECL_LET : VARDECL_VAR;
|
VarDeclKind kind = let ? VARDECL_LET : VARDECL_VAR;
|
||||||
|
@ -1936,17 +1936,17 @@ ASTSerializer::variableDeclaration(ParseNode *pn, bool let, Value *dst)
|
||||||
bool
|
bool
|
||||||
ASTSerializer::variableDeclarator(ParseNode *pn, VarDeclKind *pkind, Value *dst)
|
ASTSerializer::variableDeclarator(ParseNode *pn, VarDeclKind *pkind, Value *dst)
|
||||||
{
|
{
|
||||||
/* A destructuring declarator is always a TOK_ASSIGN. */
|
/* A destructuring declarator is always a PNK_ASSIGN. */
|
||||||
JS_ASSERT(pn->isKind(TOK_NAME) || pn->isKind(TOK_ASSIGN));
|
JS_ASSERT(pn->isKind(PNK_NAME) || pn->isKind(PNK_ASSIGN));
|
||||||
|
|
||||||
ParseNode *pnleft;
|
ParseNode *pnleft;
|
||||||
ParseNode *pnright;
|
ParseNode *pnright;
|
||||||
|
|
||||||
if (pn->isKind(TOK_NAME)) {
|
if (pn->isKind(PNK_NAME)) {
|
||||||
pnleft = pn;
|
pnleft = pn;
|
||||||
pnright = pn->isUsed() ? NULL : pn->pn_expr;
|
pnright = pn->isUsed() ? NULL : pn->pn_expr;
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(pn->isKind(TOK_ASSIGN));
|
JS_ASSERT(pn->isKind(PNK_ASSIGN));
|
||||||
pnleft = pn->pn_left;
|
pnleft = pn->pn_left;
|
||||||
pnright = pn->pn_right;
|
pnright = pn->pn_right;
|
||||||
}
|
}
|
||||||
|
@ -2002,7 +2002,7 @@ ASTSerializer::switchStatement(ParseNode *pn, Value *dst)
|
||||||
ParseNode *listNode;
|
ParseNode *listNode;
|
||||||
bool lexical;
|
bool lexical;
|
||||||
|
|
||||||
if (pn->pn_right->isKind(TOK_LEXICALSCOPE)) {
|
if (pn->pn_right->isKind(PNK_LEXICALSCOPE)) {
|
||||||
listNode = pn->pn_right->pn_expr;
|
listNode = pn->pn_right->pn_expr;
|
||||||
lexical = true;
|
lexical = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2071,9 +2071,9 @@ ASTSerializer::forInit(ParseNode *pn, Value *dst)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pn->isKind(TOK_VAR)
|
return pn->isKind(PNK_VAR)
|
||||||
? variableDeclaration(pn, false, dst)
|
? variableDeclaration(pn, false, dst)
|
||||||
: pn->isKind(TOK_LET)
|
: pn->isKind(PNK_LET)
|
||||||
? variableDeclaration(pn, true, dst)
|
? variableDeclaration(pn, true, dst)
|
||||||
: expression(pn, dst);
|
: expression(pn, dst);
|
||||||
}
|
}
|
||||||
|
@ -2083,16 +2083,16 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
|
||||||
{
|
{
|
||||||
JS_CHECK_RECURSION(cx, return false);
|
JS_CHECK_RECURSION(cx, return false);
|
||||||
switch (pn->getKind()) {
|
switch (pn->getKind()) {
|
||||||
case TOK_FUNCTION:
|
case PNK_FUNCTION:
|
||||||
case TOK_VAR:
|
case PNK_VAR:
|
||||||
case TOK_LET:
|
case PNK_LET:
|
||||||
return declaration(pn, dst);
|
return declaration(pn, dst);
|
||||||
|
|
||||||
case TOK_NAME:
|
case PNK_NAME:
|
||||||
LOCAL_ASSERT(pn->isUsed());
|
LOCAL_ASSERT(pn->isUsed());
|
||||||
return statement(pn->pn_lexdef, dst);
|
return statement(pn->pn_lexdef, dst);
|
||||||
|
|
||||||
case TOK_SEMI:
|
case PNK_SEMI:
|
||||||
if (pn->pn_kid) {
|
if (pn->pn_kid) {
|
||||||
Value expr;
|
Value expr;
|
||||||
return expression(pn->pn_kid, &expr) &&
|
return expression(pn->pn_kid, &expr) &&
|
||||||
|
@ -2100,9 +2100,9 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
|
||||||
}
|
}
|
||||||
return builder.emptyStatement(&pn->pn_pos, dst);
|
return builder.emptyStatement(&pn->pn_pos, dst);
|
||||||
|
|
||||||
case TOK_LEXICALSCOPE:
|
case PNK_LEXICALSCOPE:
|
||||||
pn = pn->pn_expr;
|
pn = pn->pn_expr;
|
||||||
if (pn->isKind(TOK_LET)) {
|
if (pn->isKind(PNK_LET)) {
|
||||||
NodeVector dtors(cx);
|
NodeVector dtors(cx);
|
||||||
Value stmt;
|
Value stmt;
|
||||||
|
|
||||||
|
@ -2111,14 +2111,14 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
|
||||||
builder.letStatement(dtors, stmt, &pn->pn_pos, dst);
|
builder.letStatement(dtors, stmt, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pn->isKind(TOK_LC))
|
if (!pn->isKind(PNK_LC))
|
||||||
return statement(pn, dst);
|
return statement(pn, dst);
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
|
|
||||||
case TOK_LC:
|
case PNK_LC:
|
||||||
return blockStatement(pn, dst);
|
return blockStatement(pn, dst);
|
||||||
|
|
||||||
case TOK_IF:
|
case PNK_IF:
|
||||||
{
|
{
|
||||||
Value test, cons, alt;
|
Value test, cons, alt;
|
||||||
|
|
||||||
|
@ -2128,25 +2128,25 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
|
||||||
builder.ifStatement(test, cons, alt, &pn->pn_pos, dst);
|
builder.ifStatement(test, cons, alt, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_SWITCH:
|
case PNK_SWITCH:
|
||||||
return switchStatement(pn, dst);
|
return switchStatement(pn, dst);
|
||||||
|
|
||||||
case TOK_TRY:
|
case PNK_TRY:
|
||||||
return tryStatement(pn, dst);
|
return tryStatement(pn, dst);
|
||||||
|
|
||||||
case TOK_WITH:
|
case PNK_WITH:
|
||||||
case TOK_WHILE:
|
case PNK_WHILE:
|
||||||
{
|
{
|
||||||
Value expr, stmt;
|
Value expr, stmt;
|
||||||
|
|
||||||
return expression(pn->pn_left, &expr) &&
|
return expression(pn->pn_left, &expr) &&
|
||||||
statement(pn->pn_right, &stmt) &&
|
statement(pn->pn_right, &stmt) &&
|
||||||
(pn->isKind(TOK_WITH)
|
(pn->isKind(PNK_WITH)
|
||||||
? builder.withStatement(expr, stmt, &pn->pn_pos, dst)
|
? builder.withStatement(expr, stmt, &pn->pn_pos, dst)
|
||||||
: builder.whileStatement(expr, stmt, &pn->pn_pos, dst));
|
: builder.whileStatement(expr, stmt, &pn->pn_pos, dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_DO:
|
case PNK_DO:
|
||||||
{
|
{
|
||||||
Value stmt, test;
|
Value stmt, test;
|
||||||
|
|
||||||
|
@ -2155,7 +2155,7 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
|
||||||
builder.doWhileStatement(stmt, test, &pn->pn_pos, dst);
|
builder.doWhileStatement(stmt, test, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_FOR:
|
case PNK_FOR:
|
||||||
{
|
{
|
||||||
ParseNode *head = pn->pn_left;
|
ParseNode *head = pn->pn_left;
|
||||||
|
|
||||||
|
@ -2165,13 +2165,13 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
|
||||||
|
|
||||||
bool isForEach = pn->pn_iflags & JSITER_FOREACH;
|
bool isForEach = pn->pn_iflags & JSITER_FOREACH;
|
||||||
|
|
||||||
if (head->isKind(TOK_IN)) {
|
if (head->isKind(PNK_IN)) {
|
||||||
Value var, expr;
|
Value var, expr;
|
||||||
|
|
||||||
return (!head->pn_kid1
|
return (!head->pn_kid1
|
||||||
? pattern(head->pn_kid2, NULL, &var)
|
? pattern(head->pn_kid2, NULL, &var)
|
||||||
: variableDeclaration(head->pn_kid1,
|
: variableDeclaration(head->pn_kid1,
|
||||||
head->pn_kid1->isKind(TOK_LET),
|
head->pn_kid1->isKind(PNK_LET),
|
||||||
&var)) &&
|
&var)) &&
|
||||||
expression(head->pn_kid3, &expr) &&
|
expression(head->pn_kid3, &expr) &&
|
||||||
builder.forInStatement(var, expr, stmt, isForEach, &pn->pn_pos, dst);
|
builder.forInStatement(var, expr, stmt, isForEach, &pn->pn_pos, dst);
|
||||||
|
@ -2186,21 +2186,21 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Synthesized by the parser when a for-in loop contains a variable initializer. */
|
/* Synthesized by the parser when a for-in loop contains a variable initializer. */
|
||||||
case TOK_SEQ:
|
case PNK_SEQ:
|
||||||
{
|
{
|
||||||
LOCAL_ASSERT(pn->pn_count == 2);
|
LOCAL_ASSERT(pn->pn_count == 2);
|
||||||
|
|
||||||
ParseNode *prelude = pn->pn_head;
|
ParseNode *prelude = pn->pn_head;
|
||||||
ParseNode *loop = prelude->pn_next;
|
ParseNode *loop = prelude->pn_next;
|
||||||
|
|
||||||
LOCAL_ASSERT(prelude->isKind(TOK_VAR) && loop->isKind(TOK_FOR));
|
LOCAL_ASSERT(prelude->isKind(PNK_VAR) && loop->isKind(PNK_FOR));
|
||||||
|
|
||||||
Value var;
|
Value var;
|
||||||
if (!variableDeclaration(prelude, false, &var))
|
if (!variableDeclaration(prelude, false, &var))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ParseNode *head = loop->pn_left;
|
ParseNode *head = loop->pn_left;
|
||||||
JS_ASSERT(head->isKind(TOK_IN));
|
JS_ASSERT(head->isKind(PNK_IN));
|
||||||
|
|
||||||
bool isForEach = loop->pn_iflags & JSITER_FOREACH;
|
bool isForEach = loop->pn_iflags & JSITER_FOREACH;
|
||||||
|
|
||||||
|
@ -2211,18 +2211,18 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
|
||||||
builder.forInStatement(var, expr, stmt, isForEach, &pn->pn_pos, dst);
|
builder.forInStatement(var, expr, stmt, isForEach, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_BREAK:
|
case PNK_BREAK:
|
||||||
case TOK_CONTINUE:
|
case PNK_CONTINUE:
|
||||||
{
|
{
|
||||||
Value label;
|
Value label;
|
||||||
|
|
||||||
return optIdentifier(pn->pn_atom, NULL, &label) &&
|
return optIdentifier(pn->pn_atom, NULL, &label) &&
|
||||||
(pn->isKind(TOK_BREAK)
|
(pn->isKind(PNK_BREAK)
|
||||||
? builder.breakStatement(label, &pn->pn_pos, dst)
|
? builder.breakStatement(label, &pn->pn_pos, dst)
|
||||||
: builder.continueStatement(label, &pn->pn_pos, dst));
|
: builder.continueStatement(label, &pn->pn_pos, dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_COLON:
|
case PNK_COLON:
|
||||||
{
|
{
|
||||||
Value label, stmt;
|
Value label, stmt;
|
||||||
|
|
||||||
|
@ -2231,22 +2231,22 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
|
||||||
builder.labeledStatement(label, stmt, &pn->pn_pos, dst);
|
builder.labeledStatement(label, stmt, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_THROW:
|
case PNK_THROW:
|
||||||
case TOK_RETURN:
|
case PNK_RETURN:
|
||||||
{
|
{
|
||||||
Value arg;
|
Value arg;
|
||||||
|
|
||||||
return optExpression(pn->pn_kid, &arg) &&
|
return optExpression(pn->pn_kid, &arg) &&
|
||||||
(pn->isKind(TOK_THROW)
|
(pn->isKind(PNK_THROW)
|
||||||
? builder.throwStatement(arg, &pn->pn_pos, dst)
|
? builder.throwStatement(arg, &pn->pn_pos, dst)
|
||||||
: builder.returnStatement(arg, &pn->pn_pos, dst));
|
: builder.returnStatement(arg, &pn->pn_pos, dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_DEBUGGER:
|
case PNK_DEBUGGER:
|
||||||
return builder.debuggerStatement(&pn->pn_pos, dst);
|
return builder.debuggerStatement(&pn->pn_pos, dst);
|
||||||
|
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
case TOK_DEFAULT:
|
case PNK_DEFAULT:
|
||||||
{
|
{
|
||||||
LOCAL_ASSERT(pn->isArity(PN_UNARY));
|
LOCAL_ASSERT(pn->isArity(PN_UNARY));
|
||||||
|
|
||||||
|
@ -2268,9 +2268,9 @@ ASTSerializer::leftAssociate(ParseNode *pn, Value *dst)
|
||||||
JS_ASSERT(pn->isArity(PN_LIST));
|
JS_ASSERT(pn->isArity(PN_LIST));
|
||||||
JS_ASSERT(pn->pn_count >= 1);
|
JS_ASSERT(pn->pn_count >= 1);
|
||||||
|
|
||||||
TokenKind tk = pn->getKind();
|
ParseNodeKind kind = pn->getKind();
|
||||||
bool lor = tk == TOK_OR;
|
bool lor = kind == PNK_OR;
|
||||||
bool logop = lor || (tk == TOK_AND);
|
bool logop = lor || (kind == PNK_AND);
|
||||||
|
|
||||||
ParseNode *head = pn->pn_head;
|
ParseNode *head = pn->pn_head;
|
||||||
Value left;
|
Value left;
|
||||||
|
@ -2306,7 +2306,7 @@ ASTSerializer::comprehensionBlock(ParseNode *pn, Value *dst)
|
||||||
|
|
||||||
ParseNode *in = pn->pn_left;
|
ParseNode *in = pn->pn_left;
|
||||||
|
|
||||||
LOCAL_ASSERT(in && in->isKind(TOK_IN));
|
LOCAL_ASSERT(in && in->isKind(PNK_IN));
|
||||||
|
|
||||||
bool isForEach = pn->pn_iflags & JSITER_FOREACH;
|
bool isForEach = pn->pn_iflags & JSITER_FOREACH;
|
||||||
|
|
||||||
|
@ -2319,12 +2319,12 @@ ASTSerializer::comprehensionBlock(ParseNode *pn, Value *dst)
|
||||||
bool
|
bool
|
||||||
ASTSerializer::comprehension(ParseNode *pn, Value *dst)
|
ASTSerializer::comprehension(ParseNode *pn, Value *dst)
|
||||||
{
|
{
|
||||||
LOCAL_ASSERT(pn->isKind(TOK_FOR));
|
LOCAL_ASSERT(pn->isKind(PNK_FOR));
|
||||||
|
|
||||||
NodeVector blocks(cx);
|
NodeVector blocks(cx);
|
||||||
|
|
||||||
ParseNode *next = pn;
|
ParseNode *next = pn;
|
||||||
while (next->isKind(TOK_FOR)) {
|
while (next->isKind(PNK_FOR)) {
|
||||||
Value block;
|
Value block;
|
||||||
if (!comprehensionBlock(next, &block) || !blocks.append(block))
|
if (!comprehensionBlock(next, &block) || !blocks.append(block))
|
||||||
return false;
|
return false;
|
||||||
|
@ -2333,17 +2333,17 @@ ASTSerializer::comprehension(ParseNode *pn, Value *dst)
|
||||||
|
|
||||||
Value filter = MagicValue(JS_SERIALIZE_NO_NODE);
|
Value filter = MagicValue(JS_SERIALIZE_NO_NODE);
|
||||||
|
|
||||||
if (next->isKind(TOK_IF)) {
|
if (next->isKind(PNK_IF)) {
|
||||||
if (!optExpression(next->pn_kid1, &filter))
|
if (!optExpression(next->pn_kid1, &filter))
|
||||||
return false;
|
return false;
|
||||||
next = next->pn_kid2;
|
next = next->pn_kid2;
|
||||||
} else if (next->isKind(TOK_LC) && next->pn_count == 0) {
|
} else if (next->isKind(PNK_LC) && next->pn_count == 0) {
|
||||||
/* FoldConstants optimized away the push. */
|
/* FoldConstants optimized away the push. */
|
||||||
NodeVector empty(cx);
|
NodeVector empty(cx);
|
||||||
return builder.arrayExpression(empty, &pn->pn_pos, dst);
|
return builder.arrayExpression(empty, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCAL_ASSERT(next->isKind(TOK_ARRAYPUSH));
|
LOCAL_ASSERT(next->isKind(PNK_ARRAYPUSH));
|
||||||
|
|
||||||
Value body;
|
Value body;
|
||||||
|
|
||||||
|
@ -2354,12 +2354,12 @@ ASTSerializer::comprehension(ParseNode *pn, Value *dst)
|
||||||
bool
|
bool
|
||||||
ASTSerializer::generatorExpression(ParseNode *pn, Value *dst)
|
ASTSerializer::generatorExpression(ParseNode *pn, Value *dst)
|
||||||
{
|
{
|
||||||
LOCAL_ASSERT(pn->isKind(TOK_FOR));
|
LOCAL_ASSERT(pn->isKind(PNK_FOR));
|
||||||
|
|
||||||
NodeVector blocks(cx);
|
NodeVector blocks(cx);
|
||||||
|
|
||||||
ParseNode *next = pn;
|
ParseNode *next = pn;
|
||||||
while (next->isKind(TOK_FOR)) {
|
while (next->isKind(PNK_FOR)) {
|
||||||
Value block;
|
Value block;
|
||||||
if (!comprehensionBlock(next, &block) || !blocks.append(block))
|
if (!comprehensionBlock(next, &block) || !blocks.append(block))
|
||||||
return false;
|
return false;
|
||||||
|
@ -2368,14 +2368,14 @@ ASTSerializer::generatorExpression(ParseNode *pn, Value *dst)
|
||||||
|
|
||||||
Value filter = MagicValue(JS_SERIALIZE_NO_NODE);
|
Value filter = MagicValue(JS_SERIALIZE_NO_NODE);
|
||||||
|
|
||||||
if (next->isKind(TOK_IF)) {
|
if (next->isKind(PNK_IF)) {
|
||||||
if (!optExpression(next->pn_kid1, &filter))
|
if (!optExpression(next->pn_kid1, &filter))
|
||||||
return false;
|
return false;
|
||||||
next = next->pn_kid2;
|
next = next->pn_kid2;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCAL_ASSERT(next->isKind(TOK_SEMI) &&
|
LOCAL_ASSERT(next->isKind(PNK_SEMI) &&
|
||||||
next->pn_kid->isKind(TOK_YIELD) &&
|
next->pn_kid->isKind(PNK_YIELD) &&
|
||||||
next->pn_kid->pn_kid);
|
next->pn_kid->pn_kid);
|
||||||
|
|
||||||
Value body;
|
Value body;
|
||||||
|
@ -2389,17 +2389,17 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
{
|
{
|
||||||
JS_CHECK_RECURSION(cx, return false);
|
JS_CHECK_RECURSION(cx, return false);
|
||||||
switch (pn->getKind()) {
|
switch (pn->getKind()) {
|
||||||
case TOK_FUNCTION:
|
case PNK_FUNCTION:
|
||||||
return function(pn, AST_FUNC_EXPR, dst);
|
return function(pn, AST_FUNC_EXPR, dst);
|
||||||
|
|
||||||
case TOK_COMMA:
|
case PNK_COMMA:
|
||||||
{
|
{
|
||||||
NodeVector exprs(cx);
|
NodeVector exprs(cx);
|
||||||
return expressions(pn, exprs) &&
|
return expressions(pn, exprs) &&
|
||||||
builder.sequenceExpression(exprs, &pn->pn_pos, dst);
|
builder.sequenceExpression(exprs, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_HOOK:
|
case PNK_HOOK:
|
||||||
{
|
{
|
||||||
Value test, cons, alt;
|
Value test, cons, alt;
|
||||||
|
|
||||||
|
@ -2409,22 +2409,22 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
builder.conditionalExpression(test, cons, alt, &pn->pn_pos, dst);
|
builder.conditionalExpression(test, cons, alt, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_OR:
|
case PNK_OR:
|
||||||
case TOK_AND:
|
case PNK_AND:
|
||||||
{
|
{
|
||||||
if (pn->isArity(PN_BINARY)) {
|
if (pn->isArity(PN_BINARY)) {
|
||||||
Value left, right;
|
Value left, right;
|
||||||
return expression(pn->pn_left, &left) &&
|
return expression(pn->pn_left, &left) &&
|
||||||
expression(pn->pn_right, &right) &&
|
expression(pn->pn_right, &right) &&
|
||||||
builder.logicalExpression(pn->isKind(TOK_OR), left, right, &pn->pn_pos, dst);
|
builder.logicalExpression(pn->isKind(PNK_OR), left, right, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
return leftAssociate(pn, dst);
|
return leftAssociate(pn, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_INC:
|
case PNK_INC:
|
||||||
case TOK_DEC:
|
case PNK_DEC:
|
||||||
{
|
{
|
||||||
bool incr = pn->isKind(TOK_INC);
|
bool incr = pn->isKind(PNK_INC);
|
||||||
bool prefix = pn->getOp() >= JSOP_INCNAME && pn->getOp() <= JSOP_DECELEM;
|
bool prefix = pn->getOp() >= JSOP_INCNAME && pn->getOp() <= JSOP_DECELEM;
|
||||||
|
|
||||||
Value expr;
|
Value expr;
|
||||||
|
@ -2432,18 +2432,18 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
builder.updateExpression(expr, incr, prefix, &pn->pn_pos, dst);
|
builder.updateExpression(expr, incr, prefix, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_ASSIGN:
|
case PNK_ASSIGN:
|
||||||
case TOK_ADDASSIGN:
|
case PNK_ADDASSIGN:
|
||||||
case TOK_SUBASSIGN:
|
case PNK_SUBASSIGN:
|
||||||
case TOK_BITORASSIGN:
|
case PNK_BITORASSIGN:
|
||||||
case TOK_BITXORASSIGN:
|
case PNK_BITXORASSIGN:
|
||||||
case TOK_BITANDASSIGN:
|
case PNK_BITANDASSIGN:
|
||||||
case TOK_LSHASSIGN:
|
case PNK_LSHASSIGN:
|
||||||
case TOK_RSHASSIGN:
|
case PNK_RSHASSIGN:
|
||||||
case TOK_URSHASSIGN:
|
case PNK_URSHASSIGN:
|
||||||
case TOK_MULASSIGN:
|
case PNK_MULASSIGN:
|
||||||
case TOK_DIVASSIGN:
|
case PNK_DIVASSIGN:
|
||||||
case TOK_MODASSIGN:
|
case PNK_MODASSIGN:
|
||||||
{
|
{
|
||||||
AssignmentOperator op = aop(pn->getOp());
|
AssignmentOperator op = aop(pn->getOp());
|
||||||
LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT);
|
LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT);
|
||||||
|
@ -2454,31 +2454,31 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
builder.assignmentExpression(op, lhs, rhs, &pn->pn_pos, dst);
|
builder.assignmentExpression(op, lhs, rhs, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_PLUS:
|
case PNK_PLUS:
|
||||||
case TOK_MINUS:
|
case PNK_MINUS:
|
||||||
if (pn->isArity(PN_UNARY))
|
if (pn->isArity(PN_UNARY))
|
||||||
goto unary_plusminus;
|
goto unary_plusminus;
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case TOK_STRICTEQ:
|
case PNK_STRICTEQ:
|
||||||
case TOK_EQ:
|
case PNK_EQ:
|
||||||
case TOK_STRICTNE:
|
case PNK_STRICTNE:
|
||||||
case TOK_NE:
|
case PNK_NE:
|
||||||
case TOK_LT:
|
case PNK_LT:
|
||||||
case TOK_LE:
|
case PNK_LE:
|
||||||
case TOK_GT:
|
case PNK_GT:
|
||||||
case TOK_GE:
|
case PNK_GE:
|
||||||
case TOK_LSH:
|
case PNK_LSH:
|
||||||
case TOK_RSH:
|
case PNK_RSH:
|
||||||
case TOK_URSH:
|
case PNK_URSH:
|
||||||
case TOK_STAR:
|
case PNK_STAR:
|
||||||
case TOK_DIV:
|
case PNK_DIV:
|
||||||
case TOK_MOD:
|
case PNK_MOD:
|
||||||
case TOK_BITOR:
|
case PNK_BITOR:
|
||||||
case TOK_BITXOR:
|
case PNK_BITXOR:
|
||||||
case TOK_BITAND:
|
case PNK_BITAND:
|
||||||
case TOK_IN:
|
case PNK_IN:
|
||||||
case TOK_INSTANCEOF:
|
case PNK_INSTANCEOF:
|
||||||
case TOK_DBLDOT:
|
case PNK_DBLDOT:
|
||||||
if (pn->isArity(PN_BINARY)) {
|
if (pn->isArity(PN_BINARY)) {
|
||||||
BinaryOperator op = binop(pn->getKind(), pn->getOp());
|
BinaryOperator op = binop(pn->getKind(), pn->getOp());
|
||||||
LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
|
LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
|
||||||
|
@ -2490,11 +2490,11 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
}
|
}
|
||||||
return leftAssociate(pn, dst);
|
return leftAssociate(pn, dst);
|
||||||
|
|
||||||
case TOK_DELETE:
|
case PNK_DELETE:
|
||||||
case TOK_TYPEOF:
|
case PNK_TYPEOF:
|
||||||
case TOK_VOID:
|
case PNK_VOID:
|
||||||
case TOK_NOT:
|
case PNK_NOT:
|
||||||
case TOK_BITNOT:
|
case PNK_BITNOT:
|
||||||
unary_plusminus: {
|
unary_plusminus: {
|
||||||
UnaryOperator op = unop(pn->getKind(), pn->getOp());
|
UnaryOperator op = unop(pn->getKind(), pn->getOp());
|
||||||
LOCAL_ASSERT(op > UNOP_ERR && op < UNOP_LIMIT);
|
LOCAL_ASSERT(op > UNOP_ERR && op < UNOP_LIMIT);
|
||||||
|
@ -2504,8 +2504,8 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
builder.unaryExpression(op, expr, &pn->pn_pos, dst);
|
builder.unaryExpression(op, expr, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_NEW:
|
case PNK_NEW:
|
||||||
case TOK_LP:
|
case PNK_LP:
|
||||||
{
|
{
|
||||||
#ifdef JS_HAS_GENERATOR_EXPRS
|
#ifdef JS_HAS_GENERATOR_EXPRS
|
||||||
if (pn->isGeneratorExpr())
|
if (pn->isGeneratorExpr())
|
||||||
|
@ -2529,12 +2529,12 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
args.infallibleAppend(arg);
|
args.infallibleAppend(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pn->isKind(TOK_NEW)
|
return pn->isKind(PNK_NEW)
|
||||||
? builder.newExpression(callee, args, &pn->pn_pos, dst)
|
? builder.newExpression(callee, args, &pn->pn_pos, dst)
|
||||||
: builder.callExpression(callee, args, &pn->pn_pos, dst);
|
: builder.callExpression(callee, args, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_DOT:
|
case PNK_DOT:
|
||||||
{
|
{
|
||||||
Value expr, id;
|
Value expr, id;
|
||||||
return expression(pn->pn_expr, &expr) &&
|
return expression(pn->pn_expr, &expr) &&
|
||||||
|
@ -2542,7 +2542,7 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
builder.memberExpression(false, expr, id, &pn->pn_pos, dst);
|
builder.memberExpression(false, expr, id, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_LB:
|
case PNK_LB:
|
||||||
{
|
{
|
||||||
Value left, right;
|
Value left, right;
|
||||||
return expression(pn->pn_left, &left) &&
|
return expression(pn->pn_left, &left) &&
|
||||||
|
@ -2550,14 +2550,14 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
builder.memberExpression(true, left, right, &pn->pn_pos, dst);
|
builder.memberExpression(true, left, right, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_RB:
|
case PNK_RB:
|
||||||
{
|
{
|
||||||
NodeVector elts(cx);
|
NodeVector elts(cx);
|
||||||
if (!elts.reserve(pn->pn_count))
|
if (!elts.reserve(pn->pn_count))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
|
for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
|
||||||
if (next->isKind(TOK_COMMA)) {
|
if (next->isKind(PNK_COMMA)) {
|
||||||
elts.infallibleAppend(MagicValue(JS_SERIALIZE_NO_NODE));
|
elts.infallibleAppend(MagicValue(JS_SERIALIZE_NO_NODE));
|
||||||
} else {
|
} else {
|
||||||
Value expr;
|
Value expr;
|
||||||
|
@ -2570,7 +2570,7 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
return builder.arrayExpression(elts, &pn->pn_pos, dst);
|
return builder.arrayExpression(elts, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_RC:
|
case PNK_RC:
|
||||||
{
|
{
|
||||||
/* The parser notes any uninitialized properties by setting the PNX_DESTRUCT flag. */
|
/* The parser notes any uninitialized properties by setting the PNX_DESTRUCT flag. */
|
||||||
if (pn->pn_xflags & PNX_DESTRUCT) {
|
if (pn->pn_xflags & PNX_DESTRUCT) {
|
||||||
|
@ -2591,45 +2591,45 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
return builder.objectExpression(elts, &pn->pn_pos, dst);
|
return builder.objectExpression(elts, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_NAME:
|
case PNK_NAME:
|
||||||
return identifier(pn, dst);
|
return identifier(pn, dst);
|
||||||
|
|
||||||
case TOK_THIS:
|
case PNK_THIS:
|
||||||
return builder.thisExpression(&pn->pn_pos, dst);
|
return builder.thisExpression(&pn->pn_pos, dst);
|
||||||
|
|
||||||
case TOK_STRING:
|
case PNK_STRING:
|
||||||
case TOK_REGEXP:
|
case PNK_REGEXP:
|
||||||
case TOK_NUMBER:
|
case PNK_NUMBER:
|
||||||
case TOK_TRUE:
|
case PNK_TRUE:
|
||||||
case TOK_FALSE:
|
case PNK_FALSE:
|
||||||
case TOK_NULL:
|
case PNK_NULL:
|
||||||
return literal(pn, dst);
|
return literal(pn, dst);
|
||||||
|
|
||||||
case TOK_YIELD:
|
case PNK_YIELD:
|
||||||
{
|
{
|
||||||
Value arg;
|
Value arg;
|
||||||
return optExpression(pn->pn_kid, &arg) &&
|
return optExpression(pn->pn_kid, &arg) &&
|
||||||
builder.yieldExpression(arg, &pn->pn_pos, dst);
|
builder.yieldExpression(arg, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_DEFSHARP:
|
case PNK_DEFSHARP:
|
||||||
{
|
{
|
||||||
Value expr;
|
Value expr;
|
||||||
return expression(pn->pn_kid, &expr) &&
|
return expression(pn->pn_kid, &expr) &&
|
||||||
builder.graphExpression(pn->pn_num, expr, &pn->pn_pos, dst);
|
builder.graphExpression(pn->pn_num, expr, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_USESHARP:
|
case PNK_USESHARP:
|
||||||
return builder.graphIndexExpression(pn->pn_num, &pn->pn_pos, dst);
|
return builder.graphIndexExpression(pn->pn_num, &pn->pn_pos, dst);
|
||||||
|
|
||||||
case TOK_ARRAYCOMP:
|
case PNK_ARRAYCOMP:
|
||||||
/* NB: it's no longer the case that pn_count could be 2. */
|
/* NB: it's no longer the case that pn_count could be 2. */
|
||||||
LOCAL_ASSERT(pn->pn_count == 1);
|
LOCAL_ASSERT(pn->pn_count == 1);
|
||||||
LOCAL_ASSERT(pn->pn_head->isKind(TOK_LEXICALSCOPE));
|
LOCAL_ASSERT(pn->pn_head->isKind(PNK_LEXICALSCOPE));
|
||||||
|
|
||||||
return comprehension(pn->pn_head->pn_expr, dst);
|
return comprehension(pn->pn_head->pn_expr, dst);
|
||||||
|
|
||||||
case TOK_LEXICALSCOPE:
|
case PNK_LEXICALSCOPE:
|
||||||
{
|
{
|
||||||
pn = pn->pn_expr;
|
pn = pn->pn_expr;
|
||||||
|
|
||||||
|
@ -2642,7 +2642,7 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JS_HAS_XML_SUPPORT
|
#ifdef JS_HAS_XML_SUPPORT
|
||||||
case TOK_ANYNAME:
|
case PNK_ANYNAME:
|
||||||
if (pn->isOp(JSOP_XMLNAME) ||
|
if (pn->isOp(JSOP_XMLNAME) ||
|
||||||
pn->isOp(JSOP_SETXMLNAME) ||
|
pn->isOp(JSOP_SETXMLNAME) ||
|
||||||
pn->isOp(JSOP_BINDXMLNAME))
|
pn->isOp(JSOP_BINDXMLNAME))
|
||||||
|
@ -2651,7 +2651,7 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
}
|
}
|
||||||
return builder.xmlAnyName(&pn->pn_pos, dst);
|
return builder.xmlAnyName(&pn->pn_pos, dst);
|
||||||
|
|
||||||
case TOK_DBLCOLON:
|
case PNK_DBLCOLON:
|
||||||
{
|
{
|
||||||
if (pn->isOp(JSOP_XMLNAME) ||
|
if (pn->isOp(JSOP_XMLNAME) ||
|
||||||
pn->isOp(JSOP_SETXMLNAME) ||
|
pn->isOp(JSOP_SETXMLNAME) ||
|
||||||
|
@ -2680,7 +2680,7 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pnleft->isKind(TOK_FUNCTION))
|
if (pnleft->isKind(PNK_FUNCTION))
|
||||||
return builder.xmlFunctionQualifiedIdentifier(right, computed, &pn->pn_pos, dst);
|
return builder.xmlFunctionQualifiedIdentifier(right, computed, &pn->pn_pos, dst);
|
||||||
|
|
||||||
Value left;
|
Value left;
|
||||||
|
@ -2688,7 +2688,7 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
builder.xmlQualifiedIdentifier(left, right, computed, &pn->pn_pos, dst);
|
builder.xmlQualifiedIdentifier(left, right, computed, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_AT:
|
case PNK_AT:
|
||||||
{
|
{
|
||||||
if (pn->isOp(JSOP_XMLNAME) ||
|
if (pn->isOp(JSOP_XMLNAME) ||
|
||||||
pn->isOp(JSOP_SETXMLNAME) ||
|
pn->isOp(JSOP_SETXMLNAME) ||
|
||||||
|
@ -2699,14 +2699,14 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
|
||||||
|
|
||||||
Value expr;
|
Value expr;
|
||||||
ParseNode *kid = pn->pn_kid;
|
ParseNode *kid = pn->pn_kid;
|
||||||
bool computed = ((!kid->isKind(TOK_NAME) || !kid->isOp(JSOP_QNAMEPART)) &&
|
bool computed = ((!kid->isKind(PNK_NAME) || !kid->isOp(JSOP_QNAMEPART)) &&
|
||||||
!kid->isKind(TOK_DBLCOLON) &&
|
!kid->isKind(PNK_DBLCOLON) &&
|
||||||
!kid->isKind(TOK_ANYNAME));
|
!kid->isKind(PNK_ANYNAME));
|
||||||
return expression(kid, &expr) &&
|
return expression(kid, &expr) &&
|
||||||
builder.xmlAttributeSelector(expr, computed, &pn->pn_pos, dst);
|
builder.xmlAttributeSelector(expr, computed, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_FILTER:
|
case PNK_FILTER:
|
||||||
{
|
{
|
||||||
Value left, right;
|
Value left, right;
|
||||||
return expression(pn->pn_left, &left) &&
|
return expression(pn->pn_left, &left) &&
|
||||||
|
@ -2730,14 +2730,14 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
|
||||||
JS_CHECK_RECURSION(cx, return false);
|
JS_CHECK_RECURSION(cx, return false);
|
||||||
switch (pn->getKind()) {
|
switch (pn->getKind()) {
|
||||||
#ifdef JS_HAS_XML_SUPPORT
|
#ifdef JS_HAS_XML_SUPPORT
|
||||||
case TOK_LC:
|
case PNK_LC:
|
||||||
{
|
{
|
||||||
Value expr;
|
Value expr;
|
||||||
return expression(pn->pn_kid, &expr) &&
|
return expression(pn->pn_kid, &expr) &&
|
||||||
builder.xmlEscapeExpression(expr, &pn->pn_pos, dst);
|
builder.xmlEscapeExpression(expr, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_XMLELEM:
|
case PNK_XMLELEM:
|
||||||
{
|
{
|
||||||
NodeVector elts(cx);
|
NodeVector elts(cx);
|
||||||
if (!xmls(pn, elts))
|
if (!xmls(pn, elts))
|
||||||
|
@ -2745,7 +2745,7 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
|
||||||
return builder.xmlElement(elts, &pn->pn_pos, dst);
|
return builder.xmlElement(elts, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_XMLLIST:
|
case PNK_XMLLIST:
|
||||||
{
|
{
|
||||||
NodeVector elts(cx);
|
NodeVector elts(cx);
|
||||||
if (!xmls(pn, elts))
|
if (!xmls(pn, elts))
|
||||||
|
@ -2753,7 +2753,7 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
|
||||||
return builder.xmlList(elts, &pn->pn_pos, dst);
|
return builder.xmlList(elts, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_XMLSTAGO:
|
case PNK_XMLSTAGO:
|
||||||
{
|
{
|
||||||
NodeVector elts(cx);
|
NodeVector elts(cx);
|
||||||
if (!xmls(pn, elts))
|
if (!xmls(pn, elts))
|
||||||
|
@ -2761,7 +2761,7 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
|
||||||
return builder.xmlStartTag(elts, &pn->pn_pos, dst);
|
return builder.xmlStartTag(elts, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_XMLETAGO:
|
case PNK_XMLETAGO:
|
||||||
{
|
{
|
||||||
NodeVector elts(cx);
|
NodeVector elts(cx);
|
||||||
if (!xmls(pn, elts))
|
if (!xmls(pn, elts))
|
||||||
|
@ -2769,7 +2769,7 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
|
||||||
return builder.xmlEndTag(elts, &pn->pn_pos, dst);
|
return builder.xmlEndTag(elts, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_XMLPTAGC:
|
case PNK_XMLPTAGC:
|
||||||
{
|
{
|
||||||
NodeVector elts(cx);
|
NodeVector elts(cx);
|
||||||
if (!xmls(pn, elts))
|
if (!xmls(pn, elts))
|
||||||
|
@ -2777,11 +2777,11 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
|
||||||
return builder.xmlPointTag(elts, &pn->pn_pos, dst);
|
return builder.xmlPointTag(elts, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_XMLTEXT:
|
case PNK_XMLTEXT:
|
||||||
case TOK_XMLSPACE:
|
case PNK_XMLSPACE:
|
||||||
return builder.xmlText(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
return builder.xmlText(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
||||||
|
|
||||||
case TOK_XMLNAME:
|
case PNK_XMLNAME:
|
||||||
if (pn->isArity(PN_NULLARY))
|
if (pn->isArity(PN_NULLARY))
|
||||||
return builder.xmlName(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
return builder.xmlName(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
||||||
|
|
||||||
|
@ -2793,16 +2793,16 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
|
||||||
builder.xmlName(elts, &pn->pn_pos, dst);
|
builder.xmlName(elts, &pn->pn_pos, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_XMLATTR:
|
case PNK_XMLATTR:
|
||||||
return builder.xmlAttribute(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
return builder.xmlAttribute(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
||||||
|
|
||||||
case TOK_XMLCDATA:
|
case PNK_XMLCDATA:
|
||||||
return builder.xmlCdata(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
return builder.xmlCdata(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
||||||
|
|
||||||
case TOK_XMLCOMMENT:
|
case PNK_XMLCOMMENT:
|
||||||
return builder.xmlComment(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
return builder.xmlComment(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
||||||
|
|
||||||
case TOK_XMLPI:
|
case PNK_XMLPI:
|
||||||
if (!pn->pn_pidata)
|
if (!pn->pn_pidata)
|
||||||
return builder.xmlPI(atomContents(pn->pn_pitarget), &pn->pn_pos, dst);
|
return builder.xmlPI(atomContents(pn->pn_pitarget), &pn->pn_pos, dst);
|
||||||
else
|
else
|
||||||
|
@ -2820,10 +2820,10 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
|
||||||
bool
|
bool
|
||||||
ASTSerializer::propertyName(ParseNode *pn, Value *dst)
|
ASTSerializer::propertyName(ParseNode *pn, Value *dst)
|
||||||
{
|
{
|
||||||
if (pn->isKind(TOK_NAME))
|
if (pn->isKind(PNK_NAME))
|
||||||
return identifier(pn, dst);
|
return identifier(pn, dst);
|
||||||
|
|
||||||
LOCAL_ASSERT(pn->isKind(TOK_STRING) || pn->isKind(TOK_NUMBER));
|
LOCAL_ASSERT(pn->isKind(PNK_STRING) || pn->isKind(PNK_NUMBER));
|
||||||
|
|
||||||
return literal(pn, dst);
|
return literal(pn, dst);
|
||||||
}
|
}
|
||||||
|
@ -2860,11 +2860,11 @@ ASTSerializer::literal(ParseNode *pn, Value *dst)
|
||||||
{
|
{
|
||||||
Value val;
|
Value val;
|
||||||
switch (pn->getKind()) {
|
switch (pn->getKind()) {
|
||||||
case TOK_STRING:
|
case PNK_STRING:
|
||||||
val.setString(pn->pn_atom);
|
val.setString(pn->pn_atom);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_REGEXP:
|
case PNK_REGEXP:
|
||||||
{
|
{
|
||||||
JSObject *re1 = pn->pn_objbox ? pn->pn_objbox->object : NULL;
|
JSObject *re1 = pn->pn_objbox ? pn->pn_objbox->object : NULL;
|
||||||
LOCAL_ASSERT(re1 && re1->isRegExp());
|
LOCAL_ASSERT(re1 && re1->isRegExp());
|
||||||
|
@ -2881,19 +2881,19 @@ ASTSerializer::literal(ParseNode *pn, Value *dst)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_NUMBER:
|
case PNK_NUMBER:
|
||||||
val.setNumber(pn->pn_dval);
|
val.setNumber(pn->pn_dval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_NULL:
|
case PNK_NULL:
|
||||||
val.setNull();
|
val.setNull();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_TRUE:
|
case PNK_TRUE:
|
||||||
val.setBoolean(true);
|
val.setBoolean(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_FALSE:
|
case PNK_FALSE:
|
||||||
val.setBoolean(false);
|
val.setBoolean(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2907,14 +2907,14 @@ ASTSerializer::literal(ParseNode *pn, Value *dst)
|
||||||
bool
|
bool
|
||||||
ASTSerializer::arrayPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst)
|
ASTSerializer::arrayPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst)
|
||||||
{
|
{
|
||||||
JS_ASSERT(pn->isKind(TOK_RB));
|
JS_ASSERT(pn->isKind(PNK_RB));
|
||||||
|
|
||||||
NodeVector elts(cx);
|
NodeVector elts(cx);
|
||||||
if (!elts.reserve(pn->pn_count))
|
if (!elts.reserve(pn->pn_count))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
|
for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
|
||||||
if (next->isKind(TOK_COMMA)) {
|
if (next->isKind(PNK_COMMA)) {
|
||||||
elts.infallibleAppend(MagicValue(JS_SERIALIZE_NO_NODE));
|
elts.infallibleAppend(MagicValue(JS_SERIALIZE_NO_NODE));
|
||||||
} else {
|
} else {
|
||||||
Value patt;
|
Value patt;
|
||||||
|
@ -2930,7 +2930,7 @@ ASTSerializer::arrayPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst)
|
||||||
bool
|
bool
|
||||||
ASTSerializer::objectPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst)
|
ASTSerializer::objectPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst)
|
||||||
{
|
{
|
||||||
JS_ASSERT(pn->isKind(TOK_RC));
|
JS_ASSERT(pn->isKind(PNK_RC));
|
||||||
|
|
||||||
NodeVector elts(cx);
|
NodeVector elts(cx);
|
||||||
if (!elts.reserve(pn->pn_count))
|
if (!elts.reserve(pn->pn_count))
|
||||||
|
@ -2957,13 +2957,13 @@ ASTSerializer::pattern(ParseNode *pn, VarDeclKind *pkind, Value *dst)
|
||||||
{
|
{
|
||||||
JS_CHECK_RECURSION(cx, return false);
|
JS_CHECK_RECURSION(cx, return false);
|
||||||
switch (pn->getKind()) {
|
switch (pn->getKind()) {
|
||||||
case TOK_RC:
|
case PNK_RC:
|
||||||
return objectPattern(pn, pkind, dst);
|
return objectPattern(pn, pkind, dst);
|
||||||
|
|
||||||
case TOK_RB:
|
case PNK_RB:
|
||||||
return arrayPattern(pn, pkind, dst);
|
return arrayPattern(pn, pkind, dst);
|
||||||
|
|
||||||
case TOK_NAME:
|
case PNK_NAME:
|
||||||
if (pkind && (pn->pn_dflags & PND_CONST))
|
if (pkind && (pn->pn_dflags & PND_CONST))
|
||||||
*pkind = VARDECL_CONST;
|
*pkind = VARDECL_CONST;
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
|
@ -3013,7 +3013,7 @@ ASTSerializer::function(ParseNode *pn, ASTType type, Value *dst)
|
||||||
|
|
||||||
NodeVector args(cx);
|
NodeVector args(cx);
|
||||||
|
|
||||||
ParseNode *argsAndBody = pn->pn_body->isKind(TOK_UPVARS)
|
ParseNode *argsAndBody = pn->pn_body->isKind(PNK_UPVARS)
|
||||||
? pn->pn_body->pn_tree
|
? pn->pn_body->pn_tree
|
||||||
: pn->pn_body;
|
: pn->pn_body;
|
||||||
|
|
||||||
|
@ -3029,7 +3029,7 @@ ASTSerializer::functionArgsAndBody(ParseNode *pn, NodeVector &args, Value *body)
|
||||||
ParseNode *pnbody;
|
ParseNode *pnbody;
|
||||||
|
|
||||||
/* Extract the args and body separately. */
|
/* Extract the args and body separately. */
|
||||||
if (pn->isKind(TOK_ARGSBODY)) {
|
if (pn->isKind(PNK_ARGSBODY)) {
|
||||||
pnargs = pn;
|
pnargs = pn;
|
||||||
pnbody = pn->last();
|
pnbody = pn->last();
|
||||||
} else {
|
} else {
|
||||||
|
@ -3042,30 +3042,30 @@ ASTSerializer::functionArgsAndBody(ParseNode *pn, NodeVector &args, Value *body)
|
||||||
/* Extract the destructuring assignments. */
|
/* Extract the destructuring assignments. */
|
||||||
if (pnbody->isArity(PN_LIST) && (pnbody->pn_xflags & PNX_DESTRUCT)) {
|
if (pnbody->isArity(PN_LIST) && (pnbody->pn_xflags & PNX_DESTRUCT)) {
|
||||||
ParseNode *head = pnbody->pn_head;
|
ParseNode *head = pnbody->pn_head;
|
||||||
LOCAL_ASSERT(head && head->isKind(TOK_SEMI));
|
LOCAL_ASSERT(head && head->isKind(PNK_SEMI));
|
||||||
|
|
||||||
pndestruct = head->pn_kid;
|
pndestruct = head->pn_kid;
|
||||||
LOCAL_ASSERT(pndestruct && pndestruct->isKind(TOK_VAR));
|
LOCAL_ASSERT(pndestruct && pndestruct->isKind(PNK_VAR));
|
||||||
} else {
|
} else {
|
||||||
pndestruct = NULL;
|
pndestruct = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Serialize the arguments and body. */
|
/* Serialize the arguments and body. */
|
||||||
switch (pnbody->getKind()) {
|
switch (pnbody->getKind()) {
|
||||||
case TOK_RETURN: /* expression closure, no destructured args */
|
case PNK_RETURN: /* expression closure, no destructured args */
|
||||||
return functionArgs(pn, pnargs, NULL, pnbody, args) &&
|
return functionArgs(pn, pnargs, NULL, pnbody, args) &&
|
||||||
expression(pnbody->pn_kid, body);
|
expression(pnbody->pn_kid, body);
|
||||||
|
|
||||||
case TOK_SEQ: /* expression closure with destructured args */
|
case PNK_SEQ: /* expression closure with destructured args */
|
||||||
{
|
{
|
||||||
ParseNode *pnstart = pnbody->pn_head->pn_next;
|
ParseNode *pnstart = pnbody->pn_head->pn_next;
|
||||||
LOCAL_ASSERT(pnstart && pnstart->isKind(TOK_RETURN));
|
LOCAL_ASSERT(pnstart && pnstart->isKind(PNK_RETURN));
|
||||||
|
|
||||||
return functionArgs(pn, pnargs, pndestruct, pnbody, args) &&
|
return functionArgs(pn, pnargs, pndestruct, pnbody, args) &&
|
||||||
expression(pnstart->pn_kid, body);
|
expression(pnstart->pn_kid, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_LC: /* statement closure */
|
case PNK_LC: /* statement closure */
|
||||||
{
|
{
|
||||||
ParseNode *pnstart = (pnbody->pn_xflags & PNX_DESTRUCT)
|
ParseNode *pnstart = (pnbody->pn_xflags & PNX_DESTRUCT)
|
||||||
? pnbody->pn_head->pn_next
|
? pnbody->pn_head->pn_next
|
||||||
|
|
|
@ -1313,7 +1313,7 @@ ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN fla
|
||||||
if (!js_EnterLocalRootScope(cx))
|
if (!js_EnterLocalRootScope(cx))
|
||||||
return NULL;
|
return NULL;
|
||||||
switch (pn->getKind()) {
|
switch (pn->getKind()) {
|
||||||
case TOK_XMLELEM:
|
case PNK_XMLELEM:
|
||||||
length = inScopeNSes->length;
|
length = inScopeNSes->length;
|
||||||
pn2 = pn->pn_head;
|
pn2 = pn->pn_head;
|
||||||
xml = ParseNodeToXML(parser, pn2, inScopeNSes, flags);
|
xml = ParseNodeToXML(parser, pn2, inScopeNSes, flags);
|
||||||
|
@ -1330,12 +1330,12 @@ ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN fla
|
||||||
while ((pn2 = pn2->pn_next) != NULL) {
|
while ((pn2 = pn2->pn_next) != NULL) {
|
||||||
if (!pn2->pn_next) {
|
if (!pn2->pn_next) {
|
||||||
/* Don't append the end tag! */
|
/* Don't append the end tag! */
|
||||||
JS_ASSERT(pn2->isKind(TOK_XMLETAGO));
|
JS_ASSERT(pn2->isKind(PNK_XMLETAGO));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & XSF_IGNORE_WHITESPACE) &&
|
if ((flags & XSF_IGNORE_WHITESPACE) &&
|
||||||
n > 1 && pn2->isKind(TOK_XMLSPACE)) {
|
n > 1 && pn2->isKind(PNK_XMLSPACE)) {
|
||||||
--n;
|
--n;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1370,7 +1370,7 @@ ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN fla
|
||||||
XMLARRAY_TRUNCATE(cx, inScopeNSes, length);
|
XMLARRAY_TRUNCATE(cx, inScopeNSes, length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_XMLLIST:
|
case PNK_XMLLIST:
|
||||||
xml = js_NewXML(cx, JSXML_CLASS_LIST);
|
xml = js_NewXML(cx, JSXML_CLASS_LIST);
|
||||||
if (!xml)
|
if (!xml)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1386,7 +1386,7 @@ ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN fla
|
||||||
* condition this on an XML.ignoreWhitespace setting when the list
|
* condition this on an XML.ignoreWhitespace setting when the list
|
||||||
* constructor is XMLList (note XML/XMLList unification hazard).
|
* constructor is XMLList (note XML/XMLList unification hazard).
|
||||||
*/
|
*/
|
||||||
if (pn2->isKind(TOK_XMLSPACE)) {
|
if (pn2->isKind(PNK_XMLSPACE)) {
|
||||||
--n;
|
--n;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1408,11 +1408,11 @@ ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN fla
|
||||||
xml->xml_kids.trim();
|
xml->xml_kids.trim();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_XMLSTAGO:
|
case PNK_XMLSTAGO:
|
||||||
case TOK_XMLPTAGC:
|
case PNK_XMLPTAGC:
|
||||||
length = inScopeNSes->length;
|
length = inScopeNSes->length;
|
||||||
pn2 = pn->pn_head;
|
pn2 = pn->pn_head;
|
||||||
JS_ASSERT(pn2->isKind(TOK_XMLNAME));
|
JS_ASSERT(pn2->isKind(PNK_XMLNAME));
|
||||||
if (pn2->isArity(PN_LIST))
|
if (pn2->isArity(PN_LIST))
|
||||||
goto syntax;
|
goto syntax;
|
||||||
|
|
||||||
|
@ -1429,7 +1429,7 @@ ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN fla
|
||||||
size_t length;
|
size_t length;
|
||||||
const jschar *chars;
|
const jschar *chars;
|
||||||
|
|
||||||
if (!pn2->isKind(TOK_XMLNAME) || !pn2->isArity(PN_NULLARY))
|
if (!pn2->isKind(PNK_XMLNAME) || !pn2->isArity(PN_NULLARY))
|
||||||
goto syntax;
|
goto syntax;
|
||||||
|
|
||||||
/* Enforce "Well-formedness constraint: Unique Att Spec". */
|
/* Enforce "Well-formedness constraint: Unique Att Spec". */
|
||||||
|
@ -1449,7 +1449,7 @@ ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN fla
|
||||||
JSAtom *atom = pn2->pn_atom;
|
JSAtom *atom = pn2->pn_atom;
|
||||||
pn2 = pn2->pn_next;
|
pn2 = pn2->pn_next;
|
||||||
JS_ASSERT(pn2);
|
JS_ASSERT(pn2);
|
||||||
if (!pn2->isKind(TOK_XMLATTR))
|
if (!pn2->isKind(PNK_XMLATTR))
|
||||||
goto syntax;
|
goto syntax;
|
||||||
|
|
||||||
chars = atom->chars();
|
chars = atom->chars();
|
||||||
|
@ -1546,7 +1546,7 @@ ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN fla
|
||||||
|
|
||||||
pn2 = pn2->pn_next;
|
pn2 = pn2->pn_next;
|
||||||
JS_ASSERT(pn2);
|
JS_ASSERT(pn2);
|
||||||
JS_ASSERT(pn2->isKind(TOK_XMLATTR));
|
JS_ASSERT(pn2->isKind(PNK_XMLATTR));
|
||||||
|
|
||||||
attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE);
|
attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE);
|
||||||
if (!attr)
|
if (!attr)
|
||||||
|
@ -1559,22 +1559,22 @@ ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN fla
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Point tag closes its own namespace scope. */
|
/* Point tag closes its own namespace scope. */
|
||||||
if (pn->isKind(TOK_XMLPTAGC))
|
if (pn->isKind(PNK_XMLPTAGC))
|
||||||
XMLARRAY_TRUNCATE(cx, inScopeNSes, length);
|
XMLARRAY_TRUNCATE(cx, inScopeNSes, length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_XMLSPACE:
|
case PNK_XMLSPACE:
|
||||||
case TOK_XMLTEXT:
|
case PNK_XMLTEXT:
|
||||||
case TOK_XMLCDATA:
|
case PNK_XMLCDATA:
|
||||||
case TOK_XMLCOMMENT:
|
case PNK_XMLCOMMENT:
|
||||||
case TOK_XMLPI:
|
case PNK_XMLPI:
|
||||||
str = pn->pn_atom;
|
str = pn->pn_atom;
|
||||||
qn = NULL;
|
qn = NULL;
|
||||||
if (pn->isKind(TOK_XMLCOMMENT)) {
|
if (pn->isKind(PNK_XMLCOMMENT)) {
|
||||||
if (flags & XSF_IGNORE_COMMENTS)
|
if (flags & XSF_IGNORE_COMMENTS)
|
||||||
goto skip_child;
|
goto skip_child;
|
||||||
xml_class = JSXML_CLASS_COMMENT;
|
xml_class = JSXML_CLASS_COMMENT;
|
||||||
} else if (pn->isKind(TOK_XMLPI)) {
|
} else if (pn->isKind(PNK_XMLPI)) {
|
||||||
if (IS_XML(str)) {
|
if (IS_XML(str)) {
|
||||||
Value v = StringValue(str);
|
Value v = StringValue(str);
|
||||||
JSAutoByteString bytes;
|
JSAutoByteString bytes;
|
||||||
|
@ -1603,7 +1603,7 @@ ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN fla
|
||||||
if (!xml)
|
if (!xml)
|
||||||
goto fail;
|
goto fail;
|
||||||
xml->name = qn;
|
xml->name = qn;
|
||||||
if (pn->isKind(TOK_XMLSPACE))
|
if (pn->isKind(PNK_XMLSPACE))
|
||||||
xml->xml_flags |= XMLF_WHITESPACE_TEXT;
|
xml->xml_flags |= XMLF_WHITESPACE_TEXT;
|
||||||
xml->xml_value = str;
|
xml->xml_value = str;
|
||||||
break;
|
break;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче