Bug 1170216 - When using the slow-and-standard path in js::SetIntegrityLevel, don't manually call setNonwritableArrayLength afterwards. r=Waldo.
☠☠ backed out by ed587a5aaecf ☠ ☠
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 01 Jun 2015 12:01:02 -0500
changeset 249240 822901f56c1fe2ed23d638cc90759ffe08a0e93c
parent 249239 94f14d6b26d5e6c060e965c0982708e63d27db66
child 249241 9345403c76288e468409cc12411f8ce16ed1a630
push id61183
push userjorendorff@mozilla.com
push dateWed, 17 Jun 2015 00:50:30 +0000
treeherdermozilla-inbound@9345403c7628 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1170216
milestone41.0a1
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
Bug 1170216 - When using the slow-and-standard path in js::SetIntegrityLevel, don't manually call setNonwritableArrayLength afterwards. r=Waldo.
js/src/jsobj.cpp
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -543,16 +543,29 @@ js::SetIntegrityLevel(JSContext* cx, Han
 
             last = cx->compartment()->propertyTree.getChild(cx, last, *child);
             if (!last)
                 return false;
         }
 
         MOZ_ASSERT(nobj->lastProperty()->slotSpan() == last->slotSpan());
         JS_ALWAYS_TRUE(nobj->setLastProperty(cx, last));
+
+        // Ordinarily ArraySetLength handles this, but we're going behind its back
+        // right now, so we must do this manually.
+        //
+        // ArraySetLength also implements the capacity <= length invariant for
+        // arrays with non-writable length.  We don't need to do anything special
+        // for that, because capacity was zeroed out by preventExtensions.  (See
+        // the assertion about getDenseCapacity above.)
+        if (level == IntegrityLevel::Frozen && obj->is<ArrayObject>()) {
+            if (!obj->as<ArrayObject>().maybeCopyElementsForWrite(cx))
+                return false;
+            obj->as<ArrayObject>().getElementsHeader()->setNonwritableArrayLength();
+        }
     } else {
         RootedId id(cx);
         Rooted<PropertyDescriptor> desc(cx);
 
         const unsigned AllowConfigure = JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_READONLY |
                                         JSPROP_IGNORE_VALUE;
         const unsigned AllowConfigureAndWritable = AllowConfigure & ~JSPROP_IGNORE_READONLY;
 
@@ -581,31 +594,16 @@ js::SetIntegrityLevel(JSContext* cx, Han
             }
 
             // 8.a.i-ii. / 9.a.iii.3-4
             if (!DefineProperty(cx, obj, id, desc))
                 return false;
         }
     }
 
-    // Ordinarily ArraySetLength handles this, but we're going behind its back
-    // right now, so we must do this manually.  Neither the custom property
-    // tree mutations nor the DefineProperty call in the above code will do
-    // this for us.
-    //
-    // ArraySetLength also implements the capacity <= length invariant for
-    // arrays with non-writable length.  We don't need to do anything special
-    // for that, because capacity was zeroed out by preventExtensions.  (See
-    // the assertion before the if-else above.)
-    if (level == IntegrityLevel::Frozen && obj->is<ArrayObject>()) {
-        if (!obj->as<ArrayObject>().maybeCopyElementsForWrite(cx))
-            return false;
-        obj->as<ArrayObject>().getElementsHeader()->setNonwritableArrayLength();
-    }
-
     return true;
 }
 
 // ES6 draft rev33 (12 Feb 2015) 7.3.15
 bool
 js::TestIntegrityLevel(JSContext* cx, HandleObject obj, IntegrityLevel level, bool* result)
 {
     // Steps 3-6. (Steps 1-2 are redundant assertions.)