nsresult nsPropertyTable::SetPropertyInternal(nsPropertyOwner aObject, nsIAtom *aPropertyName, void *aPropertyValue, NSPropertyDtorFunc aPropDtorFunc, void *aPropDtorData, bool aTransfer, void **aOldValue) { NS_PRECONDITION(aPropertyName && aObject, "unexpected null param"); PropertyList* propertyList = GetPropertyListFor(aPropertyName); if (propertyList) { // Make sure the dtor function and data and the transfer flag match if (aPropDtorFunc != propertyList->mDtorFunc || aPropDtorData != propertyList->mDtorData || aTransfer != propertyList->mTransfer) { NS_WARNING("Destructor/data mismatch while setting property"); return NS_ERROR_INVALID_ARG; } } else { propertyList = new PropertyList(aPropertyName, aPropDtorFunc, aPropDtorData, aTransfer); if (!propertyList || !propertyList->mObjectValueMap.ops) { delete propertyList; return NS_ERROR_OUT_OF_MEMORY; } propertyList->mNext = mPropertyList; mPropertyList = propertyList; } // The current property value (if there is one) is replaced and the current // value is destroyed nsresult result = NS_OK; PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*> (PL_DHashTableOperate(&propertyList->mObjectValueMap, aObject, PL_DHASH_ADD)); if (!entry) return NS_ERROR_OUT_OF_MEMORY; // A nullptr entry->key is the sign that the entry has just been allocated // for us. If it's non-nullptr then we have an existing entry. if (entry->key) { if (aOldValue) *aOldValue = entry->value; else if (propertyList->mDtorFunc) propertyList->mDtorFunc(const_cast<void*>(entry->key), aPropertyName, entry->value, propertyList->mDtorData); result = NS_PROPTABLE_PROP_OVERWRITTEN; } else if (aOldValue) { *aOldValue = nullptr; } entry->key = aObject; entry->value = aPropertyValue; return result; }