Bug 1473256 - Don't add a length property in AddLengthProperty if it's already present. r=anba a=lizzard
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 10 Jul 2018 14:32:51 +0200
changeset 478014 0e7242cbb1ce425e8e8caf0457defc0e01881220
parent 478013 1f9ce3126115f82fa8440a311e175e0771183425
child 478015 ce18b96ec82bfaf85bd85c6ad79dad52a063b152
push id9499
push userarchaeopteryx@coole-files.de
push dateThu, 19 Jul 2018 06:52:33 +0000
treeherdermozilla-beta@ce18b96ec82b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersanba, lizzard
bugs1473256
milestone62.0
Bug 1473256 - Don't add a length property in AddLengthProperty if it's already present. r=anba a=lizzard
js/src/builtin/Array.cpp
js/src/jit-test/tests/basic/bug1473256.js
--- a/js/src/builtin/Array.cpp
+++ b/js/src/builtin/Array.cpp
@@ -1010,26 +1010,29 @@ ObjectMayHaveExtraIndexedProperties(JSOb
         if (obj->as<NativeObject>().getDenseInitializedLength() != 0)
             return true;
     } while (true);
 }
 
 static bool
 AddLengthProperty(JSContext* cx, HandleArrayObject obj)
 {
-    /*
-     * Add the 'length' property for a newly created array,
-     * and update the elements to be an empty array owned by the object.
-     * The shared emptyObjectElements singleton cannot be used for slow arrays,
-     * as accesses to 'length' will use the elements header.
-     */
+    // Add the 'length' property for a newly created array. Shapes are shared
+    // across realms within a zone and because we update the initial shape with
+    // a Shape that contains the length-property (in NewArray), it's possible
+    // the length property has already been defined.
+
+    Shape* shape = obj->lastProperty();
+    if (!shape->isEmptyShape()) {
+        MOZ_ASSERT(JSID_IS_ATOM(shape->propidRaw(), cx->names().length));
+        MOZ_ASSERT(shape->previous()->isEmptyShape());
+        return true;
+    }
 
     RootedId lengthId(cx, NameToId(cx->names().length));
-    MOZ_ASSERT(!obj->lookup(cx, lengthId));
-
     return NativeObject::addAccessorProperty(cx, obj, lengthId,
                                              array_length_getter, array_length_setter,
                                              JSPROP_PERMANENT);
 }
 
 static bool
 IsArrayConstructor(const JSObject* obj)
 {
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug1473256.js
@@ -0,0 +1,5 @@
+var a1 = Reflect.construct(Array, [], Object);
+var g = newGlobal({sameZoneAs: this});
+var a2 = new g.Array(1, 2, 3);
+assertEq(a1.length, 0);
+assertEq(a2.length, 3);