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/. */
6 #include "mozilla/Move.h"
7 #include "XPathExpression.h"
9 #include "txExprResult.h"
10 #include "txIXPathContext.h"
12 #include "nsIDOMCharacterData.h"
13 #include "nsDOMClassInfoID.h"
14 #include "nsIDOMDocument.h"
15 #include "XPathResult.h"
16 #include "txURIUtils.h"
17 #include "txXPathTreeWalker.h"
18 #include "mozilla/dom/BindingUtils.h"
19 #include "mozilla/dom/XPathResultBinding.h"
26 class EvalContextImpl
: public txIEvalContext
29 EvalContextImpl(const txXPathNode
& aContextNode
,
30 uint32_t aContextPosition
, uint32_t aContextSize
,
31 txResultRecycler
* aRecycler
)
32 : mContextNode(aContextNode
),
33 mContextPosition(aContextPosition
),
34 mContextSize(aContextSize
),
48 const txXPathNode
& mContextNode
;
49 uint32_t mContextPosition
;
50 uint32_t mContextSize
;
52 nsRefPtr
<txResultRecycler
> mRecycler
;
55 XPathExpression::XPathExpression(nsAutoPtr
<Expr
>&& aExpression
,
56 txResultRecycler
* aRecycler
,
57 nsIDocument
*aDocument
)
58 : mExpression(Move(aExpression
)),
60 mDocument(do_GetWeakReference(aDocument
)),
61 mCheckDocument(aDocument
!= nullptr)
65 XPathExpression::~XPathExpression()
69 already_AddRefed
<XPathResult
>
70 XPathExpression::EvaluateWithContext(JSContext
* aCx
,
71 nsINode
& aContextNode
,
72 uint32_t aContextPosition
,
73 uint32_t aContextSize
,
75 JS::Handle
<JSObject
*> aInResult
,
78 XPathResult
* inResult
= nullptr;
80 nsresult rv
= UNWRAP_OBJECT(XPathResult
, aInResult
, inResult
);
81 if (NS_FAILED(rv
) && rv
!= NS_ERROR_XPC_BAD_CONVERT_JS
) {
87 return EvaluateWithContext(aContextNode
, aContextPosition
, aContextSize
,
88 aType
, inResult
, aRv
);
91 already_AddRefed
<XPathResult
>
92 XPathExpression::EvaluateWithContext(nsINode
& aContextNode
,
93 uint32_t aContextPosition
,
94 uint32_t aContextSize
,
96 XPathResult
* aInResult
,
99 if (aContextPosition
> aContextSize
) {
100 aRv
.Throw(NS_ERROR_FAILURE
);
104 if (!nsContentUtils::CanCallerAccess(&aContextNode
)) {
105 aRv
.Throw(NS_ERROR_DOM_SECURITY_ERR
);
109 if (mCheckDocument
) {
110 nsCOMPtr
<nsIDocument
> doc
= do_QueryReferent(mDocument
);
111 if (doc
!= aContextNode
.OwnerDoc()) {
112 aRv
.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR
);
117 uint16_t nodeType
= aContextNode
.NodeType();
119 if (nodeType
== nsIDOMNode::TEXT_NODE
||
120 nodeType
== nsIDOMNode::CDATA_SECTION_NODE
) {
121 nsCOMPtr
<nsIDOMCharacterData
> textNode
=
122 do_QueryInterface(&aContextNode
);
124 aRv
.Throw(NS_ERROR_FAILURE
);
129 textNode
->GetLength(&textLength
);
130 if (textLength
== 0) {
131 aRv
.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR
);
135 // XXX Need to get logical XPath text node for CDATASection
138 else if (nodeType
!= nsIDOMNode::DOCUMENT_NODE
&&
139 nodeType
!= nsIDOMNode::ELEMENT_NODE
&&
140 nodeType
!= nsIDOMNode::ATTRIBUTE_NODE
&&
141 nodeType
!= nsIDOMNode::COMMENT_NODE
&&
142 nodeType
!= nsIDOMNode::PROCESSING_INSTRUCTION_NODE
) {
143 aRv
.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR
);
147 nsAutoPtr
<txXPathNode
> contextNode(txXPathNativeNode::createXPathNode(&aContextNode
));
148 EvalContextImpl
eContext(*contextNode
, aContextPosition
, aContextSize
,
150 nsRefPtr
<txAExprResult
> exprResult
;
151 aRv
= mExpression
->evaluate(&eContext
, getter_AddRefs(exprResult
));
156 uint16_t resultType
= aType
;
157 if (aType
== XPathResult::ANY_TYPE
) {
158 short exprResultType
= exprResult
->getResultType();
159 switch (exprResultType
) {
160 case txAExprResult::NUMBER
:
161 resultType
= XPathResult::NUMBER_TYPE
;
163 case txAExprResult::STRING
:
164 resultType
= XPathResult::STRING_TYPE
;
166 case txAExprResult::BOOLEAN
:
167 resultType
= XPathResult::BOOLEAN_TYPE
;
169 case txAExprResult::NODESET
:
170 resultType
= XPathResult::UNORDERED_NODE_ITERATOR_TYPE
;
172 case txAExprResult::RESULT_TREE_FRAGMENT
:
173 aRv
.Throw(NS_ERROR_FAILURE
);
178 nsRefPtr
<XPathResult
> xpathResult
= aInResult
;
180 xpathResult
= new XPathResult(&aContextNode
);
183 aRv
= xpathResult
->SetExprResult(exprResult
, resultType
, &aContextNode
);
185 return xpathResult
.forget();
189 * Implementation of the txIEvalContext private to XPathExpression
190 * EvalContextImpl bases on only one context node and no variables
194 EvalContextImpl::getVariable(int32_t aNamespace
,
196 txAExprResult
*& aResult
)
199 return NS_ERROR_INVALID_ARG
;
203 EvalContextImpl::isStripSpaceAllowed(const txXPathNode
& aNode
)
209 EvalContextImpl::getPrivateContext()
211 // we don't have a private context here.
216 EvalContextImpl::recycler()
222 EvalContextImpl::receiveError(const nsAString
& aMsg
, nsresult aRes
)
225 // forward aMsg to console service?
229 EvalContextImpl::getContextNode()
235 EvalContextImpl::size()
241 EvalContextImpl::position()
243 return mContextPosition
;
247 } // namespace mozilla