Node NamedAttrMapImpl::setNamedItem ( NodeImpl* arg, int &exceptioncode )
{
    if (!element) {
        exceptioncode = DOMException::NOT_FOUND_ERR;
        return 0;
    }

    // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
    if (isReadOnly()) {
        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
        return 0;
    }

    // WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this map.
    if (arg->getDocument() != element->getDocument()) {
        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
        return 0;
    }

    // Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node
    if (!arg->isAttributeNode()) {
        exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
        return 0;
    }
    AttrImpl *attr = static_cast<AttrImpl*>(arg);

    AttributeImpl* a = attr->attrImpl();
    AttributeImpl* old = getAttributeItem(a->id());
    if (old == a) return arg; // we know about it already

    // INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an attribute of another Element object.
    // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
    if (attr->ownerElement()) {
        exceptioncode = DOMException::INUSE_ATTRIBUTE_ERR;
        return 0;
    }

    if (a->id() == ATTR_ID) {
	element->updateId(old ? old->value() : nullAtom, a->value());
    }

    // ### slightly inefficient - resizes attribute array twice.
    Node r;
    if (old) {
        if (!old->attrImpl())
            old->allocateImpl(element);
        r = old->_impl;
        removeAttribute(a->id());
    }

    addAttribute(a);
    return r;
}
Exemple #2
0
Node NamedAttrMapImpl::setNamedItem(NodeImpl *arg, bool nsAware, DOMStringImpl *qName, int &exceptioncode)
{
    if(!m_element)
    {
        exceptioncode = DOMException::NOT_FOUND_ERR;
        return 0;
    }

    // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
    if(isReadOnly())
    {
        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
        return 0;
    }

    // WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this map.
    if(arg->getDocument() != m_element->getDocument())
    {
        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
        return 0;
    }

    // HIERARCHY_REQUEST_ERR: Raised if an attempt is made to add a node doesn't belong in this NamedNodeMap
    if(!arg->isAttributeNode())
    {
        exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
        return 0;
    }
    AttrImpl *attr = static_cast< AttrImpl * >(arg);

    // INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an attribute of another Element object.
    // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
    if(attr->ownerElement() && attr->ownerElement() != m_element)
    {
        exceptioncode = DOMException::INUSE_ATTRIBUTE_ERR;
        return 0;
    }

    if(attr->ownerElement() == m_element)
    {
        // Already have this attribute.
        // DOMTS core-1 test "hc_elementreplaceattributewithself" says we should return it.
        return attr;
    }
    unsigned int mask = nsAware ? ~0L : NodeImpl_IdLocalMask;
    NodeImpl::Id id = (attr->id() & mask);

    for(unsigned long i = 0; i < m_attrCount; i++)
    {
        if((m_attrs[i].id() & mask) == id)
        {
            // if we are called with a qualified name, filter out NS-aware elements with non-matching name.
            if(qName && (namespacePart(m_attrs[i].id()) != defaultNamespace) && strcasecmp(m_attrs[i].name(), DOMString(qName)))
                continue;
            // Attribute exists; replace it
            if(id == ATTR_ID)
                m_element->updateId(m_attrs[i].val(), attr->val());

            Node replaced = m_attrs[i].createAttr(m_element, m_element->docPtr());
            m_attrs[i].free();
            m_attrs[i].m_attrId = 0; /* "has implementation" flag */
            m_attrs[i].m_data.attr = attr;
            m_attrs[i].m_data.attr->ref();
            attr->setElement(m_element);
            m_element->parseAttribute(&m_attrs[i]);
            m_element->attributeChanged(m_attrs[i].id());
            // ### dispatch mutation events
            return replaced;
        }
    }

    // No existing attribute; add to list
    m_attrCount++;
    m_attrs = (AttributeImpl *)realloc(m_attrs, m_attrCount * sizeof(AttributeImpl));
    m_attrs[m_attrCount - 1].m_attrId = 0; /* "has implementation" flag */
    m_attrs[m_attrCount - 1].m_data.attr = attr;
    m_attrs[m_attrCount - 1].m_data.attr->ref();
    attr->setElement(m_element);
    if(id == ATTR_ID)
        m_element->updateId(0, attr->val());
    m_element->parseAttribute(&m_attrs[m_attrCount - 1]);
    m_element->attributeChanged(m_attrs[m_attrCount - 1].id());
    // ### dispatch mutation events

    return 0;
}