void*
nsPropertyTable::GetPropertyInternal(nsPropertyOwner aObject,
                                     nsIAtom    *aPropertyName,
                                     bool        aRemove,
                                     nsresult   *aResult)
{
    NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
    nsresult rv = NS_PROPTABLE_PROP_NOT_THERE;
    void *propValue = nullptr;

    PropertyList* propertyList = GetPropertyListFor(aPropertyName);
    if (propertyList) {
        auto entry = static_cast<PropertyListMapEntry*>
                     (propertyList->mObjectValueMap.Search(aObject));
        if (entry) {
            propValue = entry->value;
            if (aRemove) {
                // don't call propertyList->mDtorFunc.  That's the caller's job now.
                propertyList->mObjectValueMap.RemoveEntry(entry);
            }
            rv = NS_OK;
        }
    }

    if (aResult)
        *aResult = rv;

    return propValue;
}
void*
nsPropertyTable::GetPropertyInternal(nsPropertyOwner aObject,
                                     nsIAtom    *aPropertyName,
                                     bool        aRemove,
                                     nsresult   *aResult)
{
  NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
  nsresult rv = NS_PROPTABLE_PROP_NOT_THERE;
  void *propValue = nullptr;

  PropertyList* propertyList = GetPropertyListFor(aPropertyName);
  if (propertyList) {
    PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
                                             (PL_DHashTableOperate(&propertyList->mObjectValueMap, aObject,
                             PL_DHASH_LOOKUP));
    if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
      propValue = entry->value;
      if (aRemove) {
        // don't call propertyList->mDtorFunc.  That's the caller's job now.
        PL_DHashTableRawRemove(&propertyList->mObjectValueMap, entry);
      }
      rv = NS_OK;
    }
  }

  if (aResult)
    *aResult = rv;

  return propValue;
}
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;
}
nsresult
nsPropertyTable::DeleteProperty(nsPropertyOwner aObject,
                                nsIAtom    *aPropertyName)
{
    NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");

    PropertyList* propertyList = GetPropertyListFor(aPropertyName);
    if (propertyList) {
        if (propertyList->DeletePropertyFor(aObject))
            return NS_OK;
    }

    return NS_PROPTABLE_PROP_NOT_THERE;
}