Clean up API for creating natives with reserved slots, fix uses in CTypes and jsworkers shell, bug 697537.
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 27 Oct 2011 11:14:56 -0700
changeset 81281 98d248b24658c0fcbdfc6492128e5be56f5da1a5
parent 81280 636842dccfc9d88688488422dc04cc6758e5023f
child 81283 2b0d447b1b9ffc2ddb9d3cc691d35470606e769a
push id370
push usertim.taubert@gmx.de
push dateMon, 05 Dec 2011 10:13:38 +0000
treeherderfx-team@69b62700aa75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs697537
milestone10.0a1
Clean up API for creating natives with reserved slots, fix uses in CTypes and jsworkers shell, bug 697537.
js/src/ctypes/CTypes.cpp
js/src/jsapi.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/shell/jsworkers.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/src/XPCWrappedNativeInfo.cpp
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -636,17 +636,17 @@ InitTypeConstructor(JSContext* cx,
                     JSFunctionSpec spec,
                     JSFunctionSpec* fns,
                     JSPropertySpec* props,
                     JSFunctionSpec* instanceFns,
                     JSPropertySpec* instanceProps,
                     JSObject*& typeProto,
                     JSObject*& dataProto)
 {
-  JSFunction* fun = JS_DefineFunction(cx, parent, spec.name, spec.call, 
+  JSFunction* fun = js::DefineFunctionWithReserved(cx, parent, spec.name, spec.call, 
                       spec.nargs, spec.flags);
   if (!fun)
     return false;
 
   JSObject* obj = JS_GetFunctionObject(fun);
   if (!obj)
     return false;
 
@@ -667,18 +667,17 @@ InitTypeConstructor(JSContext* cx,
     return false;
 
   if (!JS_DefineProperty(cx, typeProto, "constructor", OBJECT_TO_JSVAL(obj),
          NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
     return false;
 
   // Stash ctypes.{Pointer,Array,Struct}Type.prototype on a reserved slot of
   // the type constructor, for faster lookup.
-  if (!JS_SetReservedSlot(cx, obj, SLOT_FN_CTORPROTO, OBJECT_TO_JSVAL(typeProto)))
-    return false;
+  js::SetFunctionNativeReserved(obj, SLOT_FN_CTORPROTO, OBJECT_TO_JSVAL(typeProto));
 
   // Create an object to serve as the common ancestor for all CData objects
   // created from the given type constructor. This has ctypes.CData.prototype
   // as its prototype, such that it inherits the properties and functions
   // common to all CDatas.
   dataProto = JS_NewObject(cx, &sCDataProtoClass, CDataProto, parent);
   if (!dataProto)
     return false;
@@ -716,24 +715,28 @@ InitInt64Class(JSContext* cx,
     return NULL;
 
   JSObject* ctor = JS_GetConstructor(cx, prototype);
   if (!ctor)
     return NULL;
   if (!JS_FreezeObject(cx, ctor))
     return NULL;
 
-  // Stash ctypes.{Int64,UInt64}.prototype on a reserved slot of the 'join'
-  // function.
-  jsval join;
-  ASSERT_OK(JS_GetProperty(cx, ctor, "join", &join));
-  if (!JS_SetReservedSlot(cx, JSVAL_TO_OBJECT(join), SLOT_FN_INT64PROTO,
-         OBJECT_TO_JSVAL(prototype)))
+  // Redefine the 'join' function as an extended native and stash
+  // ctypes.{Int64,UInt64}.prototype in a reserved slot of the new function.
+  JS_ASSERT(clasp == &sInt64ProtoClass || clasp == &sUInt64ProtoClass);
+  JSNative native = (clasp == &sInt64ProtoClass) ? Int64::Join : UInt64::Join;
+  JSFunction* fun = js::DefineFunctionWithReserved(cx, ctor, "join", native,
+                      2, CTYPESFN_FLAGS);
+  if (!fun)
     return NULL;
 
+  js::SetFunctionNativeReserved(fun, SLOT_FN_INT64PROTO,
+    OBJECT_TO_JSVAL(prototype));
+
   if (!JS_FreezeObject(cx, prototype))
     return NULL;
 
   return prototype;
 }
 
 static JSBool
 AttachProtos(JSContext* cx, JSObject* proto, JSObject** protos)
@@ -3025,18 +3028,17 @@ CType::GetName(JSContext* cx, JSObject* 
   return JSVAL_TO_STRING(string);
 }
 
 JSObject*
 CType::GetProtoFromCtor(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
 {
   // Get ctypes.{Pointer,Array,Struct}Type.prototype from a reserved slot
   // on the type constructor.
-  jsval protoslot;
-  ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FN_CTORPROTO, &protoslot));
+  jsval protoslot = js::GetFunctionNativeReserved(obj, SLOT_FN_CTORPROTO);
   JSObject* proto = JSVAL_TO_OBJECT(protoslot);
   JS_ASSERT(proto);
   JS_ASSERT(JS_GET_CLASS(cx, proto) == &sCTypeProtoClass);
 
   // Get the desired prototype.
   jsval result;
   ASSERT_OK(JS_GetReservedSlot(cx, proto, slot, &result));
   return JSVAL_TO_OBJECT(result);
@@ -6237,18 +6239,17 @@ Int64::Join(JSContext* cx, uintN argc, j
   if (!jsvalToInteger(cx, argv[1], &lo))
     return TypeError(cx, "uint32", argv[1]);
 
   JSInt64 i = (JSInt64(hi) << 32) + JSInt64(lo);
 
   // Get Int64.prototype from the function's reserved slot.
   JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
 
-  jsval slot;
-  ASSERT_OK(JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot));
+  jsval slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO);
   JSObject* proto = JSVAL_TO_OBJECT(slot);
   JS_ASSERT(JS_GET_CLASS(cx, proto) == &sInt64ProtoClass);
 
   JSObject* result = Int64Base::Construct(cx, proto, i, false);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
@@ -6405,18 +6406,17 @@ UInt64::Join(JSContext* cx, uintN argc, 
   if (!jsvalToInteger(cx, argv[1], &lo))
     return TypeError(cx, "uint32_t", argv[1]);
 
   JSUint64 u = (JSUint64(hi) << 32) + JSUint64(lo);
 
   // Get UInt64.prototype from the function's reserved slot.
   JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
 
-  jsval slot;
-  ASSERT_OK(JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot));
+  jsval slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO);
   JSObject* proto = JSVAL_TO_OBJECT(slot);
   JS_ASSERT(JS_GET_CLASS(cx, proto) == &sUInt64ProtoClass);
 
   JSObject* result = Int64Base::Construct(cx, proto, u, true);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4285,22 +4285,17 @@ JS_PUBLIC_API(JSFunction *)
 JS_NewFunctionById(JSContext *cx, JSNative native, uintN nargs, uintN flags, JSObject *parent,
                    jsid id)
 {
     JS_ASSERT(JSID_IS_STRING(id));
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
-    /* Allow natives created through this interface to use {Get,Set}FunctionNativeReserved. */
-    AllocKind kind = native
-        ? (AllocKind) JSFunction::ExtendedFinalizeKind
-        : (AllocKind) JSFunction::FinalizeKind;
-
-    return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id), kind);
+    return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id));
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);  // XXX no funobj for now
     if (!parent) {
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -202,16 +202,56 @@ js::GetObjectSlotSpan(const JSObject *ob
 }
 
 JS_FRIEND_API(bool)
 js::IsOriginalScriptFunction(JSFunction *fun)
 {
     return fun->script()->function() == fun;
 }
 
+JS_FRIEND_API(JSFunction *)
+js::DefineFunctionWithReserved(JSContext *cx, JSObject *obj, const char *name, JSNative call,
+                               uintN nargs, uintN attrs)
+{
+    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, obj);
+    JSAtom *atom = js_Atomize(cx, name, strlen(name));
+    if (!atom)
+        return NULL;
+    return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), call, nargs, attrs,
+                             JSFunction::ExtendedFinalizeKind);
+}
+
+JS_FRIEND_API(JSFunction *)
+js::NewFunctionByIdWithReserved(JSContext *cx, JSNative native, uintN nargs, uintN flags, JSObject *parent,
+                                jsid id)
+{
+    JS_ASSERT(JSID_IS_STRING(id));
+    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, parent);
+
+    return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id),
+                          JSFunction::ExtendedFinalizeKind);
+}
+
+JS_FRIEND_API(JSObject *)
+js::InitClassWithReserved(JSContext *cx, JSObject *obj, JSObject *parent_proto,
+                          JSClass *clasp, JSNative constructor, uintN nargs,
+                          JSPropertySpec *ps, JSFunctionSpec *fs,
+                          JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, obj, parent_proto);
+    return js_InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
+                        nargs, ps, fs, static_ps, static_fs, NULL,
+                        JSFunction::ExtendedFinalizeKind);
+}
+
 JS_FRIEND_API(const Value &)
 js::GetFunctionNativeReserved(JSObject *fun, size_t which)
 {
     return fun->toFunction()->getNativeReserved(which);
 }
 
 JS_FRIEND_API(void)
 js::SetFunctionNativeReserved(JSObject *fun, size_t which, const Value &val)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -271,16 +271,30 @@ JS_FRIEND_API(JSObject *)
 GetObjectParentMaybeScope(const JSObject *obj);
 
 JS_FRIEND_API(JSObject *)
 GetObjectGlobal(JSObject *obj);
 
 JS_FRIEND_API(bool)
 IsOriginalScriptFunction(JSFunction *fun);
 
+JS_FRIEND_API(JSFunction *)
+DefineFunctionWithReserved(JSContext *cx, JSObject *obj, const char *name, JSNative call,
+                           uintN nargs, uintN attrs);
+
+JS_FRIEND_API(JSFunction *)
+NewFunctionByIdWithReserved(JSContext *cx, JSNative native, uintN nargs, uintN flags,
+                            JSObject *parent, jsid id);
+
+JS_FRIEND_API(JSObject *)
+InitClassWithReserved(JSContext *cx, JSObject *obj, JSObject *parent_proto,
+                      JSClass *clasp, JSNative constructor, uintN nargs,
+                      JSPropertySpec *ps, JSFunctionSpec *fs,
+                      JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
+
 JS_FRIEND_API(const Value &)
 GetFunctionNativeReserved(JSObject *fun, size_t which);
 
 JS_FRIEND_API(void)
 SetFunctionNativeReserved(JSObject *fun, size_t which, const Value &val);
 
 inline JSObject *
 GetObjectProto(const JSObject *obj)
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4238,17 +4238,17 @@ ClearClassObject(JSContext *cx, JSObject
 }
 
 JSObject *
 DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
                               JSObject *protoProto, Class *clasp,
                               Native constructor, uintN nargs,
                               JSPropertySpec *ps, JSFunctionSpec *fs,
                               JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
-                              JSObject **ctorp)
+                              JSObject **ctorp, AllocKind ctorKind)
 {
     /*
      * Create a prototype object for this class.
      *
      * FIXME: lazy standard (built-in) class initialization and even older
      * eager boostrapping code rely on all of these properties:
      *
      * 1. NewObject attempting to compute a default prototype object when
@@ -4311,17 +4311,18 @@ DefineConstructorAndPrototype(JSContext 
     } else {
         /*
          * Create the constructor, not using GlobalObject::createConstructor
          * because the constructor currently must have |obj| as its parent.
          * (FIXME: remove this dependency on the exact identity of the parent,
          * perhaps as part of bug 638316.)
          */
         JSFunction *fun =
-            js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom);
+            js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom,
+                           ctorKind);
         if (!fun)
             goto bad;
         fun->setConstructorClass(clasp);
 
         /*
          * Set the class object early for standard class constructors. Type
          * inference may need to access these, and js_GetClassPrototype will
          * fail if it tries to do a reentrant reconstruction of the class.
@@ -4426,17 +4427,17 @@ MarkStandardClassInitializedNoProto(JSOb
 
 }
 
 JSObject *
 js_InitClass(JSContext *cx, JSObject *obj, JSObject *protoProto,
              Class *clasp, Native constructor, uintN nargs,
              JSPropertySpec *ps, JSFunctionSpec *fs,
              JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
-             JSObject **ctorp)
+             JSObject **ctorp, AllocKind ctorKind)
 {
     JSAtom *atom = js_Atomize(cx, clasp->name, strlen(clasp->name));
     if (!atom)
         return NULL;
 
     /*
      * All instances of the class will inherit properties from the prototype
      * object we are about to create (in DefineConstructorAndPrototype), which
@@ -4452,17 +4453,17 @@ js_InitClass(JSContext *cx, JSObject *ob
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
     if (key != JSProto_Null &&
         !protoProto &&
         !js_GetClassPrototype(cx, obj, JSProto_Object, &protoProto)) {
         return NULL;
     }
 
     return DefineConstructorAndPrototype(cx, obj, key, atom, protoProto, clasp, constructor, nargs,
-                                         ps, fs, static_ps, static_fs, ctorp);
+                                         ps, fs, static_ps, static_fs, ctorp, ctorKind);
 }
 
 void
 JSObject::copySlotRange(size_t start, const Value *vector, size_t length)
 {
     JS_ASSERT(!isDenseArray());
     JS_ASSERT(slotInRange(start + length, /* sentinelAllowed = */ true));
     size_t fixed = numFixedSlots();
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1512,39 +1512,24 @@ extern JSPropertySpec object_props[];
 #define object_props NULL
 #endif
 
 extern JSFunctionSpec object_methods[];
 extern JSFunctionSpec object_static_methods[];
 
 namespace js {
 
-JSObject *
-DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
-                              JSObject *protoProto, Class *clasp,
-                              Native constructor, uintN nargs,
-                              JSPropertySpec *ps, JSFunctionSpec *fs,
-                              JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
-                              JSObject **ctorp = NULL);
-
 bool
 IsStandardClassResolved(JSObject *obj, js::Class *clasp);
 
 void
 MarkStandardClassInitializedNoProto(JSObject *obj, js::Class *clasp);
 
 }
 
-extern JSObject *
-js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
-             js::Class *clasp, JSNative constructor, uintN nargs,
-             JSPropertySpec *ps, JSFunctionSpec *fs,
-             JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
-             JSObject **ctorp = NULL);
-
 /*
  * Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
  */
 extern const char js_watch_str[];
 extern const char js_unwatch_str[];
 extern const char js_hasOwnProperty_str[];
 extern const char js_isPrototypeOf_str[];
 extern const char js_propertyIsEnumerable_str[];
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1934,18 +1934,35 @@ ValueIsSpecial(JSObject *obj, Value *pro
         propval->setString(name);
         return false;
     }
 #endif
 
     return false;
 }
 
+JSObject *
+DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
+                              JSObject *protoProto, Class *clasp,
+                              Native constructor, uintN nargs,
+                              JSPropertySpec *ps, JSFunctionSpec *fs,
+                              JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
+                              JSObject **ctorp = NULL,
+                              gc::AllocKind ctorKind = JSFunction::FinalizeKind);
+
 } /* namespace js */
 
+extern JSObject *
+js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
+             js::Class *clasp, JSNative constructor, uintN nargs,
+             JSPropertySpec *ps, JSFunctionSpec *fs,
+             JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
+             JSObject **ctorp = NULL,
+             js::gc::AllocKind ctorKind = JSFunction::FinalizeKind);
+
 inline JSObject *
 js_GetProtoIfDenseArray(JSObject *obj)
 {
     return obj->isDenseArray() ? obj->getProto() : obj;
 }
 
 /*
  * js_PurgeScopeChain does nothing if obj is not itself a prototype or parent
--- a/js/src/shell/jsworkers.cpp
+++ b/js/src/shell/jsworkers.cpp
@@ -642,30 +642,35 @@ class Worker : public WorkerParent
             goto bad;
         JS_SetGlobalObject(context, global);
 
         // Because the Worker is completely isolated from the rest of the
         // runtime, and because any pending events on a Worker keep the Worker
         // alive, this postMessage function cannot be called after the Worker
         // is collected.  Therefore it's safe to stash a pointer (a weak
         // reference) to the C++ Worker object in the reserved slot.
-        post = JS_GetFunctionObject(JS_DefineFunction(context, global, "postMessage",
-                                                      (JSNative) jsPostMessageToParent, 1, 0));
-        if (!post || !JS_SetReservedSlot(context, post, 0, PRIVATE_TO_JSVAL(this)))
+        post = JS_GetFunctionObject(
+                   js::DefineFunctionWithReserved(context, global, "postMessage",
+                                                  (JSNative) jsPostMessageToParent, 1, 0));
+        if (!post)
             goto bad;
 
-        proto = JS_InitClass(context, global, NULL, &jsWorkerClass, jsConstruct, 1,
-                             NULL, jsMethods, NULL, NULL);
+        js::SetFunctionNativeReserved(post, 0, PRIVATE_TO_JSVAL(this));
+
+        proto = js::InitClassWithReserved(context, global, NULL, &jsWorkerClass, jsConstruct, 1,
+                                          NULL, jsMethods, NULL, NULL);
         if (!proto)
             goto bad;
 
         ctor = JS_GetConstructor(context, proto);
-        if (!ctor || !JS_SetReservedSlot(context, ctor, 0, PRIVATE_TO_JSVAL(this)))
+        if (!ctor)
             goto bad;
 
+        js::SetFunctionNativeReserved(post, 0, PRIVATE_TO_JSVAL(this));
+
         JS_EndRequest(context);
         JS_ClearContextThread(context);
         return true;
 
     bad:
         JS_EndRequest(context);
         JS_DestroyContext(context);
         context = NULL;
@@ -801,33 +806,27 @@ class Worker : public WorkerParent
     /* Trace method to be called from C++. */
     void trace(JSTracer *trc) {
         // Just mark the JSObject. If we haven't already been marked,
         // jsTraceWorker will be called, at which point we'll trace referents.
         JS_CALL_OBJECT_TRACER(trc, object, "queued Worker");
     }
 
     static bool getWorkerParentFromConstructor(JSContext *cx, JSObject *ctor, WorkerParent **p) {
-        jsval v;
-        if (!JS_GetReservedSlot(cx, ctor, 0, &v))
-            return false;
+        jsval v = js::GetFunctionNativeReserved(ctor, 0);
         if (JSVAL_IS_VOID(v)) {
             // This means ctor is the root Worker constructor (created in
             // Worker::initWorkers as opposed to Worker::createContext, which sets up
             // Worker sandboxes) and nothing is initialized yet.
-            if (!JS_GetReservedSlot(cx, ctor, 1, &v))
-                return false;
+            v = js::GetFunctionNativeReserved(ctor, 1);
             ThreadPool *threadPool = (ThreadPool *) JSVAL_TO_PRIVATE(v);
             if (!threadPool->start(cx))
                 return false;
             WorkerParent *parent = threadPool->getMainQueue();
-            if (!JS_SetReservedSlot(cx, ctor, 0, PRIVATE_TO_JSVAL(parent))) {
-                threadPool->shutdown(cx);
-                return false;
-            }
+            js::SetFunctionNativeReserved(ctor, 0, PRIVATE_TO_JSVAL(parent));
             *p = parent;
             return true;
         }
         *p = (WorkerParent *) JSVAL_TO_PRIVATE(v);
         return true;
     }
 
     static JSBool jsConstruct(JSContext *cx, uintN argc, jsval *vp) {
@@ -856,27 +855,26 @@ class Worker : public WorkerParent
         ThreadPool *threadPool = ThreadPool::create(cx, hooks);
         if (!threadPool)
             return NULL;
 
         // Root the ThreadPool JSObject early.
         *objp = threadPool->asObject();
 
         // Create the Worker constructor.
-        JSObject *proto = JS_InitClass(cx, global, NULL, &jsWorkerClass,
-                                       jsConstruct, 1,
-                                       NULL, jsMethods, NULL, NULL);
+        JSObject *proto = js::InitClassWithReserved(cx, global, NULL, &jsWorkerClass,
+                                                    jsConstruct, 1,
+                                                    NULL, jsMethods, NULL, NULL);
         if (!proto)
             return NULL;
 
         // Stash a pointer to the ThreadPool in constructor reserved slot 1.
         // It will be used later when lazily creating the MainQueue.
         JSObject *ctor = JS_GetConstructor(cx, proto);
-        if (!JS_SetReservedSlot(cx, ctor, 1, PRIVATE_TO_JSVAL(threadPool)))
-            return NULL;
+        js::SetFunctionNativeReserved(ctor, 1, PRIVATE_TO_JSVAL(threadPool));
 
         return threadPool;
     }
 };
 
 class InitEvent : public Event
 {
   public:
@@ -1150,19 +1148,17 @@ Worker::processOneEvent()
                 JS_ReportOutOfMemory(context);
         }
     }
 }
 
 JSBool
 Worker::jsPostMessageToParent(JSContext *cx, uintN argc, jsval *vp)
 {
-    jsval workerval;
-    if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0, &workerval))
-        return false;
+    jsval workerval = js::GetFunctionNativeReserved(JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0);
     Worker *w = (Worker *) JSVAL_TO_PRIVATE(workerval);
 
     {
         JSAutoSuspendRequest suspend(cx);  // avoid nesting w->lock in a request
         if (w->checkTermination())
             return false;
     }
 
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3874,18 +3874,18 @@ FunctionWrapper(JSContext *cx, uintN arg
 
     return JS_CallFunctionValue(cx, JS_THIS_OBJECT(cx, vp), v,
                                 argc, JS_ARGV(cx, vp), vp);
 }
 
 JSBool
 WrapCallable(JSContext *cx, JSObject *obj, jsid id, JSObject *propobj, jsval *vp)
 {
-    JSFunction *fun = JS_NewFunctionById(cx, FunctionWrapper, 0, 0,
-                                         JS_GetGlobalForObject(cx, obj), id);
+    JSFunction *fun = js::NewFunctionByIdWithReserved(cx, FunctionWrapper, 0, 0,
+                                                      JS_GetGlobalForObject(cx, obj), id);
     if (!fun)
         return JS_FALSE;
 
     JSObject *funobj = JS_GetFunctionObject(fun);
     js::SetFunctionNativeReserved(funobj, 0, OBJECT_TO_JSVAL(propobj));
     *vp = OBJECT_TO_JSVAL(funobj);
     return JS_TRUE;
 }
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -181,17 +181,17 @@ PointerHolderClass = {
 
 template<typename Op>
 static JSObject *
 GeneratePropertyOp(JSContext *cx, JSObject *obj, jsid id, uintN argc, Op pop)
 {
     // The JS engine provides two reserved slots on function objects for
     // XPConnect to use. Use them to stick the necessary info here.
     JSFunction *fun =
-        JS_NewFunctionById(cx, PropertyOpForwarder<Op>, argc, 0, obj, id);
+        js::NewFunctionByIdWithReserved(cx, PropertyOpForwarder<Op>, argc, 0, obj, id);
     if (!fun)
         return JS_FALSE;
 
     JSObject *funobj = JS_GetFunctionObject(fun);
 
     js::AutoObjectRooter tvr(cx, funobj);
 
     // Unfortunately, we cannot guarantee that Op is aligned. Use a
--- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp
@@ -155,17 +155,17 @@ XPCNativeMember::Resolve(XPCCallContext&
             argc-- ;
 
         callback = XPC_WN_CallMethod;
     } else {
         argc = 0;
         callback = XPC_WN_GetterSetter;
     }
 
-    JSFunction *fun = JS_NewFunctionById(ccx, callback, argc, 0, parent, GetName());
+    JSFunction *fun = js::NewFunctionByIdWithReserved(ccx, callback, argc, 0, parent, GetName());
     if (!fun)
         return JS_FALSE;
 
     JSObject* funobj = JS_GetFunctionObject(fun);
     if (!funobj)
         return JS_FALSE;
 
     js::SetFunctionNativeReserved(funobj, 0, PRIVATE_TO_JSVAL(iface));