Fix broken left-associativity and constant folding for + chains involving some string terms (196290, r=shaver by telepathy).

git-svn-id: svn://10.0.0.236/trunk@139787 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
brendan%mozilla.org 2003-03-19 19:33:33 +00:00
parent c3c549beae
commit 7cc2d1c1ff
2 changed files with 52 additions and 13 deletions

View File

@ -237,14 +237,41 @@ NewBinary(JSContext *cx, JSTokenType tt,
left->pn_arity = PN_LIST;
PN_INIT_LIST_1(left, pn1);
PN_APPEND(left, pn2);
left->pn_strcat = (tt == TOK_PLUS &&
(pn1->pn_type == TOK_STRING ||
pn2->pn_type == TOK_STRING));
left->pn_extra = 0;
if (tt == TOK_PLUS) {
if (pn1->pn_type == TOK_STRING)
left->pn_extra |= PNX_STRCAT;
else if (pn1->pn_type != TOK_NUMBER)
left->pn_extra |= PNX_CANTFOLD;
if (pn2->pn_type == TOK_STRING)
left->pn_extra |= PNX_STRCAT;
else if (pn2->pn_type != TOK_NUMBER)
left->pn_extra |= PNX_CANTFOLD;
}
}
PN_APPEND(left, right);
left->pn_pos.end = right->pn_pos.end;
if (tt == TOK_PLUS && right->pn_type == TOK_STRING)
left->pn_strcat = JS_TRUE;
if (tt == TOK_PLUS) {
if (right->pn_type == TOK_STRING)
left->pn_extra |= PNX_STRCAT;
else if (right->pn_type != TOK_NUMBER)
left->pn_extra |= PNX_CANTFOLD;
}
return left;
}
/*
* Fold constant addition immediately, to conserve node space and, what's
* more, so js_FoldConstants never sees mixed addition and concatenation
* operations with more than one leading non-string operand in a PN_LIST
* generated for expressions such as 1 + 2 + "pt" (which should evaluate
* to "3pt", not "12pt").
*/
if (tt == TOK_PLUS &&
left->pn_type == TOK_NUMBER &&
right->pn_type == TOK_NUMBER) {
left->pn_dval += right->pn_dval;
RecycleTree(right, tc);
return left;
}
@ -3314,9 +3341,15 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc)
jschar *chars;
JSString *str, *str2;
/* Any one string literal operand means this is a concatenation. */
/*
* Any string literal term with all others number or string means
* this is a concatenation. If any term is not a string or number
* literal, we can't fold.
*/
JS_ASSERT(pn->pn_count > 2);
if (!pn->pn_strcat)
if (pn->pn_extra & PNX_CANTFOLD)
return JS_TRUE;
if (pn->pn_extra != PNX_STRCAT)
goto do_binary_op;
/* Ok, we're concatenating: convert non-string constant operands. */

View File

@ -128,11 +128,14 @@ JS_BEGIN_EXTERN_C
* TOK_SHOP binary pn_left: left-assoc SH expr, pn_right: ADD expr
* pn_op: JSOP_LSH, JSOP_RSH, JSOP_URSH
* TOK_PLUS, binary pn_left: left-assoc ADD expr, pn_right: MUL expr
* pn_strcat: if a left-associated binary TOK_PLUS
* pn_extra: if a left-associated binary TOK_PLUS
* tree has been flattened into a list (see above
* under <Expressions>), pn_strcat will be true if
* at least one list element is a string literal
* (TOK_STRING), and false otherwise.
* under <Expressions>), pn_extra will contain
* PNX_STRCAT if at least one list element is a
* string literal (TOK_STRING); if such a list has
* any non-string, non-number term, pn_extra will
* contain PNX_CANTFOLD.
* pn_
* TOK_MINUS pn_op: JSOP_ADD, JSOP_SUB
* TOK_STAR, binary pn_left: left-assoc MUL expr, pn_right: UNARY expr
* TOK_DIVOP pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
@ -198,7 +201,7 @@ struct JSParseNode {
JSParseNode *head; /* first node in list */
JSParseNode **tail; /* ptr to ptr to last node in list */
uint32 count; /* number of nodes in list */
JSBool extra; /* extra comma flag for [1,2,,] */
uint32 extra; /* extra comma flag for [1,2,,] */
} list;
struct { /* ternary: if, for(;;), ?: */
JSParseNode *kid1; /* condition, discriminant, etc. */
@ -233,7 +236,6 @@ struct JSParseNode {
#define pn_tail pn_u.list.tail
#define pn_count pn_u.list.count
#define pn_extra pn_u.list.extra
#define pn_strcat pn_u.list.extra
#define pn_kid1 pn_u.ternary.kid1
#define pn_kid2 pn_u.ternary.kid2
#define pn_kid3 pn_u.ternary.kid3
@ -248,6 +250,10 @@ struct JSParseNode {
#define pn_attrs pn_u.name.attrs
#define pn_dval pn_u.dval
/* PN_LIST pn_extra flags. */
#define PNX_STRCAT 0x1 /* TOK_PLUS list has string term */
#define PNX_CANTFOLD 0x2 /* TOK_PLUS list has unfoldable term */
/*
* Move pn2 into pn, preserving pn->pn_pos and pn->pn_offset and handing off
* any kids in pn2->pn_u, by clearing pn2.