Backed out changeset 013bde94ad94
authorRobert Sayre <sayrer@gmail.com>
Thu, 06 Jan 2011 21:41:59 -0500
changeset 60204 07e54a3b39db34326f2a1eed8ed74435e3863a07
parent 60173 013bde94ad94215f355d466f2e48bf19214fab03
child 60205 258127ad6756bab8ef7b06079b439689baa68142
push id17881
push usercleary@mozilla.com
push dateFri, 07 Jan 2011 19:57:21 +0000
treeherdermozilla-central@54576be62860 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.0b9pre
backs out013bde94ad94215f355d466f2e48bf19214fab03
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 013bde94ad94
js/src/jsparse.cpp
js/src/tests/ecma_5/strict/11.1.5.js
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -8418,25 +8418,23 @@ Parser::primaryExpr(TokenKind tt, JSBool
       }
 
       case TOK_LC:
       {
         JSBool afterComma;
         JSParseNode *pnval;
 
         /*
-         * A map from property names we've seen thus far to a mask of property
-         * assignment types, stored and retrieved with ALE_SET_INDEX/ALE_INDEX.
+         * A map from property names we've seen thus far to bit masks.
+         * (We use ALE_INDEX/ALE_SET_INDEX).  An atom's mask includes
+         * JSPROP_SETTER if we've seen a setter for it, JSPROP_GETTER
+         * if we've seen as getter, and both of those if we've just
+         * seen an ordinary value.
          */
         JSAutoAtomList seen(tc->parser);
-        enum AssignmentType {
-            GET     = 0x1,
-            SET     = 0x2,
-            VALUE   = 0x4 | GET | SET
-        };
 
         pn = ListNode::create(tc);
         if (!pn)
             return NULL;
         pn->pn_type = TOK_RC;
         pn->pn_op = JSOP_NEWINIT;
         pn->makeEmpty();
 
@@ -8445,18 +8443,26 @@ Parser::primaryExpr(TokenKind tt, JSBool
             JSAtom *atom;
             tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME);
             switch (tt) {
               case TOK_NUMBER:
                 pn3 = NullaryNode::create(tc);
                 if (!pn3)
                     return NULL;
                 pn3->pn_dval = tokenStream.currentToken().t_dval;
-                if (!js_ValueToAtom(context, DoubleValue(pn3->pn_dval), &atom))
-                    return NULL;
+                if (tc->needStrictChecks()) {
+                    /*
+                     * Use string-valued atoms for detecting duplicate
+                     * properties so that 1 and "1" properly collide.
+                     */
+                    if (!js_ValueToAtom(context, DoubleValue(pn3->pn_dval), &atom))
+                        return NULL;
+                } else {
+                    atom = NULL; /* for the compiler */
+                }
                 break;
               case TOK_NAME:
                 {
                     atom = tokenStream.currentToken().t_atom;
                     if (atom == context->runtime->atomState.getAtom)
                         op = JSOP_GETTER;
                     else if (atom == context->runtime->atomState.setAtom)
                         op = JSOP_SETTER;
@@ -8469,18 +8475,26 @@ Parser::primaryExpr(TokenKind tt, JSBool
                         pn3 = NameNode::create(atom, tc);
                         if (!pn3)
                             return NULL;
                     } else if (tt == TOK_NUMBER) {
                         pn3 = NullaryNode::create(tc);
                         if (!pn3)
                             return NULL;
                         pn3->pn_dval = tokenStream.currentToken().t_dval;
-                        if (!js_ValueToAtom(context, DoubleValue(pn3->pn_dval), &atom))
-                            return NULL;
+                        if (tc->needStrictChecks()) {
+                            /*
+                             * Use string-valued atoms for detecting duplicate
+                             * properties so that 1 and "1" properly collide.
+                             */
+                            if (!js_ValueToAtom(context, DoubleValue(pn3->pn_dval), &atom))
+                                return NULL;
+                        } else {
+                            atom = NULL; /* for the compiler */
+                        }
                     } else {
                         tokenStream.ungetToken();
                         goto property_name;
                     }
 
                     pn->pn_xflags |= PNX_NONCONST;
 
                     /* NB: Getter function in { get x(){} } is unnamed. */
@@ -8534,59 +8548,50 @@ Parser::primaryExpr(TokenKind tt, JSBool
 
             pn2 = JSParseNode::newBinaryOrAppend(TOK_COLON, op, pn3, pnval, tc);
           skip:
             if (!pn2)
                 return NULL;
             pn->append(pn2);
 
             /*
-             * Check for duplicate property names.  Duplicate data properties
-             * only conflict in strict mode.  Duplicate getter or duplicate
-             * setter halves always conflict.  A data property conflicts with
-             * any part of an accessor property.
+             * In strict mode code, check for duplicate property names.  Treat
+             * getters and setters as distinct attributes of each property.  A
+             * plain old value conflicts with a getter or a setter.
              */
-            AssignmentType assignType;
-            if (op == JSOP_INITPROP) {
-                assignType = VALUE;
-            } else if (op == JSOP_GETTER) {
-                assignType = GET;
-            } else if (op == JSOP_SETTER) {
-                assignType = SET;
-            } else {
-                JS_NOT_REACHED("bad opcode in object initializer");
-                assignType = VALUE; /* try to error early */
-            }
-
-            if (JSAtomListElement *ale = seen.lookup(atom)) {
-                AssignmentType oldAssignType = AssignmentType(ALE_INDEX(ale));
-                if ((oldAssignType & assignType) &&
-                    (oldAssignType != VALUE || assignType != VALUE || tc->needStrictChecks()))
-                {
-                    JSAutoByteString name;
-                    if (!js_AtomToPrintableString(context, atom, &name))
+            if (tc->needStrictChecks()) {
+                unsigned attributesMask;
+                if (op == JSOP_INITPROP) {
+                    attributesMask = JSPROP_GETTER | JSPROP_SETTER;
+                } else if (op == JSOP_GETTER) {
+                    attributesMask = JSPROP_GETTER;
+                } else if (op == JSOP_SETTER) {
+                    attributesMask = JSPROP_SETTER;
+                } else {
+                    JS_NOT_REACHED("bad opcode in object initializer");
+                    attributesMask = 0;
+                }
+
+                JSAtomListElement *ale = seen.lookup(atom);
+                if (ale) {
+                    if (ALE_INDEX(ale) & attributesMask) {
+                        JSAutoByteString name;
+                        if (!js_AtomToPrintableString(context, atom, &name) ||
+                            !ReportStrictModeError(context, &tokenStream, tc, NULL,
+                                                   JSMSG_DUPLICATE_PROPERTY, name.ptr())) {
+                            return NULL;
+                        }
+                    }
+                    ALE_SET_INDEX(ale, attributesMask | ALE_INDEX(ale));
+                } else {
+                    ale = seen.add(tc->parser, atom);
+                    if (!ale)
                         return NULL;
-
-                    uintN flags = (oldAssignType == VALUE &&
-                                   assignType == VALUE &&
-                                   !tc->inStrictMode())
-                                  ? JSREPORT_WARNING
-                                  : JSREPORT_ERROR;
-                    if (!ReportCompileErrorNumber(context, &tokenStream, NULL, flags,
-                                                  JSMSG_DUPLICATE_PROPERTY, name.ptr()))
-                    {
-                        return NULL;
-                    }
+                    ALE_SET_INDEX(ale, attributesMask);
                 }
-                ALE_SET_INDEX(ale, assignType | oldAssignType);
-            } else {
-                ale = seen.add(tc->parser, atom);
-                if (!ale)
-                    return NULL;
-                ALE_SET_INDEX(ale, assignType);
             }
 
             tt = tokenStream.getToken();
             if (tt == TOK_RC)
                 goto end_obj_init;
             if (tt != TOK_COMMA) {
                 reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_CURLY_AFTER_LIST);
                 return NULL;
--- a/js/src/tests/ecma_5/strict/11.1.5.js
+++ b/js/src/tests/ecma_5/strict/11.1.5.js
@@ -89,82 +89,57 @@ assertEq(testLenientAndStrict('({a:1, b:
                               parseRaisesException(SyntaxError)),
          true);
 
 /*
  * Getters, setters, and value properties should conflict only when
  * appropriate.
  */
 assertEq(testLenientAndStrict('({get x() {}, x:1})',
-                              parseRaisesException(SyntaxError),
+                              parsesSuccessfully,
                               parseRaisesException(SyntaxError)),
          true);
 
 assertEq(testLenientAndStrict('({x:1, get x() {}})',
-                              parseRaisesException(SyntaxError),
+                              parsesSuccessfully,
                               parseRaisesException(SyntaxError)),
          true);
 
 assertEq(testLenientAndStrict('({set x(q) {}, x:1})',
-                              parseRaisesException(SyntaxError),
+                              parsesSuccessfully,
                               parseRaisesException(SyntaxError)),
          true);
 
 assertEq(testLenientAndStrict('({x:1, set x(q) {}})',
-                              parseRaisesException(SyntaxError),
-                              parseRaisesException(SyntaxError)),
-         true);
-
-assertEq(testLenientAndStrict('({1:1, set 1(q) {}})',
-                              parseRaisesException(SyntaxError),
-                              parseRaisesException(SyntaxError)),
-         true);
-
-assertEq(testLenientAndStrict('({set 1(q) {}, 1:1})',
-                              parseRaisesException(SyntaxError),
-                              parseRaisesException(SyntaxError)),
-         true);
-
-assertEq(testLenientAndStrict('({"1":1, set 1(q) {}})',
-                              parseRaisesException(SyntaxError),
-                              parseRaisesException(SyntaxError)),
-         true);
-
-assertEq(testLenientAndStrict('({set 1(q) {}, "1":1})',
-                              parseRaisesException(SyntaxError),
+                              parsesSuccessfully,
                               parseRaisesException(SyntaxError)),
          true);
 
 assertEq(testLenientAndStrict('({get x() {}, set x(q) {}})',
                               parsesSuccessfully,
                               parsesSuccessfully),
          true);
 
 assertEq(testLenientAndStrict('({set x(q) {}, get x() {}})',
                               parsesSuccessfully,
                               parsesSuccessfully),
          true);
 
 assertEq(testLenientAndStrict('({get x() {}, set x(q) {}, x:1})',
-                              parseRaisesException(SyntaxError),
+                              parsesSuccessfully,
                               parseRaisesException(SyntaxError)),
          true);
 
 assertEq(testLenientAndStrict('({set x(q) {}, get x() {}, x:1})',
-                              parseRaisesException(SyntaxError),
+                              parsesSuccessfully,
                               parseRaisesException(SyntaxError)),
          true);
 
 assertEq(testLenientAndStrict('({get x() {}, get x() {}})',
-                              parseRaisesException(SyntaxError),
-                              parseRaisesException(SyntaxError)),
-         true);
-
-assertEq(testLenientAndStrict('({set x() {}, set x() {}})',
-                              parseRaisesException(SyntaxError),
+                              parsesSuccessfully,
                               parseRaisesException(SyntaxError)),
          true);
 
 assertEq(testLenientAndStrict('({get x() {}, set x(q) {}, y:1})',
                               parsesSuccessfully,
                               parsesSuccessfully),
          true);