[INFER] Don't swap newTypes for objects during TradeGuts, bug 684348. r=billm
authorBrian Hackett <bhackett1024@gmail.com>
Sun, 04 Sep 2011 13:32:13 -0700
changeset 76578 8385e0145b8dbcc44b5be0baaf17a05e11af0320
parent 76577 f1c28af788ba290cf51f8717004dc8b69eb93e09
child 76579 77e9502bd20f3c61a639f6533535a4f763b8d792
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersbillm
bugs684348
milestone9.0a1
[INFER] Don't swap newTypes for objects during TradeGuts, bug 684348. r=billm
js/src/jit-test/tests/basic/bug684348.js
js/src/jsobj.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug684348.js
@@ -0,0 +1,4 @@
+var x = Proxy.create({ fix: function() { return []; } });
+Object.__proto__ = x;
+Object.freeze(x);
+quit();
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3727,16 +3727,20 @@ JSObject::TradeGuts(JSContext *cx, JSObj
 
     /*
      * Callers should not try to swap dense arrays or ArrayBuffer objects,
      * these use a different slot representation from other objects.
      */
     JS_ASSERT(!a->isDenseArray() && !b->isDenseArray());
     JS_ASSERT(!a->isArrayBuffer() && !b->isArrayBuffer());
 
+    /* New types for a JSObject need to be stable when trading guts. */
+    TypeObject *newTypeA = a->newType;
+    TypeObject *newTypeB = b->newType;
+
     /* Trade the guts of the objects. */
     const size_t size = a->structSize();
     if (size == b->structSize()) {
         /*
          * If the objects are the same size, then we make no assumptions about
          * whether they have dynamically allocated slots and instead just copy
          * them over wholesale.
          */
@@ -3797,16 +3801,19 @@ JSObject::TradeGuts(JSContext *cx, JSObj
         b->capacity = Max(bfixed, acap);
         b->copySlotRange(0, reserved.avals.begin(), acap);
         b->clearSlotRange(acap, b->capacity - acap);
 
         /* Make sure the destructor for reserved doesn't free the slots. */
         reserved.newaslots = NULL;
         reserved.newbslots = NULL;
     }
+
+    a->newType = newTypeA;
+    b->newType = newTypeB;
 }
 
 /*
  * Use this method with extreme caution. It trades the guts of two objects and updates
  * scope ownership. This operation is not thread-safe, just as fast array to slow array
  * transitions are inherently not thread-safe. Don't perform a swap operation on objects
  * shared across threads or, or bad things will happen. You have been warned.
  */