diff --git a/content/base/src/nsDOMLists.h b/content/base/src/nsDOMLists.h index b1ab7610422dea87dec328428e86ec4045493561..c9bbe5f94dc5a50292a1c83bd89b11e87705d29f 100644 --- a/content/base/src/nsDOMLists.h +++ b/content/base/src/nsDOMLists.h @@ -28,6 +28,11 @@ public: return mNames.AppendElement(aName) != nsnull; } + void Clear() + { + mNames.Clear(); + } + private: nsTArray<nsString> mNames; }; diff --git a/content/base/src/nsDOMSettableTokenList.h b/content/base/src/nsDOMSettableTokenList.h index 867bf1753d6fb645ed6a7938b2c700a8c26f0a47..3ca8a08ec8e6a15cc3959b9ec4ec838e96edc0ba 100644 --- a/content/base/src/nsDOMSettableTokenList.h +++ b/content/base/src/nsDOMSettableTokenList.h @@ -16,6 +16,8 @@ class nsGenericElement; class nsIAtom; +// nsISupports must be on the primary inheritance chain +// because nsDOMSettableTokenList is traversed by nsGenericElement. class nsDOMSettableTokenList : public nsDOMTokenList, public nsIDOMDOMSettableTokenList { @@ -30,7 +32,6 @@ public: virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap); -protected: virtual ~nsDOMSettableTokenList(); }; diff --git a/content/base/src/nsDOMTokenList.h b/content/base/src/nsDOMTokenList.h index 1924613e397b484b1cee9e7f8589311d9fe40569..72befdd37ba9ac0bc1febe6286677ed1e3ddc797 100644 --- a/content/base/src/nsDOMTokenList.h +++ b/content/base/src/nsDOMTokenList.h @@ -14,6 +14,8 @@ class nsAttrValue; +// nsISupports must be on the primary inheritance chain +// because nsDOMSettableTokenList is traversed by nsGenericElement. class nsDOMTokenList : public nsIDOMDOMTokenList, public nsWrapperCache { @@ -34,9 +36,6 @@ public: return mElement; } -protected: - ~nsDOMTokenList(); - const nsAttrValue* GetParsedAttr() { if (!mElement) { return nsnull; @@ -44,6 +43,9 @@ protected: return mElement->GetAttrInfo(kNameSpaceID_None, mAttrAtom).mValue; } +protected: + ~nsDOMTokenList(); + nsresult CheckToken(const nsAString& aStr); void AddInternal(const nsAttrValue* aAttr, const nsAString& aToken); void RemoveInternal(const nsAttrValue* aAttr, const nsAString& aToken); diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 5dd1576292fa258fc4b7f9e86e90e5bfd3498ef5..c082991d4c0bdb72faa7130cbd0ab67d1be35c6a 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -4487,9 +4487,16 @@ ContentUnbinder* ContentUnbinder::sContentUnbinder = nsnull; NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericElement) nsINode::Unlink(tmp); - if (tmp->HasProperties() && tmp->IsXUL()) { - tmp->DeleteProperty(nsGkAtoms::contextmenulistener); - tmp->DeleteProperty(nsGkAtoms::popuplistener); + if (tmp->HasProperties()) { + if (tmp->IsHTML()) { + tmp->DeleteProperty(nsGkAtoms::microdataProperties); + tmp->DeleteProperty(nsGkAtoms::itemtype); + tmp->DeleteProperty(nsGkAtoms::itemref); + tmp->DeleteProperty(nsGkAtoms::itemprop); + } else if (tmp->IsXUL()) { + tmp->DeleteProperty(nsGkAtoms::contextmenulistener); + tmp->DeleteProperty(nsGkAtoms::popuplistener); + } } // Unlink child content (and unbind our subtree). @@ -4987,14 +4994,25 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGenericElement) tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb); - if (tmp->HasProperties() && tmp->IsXUL()) { - nsISupports* property = - static_cast<nsISupports*> - (tmp->GetProperty(nsGkAtoms::contextmenulistener)); - cb.NoteXPCOMChild(property); - property = static_cast<nsISupports*> - (tmp->GetProperty(nsGkAtoms::popuplistener)); - cb.NoteXPCOMChild(property); + if (tmp->HasProperties()) { + if (tmp->IsHTML()) { + nsISupports* property = static_cast<nsISupports*> + (tmp->GetProperty(nsGkAtoms::microdataProperties)); + cb.NoteXPCOMChild(property); + property = static_cast<nsISupports*>(tmp->GetProperty(nsGkAtoms::itemref)); + cb.NoteXPCOMChild(property); + property = static_cast<nsISupports*>(tmp->GetProperty(nsGkAtoms::itemprop)); + cb.NoteXPCOMChild(property); + property = static_cast<nsISupports*>(tmp->GetProperty(nsGkAtoms::itemtype)); + cb.NoteXPCOMChild(property); + } else if (tmp->IsXUL()) { + nsISupports* property = static_cast<nsISupports*> + (tmp->GetProperty(nsGkAtoms::contextmenulistener)); + cb.NoteXPCOMChild(property); + property = static_cast<nsISupports*> + (tmp->GetProperty(nsGkAtoms::popuplistener)); + cb.NoteXPCOMChild(property); + } } // Traverse attribute names and child content. diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index f25b95077f0d84d9403c8959384c2f666258ef87..ebd1c5d614b6d12405df6440fcee334ff2a4a77c 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -536,6 +536,7 @@ GK_ATOM(message, "message") GK_ATOM(meta, "meta") GK_ATOM(meter, "meter") GK_ATOM(method, "method") +GK_ATOM(microdataProperties, "microdataProperties") GK_ATOM(middle, "middle") GK_ATOM(min, "min") GK_ATOM(minheight, "minheight") diff --git a/content/html/content/public/nsHTMLAudioElement.h b/content/html/content/public/nsHTMLAudioElement.h index 1538c234134ffcb3f0e34019b7bfdc2ec16fb4e7..0aab9fc804cdae6f2270a3f8a2908de81897b6ea 100644 --- a/content/html/content/public/nsHTMLAudioElement.h +++ b/content/html/content/public/nsHTMLAudioElement.h @@ -49,6 +49,10 @@ public: virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } + +protected: + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); }; #endif diff --git a/content/html/content/public/nsHTMLVideoElement.h b/content/html/content/public/nsHTMLVideoElement.h index 4dfad6316ac26911c507737bf9497940472400ac..1a66fd925743ecb803235ba39f2d22f25a07aa8b 100644 --- a/content/html/content/public/nsHTMLVideoElement.h +++ b/content/html/content/public/nsHTMLVideoElement.h @@ -60,6 +60,10 @@ public: virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } + +protected: + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); }; #endif diff --git a/content/html/content/src/HTMLPropertiesCollection.cpp b/content/html/content/src/HTMLPropertiesCollection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7504ea6d6c22ecad30398d377fc15985e58ef13a --- /dev/null +++ b/content/html/content/src/HTMLPropertiesCollection.cpp @@ -0,0 +1,610 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "HTMLPropertiesCollection.h" +#include "dombindings.h" +#include "nsIDocument.h" +#include "nsContentUtils.h" +#include "nsGenericHTMLElement.h" +#include "nsVariant.h" +#include "nsDOMSettableTokenList.h" +#include "nsAttrValue.h" + +DOMCI_DATA(HTMLPropertiesCollection, mozilla::dom::HTMLPropertiesCollection) +DOMCI_DATA(PropertyNodeList, mozilla::dom::PropertyNodeList) + +namespace mozilla { +namespace dom { + +static PLDHashOperator +TraverseNamedProperties(const nsAString& aKey, PropertyNodeList* aEntry, void* aData) +{ + nsCycleCollectionTraversalCallback* cb = static_cast<nsCycleCollectionTraversalCallback*>(aData); + cb->NoteXPCOMChild(static_cast<nsIDOMPropertyNodeList*>(aEntry)); + return PL_DHASH_NEXT; +} + +NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLPropertiesCollection) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HTMLPropertiesCollection) + // SetDocument(nsnull) ensures that we remove ourselves as a mutation observer + tmp->SetDocument(nsnull); + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRoot) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNames) + tmp->mNamedItemEntries.Clear(); + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mProperties) + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(HTMLPropertiesCollection) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNames) + tmp->mNamedItemEntries.EnumerateRead(TraverseNamedProperties, &cb); + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mProperties) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(HTMLPropertiesCollection) + NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +HTMLPropertiesCollection::HTMLPropertiesCollection(nsGenericHTMLElement* aRoot) + : mRoot(aRoot) + , mDoc(aRoot->GetCurrentDoc()) + , mIsDirty(true) +{ + SetIsDOMBinding(); + mNames = new PropertyStringList(this); + if (mDoc) { + mDoc->AddMutationObserver(this); + } + mNamedItemEntries.Init(); +} + +HTMLPropertiesCollection::~HTMLPropertiesCollection() +{ + if (mDoc) { + mDoc->RemoveMutationObserver(this); + } +} + +NS_INTERFACE_TABLE_HEAD(HTMLPropertiesCollection) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_TABLE4(HTMLPropertiesCollection, + nsIDOMHTMLPropertiesCollection, + nsIDOMHTMLCollection, + nsIHTMLCollection, + nsIMutationObserver) + NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(HTMLPropertiesCollection) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLPropertiesCollection) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(HTMLPropertiesCollection) +NS_IMPL_CYCLE_COLLECTING_RELEASE(HTMLPropertiesCollection) + + +static PLDHashOperator +SetPropertyListDocument(const nsAString& aKey, PropertyNodeList* aEntry, void* aData) +{ + aEntry->SetDocument(static_cast<nsIDocument*>(aData)); + return PL_DHASH_NEXT; +} + +void +HTMLPropertiesCollection::SetDocument(nsIDocument* aDocument) { + if (mDoc) { + mDoc->RemoveMutationObserver(this); + } + mDoc = aDocument; + if (mDoc) { + mDoc->AddMutationObserver(this); + } + mNamedItemEntries.EnumerateRead(SetPropertyListDocument, aDocument); + mIsDirty = true; +} + +JSObject* +HTMLPropertiesCollection::WrapObject(JSContext* cx, JSObject* scope, + bool* triedToWrap) +{ + return mozilla::dom::binding::HTMLPropertiesCollection::create(cx, scope, this, + triedToWrap); +} + +NS_IMETHODIMP +HTMLPropertiesCollection::GetLength(PRUint32* aLength) +{ + EnsureFresh(); + *aLength = mProperties.Length(); + return NS_OK; +} + +NS_IMETHODIMP +HTMLPropertiesCollection::Item(PRUint32 aIndex, nsIDOMNode** aResult) +{ + EnsureFresh(); + nsGenericHTMLElement* property = mProperties.SafeElementAt(aIndex); + *aResult = property ? property->AsDOMNode() : NULL; + NS_IF_ADDREF(*aResult); + return NS_OK; +} + +NS_IMETHODIMP +HTMLPropertiesCollection::NamedItem(const nsAString& aName, + nsIDOMNode** aResult) +{ + *aResult = NULL; + return NS_OK; +} + +nsISupports* +HTMLPropertiesCollection::GetNamedItem(const nsAString& aName, + nsWrapperCache **aCache) +{ + EnsureFresh(); + if (!mNames->ContainsInternal(aName)) { + *aCache = NULL; + return NULL; + } + + nsRefPtr<PropertyNodeList> propertyList; + if (!mNamedItemEntries.Get(aName, getter_AddRefs(propertyList))) { + propertyList = new PropertyNodeList(this, mRoot, aName); + mNamedItemEntries.Put(aName, propertyList); + } + *aCache = propertyList; + return static_cast<nsIDOMPropertyNodeList*>(propertyList); +} + +nsIContent* +HTMLPropertiesCollection::GetNodeAt(PRUint32 aIndex) +{ + EnsureFresh(); + return mProperties.SafeElementAt(aIndex); +} + +nsINode* +HTMLPropertiesCollection::GetParentObject() +{ + return mRoot; +} + +NS_IMETHODIMP +HTMLPropertiesCollection::NamedItem(const nsAString& aName, + nsIDOMPropertyNodeList** aResult) +{ + EnsureFresh(); + + nsRefPtr<PropertyNodeList> propertyList; + if (!mNamedItemEntries.Get(aName, getter_AddRefs(propertyList))) { + propertyList = new PropertyNodeList(this, mRoot, aName); + mNamedItemEntries.Put(aName, propertyList); + } + propertyList.forget(aResult); + return NS_OK; +} + +NS_IMETHODIMP +HTMLPropertiesCollection::GetNames(nsIDOMDOMStringList** aResult) +{ + EnsureFresh(); + NS_ADDREF(*aResult = mNames); + return NS_OK; +} + +void +HTMLPropertiesCollection::AttributeChanged(nsIDocument *aDocument, Element* aElement, + PRInt32 aNameSpaceID, nsIAtom* aAttribute, + PRInt32 aModType) +{ + mIsDirty = true; +} + +void +HTMLPropertiesCollection::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer, + nsIContent* aFirstNewContent, + PRInt32 aNewIndexInContainer) +{ + mIsDirty = true; +} + +void +HTMLPropertiesCollection::ContentInserted(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer) +{ + mIsDirty = true; +} + +void +HTMLPropertiesCollection::ContentRemoved(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer, + nsIContent* aPreviousSibling) +{ + mIsDirty = true; +} + +class TreeOrderComparator { + public: + bool Equals(const nsGenericHTMLElement* aElem1, + const nsGenericHTMLElement* aElem2) const { + return aElem1 == aElem2; + } + bool LessThan(const nsGenericHTMLElement* aElem1, + const nsGenericHTMLElement* aElem2) const { + return nsContentUtils::PositionIsBefore(const_cast<nsGenericHTMLElement*>(aElem1), + const_cast<nsGenericHTMLElement*>(aElem2)); + } +}; + +static PLDHashOperator +MarkDirty(const nsAString& aKey, PropertyNodeList* aEntry, void* aData) +{ + aEntry->SetDirty(); + return PL_DHASH_NEXT; +} + +void +HTMLPropertiesCollection::EnsureFresh() +{ + if (mDoc && !mIsDirty) { + return; + } + mIsDirty = false; + + mProperties.Clear(); + mNames->Clear(); + // We don't clear NamedItemEntries because the PropertyNodeLists must be live. + mNamedItemEntries.EnumerateRead(MarkDirty, NULL); + if (!mRoot->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope)) { + return; + } + + CrawlProperties(); + TreeOrderComparator comparator; + mProperties.Sort(comparator); + + // Create the names DOMStringList + PRUint32 count = mProperties.Length(); + for (PRUint32 i = 0; i < count; ++i) { + const nsAttrValue* attr = mProperties.ElementAt(i)->GetParsedAttr(nsGkAtoms::itemprop); + for (PRUint32 i = 0; i < attr->GetAtomCount(); i++) { + nsDependentAtomString propName(attr->AtomAt(i)); + // ContainsInternal must not call EnsureFresh + bool contains = mNames->ContainsInternal(propName); + if (!contains) { + mNames->Add(propName); + } + } + } +} + +static Element* +GetElementByIdForConnectedSubtree(nsIContent* aContent, const nsIAtom* aId) +{ + aContent = static_cast<nsIContent*>(aContent->SubtreeRoot()); + do { + if (aContent->GetID() == aId) { + return aContent->AsElement(); + } + aContent = aContent->GetNextNode(); + } while(aContent); + + return NULL; +} + +void +HTMLPropertiesCollection::CrawlProperties() +{ + nsIDocument* doc = mRoot->GetCurrentDoc(); + + const nsAttrValue* attr = mRoot->GetParsedAttr(nsGkAtoms::itemref); + if (attr) { + for (PRUint32 i = 0; i < attr->GetAtomCount(); i++) { + nsIAtom* ref = attr->AtomAt(i); + Element* element; + if (doc) { + element = doc->GetElementById(nsDependentAtomString(ref)); + } else { + element = GetElementByIdForConnectedSubtree(mRoot, ref); + } + if (element && element != mRoot) { + CrawlSubtree(element); + } + } + } + + CrawlSubtree(mRoot); +} + +void +HTMLPropertiesCollection::CrawlSubtree(Element* aElement) +{ + nsIContent* aContent = aElement; + while (aContent) { + // We must check aContent against mRoot because + // an element must not be its own property + if (aContent == mRoot || !aContent->IsHTML()) { + // Move on to the next node in the tree + aContent = aContent->GetNextNode(aElement); + } else { + MOZ_ASSERT(aContent->IsElement(), "IsHTML() returned true!"); + Element* element = aContent->AsElement(); + if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) && + !mProperties.Contains(element)) { + mProperties.AppendElement(static_cast<nsGenericHTMLElement*>(element)); + } + + if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope)) { + aContent = element->GetNextNonChildNode(aElement); + } else { + aContent = element->GetNextNode(aElement); + } + } + } +} + +PropertyNodeList::PropertyNodeList(HTMLPropertiesCollection* aCollection, + nsIContent* aParent, const nsAString& aName) + : mName(aName), + mDoc(aParent->GetCurrentDoc()), + mCollection(aCollection), + mParent(aParent), + mIsDirty(true) +{ + SetIsDOMBinding(); + if (mDoc) { + mDoc->AddMutationObserver(this); + } +} + +PropertyNodeList::~PropertyNodeList() +{ + if (mDoc) { + mDoc->RemoveMutationObserver(this); + } +} + +void +PropertyNodeList::SetDocument(nsIDocument* aDoc) +{ + if (mDoc) { + mDoc->RemoveMutationObserver(this); + } + mDoc = aDoc; + if (mDoc) { + mDoc->AddMutationObserver(this); + } + mIsDirty = true; +} + +NS_IMETHODIMP +PropertyNodeList::GetLength(PRUint32* aLength) +{ + EnsureFresh(); + *aLength = mElements.Length(); + return NS_OK; +} + +NS_IMETHODIMP +PropertyNodeList::Item(PRUint32 aIndex, nsIDOMNode** aReturn) +{ + EnsureFresh(); + nsINode* element = mElements.SafeElementAt(aIndex); + if (!element) { + *aReturn = NULL; + return NS_OK; + } + return CallQueryInterface(element, aReturn); +} + +nsIContent* +PropertyNodeList::GetNodeAt(PRUint32 aIndex) +{ + EnsureFresh(); + return mElements.SafeElementAt(aIndex); +} + +PRInt32 +PropertyNodeList::IndexOf(nsIContent* aContent) +{ + EnsureFresh(); + return mElements.IndexOf(aContent); +} + +nsINode* +PropertyNodeList::GetParentObject() +{ + return mParent; +} + +JSObject* +PropertyNodeList::WrapObject(JSContext *cx, JSObject *scope, + bool *triedToWrap) +{ + return mozilla::dom::binding::PropertyNodeList::create(cx, scope, this, + triedToWrap); +} + +NS_IMPL_CYCLE_COLLECTION_CLASS(PropertyNodeList) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PropertyNodeList) + // SetDocument(nsnull) ensures that we remove ourselves as a mutation observer + tmp->SetDocument(nsnull); + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCollection) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements) + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PropertyNodeList) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCollection, nsIDOMHTMLPropertiesCollection) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mElements) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(PropertyNodeList) + NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(PropertyNodeList) +NS_IMPL_CYCLE_COLLECTING_RELEASE(PropertyNodeList) + +NS_INTERFACE_TABLE_HEAD(PropertyNodeList) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_TABLE4(PropertyNodeList, + nsIDOMPropertyNodeList, + nsIDOMNodeList, + nsINodeList, + nsIMutationObserver) + NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(PropertyNodeList) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PropertyNodeList) +NS_INTERFACE_MAP_END + +NS_IMETHODIMP +PropertyNodeList::GetValues(nsIVariant** aValues) +{ + EnsureFresh(); + nsCOMPtr<nsIWritableVariant> out = new nsVariant(); + + // We have to use an nsTArray<nsIVariant*> here and do manual refcounting because + // nsWritableVariant::SetAsArray takes an nsIVariant**. + nsTArray<nsIVariant*> values; + + PRUint32 length = mElements.Length(); + if (length == 0) { + out->SetAsEmptyArray(); + } else { + for (PRUint32 i = 0; i < length; ++i) { + nsIVariant* itemValue; + mElements.ElementAt(i)->GetItemValue(&itemValue); + values.AppendElement(itemValue); + } + out->SetAsArray(nsIDataType::VTYPE_INTERFACE_IS, + &NS_GET_IID(nsIVariant), + values.Length(), + values.Elements()); + } + + out.forget(aValues); + + for (PRUint32 i = 0; i < values.Length(); ++i) { + NS_RELEASE(values[i]); + } + + return NS_OK; +} + +void +PropertyNodeList::AttributeChanged(nsIDocument* aDocument, Element* aElement, + PRInt32 aNameSpaceID, nsIAtom* aAttribute, + PRInt32 aModType) +{ + mIsDirty = true; +} + +void +PropertyNodeList::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer, + nsIContent* aFirstNewContent, + PRInt32 aNewIndexInContainer) +{ + mIsDirty = true; +} + +void +PropertyNodeList::ContentInserted(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer) +{ + mIsDirty = true; +} + +void +PropertyNodeList::ContentRemoved(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer, + nsIContent* aPreviousSibling) +{ + mIsDirty = true; +} + +void +PropertyNodeList::EnsureFresh() +{ + if (mDoc && !mIsDirty) { + return; + } + mIsDirty = false; + + mCollection->EnsureFresh(); + Clear(); + + PRUint32 count = mCollection->mProperties.Length(); + for (PRUint32 i = 0; i < count; ++i) { + nsGenericHTMLElement* element = mCollection->mProperties.ElementAt(i); + const nsAttrValue* attr = element->GetParsedAttr(nsGkAtoms::itemprop); + if (attr->Contains(mName)) { + AppendElement(element); + } + } +} + +PropertyStringList::PropertyStringList(HTMLPropertiesCollection* aCollection) + : nsDOMStringList() + , mCollection(aCollection) +{ } + +NS_IMPL_CYCLE_COLLECTION_CLASS(PropertyStringList) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PropertyStringList) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCollection) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PropertyStringList) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCollection, nsIDOMHTMLPropertiesCollection) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(PropertyStringList) +NS_IMPL_CYCLE_COLLECTING_RELEASE(PropertyStringList) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PropertyStringList) + NS_INTERFACE_MAP_ENTRY(nsIDOMDOMStringList) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMStringList) +NS_INTERFACE_MAP_END + +NS_IMETHODIMP +PropertyStringList::Item(PRUint32 aIndex, nsAString& aResult) +{ + mCollection->EnsureFresh(); + return nsDOMStringList::Item(aIndex, aResult); +} + +NS_IMETHODIMP +PropertyStringList::GetLength(PRUint32* aLength) +{ + mCollection->EnsureFresh(); + return nsDOMStringList::GetLength(aLength); +} + +NS_IMETHODIMP +PropertyStringList::Contains(const nsAString& aString, bool* aResult) +{ + mCollection->EnsureFresh(); + return nsDOMStringList::Contains(aString, aResult); +} + +bool +PropertyStringList::ContainsInternal(const nsAString& aString) +{ + // This method should not call EnsureFresh, otherwise we may become stuck in an infinite loop. + bool result; + nsDOMStringList::Contains(aString, &result); + return result; +} + +} // namespace dom +} // namespace mozilla diff --git a/content/html/content/src/HTMLPropertiesCollection.h b/content/html/content/src/HTMLPropertiesCollection.h new file mode 100644 index 0000000000000000000000000000000000000000..7d1d8d099c42512dab85a2384082a0146af84021 --- /dev/null +++ b/content/html/content/src/HTMLPropertiesCollection.h @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef HTMLPropertiesCollection_h_ +#define HTMLPropertiesCollection_h_ + +#include "nsDOMLists.h" +#include "nsCycleCollectionParticipant.h" +#include "nsAutoPtr.h" +#include "nsIDOMHTMLPropertiesCollection.h" +#include "nsIDOMPropertyNodeList.h" +#include "nsCOMArray.h" +#include "nsIMutationObserver.h" +#include "nsStubMutationObserver.h" +#include "nsBaseHashtable.h" +#include "nsINodeList.h" +#include "nsIHTMLCollection.h" +#include "nsHashKeys.h" +#include "nsGenericHTMLElement.h" + +class nsXPCClassInfo; +class nsIDocument; +class nsINode; + +namespace mozilla { +namespace dom { + +class HTMLPropertiesCollection; +class PropertyNodeList; + +class PropertyStringList : public nsDOMStringList +{ +public: + PropertyStringList(HTMLPropertiesCollection* aCollection); + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(PropertyStringList) + NS_DECL_NSIDOMDOMSTRINGLIST + + bool ContainsInternal(const nsAString& aString); + +protected: + nsRefPtr<HTMLPropertiesCollection> mCollection; +}; + +class HTMLPropertiesCollection : public nsIDOMHTMLPropertiesCollection, + public nsStubMutationObserver, + public nsWrapperCache, + public nsIHTMLCollection +{ + friend class PropertyNodeList; + friend class PropertyStringList; +public: + HTMLPropertiesCollection(nsGenericHTMLElement* aRoot); + virtual ~HTMLPropertiesCollection(); + + virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, + bool *triedToWrap); + + NS_IMETHOD NamedItem(const nsAString& aName, nsIDOMNode** aResult); + void SetDocument(nsIDocument* aDocument); + nsINode* GetParentObject(); + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_NSIDOMHTMLPROPERTIESCOLLECTION + + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(HTMLPropertiesCollection, + nsIHTMLCollection) + + nsXPCClassInfo* GetClassInfo(); + +protected: + // Make sure this collection is up to date, in case the DOM has been mutated. + void EnsureFresh(); + + // Crawl the properties of mRoot, following any itemRefs it may have + void CrawlProperties(); + + // Crawl startNode and its descendants, looking for items + void CrawlSubtree(Element* startNode); + + // the items that make up this collection + nsTArray<nsRefPtr<nsGenericHTMLElement> > mProperties; + + // the itemprop attribute of the properties + nsRefPtr<PropertyStringList> mNames; + + // The cached PropertyNodeLists that are NamedItems of this collection + nsRefPtrHashtable<nsStringHashKey, PropertyNodeList> mNamedItemEntries; + + // The element this collection is rooted at + nsCOMPtr<nsGenericHTMLElement> mRoot; + + // The document mRoot is in, if any + nsCOMPtr<nsIDocument> mDoc; + + // True if there have been DOM modifications since the last EnsureFresh call. + bool mIsDirty; +}; + +class PropertyNodeList : public nsINodeList, + public nsIDOMPropertyNodeList, + public nsStubMutationObserver +{ +public: + PropertyNodeList(HTMLPropertiesCollection* aCollection, + nsIContent* aRoot, const nsAString& aName); + virtual ~PropertyNodeList(); + + virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, + bool *triedToWrap); + + void SetDocument(nsIDocument* aDocument); + + NS_DECL_NSIDOMPROPERTYNODELIST + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(PropertyNodeList, + nsINodeList) + + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + + // nsINodeList interface + virtual PRInt32 IndexOf(nsIContent* aContent); + virtual nsINode* GetParentObject(); + + void AppendElement(nsGenericHTMLElement* aElement) + { + mElements.AppendElement(aElement); + } + + void Clear() + { + mElements.Clear(); + } + + void SetDirty() { mIsDirty = true; } + +protected: + // Make sure this list is up to date, in case the DOM has been mutated. + void EnsureFresh(); + + // the the name that this list corresponds to + nsString mName; + + // the document mParent is in, if any + nsCOMPtr<nsIDocument> mDoc; + + // the collection that this list is a named item of + nsRefPtr<HTMLPropertiesCollection> mCollection; + + // the node this list is rooted at + nsCOMPtr<nsINode> mParent; + + // the properties that make up this list + nsTArray<nsRefPtr<nsGenericHTMLElement> > mElements; + + // True if there have been DOM modifications since the last EnsureFresh call. + bool mIsDirty; +}; + +} // namespace dom +} // namespace mozilla +#endif // HTMLPropertiesCollection_h_ diff --git a/content/html/content/src/Makefile.in b/content/html/content/src/Makefile.in index c225b544fb0e308d16d15839613966fa3e362787..54be7d9bf1548f1f2c5146a215093c8769cedc25 100644 --- a/content/html/content/src/Makefile.in +++ b/content/html/content/src/Makefile.in @@ -22,6 +22,7 @@ EXPORTS = \ $(NULL) CPPSRCS = \ + HTMLPropertiesCollection.cpp \ nsClientRect.cpp \ nsHTMLDNSPrefetch.cpp \ nsGenericHTMLElement.cpp \ diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index ba71914ecdbf52291b6a59f88572d16464abb8e0..ad4479b24e1ec4b025e741b49e9f4e3bb6b4c84c 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -91,6 +91,9 @@ #include "mozilla/dom/FromParser.h" #include "mozilla/BloomFilter.h" +#include "HTMLPropertiesCollection.h" +#include "nsVariant.h" + using namespace mozilla; using namespace mozilla::dom; @@ -248,7 +251,6 @@ NS_INTERFACE_TABLE_HEAD(nsGenericHTMLElementTearoff) NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsGenericHTMLElementTearoff) NS_INTERFACE_MAP_END_AGGREGATED(mElement) - NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsGenericHTMLElement, TabIndex, tabindex, -1) NS_IMPL_BOOL_ATTR(nsGenericHTMLElement, Hidden, hidden) @@ -1699,6 +1701,13 @@ nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, NS_ENSURE_SUCCESS(rv, rv); if (aDocument) { + if (HasProperties()) { + HTMLPropertiesCollection* properties = + static_cast<HTMLPropertiesCollection*>(GetProperty(nsGkAtoms::microdataProperties)); + if (properties) { + properties->SetDocument(aDocument); + } + } RegAccessKey(); if (HasName()) { aDocument-> @@ -1721,6 +1730,14 @@ nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent) if (IsInDoc()) { UnregAccessKey(); } + + if(HasProperties()) { + HTMLPropertiesCollection* properties = + static_cast<HTMLPropertiesCollection*>(GetProperty(nsGkAtoms::microdataProperties)); + if (properties) { + properties->SetDocument(nsnull); + } + } RemoveFromNameTable(); @@ -2073,6 +2090,13 @@ nsGenericHTMLElement::ParseAttribute(PRInt32 aNamespaceID, aResult.ParseAtom(aValue); return true; } + + if (aAttribute == nsGkAtoms::itemref || + aAttribute == nsGkAtoms::itemprop || + aAttribute == nsGkAtoms::itemtype) { + aResult.ParseAtomArray(aValue); + return true; + } } return nsGenericHTMLElementBase::ParseAttribute(aNamespaceID, aAttribute, @@ -4081,3 +4105,162 @@ nsGenericHTMLElement::ChangeEditableState(PRInt32 aChange) nsAutoScriptBlocker scriptBlocker; MakeContentDescendantsEditable(this, document); } + +NS_IMPL_BOOL_ATTR(nsGenericHTMLElement, ItemScope, itemscope) +NS_IMPL_URI_ATTR(nsGenericHTMLElement, ItemId, itemid) + +NS_IMETHODIMP +nsGenericHTMLElement::GetItemValue(nsIVariant** aValue) +{ + nsCOMPtr<nsIWritableVariant> out = new nsVariant(); + + if (!HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop)) { + out->SetAsEmpty(); + out.forget(aValue); + return NS_OK; + } + + bool itemScope; + GetItemScope(&itemScope); + if (itemScope) { + out->SetAsISupports(static_cast<nsISupports*>(this)); + } else { + nsAutoString string; + GetItemValueText(string); + out->SetAsAString(string); + } + + out.forget(aValue); + return NS_OK; +} + +NS_IMETHODIMP +nsGenericHTMLElement::SetItemValue(nsIVariant* aValue) +{ + if (!HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) || + HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope)) { + return NS_ERROR_DOM_INVALID_ACCESS_ERR; + } + + nsAutoString string; + aValue->GetAsAString(string); + SetItemValueText(string); + return NS_OK; +} + +void +nsGenericHTMLElement::GetItemValueText(nsAString& text) +{ + GetTextContent(text); +} + +void +nsGenericHTMLElement::SetItemValueText(const nsAString& text) +{ + SetTextContent(text); +} + +static void +nsDOMSettableTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty, + void *aPropertyValue, void *aData) +{ + nsDOMSettableTokenList* list = + static_cast<nsDOMSettableTokenList*>(aPropertyValue); + NS_IF_RELEASE(list); +} + +nsDOMSettableTokenList* +nsGenericHTMLElement::GetTokenList(nsIAtom* aAtom) +{ + nsDOMSettableTokenList* list = NULL; + if (HasProperties()) { + list = static_cast<nsDOMSettableTokenList*>(GetProperty(aAtom)); + } + if (!list) { + list = new nsDOMSettableTokenList(this, aAtom); + NS_ADDREF(list); + SetProperty(aAtom, list, nsDOMSettableTokenListPropertyDestructor); + } + return list; +} + +NS_IMETHODIMP +nsGenericHTMLElement::GetItemRef(nsIVariant** aResult) +{ + nsIDOMDOMSettableTokenList* itemRef = GetTokenList(nsGkAtoms::itemref); + nsCOMPtr<nsIWritableVariant> out = new nsVariant(); + out->SetAsInterface(NS_GET_IID(nsIDOMDOMSettableTokenList), itemRef); + out.forget(aResult); + return NS_OK; +} + +NS_IMETHODIMP +nsGenericHTMLElement::SetItemRef(nsIVariant* aValue) +{ + nsDOMSettableTokenList* itemRef = GetTokenList(nsGkAtoms::itemref); + nsAutoString string; + aValue->GetAsAString(string); + return itemRef->SetValue(string); +} + +NS_IMETHODIMP +nsGenericHTMLElement::GetItemProp(nsIVariant** aResult) +{ + nsIDOMDOMSettableTokenList* itemProp = GetTokenList(nsGkAtoms::itemprop); + nsCOMPtr<nsIWritableVariant> out = new nsVariant(); + out->SetAsInterface(NS_GET_IID(nsIDOMDOMSettableTokenList), itemProp); + out.forget(aResult); + return NS_OK; +} + +NS_IMETHODIMP +nsGenericHTMLElement::SetItemProp(nsIVariant* aValue) +{ + nsDOMSettableTokenList* itemProp = GetTokenList(nsGkAtoms::itemprop); + nsAutoString string; + aValue->GetAsAString(string); + return itemProp->SetValue(string); +} + +NS_IMETHODIMP +nsGenericHTMLElement::GetItemType(nsIVariant** aResult) +{ + nsIDOMDOMSettableTokenList* itemType = GetTokenList(nsGkAtoms::itemtype); + nsCOMPtr<nsIWritableVariant> out = new nsVariant(); + out->SetAsInterface(NS_GET_IID(nsIDOMDOMSettableTokenList), itemType); + out.forget(aResult); + return NS_OK; +} + +NS_IMETHODIMP +nsGenericHTMLElement::SetItemType(nsIVariant* aValue) +{ + nsDOMSettableTokenList* itemType = GetTokenList(nsGkAtoms::itemtype); + nsAutoString string; + aValue->GetAsAString(string); + return itemType->SetValue(string); +} + +static void +nsIDOMHTMLPropertiesCollectionDestructor(void *aObject, nsIAtom *aProperty, + void *aPropertyValue, void *aData) +{ + nsIDOMHTMLPropertiesCollection* properties = + static_cast<nsIDOMHTMLPropertiesCollection*>(aPropertyValue); + NS_IF_RELEASE(properties); +} + +NS_IMETHODIMP +nsGenericHTMLElement::GetProperties(nsIDOMHTMLPropertiesCollection** aReturn) +{ + nsIDOMHTMLPropertiesCollection* properties = + static_cast<nsIDOMHTMLPropertiesCollection*>(GetProperty(nsGkAtoms::microdataProperties)); + if (!properties) { + properties = new HTMLPropertiesCollection(this); + NS_ADDREF(properties); + SetProperty(nsGkAtoms::microdataProperties, properties, nsIDOMHTMLPropertiesCollectionDestructor); + } + NS_ADDREF(*aReturn = properties); + return NS_OK; +} + diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 49c8fb1f6e14932b8c86439952f7d76009068df8..cf970b5466b35ac7623ed02a27a94ba302edb28b 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -13,6 +13,8 @@ #include "nsFrameLoader.h" #include "nsGkAtoms.h" #include "nsContentCreatorFunctions.h" +#include "nsDOMSettableTokenList.h" +#include "nsIDOMHTMLPropertiesCollection.h" class nsIDOMAttr; class nsIDOMEventListener; @@ -33,6 +35,7 @@ struct nsSize; class nsHTMLFormElement; class nsIDOMDOMStringMap; class nsIDOMHTMLMenuElement; +class nsIDOMHTMLCollection; typedef nsMappedAttributeElement nsGenericHTMLElementBase; @@ -114,6 +117,26 @@ public: NS_IMETHOD SetSpellcheck(bool aSpellcheck); NS_IMETHOD GetDraggable(bool* aDraggable); NS_IMETHOD SetDraggable(bool aDraggable); + NS_IMETHOD GetItemScope(bool* aItemScope); + NS_IMETHOD SetItemScope(bool aItemScope); + NS_IMETHOD GetItemValue(nsIVariant** aValue); + NS_IMETHOD SetItemValue(nsIVariant* aValue); +protected: + // These methods are used to implement element-specific behavior of Get/SetItemValue + // when an element has @itemprop but no @itemscope. + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); + nsDOMSettableTokenList* GetTokenList(nsIAtom* aAtom); +public: + NS_IMETHOD GetItemType(nsIVariant** aType); + NS_IMETHOD SetItemType(nsIVariant* aType); + NS_IMETHOD GetItemId(nsAString& aId); + NS_IMETHOD SetItemId(const nsAString& aId); + NS_IMETHOD GetItemRef(nsIVariant** aRef); + NS_IMETHOD SetItemRef(nsIVariant* aValue); + NS_IMETHOD GetItemProp(nsIVariant** aProp); + NS_IMETHOD SetItemProp(nsIVariant* aValue); + NS_IMETHOD GetProperties(nsIDOMHTMLPropertiesCollection** aReturn); NS_IMETHOD GetAccessKey(nsAString &aAccessKey); NS_IMETHOD SetAccessKey(const nsAString& aAccessKey); NS_IMETHOD GetAccessKeyLabel(nsAString& aLabel); @@ -771,9 +794,6 @@ private: void ChangeEditableState(PRInt32 aChange); }; - -//---------------------------------------------------------------------- - class nsHTMLFieldSetElement; /** @@ -1376,6 +1396,45 @@ PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32); NS_SCRIPTABLE NS_IMETHOD Blur() { \ return _to Blur(); \ } \ + NS_SCRIPTABLE NS_IMETHOD GetItemScope(bool* aItemScope) { \ + return _to GetItemScope(aItemScope); \ + } \ + NS_SCRIPTABLE NS_IMETHOD SetItemScope(bool aItemScope) { \ + return _to SetItemScope(aItemScope); \ + } \ + NS_SCRIPTABLE NS_IMETHOD GetItemType(nsIVariant** aType) { \ + return _to GetItemType(aType); \ + } \ + NS_SCRIPTABLE NS_IMETHOD SetItemType(nsIVariant* aType) { \ + return _to SetItemType(aType); \ + } \ + NS_SCRIPTABLE NS_IMETHOD GetItemId(nsAString& aId) { \ + return _to GetItemId(aId); \ + } \ + NS_SCRIPTABLE NS_IMETHOD SetItemId(const nsAString& aId) { \ + return _to SetItemId(aId); \ + } \ + NS_SCRIPTABLE NS_IMETHOD GetProperties(nsIDOMHTMLPropertiesCollection** aReturn) { \ + return _to GetProperties(aReturn); \ + } \ + NS_SCRIPTABLE NS_IMETHOD GetItemValue(nsIVariant** aValue) { \ + return _to GetItemValue(aValue); \ + } \ + NS_SCRIPTABLE NS_IMETHOD SetItemValue(nsIVariant* aValue) { \ + return _to SetItemValue(aValue); \ + } \ + NS_SCRIPTABLE NS_IMETHOD GetItemRef(nsIVariant** aRef) { \ + return _to GetItemRef(aRef); \ + } \ + NS_SCRIPTABLE NS_IMETHOD SetItemRef(nsIVariant* aRef) { \ + return _to SetItemRef(aRef); \ + } \ + NS_SCRIPTABLE NS_IMETHOD GetItemProp(nsIVariant** aProp) { \ + return _to GetItemProp(aProp); \ + } \ + NS_SCRIPTABLE NS_IMETHOD SetItemProp(nsIVariant* aProp) { \ + return _to SetItemProp(aProp); \ + } \ NS_SCRIPTABLE NS_IMETHOD GetAccessKey(nsAString& aAccessKey) { \ return _to GetAccessKey(aAccessKey); \ } \ diff --git a/content/html/content/src/nsHTMLAnchorElement.cpp b/content/html/content/src/nsHTMLAnchorElement.cpp index 533098e0da672d5151145aa56f74f46eeb38bedb..2794c88e59a13905564d94a5802e28a54077ea6d 100644 --- a/content/html/content/src/nsHTMLAnchorElement.cpp +++ b/content/html/content/src/nsHTMLAnchorElement.cpp @@ -110,6 +110,10 @@ public: virtual void OnDNSPrefetchDeferred(); virtual void OnDNSPrefetchRequested(); virtual bool HasDeferredDNSPrefetchRequest(); + +protected: + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); }; // Indicates that a DNS Prefetch has been requested from this Anchor elem @@ -166,6 +170,18 @@ NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Shape, shape) NS_IMPL_INT_ATTR(nsHTMLAnchorElement, TabIndex, tabindex) NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Type, type) +void +nsHTMLAnchorElement::GetItemValueText(nsAString& aValue) +{ + GetHref(aValue); +} + +void +nsHTMLAnchorElement::SetItemValueText(const nsAString& aValue) +{ + SetHref(aValue); +} + NS_IMETHODIMP nsHTMLAnchorElement::GetDraggable(bool* aDraggable) { diff --git a/content/html/content/src/nsHTMLAreaElement.cpp b/content/html/content/src/nsHTMLAreaElement.cpp index 47bdfe0f96da4076b70d7e83fe8ffb04bcedbcf0..1eb3d0d8c3f5692abeefd176ab74fd7009cd0f72 100644 --- a/content/html/content/src/nsHTMLAreaElement.cpp +++ b/content/html/content/src/nsHTMLAreaElement.cpp @@ -95,6 +95,10 @@ public: virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } + +protected: + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); }; @@ -137,6 +141,18 @@ NS_IMPL_BOOL_ATTR(nsHTMLAreaElement, NoHref, nohref) NS_IMPL_STRING_ATTR(nsHTMLAreaElement, Shape, shape) NS_IMPL_INT_ATTR(nsHTMLAreaElement, TabIndex, tabindex) +void +nsHTMLAreaElement::GetItemValueText(nsAString& aValue) +{ + GetHref(aValue); +} + +void +nsHTMLAreaElement::SetItemValueText(const nsAString& aValue) +{ + SetHref(aValue); +} + NS_IMETHODIMP nsHTMLAreaElement::GetTarget(nsAString& aValue) { diff --git a/content/html/content/src/nsHTMLAudioElement.cpp b/content/html/content/src/nsHTMLAudioElement.cpp index ee3177a92cd5cb556e29be0e390bd52ce69d7644..229f0c806b6a1392a61d052cddb5072daf2d47b8 100644 --- a/content/html/content/src/nsHTMLAudioElement.cpp +++ b/content/html/content/src/nsHTMLAudioElement.cpp @@ -83,6 +83,20 @@ nsHTMLAudioElement::~nsHTMLAudioElement() { } +void +nsHTMLAudioElement::GetItemValueText(nsAString& aValue) +{ + // Can't call GetSrc because we don't have a JSContext + GetURIAttr(nsGkAtoms::src, nsnull, aValue); +} + +void +nsHTMLAudioElement::SetItemValueText(const nsAString& aValue) +{ + // Can't call SetSrc because we don't have a JSContext + SetAttr(kNameSpaceID_None, nsGkAtoms::src, aValue, true); +} + NS_IMETHODIMP nsHTMLAudioElement::Initialize(nsISupports* aOwner, JSContext* aContext, JSObject *aObj, PRUint32 argc, jsval *argv) diff --git a/content/html/content/src/nsHTMLIFrameElement.cpp b/content/html/content/src/nsHTMLIFrameElement.cpp index 9d9cb7ec2d5069eee5444cdc6a42a29b92e3baa7..69bb73fa09a0493cdd48023c66f787483428b5b8 100644 --- a/content/html/content/src/nsHTMLIFrameElement.cpp +++ b/content/html/content/src/nsHTMLIFrameElement.cpp @@ -58,6 +58,10 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } + +protected: + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); }; @@ -106,6 +110,18 @@ NS_IMPL_URI_ATTR(nsHTMLIFrameElement, Src, src) NS_IMPL_STRING_ATTR(nsHTMLIFrameElement, Width, width) NS_IMPL_BOOL_ATTR(nsHTMLIFrameElement, MozAllowFullScreen, mozallowfullscreen) +void +nsHTMLIFrameElement::GetItemValueText(nsAString& aValue) +{ + GetSrc(aValue); +} + +void +nsHTMLIFrameElement::SetItemValueText(const nsAString& aValue) +{ + SetSrc(aValue); +} + NS_IMETHODIMP nsHTMLIFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument) { diff --git a/content/html/content/src/nsHTMLImageElement.cpp b/content/html/content/src/nsHTMLImageElement.cpp index 6a2a089f4ab9cd67de58a314c09497c252b32898..812334e48de6f49877d6ab10a61702a5a4a2d6be 100644 --- a/content/html/content/src/nsHTMLImageElement.cpp +++ b/content/html/content/src/nsHTMLImageElement.cpp @@ -116,6 +116,18 @@ NS_IMPL_URI_ATTR(nsHTMLImageElement, Src, src) NS_IMPL_STRING_ATTR(nsHTMLImageElement, UseMap, usemap) NS_IMPL_INT_ATTR(nsHTMLImageElement, Vspace, vspace) +void +nsHTMLImageElement::GetItemValueText(nsAString& aValue) +{ + GetSrc(aValue); +} + +void +nsHTMLImageElement::SetItemValueText(const nsAString& aValue) +{ + SetSrc(aValue); +} + // crossorigin is not "limited to only known values" per spec, so it's // just a string attr purposes of the DOM crossOrigin property. NS_IMPL_STRING_ATTR(nsHTMLImageElement, CrossOrigin, crossorigin) diff --git a/content/html/content/src/nsHTMLImageElement.h b/content/html/content/src/nsHTMLImageElement.h index e230f0f7bef7e01d23c5cf5c1b4853632efd1bf5..99c0a00a31a95dde1ee2f8d4a4d71e475f466777 100644 --- a/content/html/content/src/nsHTMLImageElement.h +++ b/content/html/content/src/nsHTMLImageElement.h @@ -103,6 +103,8 @@ public: protected: nsIntPoint GetXY(); nsSize GetWidthHeight(); + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); }; #endif /* nsHTMLImageElement_h */ diff --git a/content/html/content/src/nsHTMLLinkElement.cpp b/content/html/content/src/nsHTMLLinkElement.cpp index 6ae52fb16cd8d8a2a73f51b6aabe3f5b9d117379..2e72964081faa81974ba19a8a5a8dea6755fda41 100644 --- a/content/html/content/src/nsHTMLLinkElement.cpp +++ b/content/html/content/src/nsHTMLLinkElement.cpp @@ -95,6 +95,9 @@ protected: nsAString& aType, nsAString& aMedia, bool* aIsAlternate); +protected: + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); }; @@ -172,6 +175,18 @@ NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rev, rev) NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Target, target) NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Type, type) +void +nsHTMLLinkElement::GetItemValueText(nsAString& aValue) +{ + GetHref(aValue); +} + +void +nsHTMLLinkElement::SetItemValueText(const nsAString& aValue) +{ + SetHref(aValue); +} + nsresult nsHTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, diff --git a/content/html/content/src/nsHTMLMetaElement.cpp b/content/html/content/src/nsHTMLMetaElement.cpp index d5c8bf76772e4d69f9f1aba796a9f3127946f60e..f82bafa21b2ce4e990652294422a148930f7fd30 100644 --- a/content/html/content/src/nsHTMLMetaElement.cpp +++ b/content/html/content/src/nsHTMLMetaElement.cpp @@ -45,6 +45,10 @@ public: virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } + +protected: + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); }; @@ -83,6 +87,19 @@ NS_IMPL_STRING_ATTR(nsHTMLMetaElement, HttpEquiv, httpEquiv) NS_IMPL_STRING_ATTR(nsHTMLMetaElement, Name, name) NS_IMPL_STRING_ATTR(nsHTMLMetaElement, Scheme, scheme) +void +nsHTMLMetaElement::GetItemValueText(nsAString& aValue) +{ + GetContent(aValue); +} + +void +nsHTMLMetaElement::SetItemValueText(const nsAString& aValue) +{ + SetContent(aValue); +} + + nsresult nsHTMLMetaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, diff --git a/content/html/content/src/nsHTMLObjectElement.cpp b/content/html/content/src/nsHTMLObjectElement.cpp index 6d6611827b7ded5dca367a284195d73b2f1b8148..6559d1b24317a4bde09184d55a40f357de1d920c 100644 --- a/content/html/content/src/nsHTMLObjectElement.cpp +++ b/content/html/content/src/nsHTMLObjectElement.cpp @@ -136,6 +136,9 @@ private: * value. This is used to know the default tabindex value. */ bool IsFocusableForTabIndex(); + + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); bool mIsDoneAddingChildren; }; @@ -224,6 +227,18 @@ nsHTMLObjectElement::GetForm(nsIDOMHTMLFormElement **aForm) return nsGenericHTMLFormElement::GetForm(aForm); } +void +nsHTMLObjectElement::GetItemValueText(nsAString& aValue) +{ + GetData(aValue); +} + +void +nsHTMLObjectElement::SetItemValueText(const nsAString& aValue) +{ + SetData(aValue); +} + nsresult nsHTMLObjectElement::BindToTree(nsIDocument *aDocument, nsIContent *aParent, diff --git a/content/html/content/src/nsHTMLSharedObjectElement.cpp b/content/html/content/src/nsHTMLSharedObjectElement.cpp index d2e8e6ba50668484ff4089f936cdd7bec93cf5d3..13c500d5d1919f166da3cec8c8e63238f5416699 100644 --- a/content/html/content/src/nsHTMLSharedObjectElement.cpp +++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp @@ -153,6 +153,9 @@ private: // mIsDoneAddingChildren is only really used for <applet>. This boolean is // always true for <embed>, per the documentation in nsIContent.h. bool mIsDoneAddingChildren; + + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); }; @@ -171,6 +174,26 @@ nsHTMLSharedObjectElement::nsHTMLSharedObjectElement(already_AddRefed<nsINodeInf AddStatesSilently(NS_EVENT_STATE_LOADING); } +void +nsHTMLSharedObjectElement::GetItemValueText(nsAString& aValue) +{ + if (mNodeInfo->Equals(nsGkAtoms::applet)) { + nsGenericHTMLElement::GetItemValueText(aValue); + } else { + GetSrc(aValue); + } +} + +void +nsHTMLSharedObjectElement::SetItemValueText(const nsAString& aValue) +{ + if (mNodeInfo->Equals(nsGkAtoms::applet)) { + nsGenericHTMLElement::SetItemValueText(aValue); + } else { + SetSrc(aValue); + } +} + nsHTMLSharedObjectElement::~nsHTMLSharedObjectElement() { UnregisterFreezableElement(); diff --git a/content/html/content/src/nsHTMLSourceElement.cpp b/content/html/content/src/nsHTMLSourceElement.cpp index 3263956004df18395788601c22dd25f3778f2465..64e4a24b08aec9deb7108c6b4f6db886aab6146d 100644 --- a/content/html/content/src/nsHTMLSourceElement.cpp +++ b/content/html/content/src/nsHTMLSourceElement.cpp @@ -47,6 +47,10 @@ public: virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } + +protected: + virtual void GetItemValueText(nsAString& text); + virtual void SetItemValueText(const nsAString& text); }; @@ -84,6 +88,18 @@ NS_IMPL_URI_ATTR(nsHTMLSourceElement, Src, src) NS_IMPL_STRING_ATTR(nsHTMLSourceElement, Type, type) NS_IMPL_STRING_ATTR(nsHTMLSourceElement, Media, media) +void +nsHTMLSourceElement::GetItemValueText(nsAString& aValue) +{ + GetSrc(aValue); +} + +void +nsHTMLSourceElement::SetItemValueText(const nsAString& aValue) +{ + SetSrc(aValue); +} + nsresult nsHTMLSourceElement::BindToTree(nsIDocument *aDocument, nsIContent *aParent, diff --git a/content/html/content/src/nsHTMLVideoElement.cpp b/content/html/content/src/nsHTMLVideoElement.cpp index 956d6c6123dbd3b751252c651e9ecb6c1eff6ae7..72d03ae80e86d24ee7c635d6bdbf358cb2a16993 100644 --- a/content/html/content/src/nsHTMLVideoElement.cpp +++ b/content/html/content/src/nsHTMLVideoElement.cpp @@ -80,6 +80,20 @@ nsHTMLVideoElement::~nsHTMLVideoElement() { } +void +nsHTMLVideoElement::GetItemValueText(nsAString& aValue) +{ + // Can't call GetSrc because we don't have a JSContext + GetURIAttr(nsGkAtoms::src, nsnull, aValue); +} + +void +nsHTMLVideoElement::SetItemValueText(const nsAString& aValue) +{ + // Can't call SetSrc because we don't have a JSContext + SetAttr(kNameSpaceID_None, nsGkAtoms::src, aValue, true); +} + nsresult nsHTMLVideoElement::GetVideoSize(nsIntSize* size) { if (mMediaSize.width == -1 && mMediaSize.height == -1) { diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 3634df795190b3da16dc8b4f6b6cf02a8432bb84..e4aba11fd8bd3f503826e48b03c248267c2ecf3e 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -1765,6 +1765,84 @@ nsHTMLDocument::GetElementsByName(const nsAString& aElementName, return NS_OK; } +static bool MatchItems(nsIContent* aContent, PRInt32 aNameSpaceID, + nsIAtom* aAtom, void* aData) +{ + if (!(aContent->IsElement() && aContent->AsElement()->IsHTML())) { + return false; + } + + nsGenericHTMLElement* elem = static_cast<nsGenericHTMLElement*>(aContent); + if (!elem->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope) || + elem->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop)) { + return false; + } + + nsTArray<nsCOMPtr<nsIAtom> >* tokens = static_cast<nsTArray<nsCOMPtr<nsIAtom> >*>(aData); + if (tokens->IsEmpty()) { + return true; + } + + const nsAttrValue* attr = elem->GetParsedAttr(nsGkAtoms::itemtype); + if (!attr) + return false; + + for (PRUint32 i = 0; i < tokens->Length(); i++) { + if (!attr->Contains(tokens->ElementAt(i), eCaseMatters)) { + return false; + } + } + return true; +} + +static void DestroyTokens(void* aData) +{ + nsTArray<nsCOMPtr<nsIAtom> >* tokens = static_cast<nsTArray<nsCOMPtr<nsIAtom> >*>(aData); + delete tokens; +} + +static void* CreateTokens(nsINode* aRootNode, const nsString* types) +{ + nsTArray<nsCOMPtr<nsIAtom> >* tokens = new nsTArray<nsCOMPtr<nsIAtom> >(); + nsAString::const_iterator iter, end; + types->BeginReading(iter); + types->EndReading(end); + + // skip initial whitespace + while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) { + ++iter; + } + + // parse the tokens + while (iter != end) { + nsAString::const_iterator start(iter); + + do { + ++iter; + } while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter)); + + tokens->AppendElement(do_GetAtom(Substring(start, iter))); + + // skip whitespace + while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) { + ++iter; + } + } + return tokens; +} + +NS_IMETHODIMP +nsHTMLDocument::GetItems(const nsAString& types, nsIDOMNodeList** aReturn) +{ + nsRefPtr<nsContentList> elements = + NS_GetFuncStringContentList(this, MatchItems, DestroyTokens, + CreateTokens, types); + NS_ENSURE_TRUE(elements, NS_ERROR_OUT_OF_MEMORY); + elements.forget(aReturn); + return NS_OK; +} + + void nsHTMLDocument::AddedForm() { diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 288629e86c8b50e7caaf10ac75e57e804234cd2e..cf7a1b17fa1e67c995a271d3f7d976c47b67e3b1 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -112,7 +112,6 @@ public: UseExistingNameString, aName); } - virtual nsresult ResolveName(const nsAString& aName, nsIContent *aForm, nsISupports **aResult, diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 92a0a708213afb02f3ee29a94a592546afdcfe55..99233e6422c0d5e547d5fa37ece24853543e93e8 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -828,6 +828,11 @@ static nsDOMClassInfoData sClassInfoData[] = { DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(HTMLCollection, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(HTMLPropertiesCollection, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(PropertyNodeList, + nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) // HTML element classes NS_DEFINE_CLASSINFO_DATA(HTMLElement, nsElementSH, @@ -2731,6 +2736,16 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLCollection) DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(HTMLPropertiesCollection, nsIDOMHTMLPropertiesCollection) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLPropertiesCollection) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLCollection) + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(PropertyNodeList, nsIDOMPropertyNodeList) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMPropertyNodeList) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeList) + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(HTMLElement, nsIDOMHTMLElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLElement) DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h index 02b0814fcecf16bb36bf359a7fc7573071256cbb..ad155afaaa929cd0140c0b3e02ecb5ecaa4076ff 100644 --- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -58,6 +58,8 @@ DOMCI_CLASS(DeviceRotationRate) DOMCI_CLASS(HTMLDocument) DOMCI_CLASS(HTMLOptionsCollection) DOMCI_CLASS(HTMLCollection) +DOMCI_CLASS(HTMLPropertiesCollection) +DOMCI_CLASS(PropertyNodeList) // HTML element classes DOMCI_CLASS(HTMLElement) diff --git a/dom/interfaces/html/Makefile.in b/dom/interfaces/html/Makefile.in index 5d9e08a2c2e9694fe9b18111fcfbf65003748c43..098fa2ed14100d309bcef483ced79f30c0c216c4 100644 --- a/dom/interfaces/html/Makefile.in +++ b/dom/interfaces/html/Makefile.in @@ -61,6 +61,8 @@ SDK_XPIDLSRCS = \ nsIDOMHTMLParagraphElement.idl \ nsIDOMHTMLParamElement.idl \ nsIDOMHTMLPreElement.idl \ + nsIDOMHTMLPropertiesCollection.idl \ + nsIDOMPropertyNodeList.idl \ nsIDOMHTMLProgressElement.idl \ nsIDOMHTMLQuoteElement.idl \ nsIDOMHTMLScriptElement.idl \ diff --git a/dom/interfaces/html/nsIDOMHTMLDocument.idl b/dom/interfaces/html/nsIDOMHTMLDocument.idl index 36255bf89cdb385d58ad531e11bbf9a4914c1bca..406c74b7c455f09b34e6f0ea786095c7be560123 100644 --- a/dom/interfaces/html/nsIDOMHTMLDocument.idl +++ b/dom/interfaces/html/nsIDOMHTMLDocument.idl @@ -13,7 +13,7 @@ */ interface nsISelection; -[scriptable, uuid(1B93973F-28CC-4F33-8E7B-B89C63AA9200)] +[scriptable, uuid(ecae54c6-2ab9-4167-b0ef-61960aadbb68)] interface nsIDOMHTMLDocument : nsIDOMDocument { readonly attribute DOMString URL; @@ -34,6 +34,7 @@ interface nsIDOMHTMLDocument : nsIDOMDocument readonly attribute nsIDOMHTMLCollection forms; readonly attribute nsIDOMHTMLCollection scripts; nsIDOMNodeList getElementsByName(in DOMString elementName); + nsIDOMNodeList getItems([optional] in DOMString types); // If aContentType is not something supported by nsHTMLDocument and // the HTML content sink, trying to write to the document will diff --git a/dom/interfaces/html/nsIDOMHTMLElement.idl b/dom/interfaces/html/nsIDOMHTMLElement.idl index 91c6892114414695128d886edb3f0cff36cf94b9..9b08411ae17314fc6f084e43fd2c58396804f1b2 100644 --- a/dom/interfaces/html/nsIDOMHTMLElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLElement.idl @@ -4,9 +4,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsIDOMElement.idl" +#include "nsIVariant.idl" interface nsIDOMDOMStringMap; interface nsIDOMHTMLMenuElement; +interface nsIDOMHTMLPropertiesCollection; /** * The nsIDOMHTMLElement interface is the primary [X]HTML element @@ -19,7 +21,7 @@ interface nsIDOMHTMLMenuElement; * with changes from the work-in-progress WHATWG HTML specification: * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(5C8B21BC-EF6E-4599-A26F-FACC05B4ADBE)] +[scriptable, uuid(9a677a5b-e6f7-4e2e-9ef9-22c2ac9967b3)] interface nsIDOMHTMLElement : nsIDOMElement { // metadata attributes @@ -30,6 +32,16 @@ interface nsIDOMHTMLElement : nsIDOMElement attribute DOMString className; readonly attribute nsIDOMDOMStringMap dataset; + attribute boolean itemScope; + attribute nsIVariant itemType; + attribute DOMString itemId; + readonly attribute nsIDOMHTMLPropertiesCollection properties; + // The following attributes are really nsDOMSettableTokenList, which has + // PutForwards, so we express them as nsIVariants to deal with this. + attribute nsIVariant itemValue; + attribute nsIVariant itemProp; + attribute nsIVariant itemRef; + // user interaction /** * Indicates that the element is not yet, or is no longer, relevant. diff --git a/dom/interfaces/html/nsIDOMHTMLPropertiesCollection.idl b/dom/interfaces/html/nsIDOMHTMLPropertiesCollection.idl new file mode 100644 index 0000000000000000000000000000000000000000..0e949b3db0568049cc0bc8455c1114c1dbcda1cd --- /dev/null +++ b/dom/interfaces/html/nsIDOMHTMLPropertiesCollection.idl @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsIDOMHTMLElement.idl" +#include "nsIDOMPropertyNodeList.idl" +#include "nsIDOMDOMStringList.idl" + +// This interface should extend nsIDOMHTMLCollection, which will be fixed when +// it is converted to webidl. +[scriptable, uuid(da1101db-d1d7-465d-9fd6-49ec9960cb20)] +interface nsIDOMHTMLPropertiesCollection : nsISupports +{ + readonly attribute unsigned long length; + readonly attribute nsIDOMDOMStringList names; + + [getter,forward(getNodeAt)] nsIDOMNode item(in unsigned long index); + nsIDOMPropertyNodeList namedItem(in DOMString name); + + /** + * Get the node at the index. Returns null if the index is out of bounds. + */ + [noscript,notxpcom,nostdcall] nsIContent getNodeAt(in unsigned long index); + + /** + * Get the node for the name. Returns null if no node exists for the name. + */ + [noscript,notxpcom,nostdcall] nsISupports getNamedItem(in DOMString name, + out nsWrapperCachePtr cache); +}; diff --git a/dom/interfaces/html/nsIDOMPropertyNodeList.idl b/dom/interfaces/html/nsIDOMPropertyNodeList.idl new file mode 100644 index 0000000000000000000000000000000000000000..2b69cc1f3b0602c7a87de94c4b9823f3983b0afd --- /dev/null +++ b/dom/interfaces/html/nsIDOMPropertyNodeList.idl @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsIVariant.idl" + +interface nsIDOMNode; +interface nsIContent; + +[scriptable, uuid(255cc828-49e8-4fb0-8e36-875e6e072da3)] +interface nsIDOMPropertyNodeList : nsISupports { + [getter,forward(getNodeAt)] nsIDOMNode item(in unsigned long index); + readonly attribute unsigned long length; + + /** + * Get the node at the index. Returns null if the index is out of bounds + */ + [noscript,notxpcom,nostdcall] nsIContent getNodeAt(in unsigned long index); + + nsIVariant getValues(); +}; diff --git a/js/xpconnect/src/codegen.py b/js/xpconnect/src/codegen.py index 3a610491c5a9f570e9e9a7cf7b0daa174ca297fe..00b13b7bc3ca572485587ca0b63a28aced5ea77e 100644 --- a/js/xpconnect/src/codegen.py +++ b/js/xpconnect/src/codegen.py @@ -365,7 +365,8 @@ def writeResultConv(f, type, interfaceResultTemplate, jsvalPtr, jsvalRef): template = resultConvTemplates.get(typeName) elif isInterfaceType(type): if isVariantType(type): - template = " return xpc_qsVariantToJsval(lccx, result, ${jsvalPtr});\n" + template = (" XPCLazyCallContext lccx(JS_CALLER, cx, obj);\n" + " return xpc_qsVariantToJsval(lccx, result, ${jsvalPtr});\n") else: template = (" if (!result) {\n" " *${jsvalPtr} = JSVAL_NULL;\n" diff --git a/js/xpconnect/src/dom_quickstubs.qsconf b/js/xpconnect/src/dom_quickstubs.qsconf index 83bfd35b8416ccef64cc205c988947bcbdb91d3a..4a1da7e979ca0d791c85503e7eea564fe4187ac7 100644 --- a/js/xpconnect/src/dom_quickstubs.qsconf +++ b/js/xpconnect/src/dom_quickstubs.qsconf @@ -219,7 +219,33 @@ members = [ 'nsIDOMHTMLDocument.getSelection', 'nsIDOMHTMLDocument.designMode', 'nsIDOMHTMLDocument.head', - 'nsIDOMHTMLElement.*', + # We can't quick stub nsIDOMHTMLElement.* because we don't + # generate quick stubs for nsIVariant attributes. + 'nsIDOMHTMLElement.id', + 'nsIDOMHTMLElement.title', + 'nsIDOMHTMLElement.lang', + 'nsIDOMHTMLElement.dir', + 'nsIDOMHTMLElement.className', + 'nsIDOMHTMLElement.dataset', + 'nsIDOMHTMLElement.itemScope', + 'nsIDOMHTMLElement.itemId', + 'nsIDOMHTMLElement.properties', + 'nsIDOMHTMLElement.hidden', + 'nsIDOMHTMLElement.tabIndex', + 'nsIDOMHTMLElement.accessKey', + 'nsIDOMHTMLElement.accessKeyLabel', + 'nsIDOMHTMLElement.draggable', + 'nsIDOMHTMLElement.contentEditable', + 'nsIDOMHTMLElement.isContentEditable', + 'nsIDOMHTMLElement.contextMenu', + 'nsIDOMHTMLElement.spellcheck', + 'nsIDOMHTMLElement.innerHTML', + 'nsIDOMHTMLElement.outerHTML', + 'nsIDOMHTMLElement.offsetParent', + 'nsIDOMHTMLElement.offsetTop', + 'nsIDOMHTMLElement.offsetLeft', + 'nsIDOMHTMLElement.offsetWidth', + 'nsIDOMHTMLElement.offsetHeight', 'nsIDOMHTMLFormElement.elements', 'nsIDOMHTMLFormElement.name', 'nsIDOMHTMLFormElement.submit', @@ -269,6 +295,8 @@ members = [ 'nsIDOMHTMLOptionsCollection.item', 'nsIDOMHTMLOptionsCollection.length', 'nsIDOMHTMLProgressElement.*', + 'nsIDOMHTMLPropertiesCollection.*', + 'nsIDOMPropertyNodeList.*', 'nsIDOMHTMLSelectElement.name', 'nsIDOMHTMLSelectElement.form', 'nsIDOMHTMLSelectElement.add', diff --git a/js/xpconnect/src/dombindings.conf b/js/xpconnect/src/dombindings.conf index a1b709663b3c94dce75e2e5f6c54aa0d221c3864..83a4ed6759c9fc081947950d617369dd995a02a2 100644 --- a/js/xpconnect/src/dombindings.conf +++ b/js/xpconnect/src/dombindings.conf @@ -8,6 +8,10 @@ list_classes = [ 'name': 'NodeList', 'nativeClass': 'nsINodeList' }, + { + 'name': 'PropertyNodeList', + 'nativeClass': 'mozilla::dom::PropertyNodeList' + }, { 'name': 'HTMLCollection', 'nativeClass': 'nsIHTMLCollection' @@ -15,6 +19,10 @@ list_classes = [ { 'name': 'HTMLOptionsCollection', 'nativeClass': 'nsHTMLOptionCollection' + }, + { + 'name': 'HTMLPropertiesCollection', + 'nativeClass': 'mozilla::dom::HTMLPropertiesCollection' } ] @@ -33,11 +41,14 @@ prefableClasses = { irregularFilenames = { 'nsHTMLOptionCollection': 'nsHTMLSelectElement', + 'mozilla::dom::PropertyNodeList': 'HTMLPropertiesCollection', 'nsClientRectList': 'nsClientRect', 'nsPaintRequestList': 'nsPaintRequest', 'nsDOMFileList': 'nsDOMFile', } customInheritance = { + 'nsIDOMPropertyNodeList': 'nsIDOMNodeList', 'nsIDOMHTMLOptionsCollection': 'nsIDOMHTMLCollection', + 'nsIDOMHTMLPropertiesCollection': 'nsIDOMHTMLCollection', }