1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_dom_HTMLFormControlsCollection_h
8 #define mozilla_dom_HTMLFormControlsCollection_h
9 
10 #include "nsIHTMLCollection.h"
11 #include "nsInterfaceHashtable.h"
12 #include "nsTArray.h"
13 #include "nsWrapperCache.h"
14 
15 class nsGenericHTMLFormElement;
16 class nsIContent;
17 class nsIFormControl;
18 template <class T>
19 class RefPtr;
20 
21 namespace mozilla::dom {
22 class Element;
23 class HTMLFormElement;
24 class HTMLImageElement;
25 class OwningRadioNodeListOrElement;
26 template <typename>
27 struct Nullable;
28 
29 class HTMLFormControlsCollection final : public nsIHTMLCollection,
30                                          public nsWrapperCache {
31  public:
32   explicit HTMLFormControlsCollection(HTMLFormElement* aForm);
33 
34   void DropFormReference();
35 
36   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
37 
38   virtual uint32_t Length() override;
39   virtual Element* GetElementAt(uint32_t index) override;
40   virtual nsINode* GetParentObject() override;
41 
42   virtual Element* GetFirstNamedElement(const nsAString& aName,
43                                         bool& aFound) override;
44 
45   void NamedGetter(const nsAString& aName, bool& aFound,
46                    Nullable<OwningRadioNodeListOrElement>& aResult);
NamedItem(const nsAString & aName,Nullable<OwningRadioNodeListOrElement> & aResult)47   void NamedItem(const nsAString& aName,
48                  Nullable<OwningRadioNodeListOrElement>& aResult) {
49     bool dummy;
50     NamedGetter(aName, dummy, aResult);
51   }
52   virtual void GetSupportedNames(nsTArray<nsString>& aNames) override;
53 
54   nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
55                              const nsAString& aName);
56   nsresult AddImageElementToTable(HTMLImageElement* aChild,
57                                   const nsAString& aName);
58   nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
59                                   const nsAString& aName);
60   nsresult IndexOfContent(nsIContent* aContent, int32_t* aIndex);
61 
62   nsISupports* NamedItemInternal(const nsAString& aName);
63 
64   /**
65    * Create a sorted list of form control elements. This list is sorted
66    * in document order and contains the controls in the mElements and
67    * mNotInElements list. This function does not add references to the
68    * elements.
69    *
70    * @param aControls The list of sorted controls[out].
71    * @return NS_OK or NS_ERROR_OUT_OF_MEMORY.
72    */
73   nsresult GetSortedControls(
74       nsTArray<RefPtr<nsGenericHTMLFormElement>>& aControls) const;
75 
76   // nsWrapperCache
77   using nsWrapperCache::GetWrapperPreserveColor;
78   using nsWrapperCache::PreserveWrapper;
79   virtual JSObject* WrapObject(JSContext* aCx,
80                                JS::Handle<JSObject*> aGivenProto) override;
81 
82  protected:
83   virtual ~HTMLFormControlsCollection();
GetWrapperPreserveColorInternal()84   virtual JSObject* GetWrapperPreserveColorInternal() override {
85     return nsWrapperCache::GetWrapperPreserveColor();
86   }
PreserveWrapperInternal(nsISupports * aScriptObjectHolder)87   virtual void PreserveWrapperInternal(
88       nsISupports* aScriptObjectHolder) override {
89     nsWrapperCache::PreserveWrapper(aScriptObjectHolder);
90   }
91 
92  public:
93   static bool ShouldBeInElements(nsIFormControl* aFormControl);
94 
95   HTMLFormElement* mForm;  // WEAK - the form owns me
96 
97   nsTArray<nsGenericHTMLFormElement*>
98       mElements;  // Holds WEAK references - bug 36639
99 
100   // This array holds on to all form controls that are not contained
101   // in mElements (form.elements in JS, see ShouldBeInFormControl()).
102   // This is needed to properly clean up the bi-directional references
103   // (both weak and strong) between the form and its form controls.
104 
105   nsTArray<nsGenericHTMLFormElement*> mNotInElements;  // Holds WEAK references
106 
107   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(HTMLFormControlsCollection)
108 
109  protected:
110   // Drop all our references to the form elements
111   void Clear();
112 
113   // A map from an ID or NAME attribute to the form control(s), this
114   // hash holds strong references either to the named form control, or
115   // to a list of named form controls, in the case where this hash
116   // holds on to a list of named form controls the list has weak
117   // references to the form control.
118 
119   nsInterfaceHashtable<nsStringHashKey, nsISupports> mNameLookupTable;
120 };
121 
122 }  // namespace mozilla::dom
123 
124 #endif  // mozilla_dom_HTMLFormControlsCollection_h
125