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/. */
5 
6 #include "txStylesheetCompileHandlers.h"
7 
8 #include <utility>
9 
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"
28 
29 using namespace mozilla;
30 
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;
47 
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);
53 
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)
61 
getStyleAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,int32_t aNamespace,nsAtom * aName,bool aRequired,txStylesheetAttr ** aAttr)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;
71 
72       return NS_OK;
73     }
74   }
75   *aAttr = nullptr;
76 
77   if (aRequired) {
78     // XXX ErrorReport: missing required attribute
79     return NS_ERROR_XSLT_PARSE_FAILURE;
80   }
81 
82   return NS_OK;
83 }
84 
parseUseAttrSets(txStylesheetAttr * aAttributes,int32_t aAttrCount,bool aInXSLTNS,txStylesheetCompilerState & aState)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;
94   }
95 
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);
101 
102     aState.addInstruction(MakeUnique<txInsertAttrSet>(name));
103   }
104   return NS_OK;
105 }
106 
parseExcludeResultPrefixes(txStylesheetAttr * aAttributes,int32_t aAttrCount,int32_t aNamespaceID)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;
115   }
116 
117   // XXX Needs to be implemented.
118 
119   return NS_OK;
120 }
121 
getQNameAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,txExpandedName & aExpName)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;
132   }
133 
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;
138   }
139 
140   return rv;
141 }
142 
getExprAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,UniquePtr<Expr> & aExpr)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;
153   }
154 
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
163       );
164     } else {
165       aExpr = nullptr;
166     }
167     return NS_OK;
168   }
169 
170   return rv;
171 }
172 
getAVTAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,UniquePtr<Expr> & aAVT)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;
183   }
184 
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
193       );
194     } else {
195       aAVT = nullptr;
196     }
197     return NS_OK;
198   }
199 
200   return rv;
201 }
202 
getPatternAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,UniquePtr<txPattern> & aPattern)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;
214   }
215 
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;
221   }
222 
223   return NS_OK;
224 }
225 
getNumberAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,double & aNumber)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;
236   }
237 
238   aNumber = txDouble::toDouble(attr->mValue);
239   if (mozilla::IsNaN(aNumber) && (aRequired || !aState.fcp())) {
240     // XXX ErrorReport: number parse failure
241     return NS_ERROR_XSLT_PARSE_FAILURE;
242   }
243 
244   return NS_OK;
245 }
246 
getAtomAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,nsAtom ** aAtom)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;
256   }
257 
258   *aAtom = NS_Atomize(attr->mValue).take();
259   NS_ENSURE_TRUE(*aAtom, NS_ERROR_OUT_OF_MEMORY);
260 
261   return NS_OK;
262 }
263 
getYesNoAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,txThreeState & aRes)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;
274   }
275 
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;
283   }
284 
285   return NS_OK;
286 }
287 
getCharAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,char16_t & aChar)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;
298   }
299 
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;
305   }
306 
307   return NS_OK;
308 }
309 
pushInstruction(txStylesheetCompilerState & aState,UniquePtr<txInstruction> aInstruction)310 static void pushInstruction(txStylesheetCompilerState& aState,
311                             UniquePtr<txInstruction> aInstruction) {
312   aState.pushObject(aInstruction.release());
313 }
314 
315 template <class T = txInstruction>
popInstruction(txStylesheetCompilerState & aState)316 static UniquePtr<T> popInstruction(txStylesheetCompilerState& aState) {
317   return UniquePtr<T>(static_cast<T*>(aState.popObject()));
318 }
319 
320 /**
321  * Ignore and error handlers
322  */
txFnTextIgnore(const nsAString & aStr,txStylesheetCompilerState & aState)323 static nsresult txFnTextIgnore(const nsAString& aStr,
324                                txStylesheetCompilerState& aState) {
325   return NS_OK;
326 }
327 
txFnTextError(const nsAString & aStr,txStylesheetCompilerState & aState)328 static nsresult txFnTextError(const nsAString& aStr,
329                               txStylesheetCompilerState& aState) {
330   TX_RETURN_IF_WHITESPACE(aStr, aState);
331 
332   return NS_ERROR_XSLT_PARSE_FAILURE;
333 }
334 
clearAttributes(txStylesheetAttr * aAttributes,int32_t aAttrCount)335 void clearAttributes(txStylesheetAttr* aAttributes, int32_t aAttrCount) {
336   int32_t i;
337   for (i = 0; i < aAttrCount; ++i) {
338     aAttributes[i].mLocalName = nullptr;
339   }
340 }
341 
txFnStartElementIgnore(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
349   }
350 
351   return NS_OK;
352 }
353 
txFnEndElementIgnore(txStylesheetCompilerState & aState)354 static void txFnEndElementIgnore(txStylesheetCompilerState& aState) {}
355 
txFnStartElementSetIgnore(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,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);
363   }
364 
365   aState.pushHandlerTable(gTxIgnoreHandler);
366 
367   return NS_OK;
368 }
369 
txFnEndElementSetIgnore(txStylesheetCompilerState & aState)370 static void txFnEndElementSetIgnore(txStylesheetCompilerState& aState) {
371   aState.popHandlerTable();
372 }
373 
txFnStartElementError(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
380 }
381 
txFnEndElementError(txStylesheetCompilerState & aState)382 static void txFnEndElementError(txStylesheetCompilerState& aState) {
383   MOZ_CRASH("txFnEndElementError shouldn't be called");
384 }
385 
386 /**
387  * Root handlers
388  */
txFnStartStylesheet(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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
396 
397   txStylesheetAttr* attr;
398   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
399                              nsGkAtoms::id, false, &attr);
400   NS_ENSURE_SUCCESS(rv, rv);
401 
402   rv = parseExcludeResultPrefixes(aAttributes, aAttrCount, kNameSpaceID_None);
403   NS_ENSURE_SUCCESS(rv, rv);
404 
405   rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
406                     nsGkAtoms::version, true, &attr);
407   NS_ENSURE_SUCCESS(rv, rv);
408 
409   aState.pushHandlerTable(gTxImportHandler);
410 
411   return NS_OK;
412 }
413 
txFnEndStylesheet(txStylesheetCompilerState & aState)414 static void txFnEndStylesheet(txStylesheetCompilerState& aState) {
415   aState.popHandlerTable();
416 }
417 
txFnStartElementContinueTopLevel(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
423 
424   return NS_XSLT_GET_NEW_HANDLER;
425 }
426 
txFnStartLREStylesheet(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
436 
437   txExpandedName nullExpr;
438   double prio = UnspecifiedNaN<double>();
439 
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());
445 
446   aState.pushHandlerTable(gTxTemplateHandler);
447 
448   return txFnStartLRE(aNamespaceID, aLocalName, aPrefix, aAttributes,
449                       aAttrCount, aState);
450 }
451 
txFnEndLREStylesheet(txStylesheetCompilerState & aState)452 static void txFnEndLREStylesheet(txStylesheetCompilerState& aState) {
453   txFnEndLRE(aState);
454 
455   aState.popHandlerTable();
456 
457   aState.addInstruction(MakeUnique<txReturn>());
458 
459   aState.closeInstructionContainer();
460 }
461 
txFnStartEmbed(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
468   }
469   if (aNamespaceID != kNameSpaceID_XSLT ||
470       (aLocalName != nsGkAtoms::stylesheet &&
471        aLocalName != nsGkAtoms::transform)) {
472     return NS_ERROR_XSLT_PARSE_FAILURE;
473   }
474   return txFnStartStylesheet(aNamespaceID, aLocalName, aPrefix, aAttributes,
475                              aAttrCount, aState);
476 }
477 
txFnEndEmbed(txStylesheetCompilerState & aState)478 static void txFnEndEmbed(txStylesheetCompilerState& aState) {
479   if (!aState.handleEmbeddedSheet()) {
480     return;
481   }
482   txFnEndStylesheet(aState);
483   aState.doneEmbedding();
484 }
485 
486 /**
487  * Top handlers
488  */
txFnStartOtherTop(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
497   }
498 
499   aState.pushHandlerTable(gTxIgnoreHandler);
500 
501   return NS_OK;
502 }
503 
txFnEndOtherTop(txStylesheetCompilerState & aState)504 static void txFnEndOtherTop(txStylesheetCompilerState& aState) {
505   aState.popHandlerTable();
506 }
507 
508 // xsl:attribute-set
txFnStartAttributeSet(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
519 
520   UniquePtr<txAttributeSetItem> attrSet(new txAttributeSetItem(name));
521   aState.openInstructionContainer(attrSet.get());
522 
523   aState.addToplevelItem(attrSet.release());
524 
525   rv = parseUseAttrSets(aAttributes, aAttrCount, false, aState);
526   NS_ENSURE_SUCCESS(rv, rv);
527 
528   aState.pushHandlerTable(gTxAttributeSetHandler);
529 
530   return NS_OK;
531 }
532 
txFnEndAttributeSet(txStylesheetCompilerState & aState)533 static void txFnEndAttributeSet(txStylesheetCompilerState& aState) {
534   aState.popHandlerTable();
535 
536   aState.addInstruction(MakeUnique<txReturn>());
537 
538   aState.closeInstructionContainer();
539 }
540 
541 // xsl:decimal-format
txFnStartDecimalFormat(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
552 
553   UniquePtr<txDecimalFormat> format(new txDecimalFormat);
554   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::decimalSeparator, false,
555                    aState, format->mDecimalSeparator);
556   NS_ENSURE_SUCCESS(rv, rv);
557 
558   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSeparator, false,
559                    aState, format->mGroupingSeparator);
560   NS_ENSURE_SUCCESS(rv, rv);
561 
562   txStylesheetAttr* attr = nullptr;
563   rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
564                     nsGkAtoms::infinity, false, &attr);
565   NS_ENSURE_SUCCESS(rv, rv);
566 
567   if (attr) {
568     format->mInfinity = attr->mValue;
569   }
570 
571   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::minusSign, false, aState,
572                    format->mMinusSign);
573   NS_ENSURE_SUCCESS(rv, rv);
574 
575   rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::NaN,
576                     false, &attr);
577   NS_ENSURE_SUCCESS(rv, rv);
578 
579   if (attr) {
580     format->mNaN = attr->mValue;
581   }
582 
583   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::percent, false, aState,
584                    format->mPercent);
585   NS_ENSURE_SUCCESS(rv, rv);
586 
587   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::perMille, false, aState,
588                    format->mPerMille);
589   NS_ENSURE_SUCCESS(rv, rv);
590 
591   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::zeroDigit, false, aState,
592                    format->mZeroDigit);
593   NS_ENSURE_SUCCESS(rv, rv);
594 
595   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::digit, false, aState,
596                    format->mDigit);
597   NS_ENSURE_SUCCESS(rv, rv);
598 
599   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::patternSeparator, false,
600                    aState, format->mPatternSeparator);
601   NS_ENSURE_SUCCESS(rv, rv);
602 
603   rv = aState.mStylesheet->addDecimalFormat(name, std::move(format));
604   NS_ENSURE_SUCCESS(rv, rv);
605 
606   aState.pushHandlerTable(gTxIgnoreHandler);
607 
608   return NS_OK;
609 }
610 
txFnEndDecimalFormat(txStylesheetCompilerState & aState)611 static void txFnEndDecimalFormat(txStylesheetCompilerState& aState) {
612   aState.popHandlerTable();
613 }
614 
615 // xsl:import
txFnStartImport(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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());
624 
625   txStylesheetAttr* attr = nullptr;
626   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
627                              nsGkAtoms::href, true, &attr);
628   NS_ENSURE_SUCCESS(rv, rv);
629 
630   nsAutoString absUri;
631   URIUtils::resolveHref(attr->mValue, aState.mElementContext->mBaseURI, absUri);
632   rv = aState.loadImportedStylesheet(absUri, frame);
633   NS_ENSURE_SUCCESS(rv, rv);
634 
635   aState.pushHandlerTable(gTxIgnoreHandler);
636 
637   return NS_OK;
638 }
639 
txFnEndImport(txStylesheetCompilerState & aState)640 static void txFnEndImport(txStylesheetCompilerState& aState) {
641   aState.popHandlerTable();
642 }
643 
644 // xsl:include
txFnStartInclude(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
653 
654   nsAutoString absUri;
655   URIUtils::resolveHref(attr->mValue, aState.mElementContext->mBaseURI, absUri);
656   rv = aState.loadIncludedStylesheet(absUri);
657   NS_ENSURE_SUCCESS(rv, rv);
658 
659   aState.pushHandlerTable(gTxIgnoreHandler);
660 
661   return NS_OK;
662 }
663 
txFnEndInclude(txStylesheetCompilerState & aState)664 static void txFnEndInclude(txStylesheetCompilerState& aState) {
665   aState.popHandlerTable();
666 }
667 
668 // xsl:key
txFnStartKey(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
678 
679   aState.mDisAllowed = txIParseContext::KEY_FUNCTION;
680 
681   UniquePtr<txPattern> match;
682   rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::match, true, aState,
683                       match);
684   NS_ENSURE_SUCCESS(rv, rv);
685 
686   UniquePtr<Expr> use;
687   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::use, true, aState, use);
688   NS_ENSURE_SUCCESS(rv, rv);
689 
690   aState.mDisAllowed = 0;
691 
692   rv = aState.mStylesheet->addKey(name, std::move(match), std::move(use));
693   NS_ENSURE_SUCCESS(rv, rv);
694 
695   aState.pushHandlerTable(gTxIgnoreHandler);
696 
697   return NS_OK;
698 }
699 
txFnEndKey(txStylesheetCompilerState & aState)700 static void txFnEndKey(txStylesheetCompilerState& aState) {
701   aState.popHandlerTable();
702 }
703 
704 // xsl:namespace-alias
txFnStartNamespaceAlias(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
714 
715   rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
716                     nsGkAtoms::resultPrefix, true, &attr);
717   NS_ENSURE_SUCCESS(rv, rv);
718 
719   // XXX Needs to be implemented.
720 
721   aState.pushHandlerTable(gTxIgnoreHandler);
722 
723   return NS_OK;
724 }
725 
txFnEndNamespaceAlias(txStylesheetCompilerState & aState)726 static void txFnEndNamespaceAlias(txStylesheetCompilerState& aState) {
727   aState.popHandlerTable();
728 }
729 
730 // xsl:output
txFnStartOutput(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
736 
737   UniquePtr<txOutputItem> item(new txOutputItem);
738 
739   txExpandedName methodExpName;
740   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::method, false, aState,
741                     methodExpName);
742   NS_ENSURE_SUCCESS(rv, rv);
743 
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;
756     }
757   }
758 
759   txStylesheetAttr* attr = nullptr;
760   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::version,
761                false, &attr);
762   if (attr) {
763     item->mFormat.mVersion = attr->mValue;
764   }
765 
766   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::encoding,
767                false, &attr);
768   if (attr) {
769     item->mFormat.mEncoding = attr->mValue;
770   }
771 
772   rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::omitXmlDeclaration,
773                     false, aState, item->mFormat.mOmitXMLDeclaration);
774   NS_ENSURE_SUCCESS(rv, rv);
775 
776   rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::standalone, false,
777                     aState, item->mFormat.mStandalone);
778   NS_ENSURE_SUCCESS(rv, rv);
779 
780   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
781                nsGkAtoms::doctypePublic, false, &attr);
782   if (attr) {
783     item->mFormat.mPublicId = attr->mValue;
784   }
785 
786   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
787                nsGkAtoms::doctypeSystem, false, &attr);
788   if (attr) {
789     item->mFormat.mSystemId = attr->mValue;
790   }
791 
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);
801 
802       item->mFormat.mCDATASectionElements.add(qname.release());
803     }
804   }
805 
806   rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::indent, false, aState,
807                     item->mFormat.mIndent);
808   NS_ENSURE_SUCCESS(rv, rv);
809 
810   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::mediaType,
811                false, &attr);
812   if (attr) {
813     item->mFormat.mMediaType = NS_ConvertUTF16toUTF8(attr->mValue);
814   }
815 
816   aState.addToplevelItem(item.release());
817 
818   aState.pushHandlerTable(gTxIgnoreHandler);
819 
820   return NS_OK;
821 }
822 
txFnEndOutput(txStylesheetCompilerState & aState)823 static void txFnEndOutput(txStylesheetCompilerState& aState) {
824   aState.popHandlerTable();
825 }
826 
827 // xsl:strip-space/xsl:preserve-space
txFnStartStripSpace(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
837 
838   bool strip = aLocalName == nsGkAtoms::stripSpace;
839 
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;
856       }
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;
863         }
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;
870         }
871         prefix = localName;
872       }
873       localName = nsGkAtoms::_asterisk;
874     }
875     if (prefix) {
876       ns = aState.mElementContext->mMappings->lookupNamespace(prefix);
877       NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, NS_ERROR_FAILURE);
878     }
879     stripItem->addStripSpaceTest(
880         new txStripSpaceTest(prefix, localName, ns, strip));
881   }
882 
883   aState.addToplevelItem(stripItem.release());
884 
885   aState.pushHandlerTable(gTxIgnoreHandler);
886 
887   return NS_OK;
888 }
889 
txFnEndStripSpace(txStylesheetCompilerState & aState)890 static void txFnEndStripSpace(txStylesheetCompilerState& aState) {
891   aState.popHandlerTable();
892 }
893 
894 // xsl:template
txFnStartTemplate(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
905 
906   txExpandedName mode;
907   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::mode, false, aState,
908                     mode);
909   NS_ENSURE_SUCCESS(rv, rv);
910 
911   double prio = UnspecifiedNaN<double>();
912   rv = getNumberAttr(aAttributes, aAttrCount, nsGkAtoms::priority, false,
913                      aState, prio);
914   NS_ENSURE_SUCCESS(rv, rv);
915 
916   UniquePtr<txPattern> match;
917   rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::match, name.isNull(),
918                       aState, match);
919   NS_ENSURE_SUCCESS(rv, rv);
920 
921   UniquePtr<txTemplateItem> templ(
922       new txTemplateItem(std::move(match), name, mode, prio));
923   aState.openInstructionContainer(templ.get());
924   aState.addToplevelItem(templ.release());
925 
926   aState.pushHandlerTable(gTxParamHandler);
927 
928   return NS_OK;
929 }
930 
txFnEndTemplate(txStylesheetCompilerState & aState)931 static void txFnEndTemplate(txStylesheetCompilerState& aState) {
932   aState.popHandlerTable();
933 
934   aState.addInstruction(MakeUnique<txReturn>());
935 
936   aState.closeInstructionContainer();
937 }
938 
939 // xsl:variable, xsl:param
txFnStartTopVariable(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
950 
951   UniquePtr<Expr> select;
952   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
953                    select);
954   NS_ENSURE_SUCCESS(rv, rv);
955 
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);
960 
961   if (var->mValue) {
962     // XXX should be gTxErrorHandler?
963     aState.pushHandlerTable(gTxIgnoreHandler);
964   } else {
965     aState.pushHandlerTable(gTxTopVariableHandler);
966   }
967 
968   aState.addToplevelItem(var.release());
969 
970   return NS_OK;
971 }
972 
txFnEndTopVariable(txStylesheetCompilerState & aState)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));
978 
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>());
986   }
987 
988   aState.closeInstructionContainer();
989 }
990 
txFnStartElementStartTopVar(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
997 
998   return NS_XSLT_GET_NEW_HANDLER;
999 }
1000 
txFnTextStartTopVar(const nsAString & aStr,txStylesheetCompilerState & aState)1001 static nsresult txFnTextStartTopVar(const nsAString& aStr,
1002                                     txStylesheetCompilerState& aState) {
1003   TX_RETURN_IF_WHITESPACE(aStr, aState);
1004 
1005   aState.mHandlerTable = gTxTemplateHandler;
1006 
1007   return NS_XSLT_GET_NEW_HANDLER;
1008 }
1009 
1010 /**
1011  * Template Handlers
1012  */
1013 
1014 /*
1015   LRE
1016 
1017   txStartLREElement
1018   txInsertAttrSet        one for each qname in xsl:use-attribute-sets
1019   txLREAttribute         one for each attribute
1020   [children]
1021   txEndElement
1022 */
txFnStartLRE(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1028 
1029   aState.addInstruction(
1030       MakeUnique<txStartLREElement>(aNamespaceID, aLocalName, aPrefix));
1031 
1032   rv = parseExcludeResultPrefixes(aAttributes, aAttrCount, kNameSpaceID_XSLT);
1033   NS_ENSURE_SUCCESS(rv, rv);
1034 
1035   rv = parseUseAttrSets(aAttributes, aAttrCount, true, aState);
1036   NS_ENSURE_SUCCESS(rv, rv);
1037 
1038   txStylesheetAttr* attr = nullptr;
1039   int32_t i;
1040   for (i = 0; i < aAttrCount; ++i) {
1041     attr = aAttributes + i;
1042 
1043     if (attr->mNamespaceID == kNameSpaceID_XSLT) {
1044       if (attr->mLocalName == nsGkAtoms::version) {
1045         attr->mLocalName = nullptr;
1046       }
1047 
1048       continue;
1049     }
1050 
1051     UniquePtr<Expr> avt;
1052     rv = txExprParser::createAVT(attr->mValue, &aState, getter_Transfers(avt));
1053     NS_ENSURE_SUCCESS(rv, rv);
1054 
1055     aState.addInstruction(MakeUnique<txLREAttribute>(
1056         attr->mNamespaceID, attr->mLocalName, attr->mPrefix, std::move(avt)));
1057   }
1058 
1059   return NS_OK;
1060 }
1061 
txFnEndLRE(txStylesheetCompilerState & aState)1062 static void txFnEndLRE(txStylesheetCompilerState& aState) {
1063   aState.addInstruction(MakeUnique<txEndElement>());
1064 }
1065 
1066 /*
1067   "LRE text"
1068 
1069   txText
1070 */
txFnText(const nsAString & aStr,txStylesheetCompilerState & aState)1071 static nsresult txFnText(const nsAString& aStr,
1072                          txStylesheetCompilerState& aState) {
1073   TX_RETURN_IF_WHITESPACE(aStr, aState);
1074 
1075   aState.addInstruction(MakeUnique<txText>(aStr, false));
1076 
1077   return NS_OK;
1078 }
1079 
1080 /*
1081   xsl:apply-imports
1082 
1083   txApplyImportsStart
1084   txApplyImportsEnd
1085 */
txFnStartApplyImports(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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>());
1093 
1094   aState.pushHandlerTable(gTxIgnoreHandler);
1095 
1096   return NS_OK;
1097 }
1098 
txFnEndApplyImports(txStylesheetCompilerState & aState)1099 static void txFnEndApplyImports(txStylesheetCompilerState& aState) {
1100   aState.popHandlerTable();
1101 }
1102 
1103 /*
1104   xsl:apply-templates
1105 
1106   txPushParams
1107   [params]
1108   txPushNewContext    -+   (holds <xsl:sort>s)
1109   txApplyTemplate <-+  |
1110   txLoopNodeSet    -+  |
1111   txPopParams        <-+
1112 */
txFnStartApplyTemplates(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1119 
1120   aState.addInstruction(MakeUnique<txPushParams>());
1121 
1122   txExpandedName mode;
1123   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::mode, false, aState,
1124                     mode);
1125   NS_ENSURE_SUCCESS(rv, rv);
1126 
1127   pushInstruction(aState, MakeUnique<txApplyTemplates>(mode));
1128 
1129   UniquePtr<Expr> select;
1130   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1131                    select);
1132   NS_ENSURE_SUCCESS(rv, rv);
1133 
1134   if (!select) {
1135     UniquePtr<txNodeTest> nt(new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
1136     select = MakeUnique<LocationStep>(nt.release(), LocationStep::CHILD_AXIS);
1137   }
1138 
1139   UniquePtr<txPushNewContext> pushcontext(
1140       new txPushNewContext(std::move(select)));
1141   aState.pushSorter(pushcontext.get());
1142   pushInstruction(aState, std::move(pushcontext));
1143 
1144   aState.pushHandlerTable(gTxApplyTemplatesHandler);
1145 
1146   return NS_OK;
1147 }
1148 
txFnEndApplyTemplates(txStylesheetCompilerState & aState)1149 static void txFnEndApplyTemplates(txStylesheetCompilerState& aState) {
1150   aState.popHandlerTable();
1151 
1152   txPushNewContext* pushcontext =
1153       aState.addInstruction(popInstruction<txPushNewContext>(aState));
1154 
1155   aState.popSorter();
1156 
1157   // txApplyTemplates
1158   txInstruction* instr = aState.addInstruction(popInstruction(aState));
1159   aState.addInstruction(MakeUnique<txLoopNodeSet>(instr));
1160 
1161   pushcontext->mBailTarget = aState.addInstruction(MakeUnique<txPopParams>());
1162 }
1163 
1164 /*
1165   xsl:attribute
1166 
1167   txPushStringHandler
1168   [children]
1169   txAttribute
1170 */
txFnStartAttribute(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1177 
1178   aState.addInstruction(MakeUnique<txPushStringHandler>(true));
1179 
1180   UniquePtr<Expr> name;
1181   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState, name);
1182   NS_ENSURE_SUCCESS(rv, rv);
1183 
1184   UniquePtr<Expr> nspace;
1185   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::_namespace, false, aState,
1186                   nspace);
1187   NS_ENSURE_SUCCESS(rv, rv);
1188 
1189   pushInstruction(aState,
1190                   MakeUnique<txAttribute>(std::move(name), std::move(nspace),
1191                                           aState.mElementContext->mMappings));
1192 
1193   // We need to push the template-handler since the current might be
1194   // the attributeset-handler
1195   aState.pushHandlerTable(gTxTemplateHandler);
1196 
1197   return NS_OK;
1198 }
1199 
txFnEndAttribute(txStylesheetCompilerState & aState)1200 static void txFnEndAttribute(txStylesheetCompilerState& aState) {
1201   aState.popHandlerTable();
1202   aState.addInstruction(popInstruction(aState));
1203 }
1204 
1205 /*
1206   xsl:call-template
1207 
1208   txPushParams
1209   [params]
1210   txCallTemplate
1211   txPopParams
1212 */
txFnStartCallTemplate(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1219 
1220   aState.addInstruction(MakeUnique<txPushParams>());
1221 
1222   txExpandedName name;
1223   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1224                     name);
1225   NS_ENSURE_SUCCESS(rv, rv);
1226 
1227   pushInstruction(aState, MakeUnique<txCallTemplate>(name));
1228 
1229   aState.pushHandlerTable(gTxCallTemplateHandler);
1230 
1231   return NS_OK;
1232 }
1233 
txFnEndCallTemplate(txStylesheetCompilerState & aState)1234 static void txFnEndCallTemplate(txStylesheetCompilerState& aState) {
1235   aState.popHandlerTable();
1236 
1237   // txCallTemplate
1238   aState.addInstruction(popInstruction(aState));
1239 
1240   aState.addInstruction(MakeUnique<txPopParams>());
1241 }
1242 
1243 /*
1244   xsl:choose
1245 
1246   txCondotionalGoto      --+        \
1247   [children]               |         | one for each xsl:when
1248   txGoTo           --+     |        /
1249                      |     |
1250   txCondotionalGoto  |   <-+  --+
1251   [children]         |          |
1252   txGoTo           --+          |
1253                      |          |
1254   [children]         |        <-+      for the xsl:otherwise, if there is one
1255                    <-+
1256 */
txFnStartChoose(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1257 static nsresult txFnStartChoose(int32_t aNamespaceID, nsAtom* aLocalName,
1258                                 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1259                                 int32_t aAttrCount,
1260                                 txStylesheetCompilerState& aState) {
1261   aState.pushChooseGotoList();
1262 
1263   aState.pushHandlerTable(gTxChooseHandler);
1264 
1265   return NS_OK;
1266 }
1267 
txFnEndChoose(txStylesheetCompilerState & aState)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);
1274   }
1275 
1276   aState.popChooseGotoList();
1277 }
1278 
1279 /*
1280   xsl:comment
1281 
1282   txPushStringHandler
1283   [children]
1284   txComment
1285 */
txFnStartComment(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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));
1291 
1292   return NS_OK;
1293 }
1294 
txFnEndComment(txStylesheetCompilerState & aState)1295 static void txFnEndComment(txStylesheetCompilerState& aState) {
1296   aState.addInstruction(MakeUnique<txComment>());
1297 }
1298 
1299 /*
1300   xsl:copy
1301 
1302   txCopy          -+
1303   txInsertAttrSet  |     one for each qname in use-attribute-sets
1304   [children]       |
1305   txEndElement     |
1306                  <-+
1307 */
txFnStartCopy(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
1313 
1314   return parseUseAttrSets(aAttributes, aAttrCount, false, aState);
1315 }
1316 
txFnEndCopy(txStylesheetCompilerState & aState)1317 static void txFnEndCopy(txStylesheetCompilerState& aState) {
1318   aState.addInstruction(MakeUnique<txEndElement>());
1319 
1320   txCopy* copy = static_cast<txCopy*>(aState.popPtr(aState.eCopy));
1321   aState.addGotoTarget(&copy->mBailTarget);
1322 }
1323 
1324 /*
1325   xsl:copy-of
1326 
1327   txCopyOf
1328 */
txFnStartCopyOf(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1334 
1335   UniquePtr<Expr> select;
1336   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true, aState,
1337                    select);
1338   NS_ENSURE_SUCCESS(rv, rv);
1339 
1340   aState.addInstruction(MakeUnique<txCopyOf>(std::move(select)));
1341 
1342   aState.pushHandlerTable(gTxIgnoreHandler);
1343 
1344   return NS_OK;
1345 }
1346 
txFnEndCopyOf(txStylesheetCompilerState & aState)1347 static void txFnEndCopyOf(txStylesheetCompilerState& aState) {
1348   aState.popHandlerTable();
1349 }
1350 
1351 /*
1352   xsl:element
1353 
1354   txStartElement
1355   txInsertAttrSet        one for each qname in use-attribute-sets
1356   [children]
1357   txEndElement
1358 */
txFnStartElement(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1364 
1365   UniquePtr<Expr> name;
1366   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState, name);
1367   NS_ENSURE_SUCCESS(rv, rv);
1368 
1369   UniquePtr<Expr> nspace;
1370   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::_namespace, false, aState,
1371                   nspace);
1372   NS_ENSURE_SUCCESS(rv, rv);
1373 
1374   aState.addInstruction(MakeUnique<txStartElement>(
1375       std::move(name), std::move(nspace), aState.mElementContext->mMappings));
1376 
1377   rv = parseUseAttrSets(aAttributes, aAttrCount, false, aState);
1378   NS_ENSURE_SUCCESS(rv, rv);
1379 
1380   return NS_OK;
1381 }
1382 
txFnEndElement(txStylesheetCompilerState & aState)1383 static void txFnEndElement(txStylesheetCompilerState& aState) {
1384   aState.addInstruction(MakeUnique<txEndElement>());
1385 }
1386 
1387 /*
1388     xsl:fallback
1389 
1390     [children]
1391 */
txFnStartFallback(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1398 
1399   aState.pushHandlerTable(gTxTemplateHandler);
1400 
1401   return NS_OK;
1402 }
1403 
txFnEndFallback(txStylesheetCompilerState & aState)1404 static void txFnEndFallback(txStylesheetCompilerState& aState) {
1405   aState.popHandlerTable();
1406 
1407   NS_ASSERTION(!aState.mSearchingForFallback,
1408                "bad nesting of unknown-instruction and fallback handlers");
1409 }
1410 
1411 /*
1412   xsl:for-each
1413 
1414   txPushNewContext            -+    (holds <xsl:sort>s)
1415   txPushNullTemplateRule  <-+  |
1416   [children]                |  |
1417   txLoopNodeSet            -+  |
1418                              <-+
1419 */
txFnStartForEach(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1425 
1426   UniquePtr<Expr> select;
1427   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true, aState,
1428                    select);
1429   NS_ENSURE_SUCCESS(rv, rv);
1430 
1431   txPushNewContext* pushcontext =
1432       aState.addInstruction(MakeUnique<txPushNewContext>(std::move(select)));
1433   aState.pushPtr(pushcontext, aState.ePushNewContext);
1434   aState.pushSorter(pushcontext);
1435 
1436   aState.pushPtr(aState.addInstruction(MakeUnique<txPushNullTemplateRule>()),
1437                  aState.ePushNullTemplateRule);
1438 
1439   aState.pushHandlerTable(gTxForEachHandler);
1440 
1441   return NS_OK;
1442 }
1443 
txFnEndForEach(txStylesheetCompilerState & aState)1444 static void txFnEndForEach(txStylesheetCompilerState& aState) {
1445   aState.popHandlerTable();
1446 
1447   // This is a txPushNullTemplateRule
1448   txInstruction* pnullrule =
1449       static_cast<txInstruction*>(aState.popPtr(aState.ePushNullTemplateRule));
1450 
1451   aState.addInstruction(MakeUnique<txLoopNodeSet>(pnullrule));
1452 
1453   aState.popSorter();
1454   txPushNewContext* pushcontext =
1455       static_cast<txPushNewContext*>(aState.popPtr(aState.ePushNewContext));
1456   aState.addGotoTarget(&pushcontext->mBailTarget);
1457 }
1458 
txFnStartElementContinueTemplate(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1464 
1465   return NS_XSLT_GET_NEW_HANDLER;
1466 }
1467 
txFnTextContinueTemplate(const nsAString & aStr,txStylesheetCompilerState & aState)1468 static nsresult txFnTextContinueTemplate(const nsAString& aStr,
1469                                          txStylesheetCompilerState& aState) {
1470   TX_RETURN_IF_WHITESPACE(aStr, aState);
1471 
1472   aState.mHandlerTable = gTxTemplateHandler;
1473 
1474   return NS_XSLT_GET_NEW_HANDLER;
1475 }
1476 
1477 /*
1478   xsl:if
1479 
1480   txConditionalGoto  -+
1481   [children]          |
1482                     <-+
1483 */
txFnStartIf(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1489 
1490   UniquePtr<Expr> test;
1491   rv =
1492       getExprAttr(aAttributes, aAttrCount, nsGkAtoms::test, true, aState, test);
1493   NS_ENSURE_SUCCESS(rv, rv);
1494 
1495   aState.pushPtr(aState.addInstruction(
1496                      MakeUnique<txConditionalGoto>(std::move(test), nullptr)),
1497                  aState.eConditionalGoto);
1498 
1499   return NS_OK;
1500 }
1501 
txFnEndIf(txStylesheetCompilerState & aState)1502 static void txFnEndIf(txStylesheetCompilerState& aState) {
1503   txConditionalGoto* condGoto =
1504       static_cast<txConditionalGoto*>(aState.popPtr(aState.eConditionalGoto));
1505   aState.addGotoTarget(&condGoto->mTarget);
1506 }
1507 
1508 /*
1509   xsl:message
1510 
1511   txPushStringHandler
1512   [children]
1513   txMessage
1514 */
txFnStartMessage(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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));
1520 
1521   txThreeState term;
1522   nsresult rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::terminate,
1523                              false, aState, term);
1524   NS_ENSURE_SUCCESS(rv, rv);
1525 
1526   pushInstruction(aState, MakeUnique<txMessage>(term == eTrue));
1527 
1528   return NS_OK;
1529 }
1530 
txFnEndMessage(txStylesheetCompilerState & aState)1531 static void txFnEndMessage(txStylesheetCompilerState& aState) {
1532   aState.addInstruction(popInstruction(aState));
1533 }
1534 
1535 /*
1536   xsl:number
1537 
1538   txNumber
1539 */
txFnStartNumber(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1545 
1546   RefPtr<nsAtom> levelAtom;
1547   rv = getAtomAttr(aAttributes, aAttrCount, nsGkAtoms::level, false, aState,
1548                    getter_AddRefs(levelAtom));
1549   NS_ENSURE_SUCCESS(rv, rv);
1550 
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;
1558   }
1559 
1560   UniquePtr<txPattern> count;
1561   rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::count, false, aState,
1562                       count);
1563   NS_ENSURE_SUCCESS(rv, rv);
1564 
1565   UniquePtr<txPattern> from;
1566   rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::from, false, aState,
1567                       from);
1568   NS_ENSURE_SUCCESS(rv, rv);
1569 
1570   UniquePtr<Expr> value;
1571   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::value, false, aState,
1572                    value);
1573   NS_ENSURE_SUCCESS(rv, rv);
1574 
1575   UniquePtr<Expr> format;
1576   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::format, false, aState,
1577                   format);
1578   NS_ENSURE_SUCCESS(rv, rv);
1579 
1580   UniquePtr<Expr> lang;
1581   rv =
1582       getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::lang, false, aState, lang);
1583   NS_ENSURE_SUCCESS(rv, rv);
1584 
1585   UniquePtr<Expr> letterValue;
1586   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::letterValue, false,
1587                   aState, letterValue);
1588   NS_ENSURE_SUCCESS(rv, rv);
1589 
1590   UniquePtr<Expr> groupingSeparator;
1591   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSeparator, false,
1592                   aState, groupingSeparator);
1593   NS_ENSURE_SUCCESS(rv, rv);
1594 
1595   UniquePtr<Expr> groupingSize;
1596   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSize, false,
1597                   aState, groupingSize);
1598   NS_ENSURE_SUCCESS(rv, rv);
1599 
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)));
1604 
1605   aState.pushHandlerTable(gTxIgnoreHandler);
1606 
1607   return NS_OK;
1608 }
1609 
txFnEndNumber(txStylesheetCompilerState & aState)1610 static void txFnEndNumber(txStylesheetCompilerState& aState) {
1611   aState.popHandlerTable();
1612 }
1613 
1614 /*
1615     xsl:otherwise
1616 
1617     (see xsl:choose)
1618 */
txFnStartOtherwise(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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);
1625 
1626   return NS_OK;
1627 }
1628 
txFnEndOtherwise(txStylesheetCompilerState & aState)1629 static void txFnEndOtherwise(txStylesheetCompilerState& aState) {
1630   aState.popHandlerTable();
1631   aState.mHandlerTable = gTxIgnoreHandler;  // XXX should be gTxErrorHandler
1632 }
1633 
1634 /*
1635     xsl:param
1636 
1637     txCheckParam    --+
1638     txPushRTFHandler  |  --- (for RTF-parameters)
1639     [children]        |  /
1640     txSetVariable     |
1641                     <-+
1642 */
txFnStartParam(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1648 
1649   txExpandedName name;
1650   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1651                     name);
1652   NS_ENSURE_SUCCESS(rv, rv);
1653 
1654   aState.pushPtr(aState.addInstruction(MakeUnique<txCheckParam>(name)),
1655                  aState.eCheckParam);
1656 
1657   UniquePtr<Expr> select;
1658   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1659                    select);
1660   NS_ENSURE_SUCCESS(rv, rv);
1661 
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);
1669   }
1670 
1671   pushInstruction(aState, std::move(var));
1672 
1673   return NS_OK;
1674 }
1675 
txFnEndParam(txStylesheetCompilerState & aState)1676 static void txFnEndParam(txStylesheetCompilerState& aState) {
1677   UniquePtr<txSetVariable> var = popInstruction<txSetVariable>(aState);
1678   txHandlerTable* prev = aState.mHandlerTable;
1679   aState.popHandlerTable();
1680 
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);
1685   }
1686 
1687   aState.addVariable(var->mName);
1688 
1689   aState.addInstruction(std::move(var));
1690 
1691   txCheckParam* checkParam =
1692       static_cast<txCheckParam*>(aState.popPtr(aState.eCheckParam));
1693   aState.addGotoTarget(&checkParam->mBailTarget);
1694 }
1695 
1696 /*
1697   xsl:processing-instruction
1698 
1699   txPushStringHandler
1700   [children]
1701   txProcessingInstruction
1702 */
txFnStartPI(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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));
1708 
1709   UniquePtr<Expr> name;
1710   nsresult rv =
1711       getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState, name);
1712   NS_ENSURE_SUCCESS(rv, rv);
1713 
1714   pushInstruction(aState, MakeUnique<txProcessingInstruction>(std::move(name)));
1715 
1716   return NS_OK;
1717 }
1718 
txFnEndPI(txStylesheetCompilerState & aState)1719 static void txFnEndPI(txStylesheetCompilerState& aState) {
1720   aState.addInstruction(popInstruction(aState));
1721 }
1722 
1723 /*
1724     xsl:sort
1725 
1726     (no instructions)
1727 */
txFnStartSort(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1733 
1734   UniquePtr<Expr> select;
1735   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1736                    select);
1737   NS_ENSURE_SUCCESS(rv, rv);
1738 
1739   if (!select) {
1740     UniquePtr<txNodeTest> nt(new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
1741     select = MakeUnique<LocationStep>(nt.release(), LocationStep::SELF_AXIS);
1742   }
1743 
1744   UniquePtr<Expr> lang;
1745   rv =
1746       getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::lang, false, aState, lang);
1747   NS_ENSURE_SUCCESS(rv, rv);
1748 
1749   UniquePtr<Expr> dataType;
1750   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::dataType, false, aState,
1751                   dataType);
1752   NS_ENSURE_SUCCESS(rv, rv);
1753 
1754   UniquePtr<Expr> order;
1755   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::order, false, aState,
1756                   order);
1757   NS_ENSURE_SUCCESS(rv, rv);
1758 
1759   UniquePtr<Expr> caseOrder;
1760   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::caseOrder, false, aState,
1761                   caseOrder);
1762   NS_ENSURE_SUCCESS(rv, rv);
1763 
1764   aState.mSorter->addSort(std::move(select), std::move(lang),
1765                           std::move(dataType), std::move(order),
1766                           std::move(caseOrder));
1767 
1768   aState.pushHandlerTable(gTxIgnoreHandler);
1769 
1770   return NS_OK;
1771 }
1772 
txFnEndSort(txStylesheetCompilerState & aState)1773 static void txFnEndSort(txStylesheetCompilerState& aState) {
1774   aState.popHandlerTable();
1775 }
1776 
1777 /*
1778   xsl:text
1779 
1780   [children]     (only txText)
1781 */
txFnStartText(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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");
1787 
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);
1793 
1794   aState.mDOE = doe == eTrue;
1795 
1796   aState.pushHandlerTable(gTxTextHandler);
1797 
1798   return NS_OK;
1799 }
1800 
txFnEndText(txStylesheetCompilerState & aState)1801 static void txFnEndText(txStylesheetCompilerState& aState) {
1802   aState.mDOE = false;
1803   aState.popHandlerTable();
1804 }
1805 
txFnTextText(const nsAString & aStr,txStylesheetCompilerState & aState)1806 static nsresult txFnTextText(const nsAString& aStr,
1807                              txStylesheetCompilerState& aState) {
1808   aState.addInstruction(MakeUnique<txText>(aStr, aState.mDOE));
1809 
1810   return NS_OK;
1811 }
1812 
1813 /*
1814   xsl:value-of
1815 
1816   txValueOf
1817 */
txFnStartValueOf(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1823 
1824   txThreeState doe;
1825   rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::disableOutputEscaping,
1826                     false, aState, doe);
1827   NS_ENSURE_SUCCESS(rv, rv);
1828 
1829   UniquePtr<Expr> select;
1830   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true, aState,
1831                    select);
1832   NS_ENSURE_SUCCESS(rv, rv);
1833 
1834   aState.addInstruction(MakeUnique<txValueOf>(std::move(select), doe == eTrue));
1835 
1836   aState.pushHandlerTable(gTxIgnoreHandler);
1837 
1838   return NS_OK;
1839 }
1840 
txFnEndValueOf(txStylesheetCompilerState & aState)1841 static void txFnEndValueOf(txStylesheetCompilerState& aState) {
1842   aState.popHandlerTable();
1843 }
1844 
1845 /*
1846     xsl:variable
1847 
1848     txPushRTFHandler     --- (for RTF-parameters)
1849     [children]           /
1850     txSetVariable
1851 */
txFnStartVariable(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1858 
1859   txExpandedName name;
1860   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1861                     name);
1862   NS_ENSURE_SUCCESS(rv, rv);
1863 
1864   UniquePtr<Expr> select;
1865   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1866                    select);
1867   NS_ENSURE_SUCCESS(rv, rv);
1868 
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);
1876   }
1877 
1878   pushInstruction(aState, std::move(var));
1879 
1880   return NS_OK;
1881 }
1882 
txFnEndVariable(txStylesheetCompilerState & aState)1883 static void txFnEndVariable(txStylesheetCompilerState& aState) {
1884   UniquePtr<txSetVariable> var = popInstruction<txSetVariable>(aState);
1885 
1886   txHandlerTable* prev = aState.mHandlerTable;
1887   aState.popHandlerTable();
1888 
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);
1893   }
1894 
1895   aState.addVariable(var->mName);
1896 
1897   aState.addInstruction(std::move(var));
1898 }
1899 
txFnStartElementStartRTF(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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>());
1906 
1907   aState.mHandlerTable = gTxTemplateHandler;
1908 
1909   return NS_XSLT_GET_NEW_HANDLER;
1910 }
1911 
txFnTextStartRTF(const nsAString & aStr,txStylesheetCompilerState & aState)1912 static nsresult txFnTextStartRTF(const nsAString& aStr,
1913                                  txStylesheetCompilerState& aState) {
1914   TX_RETURN_IF_WHITESPACE(aStr, aState);
1915 
1916   aState.addInstruction(MakeUnique<txPushRTFHandler>());
1917 
1918   aState.mHandlerTable = gTxTemplateHandler;
1919 
1920   return NS_XSLT_GET_NEW_HANDLER;
1921 }
1922 
1923 /*
1924     xsl:when
1925 
1926     (see xsl:choose)
1927 */
txFnStartWhen(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1933 
1934   UniquePtr<Expr> test;
1935   rv =
1936       getExprAttr(aAttributes, aAttrCount, nsGkAtoms::test, true, aState, test);
1937   NS_ENSURE_SUCCESS(rv, rv);
1938 
1939   aState.pushPtr(aState.addInstruction(
1940                      MakeUnique<txConditionalGoto>(std::move(test), nullptr)),
1941                  aState.eConditionalGoto);
1942 
1943   aState.pushHandlerTable(gTxTemplateHandler);
1944 
1945   return NS_OK;
1946 }
1947 
txFnEndWhen(txStylesheetCompilerState & aState)1948 static void txFnEndWhen(txStylesheetCompilerState& aState) {
1949   aState.popHandlerTable();
1950   aState.mChooseGotoList->add(
1951       aState.addInstruction(MakeUnique<txGoTo>(nullptr)));
1952 
1953   txConditionalGoto* condGoto =
1954       static_cast<txConditionalGoto*>(aState.popPtr(aState.eConditionalGoto));
1955   aState.addGotoTarget(&condGoto->mTarget);
1956 }
1957 
1958 /*
1959     xsl:with-param
1960 
1961     txPushRTFHandler   -- for RTF-parameters
1962     [children]         /
1963     txSetParam
1964 */
txFnStartWithParam(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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;
1971 
1972   txExpandedName name;
1973   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1974                     name);
1975   NS_ENSURE_SUCCESS(rv, rv);
1976 
1977   UniquePtr<Expr> select;
1978   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1979                    select);
1980   NS_ENSURE_SUCCESS(rv, rv);
1981 
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);
1988   }
1989 
1990   pushInstruction(aState, std::move(var));
1991 
1992   return NS_OK;
1993 }
1994 
txFnEndWithParam(txStylesheetCompilerState & aState)1995 static void txFnEndWithParam(txStylesheetCompilerState& aState) {
1996   UniquePtr<txSetParam> var = popInstruction<txSetParam>(aState);
1997   txHandlerTable* prev = aState.mHandlerTable;
1998   aState.popHandlerTable();
1999 
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);
2004   }
2005 
2006   aState.addInstruction(std::move(var));
2007 }
2008 
2009 /*
2010     Unknown instruction
2011 
2012     [fallbacks]           if one or more xsl:fallbacks are found
2013     or
2014     txErrorInstruction    otherwise
2015 */
txFnStartUnknownInstruction(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)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");
2023 
2024   if (aNamespaceID == kNameSpaceID_XSLT && !aState.fcp()) {
2025     return NS_ERROR_XSLT_PARSE_FAILURE;
2026   }
2027 
2028   aState.mSearchingForFallback = true;
2029 
2030   aState.pushHandlerTable(gTxFallbackHandler);
2031 
2032   return NS_OK;
2033 }
2034 
txFnEndUnknownInstruction(txStylesheetCompilerState & aState)2035 static void txFnEndUnknownInstruction(txStylesheetCompilerState& aState) {
2036   aState.popHandlerTable();
2037 
2038   if (aState.mSearchingForFallback) {
2039     aState.addInstruction(MakeUnique<txErrorInstruction>());
2040   }
2041 
2042   aState.mSearchingForFallback = false;
2043 }
2044 
2045 /**
2046  * Table Datas
2047  */
2048 
2049 struct txHandlerTableData {
2050   txElementHandler mOtherHandler;
2051   txElementHandler mLREHandler;
2052   HandleTextFn mTextHandler;
2053 };
2054 
2055 const txHandlerTableData gTxIgnoreTableData = {
2056     // Other
2057     {0, 0, txFnStartElementIgnore, txFnEndElementIgnore},
2058     // LRE
2059     {0, 0, txFnStartElementIgnore, txFnEndElementIgnore},
2060     // Text
2061     txFnTextIgnore};
2062 
2063 const txElementHandler gTxRootElementHandlers[] = {
2064     {kNameSpaceID_XSLT, "stylesheet", txFnStartStylesheet, txFnEndStylesheet},
2065     {kNameSpaceID_XSLT, "transform", txFnStartStylesheet, txFnEndStylesheet}};
2066 
2067 const txHandlerTableData gTxRootTableData = {
2068     // Other
2069     {0, 0, txFnStartElementError, txFnEndElementError},
2070     // LRE
2071     {0, 0, txFnStartLREStylesheet, txFnEndLREStylesheet},
2072     // Text
2073     txFnTextError};
2074 
2075 const txHandlerTableData gTxEmbedTableData = {
2076     // Other
2077     {0, 0, txFnStartEmbed, txFnEndEmbed},
2078     // LRE
2079     {0, 0, txFnStartEmbed, txFnEndEmbed},
2080     // Text
2081     txFnTextIgnore};
2082 
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}};
2099 
2100 const txHandlerTableData gTxTopTableData = {
2101     // Other
2102     {0, 0, txFnStartOtherTop, txFnEndOtherTop},
2103     // LRE
2104     {0, 0, txFnStartOtherTop, txFnEndOtherTop},
2105     // Text
2106     txFnTextIgnore};
2107 
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}};
2131 
2132 const txHandlerTableData gTxTemplateTableData = {
2133     // Other
2134     {0, 0, txFnStartUnknownInstruction, txFnEndUnknownInstruction},
2135     // LRE
2136     {0, 0, txFnStartLRE, txFnEndLRE},
2137     // Text
2138     txFnText};
2139 
2140 const txHandlerTableData gTxTextTableData = {
2141     // Other
2142     {0, 0, txFnStartElementError, txFnEndElementError},
2143     // LRE
2144     {0, 0, txFnStartElementError, txFnEndElementError},
2145     // Text
2146     txFnTextText};
2147 
2148 const txElementHandler gTxApplyTemplatesElementHandlers[] = {
2149     {kNameSpaceID_XSLT, "sort", txFnStartSort, txFnEndSort},
2150     {kNameSpaceID_XSLT, "with-param", txFnStartWithParam, txFnEndWithParam}};
2151 
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};
2160 
2161 const txElementHandler gTxCallTemplateElementHandlers[] = {
2162     {kNameSpaceID_XSLT, "with-param", txFnStartWithParam, txFnEndWithParam}};
2163 
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};
2172 
2173 const txHandlerTableData gTxVariableTableData = {
2174     // Other
2175     {0, 0, txFnStartElementStartRTF, 0},
2176     // LRE
2177     {0, 0, txFnStartElementStartRTF, 0},
2178     // Text
2179     txFnTextStartRTF};
2180 
2181 const txElementHandler gTxForEachElementHandlers[] = {
2182     {kNameSpaceID_XSLT, "sort", txFnStartSort, txFnEndSort}};
2183 
2184 const txHandlerTableData gTxForEachTableData = {
2185     // Other
2186     {0, 0, txFnStartElementContinueTemplate, 0},
2187     // LRE
2188     {0, 0, txFnStartElementContinueTemplate, 0},
2189     // Text
2190     txFnTextContinueTemplate};
2191 
2192 const txHandlerTableData gTxTopVariableTableData = {
2193     // Other
2194     {0, 0, txFnStartElementStartTopVar, 0},
2195     // LRE
2196     {0, 0, txFnStartElementStartTopVar, 0},
2197     // Text
2198     txFnTextStartTopVar};
2199 
2200 const txElementHandler gTxChooseElementHandlers[] = {
2201     {kNameSpaceID_XSLT, "otherwise", txFnStartOtherwise, txFnEndOtherwise},
2202     {kNameSpaceID_XSLT, "when", txFnStartWhen, txFnEndWhen}};
2203 
2204 const txHandlerTableData gTxChooseTableData = {
2205     // Other
2206     {0, 0, txFnStartElementError, 0},
2207     // LRE
2208     {0, 0, txFnStartElementError, 0},
2209     // Text
2210     txFnTextError};
2211 
2212 const txElementHandler gTxParamElementHandlers[] = {
2213     {kNameSpaceID_XSLT, "param", txFnStartParam, txFnEndParam}};
2214 
2215 const txHandlerTableData gTxParamTableData = {
2216     // Other
2217     {0, 0, txFnStartElementContinueTemplate, 0},
2218     // LRE
2219     {0, 0, txFnStartElementContinueTemplate, 0},
2220     // Text
2221     txFnTextContinueTemplate};
2222 
2223 const txElementHandler gTxImportElementHandlers[] = {
2224     {kNameSpaceID_XSLT, "import", txFnStartImport, txFnEndImport}};
2225 
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?
2233 };
2234 
2235 const txElementHandler gTxAttributeSetElementHandlers[] = {
2236     {kNameSpaceID_XSLT, "attribute", txFnStartAttribute, txFnEndAttribute}};
2237 
2238 const txHandlerTableData gTxAttributeSetTableData = {
2239     // Other
2240     {0, 0, txFnStartElementError, 0},
2241     // LRE
2242     {0, 0, txFnStartElementError, 0},
2243     // Text
2244     txFnTextError};
2245 
2246 const txElementHandler gTxFallbackElementHandlers[] = {
2247     {kNameSpaceID_XSLT, "fallback", txFnStartFallback, txFnEndFallback}};
2248 
2249 const txHandlerTableData gTxFallbackTableData = {
2250     // Other
2251     {0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore},
2252     // LRE
2253     {0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore},
2254     // Text
2255     txFnTextIgnore};
2256 
2257 /**
2258  * txHandlerTable
2259  */
txHandlerTable(const HandleTextFn aTextHandler,const txElementHandler * aLREHandler,const txElementHandler * aOtherHandler)2260 txHandlerTable::txHandlerTable(const HandleTextFn aTextHandler,
2261                                const txElementHandler* aLREHandler,
2262                                const txElementHandler* aOtherHandler)
2263     : mTextHandler(aTextHandler),
2264       mLREHandler(aLREHandler),
2265       mOtherHandler(aOtherHandler) {}
2266 
init(const txElementHandler * aHandlers,uint32_t aCount)2267 nsresult txHandlerTable::init(const txElementHandler* aHandlers,
2268                               uint32_t aCount) {
2269   nsresult rv = NS_OK;
2270 
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);
2277 
2278     ++aHandlers;
2279   }
2280   return NS_OK;
2281 }
2282 
find(int32_t aNamespaceID,nsAtom * aLocalName)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;
2289   }
2290   return handler;
2291 }
2292 
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
2298 
2299 #define INIT_HANDLER_WITH_ELEMENT_HANDLERS(_name)                           \
2300   INIT_HANDLER(_name);                                                      \
2301                                                                             \
2302   rv = gTx##_name##Handler->init(gTx##_name##ElementHandlers,               \
2303                                  ArrayLength(gTx##_name##ElementHandlers)); \
2304   if (NS_FAILED(rv)) return false
2305 
2306 #define SHUTDOWN_HANDLER(_name) \
2307   delete gTx##_name##Handler;   \
2308   gTx##_name##Handler = nullptr
2309 
2310 // static
init()2311 bool txHandlerTable::init() {
2312   nsresult rv = NS_OK;
2313 
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);
2330 
2331   return true;
2332 }
2333 
2334 // static
shutdown()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);
2352 }
2353