XPCWrappedNative *wn = XPCNativeWrapper::GetWrappedNative(cx, obj);
XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,                        JSBool aIsSet){  // We don't deal with the following properties here.  if (id == GetStringByIndex(cx, XPCJSRuntime::IDX_PROTOTYPE) ||      id == GetStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {    return JS_TRUE;  }  // We can't use XPC_NW_BYPASS here, because we need to do a full  // OBJ_SET_PROPERTY or OBJ_GET_PROPERTY on the wrapped native's  // object, in order to trigger reflection done by the underlying  // OBJ_LOOKUP_PROPERTY done by SET and GET.  if (ShouldBypassNativeWrapper(cx, obj)) {    XPCWrappedNative *wn = XPCNativeWrapper::GetWrappedNative(cx, obj);    jsid interned_id;    if (!::JS_ValueToId(cx, id, &interned_id)) {      return JS_FALSE;    }    JSObject *wn_obj = wn->GetFlatJSObject();    return aIsSet           ? OBJ_SET_PROPERTY(cx, wn_obj, interned_id, vp)           : OBJ_GET_PROPERTY(cx, wn_obj, interned_id, vp);  }  // Be paranoid, don't let people use this as another object's  // prototype or anything like that.  if (!XPCNativeWrapper::IsNativeWrapper(cx, obj)) {    return ThrowException(NS_ERROR_UNEXPECTED, cx);  }  XPCWrappedNative *wrappedNative =    XPCNativeWrapper::GetWrappedNative(cx, obj);  if (!wrappedNative) {    return ThrowException(NS_ERROR_UNEXPECTED, cx);  }  JSObject *nativeObj = wrappedNative->GetFlatJSObject();  if (!aIsSet &&      id == GetStringByIndex(cx, XPCJSRuntime::IDX_WRAPPED_JSOBJECT)) {    // Return the underlying native object, the XPConnect wrapped    // object that this additional wrapper layer wraps.    *vp = OBJECT_TO_JSVAL(nativeObj);    return JS_TRUE;  }  jsval methodName;  if (JSVAL_IS_STRING(id)) {    methodName = id;  } else if (JSVAL_IS_INT(id)) {    // Map wrapper[n] to wrapper.item(n) for get. For set, throw an    // error as we don't support that.    if (aIsSet) {      return ThrowException(NS_ERROR_UNEXPECTED, cx);    }    methodName = GetStringByIndex(cx, XPCJSRuntime::IDX_ITEM);  } else {    return ThrowException(NS_ERROR_INVALID_ARG, cx);  }  // This will do verification and the method lookup for us.  XPCCallContext ccx(JS_CALLER, cx, nativeObj, nsnull, methodName);  // Verify that our jsobject really is a wrapped native.  XPCWrappedNative* wrapper = ccx.GetWrapper();  if (wrapper != wrappedNative || !wrapper->IsValid()) {    NS_ASSERTION(wrapper == wrappedNative, "Uh, how did this happen!");    return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);  }  // it would be a big surprise if there is a member without an  // interface :)  XPCNativeInterface* iface = ccx.GetInterface();  if (!iface) {    // No interface, no property -- unless we're getting an indexed    // property such as frames[0].  Handle that as a special case    // here, now that we know there's no XPConnected .item() method.    if (methodName != id) {      jsid index_id;      JSObject *pobj;      JSProperty *prop;      // Look up the property for the id being indexed in nativeObj.      if (!::JS_ValueToId(cx, id, &index_id) ||          !OBJ_LOOKUP_PROPERTY(cx, nativeObj, index_id, &pobj, &prop)) {        return JS_FALSE;      }      if (prop) {        JSBool safe = JS_FALSE;        if (OBJ_IS_NATIVE(pobj)) {          // At this point we know we have a native JS object (one that          // has a JSScope for its map, containing refs to the runtime's          // JSScopeProperty tree nodes.  Compare that property's getter          // to the class default getter to decide whether this element          // is safe to get -- i.e., it is not overridden, possibly by a          // user-defined getter.          JSScopeProperty *sprop = (JSScopeProperty *) prop;          JSClass *nativeObjClass = JS_GET_CLASS(cx, nativeObj);          safe = (sprop->getter == nativeObjClass->getProperty);        }        OBJ_DROP_PROPERTY(cx, pobj, prop);        if (safe) {          return ::JS_GetElement(cx, nativeObj, JSVAL_TO_INT(id), vp);        }      }    }    *vp = JSVAL_VOID;    return JS_TRUE;  }  // did we find a method/attribute by that name?  XPCNativeMember* member = ccx.GetMember();  NS_ASSERTION(member, "not doing IDispatch, how'd this happen?");  if (!member) {    // No member, no property.    *vp = JSVAL_VOID;    return JS_TRUE;  }  // Get (and perhaps lazily create) the member's value (commonly a  // cloneable function).  jsval memberval;  if (!member->GetValue(ccx, iface, &memberval)) {    return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);  }  if (member->IsConstant()) {    // Getting the value of constants is easy, just return the    // value. Setting is not supported (obviously).    if (aIsSet) {      return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);    }    *vp = memberval;    return JS_TRUE;  }  if (!member->IsAttribute() && methodName == id) {    // Getting the value of a method. Just return and let the value    // from XPC_NW_NewResolve() be used.  Note that if methodName != id    // then we fully expect that member is not an attribute and we need    // to keep going and handle this case below.    return JS_TRUE;  }  // Make sure the function we're cloning doesn't go away while  // we're cloning it.  AUTO_MARK_JSVAL(ccx, memberval);  // clone a function we can use for this object  JSObject* funobj = xpc_CloneJSFunction(ccx, JSVAL_TO_OBJECT(memberval),                                         wrapper->GetFlatJSObject());  if (!funobj) {    return JS_FALSE;  }  jsval *argv = nsnull;  uintN argc = 0;  if (methodName != id) {    // wrapper[n] to wrapper.item(n) mapping case.    if (member->IsAttribute()) {      // Uh oh, somehow wrapper.item is an attribute, not a function.      // Throw an error since we don't know how to deal with this case.      return ThrowException(NS_ERROR_UNEXPECTED, cx);    }#ifdef DEBUG_XPCNativeWrapper    printf("Mapping wrapper[%d] to wrapper.item(%d)\n", JSVAL_TO_INT(id),           JSVAL_TO_INT(id));#endif    argv = &id;    argc = 1;  } else if (aIsSet) {    if (member->IsReadOnlyAttribute()) {      // Trying to set a property for which there is no setter!      return ThrowException(NS_ERROR_NOT_AVAILABLE, cx);    }#ifdef DEBUG_XPCNativeWrapper    printf("Calling setter for %s\n",           ::JS_GetStringBytes(JSVAL_TO_STRING(id)));#endif    argv = vp;    argc = 1;  } else {#ifdef DEBUG_XPCNativeWrapper    printf("Calling getter for %s\n",           ::JS_GetStringBytes(JSVAL_TO_STRING(id)));#endif  }  // Call the getter (or method if an id access was mapped to  // .item(n)).  jsval v;  if (!::JS_CallFunctionValue(cx, wrapper->GetFlatJSObject(),                              OBJECT_TO_JSVAL(funobj), argc, argv, &v)) {    return JS_FALSE;  }  if (aIsSet) {    return JS_TRUE;  }  {    // Make sure v doesn't get collected while we're re-wrapping it.    AUTO_MARK_JSVAL(ccx, v);    return RewrapIfDeepWrapper(cx, obj, v, vp);  }}