Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/xslt/xpath/XPathExpression.cpp
Line
Count
Source (jump to first uncovered line)
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
#include "mozilla/Move.h"
7
#include "XPathExpression.h"
8
#include "txExpr.h"
9
#include "txExprResult.h"
10
#include "txIXPathContext.h"
11
#include "nsError.h"
12
#include "nsINode.h"
13
#include "XPathResult.h"
14
#include "txURIUtils.h"
15
#include "txXPathTreeWalker.h"
16
#include "mozilla/dom/BindingUtils.h"
17
#include "mozilla/dom/Text.h"
18
#include "mozilla/dom/XPathResultBinding.h"
19
20
namespace mozilla {
21
namespace dom {
22
23
class EvalContextImpl : public txIEvalContext
24
{
25
public:
26
    EvalContextImpl(const txXPathNode& aContextNode,
27
                    uint32_t aContextPosition, uint32_t aContextSize,
28
                    txResultRecycler* aRecycler)
29
        : mContextNode(aContextNode),
30
          mContextPosition(aContextPosition),
31
          mContextSize(aContextSize),
32
          mLastError(NS_OK),
33
          mRecycler(aRecycler)
34
0
    {
35
0
    }
36
37
    nsresult getError()
38
0
    {
39
0
        return mLastError;
40
0
    }
41
42
    TX_DECL_EVAL_CONTEXT;
43
44
private:
45
    const txXPathNode& mContextNode;
46
    uint32_t mContextPosition;
47
    uint32_t mContextSize;
48
    nsresult mLastError;
49
    RefPtr<txResultRecycler> mRecycler;
50
};
51
52
XPathExpression::XPathExpression(nsAutoPtr<Expr>&& aExpression,
53
                                 txResultRecycler* aRecycler,
54
                                 nsIDocument *aDocument)
55
    : mExpression(std::move(aExpression)),
56
      mRecycler(aRecycler),
57
      mDocument(do_GetWeakReference(aDocument)),
58
      mCheckDocument(aDocument != nullptr)
59
0
{
60
0
}
61
62
XPathExpression::~XPathExpression()
63
0
{
64
0
}
65
66
already_AddRefed<XPathResult>
67
XPathExpression::EvaluateWithContext(JSContext* aCx,
68
                                     nsINode& aContextNode,
69
                                     uint32_t aContextPosition,
70
                                     uint32_t aContextSize,
71
                                     uint16_t aType,
72
                                     JS::Handle<JSObject*> aInResult,
73
                                     ErrorResult& aRv)
74
0
{
75
0
    RefPtr<XPathResult> inResult;
76
0
    if (aInResult) {
77
0
        nsresult rv = UNWRAP_OBJECT(XPathResult, aInResult, inResult);
78
0
        if (NS_FAILED(rv) && rv != NS_ERROR_XPC_BAD_CONVERT_JS) {
79
0
            aRv.Throw(rv);
80
0
            return nullptr;
81
0
        }
82
0
    }
83
0
84
0
    return EvaluateWithContext(aContextNode, aContextPosition, aContextSize,
85
0
                               aType, inResult, aRv);
86
0
}
87
88
already_AddRefed<XPathResult>
89
XPathExpression::EvaluateWithContext(nsINode& aContextNode,
90
                                     uint32_t aContextPosition,
91
                                     uint32_t aContextSize,
92
                                     uint16_t aType,
93
                                     XPathResult* aInResult,
94
                                     ErrorResult& aRv)
95
0
{
96
0
    if (aContextPosition > aContextSize) {
97
0
        aRv.Throw(NS_ERROR_FAILURE);
98
0
        return nullptr;
99
0
    }
100
0
101
0
    if (aType > XPathResult_Binding::FIRST_ORDERED_NODE_TYPE) {
102
0
        aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
103
0
        return nullptr;
104
0
    }
105
0
106
0
    if (!nsContentUtils::LegacyIsCallerNativeCode() &&
107
0
        !nsContentUtils::CanCallerAccess(&aContextNode))
108
0
    {
109
0
        aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
110
0
        return nullptr;
111
0
    }
112
0
113
0
    if (mCheckDocument) {
114
0
        nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
115
0
        if (doc != aContextNode.OwnerDoc()) {
116
0
            aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
117
0
            return nullptr;
118
0
        }
119
0
    }
120
0
121
0
    uint16_t nodeType = aContextNode.NodeType();
122
0
123
0
    if (nodeType == nsINode::TEXT_NODE ||
124
0
        nodeType == nsINode::CDATA_SECTION_NODE) {
125
0
        Text* textNode = aContextNode.GetAsText();
126
0
        MOZ_ASSERT(textNode);
127
0
128
0
        uint32_t textLength = textNode->Length();
129
0
        if (textLength == 0) {
130
0
            aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
131
0
            return nullptr;
132
0
        }
133
0
134
0
        // XXX Need to get logical XPath text node for CDATASection
135
0
        //     and Text nodes.
136
0
    }
137
0
    else if (nodeType != nsINode::DOCUMENT_NODE &&
138
0
             nodeType != nsINode::ELEMENT_NODE &&
139
0
             nodeType != nsINode::ATTRIBUTE_NODE &&
140
0
             nodeType != nsINode::COMMENT_NODE &&
141
0
             nodeType != nsINode::PROCESSING_INSTRUCTION_NODE) {
142
0
        aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
143
0
        return nullptr;
144
0
    }
145
0
146
0
    nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(&aContextNode));
147
0
    if (!contextNode) {
148
0
      aRv.Throw(NS_ERROR_FAILURE);
149
0
      return nullptr;
150
0
    }
151
0
152
0
    EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize,
153
0
                             mRecycler);
154
0
    RefPtr<txAExprResult> exprResult;
155
0
    aRv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
156
0
    if (aRv.Failed()) {
157
0
        return nullptr;
158
0
    }
159
0
160
0
    uint16_t resultType = aType;
161
0
    if (aType == XPathResult::ANY_TYPE) {
162
0
        short exprResultType = exprResult->getResultType();
163
0
        switch (exprResultType) {
164
0
            case txAExprResult::NUMBER:
165
0
                resultType = XPathResult::NUMBER_TYPE;
166
0
                break;
167
0
            case txAExprResult::STRING:
168
0
                resultType = XPathResult::STRING_TYPE;
169
0
                break;
170
0
            case txAExprResult::BOOLEAN:
171
0
                resultType = XPathResult::BOOLEAN_TYPE;
172
0
                break;
173
0
            case txAExprResult::NODESET:
174
0
                resultType = XPathResult::UNORDERED_NODE_ITERATOR_TYPE;
175
0
                break;
176
0
            case txAExprResult::RESULT_TREE_FRAGMENT:
177
0
                aRv.Throw(NS_ERROR_FAILURE);
178
0
                return nullptr;
179
0
        }
180
0
    }
181
0
182
0
    RefPtr<XPathResult> xpathResult = aInResult;
183
0
    if (!xpathResult) {
184
0
        xpathResult = new XPathResult(&aContextNode);
185
0
    }
186
0
187
0
    aRv = xpathResult->SetExprResult(exprResult, resultType, &aContextNode);
188
0
189
0
    return xpathResult.forget();
190
0
}
191
192
/*
193
 * Implementation of the txIEvalContext private to XPathExpression
194
 * EvalContextImpl bases on only one context node and no variables
195
 */
196
197
nsresult
198
EvalContextImpl::getVariable(int32_t aNamespace,
199
                             nsAtom* aLName,
200
                             txAExprResult*& aResult)
201
0
{
202
0
    aResult = 0;
203
0
    return NS_ERROR_INVALID_ARG;
204
0
}
205
206
nsresult
207
EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode, bool& aAllowed)
208
0
{
209
0
    aAllowed = false;
210
0
211
0
    return NS_OK;
212
0
}
213
214
void*
215
EvalContextImpl::getPrivateContext()
216
0
{
217
0
    // we don't have a private context here.
218
0
    return nullptr;
219
0
}
220
221
txResultRecycler*
222
EvalContextImpl::recycler()
223
0
{
224
0
    return mRecycler;
225
0
}
226
227
void
228
EvalContextImpl::receiveError(const nsAString& aMsg, nsresult aRes)
229
0
{
230
0
    mLastError = aRes;
231
0
    // forward aMsg to console service?
232
0
}
233
234
const txXPathNode&
235
EvalContextImpl::getContextNode()
236
0
{
237
0
    return mContextNode;
238
0
}
239
240
uint32_t
241
EvalContextImpl::size()
242
0
{
243
0
    return mContextSize;
244
0
}
245
246
uint32_t
247
EvalContextImpl::position()
248
0
{
249
0
    return mContextPosition;
250
0
}
251
252
} // namespace dom
253
} // namespace mozilla