1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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/ArrayUtils.h"
7 #include "mozilla/EnumeratedArray.h"
8 #include "mozilla/EnumeratedRange.h"
9 #include "mozilla/FloatingPoint.h"
10 #include "mozilla/MacroArgs.h"
11 #include "mozilla/MacroForEach.h"
14 #include "nsGkAtoms.h"
15 #include "txExecutionState.h"
17 #include "txIXPathContext.h"
18 #include "txIEXSLTFunctions.h"
19 #include "txNodeSet.h"
20 #include "txOutputFormat.h"
21 #include "txRtfHandler.h"
22 #include "txXPathTreeWalker.h"
23 #include "nsImportModule.h"
24 #include "nsPrintfCString.h"
25 #include "nsComponentManagerUtils.h"
26 #include "nsContentCreatorFunctions.h"
27 #include "nsIContent.h"
28 #include "txMozillaXMLOutput.h"
29 #include "nsTextNode.h"
30 #include "mozilla/dom/DocumentFragmentBinding.h"
32 #include "xpcprivate.h"
34 using namespace mozilla
;
35 using namespace mozilla::dom
;
37 class txStylesheetCompilerState
;
39 // ------------------------------------------------------------------
41 // ------------------------------------------------------------------
43 static Document
* getSourceDocument(txIEvalContext
* aContext
) {
44 txExecutionState
* es
=
45 static_cast<txExecutionState
*>(aContext
->getPrivateContext());
47 NS_ERROR("Need txExecutionState!");
52 const txXPathNode
& document
= es
->getSourceDocument();
53 return txXPathNativeNode::getDocument(document
);
56 static nsresult
convertRtfToNode(txIEvalContext
* aContext
,
57 txResultTreeFragment
* aRtf
) {
58 Document
* doc
= getSourceDocument(aContext
);
60 return NS_ERROR_UNEXPECTED
;
63 RefPtr
<DocumentFragment
> domFragment
=
64 new (doc
->NodeInfoManager()) DocumentFragment(doc
->NodeInfoManager());
66 txOutputFormat format
;
67 txMozillaXMLOutput
mozHandler(&format
, domFragment
, true);
69 nsresult rv
= aRtf
->flushToHandler(&mozHandler
);
70 NS_ENSURE_SUCCESS(rv
, rv
);
72 rv
= mozHandler
.closePrevious(true);
73 NS_ENSURE_SUCCESS(rv
, rv
);
75 // The txResultTreeFragment will own this.
76 const txXPathNode
* node
=
77 txXPathNativeNode::createXPathNode(domFragment
, true);
78 NS_ENSURE_TRUE(node
, NS_ERROR_OUT_OF_MEMORY
);
85 static nsresult
createTextNode(txIEvalContext
* aContext
, nsString
& aValue
,
86 txXPathNode
** aResult
) {
87 Document
* doc
= getSourceDocument(aContext
);
89 return NS_ERROR_UNEXPECTED
;
92 RefPtr
<nsTextNode
> text
=
93 new (doc
->NodeInfoManager()) nsTextNode(doc
->NodeInfoManager());
95 nsresult rv
= text
->SetText(aValue
, false);
96 NS_ENSURE_SUCCESS(rv
, rv
);
98 *aResult
= txXPathNativeNode::createXPathNode(text
, true);
99 NS_ENSURE_TRUE(*aResult
, NS_ERROR_OUT_OF_MEMORY
);
104 static nsresult
createAndAddToResult(nsAtom
* aName
, const nsAString
& aValue
,
105 txNodeSet
* aResultSet
,
106 DocumentFragment
* aResultHolder
) {
107 Document
* doc
= aResultHolder
->OwnerDoc();
108 nsCOMPtr
<Element
> elem
=
109 doc
->CreateElem(nsDependentAtomString(aName
), nullptr, kNameSpaceID_None
);
110 NS_ENSURE_TRUE(elem
, NS_ERROR_NULL_POINTER
);
112 RefPtr
<nsTextNode
> text
=
113 new (doc
->NodeInfoManager()) nsTextNode(doc
->NodeInfoManager());
115 nsresult rv
= text
->SetText(aValue
, false);
116 NS_ENSURE_SUCCESS(rv
, rv
);
119 elem
->AppendChildTo(text
, false, error
);
120 if (error
.Failed()) {
121 return error
.StealNSResult();
124 aResultHolder
->AppendChildTo(elem
, false, error
);
125 if (error
.Failed()) {
126 return error
.StealNSResult();
129 UniquePtr
<txXPathNode
> xpathNode(
130 txXPathNativeNode::createXPathNode(elem
, true));
131 NS_ENSURE_TRUE(xpathNode
, NS_ERROR_OUT_OF_MEMORY
);
133 aResultSet
->append(*xpathNode
);
138 // Need to update this array if types are added to the ResultType enum in
140 static const char* const sTypes
[] = {"node-set", "boolean", "number", "string",
143 // ------------------------------------------------------------------
144 // Function implementations
145 // ------------------------------------------------------------------
147 enum class txEXSLTType
{
148 // http://exslt.org/common
152 // http://exslt.org/dates-and-times
155 // http://exslt.org/math
161 // http://exslt.org/regular-expressions
166 // http://exslt.org/sets
167 DIFFERENCE_
, // not DIFFERENCE to avoid a conflict with a winuser.h macro
174 // http://exslt.org/strings
182 struct txEXSLTFunctionDescriptor
{
185 Expr::ResultType mReturnType
;
187 bool (*mCreator
)(txEXSLTType
, FunctionCall
**);
188 int32_t mNamespaceID
;
191 static EnumeratedArray
<txEXSLTType
, txEXSLTFunctionDescriptor
,
192 size_t(txEXSLTType::_LIMIT
)>
195 class txEXSLTFunctionCall
: public FunctionCall
{
197 explicit txEXSLTFunctionCall(txEXSLTType aType
) : mType(aType
) {}
199 static bool Create(txEXSLTType aType
, FunctionCall
** aFunction
) {
200 *aFunction
= new txEXSLTFunctionCall(aType
);
210 class txEXSLTRegExFunctionCall
: public FunctionCall
{
212 explicit txEXSLTRegExFunctionCall(txEXSLTType aType
) : mType(aType
) {}
214 static bool Create(txEXSLTType aType
, FunctionCall
** aFunction
) {
215 *aFunction
= new txEXSLTRegExFunctionCall(aType
);
225 nsresult
txEXSLTFunctionCall::evaluate(txIEvalContext
* aContext
,
226 txAExprResult
** aResult
) {
228 if (!requireParams(descriptTable
[mType
].mMinParams
,
229 descriptTable
[mType
].mMaxParams
, aContext
)) {
230 return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT
;
235 case txEXSLTType::NODE_SET
: {
236 RefPtr
<txAExprResult
> exprResult
;
237 rv
= mParams
[0]->evaluate(aContext
, getter_AddRefs(exprResult
));
238 NS_ENSURE_SUCCESS(rv
, rv
);
240 if (exprResult
->getResultType() == txAExprResult::NODESET
) {
241 exprResult
.forget(aResult
);
243 RefPtr
<txNodeSet
> resultSet
;
244 rv
= aContext
->recycler()->getNodeSet(getter_AddRefs(resultSet
));
245 NS_ENSURE_SUCCESS(rv
, rv
);
247 if (exprResult
->getResultType() ==
248 txAExprResult::RESULT_TREE_FRAGMENT
) {
249 txResultTreeFragment
* rtf
=
250 static_cast<txResultTreeFragment
*>(exprResult
.get());
252 const txXPathNode
* node
= rtf
->getNode();
254 rv
= convertRtfToNode(aContext
, rtf
);
255 NS_ENSURE_SUCCESS(rv
, rv
);
257 node
= rtf
->getNode();
260 resultSet
->append(*node
);
263 exprResult
->stringValue(value
);
265 UniquePtr
<txXPathNode
> node
;
266 rv
= createTextNode(aContext
, value
, getter_Transfers(node
));
267 NS_ENSURE_SUCCESS(rv
, rv
);
269 resultSet
->append(*node
);
272 NS_ADDREF(*aResult
= resultSet
);
277 case txEXSLTType::OBJECT_TYPE
: {
278 RefPtr
<txAExprResult
> exprResult
;
279 nsresult rv
= mParams
[0]->evaluate(aContext
, getter_AddRefs(exprResult
));
280 NS_ENSURE_SUCCESS(rv
, rv
);
282 RefPtr
<StringResult
> strRes
;
283 rv
= aContext
->recycler()->getStringResult(getter_AddRefs(strRes
));
284 NS_ENSURE_SUCCESS(rv
, rv
);
286 AppendASCIItoUTF16(MakeStringSpan(sTypes
[exprResult
->getResultType()]),
289 NS_ADDREF(*aResult
= strRes
);
293 case txEXSLTType::DIFFERENCE_
:
294 case txEXSLTType::INTERSECTION
: {
295 RefPtr
<txNodeSet
> nodes1
;
296 rv
= evaluateToNodeSet(mParams
[0], aContext
, getter_AddRefs(nodes1
));
297 NS_ENSURE_SUCCESS(rv
, rv
);
299 RefPtr
<txNodeSet
> nodes2
;
300 rv
= evaluateToNodeSet(mParams
[1], aContext
, getter_AddRefs(nodes2
));
301 NS_ENSURE_SUCCESS(rv
, rv
);
303 RefPtr
<txNodeSet
> resultSet
;
304 rv
= aContext
->recycler()->getNodeSet(getter_AddRefs(resultSet
));
305 NS_ENSURE_SUCCESS(rv
, rv
);
307 bool insertOnFound
= mType
== txEXSLTType::INTERSECTION
;
309 int32_t searchPos
= 0;
310 int32_t i
, len
= nodes1
->size();
311 for (i
= 0; i
< len
; ++i
) {
312 const txXPathNode
& node
= nodes1
->get(i
);
313 int32_t foundPos
= nodes2
->indexOf(node
, searchPos
);
315 searchPos
= foundPos
+ 1;
318 if ((foundPos
>= 0) == insertOnFound
) {
319 rv
= resultSet
->append(node
);
320 NS_ENSURE_SUCCESS(rv
, rv
);
324 NS_ADDREF(*aResult
= resultSet
);
328 case txEXSLTType::DISTINCT
: {
329 RefPtr
<txNodeSet
> nodes
;
330 rv
= evaluateToNodeSet(mParams
[0], aContext
, getter_AddRefs(nodes
));
331 NS_ENSURE_SUCCESS(rv
, rv
);
333 RefPtr
<txNodeSet
> resultSet
;
334 rv
= aContext
->recycler()->getNodeSet(getter_AddRefs(resultSet
));
335 NS_ENSURE_SUCCESS(rv
, rv
);
337 nsTHashSet
<nsString
> hash
;
339 int32_t i
, len
= nodes
->size();
340 for (i
= 0; i
< len
; ++i
) {
342 const txXPathNode
& node
= nodes
->get(i
);
343 txXPathNodeUtils::appendNodeValue(node
, str
);
344 if (hash
.EnsureInserted(str
)) {
345 rv
= resultSet
->append(node
);
346 NS_ENSURE_SUCCESS(rv
, rv
);
350 NS_ADDREF(*aResult
= resultSet
);
354 case txEXSLTType::HAS_SAME_NODE
: {
355 RefPtr
<txNodeSet
> nodes1
;
356 rv
= evaluateToNodeSet(mParams
[0], aContext
, getter_AddRefs(nodes1
));
357 NS_ENSURE_SUCCESS(rv
, rv
);
359 RefPtr
<txNodeSet
> nodes2
;
360 rv
= evaluateToNodeSet(mParams
[1], aContext
, getter_AddRefs(nodes2
));
361 NS_ENSURE_SUCCESS(rv
, rv
);
364 int32_t i
, len
= nodes1
->size();
365 for (i
= 0; i
< len
; ++i
) {
366 if (nodes2
->contains(nodes1
->get(i
))) {
372 aContext
->recycler()->getBoolResult(found
, aResult
);
376 case txEXSLTType::LEADING
:
377 case txEXSLTType::TRAILING
: {
378 RefPtr
<txNodeSet
> nodes1
;
379 rv
= evaluateToNodeSet(mParams
[0], aContext
, getter_AddRefs(nodes1
));
380 NS_ENSURE_SUCCESS(rv
, rv
);
382 RefPtr
<txNodeSet
> nodes2
;
383 rv
= evaluateToNodeSet(mParams
[1], aContext
, getter_AddRefs(nodes2
));
384 NS_ENSURE_SUCCESS(rv
, rv
);
386 if (nodes2
->isEmpty()) {
393 RefPtr
<txNodeSet
> resultSet
;
394 rv
= aContext
->recycler()->getNodeSet(getter_AddRefs(resultSet
));
395 NS_ENSURE_SUCCESS(rv
, rv
);
397 int32_t end
= nodes1
->indexOf(nodes2
->get(0));
400 if (mType
== txEXSLTType::TRAILING
) {
402 end
= nodes1
->size();
404 for (; i
< end
; ++i
) {
405 rv
= resultSet
->append(nodes1
->get(i
));
406 NS_ENSURE_SUCCESS(rv
, rv
);
410 NS_ADDREF(*aResult
= resultSet
);
414 case txEXSLTType::CONCAT
: {
415 RefPtr
<txNodeSet
> nodes
;
416 rv
= evaluateToNodeSet(mParams
[0], aContext
, getter_AddRefs(nodes
));
417 NS_ENSURE_SUCCESS(rv
, rv
);
420 int32_t i
, len
= nodes
->size();
421 for (i
= 0; i
< len
; ++i
) {
422 txXPathNodeUtils::appendNodeValue(nodes
->get(i
), str
);
425 return aContext
->recycler()->getStringResult(str
, aResult
);
427 case txEXSLTType::SPLIT
:
428 case txEXSLTType::TOKENIZE
: {
429 // Evaluate parameters
431 rv
= mParams
[0]->evaluateToString(aContext
, string
);
432 NS_ENSURE_SUCCESS(rv
, rv
);
434 nsAutoString pattern
;
435 if (mParams
.Length() == 2) {
436 rv
= mParams
[1]->evaluateToString(aContext
, pattern
);
437 NS_ENSURE_SUCCESS(rv
, rv
);
438 } else if (mType
== txEXSLTType::SPLIT
) {
441 pattern
.AssignLiteral("\t\r\n ");
444 // Set up holders for the result
445 Document
* sourceDoc
= getSourceDocument(aContext
);
446 NS_ENSURE_STATE(sourceDoc
);
448 RefPtr
<DocumentFragment
> docFrag
= new (sourceDoc
->NodeInfoManager())
449 DocumentFragment(sourceDoc
->NodeInfoManager());
451 RefPtr
<txNodeSet
> resultSet
;
452 rv
= aContext
->recycler()->getNodeSet(getter_AddRefs(resultSet
));
453 NS_ENSURE_SUCCESS(rv
, rv
);
458 if (pattern
.IsEmpty()) {
459 nsString::const_char_iterator start
= string
.BeginReading();
460 nsString::const_char_iterator end
= string
.EndReading();
461 for (; start
< end
; ++start
) {
462 rv
= createAndAddToResult(nsGkAtoms::token
,
463 Substring(start
, start
+ 1), resultSet
,
465 NS_ENSURE_SUCCESS(rv
, rv
);
468 tailIndex
= string
.Length();
469 } else if (mType
== txEXSLTType::SPLIT
) {
470 nsAString::const_iterator strStart
, strEnd
;
471 string
.BeginReading(strStart
);
472 string
.EndReading(strEnd
);
473 nsAString::const_iterator start
= strStart
, end
= strEnd
;
475 while (FindInReadable(pattern
, start
, end
)) {
476 if (start
!= strStart
) {
477 rv
= createAndAddToResult(nsGkAtoms::token
,
478 Substring(strStart
, start
), resultSet
,
480 NS_ENSURE_SUCCESS(rv
, rv
);
482 strStart
= start
= end
;
486 tailIndex
= strStart
.get() - string
.get();
488 int32_t found
, start
= 0;
489 while ((found
= string
.FindCharInSet(pattern
, start
)) != kNotFound
) {
490 if (found
!= start
) {
491 rv
= createAndAddToResult(nsGkAtoms::token
,
492 Substring(string
, start
, found
- start
),
494 NS_ENSURE_SUCCESS(rv
, rv
);
502 // Add tail if needed
503 if (tailIndex
!= (uint32_t)string
.Length()) {
504 rv
= createAndAddToResult(
505 nsGkAtoms::token
, Substring(string
, tailIndex
), resultSet
, docFrag
);
506 NS_ENSURE_SUCCESS(rv
, rv
);
509 NS_ADDREF(*aResult
= resultSet
);
513 case txEXSLTType::MAX
:
514 case txEXSLTType::MIN
: {
515 RefPtr
<txNodeSet
> nodes
;
516 rv
= evaluateToNodeSet(mParams
[0], aContext
, getter_AddRefs(nodes
));
517 NS_ENSURE_SUCCESS(rv
, rv
);
519 if (nodes
->isEmpty()) {
520 return aContext
->recycler()->getNumberResult(UnspecifiedNaN
<double>(),
524 bool findMax
= mType
== txEXSLTType::MAX
;
526 double res
= findMax
? mozilla::NegativeInfinity
<double>()
527 : mozilla::PositiveInfinity
<double>();
528 int32_t i
, len
= nodes
->size();
529 for (i
= 0; i
< len
; ++i
) {
531 txXPathNodeUtils::appendNodeValue(nodes
->get(i
), str
);
532 double val
= txDouble::toDouble(str
);
533 if (std::isnan(val
)) {
534 res
= UnspecifiedNaN
<double>();
538 if (findMax
? (val
> res
) : (val
< res
)) {
543 return aContext
->recycler()->getNumberResult(res
, aResult
);
545 case txEXSLTType::HIGHEST
:
546 case txEXSLTType::LOWEST
: {
547 RefPtr
<txNodeSet
> nodes
;
548 rv
= evaluateToNodeSet(mParams
[0], aContext
, getter_AddRefs(nodes
));
549 NS_ENSURE_SUCCESS(rv
, rv
);
551 if (nodes
->isEmpty()) {
552 NS_ADDREF(*aResult
= nodes
);
557 RefPtr
<txNodeSet
> resultSet
;
558 rv
= aContext
->recycler()->getNodeSet(getter_AddRefs(resultSet
));
559 NS_ENSURE_SUCCESS(rv
, rv
);
561 bool findMax
= mType
== txEXSLTType::HIGHEST
;
562 double res
= findMax
? mozilla::NegativeInfinity
<double>()
563 : mozilla::PositiveInfinity
<double>();
564 int32_t i
, len
= nodes
->size();
565 for (i
= 0; i
< len
; ++i
) {
567 const txXPathNode
& node
= nodes
->get(i
);
568 txXPathNodeUtils::appendNodeValue(node
, str
);
569 double val
= txDouble::toDouble(str
);
570 if (std::isnan(val
)) {
574 if (findMax
? (val
> res
) : (val
< res
)) {
580 rv
= resultSet
->append(node
);
581 NS_ENSURE_SUCCESS(rv
, rv
);
585 NS_ADDREF(*aResult
= resultSet
);
589 case txEXSLTType::DATE_TIME
: {
590 // http://exslt.org/date/functions/date-time/
592 PRExplodedTime prtime
;
593 PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters
, &prtime
);
596 (prtime
.tm_params
.tp_gmt_offset
+ prtime
.tm_params
.tp_dst_offset
) /
599 bool isneg
= offset
< 0;
600 if (isneg
) offset
= -offset
;
602 StringResult
* strRes
;
603 rv
= aContext
->recycler()->getStringResult(&strRes
);
604 NS_ENSURE_SUCCESS(rv
, rv
);
606 // format: YYYY-MM-DDTTHH:MM:SS.sss+00:00
608 nsPrintfCString("%04hd-%02" PRId32
"-%02" PRId32
"T%02" PRId32
609 ":%02" PRId32
":%02" PRId32
".%03" PRId32
610 "%c%02" PRId32
":%02" PRId32
,
611 prtime
.tm_year
, prtime
.tm_month
+ 1, prtime
.tm_mday
,
612 prtime
.tm_hour
, prtime
.tm_min
, prtime
.tm_sec
,
613 prtime
.tm_usec
/ 10000, isneg
? '-' : '+',
614 offset
/ 60, offset
% 60),
622 aContext
->receiveError(u
"Internal error"_ns
, NS_ERROR_UNEXPECTED
);
623 return NS_ERROR_UNEXPECTED
;
627 MOZ_ASSERT_UNREACHABLE("Missing return?");
628 return NS_ERROR_UNEXPECTED
;
631 Expr::ResultType
txEXSLTFunctionCall::getReturnType() {
632 return descriptTable
[mType
].mReturnType
;
635 bool txEXSLTFunctionCall::isSensitiveTo(ContextSensitivity aContext
) {
636 if (mType
== txEXSLTType::NODE_SET
|| mType
== txEXSLTType::SPLIT
||
637 mType
== txEXSLTType::TOKENIZE
) {
638 return (aContext
& PRIVATE_CONTEXT
) || argsSensitiveTo(aContext
);
640 return argsSensitiveTo(aContext
);
644 void txEXSLTFunctionCall::appendName(nsAString
& aDest
) {
645 aDest
.Append(descriptTable
[mType
].mName
->GetUTF16String());
649 nsresult
txEXSLTRegExFunctionCall::evaluate(txIEvalContext
* aContext
,
650 txAExprResult
** aResult
) {
652 if (!requireParams(descriptTable
[mType
].mMinParams
,
653 descriptTable
[mType
].mMaxParams
, aContext
)) {
654 return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT
;
658 nsresult rv
= mParams
[0]->evaluateToString(aContext
, string
);
659 NS_ENSURE_SUCCESS(rv
, rv
);
662 rv
= mParams
[1]->evaluateToString(aContext
, regex
);
663 NS_ENSURE_SUCCESS(rv
, rv
);
666 if (mParams
.Length() >= 3) {
667 rv
= mParams
[2]->evaluateToString(aContext
, flags
);
668 NS_ENSURE_SUCCESS(rv
, rv
);
671 nsCOMPtr
<txIEXSLTFunctions
> funcs
=
672 do_ImportESModule("resource://gre/modules/txEXSLTRegExFunctions.sys.mjs");
673 MOZ_ALWAYS_TRUE(funcs
);
676 case txEXSLTType::MATCH
: {
677 nsCOMPtr
<Document
> sourceDoc
= getSourceDocument(aContext
);
678 NS_ENSURE_STATE(sourceDoc
);
680 RefPtr
<DocumentFragment
> docFrag
;
681 rv
= funcs
->Match(string
, regex
, flags
, sourceDoc
,
682 getter_AddRefs(docFrag
));
683 NS_ENSURE_SUCCESS(rv
, rv
);
684 NS_ENSURE_STATE(docFrag
);
686 RefPtr
<txNodeSet
> resultSet
;
687 rv
= aContext
->recycler()->getNodeSet(getter_AddRefs(resultSet
));
688 NS_ENSURE_SUCCESS(rv
, rv
);
690 UniquePtr
<txXPathNode
> node
;
691 for (nsIContent
* result
= docFrag
->GetFirstChild(); result
;
692 result
= result
->GetNextSibling()) {
693 node
= WrapUnique(txXPathNativeNode::createXPathNode(result
, true));
694 rv
= resultSet
->add(*node
);
695 NS_ENSURE_SUCCESS(rv
, rv
);
698 resultSet
.forget(aResult
);
702 case txEXSLTType::REPLACE
: {
703 nsAutoString replace
;
704 rv
= mParams
[3]->evaluateToString(aContext
, replace
);
705 NS_ENSURE_SUCCESS(rv
, rv
);
708 rv
= funcs
->Replace(string
, regex
, flags
, replace
, result
);
709 NS_ENSURE_SUCCESS(rv
, rv
);
711 rv
= aContext
->recycler()->getStringResult(result
, aResult
);
712 NS_ENSURE_SUCCESS(rv
, rv
);
716 case txEXSLTType::TEST
: {
718 rv
= funcs
->Test(string
, regex
, flags
, &result
);
719 NS_ENSURE_SUCCESS(rv
, rv
);
721 aContext
->recycler()->getBoolResult(result
, aResult
);
726 aContext
->receiveError(u
"Internal error"_ns
, NS_ERROR_UNEXPECTED
);
727 return NS_ERROR_UNEXPECTED
;
731 MOZ_ASSERT_UNREACHABLE("Missing return?");
732 return NS_ERROR_UNEXPECTED
;
735 Expr::ResultType
txEXSLTRegExFunctionCall::getReturnType() {
736 return descriptTable
[mType
].mReturnType
;
739 bool txEXSLTRegExFunctionCall::isSensitiveTo(ContextSensitivity aContext
) {
740 if (mType
== txEXSLTType::MATCH
) {
741 return (aContext
& PRIVATE_CONTEXT
) || argsSensitiveTo(aContext
);
743 return argsSensitiveTo(aContext
);
747 void txEXSLTRegExFunctionCall::appendName(nsAString
& aDest
) {
748 aDest
.Append(descriptTable
[mType
].mName
->GetUTF16String());
752 extern nsresult
TX_ConstructEXSLTFunction(nsAtom
* aName
, int32_t aNamespaceID
,
753 txStylesheetCompilerState
* aState
,
754 FunctionCall
** aResult
) {
755 for (auto i
: MakeEnumeratedRange(txEXSLTType::_LIMIT
)) {
756 const txEXSLTFunctionDescriptor
& desc
= descriptTable
[i
];
757 if (aName
== desc
.mName
&& aNamespaceID
== desc
.mNamespaceID
) {
758 return desc
.mCreator(i
, aResult
) ? NS_OK
: NS_ERROR_FAILURE
;
762 return NS_ERROR_XPATH_UNKNOWN_FUNCTION
;
765 extern bool TX_InitEXSLTFunction() {
766 #define EXSLT_FUNCS(NS, CLASS, ...) \
768 int32_t nsid = txNamespaceManager::getNamespaceID(nsLiteralString(NS)); \
769 if (nsid == kNameSpaceID_Unknown) { \
772 MOZ_FOR_EACH(EXSLT_FUNC, (nsid, CLASS, ), (__VA_ARGS__)) \
775 #define EXSLT_FUNC(NS, CLASS, ...) \
776 descriptTable[txEXSLTType::MOZ_ARG_1 __VA_ARGS__] = { \
777 MOZ_ARGS_AFTER_1 __VA_ARGS__, CLASS::Create, NS};
779 EXSLT_FUNCS(u
"http://exslt.org/common", txEXSLTFunctionCall
,
780 (NODE_SET
, 1, 1, Expr::NODESET_RESULT
, nsGkAtoms::nodeSet
),
781 (OBJECT_TYPE
, 1, 1, Expr::STRING_RESULT
, nsGkAtoms::objectType
))
783 EXSLT_FUNCS(u
"http://exslt.org/dates-and-times", txEXSLTFunctionCall
,
784 (DATE_TIME
, 0, 0, Expr::STRING_RESULT
, nsGkAtoms::dateTime
))
786 EXSLT_FUNCS(u
"http://exslt.org/math", txEXSLTFunctionCall
,
787 (MAX
, 1, 1, Expr::NUMBER_RESULT
, nsGkAtoms::max
),
788 (MIN
, 1, 1, Expr::NUMBER_RESULT
, nsGkAtoms::min
),
789 (HIGHEST
, 1, 1, Expr::NODESET_RESULT
, nsGkAtoms::highest
),
790 (LOWEST
, 1, 1, Expr::NODESET_RESULT
, nsGkAtoms::lowest
))
792 EXSLT_FUNCS(u
"http://exslt.org/regular-expressions", txEXSLTRegExFunctionCall
,
793 (MATCH
, 2, 3, Expr::NODESET_RESULT
, nsGkAtoms::match
),
794 (REPLACE
, 4, 4, Expr::STRING_RESULT
, nsGkAtoms::replace
),
795 (TEST
, 2, 3, Expr::BOOLEAN_RESULT
, nsGkAtoms::test
))
798 u
"http://exslt.org/sets", txEXSLTFunctionCall
,
799 (DIFFERENCE_
, 2, 2, Expr::NODESET_RESULT
, nsGkAtoms::difference
),
800 (DISTINCT
, 1, 1, Expr::NODESET_RESULT
, nsGkAtoms::distinct
),
801 (HAS_SAME_NODE
, 2, 2, Expr::BOOLEAN_RESULT
, nsGkAtoms::hasSameNode
),
802 (INTERSECTION
, 2, 2, Expr::NODESET_RESULT
, nsGkAtoms::intersection
),
803 (LEADING
, 2, 2, Expr::NODESET_RESULT
, nsGkAtoms::leading
),
804 (TRAILING
, 2, 2, Expr::NODESET_RESULT
, nsGkAtoms::trailing
))
806 EXSLT_FUNCS(u
"http://exslt.org/strings", txEXSLTFunctionCall
,
807 (CONCAT
, 1, 1, Expr::STRING_RESULT
, nsGkAtoms::concat
),
808 (SPLIT
, 1, 2, Expr::STRING_RESULT
, nsGkAtoms::split
),
809 (TOKENIZE
, 1, 2, Expr::STRING_RESULT
, nsGkAtoms::tokenize
))
813 #undef EXSLT_FUNC_HELPER
814 #undef EXSLT_FUNC_HELPER2