diff --git a/mozilla/js/src/jsparse.c b/mozilla/js/src/jsparse.c index 15656428710..c2e60bf4aaf 100644 --- a/mozilla/js/src/jsparse.c +++ b/mozilla/js/src/jsparse.c @@ -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. */ diff --git a/mozilla/js/src/jsparse.h b/mozilla/js/src/jsparse.h index bc00975878a..ef315fff953 100644 --- a/mozilla/js/src/jsparse.h +++ b/mozilla/js/src/jsparse.h @@ -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 ), pn_strcat will be true if - * at least one list element is a string literal - * (TOK_STRING), and false otherwise. + * under ), 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.