Bug 1874684 - Part 4: Prefer const references instead of copying Instant values....
[gecko.git] / dom / xslt / xslt / txStylesheetCompileHandlers.cpp
blobddc9f6fb381ddec08fa9f986a45a3797e0923936
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 "txStylesheetCompileHandlers.h"
8 #include <utility>
10 #include "mozilla/ArrayUtils.h"
11 #include "mozilla/FloatingPoint.h"
12 #include "mozilla/UniquePtrExtensions.h"
13 #include "nsGkAtoms.h"
14 #include "nsWhitespaceTokenizer.h"
15 #include "txCore.h"
16 #include "txInstructions.h"
17 #include "txNamespaceMap.h"
18 #include "txPatternParser.h"
19 #include "txStringUtils.h"
20 #include "txStylesheet.h"
21 #include "txStylesheetCompiler.h"
22 #include "txToplevelItems.h"
23 #include "txURIUtils.h"
24 #include "txXSLTFunctions.h"
25 #include "nsStringFlags.h"
26 #include "nsStyleUtil.h"
27 #include "nsStringIterator.h"
29 using namespace mozilla;
31 txHandlerTable* gTxIgnoreHandler = 0;
32 txHandlerTable* gTxRootHandler = 0;
33 txHandlerTable* gTxEmbedHandler = 0;
34 txHandlerTable* gTxTopHandler = 0;
35 txHandlerTable* gTxTemplateHandler = 0;
36 txHandlerTable* gTxTextHandler = 0;
37 txHandlerTable* gTxApplyTemplatesHandler = 0;
38 txHandlerTable* gTxCallTemplateHandler = 0;
39 txHandlerTable* gTxVariableHandler = 0;
40 txHandlerTable* gTxForEachHandler = 0;
41 txHandlerTable* gTxTopVariableHandler = 0;
42 txHandlerTable* gTxChooseHandler = 0;
43 txHandlerTable* gTxParamHandler = 0;
44 txHandlerTable* gTxImportHandler = 0;
45 txHandlerTable* gTxAttributeSetHandler = 0;
46 txHandlerTable* gTxFallbackHandler = 0;
48 static nsresult txFnStartLRE(int32_t aNamespaceID, nsAtom* aLocalName,
49 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
50 int32_t aAttrCount,
51 txStylesheetCompilerState& aState);
52 static void txFnEndLRE(txStylesheetCompilerState& aState);
54 #define TX_RETURN_IF_WHITESPACE(_str, _state) \
55 do { \
56 if (!_state.mElementContext->mPreserveWhitespace && \
57 XMLUtils::isWhitespace(_str)) { \
58 return NS_OK; \
59 } \
60 } while (0)
62 static nsresult getStyleAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
63 int32_t aNamespace, nsAtom* aName, bool aRequired,
64 txStylesheetAttr** aAttr) {
65 int32_t i;
66 for (i = 0; i < aAttrCount; ++i) {
67 txStylesheetAttr* attr = aAttributes + i;
68 if (attr->mNamespaceID == aNamespace && attr->mLocalName == aName) {
69 attr->mLocalName = nullptr;
70 *aAttr = attr;
72 return NS_OK;
75 *aAttr = nullptr;
77 if (aRequired) {
78 // XXX ErrorReport: missing required attribute
79 return NS_ERROR_XSLT_PARSE_FAILURE;
82 return NS_OK;
85 static nsresult parseUseAttrSets(txStylesheetAttr* aAttributes,
86 int32_t aAttrCount, bool aInXSLTNS,
87 txStylesheetCompilerState& aState) {
88 txStylesheetAttr* attr = nullptr;
89 nsresult rv = getStyleAttr(aAttributes, aAttrCount,
90 aInXSLTNS ? kNameSpaceID_XSLT : kNameSpaceID_None,
91 nsGkAtoms::useAttributeSets, false, &attr);
92 if (!attr) {
93 return rv;
96 nsWhitespaceTokenizer tok(attr->mValue);
97 while (tok.hasMoreTokens()) {
98 txExpandedName name;
99 rv = name.init(tok.nextToken(), aState.mElementContext->mMappings, false);
100 NS_ENSURE_SUCCESS(rv, rv);
102 aState.addInstruction(MakeUnique<txInsertAttrSet>(name));
104 return NS_OK;
107 static nsresult parseExcludeResultPrefixes(txStylesheetAttr* aAttributes,
108 int32_t aAttrCount,
109 int32_t aNamespaceID) {
110 txStylesheetAttr* attr = nullptr;
111 nsresult rv = getStyleAttr(aAttributes, aAttrCount, aNamespaceID,
112 nsGkAtoms::excludeResultPrefixes, false, &attr);
113 if (!attr) {
114 return rv;
117 // XXX Needs to be implemented.
119 return NS_OK;
122 static nsresult getQNameAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
123 nsAtom* aName, bool aRequired,
124 txStylesheetCompilerState& aState,
125 txExpandedName& aExpName) {
126 aExpName.reset();
127 txStylesheetAttr* attr = nullptr;
128 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
129 aRequired, &attr);
130 if (!attr) {
131 return rv;
134 rv = aExpName.init(attr->mValue, aState.mElementContext->mMappings, false);
135 if (!aRequired && NS_FAILED(rv) && aState.fcp()) {
136 aExpName.reset();
137 rv = NS_OK;
140 return rv;
143 static nsresult getExprAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
144 nsAtom* aName, bool aRequired,
145 txStylesheetCompilerState& aState,
146 UniquePtr<Expr>& aExpr) {
147 aExpr = nullptr;
148 txStylesheetAttr* attr = nullptr;
149 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
150 aRequired, &attr);
151 if (!attr) {
152 return rv;
155 rv = txExprParser::createExpr(attr->mValue, &aState, getter_Transfers(aExpr));
156 if (NS_FAILED(rv) && aState.ignoreError(rv)) {
157 // use default value in fcp for not required exprs
158 if (aRequired) {
159 aExpr = MakeUnique<txErrorExpr>(
160 #ifdef TX_TO_STRING
161 attr->mValue
162 #endif
164 } else {
165 aExpr = nullptr;
167 return NS_OK;
170 return rv;
173 static nsresult getAVTAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
174 nsAtom* aName, bool aRequired,
175 txStylesheetCompilerState& aState,
176 UniquePtr<Expr>& aAVT) {
177 aAVT = nullptr;
178 txStylesheetAttr* attr = nullptr;
179 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
180 aRequired, &attr);
181 if (!attr) {
182 return rv;
185 rv = txExprParser::createAVT(attr->mValue, &aState, getter_Transfers(aAVT));
186 if (NS_FAILED(rv) && aState.fcp()) {
187 // use default value in fcp for not required exprs
188 if (aRequired) {
189 aAVT = MakeUnique<txErrorExpr>(
190 #ifdef TX_TO_STRING
191 attr->mValue
192 #endif
194 } else {
195 aAVT = nullptr;
197 return NS_OK;
200 return rv;
203 static nsresult getPatternAttr(txStylesheetAttr* aAttributes,
204 int32_t aAttrCount, nsAtom* aName,
205 bool aRequired,
206 txStylesheetCompilerState& aState,
207 UniquePtr<txPattern>& aPattern) {
208 aPattern = nullptr;
209 txStylesheetAttr* attr = nullptr;
210 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
211 aRequired, &attr);
212 if (!attr) {
213 return rv;
216 rv = txPatternParser::createPattern(attr->mValue, &aState,
217 getter_Transfers(aPattern));
218 if (NS_FAILED(rv) && (aRequired || !aState.ignoreError(rv))) {
219 // XXX ErrorReport: XSLT-Pattern parse failure
220 return rv;
223 return NS_OK;
226 static nsresult getNumberAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
227 nsAtom* aName, bool aRequired,
228 txStylesheetCompilerState& aState,
229 double& aNumber) {
230 aNumber = UnspecifiedNaN<double>();
231 txStylesheetAttr* attr = nullptr;
232 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
233 aRequired, &attr);
234 if (!attr) {
235 return rv;
238 aNumber = txDouble::toDouble(attr->mValue);
239 if (std::isnan(aNumber) && (aRequired || !aState.fcp())) {
240 // XXX ErrorReport: number parse failure
241 return NS_ERROR_XSLT_PARSE_FAILURE;
244 return NS_OK;
247 static nsresult getAtomAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
248 nsAtom* aName, bool aRequired,
249 txStylesheetCompilerState& aState, nsAtom** aAtom) {
250 *aAtom = nullptr;
251 txStylesheetAttr* attr = nullptr;
252 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
253 aRequired, &attr);
254 if (!attr) {
255 return rv;
258 *aAtom = NS_Atomize(attr->mValue).take();
259 NS_ENSURE_TRUE(*aAtom, NS_ERROR_OUT_OF_MEMORY);
261 return NS_OK;
264 static nsresult getYesNoAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
265 nsAtom* aName, bool aRequired,
266 txStylesheetCompilerState& aState,
267 txThreeState& aRes) {
268 aRes = eNotSet;
269 RefPtr<nsAtom> atom;
270 nsresult rv = getAtomAttr(aAttributes, aAttrCount, aName, aRequired, aState,
271 getter_AddRefs(atom));
272 if (!atom) {
273 return rv;
276 if (atom == nsGkAtoms::yes) {
277 aRes = eTrue;
278 } else if (atom == nsGkAtoms::no) {
279 aRes = eFalse;
280 } else if (aRequired || !aState.fcp()) {
281 // XXX ErrorReport: unknown values
282 return NS_ERROR_XSLT_PARSE_FAILURE;
285 return NS_OK;
288 static nsresult getCharAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
289 nsAtom* aName, bool aRequired,
290 txStylesheetCompilerState& aState,
291 char16_t& aChar) {
292 // Don't reset aChar since it contains the default value
293 txStylesheetAttr* attr = nullptr;
294 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
295 aRequired, &attr);
296 if (!attr) {
297 return rv;
300 if (attr->mValue.Length() == 1) {
301 aChar = attr->mValue.CharAt(0);
302 } else if (aRequired || !aState.fcp()) {
303 // XXX ErrorReport: not a character
304 return NS_ERROR_XSLT_PARSE_FAILURE;
307 return NS_OK;
310 static void pushInstruction(txStylesheetCompilerState& aState,
311 UniquePtr<txInstruction> aInstruction) {
312 aState.pushObject(aInstruction.release());
315 template <class T = txInstruction>
316 static UniquePtr<T> popInstruction(txStylesheetCompilerState& aState) {
317 return UniquePtr<T>(static_cast<T*>(aState.popObject()));
321 * Ignore and error handlers
323 static nsresult txFnTextIgnore(const nsAString& aStr,
324 txStylesheetCompilerState& aState) {
325 return NS_OK;
328 static nsresult txFnTextError(const nsAString& aStr,
329 txStylesheetCompilerState& aState) {
330 TX_RETURN_IF_WHITESPACE(aStr, aState);
332 return NS_ERROR_XSLT_PARSE_FAILURE;
335 void clearAttributes(txStylesheetAttr* aAttributes, int32_t aAttrCount) {
336 int32_t i;
337 for (i = 0; i < aAttrCount; ++i) {
338 aAttributes[i].mLocalName = nullptr;
342 static nsresult txFnStartElementIgnore(int32_t aNamespaceID, nsAtom* aLocalName,
343 nsAtom* aPrefix,
344 txStylesheetAttr* aAttributes,
345 int32_t aAttrCount,
346 txStylesheetCompilerState& aState) {
347 if (!aState.fcp()) {
348 clearAttributes(aAttributes, aAttrCount);
351 return NS_OK;
354 static void txFnEndElementIgnore(txStylesheetCompilerState& aState) {}
356 static nsresult txFnStartElementSetIgnore(int32_t aNamespaceID,
357 nsAtom* aLocalName, nsAtom* aPrefix,
358 txStylesheetAttr* aAttributes,
359 int32_t aAttrCount,
360 txStylesheetCompilerState& aState) {
361 if (!aState.fcp()) {
362 clearAttributes(aAttributes, aAttrCount);
365 aState.pushHandlerTable(gTxIgnoreHandler);
367 return NS_OK;
370 static void txFnEndElementSetIgnore(txStylesheetCompilerState& aState) {
371 aState.popHandlerTable();
374 static nsresult txFnStartElementError(int32_t aNamespaceID, nsAtom* aLocalName,
375 nsAtom* aPrefix,
376 txStylesheetAttr* aAttributes,
377 int32_t aAttrCount,
378 txStylesheetCompilerState& aState) {
379 return NS_ERROR_XSLT_PARSE_FAILURE;
382 static void txFnEndElementError(txStylesheetCompilerState& aState) {
383 MOZ_CRASH("txFnEndElementError shouldn't be called");
387 * Root handlers
389 static nsresult txFnStartStylesheet(int32_t aNamespaceID, nsAtom* aLocalName,
390 nsAtom* aPrefix,
391 txStylesheetAttr* aAttributes,
392 int32_t aAttrCount,
393 txStylesheetCompilerState& aState) {
394 // extension-element-prefixes is handled in
395 // txStylesheetCompiler::startElementInternal
397 txStylesheetAttr* attr;
398 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
399 nsGkAtoms::id, false, &attr);
400 NS_ENSURE_SUCCESS(rv, rv);
402 rv = parseExcludeResultPrefixes(aAttributes, aAttrCount, kNameSpaceID_None);
403 NS_ENSURE_SUCCESS(rv, rv);
405 rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
406 nsGkAtoms::version, true, &attr);
407 NS_ENSURE_SUCCESS(rv, rv);
409 aState.pushHandlerTable(gTxImportHandler);
411 return NS_OK;
414 static void txFnEndStylesheet(txStylesheetCompilerState& aState) {
415 aState.popHandlerTable();
418 static nsresult txFnStartElementContinueTopLevel(
419 int32_t aNamespaceID, nsAtom* aLocalName, nsAtom* aPrefix,
420 txStylesheetAttr* aAttributes, int32_t aAttrCount,
421 txStylesheetCompilerState& aState) {
422 aState.mHandlerTable = gTxTopHandler;
424 return NS_XSLT_GET_NEW_HANDLER;
427 static nsresult txFnStartLREStylesheet(int32_t aNamespaceID, nsAtom* aLocalName,
428 nsAtom* aPrefix,
429 txStylesheetAttr* aAttributes,
430 int32_t aAttrCount,
431 txStylesheetCompilerState& aState) {
432 txStylesheetAttr* attr;
433 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_XSLT,
434 nsGkAtoms::version, true, &attr);
435 NS_ENSURE_SUCCESS(rv, rv);
437 txExpandedName nullExpr;
438 double prio = UnspecifiedNaN<double>();
440 UniquePtr<txPattern> match(new txRootPattern());
441 UniquePtr<txTemplateItem> templ(
442 new txTemplateItem(std::move(match), nullExpr, nullExpr, prio));
443 aState.openInstructionContainer(templ.get());
444 aState.addToplevelItem(templ.release());
446 aState.pushHandlerTable(gTxTemplateHandler);
448 return txFnStartLRE(aNamespaceID, aLocalName, aPrefix, aAttributes,
449 aAttrCount, aState);
452 static void txFnEndLREStylesheet(txStylesheetCompilerState& aState) {
453 txFnEndLRE(aState);
455 aState.popHandlerTable();
457 aState.addInstruction(MakeUnique<txReturn>());
459 aState.closeInstructionContainer();
462 static nsresult txFnStartEmbed(int32_t aNamespaceID, nsAtom* aLocalName,
463 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
464 int32_t aAttrCount,
465 txStylesheetCompilerState& aState) {
466 if (!aState.handleEmbeddedSheet()) {
467 return NS_OK;
469 if (aNamespaceID != kNameSpaceID_XSLT ||
470 (aLocalName != nsGkAtoms::stylesheet &&
471 aLocalName != nsGkAtoms::transform)) {
472 return NS_ERROR_XSLT_PARSE_FAILURE;
474 return txFnStartStylesheet(aNamespaceID, aLocalName, aPrefix, aAttributes,
475 aAttrCount, aState);
478 static void txFnEndEmbed(txStylesheetCompilerState& aState) {
479 if (!aState.handleEmbeddedSheet()) {
480 return;
482 txFnEndStylesheet(aState);
483 aState.doneEmbedding();
487 * Top handlers
489 static nsresult txFnStartOtherTop(int32_t aNamespaceID, nsAtom* aLocalName,
490 nsAtom* aPrefix,
491 txStylesheetAttr* aAttributes,
492 int32_t aAttrCount,
493 txStylesheetCompilerState& aState) {
494 if (aNamespaceID == kNameSpaceID_None ||
495 (aNamespaceID == kNameSpaceID_XSLT && !aState.fcp())) {
496 return NS_ERROR_XSLT_PARSE_FAILURE;
499 aState.pushHandlerTable(gTxIgnoreHandler);
501 return NS_OK;
504 static void txFnEndOtherTop(txStylesheetCompilerState& aState) {
505 aState.popHandlerTable();
508 // xsl:attribute-set
509 static nsresult txFnStartAttributeSet(int32_t aNamespaceID, nsAtom* aLocalName,
510 nsAtom* aPrefix,
511 txStylesheetAttr* aAttributes,
512 int32_t aAttrCount,
513 txStylesheetCompilerState& aState) {
514 nsresult rv = NS_OK;
515 txExpandedName name;
516 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
517 name);
518 NS_ENSURE_SUCCESS(rv, rv);
520 UniquePtr<txAttributeSetItem> attrSet(new txAttributeSetItem(name));
521 aState.openInstructionContainer(attrSet.get());
523 aState.addToplevelItem(attrSet.release());
525 rv = parseUseAttrSets(aAttributes, aAttrCount, false, aState);
526 NS_ENSURE_SUCCESS(rv, rv);
528 aState.pushHandlerTable(gTxAttributeSetHandler);
530 return NS_OK;
533 static void txFnEndAttributeSet(txStylesheetCompilerState& aState) {
534 aState.popHandlerTable();
536 aState.addInstruction(MakeUnique<txReturn>());
538 aState.closeInstructionContainer();
541 // xsl:decimal-format
542 static nsresult txFnStartDecimalFormat(int32_t aNamespaceID, nsAtom* aLocalName,
543 nsAtom* aPrefix,
544 txStylesheetAttr* aAttributes,
545 int32_t aAttrCount,
546 txStylesheetCompilerState& aState) {
547 nsresult rv = NS_OK;
548 txExpandedName name;
549 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, false, aState,
550 name);
551 NS_ENSURE_SUCCESS(rv, rv);
553 UniquePtr<txDecimalFormat> format(new txDecimalFormat);
554 rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::decimalSeparator, false,
555 aState, format->mDecimalSeparator);
556 NS_ENSURE_SUCCESS(rv, rv);
558 rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSeparator, false,
559 aState, format->mGroupingSeparator);
560 NS_ENSURE_SUCCESS(rv, rv);
562 txStylesheetAttr* attr = nullptr;
563 rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
564 nsGkAtoms::infinity, false, &attr);
565 NS_ENSURE_SUCCESS(rv, rv);
567 if (attr) {
568 format->mInfinity = attr->mValue;
571 rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::minusSign, false, aState,
572 format->mMinusSign);
573 NS_ENSURE_SUCCESS(rv, rv);
575 rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::NaN,
576 false, &attr);
577 NS_ENSURE_SUCCESS(rv, rv);
579 if (attr) {
580 format->mNaN = attr->mValue;
583 rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::percent, false, aState,
584 format->mPercent);
585 NS_ENSURE_SUCCESS(rv, rv);
587 rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::perMille, false, aState,
588 format->mPerMille);
589 NS_ENSURE_SUCCESS(rv, rv);
591 rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::zeroDigit, false, aState,
592 format->mZeroDigit);
593 NS_ENSURE_SUCCESS(rv, rv);
595 rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::digit, false, aState,
596 format->mDigit);
597 NS_ENSURE_SUCCESS(rv, rv);
599 rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::patternSeparator, false,
600 aState, format->mPatternSeparator);
601 NS_ENSURE_SUCCESS(rv, rv);
603 rv = aState.mStylesheet->addDecimalFormat(name, std::move(format));
604 NS_ENSURE_SUCCESS(rv, rv);
606 aState.pushHandlerTable(gTxIgnoreHandler);
608 return NS_OK;
611 static void txFnEndDecimalFormat(txStylesheetCompilerState& aState) {
612 aState.popHandlerTable();
615 // xsl:import
616 static nsresult txFnStartImport(int32_t aNamespaceID, nsAtom* aLocalName,
617 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
618 int32_t aAttrCount,
619 txStylesheetCompilerState& aState) {
620 UniquePtr<txImportItem> import(new txImportItem);
621 import->mFrame = MakeUnique<txStylesheet::ImportFrame>();
622 txStylesheet::ImportFrame* frame = import->mFrame.get();
623 aState.addToplevelItem(import.release());
625 txStylesheetAttr* attr = nullptr;
626 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
627 nsGkAtoms::href, true, &attr);
628 NS_ENSURE_SUCCESS(rv, rv);
630 nsAutoString absUri;
631 URIUtils::resolveHref(attr->mValue, aState.mElementContext->mBaseURI, absUri);
632 rv = aState.loadImportedStylesheet(absUri, frame);
633 NS_ENSURE_SUCCESS(rv, rv);
635 aState.pushHandlerTable(gTxIgnoreHandler);
637 return NS_OK;
640 static void txFnEndImport(txStylesheetCompilerState& aState) {
641 aState.popHandlerTable();
644 // xsl:include
645 static nsresult txFnStartInclude(int32_t aNamespaceID, nsAtom* aLocalName,
646 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
647 int32_t aAttrCount,
648 txStylesheetCompilerState& aState) {
649 txStylesheetAttr* attr = nullptr;
650 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
651 nsGkAtoms::href, true, &attr);
652 NS_ENSURE_SUCCESS(rv, rv);
654 nsAutoString absUri;
655 URIUtils::resolveHref(attr->mValue, aState.mElementContext->mBaseURI, absUri);
656 rv = aState.loadIncludedStylesheet(absUri);
657 NS_ENSURE_SUCCESS(rv, rv);
659 aState.pushHandlerTable(gTxIgnoreHandler);
661 return NS_OK;
664 static void txFnEndInclude(txStylesheetCompilerState& aState) {
665 aState.popHandlerTable();
668 // xsl:key
669 static nsresult txFnStartKey(int32_t aNamespaceID, nsAtom* aLocalName,
670 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
671 int32_t aAttrCount,
672 txStylesheetCompilerState& aState) {
673 nsresult rv = NS_OK;
674 txExpandedName name;
675 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
676 name);
677 NS_ENSURE_SUCCESS(rv, rv);
679 aState.mDisAllowed = txIParseContext::KEY_FUNCTION;
681 UniquePtr<txPattern> match;
682 rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::match, true, aState,
683 match);
684 NS_ENSURE_SUCCESS(rv, rv);
686 UniquePtr<Expr> use;
687 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::use, true, aState, use);
688 NS_ENSURE_SUCCESS(rv, rv);
690 aState.mDisAllowed = 0;
692 rv = aState.mStylesheet->addKey(name, std::move(match), std::move(use));
693 NS_ENSURE_SUCCESS(rv, rv);
695 aState.pushHandlerTable(gTxIgnoreHandler);
697 return NS_OK;
700 static void txFnEndKey(txStylesheetCompilerState& aState) {
701 aState.popHandlerTable();
704 // xsl:namespace-alias
705 static nsresult txFnStartNamespaceAlias(int32_t aNamespaceID,
706 nsAtom* aLocalName, nsAtom* aPrefix,
707 txStylesheetAttr* aAttributes,
708 int32_t aAttrCount,
709 txStylesheetCompilerState& aState) {
710 txStylesheetAttr* attr = nullptr;
711 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
712 nsGkAtoms::stylesheetPrefix, true, &attr);
713 NS_ENSURE_SUCCESS(rv, rv);
715 rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
716 nsGkAtoms::resultPrefix, true, &attr);
717 NS_ENSURE_SUCCESS(rv, rv);
719 // XXX Needs to be implemented.
721 aState.pushHandlerTable(gTxIgnoreHandler);
723 return NS_OK;
726 static void txFnEndNamespaceAlias(txStylesheetCompilerState& aState) {
727 aState.popHandlerTable();
730 // xsl:output
731 static nsresult txFnStartOutput(int32_t aNamespaceID, nsAtom* aLocalName,
732 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
733 int32_t aAttrCount,
734 txStylesheetCompilerState& aState) {
735 nsresult rv = NS_OK;
737 UniquePtr<txOutputItem> item(new txOutputItem);
739 txExpandedName methodExpName;
740 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::method, false, aState,
741 methodExpName);
742 NS_ENSURE_SUCCESS(rv, rv);
744 if (!methodExpName.isNull()) {
745 if (methodExpName.mNamespaceID != kNameSpaceID_None) {
746 // The spec doesn't say what to do here so we'll just ignore the
747 // value. We could possibly warn.
748 } else if (methodExpName.mLocalName == nsGkAtoms::html) {
749 item->mFormat.mMethod = eHTMLOutput;
750 } else if (methodExpName.mLocalName == nsGkAtoms::text) {
751 item->mFormat.mMethod = eTextOutput;
752 } else if (methodExpName.mLocalName == nsGkAtoms::xml) {
753 item->mFormat.mMethod = eXMLOutput;
754 } else {
755 return NS_ERROR_XSLT_PARSE_FAILURE;
759 txStylesheetAttr* attr = nullptr;
760 getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::version,
761 false, &attr);
762 if (attr) {
763 item->mFormat.mVersion = attr->mValue;
766 getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::encoding,
767 false, &attr);
768 if (attr) {
769 item->mFormat.mEncoding = attr->mValue;
772 rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::omitXmlDeclaration,
773 false, aState, item->mFormat.mOmitXMLDeclaration);
774 NS_ENSURE_SUCCESS(rv, rv);
776 rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::standalone, false,
777 aState, item->mFormat.mStandalone);
778 NS_ENSURE_SUCCESS(rv, rv);
780 getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
781 nsGkAtoms::doctypePublic, false, &attr);
782 if (attr) {
783 item->mFormat.mPublicId = attr->mValue;
786 getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
787 nsGkAtoms::doctypeSystem, false, &attr);
788 if (attr) {
789 item->mFormat.mSystemId = attr->mValue;
792 getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
793 nsGkAtoms::cdataSectionElements, false, &attr);
794 if (attr) {
795 nsWhitespaceTokenizer tokens(attr->mValue);
796 while (tokens.hasMoreTokens()) {
797 UniquePtr<txExpandedName> qname(new txExpandedName());
798 rv = qname->init(tokens.nextToken(), aState.mElementContext->mMappings,
799 false);
800 NS_ENSURE_SUCCESS(rv, rv);
802 item->mFormat.mCDATASectionElements.add(qname.release());
806 rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::indent, false, aState,
807 item->mFormat.mIndent);
808 NS_ENSURE_SUCCESS(rv, rv);
810 getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::mediaType,
811 false, &attr);
812 if (attr) {
813 item->mFormat.mMediaType = NS_ConvertUTF16toUTF8(attr->mValue);
816 aState.addToplevelItem(item.release());
818 aState.pushHandlerTable(gTxIgnoreHandler);
820 return NS_OK;
823 static void txFnEndOutput(txStylesheetCompilerState& aState) {
824 aState.popHandlerTable();
827 // xsl:strip-space/xsl:preserve-space
828 static nsresult txFnStartStripSpace(int32_t aNamespaceID, nsAtom* aLocalName,
829 nsAtom* aPrefix,
830 txStylesheetAttr* aAttributes,
831 int32_t aAttrCount,
832 txStylesheetCompilerState& aState) {
833 txStylesheetAttr* attr = nullptr;
834 nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
835 nsGkAtoms::elements, true, &attr);
836 NS_ENSURE_SUCCESS(rv, rv);
838 bool strip = aLocalName == nsGkAtoms::stripSpace;
840 UniquePtr<txStripSpaceItem> stripItem(new txStripSpaceItem);
841 nsWhitespaceTokenizer tokenizer(attr->mValue);
842 while (tokenizer.hasMoreTokens()) {
843 const nsAString& name = tokenizer.nextToken();
844 int32_t ns = kNameSpaceID_None;
845 RefPtr<nsAtom> prefix, localName;
846 rv = XMLUtils::splitQName(name, getter_AddRefs(prefix),
847 getter_AddRefs(localName));
848 if (NS_FAILED(rv)) {
849 // check for "*" or "prefix:*"
850 uint32_t length = name.Length();
851 const char16_t* c;
852 name.BeginReading(c);
853 if (length == 2 || c[length - 1] != '*') {
854 // these can't work
855 return NS_ERROR_XSLT_PARSE_FAILURE;
857 if (length > 1) {
858 // Check for a valid prefix, that is, the returned prefix
859 // should be empty and the real prefix is returned in
860 // localName.
861 if (c[length - 2] != ':') {
862 return NS_ERROR_XSLT_PARSE_FAILURE;
864 rv = XMLUtils::splitQName(StringHead(name, length - 2),
865 getter_AddRefs(prefix),
866 getter_AddRefs(localName));
867 if (NS_FAILED(rv) || prefix) {
868 // bad chars or two ':'
869 return NS_ERROR_XSLT_PARSE_FAILURE;
871 prefix = localName;
873 localName = nsGkAtoms::_asterisk;
875 if (prefix) {
876 ns = aState.mElementContext->mMappings->lookupNamespace(prefix);
877 NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, NS_ERROR_FAILURE);
879 stripItem->addStripSpaceTest(
880 new txStripSpaceTest(prefix, localName, ns, strip));
883 aState.addToplevelItem(stripItem.release());
885 aState.pushHandlerTable(gTxIgnoreHandler);
887 return NS_OK;
890 static void txFnEndStripSpace(txStylesheetCompilerState& aState) {
891 aState.popHandlerTable();
894 // xsl:template
895 static nsresult txFnStartTemplate(int32_t aNamespaceID, nsAtom* aLocalName,
896 nsAtom* aPrefix,
897 txStylesheetAttr* aAttributes,
898 int32_t aAttrCount,
899 txStylesheetCompilerState& aState) {
900 nsresult rv = NS_OK;
901 txExpandedName name;
902 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, false, aState,
903 name);
904 NS_ENSURE_SUCCESS(rv, rv);
906 txExpandedName mode;
907 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::mode, false, aState,
908 mode);
909 NS_ENSURE_SUCCESS(rv, rv);
911 double prio = UnspecifiedNaN<double>();
912 rv = getNumberAttr(aAttributes, aAttrCount, nsGkAtoms::priority, false,
913 aState, prio);
914 NS_ENSURE_SUCCESS(rv, rv);
916 UniquePtr<txPattern> match;
917 rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::match, name.isNull(),
918 aState, match);
919 NS_ENSURE_SUCCESS(rv, rv);
921 UniquePtr<txTemplateItem> templ(
922 new txTemplateItem(std::move(match), name, mode, prio));
923 aState.openInstructionContainer(templ.get());
924 aState.addToplevelItem(templ.release());
926 aState.pushHandlerTable(gTxParamHandler);
928 return NS_OK;
931 static void txFnEndTemplate(txStylesheetCompilerState& aState) {
932 aState.popHandlerTable();
934 aState.addInstruction(MakeUnique<txReturn>());
936 aState.closeInstructionContainer();
939 // xsl:variable, xsl:param
940 static nsresult txFnStartTopVariable(int32_t aNamespaceID, nsAtom* aLocalName,
941 nsAtom* aPrefix,
942 txStylesheetAttr* aAttributes,
943 int32_t aAttrCount,
944 txStylesheetCompilerState& aState) {
945 nsresult rv = NS_OK;
946 txExpandedName name;
947 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
948 name);
949 NS_ENSURE_SUCCESS(rv, rv);
951 UniquePtr<Expr> select;
952 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
953 select);
954 NS_ENSURE_SUCCESS(rv, rv);
956 UniquePtr<txVariableItem> var(new txVariableItem(
957 name, std::move(select), aLocalName == nsGkAtoms::param));
958 aState.openInstructionContainer(var.get());
959 aState.pushPtr(var.get(), aState.eVariableItem);
961 if (var->mValue) {
962 // XXX should be gTxErrorHandler?
963 aState.pushHandlerTable(gTxIgnoreHandler);
964 } else {
965 aState.pushHandlerTable(gTxTopVariableHandler);
968 aState.addToplevelItem(var.release());
970 return NS_OK;
973 static void txFnEndTopVariable(txStylesheetCompilerState& aState) {
974 txHandlerTable* prev = aState.mHandlerTable;
975 aState.popHandlerTable();
976 txVariableItem* var =
977 static_cast<txVariableItem*>(aState.popPtr(aState.eVariableItem));
979 if (prev == gTxTopVariableHandler) {
980 // No children were found.
981 NS_ASSERTION(!var->mValue, "There shouldn't be a select-expression here");
982 var->mValue = MakeUnique<txLiteralExpr>(u""_ns);
983 } else if (!var->mValue) {
984 // If we don't have a select-expression there mush be children.
985 aState.addInstruction(MakeUnique<txReturn>());
988 aState.closeInstructionContainer();
991 static nsresult txFnStartElementStartTopVar(int32_t aNamespaceID,
992 nsAtom* aLocalName, nsAtom* aPrefix,
993 txStylesheetAttr* aAttributes,
994 int32_t aAttrCount,
995 txStylesheetCompilerState& aState) {
996 aState.mHandlerTable = gTxTemplateHandler;
998 return NS_XSLT_GET_NEW_HANDLER;
1001 static nsresult txFnTextStartTopVar(const nsAString& aStr,
1002 txStylesheetCompilerState& aState) {
1003 TX_RETURN_IF_WHITESPACE(aStr, aState);
1005 aState.mHandlerTable = gTxTemplateHandler;
1007 return NS_XSLT_GET_NEW_HANDLER;
1011 * Template Handlers
1017 txStartLREElement
1018 txInsertAttrSet one for each qname in xsl:use-attribute-sets
1019 txLREAttribute one for each attribute
1020 [children]
1021 txEndElement
1023 static nsresult txFnStartLRE(int32_t aNamespaceID, nsAtom* aLocalName,
1024 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1025 int32_t aAttrCount,
1026 txStylesheetCompilerState& aState) {
1027 nsresult rv = NS_OK;
1029 aState.addInstruction(
1030 MakeUnique<txStartLREElement>(aNamespaceID, aLocalName, aPrefix));
1032 rv = parseExcludeResultPrefixes(aAttributes, aAttrCount, kNameSpaceID_XSLT);
1033 NS_ENSURE_SUCCESS(rv, rv);
1035 rv = parseUseAttrSets(aAttributes, aAttrCount, true, aState);
1036 NS_ENSURE_SUCCESS(rv, rv);
1038 txStylesheetAttr* attr = nullptr;
1039 int32_t i;
1040 for (i = 0; i < aAttrCount; ++i) {
1041 attr = aAttributes + i;
1043 if (attr->mNamespaceID == kNameSpaceID_XSLT) {
1044 if (attr->mLocalName == nsGkAtoms::version) {
1045 attr->mLocalName = nullptr;
1048 continue;
1051 UniquePtr<Expr> avt;
1052 rv = txExprParser::createAVT(attr->mValue, &aState, getter_Transfers(avt));
1053 NS_ENSURE_SUCCESS(rv, rv);
1055 aState.addInstruction(MakeUnique<txLREAttribute>(
1056 attr->mNamespaceID, attr->mLocalName, attr->mPrefix, std::move(avt)));
1059 return NS_OK;
1062 static void txFnEndLRE(txStylesheetCompilerState& aState) {
1063 aState.addInstruction(MakeUnique<txEndElement>());
1067 "LRE text"
1069 txText
1071 static nsresult txFnText(const nsAString& aStr,
1072 txStylesheetCompilerState& aState) {
1073 TX_RETURN_IF_WHITESPACE(aStr, aState);
1075 aState.addInstruction(MakeUnique<txText>(aStr, false));
1077 return NS_OK;
1081 xsl:apply-imports
1083 txApplyImportsStart
1084 txApplyImportsEnd
1086 static nsresult txFnStartApplyImports(int32_t aNamespaceID, nsAtom* aLocalName,
1087 nsAtom* aPrefix,
1088 txStylesheetAttr* aAttributes,
1089 int32_t aAttrCount,
1090 txStylesheetCompilerState& aState) {
1091 aState.addInstruction(MakeUnique<txApplyImportsStart>());
1092 aState.addInstruction(MakeUnique<txApplyImportsEnd>());
1094 aState.pushHandlerTable(gTxIgnoreHandler);
1096 return NS_OK;
1099 static void txFnEndApplyImports(txStylesheetCompilerState& aState) {
1100 aState.popHandlerTable();
1104 xsl:apply-templates
1106 txPushParams
1107 [params]
1108 txPushNewContext -+ (holds <xsl:sort>s)
1109 txApplyTemplate <-+ |
1110 txLoopNodeSet -+ |
1111 txPopParams <-+
1113 static nsresult txFnStartApplyTemplates(int32_t aNamespaceID,
1114 nsAtom* aLocalName, nsAtom* aPrefix,
1115 txStylesheetAttr* aAttributes,
1116 int32_t aAttrCount,
1117 txStylesheetCompilerState& aState) {
1118 nsresult rv = NS_OK;
1120 aState.addInstruction(MakeUnique<txPushParams>());
1122 txExpandedName mode;
1123 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::mode, false, aState,
1124 mode);
1125 NS_ENSURE_SUCCESS(rv, rv);
1127 pushInstruction(aState, MakeUnique<txApplyTemplates>(mode));
1129 UniquePtr<Expr> select;
1130 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1131 select);
1132 NS_ENSURE_SUCCESS(rv, rv);
1134 if (!select) {
1135 UniquePtr<txNodeTest> nt(new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
1136 select = MakeUnique<LocationStep>(nt.release(), LocationStep::CHILD_AXIS);
1139 UniquePtr<txPushNewContext> pushcontext(
1140 new txPushNewContext(std::move(select)));
1141 aState.pushSorter(pushcontext.get());
1142 pushInstruction(aState, std::move(pushcontext));
1144 aState.pushHandlerTable(gTxApplyTemplatesHandler);
1146 return NS_OK;
1149 static void txFnEndApplyTemplates(txStylesheetCompilerState& aState) {
1150 aState.popHandlerTable();
1152 txPushNewContext* pushcontext =
1153 aState.addInstruction(popInstruction<txPushNewContext>(aState));
1155 aState.popSorter();
1157 // txApplyTemplates
1158 txInstruction* instr = aState.addInstruction(popInstruction(aState));
1159 aState.addInstruction(MakeUnique<txLoopNodeSet>(instr));
1161 pushcontext->mBailTarget = aState.addInstruction(MakeUnique<txPopParams>());
1165 xsl:attribute
1167 txPushStringHandler
1168 [children]
1169 txAttribute
1171 static nsresult txFnStartAttribute(int32_t aNamespaceID, nsAtom* aLocalName,
1172 nsAtom* aPrefix,
1173 txStylesheetAttr* aAttributes,
1174 int32_t aAttrCount,
1175 txStylesheetCompilerState& aState) {
1176 nsresult rv = NS_OK;
1178 aState.addInstruction(MakeUnique<txPushStringHandler>(true));
1180 UniquePtr<Expr> name;
1181 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState, name);
1182 NS_ENSURE_SUCCESS(rv, rv);
1184 UniquePtr<Expr> nspace;
1185 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::_namespace, false, aState,
1186 nspace);
1187 NS_ENSURE_SUCCESS(rv, rv);
1189 pushInstruction(aState,
1190 MakeUnique<txAttribute>(std::move(name), std::move(nspace),
1191 aState.mElementContext->mMappings));
1193 // We need to push the template-handler since the current might be
1194 // the attributeset-handler
1195 aState.pushHandlerTable(gTxTemplateHandler);
1197 return NS_OK;
1200 static void txFnEndAttribute(txStylesheetCompilerState& aState) {
1201 aState.popHandlerTable();
1202 aState.addInstruction(popInstruction(aState));
1206 xsl:call-template
1208 txPushParams
1209 [params]
1210 txCallTemplate
1211 txPopParams
1213 static nsresult txFnStartCallTemplate(int32_t aNamespaceID, nsAtom* aLocalName,
1214 nsAtom* aPrefix,
1215 txStylesheetAttr* aAttributes,
1216 int32_t aAttrCount,
1217 txStylesheetCompilerState& aState) {
1218 nsresult rv = NS_OK;
1220 aState.addInstruction(MakeUnique<txPushParams>());
1222 txExpandedName name;
1223 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1224 name);
1225 NS_ENSURE_SUCCESS(rv, rv);
1227 pushInstruction(aState, MakeUnique<txCallTemplate>(name));
1229 aState.pushHandlerTable(gTxCallTemplateHandler);
1231 return NS_OK;
1234 static void txFnEndCallTemplate(txStylesheetCompilerState& aState) {
1235 aState.popHandlerTable();
1237 // txCallTemplate
1238 aState.addInstruction(popInstruction(aState));
1240 aState.addInstruction(MakeUnique<txPopParams>());
1244 xsl:choose
1246 txCondotionalGoto --+ \
1247 [children] | | one for each xsl:when
1248 txGoTo --+ | /
1250 txCondotionalGoto | <-+ --+
1251 [children] | |
1252 txGoTo --+ |
1254 [children] | <-+ for the xsl:otherwise, if there is one
1257 static nsresult txFnStartChoose(int32_t aNamespaceID, nsAtom* aLocalName,
1258 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1259 int32_t aAttrCount,
1260 txStylesheetCompilerState& aState) {
1261 aState.pushChooseGotoList();
1263 aState.pushHandlerTable(gTxChooseHandler);
1265 return NS_OK;
1268 static void txFnEndChoose(txStylesheetCompilerState& aState) {
1269 aState.popHandlerTable();
1270 txListIterator iter(aState.mChooseGotoList.get());
1271 txGoTo* gotoinstr;
1272 while ((gotoinstr = static_cast<txGoTo*>(iter.next()))) {
1273 aState.addGotoTarget(&gotoinstr->mTarget);
1276 aState.popChooseGotoList();
1280 xsl:comment
1282 txPushStringHandler
1283 [children]
1284 txComment
1286 static nsresult txFnStartComment(int32_t aNamespaceID, nsAtom* aLocalName,
1287 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1288 int32_t aAttrCount,
1289 txStylesheetCompilerState& aState) {
1290 aState.addInstruction(MakeUnique<txPushStringHandler>(true));
1292 return NS_OK;
1295 static void txFnEndComment(txStylesheetCompilerState& aState) {
1296 aState.addInstruction(MakeUnique<txComment>());
1300 xsl:copy
1302 txCopy -+
1303 txInsertAttrSet | one for each qname in use-attribute-sets
1304 [children] |
1305 txEndElement |
1308 static nsresult txFnStartCopy(int32_t aNamespaceID, nsAtom* aLocalName,
1309 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1310 int32_t aAttrCount,
1311 txStylesheetCompilerState& aState) {
1312 aState.pushPtr(aState.addInstruction(MakeUnique<txCopy>()), aState.eCopy);
1314 return parseUseAttrSets(aAttributes, aAttrCount, false, aState);
1317 static void txFnEndCopy(txStylesheetCompilerState& aState) {
1318 aState.addInstruction(MakeUnique<txEndElement>());
1320 txCopy* copy = static_cast<txCopy*>(aState.popPtr(aState.eCopy));
1321 aState.addGotoTarget(&copy->mBailTarget);
1325 xsl:copy-of
1327 txCopyOf
1329 static nsresult txFnStartCopyOf(int32_t aNamespaceID, nsAtom* aLocalName,
1330 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1331 int32_t aAttrCount,
1332 txStylesheetCompilerState& aState) {
1333 nsresult rv = NS_OK;
1335 UniquePtr<Expr> select;
1336 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true, aState,
1337 select);
1338 NS_ENSURE_SUCCESS(rv, rv);
1340 aState.addInstruction(MakeUnique<txCopyOf>(std::move(select)));
1342 aState.pushHandlerTable(gTxIgnoreHandler);
1344 return NS_OK;
1347 static void txFnEndCopyOf(txStylesheetCompilerState& aState) {
1348 aState.popHandlerTable();
1352 xsl:element
1354 txStartElement
1355 txInsertAttrSet one for each qname in use-attribute-sets
1356 [children]
1357 txEndElement
1359 static nsresult txFnStartElement(int32_t aNamespaceID, nsAtom* aLocalName,
1360 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1361 int32_t aAttrCount,
1362 txStylesheetCompilerState& aState) {
1363 nsresult rv = NS_OK;
1365 UniquePtr<Expr> name;
1366 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState, name);
1367 NS_ENSURE_SUCCESS(rv, rv);
1369 UniquePtr<Expr> nspace;
1370 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::_namespace, false, aState,
1371 nspace);
1372 NS_ENSURE_SUCCESS(rv, rv);
1374 aState.addInstruction(MakeUnique<txStartElement>(
1375 std::move(name), std::move(nspace), aState.mElementContext->mMappings));
1377 rv = parseUseAttrSets(aAttributes, aAttrCount, false, aState);
1378 NS_ENSURE_SUCCESS(rv, rv);
1380 return NS_OK;
1383 static void txFnEndElement(txStylesheetCompilerState& aState) {
1384 aState.addInstruction(MakeUnique<txEndElement>());
1388 xsl:fallback
1390 [children]
1392 static nsresult txFnStartFallback(int32_t aNamespaceID, nsAtom* aLocalName,
1393 nsAtom* aPrefix,
1394 txStylesheetAttr* aAttributes,
1395 int32_t aAttrCount,
1396 txStylesheetCompilerState& aState) {
1397 aState.mSearchingForFallback = false;
1399 aState.pushHandlerTable(gTxTemplateHandler);
1401 return NS_OK;
1404 static void txFnEndFallback(txStylesheetCompilerState& aState) {
1405 aState.popHandlerTable();
1407 NS_ASSERTION(!aState.mSearchingForFallback,
1408 "bad nesting of unknown-instruction and fallback handlers");
1412 xsl:for-each
1414 txPushNewContext -+ (holds <xsl:sort>s)
1415 txPushNullTemplateRule <-+ |
1416 [children] | |
1417 txLoopNodeSet -+ |
1420 static nsresult txFnStartForEach(int32_t aNamespaceID, nsAtom* aLocalName,
1421 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1422 int32_t aAttrCount,
1423 txStylesheetCompilerState& aState) {
1424 nsresult rv = NS_OK;
1426 UniquePtr<Expr> select;
1427 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true, aState,
1428 select);
1429 NS_ENSURE_SUCCESS(rv, rv);
1431 txPushNewContext* pushcontext =
1432 aState.addInstruction(MakeUnique<txPushNewContext>(std::move(select)));
1433 aState.pushPtr(pushcontext, aState.ePushNewContext);
1434 aState.pushSorter(pushcontext);
1436 aState.pushPtr(aState.addInstruction(MakeUnique<txPushNullTemplateRule>()),
1437 aState.ePushNullTemplateRule);
1439 aState.pushHandlerTable(gTxForEachHandler);
1441 return NS_OK;
1444 static void txFnEndForEach(txStylesheetCompilerState& aState) {
1445 aState.popHandlerTable();
1447 // This is a txPushNullTemplateRule
1448 txInstruction* pnullrule =
1449 static_cast<txInstruction*>(aState.popPtr(aState.ePushNullTemplateRule));
1451 aState.addInstruction(MakeUnique<txLoopNodeSet>(pnullrule));
1453 aState.popSorter();
1454 txPushNewContext* pushcontext =
1455 static_cast<txPushNewContext*>(aState.popPtr(aState.ePushNewContext));
1456 aState.addGotoTarget(&pushcontext->mBailTarget);
1459 static nsresult txFnStartElementContinueTemplate(
1460 int32_t aNamespaceID, nsAtom* aLocalName, nsAtom* aPrefix,
1461 txStylesheetAttr* aAttributes, int32_t aAttrCount,
1462 txStylesheetCompilerState& aState) {
1463 aState.mHandlerTable = gTxTemplateHandler;
1465 return NS_XSLT_GET_NEW_HANDLER;
1468 static nsresult txFnTextContinueTemplate(const nsAString& aStr,
1469 txStylesheetCompilerState& aState) {
1470 TX_RETURN_IF_WHITESPACE(aStr, aState);
1472 aState.mHandlerTable = gTxTemplateHandler;
1474 return NS_XSLT_GET_NEW_HANDLER;
1478 xsl:if
1480 txConditionalGoto -+
1481 [children] |
1484 static nsresult txFnStartIf(int32_t aNamespaceID, nsAtom* aLocalName,
1485 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1486 int32_t aAttrCount,
1487 txStylesheetCompilerState& aState) {
1488 nsresult rv = NS_OK;
1490 UniquePtr<Expr> test;
1491 rv =
1492 getExprAttr(aAttributes, aAttrCount, nsGkAtoms::test, true, aState, test);
1493 NS_ENSURE_SUCCESS(rv, rv);
1495 aState.pushPtr(aState.addInstruction(
1496 MakeUnique<txConditionalGoto>(std::move(test), nullptr)),
1497 aState.eConditionalGoto);
1499 return NS_OK;
1502 static void txFnEndIf(txStylesheetCompilerState& aState) {
1503 txConditionalGoto* condGoto =
1504 static_cast<txConditionalGoto*>(aState.popPtr(aState.eConditionalGoto));
1505 aState.addGotoTarget(&condGoto->mTarget);
1509 xsl:message
1511 txPushStringHandler
1512 [children]
1513 txMessage
1515 static nsresult txFnStartMessage(int32_t aNamespaceID, nsAtom* aLocalName,
1516 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1517 int32_t aAttrCount,
1518 txStylesheetCompilerState& aState) {
1519 aState.addInstruction(MakeUnique<txPushStringHandler>(false));
1521 txThreeState term;
1522 nsresult rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::terminate,
1523 false, aState, term);
1524 NS_ENSURE_SUCCESS(rv, rv);
1526 pushInstruction(aState, MakeUnique<txMessage>(term == eTrue));
1528 return NS_OK;
1531 static void txFnEndMessage(txStylesheetCompilerState& aState) {
1532 aState.addInstruction(popInstruction(aState));
1536 xsl:number
1538 txNumber
1540 static nsresult txFnStartNumber(int32_t aNamespaceID, nsAtom* aLocalName,
1541 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1542 int32_t aAttrCount,
1543 txStylesheetCompilerState& aState) {
1544 nsresult rv = NS_OK;
1546 RefPtr<nsAtom> levelAtom;
1547 rv = getAtomAttr(aAttributes, aAttrCount, nsGkAtoms::level, false, aState,
1548 getter_AddRefs(levelAtom));
1549 NS_ENSURE_SUCCESS(rv, rv);
1551 txXSLTNumber::LevelType level = txXSLTNumber::eLevelSingle;
1552 if (levelAtom == nsGkAtoms::multiple) {
1553 level = txXSLTNumber::eLevelMultiple;
1554 } else if (levelAtom == nsGkAtoms::any) {
1555 level = txXSLTNumber::eLevelAny;
1556 } else if (levelAtom && levelAtom != nsGkAtoms::single && !aState.fcp()) {
1557 return NS_ERROR_XSLT_PARSE_FAILURE;
1560 UniquePtr<txPattern> count;
1561 rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::count, false, aState,
1562 count);
1563 NS_ENSURE_SUCCESS(rv, rv);
1565 UniquePtr<txPattern> from;
1566 rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::from, false, aState,
1567 from);
1568 NS_ENSURE_SUCCESS(rv, rv);
1570 UniquePtr<Expr> value;
1571 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::value, false, aState,
1572 value);
1573 NS_ENSURE_SUCCESS(rv, rv);
1575 UniquePtr<Expr> format;
1576 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::format, false, aState,
1577 format);
1578 NS_ENSURE_SUCCESS(rv, rv);
1580 UniquePtr<Expr> lang;
1581 rv =
1582 getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::lang, false, aState, lang);
1583 NS_ENSURE_SUCCESS(rv, rv);
1585 UniquePtr<Expr> letterValue;
1586 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::letterValue, false,
1587 aState, letterValue);
1588 NS_ENSURE_SUCCESS(rv, rv);
1590 UniquePtr<Expr> groupingSeparator;
1591 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSeparator, false,
1592 aState, groupingSeparator);
1593 NS_ENSURE_SUCCESS(rv, rv);
1595 UniquePtr<Expr> groupingSize;
1596 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSize, false,
1597 aState, groupingSize);
1598 NS_ENSURE_SUCCESS(rv, rv);
1600 aState.addInstruction(MakeUnique<txNumber>(
1601 level, std::move(count), std::move(from), std::move(value),
1602 std::move(format), std::move(groupingSeparator),
1603 std::move(groupingSize)));
1605 aState.pushHandlerTable(gTxIgnoreHandler);
1607 return NS_OK;
1610 static void txFnEndNumber(txStylesheetCompilerState& aState) {
1611 aState.popHandlerTable();
1615 xsl:otherwise
1617 (see xsl:choose)
1619 static nsresult txFnStartOtherwise(int32_t aNamespaceID, nsAtom* aLocalName,
1620 nsAtom* aPrefix,
1621 txStylesheetAttr* aAttributes,
1622 int32_t aAttrCount,
1623 txStylesheetCompilerState& aState) {
1624 aState.pushHandlerTable(gTxTemplateHandler);
1626 return NS_OK;
1629 static void txFnEndOtherwise(txStylesheetCompilerState& aState) {
1630 aState.popHandlerTable();
1631 aState.mHandlerTable = gTxIgnoreHandler; // XXX should be gTxErrorHandler
1635 xsl:param
1637 txCheckParam --+
1638 txPushRTFHandler | --- (for RTF-parameters)
1639 [children] | /
1640 txSetVariable |
1643 static nsresult txFnStartParam(int32_t aNamespaceID, nsAtom* aLocalName,
1644 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1645 int32_t aAttrCount,
1646 txStylesheetCompilerState& aState) {
1647 nsresult rv = NS_OK;
1649 txExpandedName name;
1650 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1651 name);
1652 NS_ENSURE_SUCCESS(rv, rv);
1654 aState.pushPtr(aState.addInstruction(MakeUnique<txCheckParam>(name)),
1655 aState.eCheckParam);
1657 UniquePtr<Expr> select;
1658 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1659 select);
1660 NS_ENSURE_SUCCESS(rv, rv);
1662 UniquePtr<txSetVariable> var =
1663 MakeUnique<txSetVariable>(name, std::move(select));
1664 if (var->mValue) {
1665 // XXX should be gTxErrorHandler?
1666 aState.pushHandlerTable(gTxIgnoreHandler);
1667 } else {
1668 aState.pushHandlerTable(gTxVariableHandler);
1671 pushInstruction(aState, std::move(var));
1673 return NS_OK;
1676 static void txFnEndParam(txStylesheetCompilerState& aState) {
1677 UniquePtr<txSetVariable> var = popInstruction<txSetVariable>(aState);
1678 txHandlerTable* prev = aState.mHandlerTable;
1679 aState.popHandlerTable();
1681 if (prev == gTxVariableHandler) {
1682 // No children were found.
1683 NS_ASSERTION(!var->mValue, "There shouldn't be a select-expression here");
1684 var->mValue = MakeUnique<txLiteralExpr>(u""_ns);
1687 aState.addVariable(var->mName);
1689 aState.addInstruction(std::move(var));
1691 txCheckParam* checkParam =
1692 static_cast<txCheckParam*>(aState.popPtr(aState.eCheckParam));
1693 aState.addGotoTarget(&checkParam->mBailTarget);
1697 xsl:processing-instruction
1699 txPushStringHandler
1700 [children]
1701 txProcessingInstruction
1703 static nsresult txFnStartPI(int32_t aNamespaceID, nsAtom* aLocalName,
1704 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1705 int32_t aAttrCount,
1706 txStylesheetCompilerState& aState) {
1707 aState.addInstruction(MakeUnique<txPushStringHandler>(true));
1709 UniquePtr<Expr> name;
1710 nsresult rv =
1711 getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState, name);
1712 NS_ENSURE_SUCCESS(rv, rv);
1714 pushInstruction(aState, MakeUnique<txProcessingInstruction>(std::move(name)));
1716 return NS_OK;
1719 static void txFnEndPI(txStylesheetCompilerState& aState) {
1720 aState.addInstruction(popInstruction(aState));
1724 xsl:sort
1726 (no instructions)
1728 static nsresult txFnStartSort(int32_t aNamespaceID, nsAtom* aLocalName,
1729 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1730 int32_t aAttrCount,
1731 txStylesheetCompilerState& aState) {
1732 nsresult rv = NS_OK;
1734 UniquePtr<Expr> select;
1735 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1736 select);
1737 NS_ENSURE_SUCCESS(rv, rv);
1739 if (!select) {
1740 UniquePtr<txNodeTest> nt(new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
1741 select = MakeUnique<LocationStep>(nt.release(), LocationStep::SELF_AXIS);
1744 UniquePtr<Expr> lang;
1745 rv =
1746 getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::lang, false, aState, lang);
1747 NS_ENSURE_SUCCESS(rv, rv);
1749 UniquePtr<Expr> dataType;
1750 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::dataType, false, aState,
1751 dataType);
1752 NS_ENSURE_SUCCESS(rv, rv);
1754 UniquePtr<Expr> order;
1755 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::order, false, aState,
1756 order);
1757 NS_ENSURE_SUCCESS(rv, rv);
1759 UniquePtr<Expr> caseOrder;
1760 rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::caseOrder, false, aState,
1761 caseOrder);
1762 NS_ENSURE_SUCCESS(rv, rv);
1764 aState.mSorter->addSort(std::move(select), std::move(lang),
1765 std::move(dataType), std::move(order),
1766 std::move(caseOrder));
1768 aState.pushHandlerTable(gTxIgnoreHandler);
1770 return NS_OK;
1773 static void txFnEndSort(txStylesheetCompilerState& aState) {
1774 aState.popHandlerTable();
1778 xsl:text
1780 [children] (only txText)
1782 static nsresult txFnStartText(int32_t aNamespaceID, nsAtom* aLocalName,
1783 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1784 int32_t aAttrCount,
1785 txStylesheetCompilerState& aState) {
1786 NS_ASSERTION(!aState.mDOE, "nested d-o-e elements should not happen");
1788 nsresult rv = NS_OK;
1789 txThreeState doe;
1790 rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::disableOutputEscaping,
1791 false, aState, doe);
1792 NS_ENSURE_SUCCESS(rv, rv);
1794 aState.mDOE = doe == eTrue;
1796 aState.pushHandlerTable(gTxTextHandler);
1798 return NS_OK;
1801 static void txFnEndText(txStylesheetCompilerState& aState) {
1802 aState.mDOE = false;
1803 aState.popHandlerTable();
1806 static nsresult txFnTextText(const nsAString& aStr,
1807 txStylesheetCompilerState& aState) {
1808 aState.addInstruction(MakeUnique<txText>(aStr, aState.mDOE));
1810 return NS_OK;
1814 xsl:value-of
1816 txValueOf
1818 static nsresult txFnStartValueOf(int32_t aNamespaceID, nsAtom* aLocalName,
1819 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1820 int32_t aAttrCount,
1821 txStylesheetCompilerState& aState) {
1822 nsresult rv = NS_OK;
1824 txThreeState doe;
1825 rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::disableOutputEscaping,
1826 false, aState, doe);
1827 NS_ENSURE_SUCCESS(rv, rv);
1829 UniquePtr<Expr> select;
1830 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true, aState,
1831 select);
1832 NS_ENSURE_SUCCESS(rv, rv);
1834 aState.addInstruction(MakeUnique<txValueOf>(std::move(select), doe == eTrue));
1836 aState.pushHandlerTable(gTxIgnoreHandler);
1838 return NS_OK;
1841 static void txFnEndValueOf(txStylesheetCompilerState& aState) {
1842 aState.popHandlerTable();
1846 xsl:variable
1848 txPushRTFHandler --- (for RTF-parameters)
1849 [children] /
1850 txSetVariable
1852 static nsresult txFnStartVariable(int32_t aNamespaceID, nsAtom* aLocalName,
1853 nsAtom* aPrefix,
1854 txStylesheetAttr* aAttributes,
1855 int32_t aAttrCount,
1856 txStylesheetCompilerState& aState) {
1857 nsresult rv = NS_OK;
1859 txExpandedName name;
1860 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1861 name);
1862 NS_ENSURE_SUCCESS(rv, rv);
1864 UniquePtr<Expr> select;
1865 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1866 select);
1867 NS_ENSURE_SUCCESS(rv, rv);
1869 UniquePtr<txSetVariable> var =
1870 MakeUnique<txSetVariable>(name, std::move(select));
1871 if (var->mValue) {
1872 // XXX should be gTxErrorHandler?
1873 aState.pushHandlerTable(gTxIgnoreHandler);
1874 } else {
1875 aState.pushHandlerTable(gTxVariableHandler);
1878 pushInstruction(aState, std::move(var));
1880 return NS_OK;
1883 static void txFnEndVariable(txStylesheetCompilerState& aState) {
1884 UniquePtr<txSetVariable> var = popInstruction<txSetVariable>(aState);
1886 txHandlerTable* prev = aState.mHandlerTable;
1887 aState.popHandlerTable();
1889 if (prev == gTxVariableHandler) {
1890 // No children were found.
1891 NS_ASSERTION(!var->mValue, "There shouldn't be a select-expression here");
1892 var->mValue = MakeUnique<txLiteralExpr>(u""_ns);
1895 aState.addVariable(var->mName);
1897 aState.addInstruction(std::move(var));
1900 static nsresult txFnStartElementStartRTF(int32_t aNamespaceID,
1901 nsAtom* aLocalName, nsAtom* aPrefix,
1902 txStylesheetAttr* aAttributes,
1903 int32_t aAttrCount,
1904 txStylesheetCompilerState& aState) {
1905 aState.addInstruction(MakeUnique<txPushRTFHandler>());
1907 aState.mHandlerTable = gTxTemplateHandler;
1909 return NS_XSLT_GET_NEW_HANDLER;
1912 static nsresult txFnTextStartRTF(const nsAString& aStr,
1913 txStylesheetCompilerState& aState) {
1914 TX_RETURN_IF_WHITESPACE(aStr, aState);
1916 aState.addInstruction(MakeUnique<txPushRTFHandler>());
1918 aState.mHandlerTable = gTxTemplateHandler;
1920 return NS_XSLT_GET_NEW_HANDLER;
1924 xsl:when
1926 (see xsl:choose)
1928 static nsresult txFnStartWhen(int32_t aNamespaceID, nsAtom* aLocalName,
1929 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1930 int32_t aAttrCount,
1931 txStylesheetCompilerState& aState) {
1932 nsresult rv = NS_OK;
1934 UniquePtr<Expr> test;
1935 rv =
1936 getExprAttr(aAttributes, aAttrCount, nsGkAtoms::test, true, aState, test);
1937 NS_ENSURE_SUCCESS(rv, rv);
1939 aState.pushPtr(aState.addInstruction(
1940 MakeUnique<txConditionalGoto>(std::move(test), nullptr)),
1941 aState.eConditionalGoto);
1943 aState.pushHandlerTable(gTxTemplateHandler);
1945 return NS_OK;
1948 static void txFnEndWhen(txStylesheetCompilerState& aState) {
1949 aState.popHandlerTable();
1950 aState.mChooseGotoList->add(
1951 aState.addInstruction(MakeUnique<txGoTo>(nullptr)));
1953 txConditionalGoto* condGoto =
1954 static_cast<txConditionalGoto*>(aState.popPtr(aState.eConditionalGoto));
1955 aState.addGotoTarget(&condGoto->mTarget);
1959 xsl:with-param
1961 txPushRTFHandler -- for RTF-parameters
1962 [children] /
1963 txSetParam
1965 static nsresult txFnStartWithParam(int32_t aNamespaceID, nsAtom* aLocalName,
1966 nsAtom* aPrefix,
1967 txStylesheetAttr* aAttributes,
1968 int32_t aAttrCount,
1969 txStylesheetCompilerState& aState) {
1970 nsresult rv = NS_OK;
1972 txExpandedName name;
1973 rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1974 name);
1975 NS_ENSURE_SUCCESS(rv, rv);
1977 UniquePtr<Expr> select;
1978 rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1979 select);
1980 NS_ENSURE_SUCCESS(rv, rv);
1982 UniquePtr<txSetParam> var = MakeUnique<txSetParam>(name, std::move(select));
1983 if (var->mValue) {
1984 // XXX should be gTxErrorHandler?
1985 aState.pushHandlerTable(gTxIgnoreHandler);
1986 } else {
1987 aState.pushHandlerTable(gTxVariableHandler);
1990 pushInstruction(aState, std::move(var));
1992 return NS_OK;
1995 static void txFnEndWithParam(txStylesheetCompilerState& aState) {
1996 UniquePtr<txSetParam> var = popInstruction<txSetParam>(aState);
1997 txHandlerTable* prev = aState.mHandlerTable;
1998 aState.popHandlerTable();
2000 if (prev == gTxVariableHandler) {
2001 // No children were found.
2002 NS_ASSERTION(!var->mValue, "There shouldn't be a select-expression here");
2003 var->mValue = MakeUnique<txLiteralExpr>(u""_ns);
2006 aState.addInstruction(std::move(var));
2010 Unknown instruction
2012 [fallbacks] if one or more xsl:fallbacks are found
2014 txErrorInstruction otherwise
2016 static nsresult txFnStartUnknownInstruction(int32_t aNamespaceID,
2017 nsAtom* aLocalName, nsAtom* aPrefix,
2018 txStylesheetAttr* aAttributes,
2019 int32_t aAttrCount,
2020 txStylesheetCompilerState& aState) {
2021 NS_ASSERTION(!aState.mSearchingForFallback,
2022 "bad nesting of unknown-instruction and fallback handlers");
2024 if (aNamespaceID == kNameSpaceID_XSLT && !aState.fcp()) {
2025 return NS_ERROR_XSLT_PARSE_FAILURE;
2028 aState.mSearchingForFallback = true;
2030 aState.pushHandlerTable(gTxFallbackHandler);
2032 return NS_OK;
2035 static void txFnEndUnknownInstruction(txStylesheetCompilerState& aState) {
2036 aState.popHandlerTable();
2038 if (aState.mSearchingForFallback) {
2039 aState.addInstruction(MakeUnique<txErrorInstruction>());
2042 aState.mSearchingForFallback = false;
2046 * Table Datas
2049 struct txHandlerTableData {
2050 txElementHandler mOtherHandler;
2051 txElementHandler mLREHandler;
2052 HandleTextFn mTextHandler;
2055 const txHandlerTableData gTxIgnoreTableData = {
2056 // Other
2057 {0, 0, txFnStartElementIgnore, txFnEndElementIgnore},
2058 // LRE
2059 {0, 0, txFnStartElementIgnore, txFnEndElementIgnore},
2060 // Text
2061 txFnTextIgnore};
2063 const txElementHandler gTxRootElementHandlers[] = {
2064 {kNameSpaceID_XSLT, "stylesheet", txFnStartStylesheet, txFnEndStylesheet},
2065 {kNameSpaceID_XSLT, "transform", txFnStartStylesheet, txFnEndStylesheet}};
2067 const txHandlerTableData gTxRootTableData = {
2068 // Other
2069 {0, 0, txFnStartElementError, txFnEndElementError},
2070 // LRE
2071 {0, 0, txFnStartLREStylesheet, txFnEndLREStylesheet},
2072 // Text
2073 txFnTextError};
2075 const txHandlerTableData gTxEmbedTableData = {
2076 // Other
2077 {0, 0, txFnStartEmbed, txFnEndEmbed},
2078 // LRE
2079 {0, 0, txFnStartEmbed, txFnEndEmbed},
2080 // Text
2081 txFnTextIgnore};
2083 const txElementHandler gTxTopElementHandlers[] = {
2084 {kNameSpaceID_XSLT, "attribute-set", txFnStartAttributeSet,
2085 txFnEndAttributeSet},
2086 {kNameSpaceID_XSLT, "decimal-format", txFnStartDecimalFormat,
2087 txFnEndDecimalFormat},
2088 {kNameSpaceID_XSLT, "include", txFnStartInclude, txFnEndInclude},
2089 {kNameSpaceID_XSLT, "key", txFnStartKey, txFnEndKey},
2090 {kNameSpaceID_XSLT, "namespace-alias", txFnStartNamespaceAlias,
2091 txFnEndNamespaceAlias},
2092 {kNameSpaceID_XSLT, "output", txFnStartOutput, txFnEndOutput},
2093 {kNameSpaceID_XSLT, "param", txFnStartTopVariable, txFnEndTopVariable},
2094 {kNameSpaceID_XSLT, "preserve-space", txFnStartStripSpace,
2095 txFnEndStripSpace},
2096 {kNameSpaceID_XSLT, "strip-space", txFnStartStripSpace, txFnEndStripSpace},
2097 {kNameSpaceID_XSLT, "template", txFnStartTemplate, txFnEndTemplate},
2098 {kNameSpaceID_XSLT, "variable", txFnStartTopVariable, txFnEndTopVariable}};
2100 const txHandlerTableData gTxTopTableData = {
2101 // Other
2102 {0, 0, txFnStartOtherTop, txFnEndOtherTop},
2103 // LRE
2104 {0, 0, txFnStartOtherTop, txFnEndOtherTop},
2105 // Text
2106 txFnTextIgnore};
2108 const txElementHandler gTxTemplateElementHandlers[] = {
2109 {kNameSpaceID_XSLT, "apply-imports", txFnStartApplyImports,
2110 txFnEndApplyImports},
2111 {kNameSpaceID_XSLT, "apply-templates", txFnStartApplyTemplates,
2112 txFnEndApplyTemplates},
2113 {kNameSpaceID_XSLT, "attribute", txFnStartAttribute, txFnEndAttribute},
2114 {kNameSpaceID_XSLT, "call-template", txFnStartCallTemplate,
2115 txFnEndCallTemplate},
2116 {kNameSpaceID_XSLT, "choose", txFnStartChoose, txFnEndChoose},
2117 {kNameSpaceID_XSLT, "comment", txFnStartComment, txFnEndComment},
2118 {kNameSpaceID_XSLT, "copy", txFnStartCopy, txFnEndCopy},
2119 {kNameSpaceID_XSLT, "copy-of", txFnStartCopyOf, txFnEndCopyOf},
2120 {kNameSpaceID_XSLT, "element", txFnStartElement, txFnEndElement},
2121 {kNameSpaceID_XSLT, "fallback", txFnStartElementSetIgnore,
2122 txFnEndElementSetIgnore},
2123 {kNameSpaceID_XSLT, "for-each", txFnStartForEach, txFnEndForEach},
2124 {kNameSpaceID_XSLT, "if", txFnStartIf, txFnEndIf},
2125 {kNameSpaceID_XSLT, "message", txFnStartMessage, txFnEndMessage},
2126 {kNameSpaceID_XSLT, "number", txFnStartNumber, txFnEndNumber},
2127 {kNameSpaceID_XSLT, "processing-instruction", txFnStartPI, txFnEndPI},
2128 {kNameSpaceID_XSLT, "text", txFnStartText, txFnEndText},
2129 {kNameSpaceID_XSLT, "value-of", txFnStartValueOf, txFnEndValueOf},
2130 {kNameSpaceID_XSLT, "variable", txFnStartVariable, txFnEndVariable}};
2132 const txHandlerTableData gTxTemplateTableData = {
2133 // Other
2134 {0, 0, txFnStartUnknownInstruction, txFnEndUnknownInstruction},
2135 // LRE
2136 {0, 0, txFnStartLRE, txFnEndLRE},
2137 // Text
2138 txFnText};
2140 const txHandlerTableData gTxTextTableData = {
2141 // Other
2142 {0, 0, txFnStartElementError, txFnEndElementError},
2143 // LRE
2144 {0, 0, txFnStartElementError, txFnEndElementError},
2145 // Text
2146 txFnTextText};
2148 const txElementHandler gTxApplyTemplatesElementHandlers[] = {
2149 {kNameSpaceID_XSLT, "sort", txFnStartSort, txFnEndSort},
2150 {kNameSpaceID_XSLT, "with-param", txFnStartWithParam, txFnEndWithParam}};
2152 const txHandlerTableData gTxApplyTemplatesTableData = {
2153 // Other
2154 {0, 0, txFnStartElementSetIgnore,
2155 txFnEndElementSetIgnore}, // should this be error?
2156 // LRE
2157 {0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore},
2158 // Text
2159 txFnTextIgnore};
2161 const txElementHandler gTxCallTemplateElementHandlers[] = {
2162 {kNameSpaceID_XSLT, "with-param", txFnStartWithParam, txFnEndWithParam}};
2164 const txHandlerTableData gTxCallTemplateTableData = {
2165 // Other
2166 {0, 0, txFnStartElementSetIgnore,
2167 txFnEndElementSetIgnore}, // should this be error?
2168 // LRE
2169 {0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore},
2170 // Text
2171 txFnTextIgnore};
2173 const txHandlerTableData gTxVariableTableData = {
2174 // Other
2175 {0, 0, txFnStartElementStartRTF, 0},
2176 // LRE
2177 {0, 0, txFnStartElementStartRTF, 0},
2178 // Text
2179 txFnTextStartRTF};
2181 const txElementHandler gTxForEachElementHandlers[] = {
2182 {kNameSpaceID_XSLT, "sort", txFnStartSort, txFnEndSort}};
2184 const txHandlerTableData gTxForEachTableData = {
2185 // Other
2186 {0, 0, txFnStartElementContinueTemplate, 0},
2187 // LRE
2188 {0, 0, txFnStartElementContinueTemplate, 0},
2189 // Text
2190 txFnTextContinueTemplate};
2192 const txHandlerTableData gTxTopVariableTableData = {
2193 // Other
2194 {0, 0, txFnStartElementStartTopVar, 0},
2195 // LRE
2196 {0, 0, txFnStartElementStartTopVar, 0},
2197 // Text
2198 txFnTextStartTopVar};
2200 const txElementHandler gTxChooseElementHandlers[] = {
2201 {kNameSpaceID_XSLT, "otherwise", txFnStartOtherwise, txFnEndOtherwise},
2202 {kNameSpaceID_XSLT, "when", txFnStartWhen, txFnEndWhen}};
2204 const txHandlerTableData gTxChooseTableData = {
2205 // Other
2206 {0, 0, txFnStartElementError, 0},
2207 // LRE
2208 {0, 0, txFnStartElementError, 0},
2209 // Text
2210 txFnTextError};
2212 const txElementHandler gTxParamElementHandlers[] = {
2213 {kNameSpaceID_XSLT, "param", txFnStartParam, txFnEndParam}};
2215 const txHandlerTableData gTxParamTableData = {
2216 // Other
2217 {0, 0, txFnStartElementContinueTemplate, 0},
2218 // LRE
2219 {0, 0, txFnStartElementContinueTemplate, 0},
2220 // Text
2221 txFnTextContinueTemplate};
2223 const txElementHandler gTxImportElementHandlers[] = {
2224 {kNameSpaceID_XSLT, "import", txFnStartImport, txFnEndImport}};
2226 const txHandlerTableData gTxImportTableData = {
2227 // Other
2228 {0, 0, txFnStartElementContinueTopLevel, 0},
2229 // LRE
2230 {0, 0, txFnStartOtherTop, txFnEndOtherTop}, // XXX what should we do here?
2231 // Text
2232 txFnTextIgnore // XXX what should we do here?
2235 const txElementHandler gTxAttributeSetElementHandlers[] = {
2236 {kNameSpaceID_XSLT, "attribute", txFnStartAttribute, txFnEndAttribute}};
2238 const txHandlerTableData gTxAttributeSetTableData = {
2239 // Other
2240 {0, 0, txFnStartElementError, 0},
2241 // LRE
2242 {0, 0, txFnStartElementError, 0},
2243 // Text
2244 txFnTextError};
2246 const txElementHandler gTxFallbackElementHandlers[] = {
2247 {kNameSpaceID_XSLT, "fallback", txFnStartFallback, txFnEndFallback}};
2249 const txHandlerTableData gTxFallbackTableData = {
2250 // Other
2251 {0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore},
2252 // LRE
2253 {0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore},
2254 // Text
2255 txFnTextIgnore};
2258 * txHandlerTable
2260 txHandlerTable::txHandlerTable(const HandleTextFn aTextHandler,
2261 const txElementHandler* aLREHandler,
2262 const txElementHandler* aOtherHandler)
2263 : mTextHandler(aTextHandler),
2264 mLREHandler(aLREHandler),
2265 mOtherHandler(aOtherHandler) {}
2267 nsresult txHandlerTable::init(const txElementHandler* aHandlers,
2268 uint32_t aCount) {
2269 nsresult rv = NS_OK;
2271 uint32_t i;
2272 for (i = 0; i < aCount; ++i) {
2273 RefPtr<nsAtom> nameAtom = NS_Atomize(aHandlers->mLocalName);
2274 txExpandedName name(aHandlers->mNamespaceID, nameAtom);
2275 rv = mHandlers.add(name, aHandlers);
2276 NS_ENSURE_SUCCESS(rv, rv);
2278 ++aHandlers;
2280 return NS_OK;
2283 const txElementHandler* txHandlerTable::find(int32_t aNamespaceID,
2284 nsAtom* aLocalName) {
2285 txExpandedName name(aNamespaceID, aLocalName);
2286 const txElementHandler* handler = mHandlers.get(name);
2287 if (!handler) {
2288 handler = mOtherHandler;
2290 return handler;
2293 #define INIT_HANDLER(_name) \
2294 gTx##_name##Handler = new txHandlerTable( \
2295 gTx##_name##TableData.mTextHandler, &gTx##_name##TableData.mLREHandler, \
2296 &gTx##_name##TableData.mOtherHandler); \
2297 if (!gTx##_name##Handler) return false
2299 #define INIT_HANDLER_WITH_ELEMENT_HANDLERS(_name) \
2300 INIT_HANDLER(_name); \
2302 rv = gTx##_name##Handler->init(gTx##_name##ElementHandlers, \
2303 ArrayLength(gTx##_name##ElementHandlers)); \
2304 if (NS_FAILED(rv)) return false
2306 #define SHUTDOWN_HANDLER(_name) \
2307 delete gTx##_name##Handler; \
2308 gTx##_name##Handler = nullptr
2310 // static
2311 bool txHandlerTable::init() {
2312 nsresult rv = NS_OK;
2314 INIT_HANDLER_WITH_ELEMENT_HANDLERS(Root);
2315 INIT_HANDLER(Embed);
2316 INIT_HANDLER_WITH_ELEMENT_HANDLERS(Top);
2317 INIT_HANDLER(Ignore);
2318 INIT_HANDLER_WITH_ELEMENT_HANDLERS(Template);
2319 INIT_HANDLER(Text);
2320 INIT_HANDLER_WITH_ELEMENT_HANDLERS(ApplyTemplates);
2321 INIT_HANDLER_WITH_ELEMENT_HANDLERS(CallTemplate);
2322 INIT_HANDLER(Variable);
2323 INIT_HANDLER_WITH_ELEMENT_HANDLERS(ForEach);
2324 INIT_HANDLER(TopVariable);
2325 INIT_HANDLER_WITH_ELEMENT_HANDLERS(Choose);
2326 INIT_HANDLER_WITH_ELEMENT_HANDLERS(Param);
2327 INIT_HANDLER_WITH_ELEMENT_HANDLERS(Import);
2328 INIT_HANDLER_WITH_ELEMENT_HANDLERS(AttributeSet);
2329 INIT_HANDLER_WITH_ELEMENT_HANDLERS(Fallback);
2331 return true;
2334 // static
2335 void txHandlerTable::shutdown() {
2336 SHUTDOWN_HANDLER(Root);
2337 SHUTDOWN_HANDLER(Embed);
2338 SHUTDOWN_HANDLER(Top);
2339 SHUTDOWN_HANDLER(Ignore);
2340 SHUTDOWN_HANDLER(Template);
2341 SHUTDOWN_HANDLER(Text);
2342 SHUTDOWN_HANDLER(ApplyTemplates);
2343 SHUTDOWN_HANDLER(CallTemplate);
2344 SHUTDOWN_HANDLER(Variable);
2345 SHUTDOWN_HANDLER(ForEach);
2346 SHUTDOWN_HANDLER(TopVariable);
2347 SHUTDOWN_HANDLER(Choose);
2348 SHUTDOWN_HANDLER(Param);
2349 SHUTDOWN_HANDLER(Import);
2350 SHUTDOWN_HANDLER(AttributeSet);
2351 SHUTDOWN_HANDLER(Fallback);