Bug 787856 - Convert JS_GetPrototype to support lazy protos (r=bhackett)
authorBill McCloskey <wmccloskey@mozilla.com>
Mon, 03 Sep 2012 16:42:17 -0700
changeset 108264 fd398d69d052954dc376c64f1e17dbbc05579037
parent 108263 c372439f0aad42d3dd73306c59035f2450d2e1b7
child 108265 7228effb2e5b55055f7d8597a86d42857a270beb
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersbhackett
bugs787856
milestone18.0a1
Bug 787856 - Convert JS_GetPrototype to support lazy protos (r=bhackett)
caps/src/nsSecurityManagerFactory.cpp
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLDocumentInfo.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsGlobalWindow.cpp
dom/bindings/Codegen.py
dom/plugins/base/nsJSNPRuntime.cpp
js/ipc/ObjectWrapperChild.cpp
js/jsd/jsd_val.cpp
js/src/ctypes/CTypes.cpp
js/src/ctypes/CTypes.h
js/src/jsapi-tests/testTypedArrays.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsfriendapi.h
js/xpconnect/src/dombindings.cpp
js/xpconnect/wrappers/ChromeObjectWrapper.cpp
js/xpconnect/wrappers/WrapperFactory.cpp
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/caps/src/nsSecurityManagerFactory.cpp
+++ b/caps/src/nsSecurityManagerFactory.cpp
@@ -78,18 +78,22 @@ nsSecurityNameSet::InitializeNameSet(nsI
 
     /*
      * Find Object.prototype's class by walking up the global object's
      * prototype chain.
      */
     JSObject *obj = global;
     JSObject *proto;
     JSAutoRequest ar(cx);
-    while ((proto = JS_GetPrototype(obj)) != nullptr)
+    for (;;) {
+        MOZ_ALWAYS_TRUE(JS_GetPrototype(cx, obj, &proto));
+        if (!proto)
+            break;
         obj = proto;
+    }
     JSClass *objectClass = JS_GetClass(obj);
 
     JS::Value v;
     if (!JS_GetProperty(cx, global, "netscape", &v))
         return NS_ERROR_FAILURE;
 
     JSObject *securityObj;
     if (v.isObject()) {
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -1212,17 +1212,19 @@ nsXBLBinding::ChangeDocument(nsIDocument
 
               // Find the right prototype.
               JSObject* base = scriptObject;
               JSObject* proto;
               JSAutoRequest ar(cx);
               JSAutoCompartment ac(cx, scriptObject);
 
               for ( ; true; base = proto) { // Will break out on null proto
-                proto = ::JS_GetPrototype(base);
+                if (!JS_GetPrototype(cx, base, &proto)) {
+                  return;
+                }
                 if (!proto) {
                   break;
                 }
 
                 JSClass* clazz = ::JS_GetClass(proto);
                 if (!clazz ||
                     (~clazz->flags &
                      (JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS)) ||
@@ -1244,17 +1246,20 @@ nsXBLBinding::ChangeDocument(nsIDocument
 
                 if (JSVAL_TO_PRIVATE(protoBinding) != mPrototypeBinding) {
                   // Not the right binding
                   continue;
                 }
 
                 // Alright!  This is the right prototype.  Pull it out of the
                 // proto chain.
-                JSObject* grandProto = ::JS_GetPrototype(proto);
+                JSObject* grandProto;
+                if (!JS_GetPrototype(cx, proto, &grandProto)) {
+                  return;
+                }
                 ::JS_SetPrototype(cx, base, grandProto);
                 break;
               }
 
               mPrototypeBinding->UndefineFields(cx, scriptObject);
 
               // Don't remove the reference from the document to the
               // wrapper here since it'll be removed by the element
@@ -1341,17 +1346,19 @@ nsXBLBinding::DoInitJSClass(JSContext *c
   nsAutoCString className(aClassName);
   JSObject* parent_proto = nullptr;  // If we have an "obj" we can set this
   JSAutoRequest ar(cx);
 
   JSAutoCompartment ac(cx, global);
 
   if (obj) {
     // Retrieve the current prototype of obj.
-    parent_proto = ::JS_GetPrototype(obj);
+    if (!JS_GetPrototype(cx, obj, &parent_proto)) {
+      return NS_ERROR_FAILURE;
+    }
     if (parent_proto) {
       // We need to create a unique classname based on aClassName and
       // parent_proto.  Append a space (an invalid URI character) to ensure that
       // we don't have accidental collisions with the case when parent_proto is
       // null and aClassName ends in some bizarre numbers (yeah, it's unlikely).
       jsid parent_proto_id;
       if (!::JS_GetObjectId(cx, parent_proto, &parent_proto_id)) {
         // Probably OOM
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -93,17 +93,19 @@ nsXBLDocGlobalObject::doCheckAccess(JSCo
   if (!ssm) {
     ::JS_ReportError(cx, "Unable to verify access to a global object property.");
     return JS_FALSE;
   }
 
   // Make sure to actually operate on our object, and not some object further
   // down on the proto chain.
   while (JS_GetClass(obj) != &nsXBLDocGlobalObject::gSharedGlobalClass) {
-    obj = ::JS_GetPrototype(obj);
+    if (!::JS_GetPrototype(cx, obj, &obj)) {
+      return JS_FALSE;
+    }
     if (!obj) {
       ::JS_ReportError(cx, "Invalid access to a global object property.");
       return JS_FALSE;
     }
   }
 
   nsresult rv = ssm->CheckPropertyAccess(cx, obj, JS_GetClass(obj)->name,
                                          id, accessType);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -5126,19 +5126,22 @@ nsDOMClassInfo::PostCreatePrototype(JSCo
   // sObjectClass, so compute it here. We assume that nobody has had a
   // chance to monkey around with proto's prototype chain before this.
   if (!sObjectClass) {
     FindObjectClass(cx, proto);
     NS_ASSERTION(sObjectClass && !strcmp(sObjectClass->name, "Object"),
                  "Incorrect object class!");
   }
 
-  NS_ASSERTION(::JS_GetPrototype(proto) &&
-               JS_GetClass(::JS_GetPrototype(proto)) == sObjectClass,
-               "Hmm, somebody did something evil?");
+#ifdef DEBUG
+    JSObject *proto2;
+    JS_GetPrototype(cx, proto, &proto2);
+    NS_ASSERTION(proto2 && JS_GetClass(proto2) == sObjectClass,
+                 "Hmm, somebody did something evil?");
+#endif
 
 #ifdef DEBUG
   if (mData->mHasClassInterface && mData->mProtoChainInterface &&
       mData->mProtoChainInterface != &NS_GET_IID(nsISupports)) {
     nsCOMPtr<nsIInterfaceInfoManager>
       iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
 
     if (iim) {
@@ -5457,17 +5460,20 @@ nsWindowSH::GlobalScopePolluterNewResolv
   nsHTMLDocument *document = GetDocument(obj);
 
   if (!document) {
     // If we don't have a document, return early.
 
     return JS_TRUE;
   }
 
-  JSObject *proto = ::JS_GetPrototype(obj);
+  JSObject *proto;
+  if (!::JS_GetPrototype(cx, obj, &proto)) {
+    return JS_FALSE;
+  }
   JSBool hasProp;
 
   if (!proto || !::JS_HasPropertyById(cx, proto, id, &hasProp) ||
       hasProp) {
     // No prototype, or the property exists on the prototype. Do
     // nothing.
 
     return JS_TRUE;
@@ -5500,40 +5506,54 @@ nsWindowSH::GlobalScopePolluterNewResolv
 
     objp.set(obj);
   }
 
   return JS_TRUE;
 }
 
 // static
-void
+JSBool
 nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
 {
   JSObject *proto;
 
   JSAutoRequest ar(cx);
 
-  while ((proto = ::JS_GetPrototype(obj))) {
+  for (;;) {
+    if (!::JS_GetPrototype(cx, obj, &proto)) {
+      return JS_FALSE;
+    }
+    if (!proto) {
+      break;
+    }
+
     if (JS_GetClass(proto) == &sGlobalScopePolluterClass) {
       nsIHTMLDocument *doc = (nsIHTMLDocument *)::JS_GetPrivate(proto);
 
       NS_IF_RELEASE(doc);
 
       ::JS_SetPrivate(proto, nullptr);
 
+      JSObject *proto_proto;
+      if (!::JS_GetPrototype(cx, proto, &proto_proto)) {
+        return JS_FALSE;
+      }
+
       // Pull the global scope polluter out of the prototype chain so
       // that it can be freed.
-      ::JS_SplicePrototype(cx, obj, ::JS_GetPrototype(proto));
+      ::JS_SplicePrototype(cx, obj, proto_proto);
 
       break;
     }
 
     obj = proto;
   }
+
+  return JS_TRUE;
 }
 
 // static
 nsresult
 nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
                                        nsIHTMLDocument *doc)
 {
   // If global scope pollution is disabled, or if our document is not
@@ -5549,17 +5569,23 @@ nsWindowSH::InstallGlobalScopePolluter(J
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   JSObject *o = obj, *proto;
 
   // Find the place in the prototype chain where we want this global
   // scope polluter (right before Object.prototype).
 
-  while ((proto = ::JS_GetPrototype(o))) {
+  for (;;) {
+    if (!::JS_GetPrototype(cx, o, &proto)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+    if (!proto) {
+      break;
+    }
     if (JS_GetClass(proto) == sObjectClass) {
       // Set the global scope polluters prototype to Object.prototype
       ::JS_SplicePrototype(cx, gsp, proto);
 
       break;
     }
 
     o = proto;
@@ -6317,18 +6343,24 @@ nsDOMConstructor::HasInstance(nsIXPConne
     }
 
     if (JSVAL_IS_PRIMITIVE(val)) {
       return NS_OK;
     }
 
     JSObject *dot_prototype = JSVAL_TO_OBJECT(val);
 
-    JSObject *proto = JS_GetPrototype(dom_obj);
-    for ( ; proto; proto = JS_GetPrototype(proto)) {
+    JSObject *proto = dom_obj;
+    for (;;) {
+      if (!JS_GetPrototype(cx, proto, &proto)) {
+        return NS_ERROR_UNEXPECTED;
+      }
+      if (!proto) {
+        break;
+      }
       if (proto == dot_prototype) {
         *bp = true;
         break;
       }
     }
 
     return NS_OK;
   }
@@ -6677,17 +6709,20 @@ ResolvePrototype(nsIXPConnect *aXPConnec
         if (val.isObject()) {
           proto = &val.toObject();
         }
       }
     }
 
     if (dot_prototype) {
       JSAutoCompartment ac(cx, dot_prototype);
-      JSObject *xpc_proto_proto = ::JS_GetPrototype(dot_prototype);
+      JSObject *xpc_proto_proto;
+      if (!::JS_GetPrototype(cx, dot_prototype, &xpc_proto_proto)) {
+        return NS_ERROR_UNEXPECTED;
+      }
 
       if (proto &&
           (!xpc_proto_proto ||
            JS_GetClass(xpc_proto_proto) == sObjectClass)) {
         if (!JS_WrapObject(cx, &proto) ||
             !JS_SetPrototype(cx, dot_prototype, proto)) {
           return NS_ERROR_UNEXPECTED;
         }
@@ -8423,17 +8458,20 @@ nsNamedArraySH::NewResolve(nsIXPConnectW
 
       if (wrapper) {
         wrapper->GetJSObject(&realObj);
       } else {
         realObj = obj;
       }
 
       JSAutoCompartment ac(cx, realObj);
-      JSObject *proto = ::JS_GetPrototype(realObj);
+      JSObject *proto;
+      if (!::JS_GetPrototype(cx, realObj, &proto)) {
+        return NS_ERROR_FAILURE;
+      }
 
       if (proto) {
         JSBool hasProp;
         if (!::JS_HasPropertyById(cx, proto, id, &hasProp)) {
           *_retval = false;
           return NS_ERROR_FAILURE;
         }
 
@@ -9139,24 +9177,27 @@ nsHTMLDocumentSH::CallToGetPropMapper(JS
   if (!chars) {
     return JS_FALSE;
   }
 
   return ::JS_GetUCProperty(cx, self, chars, length, vp);
 }
 
 
-static inline JSObject *
-GetDocumentAllHelper(JSObject *obj)
+static inline bool
+GetDocumentAllHelper(JSContext *cx, JSObject *obj, JSObject **result)
 {
   while (obj && JS_GetClass(obj) != &sHTMLDocumentAllHelperClass) {
-    obj = ::JS_GetPrototype(obj);
-  }
-
-  return obj;
+    if (!::JS_GetPrototype(cx, obj, &obj)) {
+      return false;
+    }
+  }
+
+  *result = obj;
+  return true;
 }
 
 static inline void *
 FlagsToPrivate(uint32_t flags)
 {
   MOZ_ASSERT((flags & (1 << 31)) == 0);
   return reinterpret_cast<void*>(static_cast<uintptr_t>(flags << 1));
 }
@@ -9172,17 +9213,20 @@ PrivateToFlags(void *priv)
 JSBool
 nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
                                                JSHandleId id, JSMutableHandleValue vp)
 {
   if (nsDOMClassInfo::sAll_id != id) {
     return JS_TRUE;
   }
 
-  JSObject *helper = GetDocumentAllHelper(obj);
+  JSObject *helper;
+  if (!GetDocumentAllHelper(cx, obj, &helper)) {
+    return JS_FALSE;
+  }
 
   if (!helper) {
     NS_ERROR("Uh, how'd we get here?");
 
     // Let scripts continue, if we somehow did get here...
 
     return JS_TRUE;
   }
@@ -9230,17 +9274,20 @@ nsHTMLDocumentSH::DocumentAllHelperGetPr
 
 JSBool
 nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
                                               JSHandleId id, unsigned flags,
                                               JSMutableHandleObject objp)
 {
   if (nsDOMClassInfo::sAll_id == id) {
     // document.all is resolved for the first time. Define it.
-    JSObject *helper = GetDocumentAllHelper(obj);
+    JSObject *helper;
+    if (!GetDocumentAllHelper(cx, obj, &helper)) {
+      return JS_FALSE;
+    }
 
     if (helper) {
       if (!::JS_DefineProperty(cx, helper, "all", JSVAL_VOID, nullptr, nullptr,
                                JSPROP_ENUMERATE)) {
         return JS_FALSE;
       }
 
       objp.set(helper);
@@ -9254,17 +9301,20 @@ nsHTMLDocumentSH::DocumentAllHelperNewRe
 JSBool
 nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
                                             JSHandleId id, unsigned flags,
                                             JSMutableHandleObject objp)
 {
   if (JSID_IS_STRING(id)) {
     nsDocument *doc = GetDocument(obj);
 
-    JSObject *proto = ::JS_GetPrototype(obj);
+    JSObject *proto;
+    if (!::JS_GetPrototype(cx, obj, &proto)) {
+      return JS_FALSE;
+    }
     if (NS_UNLIKELY(!proto)) {
       return JS_TRUE;
     }
 
     JSBool found;
     if (!::JS_HasPropertyById(cx, proto, id, &found)) {
       return JS_FALSE;
     }
@@ -9333,53 +9383,69 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnec
       }
     }
 
     if (id == sAll_id && !sDisableDocumentAllSupport &&
         !ObjectIsNativeWrapper(cx, obj)) {
       nsIDocument *doc = static_cast<nsIDocument*>(wrapper->Native());
 
       if (doc->GetCompatibilityMode() == eCompatibility_NavQuirks) {
-        JSObject *helper = GetDocumentAllHelper(::JS_GetPrototype(obj));
-
-        JSObject *proto = ::JS_GetPrototype(helper ? helper : obj);
+        JSObject *proto;
+        if (!::JS_GetPrototype(cx, obj, &proto)) {
+          return NS_ERROR_FAILURE;
+        }
+
+        JSObject *helper;
+        if (!GetDocumentAllHelper(cx, proto, &helper)) {
+          return NS_ERROR_FAILURE;
+        }
+
+        if (!::JS_GetPrototype(cx, helper ? helper : obj, &proto)) {
+          return NS_ERROR_FAILURE;
+        }
 
         // Check if the property all is defined on obj's (or helper's
         // if obj doesn't exist) prototype, if it is, don't expose our
         // document.all helper.
 
         JSBool hasAll = JS_FALSE;
         if (proto && !JS_HasProperty(cx, proto, "all", &hasAll)) {
           return NS_ERROR_UNEXPECTED;
         }
 
         if (hasAll && helper) {
           // Our helper's prototype now has an "all" property, remove
           // the helper out of the prototype chain to prevent
           // shadowing of the now defined "all" property.
-          JSObject *tmp = obj, *tmpProto;
-
-          while ((tmpProto = ::JS_GetPrototype(tmp)) != helper) {
+          JSObject *tmp = obj, *tmpProto = tmp;
+
+          do {
             tmp = tmpProto;
-          }
+            if (!::JS_GetPrototype(cx, tmp, &tmpProto)) {
+              return NS_ERROR_UNEXPECTED;
+            }
+          } while (tmpProto != helper);
 
           ::JS_SetPrototype(cx, tmp, proto);
         }
 
         // If we don't already have a helper, and we're resolving
         // document.all qualified, and we're *not* detecting
         // document.all, e.g. if (document.all), and "all" isn't
         // already defined on our prototype, create a helper.
         if (!helper && flags & JSRESOLVE_QUALIFIED &&
             !(flags & JSRESOLVE_DETECTING) && !hasAll) {
           // Print a warning so developers can stop using document.all
           PrintWarningOnConsole(cx, "DocumentAllUsed");
 
+          if (!::JS_GetPrototype(cx, obj, &proto)) {
+            return NS_ERROR_UNEXPECTED;
+          }
           helper = ::JS_NewObject(cx, &sHTMLDocumentAllHelperClass,
-                                  ::JS_GetPrototype(obj),
+                                  proto,
                                   ::JS_GetGlobalForObject(cx, obj));
 
           if (!helper) {
             return NS_ERROR_OUT_OF_MEMORY;
           }
 
           // Insert the helper into our prototype chain. helper's prototype
           // is already obj's current prototype.
@@ -9939,17 +10005,20 @@ nsHTMLPluginObjElementSH::PostTransplant
 
 NS_IMETHODIMP
 nsHTMLPluginObjElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
                                       JSContext *cx, JSObject *obj, jsid id,
                                       jsval *vp, bool *_retval)
 {
   JSAutoRequest ar(cx);
 
-  JSObject *pi_obj = ::JS_GetPrototype(obj);
+  JSObject *pi_obj;
+  if (!::JS_GetPrototype(cx, obj, &pi_obj)) {
+    return NS_ERROR_UNEXPECTED;
+  }
   if (NS_UNLIKELY(!pi_obj)) {
     return NS_OK;
   }
 
   JSBool found = false;
 
   if (!ObjectIsNativeWrapper(cx, obj)) {
     *_retval = ::JS_HasPropertyById(cx, pi_obj, id, &found);
@@ -9968,17 +10037,20 @@ nsHTMLPluginObjElementSH::GetProperty(ns
 
 NS_IMETHODIMP
 nsHTMLPluginObjElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
                                       JSContext *cx, JSObject *obj, jsid id,
                                       jsval *vp, bool *_retval)
 {
   JSAutoRequest ar(cx);
 
-  JSObject *pi_obj = ::JS_GetPrototype(obj);
+  JSObject *pi_obj;
+  if (!::JS_GetPrototype(cx, obj, &pi_obj)) {
+    return NS_ERROR_UNEXPECTED;
+  }
   if (NS_UNLIKELY(!pi_obj)) {
     return NS_OK;
   }
 
   JSBool found = false;
 
   if (!ObjectIsNativeWrapper(cx, obj)) {
     *_retval = ::JS_HasPropertyById(cx, pi_obj, id, &found);
@@ -10044,17 +10116,19 @@ nsHTMLPluginObjElementSH::GetPluginJSObj
   // NB: We need an AutoEnterCompartment because we can be called from
   // nsObjectFrame when the plugin loads after the JS object for our content
   // node has been created.
   JSAutoCompartment ac(cx, obj);
 
   if (plugin_inst) {
     plugin_inst->GetJSObject(cx, plugin_obj);
     if (*plugin_obj) {
-      *plugin_proto = ::JS_GetPrototype(*plugin_obj);
+      if (!::JS_GetPrototype(cx, *plugin_obj, plugin_proto)) {
+        return NS_ERROR_UNEXPECTED;
+      }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLPluginObjElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
@@ -10389,17 +10463,20 @@ nsStorage2SH::NewResolve(nsIXPConnectWra
   // First check to see if the property is defined on our prototype,
   // after converting id to a string if it's an integer.
 
   JSString *jsstr = IdToString(cx, id);
   if (!jsstr) {
     return NS_OK;
   }
 
-  JSObject *proto = ::JS_GetPrototype(realObj);
+  JSObject *proto;
+  if (!::JS_GetPrototype(cx, realObj, &proto)) {
+    return NS_ERROR_FAILURE;
+  }
   JSBool hasProp;
 
   if (proto &&
       (::JS_HasPropertyById(cx, proto, id, &hasProp) &&
        hasProp)) {
     // We found the property we're resolving on the prototype,
     // nothing left to do here then.
 
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -415,17 +415,17 @@ public:
                                               JSHandleId id, unsigned flags,
                                               JSMutableHandleObject objp);
   static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
                                                JSHandleId id, JSMutableHandleValue vp);
   static JSBool SecurityCheckOnAddDelProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                           JSMutableHandleValue vp);
   static JSBool SecurityCheckOnSetProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                        JSBool strict, JSMutableHandleValue vp);
-  static void InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
+  static JSBool InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
   static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
                                              nsIHTMLDocument *doc);
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsWindowSH(aData);
   }
 };
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1682,17 +1682,21 @@ nsresult
 nsGlobalWindow::SetOuterObject(JSContext* aCx, JSObject* aOuterObject)
 {
   // Force our context's global object to be the outer.
   // NB: JS_SetGlobalObject sets aCx->compartment.
   JS_SetGlobalObject(aCx, aOuterObject);
 
   // Set up the prototype for the outer object.
   JSObject* inner = JS_GetParent(aOuterObject);
-  JS_SetPrototype(aCx, aOuterObject, JS_GetPrototype(inner));
+  JSObject* proto;
+  if (!JS_GetPrototype(aCx, inner, &proto)) {
+    return NS_ERROR_FAILURE;
+  }
+  JS_SetPrototype(aCx, aOuterObject, proto);
 
   return NS_OK;
 }
 
 /**
  * Create a new global object that will be used for an inner window.
  * Return the native global and an nsISupports 'holder' that can be used
  * to manage the lifetime of it.
@@ -1851,17 +1855,19 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   if (reUseInnerWindow) {
     // We're reusing the current inner window.
     NS_ASSERTION(!currentInner->IsFrozen(),
                  "We should never be reusing a shared inner window");
     newInnerWindow = currentInner;
 
     if (aDocument != oldDoc) {
       xpc_UnmarkGrayObject(currentInner->mJSObject);
-      nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
+      if (!nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject)) {
+        return NS_ERROR_FAILURE;
+      }
     }
 
     // We're reusing the inner window, but this still counts as a navigation,
     // so all expandos and such defined on the outer window should go away. Force
     // all Xray wrappers to be recomputed.
     xpc_UnmarkGrayObject(mJSObject);
     if (!JS_RefreshCrossCompartmentWrappers(cx, mJSObject)) {
       return NS_ERROR_FAILURE;
@@ -1987,17 +1993,18 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       mJSObject = outerObject;
       SetWrapper(mJSObject);
 
       {
         JSAutoCompartment ac(cx, mJSObject);
 
         JS_SetParent(cx, mJSObject, newInnerWindow->mJSObject);
 
-        SetOuterObject(cx, mJSObject);
+        rv = SetOuterObject(cx, mJSObject);
+        NS_ENSURE_SUCCESS(rv, rv);
 
         JSCompartment *compartment = js::GetObjectCompartment(mJSObject);
         xpc::CompartmentPrivate *priv =
           static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(compartment));
         if (priv && priv->waiverWrapperMap) {
           NS_ASSERTION(!JS_IsExceptionPending(cx),
                        "We might overwrite a pending exception!");
           priv->waiverWrapperMap->Reparent(cx, newInnerWindow->mJSObject);
@@ -2044,19 +2051,23 @@ nsGlobalWindow::SetNewDocument(nsIDocume
     JSObject* newInnerJSObject = newInnerWindow->FastGetGlobalJSObject();
 #endif
 
     // Now that we're connecting the outer global to the inner one,
     // we must have transplanted it. The JS engine tries to maintain
     // the global object's compartment as its default compartment,
     // so update that now since it might have changed.
     JS_SetGlobalObject(cx, mJSObject);
-    NS_ASSERTION(JS_GetPrototype(mJSObject) ==
-                 JS_GetPrototype(newInnerJSObject),
+#ifdef DEBUG
+    JSObject *proto1, *proto2;
+    JS_GetPrototype(cx, mJSObject, &proto1);
+    JS_GetPrototype(cx, newInnerJSObject, &proto2);
+    NS_ASSERTION(proto1 == proto2,
                  "outer and inner globals should have the same prototype");
+#endif
 
     nsCOMPtr<nsIContent> frame = do_QueryInterface(GetFrameElementInternal());
     if (frame) {
       nsPIDOMWindow* parentWindow = frame->OwnerDoc()->GetWindow();
       if (parentWindow && parentWindow->TimeoutSuspendCount()) {
         SuspendTimeouts(parentWindow->TimeoutSuspendCount());
       }
     }
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -754,23 +754,26 @@ class CGClassHasInstanceHook(CGAbstractS
   if (!protov.isObject()) {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE,
                          "%s");
     return false;
   }
   JSObject *objProto = &protov.toObject();
 
   JSObject* instance = &vp.toObject();
-  JSObject* proto = JS_GetPrototype(instance);
+  JSObject* proto;
+  if (!JS_GetPrototype(cx, instance, &proto))
+    return false;
   while (proto) {
     if (proto == objProto) {
       *bp = true;
       return true;
     }
-    proto = JS_GetPrototype(proto);
+    if (!JS_GetPrototype(cx, proto, &proto))
+      return false;
   }
 
   nsISupports* native =
     nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, instance);
   nsCOMPtr<%s> qiResult = do_QueryInterface(native);
   *bp = !!qiResult;
   return true;
 """ % (self.descriptor.name, self.descriptor.hasInstanceInterface)
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -1137,17 +1137,19 @@ GetNPObjectWrapper(JSContext *cx, JSObje
 {
   while (obj && (obj = js::UnwrapObjectChecked(cx, obj))) {
     if (JS_GetClass(obj) == &sNPObjectJSWrapperClass) {
       if (wrapResult && !JS_WrapObject(cx, &obj)) {
         return NULL;
       }
       return obj;
     }
-    obj = ::JS_GetPrototype(obj);
+    if (!::JS_GetPrototype(cx, obj, &obj)) {
+      return NULL;
+    }
   }
   return NULL;
 }
 
 static NPObject *
 GetNPObject(JSContext *cx, JSObject *obj)
 {
   obj = GetNPObjectWrapper(cx, obj, /* wrapResult = */ false);
@@ -2049,22 +2051,30 @@ nsJSNPRuntime::OnPluginDestroy(NPP npp)
     ac.construct(cx, obj);
   }
 
   // Loop over the DOM element's JS object prototype chain and remove
   // all JS objects of the class sNPObjectJSWrapperClass (there should
   // be only one, but remove all instances found in case the page put
   // more than one of the plugin's scriptable objects on the prototype
   // chain).
-  while (obj && (proto = ::JS_GetPrototype(obj))) {
+  while (obj) {
+    if (!::JS_GetPrototype(cx, obj, &proto)) {
+      return;
+    }
+    if (!proto) {
+      break;
+    }
     // Unwrap while checking the jsclass - if the prototype is a wrapper for
     // an NP object, that counts too.
     if (JS_GetClass(js::UnwrapObject(proto)) == &sNPObjectJSWrapperClass) {
       // We found an NPObject on the proto chain, get its prototype...
-      proto = ::JS_GetPrototype(proto);
+      if (!::JS_GetPrototype(cx, proto, &proto)) {
+        return;
+      }
 
       // ... and pull it out of the chain.
       ::JS_SetPrototype(cx, obj, proto);
     }
 
     obj = proto;
   }
 }
--- a/js/ipc/ObjectWrapperChild.cpp
+++ b/js/ipc/ObjectWrapperChild.cpp
@@ -417,24 +417,24 @@ ObjectWrapperChild::AnswerNewEnumerateIn
     AutoCheckOperation aco(this, status);
 
     JSClass* clasp = const_cast<JSClass*>(&sCPOW_NewEnumerateState_JSClass);
     JSObject* state = JS_NewObjectWithGivenProto(cx, clasp, NULL, NULL);
     if (!state)
         return false;
     AutoObjectRooter tvr(cx, state);
 
-    for (JSObject* proto = mObj;
-         proto;
-         proto = JS_GetPrototype(proto))
-    {
+    for (JSObject* proto = mObj; proto; ) {
         AutoIdArray ids(cx, JS_Enumerate(cx, proto));
         for (size_t i = 0; i < ids.length(); ++i)
             JS_DefinePropertyById(cx, state, ids[i], JSVAL_VOID,
                                   NULL, NULL, JSPROP_ENUMERATE | JSPROP_SHARED);
+
+        if (!JS_GetPrototype(cx, proto, &proto))
+            return false;
     }
 
     InfallibleTArray<nsString>* strIds;
     {
         AutoIdArray ids(cx, JS_Enumerate(cx, state));
         if (!ids)
             return false;
         strIds = new InfallibleTArray<nsString>(ids.length());
--- a/js/jsd/jsd_val.cpp
+++ b/js/jsd/jsd_val.cpp
@@ -609,26 +609,28 @@ jsd_GetValueFunction(JSDContext* jsdc, J
     JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
 
     return fun;
 }
 
 JSDValue*
 jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
 {
+    JSContext* cx = jsdc->dumbContext;
     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
     {
         JSObject* obj;
         JSObject* proto;
         JS_ASSERT(!jsdval->proto);
         SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
         if(JSVAL_IS_PRIMITIVE(jsdval->val))
             return NULL;
         obj = JSVAL_TO_OBJECT(jsdval->val);
-        proto = JS_GetPrototype(obj);
+        if(!JS_GetPrototype(cx, obj, &proto))
+            return NULL;
         if(!proto)
             return NULL;
         jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
     }
     if(jsdval->proto)
         jsdval->proto->nref++;
     return jsdval->proto;
 }
@@ -660,28 +662,30 @@ jsd_GetValueParent(JSDContext* jsdc, JSD
         jsdval->parent->nref++;
     return jsdval->parent;
 }
 
 JSDValue*
 jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSCompartment* oldCompartment = NULL;
+    JSContext* cx = jsdc->dumbContext;
 
     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
     {
         JSObject* obj;
         JSObject* proto;
         JSObject* ctor;
         JS_ASSERT(!jsdval->ctor);
         SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
         if(JSVAL_IS_PRIMITIVE(jsdval->val))
             return NULL;
         obj = JSVAL_TO_OBJECT(jsdval->val);
-        proto = JS_GetPrototype(obj);
+        if(!JS_GetPrototype(cx, obj, &proto))
+            return NULL;
         if(!proto)
             return NULL;
         JS_BeginRequest(jsdc->dumbContext);
         oldCompartment = JS_EnterCompartment(jsdc->dumbContext, obj);
         ctor = JS_GetConstructor(jsdc->dumbContext,proto);
         JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
         JS_EndRequest(jsdc->dumbContext);
         if(!ctor)
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -712,17 +712,19 @@ static JSObject*
 InitCTypeClass(JSContext* cx, HandleObject parent)
 {
   JSFunction *fun = JS_DefineFunction(cx, parent, "CType", ConstructAbstract, 0,
                                       CTYPESCTOR_FLAGS);
   if (!fun)
     return NULL;
 
   RootedObject ctor(cx, JS_GetFunctionObject(fun));
-  RootedObject fnproto(cx, JS_GetPrototype(ctor));
+  RootedObject fnproto(cx);
+  if (!JS_GetPrototype(cx, ctor, fnproto.address()))
+    return NULL;
   JS_ASSERT(ctor);
   JS_ASSERT(fnproto);
 
   // Set up ctypes.CType.prototype.
   RootedObject prototype(cx, JS_NewObject(cx, &sCTypeProtoClass, fnproto, parent));
   if (!prototype)
     return NULL;
 
@@ -1923,21 +1925,25 @@ ConvertToJS(JSContext* cx,
 #define DEFINE_WRAPPED_INT_TYPE(name, type, ffiType)                           \
   case TYPE_##name: {                                                          \
     /* Return an Int64 or UInt64 object - do not convert to a JS number. */    \
     uint64_t value;                                                            \
     RootedObject proto(cx);                                                    \
     if (!numeric_limits<type>::is_signed) {                                    \
       value = *static_cast<type*>(data);                                       \
       /* Get ctypes.UInt64.prototype from ctypes.CType.prototype. */           \
-      proto = CType::GetProtoFromType(typeObj, SLOT_UINT64PROTO);              \
+      proto = CType::GetProtoFromType(cx, typeObj, SLOT_UINT64PROTO);          \
+      if (!proto)                                                              \
+        return false;                                                          \
     } else {                                                                   \
       value = int64_t(*static_cast<type*>(data));                              \
       /* Get ctypes.Int64.prototype from ctypes.CType.prototype. */            \
-      proto = CType::GetProtoFromType(typeObj, SLOT_INT64PROTO);               \
+      proto = CType::GetProtoFromType(cx, typeObj, SLOT_INT64PROTO);     \
+      if (!proto)                                                              \
+        return false;                                                          \
     }                                                                          \
                                                                                \
     JSObject* obj = Int64Base::Construct(cx, proto, value,                     \
       !numeric_limits<type>::is_signed);                                       \
     if (!obj)                                                                  \
       return false;                                                            \
     *result = OBJECT_TO_JSVAL(obj);                                            \
     break;                                                                     \
@@ -3352,27 +3358,30 @@ CType::GetProtoFromCtor(JSObject* obj, C
   JS_ASSERT(CType::IsCTypeProto(proto));
 
   // Get the desired prototype.
   jsval result = JS_GetReservedSlot(proto, slot);
   return JSVAL_TO_OBJECT(result);
 }
 
 JSObject*
-CType::GetProtoFromType(JSObject* obj, CTypeProtoSlot slot)
+CType::GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
 {
   JS_ASSERT(IsCType(obj));
 
   // Get the prototype of the type object.
-  JSObject* proto = JS_GetPrototype(obj);
+  JSObject* proto;
+  if (!JS_GetPrototype(cx, obj, &proto))
+    return NULL;
   JS_ASSERT(proto);
   JS_ASSERT(CType::IsCTypeProto(proto));
 
   // Get the requested ctypes.{Pointer,Array,Struct,Function}Type.prototype.
   jsval result = JS_GetReservedSlot(proto, slot);
+  JS_ASSERT(!JSVAL_IS_PRIMITIVE(result));
   return JSVAL_TO_OBJECT(result);
 }
 
 JSBool
 CType::PrototypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!(CType::IsCType(obj) || CType::IsCTypeProto(obj))) {
     JS_ReportError(cx, "not a CType or CTypeProto");
@@ -3533,39 +3542,44 @@ CType::HasInstance(JSContext* cx, JSHand
   JS_ASSERT(prototype);
   JS_ASSERT(CData::IsCDataProto(prototype));
 
   *bp = JS_FALSE;
   if (JSVAL_IS_PRIMITIVE(v))
     return JS_TRUE;
 
   JSObject* proto = JSVAL_TO_OBJECT(v);
-  while ((proto = JS_GetPrototype(proto))) {
+  for (;;) {
+    if (!JS_GetPrototype(cx, proto, &proto))
+      return JS_FALSE;
+    if (!proto)
+      break;
     if (proto == prototype) {
       *bp = JS_TRUE;
       break;
     }
   }
   return JS_TRUE;
 }
 
 static JSObject*
 CType::GetGlobalCTypes(JSContext* cx, JSObject* obj)
 {
   JS_ASSERT(CType::IsCType(obj));
 
-  JSObject *objTypeProto = JS_GetPrototype(obj);
-  if (!objTypeProto) {
-  }
+  JSObject *objTypeProto;
+  if (!JS_GetPrototype(cx, obj, &objTypeProto))
+    return NULL;
   JS_ASSERT(objTypeProto);
   JS_ASSERT(CType::IsCTypeProto(objTypeProto));
 
   jsval valCTypes = JS_GetReservedSlot(objTypeProto, SLOT_CTYPES);
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCTypes));
 
+  JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCTypes));
   return JSVAL_TO_OBJECT(valCTypes);
 }
 
 /*******************************************************************************
 ** ABI implementation
 *******************************************************************************/
 
 bool
@@ -3648,18 +3662,22 @@ PointerType::CreateInternal(JSContext* c
   jsval slot = JS_GetReservedSlot(baseType, SLOT_PTR);
   if (!JSVAL_IS_VOID(slot))
     return JSVAL_TO_OBJECT(slot);
 
   // Get ctypes.PointerType.prototype and the common prototype for CData objects
   // of this type, or ctypes.FunctionType.prototype for function pointers.
   CTypeProtoSlot slotId = CType::GetTypeCode(baseType) == TYPE_function ?
     SLOT_FUNCTIONDATAPROTO : SLOT_POINTERDATAPROTO;
-  RootedObject dataProto(cx, CType::GetProtoFromType(baseType, slotId));
-  RootedObject typeProto(cx, CType::GetProtoFromType(baseType, SLOT_POINTERPROTO));
+  RootedObject dataProto(cx, CType::GetProtoFromType(cx, baseType, slotId));
+  if (!dataProto)
+    return NULL;
+  RootedObject typeProto(cx, CType::GetProtoFromType(cx, baseType, SLOT_POINTERPROTO));
+  if (!typeProto)
+    return NULL;
 
   // Create a new CType object with the common properties and slots.
   JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_pointer,
                         NULL, INT_TO_JSVAL(sizeof(void*)),
                         INT_TO_JSVAL(ffi_type_pointer.alignment),
                         &ffi_type_pointer);
   if (!typeObj)
     return NULL;
@@ -3966,18 +3984,22 @@ ArrayType::Create(JSContext* cx, unsigne
 JSObject*
 ArrayType::CreateInternal(JSContext* cx,
                           HandleObject baseType,
                           size_t length,
                           bool lengthDefined)
 {
   // Get ctypes.ArrayType.prototype and the common prototype for CData objects
   // of this type, from ctypes.CType.prototype.
-  RootedObject typeProto(cx, CType::GetProtoFromType(baseType, SLOT_ARRAYPROTO));
-  RootedObject dataProto(cx, CType::GetProtoFromType(baseType, SLOT_ARRAYDATAPROTO));
+  RootedObject typeProto(cx, CType::GetProtoFromType(cx, baseType, SLOT_ARRAYPROTO));
+  if (!typeProto)
+    return NULL;
+  RootedObject dataProto(cx, CType::GetProtoFromType(cx, baseType, SLOT_ARRAYDATAPROTO));
+  if (!dataProto)
+    return NULL;
 
   // Determine the size of the array from the base type, if possible.
   // The size of the base type must be defined.
   // If our length is undefined, both our size and length will be undefined.
   size_t baseSize;
   if (!CType::GetSafeSize(baseType, &baseSize)) {
     JS_ReportError(cx, "base size must be defined");
     return NULL;
@@ -4510,17 +4532,19 @@ StructType::DefineInternal(JSContext* cx
   RootedObject typeObj(cx, typeObj_);
   RootedObject fieldsObj(cx, fieldsObj_);
 
   uint32_t len;
   ASSERT_OK(JS_GetArrayLength(cx, fieldsObj, &len));
 
   // Get the common prototype for CData objects of this type from
   // ctypes.CType.prototype.
-  RootedObject dataProto(cx, CType::GetProtoFromType(typeObj, SLOT_STRUCTDATAPROTO));
+  RootedObject dataProto(cx, CType::GetProtoFromType(cx, typeObj, SLOT_STRUCTDATAPROTO));
+  if (!dataProto)
+    return JS_FALSE;
 
   // Set up the 'prototype' and 'prototype.constructor' properties.
   // The prototype will reflect the struct fields as properties on CData objects
   // created from this type.
   RootedObject prototype(cx, JS_NewObject(cx, &sCDataProtoClass, dataProto, NULL));
   if (!prototype)
     return JS_FALSE;
 
@@ -5367,20 +5391,24 @@ FunctionType::CreateInternal(JSContext* 
 {
   // Determine and check the types, and prepare the function CIF.
   AutoPtr<FunctionInfo> fninfo(NewFunctionInfo(cx, abi, rtype, argtypes, arglen));
   if (!fninfo)
     return NULL;
 
   // Get ctypes.FunctionType.prototype and the common prototype for CData objects
   // of this type, from ctypes.CType.prototype.
-  RootedObject typeProto(cx, CType::GetProtoFromType(fninfo->mReturnType,
+  RootedObject typeProto(cx, CType::GetProtoFromType(cx, fninfo->mReturnType,
                                                      SLOT_FUNCTIONPROTO));
-  RootedObject dataProto(cx, CType::GetProtoFromType(fninfo->mReturnType,
+  if (!typeProto)
+    return NULL;
+  RootedObject dataProto(cx, CType::GetProtoFromType(cx, fninfo->mReturnType,
                                                      SLOT_FUNCTIONDATAPROTO));
+  if (!dataProto)
+    return NULL;
 
   // Create a new CType object with the common properties and slots.
   JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_function,
                         NULL, JSVAL_VOID, JSVAL_VOID, NULL);
   if (!typeObj)
     return NULL;
   js::AutoObjectRooter root(cx, typeObj);
 
@@ -5585,16 +5613,18 @@ FunctionType::Call(JSContext* cx,
   lastErrorStatus = GetLastError();
   SetLastError(savedLastError);
 #endif // defined(XP_WIN)
 
   errno = savedErrno;
 
   // Store the error value for later consultation with |ctypes.getStatus|
   JSObject *objCTypes = CType::GetGlobalCTypes(cx, typeObj);
+  if (!objCTypes)
+    return false;
 
   JS_SetReservedSlot(objCTypes, SLOT_ERRNO, INT_TO_JSVAL(errnoStatus));
 #if defined(XP_WIN)
   JS_SetReservedSlot(objCTypes, SLOT_LASTERROR, INT_TO_JSVAL(lastErrorStatus));
 #endif // defined(XP_WIN)
 
   // Small integer types get returned as a word-sized ffi_arg. Coerce it back
   // into the correct size for ConvertToJS.
@@ -5735,17 +5765,19 @@ CClosure::Create(JSContext* cx,
   AutoPtr<ClosureInfo> cinfo(cx->new_<ClosureInfo>(JS_GetRuntime(cx)));
   if (!cinfo) {
     JS_ReportOutOfMemory(cx);
     return NULL;
   }
 
   // Get the prototype of the FunctionType object, of class CTypeProto,
   // which stores our JSContext for use with the closure.
-  JSObject* proto = JS_GetPrototype(typeObj);
+  JSObject* proto;
+  if (!JS_GetPrototype(cx, typeObj, &proto))
+    return NULL;
   JS_ASSERT(proto);
   JS_ASSERT(CType::IsCTypeProto(proto));
 
   // Get a JSContext for use with the closure.
   jsval slot = JS_GetReservedSlot(proto, SLOT_CLOSURECX);
   if (!JSVAL_IS_VOID(slot)) {
     // Use the existing JSContext.
     cinfo->cx = static_cast<JSContext*>(JSVAL_TO_PRIVATE(slot));
@@ -6901,16 +6933,18 @@ CDataFinalizer::Methods::Dispose(JSConte
     JS_ReportError(cx, "dispose called on an empty CDataFinalizer.");
     return JS_FALSE;
   }
 
   jsval valType = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_VALTYPE);
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(valType));
 
   JSObject *objCTypes = CType::GetGlobalCTypes(cx, JSVAL_TO_OBJECT(valType));
+  if (!objCTypes)
+    return JS_FALSE;
 
   jsval valCodePtrType = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_CODETYPE);
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCodePtrType));
   JSObject *objCodePtrType = JSVAL_TO_OBJECT(valCodePtrType);
 
   JSObject *objCodeType = PointerType::GetBaseType(objCodePtrType);
   JS_ASSERT(objCodeType);
   JS_ASSERT(CType::GetTypeCode(objCodeType) == TYPE_function);
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -423,17 +423,17 @@ namespace CType {
   bool TypesEqual(JSObject* t1, JSObject* t2);
   size_t GetSize(JSObject* obj);
   bool GetSafeSize(JSObject* obj, size_t* result);
   bool IsSizeDefined(JSObject* obj);
   size_t GetAlignment(JSObject* obj);
   ffi_type* GetFFIType(JSContext* cx, JSObject* obj);
   JSString* GetName(JSContext* cx, JSHandleObject obj);
   JSObject* GetProtoFromCtor(JSObject* obj, CTypeProtoSlot slot);
-  JSObject* GetProtoFromType(JSObject* obj, CTypeProtoSlot slot);
+  JSObject* GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot);
   JSCTypesCallbacks* GetCallbacksFromType(JSObject* obj);
 }
 
 namespace PointerType {
   JSObject* CreateInternal(JSContext* cx, JSHandleObject baseType);
 
   JSObject* GetBaseType(JSObject* obj);
 }
--- a/js/src/jsapi-tests/testTypedArrays.cpp
+++ b/js/src/jsapi-tests/testTypedArrays.cpp
@@ -25,17 +25,18 @@ BEGIN_TEST(testTypedArrays)
         TestPlainTypedArray<JS_NewUint32Array, uint32_t, JS_GetUint32ArrayData>(cx) &&
         TestPlainTypedArray<JS_NewFloat32Array, float, JS_GetFloat32ArrayData>(cx) &&
         TestPlainTypedArray<JS_NewFloat64Array, double, JS_GetFloat64ArrayData>(cx);
 
     size_t nbytes = sizeof(double) * 8;
     RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes));
     CHECK(JS_IsArrayBufferObject(buffer, cx));
 
-    RootedObject proto(cx, JS_GetPrototype(buffer));
+    RootedObject proto(cx);
+    JS_GetPrototype(cx, buffer, proto.address());
     CHECK(!JS_IsArrayBufferObject(proto, cx));
     RootedObject dummy(cx, JS_GetParent(proto));
     CHECK(!JS_IsArrayBufferObject(dummy, cx));
 
     CHECK_EQUAL(JS_GetArrayBufferByteLength(buffer, cx), nbytes);
     memset(JS_GetArrayBufferData(buffer, cx), 1, nbytes);
 
     ok = ok &&
@@ -55,17 +56,18 @@ BEGIN_TEST(testTypedArrays)
 template<JSObject *Create(JSContext *, uint32_t),
          typename Element,
          Element *GetData(JSObject *, JSContext *)>
 bool
 TestPlainTypedArray(JSContext *cx)
 {
     RootedObject array(cx, Create(cx, 7));
     CHECK(JS_IsTypedArrayObject(array, cx));
-    RootedObject proto(cx, JS_GetPrototype(array));
+    RootedObject proto(cx);
+    JS_GetPrototype(cx, array, proto.address());
     CHECK(!JS_IsTypedArrayObject(proto, cx));
     RootedObject dummy(cx, JS_GetParent(proto));
     CHECK(!JS_IsTypedArrayObject(dummy, cx));
 
     CHECK_EQUAL(JS_GetTypedArrayLength(array, cx), 7);
     CHECK_EQUAL(JS_GetTypedArrayByteOffset(array, cx), 0);
     CHECK_EQUAL(JS_GetTypedArrayByteLength(array, cx), sizeof(Element) * 7);
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3263,21 +3263,24 @@ JS_PUBLIC_API(void *)
 JS_GetInstancePrivate(JSContext *cx, JSObject *objArg, JSClass *clasp, jsval *argv)
 {
     RootedObject obj(cx, objArg);
     if (!JS_InstanceOf(cx, obj, clasp, argv))
         return NULL;
     return obj->getPrivate();
 }
 
-JS_PUBLIC_API(JSObject *)
-JS_GetPrototype(RawObject obj)
-{
-    /* FIXME! */
-    return obj->getProto();
+JS_PUBLIC_API(JSBool)
+JS_GetPrototype(JSContext *cx, JSObject *objArg, JSObject **protop)
+{
+    RootedObject obj(cx, objArg);
+    RootedObject proto(cx);
+    bool rv = JSObject::getProto(cx, obj, &proto);
+    *protop = proto;
+    return rv;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetPrototype(JSContext *cx, JSObject *objArg, JSObject *protoArg)
 {
     RootedObject obj(cx, objArg);
     RootedObject proto(cx, protoArg);
     AssertHeapIsIdle(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4329,18 +4329,18 @@ JS_GetPrivate(JSRawObject obj);
 
 extern JS_PUBLIC_API(void)
 JS_SetPrivate(JSRawObject obj, void *data);
 
 extern JS_PUBLIC_API(void *)
 JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
                       jsval *argv);
 
-extern JS_PUBLIC_API(JSObject *)
-JS_GetPrototype(JSRawObject obj);
+extern JS_PUBLIC_API(JSBool)
+JS_GetPrototype(JSContext *cx, JSObject *obj, JSObject **protop);
 
 extern JS_PUBLIC_API(JSBool)
 JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_GetParent(JSRawObject obj);
 
 extern JS_PUBLIC_API(JSBool)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -400,21 +400,20 @@ SetFunctionNativeReserved(RawObject fun,
 inline bool
 GetObjectProto(JSContext *cx, JSObject *obj, JSObject **proto)
 {
     js::Class *clasp = GetObjectClass(obj);
     if (clasp == &js::ObjectProxyClass ||
         clasp == &js::OuterWindowProxyClass ||
         clasp == &js::FunctionProxyClass)
     {
-        /* FIXME */
-        *proto = reinterpret_cast<const shadow::Object*>(obj)->type->proto;
-    } else {
-        *proto = reinterpret_cast<const shadow::Object*>(obj)->type->proto;
+        return JS_GetPrototype(cx, obj, proto);
     }
+
+    *proto = reinterpret_cast<const shadow::Object*>(obj)->type->proto;
     return true;
 }
 
 inline void *
 GetObjectPrivate(RawObject obj)
 {
     const shadow::Object *nobj = reinterpret_cast<const shadow::Object*>(obj);
     void **addr = reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
--- a/js/xpconnect/src/dombindings.cpp
+++ b/js/xpconnect/src/dombindings.cpp
@@ -283,17 +283,21 @@ interface_hasInstance(JSContext *cx, JSH
         JSObject *other = &vp.toObject();
         if (instanceIsProxy(other)) {
             ProxyHandler *handler = static_cast<ProxyHandler*>(js::GetProxyHandler(other));
             if (handler->isInstanceOf(JSVAL_TO_OBJECT(prototype))) {
                 *bp = true;
             } else {
                 JSObject *protoObj = JSVAL_TO_OBJECT(prototype);
                 JSObject *proto = other;
-                while ((proto = JS_GetPrototype(proto))) {
+                for (;;) {
+                    if (!JS_GetPrototype(cx, proto, &proto))
+                        return false;
+                    if (!proto)
+                        break;
                     if (proto == protoObj) {
                         *bp = true;
                         return true;
                     }
                 }
                 *bp = false;
             }
 
@@ -692,18 +696,19 @@ ListBase<LC>::delete_(JSContext *cx, JSO
     *bp = !!b;
     return true;
 }
 
 template<class LC>
 bool
 ListBase<LC>::enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props)
 {
-    JSObject *proto = JS_GetPrototype(proxy);
-    return getOwnPropertyNames(cx, proxy, props) &&
+    JSObject *proto;
+    return JS_GetPrototype(cx, proxy, &proto) &&
+           getOwnPropertyNames(cx, proxy, props) &&
            (!proto || js::GetPropertyNames(cx, proto, 0, &props));
 }
 
 template<class LC>
 bool
 ListBase<LC>::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
 {
     if (hasIndexGetter) {
--- a/js/xpconnect/wrappers/ChromeObjectWrapper.cpp
+++ b/js/xpconnect/wrappers/ChromeObjectWrapper.cpp
@@ -39,34 +39,38 @@ ChromeObjectWrapper::getPropertyDescript
 
     // If the property is something that can be found on a standard prototype,
     // prefer the one we'll get via the prototype chain in the content
     // compartment.
     if (desc->obj && PropIsFromStandardPrototype(cx, desc))
         desc->obj = NULL;
 
     // If we found something, were doing a set, or have no proto, we're done.
-    JSObject *wrapperProto = JS_GetPrototype(wrapper);
+    JSObject *wrapperProto;
+    if (!JS_GetPrototype(cx, wrapper, &wrapperProto))
+	return false;
     if (desc->obj || set || !wrapperProto)
         return true;
 
     // If not, try doing the lookup on the prototype.
     MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
     return JS_GetPropertyDescriptorById(cx, wrapperProto, id, 0, desc);
 }
 
 bool
 ChromeObjectWrapper::has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
 {
     // Try the lookup on the base wrapper.
     if (!ChromeObjectWrapperBase::has(cx, wrapper, id, bp))
         return false;
 
     // If we found something or have no prototype, we're done.
-    JSObject *wrapperProto = JS_GetPrototype(wrapper);
+    JSObject *wrapperProto;
+    if (!JS_GetPrototype(cx, wrapper, &wrapperProto))
+	return false;
     if (*bp || !wrapperProto)
         return true;
 
     // Try the prototype if that failed.
     MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
     JSPropertyDescriptor desc;
     memset(&desc, 0, sizeof(desc));
     if (!JS_GetPropertyDescriptorById(cx, wrapperProto, id, 0, &desc))
@@ -97,17 +101,19 @@ ChromeObjectWrapper::get(JSContext *cx, 
         if (!ChromeObjectWrapperBase::get(cx, wrapper, receiver, id, vp))
             return false;
         // If we found something, we're done.
         if (!vp->isUndefined())
             return true;
     }
 
     // If we have no proto, we're done.
-    JSObject *wrapperProto = JS_GetPrototype(wrapper);
+    JSObject *wrapperProto;
+    if (!JS_GetPrototype(cx, wrapper, &wrapperProto))
+	return false;
     if (!wrapperProto)
         return true;
 
     // Try the prototype.
     MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
     return js::GetGeneric(cx, wrapperProto, receiver, id, vp);
 }
 
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -564,35 +564,41 @@ WrapperFactory::WaiveXrayAndWrap(JSConte
 
     *vp = OBJECT_TO_JSVAL(obj);
     return JS_WrapValue(cx, vp);
 }
 
 JSObject *
 WrapperFactory::WrapSOWObject(JSContext *cx, JSObject *obj)
 {
+    JSObject *proto;
+    if (!JS_GetPrototype(cx, obj, &proto))
+        return NULL;
     JSObject *wrapperObj =
-        Wrapper::New(cx, obj, JS_GetPrototype(obj), JS_GetGlobalForObject(cx, obj),
+        Wrapper::New(cx, obj, proto, JS_GetGlobalForObject(cx, obj),
                      &FilteringWrapper<SameCompartmentSecurityWrapper,
                      OnlyIfSubjectIsSystem>::singleton);
     return wrapperObj;
 }
 
 bool
 WrapperFactory::IsComponentsObject(JSObject *obj)
 {
     const char *name = js::GetObjectClass(obj)->name;
     return name[0] == 'n' && !strcmp(name, "nsXPCComponents");
 }
 
 JSObject *
 WrapperFactory::WrapComponentsObject(JSContext *cx, JSObject *obj)
 {
+    JSObject *proto;
+    if (!JS_GetPrototype(cx, obj, &proto))
+        return NULL;
     JSObject *wrapperObj =
-        Wrapper::New(cx, obj, JS_GetPrototype(obj), JS_GetGlobalForObject(cx, obj),
+        Wrapper::New(cx, obj, proto, JS_GetGlobalForObject(cx, obj),
                      &FilteringWrapper<SameCompartmentSecurityWrapper, ComponentsObjectPolicy>::singleton);
 
     return wrapperObj;
 }
 
 JSObject *
 WrapperFactory::WrapForSameCompartmentXray(JSContext *cx, JSObject *obj)
 {
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -714,18 +714,21 @@ XPCWrappedNativeXrayTraits::resolveNativ
         id == rt->GetStringID(XPCJSRuntime::IDX_MOZMATCHESSELECTOR) &&
         Is<nsIDOMElement>(wrapper))
     {
         // XPC calling mechanism cannot handle call/bind properly in some cases
         // especially through xray wrappers. This is a temoorary work around for
         // this problem for mozMatchesSelector. See: bug 763897.
         desc->obj = wrapper;
         desc->attrs = JSPROP_ENUMERATE;
+        JSObject *proto;
+        if (!JS_GetPrototype(cx, wrapper, &proto))
+            return false;
         JSFunction *fun = JS_NewFunction(cx, mozMatchesSelectorStub, 
-                                         1, 0, JS_GetPrototype(wrapper), 
+                                         1, 0, proto, 
                                          "mozMatchesSelector");
         NS_ENSURE_TRUE(fun, false);
         desc->value = OBJECT_TO_JSVAL(JS_GetFunctionObject(fun));
         desc->getter = NULL;
         desc->setter = NULL;
         desc->shortid = 0;
         return true;
     }