[INFER] Don't bootstrap the __proto__ of the global or Function.prototype if their __proto__ has mutated, bug 642206.
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 17 Mar 2011 10:48:02 -0700
changeset 74797 57e9910e726836134d044a440500fa67bac2f945
parent 74796 54ba422e342996337749c2277a3ea8eee426ee95
child 74798 ecae35e0821df602e346f81e6a9bad047ac9cae6
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs642206
milestone2.0b13pre
[INFER] Don't bootstrap the __proto__ of the global or Function.prototype if their __proto__ has mutated, bug 642206.
js/src/jit-test/tests/basic/bug642206.js
js/src/jsapi.cpp
js/src/jsinfer.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug642206.js
@@ -0,0 +1,30 @@
+this.__proto__ = null;
+
+function testLenientAndStrict(code, lenient_pred, strict_pred) {
+  return (strict_pred("'use strict'; " + code) && 
+          lenient_pred(code));
+}
+function raisesException(exception) {
+  return function (code) {
+    try {
+      eval(code);
+    } catch (actual) {
+    }
+  };
+};
+try {
+function arr() {
+  return Object.defineProperty(Object()* delete Object, 0, {writable: false});
+}
+assertEq(testLenientAndStrict('var a = arr(); [a.splice(0, 1), a]',
+                              raisesException(TypeError),
+                              raisesException(TypeError)),
+         true);
+} catch (e) {}
+ForIn_2(this);
+function ForIn_2(object) {
+  for ( property in object ) {
+    with ( object ) {
+    }
+  }
+}
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1571,20 +1571,24 @@ js_InitFunctionAndObjectClasses(JSContex
     /* Initialize the object class next so Object.prototype works. */
     if (!js_GetClassPrototype(cx, obj, JSProto_Object, &obj_proto))
         return NULL;
     if (!obj_proto)
         obj_proto = js_InitObjectClass(cx, obj);
     if (!obj_proto)
         return NULL;
 
-    /* Function.prototype and the global object delegate to Object.prototype. */
-    if (!fun_proto->getProto())
+    /*
+     * Function.prototype and the global object delegate to Object.prototype.
+     * Don't update the prototype if the __proto__ of either object was cleared
+     * after the objects started getting used.
+     */
+    if (!fun_proto->getProto() && fun_proto->getType() != cx->getTypeEmpty())
         fun_proto->getType()->splicePrototype(cx, obj_proto);
-    if (!obj->getProto())
+    if (!obj->getProto() && obj->getType() != cx->getTypeEmpty())
         obj->getType()->splicePrototype(cx, obj_proto);
 
     return fun_proto;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_InitStandardClasses(JSContext *cx, JSObject *obj)
 {
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -2452,16 +2452,23 @@ TypeObject::getFromPrototypes(JSContext 
          obj = obj->getProto();
      }
 }
 
 void
 TypeObject::splicePrototype(JSContext *cx, JSObject *proto)
 {
     JS_ASSERT(!this->proto);
+
+    /*
+     * Make sure this is not the shared 'empty' type object. :TODO: once we
+     * can mark type objects as singletons, assert that instead.
+     */
+    JS_ASSERT(this != &cx->compartment->types.typeEmpty);
+
     this->proto = proto;
     this->instanceNext = proto->getType()->instanceList;
     proto->getType()->instanceList = this;
 
     if (!cx->typeInferenceEnabled())
         return;
 
     AutoEnterTypeInference enter(cx);