static JSObject*
CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
                      JSClass* constructorClass, JSObject* proto,
                      JSFunctionSpec* staticMethods, ConstantSpec* constants,
                      const char* name)
{
  JSObject* functionProto = JS_GetFunctionPrototype(cx, global);
  if (!functionProto) {
    return NULL;
  }

  JSObject* constructor =
    JS_NewObject(cx, constructorClass, functionProto, global);
  if (!constructor) {
    return NULL;
  }

  if (staticMethods && !JS_DefineFunctions(cx, constructor, staticMethods)) {
    return NULL;
  }

  if (constants && !DefineConstants(cx, constructor, constants)) {
    return NULL;
  }

  if (proto && !JS_LinkConstructorAndPrototype(cx, constructor, proto)) {
    return NULL;
  }

  // This is Enumerable: False per spec.
  if (!JS_DefineProperty(cx, receiver, name, OBJECT_TO_JSVAL(constructor), NULL,
                         NULL, 0)) {
    return NULL;
  }

  return constructor;
}
static JSObject*
CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
                      JSClass* constructorClass, JSNative constructorNative,
                      unsigned ctorNargs, JSObject* proto,
                      Prefable<JSFunctionSpec>* staticMethods,
                      Prefable<ConstantSpec>* constants,
                      const char* name)
{
  JSObject* constructor;
  if (constructorClass) {
    JSObject* functionProto = JS_GetFunctionPrototype(cx, global);
    if (!functionProto) {
      return NULL;
    }
    constructor = JS_NewObject(cx, constructorClass, functionProto, global);
  } else {
    MOZ_ASSERT(constructorNative);
    JSFunction* fun = JS_NewFunction(cx, constructorNative, ctorNargs,
                                     JSFUN_CONSTRUCTOR, global, name);
    if (!fun) {
      return NULL;
    }
    constructor = JS_GetFunctionObject(fun);
  }
  if (!constructor) {
    return NULL;
  }

  if (staticMethods && !DefinePrefable(cx, constructor, staticMethods)) {
    return NULL;
  }

  if (constructorClass) {
    JSFunction* toString = js::DefineFunctionWithReserved(cx, constructor,
                                                          "toString",
                                                          InterfaceObjectToString,
                                                          0, 0);
    if (!toString) {
      return NULL;
    }

    JSObject* toStringObj = JS_GetFunctionObject(toString);
    js::SetFunctionNativeReserved(toStringObj, TOSTRING_CLASS_RESERVED_SLOT,
                                  PRIVATE_TO_JSVAL(constructorClass));

    JSString *str = ::JS_InternString(cx, name);
    if (!str) {
      return NULL;
    }
    js::SetFunctionNativeReserved(toStringObj, TOSTRING_NAME_RESERVED_SLOT,
                                  STRING_TO_JSVAL(str));
  }

  if (constants && !DefinePrefable(cx, constructor, constants)) {
    return NULL;
  }

  if (proto && !JS_LinkConstructorAndPrototype(cx, constructor, proto)) {
    return NULL;
  }

  JSBool alreadyDefined;
  if (!JS_AlreadyHasOwnProperty(cx, receiver, name, &alreadyDefined)) {
    return NULL;
  }

  // This is Enumerable: False per spec.
  if (!alreadyDefined &&
      !JS_DefineProperty(cx, receiver, name, OBJECT_TO_JSVAL(constructor), NULL,
                         NULL, 0)) {
    return NULL;
  }

  return constructor;
}