1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef mozilla_dom_XPathResult_h
7 #define mozilla_dom_XPathResult_h
8 
9 #include "nsStubMutationObserver.h"
10 #include "nsAutoPtr.h"
11 #include "nsCOMPtr.h"
12 #include "nsCOMArray.h"
13 #include "nsWeakPtr.h"
14 #include "nsCycleCollectionParticipant.h"
15 #include "mozilla/Attributes.h"
16 #include "mozilla/ErrorResult.h"
17 #include "nsString.h"
18 #include "nsWrapperCache.h"
19 #include "nsINode.h"
20 
21 class nsIDocument;
22 class txAExprResult;
23 
24 // {662f2c9a-c7cd-4cab-9349-e733df5a838c}
25 #define NS_IXPATHRESULT_IID \
26 { 0x662f2c9a, 0xc7cd, 0x4cab, {0x93, 0x49, 0xe7, 0x33, 0xdf, 0x5a, 0x83, 0x8c }}
27 
28 class nsIXPathResult : public nsISupports
29 {
30 public:
31     NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXPATHRESULT_IID)
32     virtual nsresult SetExprResult(txAExprResult *aExprResult,
33                                    uint16_t aResultType,
34                                    nsINode* aContextNode) = 0;
35     virtual nsresult GetExprResult(txAExprResult **aExprResult) = 0;
36     virtual nsresult Clone(nsIXPathResult **aResult) = 0;
37 };
38 
NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPathResult,NS_IXPATHRESULT_IID)39 NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPathResult, NS_IXPATHRESULT_IID)
40 
41 namespace mozilla {
42 namespace dom {
43 
44 /**
45  * A class for evaluating an XPath expression string
46  */
47 class XPathResult final : public nsIXPathResult,
48                           public nsStubMutationObserver,
49                           public nsWrapperCache
50 {
51     ~XPathResult();
52 
53 public:
54     explicit XPathResult(nsINode* aParent);
55     XPathResult(const XPathResult &aResult);
56 
57     enum {
58         ANY_TYPE = 0U,
59         NUMBER_TYPE = 1U,
60         STRING_TYPE = 2U,
61         BOOLEAN_TYPE = 3U,
62         UNORDERED_NODE_ITERATOR_TYPE = 4U,
63         ORDERED_NODE_ITERATOR_TYPE = 5U,
64         UNORDERED_NODE_SNAPSHOT_TYPE = 6U,
65         ORDERED_NODE_SNAPSHOT_TYPE = 7U,
66         ANY_UNORDERED_NODE_TYPE = 8U,
67         FIRST_ORDERED_NODE_TYPE = 9U
68     };
69 
70     // nsISupports interface
71     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
72     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(XPathResult,
73                                                            nsIXPathResult)
74 
75     static XPathResult* FromSupports(nsISupports* aSupports)
76     {
77         return static_cast<XPathResult*>(static_cast<nsIXPathResult*>(aSupports));
78     }
79 
80     virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
81     nsINode* GetParentObject() const
82     {
83         return mParent;
84     }
85     uint16_t ResultType() const
86     {
87         return mResultType;
88     }
89     double GetNumberValue(ErrorResult& aRv) const
90     {
91         if (mResultType != NUMBER_TYPE) {
92             aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
93             return 0;
94         }
95 
96         return mNumberResult;
97     }
98     void GetStringValue(nsAString &aStringValue, ErrorResult& aRv) const
99     {
100         if (mResultType != STRING_TYPE) {
101             aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
102             return;
103         }
104 
105         aStringValue = mStringResult;
106     }
107     bool GetBooleanValue(ErrorResult& aRv) const
108     {
109         if (mResultType != BOOLEAN_TYPE) {
110             aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
111             return false;
112         }
113 
114         return mBooleanResult;
115     }
116     nsINode* GetSingleNodeValue(ErrorResult& aRv) const
117     {
118         if (!isNode()) {
119             aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
120             return nullptr;
121        }
122 
123         return mResultNodes.SafeObjectAt(0);
124     }
125     bool InvalidIteratorState() const
126     {
127         return isIterator() && mInvalidIteratorState;
128     }
129     uint32_t GetSnapshotLength(ErrorResult& aRv) const
130     {
131         if (!isSnapshot()) {
132             aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
133             return 0;
134         }
135 
136         return (uint32_t)mResultNodes.Count();
137     }
138     nsINode* IterateNext(ErrorResult& aRv);
139     nsINode* SnapshotItem(uint32_t aIndex, ErrorResult& aRv) const
140     {
141         if (!isSnapshot()) {
142             aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
143             return nullptr;
144         }
145 
146         return mResultNodes.SafeObjectAt(aIndex);
147     }
148 
149     // nsIMutationObserver interface
150     NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
151     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
152     NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
153     NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
154     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
155     NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
156 
157     nsresult SetExprResult(txAExprResult *aExprResult, uint16_t aResultType,
158                            nsINode* aContextNode) override;
159     nsresult GetExprResult(txAExprResult **aExprResult) override;
160     nsresult Clone(nsIXPathResult **aResult) override;
161     void RemoveObserver();
162 private:
163     static bool isSnapshot(uint16_t aResultType)
164     {
165         return aResultType == UNORDERED_NODE_SNAPSHOT_TYPE ||
166                aResultType == ORDERED_NODE_SNAPSHOT_TYPE;
167     }
168     static bool isIterator(uint16_t aResultType)
169     {
170         return aResultType == UNORDERED_NODE_ITERATOR_TYPE ||
171                aResultType == ORDERED_NODE_ITERATOR_TYPE;
172     }
173     static bool isNode(uint16_t aResultType)
174     {
175         return aResultType == FIRST_ORDERED_NODE_TYPE ||
176                aResultType == ANY_UNORDERED_NODE_TYPE;
177     }
178     bool isSnapshot() const
179     {
180         return isSnapshot(mResultType);
181     }
182     bool isIterator() const
183     {
184         return isIterator(mResultType);
185     }
186     bool isNode() const
187     {
188         return isNode(mResultType);
189     }
190 
191     void Invalidate(const nsIContent* aChangeRoot);
192 
193     nsCOMPtr<nsINode> mParent;
194     RefPtr<txAExprResult> mResult;
195     nsCOMArray<nsINode> mResultNodes;
196     nsCOMPtr<nsIDocument> mDocument;
197     nsWeakPtr mContextNode;
198     uint32_t mCurrentPos;
199     uint16_t mResultType;
200     bool mInvalidIteratorState;
201     bool mBooleanResult;
202     double mNumberResult;
203     nsString mStringResult;
204 };
205 
206 } // namespace dom
207 } // namespace mozilla
208 
209 #endif /* mozilla_dom_XPathResult_h */
210