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 "nsGkAtoms.h"
13 #include "nsWhitespaceTokenizer.h"
14 #include "txCore.h"
15 #include "txInstructions.h"
16 #include "txNamespaceMap.h"
17 #include "txPatternParser.h"
18 #include "txStringUtils.h"
19 #include "txStylesheet.h"
20 #include "txStylesheetCompiler.h"
21 #include "txToplevelItems.h"
22 #include "txURIUtils.h"
23 #include "txXSLTFunctions.h"
24 
25 using namespace mozilla;
26 
27 txHandlerTable* gTxIgnoreHandler = 0;
28 txHandlerTable* gTxRootHandler = 0;
29 txHandlerTable* gTxEmbedHandler = 0;
30 txHandlerTable* gTxTopHandler = 0;
31 txHandlerTable* gTxTemplateHandler = 0;
32 txHandlerTable* gTxTextHandler = 0;
33 txHandlerTable* gTxApplyTemplatesHandler = 0;
34 txHandlerTable* gTxCallTemplateHandler = 0;
35 txHandlerTable* gTxVariableHandler = 0;
36 txHandlerTable* gTxForEachHandler = 0;
37 txHandlerTable* gTxTopVariableHandler = 0;
38 txHandlerTable* gTxChooseHandler = 0;
39 txHandlerTable* gTxParamHandler = 0;
40 txHandlerTable* gTxImportHandler = 0;
41 txHandlerTable* gTxAttributeSetHandler = 0;
42 txHandlerTable* gTxFallbackHandler = 0;
43 
44 static nsresult txFnStartLRE(int32_t aNamespaceID, nsAtom* aLocalName,
45                              nsAtom* aPrefix, txStylesheetAttr* aAttributes,
46                              int32_t aAttrCount,
47                              txStylesheetCompilerState& aState);
48 static nsresult txFnEndLRE(txStylesheetCompilerState& aState);
49 
50 #define TX_RETURN_IF_WHITESPACE(_str, _state)           \
51   do {                                                  \
52     if (!_state.mElementContext->mPreserveWhitespace && \
53         XMLUtils::isWhitespace(_str)) {                 \
54       return NS_OK;                                     \
55     }                                                   \
56   } while (0)
57 
getStyleAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,int32_t aNamespace,nsAtom * aName,bool aRequired,txStylesheetAttr ** aAttr)58 static nsresult getStyleAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
59                              int32_t aNamespace, nsAtom* aName, bool aRequired,
60                              txStylesheetAttr** aAttr) {
61   int32_t i;
62   for (i = 0; i < aAttrCount; ++i) {
63     txStylesheetAttr* attr = aAttributes + i;
64     if (attr->mNamespaceID == aNamespace && attr->mLocalName == aName) {
65       attr->mLocalName = nullptr;
66       *aAttr = attr;
67 
68       return NS_OK;
69     }
70   }
71   *aAttr = nullptr;
72 
73   if (aRequired) {
74     // XXX ErrorReport: missing required attribute
75     return NS_ERROR_XSLT_PARSE_FAILURE;
76   }
77 
78   return NS_OK;
79 }
80 
parseUseAttrSets(txStylesheetAttr * aAttributes,int32_t aAttrCount,bool aInXSLTNS,txStylesheetCompilerState & aState)81 static nsresult parseUseAttrSets(txStylesheetAttr* aAttributes,
82                                  int32_t aAttrCount, bool aInXSLTNS,
83                                  txStylesheetCompilerState& aState) {
84   txStylesheetAttr* attr = nullptr;
85   nsresult rv = getStyleAttr(aAttributes, aAttrCount,
86                              aInXSLTNS ? kNameSpaceID_XSLT : kNameSpaceID_None,
87                              nsGkAtoms::useAttributeSets, false, &attr);
88   if (!attr) {
89     return rv;
90   }
91 
92   nsWhitespaceTokenizer tok(attr->mValue);
93   while (tok.hasMoreTokens()) {
94     txExpandedName name;
95     rv = name.init(tok.nextToken(), aState.mElementContext->mMappings, false);
96     NS_ENSURE_SUCCESS(rv, rv);
97 
98     UniquePtr<txInstruction> instr(new txInsertAttrSet(name));
99     aState.addInstruction(std::move(instr));
100   }
101   return NS_OK;
102 }
103 
parseExcludeResultPrefixes(txStylesheetAttr * aAttributes,int32_t aAttrCount,int32_t aNamespaceID)104 static nsresult parseExcludeResultPrefixes(txStylesheetAttr* aAttributes,
105                                            int32_t aAttrCount,
106                                            int32_t aNamespaceID) {
107   txStylesheetAttr* attr = nullptr;
108   nsresult rv = getStyleAttr(aAttributes, aAttrCount, aNamespaceID,
109                              nsGkAtoms::excludeResultPrefixes, false, &attr);
110   if (!attr) {
111     return rv;
112   }
113 
114   // XXX Needs to be implemented.
115 
116   return NS_OK;
117 }
118 
getQNameAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,txExpandedName & aExpName)119 static nsresult getQNameAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
120                              nsAtom* aName, bool aRequired,
121                              txStylesheetCompilerState& aState,
122                              txExpandedName& aExpName) {
123   aExpName.reset();
124   txStylesheetAttr* attr = nullptr;
125   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
126                              aRequired, &attr);
127   if (!attr) {
128     return rv;
129   }
130 
131   rv = aExpName.init(attr->mValue, aState.mElementContext->mMappings, false);
132   if (!aRequired && NS_FAILED(rv) && aState.fcp()) {
133     aExpName.reset();
134     rv = NS_OK;
135   }
136 
137   return rv;
138 }
139 
getExprAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,UniquePtr<Expr> & aExpr)140 static nsresult getExprAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
141                             nsAtom* aName, bool aRequired,
142                             txStylesheetCompilerState& aState,
143                             UniquePtr<Expr>& aExpr) {
144   aExpr = nullptr;
145   txStylesheetAttr* attr = nullptr;
146   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
147                              aRequired, &attr);
148   if (!attr) {
149     return rv;
150   }
151 
152   rv = txExprParser::createExpr(attr->mValue, &aState, getter_Transfers(aExpr));
153   if (NS_FAILED(rv) && aState.ignoreError(rv)) {
154     // use default value in fcp for not required exprs
155     if (aRequired) {
156       aExpr = MakeUnique<txErrorExpr>(
157 #ifdef TX_TO_STRING
158           attr->mValue
159 #endif
160       );
161     } else {
162       aExpr = nullptr;
163     }
164     return NS_OK;
165   }
166 
167   return rv;
168 }
169 
getAVTAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,UniquePtr<Expr> & aAVT)170 static nsresult getAVTAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
171                            nsAtom* aName, bool aRequired,
172                            txStylesheetCompilerState& aState,
173                            UniquePtr<Expr>& aAVT) {
174   aAVT = nullptr;
175   txStylesheetAttr* attr = nullptr;
176   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
177                              aRequired, &attr);
178   if (!attr) {
179     return rv;
180   }
181 
182   rv = txExprParser::createAVT(attr->mValue, &aState, getter_Transfers(aAVT));
183   if (NS_FAILED(rv) && aState.fcp()) {
184     // use default value in fcp for not required exprs
185     if (aRequired) {
186       aAVT = MakeUnique<txErrorExpr>(
187 #ifdef TX_TO_STRING
188           attr->mValue
189 #endif
190       );
191     } else {
192       aAVT = nullptr;
193     }
194     return NS_OK;
195   }
196 
197   return rv;
198 }
199 
getPatternAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,UniquePtr<txPattern> & aPattern)200 static nsresult getPatternAttr(txStylesheetAttr* aAttributes,
201                                int32_t aAttrCount, nsAtom* aName,
202                                bool aRequired,
203                                txStylesheetCompilerState& aState,
204                                UniquePtr<txPattern>& aPattern) {
205   aPattern = nullptr;
206   txStylesheetAttr* attr = nullptr;
207   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
208                              aRequired, &attr);
209   if (!attr) {
210     return rv;
211   }
212 
213   rv = txPatternParser::createPattern(attr->mValue, &aState,
214                                       getter_Transfers(aPattern));
215   if (NS_FAILED(rv) && (aRequired || !aState.ignoreError(rv))) {
216     // XXX ErrorReport: XSLT-Pattern parse failure
217     return rv;
218   }
219 
220   return NS_OK;
221 }
222 
getNumberAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,double & aNumber)223 static nsresult getNumberAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
224                               nsAtom* aName, bool aRequired,
225                               txStylesheetCompilerState& aState,
226                               double& aNumber) {
227   aNumber = UnspecifiedNaN<double>();
228   txStylesheetAttr* attr = nullptr;
229   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
230                              aRequired, &attr);
231   if (!attr) {
232     return rv;
233   }
234 
235   aNumber = txDouble::toDouble(attr->mValue);
236   if (mozilla::IsNaN(aNumber) && (aRequired || !aState.fcp())) {
237     // XXX ErrorReport: number parse failure
238     return NS_ERROR_XSLT_PARSE_FAILURE;
239   }
240 
241   return NS_OK;
242 }
243 
getAtomAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,nsAtom ** aAtom)244 static nsresult getAtomAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
245                             nsAtom* aName, bool aRequired,
246                             txStylesheetCompilerState& aState, nsAtom** aAtom) {
247   *aAtom = nullptr;
248   txStylesheetAttr* attr = nullptr;
249   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
250                              aRequired, &attr);
251   if (!attr) {
252     return rv;
253   }
254 
255   *aAtom = NS_Atomize(attr->mValue).take();
256   NS_ENSURE_TRUE(*aAtom, NS_ERROR_OUT_OF_MEMORY);
257 
258   return NS_OK;
259 }
260 
getYesNoAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,txThreeState & aRes)261 static nsresult getYesNoAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
262                              nsAtom* aName, bool aRequired,
263                              txStylesheetCompilerState& aState,
264                              txThreeState& aRes) {
265   aRes = eNotSet;
266   RefPtr<nsAtom> atom;
267   nsresult rv = getAtomAttr(aAttributes, aAttrCount, aName, aRequired, aState,
268                             getter_AddRefs(atom));
269   if (!atom) {
270     return rv;
271   }
272 
273   if (atom == nsGkAtoms::yes) {
274     aRes = eTrue;
275   } else if (atom == nsGkAtoms::no) {
276     aRes = eFalse;
277   } else if (aRequired || !aState.fcp()) {
278     // XXX ErrorReport: unknown values
279     return NS_ERROR_XSLT_PARSE_FAILURE;
280   }
281 
282   return NS_OK;
283 }
284 
getCharAttr(txStylesheetAttr * aAttributes,int32_t aAttrCount,nsAtom * aName,bool aRequired,txStylesheetCompilerState & aState,char16_t & aChar)285 static nsresult getCharAttr(txStylesheetAttr* aAttributes, int32_t aAttrCount,
286                             nsAtom* aName, bool aRequired,
287                             txStylesheetCompilerState& aState,
288                             char16_t& aChar) {
289   // Don't reset aChar since it contains the default value
290   txStylesheetAttr* attr = nullptr;
291   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, aName,
292                              aRequired, &attr);
293   if (!attr) {
294     return rv;
295   }
296 
297   if (attr->mValue.Length() == 1) {
298     aChar = attr->mValue.CharAt(0);
299   } else if (aRequired || !aState.fcp()) {
300     // XXX ErrorReport: not a character
301     return NS_ERROR_XSLT_PARSE_FAILURE;
302   }
303 
304   return NS_OK;
305 }
306 
307 /**
308  * Ignore and error handlers
309  */
txFnTextIgnore(const nsAString & aStr,txStylesheetCompilerState & aState)310 static nsresult txFnTextIgnore(const nsAString& aStr,
311                                txStylesheetCompilerState& aState) {
312   return NS_OK;
313 }
314 
txFnTextError(const nsAString & aStr,txStylesheetCompilerState & aState)315 static nsresult txFnTextError(const nsAString& aStr,
316                               txStylesheetCompilerState& aState) {
317   TX_RETURN_IF_WHITESPACE(aStr, aState);
318 
319   return NS_ERROR_XSLT_PARSE_FAILURE;
320 }
321 
clearAttributes(txStylesheetAttr * aAttributes,int32_t aAttrCount)322 void clearAttributes(txStylesheetAttr* aAttributes, int32_t aAttrCount) {
323   int32_t i;
324   for (i = 0; i < aAttrCount; ++i) {
325     aAttributes[i].mLocalName = nullptr;
326   }
327 }
328 
txFnStartElementIgnore(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)329 static nsresult txFnStartElementIgnore(int32_t aNamespaceID, nsAtom* aLocalName,
330                                        nsAtom* aPrefix,
331                                        txStylesheetAttr* aAttributes,
332                                        int32_t aAttrCount,
333                                        txStylesheetCompilerState& aState) {
334   if (!aState.fcp()) {
335     clearAttributes(aAttributes, aAttrCount);
336   }
337 
338   return NS_OK;
339 }
340 
txFnEndElementIgnore(txStylesheetCompilerState & aState)341 static nsresult txFnEndElementIgnore(txStylesheetCompilerState& aState) {
342   return NS_OK;
343 }
344 
txFnStartElementSetIgnore(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)345 static nsresult txFnStartElementSetIgnore(int32_t aNamespaceID,
346                                           nsAtom* aLocalName, nsAtom* aPrefix,
347                                           txStylesheetAttr* aAttributes,
348                                           int32_t aAttrCount,
349                                           txStylesheetCompilerState& aState) {
350   if (!aState.fcp()) {
351     clearAttributes(aAttributes, aAttrCount);
352   }
353 
354   return aState.pushHandlerTable(gTxIgnoreHandler);
355 }
356 
txFnEndElementSetIgnore(txStylesheetCompilerState & aState)357 static nsresult txFnEndElementSetIgnore(txStylesheetCompilerState& aState) {
358   aState.popHandlerTable();
359   return NS_OK;
360 }
361 
txFnStartElementError(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)362 static nsresult txFnStartElementError(int32_t aNamespaceID, nsAtom* aLocalName,
363                                       nsAtom* aPrefix,
364                                       txStylesheetAttr* aAttributes,
365                                       int32_t aAttrCount,
366                                       txStylesheetCompilerState& aState) {
367   return NS_ERROR_XSLT_PARSE_FAILURE;
368 }
369 
txFnEndElementError(txStylesheetCompilerState & aState)370 static nsresult txFnEndElementError(txStylesheetCompilerState& aState) {
371   NS_ERROR("txFnEndElementError shouldn't be called");
372   return NS_ERROR_XSLT_PARSE_FAILURE;
373 }
374 
375 /**
376  * Root handlers
377  */
txFnStartStylesheet(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)378 static nsresult txFnStartStylesheet(int32_t aNamespaceID, nsAtom* aLocalName,
379                                     nsAtom* aPrefix,
380                                     txStylesheetAttr* aAttributes,
381                                     int32_t aAttrCount,
382                                     txStylesheetCompilerState& aState) {
383   // extension-element-prefixes is handled in
384   // txStylesheetCompiler::startElementInternal
385 
386   txStylesheetAttr* attr;
387   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
388                              nsGkAtoms::id, false, &attr);
389   NS_ENSURE_SUCCESS(rv, rv);
390 
391   rv = parseExcludeResultPrefixes(aAttributes, aAttrCount, kNameSpaceID_None);
392   NS_ENSURE_SUCCESS(rv, rv);
393 
394   rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
395                     nsGkAtoms::version, true, &attr);
396   NS_ENSURE_SUCCESS(rv, rv);
397 
398   return aState.pushHandlerTable(gTxImportHandler);
399 }
400 
txFnEndStylesheet(txStylesheetCompilerState & aState)401 static nsresult txFnEndStylesheet(txStylesheetCompilerState& aState) {
402   aState.popHandlerTable();
403   return NS_OK;
404 }
405 
txFnStartElementContinueTopLevel(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)406 static nsresult txFnStartElementContinueTopLevel(
407     int32_t aNamespaceID, nsAtom* aLocalName, nsAtom* aPrefix,
408     txStylesheetAttr* aAttributes, int32_t aAttrCount,
409     txStylesheetCompilerState& aState) {
410   aState.mHandlerTable = gTxTopHandler;
411 
412   return NS_XSLT_GET_NEW_HANDLER;
413 }
414 
txFnStartLREStylesheet(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)415 static nsresult txFnStartLREStylesheet(int32_t aNamespaceID, nsAtom* aLocalName,
416                                        nsAtom* aPrefix,
417                                        txStylesheetAttr* aAttributes,
418                                        int32_t aAttrCount,
419                                        txStylesheetCompilerState& aState) {
420   txStylesheetAttr* attr;
421   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_XSLT,
422                              nsGkAtoms::version, true, &attr);
423   NS_ENSURE_SUCCESS(rv, rv);
424 
425   txExpandedName nullExpr;
426   double prio = UnspecifiedNaN<double>();
427 
428   UniquePtr<txPattern> match(new txRootPattern());
429   UniquePtr<txTemplateItem> templ(
430       new txTemplateItem(std::move(match), nullExpr, nullExpr, prio));
431   aState.openInstructionContainer(templ.get());
432   aState.addToplevelItem(templ.get());
433 
434   Unused << templ.release();
435 
436   rv = aState.pushHandlerTable(gTxTemplateHandler);
437   NS_ENSURE_SUCCESS(rv, rv);
438 
439   return txFnStartLRE(aNamespaceID, aLocalName, aPrefix, aAttributes,
440                       aAttrCount, aState);
441 }
442 
txFnEndLREStylesheet(txStylesheetCompilerState & aState)443 static nsresult txFnEndLREStylesheet(txStylesheetCompilerState& aState) {
444   nsresult rv = txFnEndLRE(aState);
445   NS_ENSURE_SUCCESS(rv, rv);
446 
447   aState.popHandlerTable();
448 
449   UniquePtr<txInstruction> instr(new txReturn());
450   aState.addInstruction(std::move(instr));
451 
452   aState.closeInstructionContainer();
453 
454   return NS_OK;
455 }
456 
txFnStartEmbed(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)457 static nsresult txFnStartEmbed(int32_t aNamespaceID, nsAtom* aLocalName,
458                                nsAtom* aPrefix, txStylesheetAttr* aAttributes,
459                                int32_t aAttrCount,
460                                txStylesheetCompilerState& aState) {
461   if (!aState.handleEmbeddedSheet()) {
462     return NS_OK;
463   }
464   if (aNamespaceID != kNameSpaceID_XSLT ||
465       (aLocalName != nsGkAtoms::stylesheet &&
466        aLocalName != nsGkAtoms::transform)) {
467     return NS_ERROR_XSLT_PARSE_FAILURE;
468   }
469   return txFnStartStylesheet(aNamespaceID, aLocalName, aPrefix, aAttributes,
470                              aAttrCount, aState);
471 }
472 
txFnEndEmbed(txStylesheetCompilerState & aState)473 static nsresult txFnEndEmbed(txStylesheetCompilerState& aState) {
474   if (!aState.handleEmbeddedSheet()) {
475     return NS_OK;
476   }
477   nsresult rv = txFnEndStylesheet(aState);
478   aState.doneEmbedding();
479   return rv;
480 }
481 
482 /**
483  * Top handlers
484  */
txFnStartOtherTop(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)485 static nsresult txFnStartOtherTop(int32_t aNamespaceID, nsAtom* aLocalName,
486                                   nsAtom* aPrefix,
487                                   txStylesheetAttr* aAttributes,
488                                   int32_t aAttrCount,
489                                   txStylesheetCompilerState& aState) {
490   if (aNamespaceID == kNameSpaceID_None ||
491       (aNamespaceID == kNameSpaceID_XSLT && !aState.fcp())) {
492     return NS_ERROR_XSLT_PARSE_FAILURE;
493   }
494 
495   return aState.pushHandlerTable(gTxIgnoreHandler);
496 }
497 
txFnEndOtherTop(txStylesheetCompilerState & aState)498 static nsresult txFnEndOtherTop(txStylesheetCompilerState& aState) {
499   aState.popHandlerTable();
500   return NS_OK;
501 }
502 
503 // xsl:attribute-set
txFnStartAttributeSet(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)504 static nsresult txFnStartAttributeSet(int32_t aNamespaceID, nsAtom* aLocalName,
505                                       nsAtom* aPrefix,
506                                       txStylesheetAttr* aAttributes,
507                                       int32_t aAttrCount,
508                                       txStylesheetCompilerState& aState) {
509   nsresult rv = NS_OK;
510   txExpandedName name;
511   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
512                     name);
513   NS_ENSURE_SUCCESS(rv, rv);
514 
515   UniquePtr<txAttributeSetItem> attrSet(new txAttributeSetItem(name));
516   aState.openInstructionContainer(attrSet.get());
517 
518   aState.addToplevelItem(attrSet.get());
519 
520   Unused << attrSet.release();
521 
522   rv = parseUseAttrSets(aAttributes, aAttrCount, false, aState);
523   NS_ENSURE_SUCCESS(rv, rv);
524 
525   return aState.pushHandlerTable(gTxAttributeSetHandler);
526 }
527 
txFnEndAttributeSet(txStylesheetCompilerState & aState)528 static nsresult txFnEndAttributeSet(txStylesheetCompilerState& aState) {
529   aState.popHandlerTable();
530 
531   UniquePtr<txInstruction> instr(new txReturn());
532   aState.addInstruction(std::move(instr));
533 
534   aState.closeInstructionContainer();
535 
536   return NS_OK;
537 }
538 
539 // xsl:decimal-format
txFnStartDecimalFormat(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)540 static nsresult txFnStartDecimalFormat(int32_t aNamespaceID, nsAtom* aLocalName,
541                                        nsAtom* aPrefix,
542                                        txStylesheetAttr* aAttributes,
543                                        int32_t aAttrCount,
544                                        txStylesheetCompilerState& aState) {
545   nsresult rv = NS_OK;
546   txExpandedName name;
547   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, false, aState,
548                     name);
549   NS_ENSURE_SUCCESS(rv, rv);
550 
551   UniquePtr<txDecimalFormat> format(new txDecimalFormat);
552   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::decimalSeparator, false,
553                    aState, format->mDecimalSeparator);
554   NS_ENSURE_SUCCESS(rv, rv);
555 
556   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSeparator, false,
557                    aState, format->mGroupingSeparator);
558   NS_ENSURE_SUCCESS(rv, rv);
559 
560   txStylesheetAttr* attr = nullptr;
561   rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
562                     nsGkAtoms::infinity, false, &attr);
563   NS_ENSURE_SUCCESS(rv, rv);
564 
565   if (attr) {
566     format->mInfinity = attr->mValue;
567   }
568 
569   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::minusSign, false, aState,
570                    format->mMinusSign);
571   NS_ENSURE_SUCCESS(rv, rv);
572 
573   rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::NaN,
574                     false, &attr);
575   NS_ENSURE_SUCCESS(rv, rv);
576 
577   if (attr) {
578     format->mNaN = attr->mValue;
579   }
580 
581   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::percent, false, aState,
582                    format->mPercent);
583   NS_ENSURE_SUCCESS(rv, rv);
584 
585   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::perMille, false, aState,
586                    format->mPerMille);
587   NS_ENSURE_SUCCESS(rv, rv);
588 
589   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::zeroDigit, false, aState,
590                    format->mZeroDigit);
591   NS_ENSURE_SUCCESS(rv, rv);
592 
593   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::digit, false, aState,
594                    format->mDigit);
595   NS_ENSURE_SUCCESS(rv, rv);
596 
597   rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::patternSeparator, false,
598                    aState, format->mPatternSeparator);
599   NS_ENSURE_SUCCESS(rv, rv);
600 
601   rv = aState.mStylesheet->addDecimalFormat(name, std::move(format));
602   NS_ENSURE_SUCCESS(rv, rv);
603 
604   return aState.pushHandlerTable(gTxIgnoreHandler);
605 }
606 
txFnEndDecimalFormat(txStylesheetCompilerState & aState)607 static nsresult txFnEndDecimalFormat(txStylesheetCompilerState& aState) {
608   aState.popHandlerTable();
609 
610   return NS_OK;
611 }
612 
613 // xsl:import
txFnStartImport(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)614 static nsresult txFnStartImport(int32_t aNamespaceID, nsAtom* aLocalName,
615                                 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
616                                 int32_t aAttrCount,
617                                 txStylesheetCompilerState& aState) {
618   UniquePtr<txImportItem> import(new txImportItem);
619   import->mFrame = MakeUnique<txStylesheet::ImportFrame>();
620   aState.addToplevelItem(import.get());
621 
622   txImportItem* importPtr = import.release();
623 
624   txStylesheetAttr* attr = nullptr;
625   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
626                              nsGkAtoms::href, true, &attr);
627   NS_ENSURE_SUCCESS(rv, rv);
628 
629   nsAutoString absUri;
630   URIUtils::resolveHref(attr->mValue, aState.mElementContext->mBaseURI, absUri);
631   rv = aState.loadImportedStylesheet(absUri, importPtr->mFrame.get());
632   NS_ENSURE_SUCCESS(rv, rv);
633 
634   return aState.pushHandlerTable(gTxIgnoreHandler);
635 }
636 
txFnEndImport(txStylesheetCompilerState & aState)637 static nsresult txFnEndImport(txStylesheetCompilerState& aState) {
638   aState.popHandlerTable();
639 
640   return NS_OK;
641 }
642 
643 // xsl:include
txFnStartInclude(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)644 static nsresult txFnStartInclude(int32_t aNamespaceID, nsAtom* aLocalName,
645                                  nsAtom* aPrefix, txStylesheetAttr* aAttributes,
646                                  int32_t aAttrCount,
647                                  txStylesheetCompilerState& aState) {
648   txStylesheetAttr* attr = nullptr;
649   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
650                              nsGkAtoms::href, true, &attr);
651   NS_ENSURE_SUCCESS(rv, rv);
652 
653   nsAutoString absUri;
654   URIUtils::resolveHref(attr->mValue, aState.mElementContext->mBaseURI, absUri);
655   rv = aState.loadIncludedStylesheet(absUri);
656   NS_ENSURE_SUCCESS(rv, rv);
657 
658   return aState.pushHandlerTable(gTxIgnoreHandler);
659 }
660 
txFnEndInclude(txStylesheetCompilerState & aState)661 static nsresult txFnEndInclude(txStylesheetCompilerState& aState) {
662   aState.popHandlerTable();
663 
664   return NS_OK;
665 }
666 
667 // xsl:key
txFnStartKey(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)668 static nsresult txFnStartKey(int32_t aNamespaceID, nsAtom* aLocalName,
669                              nsAtom* aPrefix, txStylesheetAttr* aAttributes,
670                              int32_t aAttrCount,
671                              txStylesheetCompilerState& aState) {
672   nsresult rv = NS_OK;
673   txExpandedName name;
674   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
675                     name);
676   NS_ENSURE_SUCCESS(rv, rv);
677 
678   aState.mDisAllowed = txIParseContext::KEY_FUNCTION;
679 
680   UniquePtr<txPattern> match;
681   rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::match, true, aState,
682                       match);
683   NS_ENSURE_SUCCESS(rv, rv);
684 
685   UniquePtr<Expr> use;
686   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::use, true, aState, use);
687   NS_ENSURE_SUCCESS(rv, rv);
688 
689   aState.mDisAllowed = 0;
690 
691   rv = aState.mStylesheet->addKey(name, std::move(match), std::move(use));
692   NS_ENSURE_SUCCESS(rv, rv);
693 
694   return aState.pushHandlerTable(gTxIgnoreHandler);
695 }
696 
txFnEndKey(txStylesheetCompilerState & aState)697 static nsresult txFnEndKey(txStylesheetCompilerState& aState) {
698   aState.popHandlerTable();
699 
700   return NS_OK;
701 }
702 
703 // xsl:namespace-alias
txFnStartNamespaceAlias(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)704 static nsresult txFnStartNamespaceAlias(int32_t aNamespaceID,
705                                         nsAtom* aLocalName, nsAtom* aPrefix,
706                                         txStylesheetAttr* aAttributes,
707                                         int32_t aAttrCount,
708                                         txStylesheetCompilerState& aState) {
709   txStylesheetAttr* attr = nullptr;
710   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
711                              nsGkAtoms::stylesheetPrefix, true, &attr);
712   NS_ENSURE_SUCCESS(rv, rv);
713 
714   rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
715                     nsGkAtoms::resultPrefix, true, &attr);
716   NS_ENSURE_SUCCESS(rv, rv);
717 
718   // XXX Needs to be implemented.
719 
720   return aState.pushHandlerTable(gTxIgnoreHandler);
721 }
722 
txFnEndNamespaceAlias(txStylesheetCompilerState & aState)723 static nsresult txFnEndNamespaceAlias(txStylesheetCompilerState& aState) {
724   aState.popHandlerTable();
725 
726   return NS_OK;
727 }
728 
729 // xsl:output
txFnStartOutput(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)730 static nsresult txFnStartOutput(int32_t aNamespaceID, nsAtom* aLocalName,
731                                 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
732                                 int32_t aAttrCount,
733                                 txStylesheetCompilerState& aState) {
734   nsresult rv = NS_OK;
735 
736   UniquePtr<txOutputItem> item(new txOutputItem);
737 
738   txExpandedName methodExpName;
739   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::method, false, aState,
740                     methodExpName);
741   NS_ENSURE_SUCCESS(rv, rv);
742 
743   if (!methodExpName.isNull()) {
744     if (methodExpName.mNamespaceID != kNameSpaceID_None) {
745       // The spec doesn't say what to do here so we'll just ignore the
746       // value. We could possibly warn.
747     } else if (methodExpName.mLocalName == nsGkAtoms::html) {
748       item->mFormat.mMethod = eHTMLOutput;
749     } else if (methodExpName.mLocalName == nsGkAtoms::text) {
750       item->mFormat.mMethod = eTextOutput;
751     } else if (methodExpName.mLocalName == nsGkAtoms::xml) {
752       item->mFormat.mMethod = eXMLOutput;
753     } else {
754       return NS_ERROR_XSLT_PARSE_FAILURE;
755     }
756   }
757 
758   txStylesheetAttr* attr = nullptr;
759   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::version,
760                false, &attr);
761   if (attr) {
762     item->mFormat.mVersion = attr->mValue;
763   }
764 
765   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::encoding,
766                false, &attr);
767   if (attr) {
768     item->mFormat.mEncoding = attr->mValue;
769   }
770 
771   rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::omitXmlDeclaration,
772                     false, aState, item->mFormat.mOmitXMLDeclaration);
773   NS_ENSURE_SUCCESS(rv, rv);
774 
775   rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::standalone, false,
776                     aState, item->mFormat.mStandalone);
777   NS_ENSURE_SUCCESS(rv, rv);
778 
779   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
780                nsGkAtoms::doctypePublic, false, &attr);
781   if (attr) {
782     item->mFormat.mPublicId = attr->mValue;
783   }
784 
785   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
786                nsGkAtoms::doctypeSystem, false, &attr);
787   if (attr) {
788     item->mFormat.mSystemId = attr->mValue;
789   }
790 
791   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
792                nsGkAtoms::cdataSectionElements, false, &attr);
793   if (attr) {
794     nsWhitespaceTokenizer tokens(attr->mValue);
795     while (tokens.hasMoreTokens()) {
796       UniquePtr<txExpandedName> qname(new txExpandedName());
797       rv = qname->init(tokens.nextToken(), aState.mElementContext->mMappings,
798                        false);
799       NS_ENSURE_SUCCESS(rv, rv);
800 
801       item->mFormat.mCDATASectionElements.add(qname.release());
802     }
803   }
804 
805   rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::indent, false, aState,
806                     item->mFormat.mIndent);
807   NS_ENSURE_SUCCESS(rv, rv);
808 
809   getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None, nsGkAtoms::mediaType,
810                false, &attr);
811   if (attr) {
812     item->mFormat.mMediaType = attr->mValue;
813   }
814 
815   aState.addToplevelItem(item.release());
816 
817   return aState.pushHandlerTable(gTxIgnoreHandler);
818 }
819 
txFnEndOutput(txStylesheetCompilerState & aState)820 static nsresult txFnEndOutput(txStylesheetCompilerState& aState) {
821   aState.popHandlerTable();
822 
823   return NS_OK;
824 }
825 
826 // xsl:strip-space/xsl:preserve-space
txFnStartStripSpace(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)827 static nsresult txFnStartStripSpace(int32_t aNamespaceID, nsAtom* aLocalName,
828                                     nsAtom* aPrefix,
829                                     txStylesheetAttr* aAttributes,
830                                     int32_t aAttrCount,
831                                     txStylesheetCompilerState& aState) {
832   txStylesheetAttr* attr = nullptr;
833   nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
834                              nsGkAtoms::elements, true, &attr);
835   NS_ENSURE_SUCCESS(rv, rv);
836 
837   bool strip = aLocalName == nsGkAtoms::stripSpace;
838 
839   UniquePtr<txStripSpaceItem> stripItem(new txStripSpaceItem);
840   nsWhitespaceTokenizer tokenizer(attr->mValue);
841   while (tokenizer.hasMoreTokens()) {
842     const nsAString& name = tokenizer.nextToken();
843     int32_t ns = kNameSpaceID_None;
844     RefPtr<nsAtom> prefix, localName;
845     rv = XMLUtils::splitQName(name, getter_AddRefs(prefix),
846                               getter_AddRefs(localName));
847     if (NS_FAILED(rv)) {
848       // check for "*" or "prefix:*"
849       uint32_t length = name.Length();
850       const char16_t* c;
851       name.BeginReading(c);
852       if (length == 2 || c[length - 1] != '*') {
853         // these can't work
854         return NS_ERROR_XSLT_PARSE_FAILURE;
855       }
856       if (length > 1) {
857         // Check for a valid prefix, that is, the returned prefix
858         // should be empty and the real prefix is returned in
859         // localName.
860         if (c[length - 2] != ':') {
861           return NS_ERROR_XSLT_PARSE_FAILURE;
862         }
863         rv = XMLUtils::splitQName(StringHead(name, length - 2),
864                                   getter_AddRefs(prefix),
865                                   getter_AddRefs(localName));
866         if (NS_FAILED(rv) || prefix) {
867           // bad chars or two ':'
868           return NS_ERROR_XSLT_PARSE_FAILURE;
869         }
870         prefix = localName;
871       }
872       localName = nsGkAtoms::_asterisk;
873     }
874     if (prefix) {
875       ns = aState.mElementContext->mMappings->lookupNamespace(prefix);
876       NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, NS_ERROR_FAILURE);
877     }
878     UniquePtr<txStripSpaceTest> sst(
879         new txStripSpaceTest(prefix, localName, ns, strip));
880     rv = stripItem->addStripSpaceTest(sst.get());
881     NS_ENSURE_SUCCESS(rv, rv);
882 
883     Unused << sst.release();
884   }
885 
886   aState.addToplevelItem(stripItem.release());
887 
888   return aState.pushHandlerTable(gTxIgnoreHandler);
889 }
890 
txFnEndStripSpace(txStylesheetCompilerState & aState)891 static nsresult txFnEndStripSpace(txStylesheetCompilerState& aState) {
892   aState.popHandlerTable();
893 
894   return NS_OK;
895 }
896 
897 // xsl:template
txFnStartTemplate(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)898 static nsresult txFnStartTemplate(int32_t aNamespaceID, nsAtom* aLocalName,
899                                   nsAtom* aPrefix,
900                                   txStylesheetAttr* aAttributes,
901                                   int32_t aAttrCount,
902                                   txStylesheetCompilerState& aState) {
903   nsresult rv = NS_OK;
904   txExpandedName name;
905   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, false, aState,
906                     name);
907   NS_ENSURE_SUCCESS(rv, rv);
908 
909   txExpandedName mode;
910   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::mode, false, aState,
911                     mode);
912   NS_ENSURE_SUCCESS(rv, rv);
913 
914   double prio = UnspecifiedNaN<double>();
915   rv = getNumberAttr(aAttributes, aAttrCount, nsGkAtoms::priority, false,
916                      aState, prio);
917   NS_ENSURE_SUCCESS(rv, rv);
918 
919   UniquePtr<txPattern> match;
920   rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::match, name.isNull(),
921                       aState, match);
922   NS_ENSURE_SUCCESS(rv, rv);
923 
924   UniquePtr<txTemplateItem> templ(
925       new txTemplateItem(std::move(match), name, mode, prio));
926   aState.openInstructionContainer(templ.get());
927   aState.addToplevelItem(templ.release());
928 
929   return aState.pushHandlerTable(gTxParamHandler);
930 }
931 
txFnEndTemplate(txStylesheetCompilerState & aState)932 static nsresult txFnEndTemplate(txStylesheetCompilerState& aState) {
933   aState.popHandlerTable();
934 
935   UniquePtr<txInstruction> instr(new txReturn());
936   aState.addInstruction(std::move(instr));
937 
938   aState.closeInstructionContainer();
939 
940   return NS_OK;
941 }
942 
943 // xsl:variable, xsl:param
txFnStartTopVariable(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)944 static nsresult txFnStartTopVariable(int32_t aNamespaceID, nsAtom* aLocalName,
945                                      nsAtom* aPrefix,
946                                      txStylesheetAttr* aAttributes,
947                                      int32_t aAttrCount,
948                                      txStylesheetCompilerState& aState) {
949   nsresult rv = NS_OK;
950   txExpandedName name;
951   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
952                     name);
953   NS_ENSURE_SUCCESS(rv, rv);
954 
955   UniquePtr<Expr> select;
956   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
957                    select);
958   NS_ENSURE_SUCCESS(rv, rv);
959 
960   UniquePtr<txVariableItem> var(new txVariableItem(
961       name, std::move(select), aLocalName == nsGkAtoms::param));
962   aState.openInstructionContainer(var.get());
963   rv = aState.pushPtr(var.get(), aState.eVariableItem);
964   NS_ENSURE_SUCCESS(rv, rv);
965 
966   if (var->mValue) {
967     // XXX should be gTxErrorHandler?
968     rv = aState.pushHandlerTable(gTxIgnoreHandler);
969     NS_ENSURE_SUCCESS(rv, rv);
970   } else {
971     rv = aState.pushHandlerTable(gTxTopVariableHandler);
972     NS_ENSURE_SUCCESS(rv, rv);
973   }
974 
975   aState.addToplevelItem(var.release());
976 
977   return NS_OK;
978 }
979 
txFnEndTopVariable(txStylesheetCompilerState & aState)980 static nsresult txFnEndTopVariable(txStylesheetCompilerState& aState) {
981   txHandlerTable* prev = aState.mHandlerTable;
982   aState.popHandlerTable();
983   txVariableItem* var =
984       static_cast<txVariableItem*>(aState.popPtr(aState.eVariableItem));
985 
986   if (prev == gTxTopVariableHandler) {
987     // No children were found.
988     NS_ASSERTION(!var->mValue, "There shouldn't be a select-expression here");
989     var->mValue = MakeUnique<txLiteralExpr>(EmptyString());
990   } else if (!var->mValue) {
991     // If we don't have a select-expression there mush be children.
992     UniquePtr<txInstruction> instr(new txReturn());
993     aState.addInstruction(std::move(instr));
994   }
995 
996   aState.closeInstructionContainer();
997 
998   return NS_OK;
999 }
1000 
txFnStartElementStartTopVar(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1001 static nsresult txFnStartElementStartTopVar(int32_t aNamespaceID,
1002                                             nsAtom* aLocalName, nsAtom* aPrefix,
1003                                             txStylesheetAttr* aAttributes,
1004                                             int32_t aAttrCount,
1005                                             txStylesheetCompilerState& aState) {
1006   aState.mHandlerTable = gTxTemplateHandler;
1007 
1008   return NS_XSLT_GET_NEW_HANDLER;
1009 }
1010 
txFnTextStartTopVar(const nsAString & aStr,txStylesheetCompilerState & aState)1011 static nsresult txFnTextStartTopVar(const nsAString& aStr,
1012                                     txStylesheetCompilerState& aState) {
1013   TX_RETURN_IF_WHITESPACE(aStr, aState);
1014 
1015   aState.mHandlerTable = gTxTemplateHandler;
1016 
1017   return NS_XSLT_GET_NEW_HANDLER;
1018 }
1019 
1020 /**
1021  * Template Handlers
1022  */
1023 
1024 /*
1025   LRE
1026 
1027   txStartLREElement
1028   txInsertAttrSet        one for each qname in xsl:use-attribute-sets
1029   txLREAttribute         one for each attribute
1030   [children]
1031   txEndElement
1032 */
txFnStartLRE(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1033 static nsresult txFnStartLRE(int32_t aNamespaceID, nsAtom* aLocalName,
1034                              nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1035                              int32_t aAttrCount,
1036                              txStylesheetCompilerState& aState) {
1037   nsresult rv = NS_OK;
1038 
1039   UniquePtr<txInstruction> instr(
1040       new txStartLREElement(aNamespaceID, aLocalName, aPrefix));
1041   aState.addInstruction(std::move(instr));
1042 
1043   rv = parseExcludeResultPrefixes(aAttributes, aAttrCount, kNameSpaceID_XSLT);
1044   NS_ENSURE_SUCCESS(rv, rv);
1045 
1046   rv = parseUseAttrSets(aAttributes, aAttrCount, true, aState);
1047   NS_ENSURE_SUCCESS(rv, rv);
1048 
1049   txStylesheetAttr* attr = nullptr;
1050   int32_t i;
1051   for (i = 0; i < aAttrCount; ++i) {
1052     attr = aAttributes + i;
1053 
1054     if (attr->mNamespaceID == kNameSpaceID_XSLT) {
1055       if (attr->mLocalName == nsGkAtoms::version) {
1056         attr->mLocalName = nullptr;
1057       }
1058 
1059       continue;
1060     }
1061 
1062     UniquePtr<Expr> avt;
1063     rv = txExprParser::createAVT(attr->mValue, &aState, getter_Transfers(avt));
1064     NS_ENSURE_SUCCESS(rv, rv);
1065 
1066     instr = MakeUnique<txLREAttribute>(attr->mNamespaceID, attr->mLocalName,
1067                                        attr->mPrefix, std::move(avt));
1068     aState.addInstruction(std::move(instr));
1069   }
1070 
1071   return NS_OK;
1072 }
1073 
txFnEndLRE(txStylesheetCompilerState & aState)1074 static nsresult txFnEndLRE(txStylesheetCompilerState& aState) {
1075   UniquePtr<txInstruction> instr(new txEndElement);
1076   aState.addInstruction(std::move(instr));
1077 
1078   return NS_OK;
1079 }
1080 
1081 /*
1082   "LRE text"
1083 
1084   txText
1085 */
txFnText(const nsAString & aStr,txStylesheetCompilerState & aState)1086 static nsresult txFnText(const nsAString& aStr,
1087                          txStylesheetCompilerState& aState) {
1088   TX_RETURN_IF_WHITESPACE(aStr, aState);
1089 
1090   UniquePtr<txInstruction> instr(new txText(aStr, false));
1091   aState.addInstruction(std::move(instr));
1092 
1093   return NS_OK;
1094 }
1095 
1096 /*
1097   xsl:apply-imports
1098 
1099   txApplyImportsStart
1100   txApplyImportsEnd
1101 */
txFnStartApplyImports(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1102 static nsresult txFnStartApplyImports(int32_t aNamespaceID, nsAtom* aLocalName,
1103                                       nsAtom* aPrefix,
1104                                       txStylesheetAttr* aAttributes,
1105                                       int32_t aAttrCount,
1106                                       txStylesheetCompilerState& aState) {
1107   UniquePtr<txInstruction> instr(new txApplyImportsStart);
1108   aState.addInstruction(std::move(instr));
1109 
1110   instr = MakeUnique<txApplyImportsEnd>();
1111   aState.addInstruction(std::move(instr));
1112 
1113   return aState.pushHandlerTable(gTxIgnoreHandler);
1114 }
1115 
txFnEndApplyImports(txStylesheetCompilerState & aState)1116 static nsresult txFnEndApplyImports(txStylesheetCompilerState& aState) {
1117   aState.popHandlerTable();
1118 
1119   return NS_OK;
1120 }
1121 
1122 /*
1123   xsl:apply-templates
1124 
1125   txPushParams
1126   [params]
1127   txPushNewContext    -+   (holds <xsl:sort>s)
1128   txApplyTemplate <-+  |
1129   txLoopNodeSet    -+  |
1130   txPopParams        <-+
1131 */
txFnStartApplyTemplates(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1132 static nsresult txFnStartApplyTemplates(int32_t aNamespaceID,
1133                                         nsAtom* aLocalName, nsAtom* aPrefix,
1134                                         txStylesheetAttr* aAttributes,
1135                                         int32_t aAttrCount,
1136                                         txStylesheetCompilerState& aState) {
1137   nsresult rv = NS_OK;
1138 
1139   UniquePtr<txInstruction> instr(new txPushParams);
1140   aState.addInstruction(std::move(instr));
1141 
1142   txExpandedName mode;
1143   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::mode, false, aState,
1144                     mode);
1145   NS_ENSURE_SUCCESS(rv, rv);
1146 
1147   instr = MakeUnique<txApplyTemplates>(mode);
1148   rv = aState.pushObject(instr.get());
1149   NS_ENSURE_SUCCESS(rv, rv);
1150 
1151   Unused << instr.release();
1152 
1153   UniquePtr<Expr> select;
1154   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1155                    select);
1156   NS_ENSURE_SUCCESS(rv, rv);
1157 
1158   if (!select) {
1159     UniquePtr<txNodeTest> nt(new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
1160     select = MakeUnique<LocationStep>(nt.release(), LocationStep::CHILD_AXIS);
1161   }
1162 
1163   UniquePtr<txPushNewContext> pushcontext(
1164       new txPushNewContext(std::move(select)));
1165   rv = aState.pushSorter(pushcontext.get());
1166   NS_ENSURE_SUCCESS(rv, rv);
1167 
1168   rv = aState.pushObject(pushcontext.get());
1169   NS_ENSURE_SUCCESS(rv, rv);
1170 
1171   Unused << pushcontext.release();
1172 
1173   return aState.pushHandlerTable(gTxApplyTemplatesHandler);
1174 }
1175 
txFnEndApplyTemplates(txStylesheetCompilerState & aState)1176 static nsresult txFnEndApplyTemplates(txStylesheetCompilerState& aState) {
1177   aState.popHandlerTable();
1178 
1179   txPushNewContext* pushcontext =
1180       static_cast<txPushNewContext*>(aState.popObject());
1181   UniquePtr<txInstruction> instr(pushcontext);  // txPushNewContext
1182   aState.addInstruction(std::move(instr));
1183 
1184   aState.popSorter();
1185 
1186   instr = WrapUnique(
1187       static_cast<txInstruction*>(aState.popObject()));  // txApplyTemplates
1188   UniquePtr<txLoopNodeSet> loop(new txLoopNodeSet(instr.get()));
1189   aState.addInstruction(std::move(instr));
1190 
1191   instr = std::move(loop);
1192   aState.addInstruction(std::move(instr));
1193 
1194   instr = MakeUnique<txPopParams>();
1195   pushcontext->mBailTarget = instr.get();
1196   aState.addInstruction(std::move(instr));
1197 
1198   return NS_OK;
1199 }
1200 
1201 /*
1202   xsl:attribute
1203 
1204   txPushStringHandler
1205   [children]
1206   txAttribute
1207 */
txFnStartAttribute(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1208 static nsresult txFnStartAttribute(int32_t aNamespaceID, nsAtom* aLocalName,
1209                                    nsAtom* aPrefix,
1210                                    txStylesheetAttr* aAttributes,
1211                                    int32_t aAttrCount,
1212                                    txStylesheetCompilerState& aState) {
1213   nsresult rv = NS_OK;
1214 
1215   UniquePtr<txInstruction> instr(new txPushStringHandler(true));
1216   aState.addInstruction(std::move(instr));
1217 
1218   UniquePtr<Expr> name;
1219   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState, name);
1220   NS_ENSURE_SUCCESS(rv, rv);
1221 
1222   UniquePtr<Expr> nspace;
1223   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::_namespace, false, aState,
1224                   nspace);
1225   NS_ENSURE_SUCCESS(rv, rv);
1226 
1227   instr = MakeUnique<txAttribute>(std::move(name), std::move(nspace),
1228                                   aState.mElementContext->mMappings);
1229   rv = aState.pushObject(instr.get());
1230   NS_ENSURE_SUCCESS(rv, rv);
1231 
1232   Unused << instr.release();
1233 
1234   // We need to push the template-handler since the current might be
1235   // the attributeset-handler
1236   return aState.pushHandlerTable(gTxTemplateHandler);
1237 }
1238 
txFnEndAttribute(txStylesheetCompilerState & aState)1239 static nsresult txFnEndAttribute(txStylesheetCompilerState& aState) {
1240   aState.popHandlerTable();
1241   UniquePtr<txInstruction> instr(
1242       static_cast<txInstruction*>(aState.popObject()));
1243   aState.addInstruction(std::move(instr));
1244 
1245   return NS_OK;
1246 }
1247 
1248 /*
1249   xsl:call-template
1250 
1251   txPushParams
1252   [params]
1253   txCallTemplate
1254   txPopParams
1255 */
txFnStartCallTemplate(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1256 static nsresult txFnStartCallTemplate(int32_t aNamespaceID, nsAtom* aLocalName,
1257                                       nsAtom* aPrefix,
1258                                       txStylesheetAttr* aAttributes,
1259                                       int32_t aAttrCount,
1260                                       txStylesheetCompilerState& aState) {
1261   nsresult rv = NS_OK;
1262 
1263   UniquePtr<txInstruction> instr(new txPushParams);
1264   aState.addInstruction(std::move(instr));
1265 
1266   txExpandedName name;
1267   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1268                     name);
1269   NS_ENSURE_SUCCESS(rv, rv);
1270 
1271   instr = MakeUnique<txCallTemplate>(name);
1272   rv = aState.pushObject(instr.get());
1273   NS_ENSURE_SUCCESS(rv, rv);
1274 
1275   Unused << instr.release();
1276 
1277   return aState.pushHandlerTable(gTxCallTemplateHandler);
1278 }
1279 
txFnEndCallTemplate(txStylesheetCompilerState & aState)1280 static nsresult txFnEndCallTemplate(txStylesheetCompilerState& aState) {
1281   aState.popHandlerTable();
1282 
1283   // txCallTemplate
1284   UniquePtr<txInstruction> instr(
1285       static_cast<txInstruction*>(aState.popObject()));
1286   aState.addInstruction(std::move(instr));
1287 
1288   instr = MakeUnique<txPopParams>();
1289   aState.addInstruction(std::move(instr));
1290 
1291   return NS_OK;
1292 }
1293 
1294 /*
1295   xsl:choose
1296 
1297   txCondotionalGoto      --+        \
1298   [children]               |         | one for each xsl:when
1299   txGoTo           --+     |        /
1300                      |     |
1301   txCondotionalGoto  |   <-+  --+
1302   [children]         |          |
1303   txGoTo           --+          |
1304                      |          |
1305   [children]         |        <-+      for the xsl:otherwise, if there is one
1306                    <-+
1307 */
txFnStartChoose(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1308 static nsresult txFnStartChoose(int32_t aNamespaceID, nsAtom* aLocalName,
1309                                 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1310                                 int32_t aAttrCount,
1311                                 txStylesheetCompilerState& aState) {
1312   nsresult rv = aState.pushChooseGotoList();
1313   NS_ENSURE_SUCCESS(rv, rv);
1314 
1315   return aState.pushHandlerTable(gTxChooseHandler);
1316 }
1317 
txFnEndChoose(txStylesheetCompilerState & aState)1318 static nsresult txFnEndChoose(txStylesheetCompilerState& aState) {
1319   nsresult rv = NS_OK;
1320   aState.popHandlerTable();
1321   txListIterator iter(aState.mChooseGotoList.get());
1322   txGoTo* gotoinstr;
1323   while ((gotoinstr = static_cast<txGoTo*>(iter.next()))) {
1324     rv = aState.addGotoTarget(&gotoinstr->mTarget);
1325     NS_ENSURE_SUCCESS(rv, rv);
1326   }
1327 
1328   aState.popChooseGotoList();
1329 
1330   return NS_OK;
1331 }
1332 
1333 /*
1334   xsl:comment
1335 
1336   txPushStringHandler
1337   [children]
1338   txComment
1339 */
txFnStartComment(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1340 static nsresult txFnStartComment(int32_t aNamespaceID, nsAtom* aLocalName,
1341                                  nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1342                                  int32_t aAttrCount,
1343                                  txStylesheetCompilerState& aState) {
1344   UniquePtr<txInstruction> instr(new txPushStringHandler(true));
1345   aState.addInstruction(std::move(instr));
1346 
1347   return NS_OK;
1348 }
1349 
txFnEndComment(txStylesheetCompilerState & aState)1350 static nsresult txFnEndComment(txStylesheetCompilerState& aState) {
1351   UniquePtr<txInstruction> instr(new txComment);
1352   aState.addInstruction(std::move(instr));
1353 
1354   return NS_OK;
1355 }
1356 
1357 /*
1358   xsl:copy
1359 
1360   txCopy          -+
1361   txInsertAttrSet  |     one for each qname in use-attribute-sets
1362   [children]       |
1363   txEndElement     |
1364                  <-+
1365 */
txFnStartCopy(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1366 static nsresult txFnStartCopy(int32_t aNamespaceID, nsAtom* aLocalName,
1367                               nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1368                               int32_t aAttrCount,
1369                               txStylesheetCompilerState& aState) {
1370   UniquePtr<txCopy> copy(new txCopy);
1371   nsresult rv = aState.pushPtr(copy.get(), aState.eCopy);
1372   NS_ENSURE_SUCCESS(rv, rv);
1373 
1374   UniquePtr<txInstruction> instr(copy.release());
1375   aState.addInstruction(std::move(instr));
1376 
1377   rv = parseUseAttrSets(aAttributes, aAttrCount, false, aState);
1378   NS_ENSURE_SUCCESS(rv, rv);
1379 
1380   return NS_OK;
1381 }
1382 
txFnEndCopy(txStylesheetCompilerState & aState)1383 static nsresult txFnEndCopy(txStylesheetCompilerState& aState) {
1384   UniquePtr<txInstruction> instr(new txEndElement);
1385   aState.addInstruction(std::move(instr));
1386 
1387   txCopy* copy = static_cast<txCopy*>(aState.popPtr(aState.eCopy));
1388   nsresult rv = aState.addGotoTarget(&copy->mBailTarget);
1389   NS_ENSURE_SUCCESS(rv, rv);
1390 
1391   return NS_OK;
1392 }
1393 
1394 /*
1395   xsl:copy-of
1396 
1397   txCopyOf
1398 */
txFnStartCopyOf(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1399 static nsresult txFnStartCopyOf(int32_t aNamespaceID, nsAtom* aLocalName,
1400                                 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1401                                 int32_t aAttrCount,
1402                                 txStylesheetCompilerState& aState) {
1403   nsresult rv = NS_OK;
1404 
1405   UniquePtr<Expr> select;
1406   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true, aState,
1407                    select);
1408   NS_ENSURE_SUCCESS(rv, rv);
1409 
1410   UniquePtr<txInstruction> instr(new txCopyOf(std::move(select)));
1411   aState.addInstruction(std::move(instr));
1412 
1413   return aState.pushHandlerTable(gTxIgnoreHandler);
1414 }
1415 
txFnEndCopyOf(txStylesheetCompilerState & aState)1416 static nsresult txFnEndCopyOf(txStylesheetCompilerState& aState) {
1417   aState.popHandlerTable();
1418   return NS_OK;
1419 }
1420 
1421 /*
1422   xsl:element
1423 
1424   txStartElement
1425   txInsertAttrSet        one for each qname in use-attribute-sets
1426   [children]
1427   txEndElement
1428 */
txFnStartElement(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1429 static nsresult txFnStartElement(int32_t aNamespaceID, nsAtom* aLocalName,
1430                                  nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1431                                  int32_t aAttrCount,
1432                                  txStylesheetCompilerState& aState) {
1433   nsresult rv = NS_OK;
1434 
1435   UniquePtr<Expr> name;
1436   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState, name);
1437   NS_ENSURE_SUCCESS(rv, rv);
1438 
1439   UniquePtr<Expr> nspace;
1440   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::_namespace, false, aState,
1441                   nspace);
1442   NS_ENSURE_SUCCESS(rv, rv);
1443 
1444   UniquePtr<txInstruction> instr(new txStartElement(
1445       std::move(name), std::move(nspace), aState.mElementContext->mMappings));
1446   aState.addInstruction(std::move(instr));
1447 
1448   rv = parseUseAttrSets(aAttributes, aAttrCount, false, aState);
1449   NS_ENSURE_SUCCESS(rv, rv);
1450 
1451   return NS_OK;
1452 }
1453 
txFnEndElement(txStylesheetCompilerState & aState)1454 static nsresult txFnEndElement(txStylesheetCompilerState& aState) {
1455   UniquePtr<txInstruction> instr(new txEndElement);
1456   aState.addInstruction(std::move(instr));
1457 
1458   return NS_OK;
1459 }
1460 
1461 /*
1462     xsl:fallback
1463 
1464     [children]
1465 */
txFnStartFallback(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1466 static nsresult txFnStartFallback(int32_t aNamespaceID, nsAtom* aLocalName,
1467                                   nsAtom* aPrefix,
1468                                   txStylesheetAttr* aAttributes,
1469                                   int32_t aAttrCount,
1470                                   txStylesheetCompilerState& aState) {
1471   aState.mSearchingForFallback = false;
1472 
1473   return aState.pushHandlerTable(gTxTemplateHandler);
1474 }
1475 
txFnEndFallback(txStylesheetCompilerState & aState)1476 static nsresult txFnEndFallback(txStylesheetCompilerState& aState) {
1477   aState.popHandlerTable();
1478 
1479   NS_ASSERTION(!aState.mSearchingForFallback,
1480                "bad nesting of unknown-instruction and fallback handlers");
1481   return NS_OK;
1482 }
1483 
1484 /*
1485   xsl:for-each
1486 
1487   txPushNewContext            -+    (holds <xsl:sort>s)
1488   txPushNullTemplateRule  <-+  |
1489   [children]                |  |
1490   txLoopNodeSet            -+  |
1491                              <-+
1492 */
txFnStartForEach(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1493 static nsresult txFnStartForEach(int32_t aNamespaceID, nsAtom* aLocalName,
1494                                  nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1495                                  int32_t aAttrCount,
1496                                  txStylesheetCompilerState& aState) {
1497   nsresult rv = NS_OK;
1498 
1499   UniquePtr<Expr> select;
1500   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true, aState,
1501                    select);
1502   NS_ENSURE_SUCCESS(rv, rv);
1503 
1504   UniquePtr<txPushNewContext> pushcontext(
1505       new txPushNewContext(std::move(select)));
1506   rv = aState.pushPtr(pushcontext.get(), aState.ePushNewContext);
1507   NS_ENSURE_SUCCESS(rv, rv);
1508 
1509   rv = aState.pushSorter(pushcontext.get());
1510   NS_ENSURE_SUCCESS(rv, rv);
1511 
1512   UniquePtr<txInstruction> instr(pushcontext.release());
1513   aState.addInstruction(std::move(instr));
1514 
1515   instr = MakeUnique<txPushNullTemplateRule>();
1516   rv = aState.pushPtr(instr.get(), aState.ePushNullTemplateRule);
1517   NS_ENSURE_SUCCESS(rv, rv);
1518 
1519   aState.addInstruction(std::move(instr));
1520 
1521   return aState.pushHandlerTable(gTxForEachHandler);
1522 }
1523 
txFnEndForEach(txStylesheetCompilerState & aState)1524 static nsresult txFnEndForEach(txStylesheetCompilerState& aState) {
1525   aState.popHandlerTable();
1526 
1527   // This is a txPushNullTemplateRule
1528   txInstruction* pnullrule =
1529       static_cast<txInstruction*>(aState.popPtr(aState.ePushNullTemplateRule));
1530 
1531   UniquePtr<txInstruction> instr(new txLoopNodeSet(pnullrule));
1532   aState.addInstruction(std::move(instr));
1533 
1534   aState.popSorter();
1535   txPushNewContext* pushcontext =
1536       static_cast<txPushNewContext*>(aState.popPtr(aState.ePushNewContext));
1537   aState.addGotoTarget(&pushcontext->mBailTarget);
1538 
1539   return NS_OK;
1540 }
1541 
txFnStartElementContinueTemplate(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1542 static nsresult txFnStartElementContinueTemplate(
1543     int32_t aNamespaceID, nsAtom* aLocalName, nsAtom* aPrefix,
1544     txStylesheetAttr* aAttributes, int32_t aAttrCount,
1545     txStylesheetCompilerState& aState) {
1546   aState.mHandlerTable = gTxTemplateHandler;
1547 
1548   return NS_XSLT_GET_NEW_HANDLER;
1549 }
1550 
txFnTextContinueTemplate(const nsAString & aStr,txStylesheetCompilerState & aState)1551 static nsresult txFnTextContinueTemplate(const nsAString& aStr,
1552                                          txStylesheetCompilerState& aState) {
1553   TX_RETURN_IF_WHITESPACE(aStr, aState);
1554 
1555   aState.mHandlerTable = gTxTemplateHandler;
1556 
1557   return NS_XSLT_GET_NEW_HANDLER;
1558 }
1559 
1560 /*
1561   xsl:if
1562 
1563   txConditionalGoto  -+
1564   [children]          |
1565                     <-+
1566 */
txFnStartIf(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1567 static nsresult txFnStartIf(int32_t aNamespaceID, nsAtom* aLocalName,
1568                             nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1569                             int32_t aAttrCount,
1570                             txStylesheetCompilerState& aState) {
1571   nsresult rv = NS_OK;
1572 
1573   UniquePtr<Expr> test;
1574   rv =
1575       getExprAttr(aAttributes, aAttrCount, nsGkAtoms::test, true, aState, test);
1576   NS_ENSURE_SUCCESS(rv, rv);
1577 
1578   UniquePtr<txConditionalGoto> condGoto(
1579       new txConditionalGoto(std::move(test), nullptr));
1580   rv = aState.pushPtr(condGoto.get(), aState.eConditionalGoto);
1581   NS_ENSURE_SUCCESS(rv, rv);
1582 
1583   UniquePtr<txInstruction> instr(condGoto.release());
1584   aState.addInstruction(std::move(instr));
1585 
1586   return NS_OK;
1587 }
1588 
txFnEndIf(txStylesheetCompilerState & aState)1589 static nsresult txFnEndIf(txStylesheetCompilerState& aState) {
1590   txConditionalGoto* condGoto =
1591       static_cast<txConditionalGoto*>(aState.popPtr(aState.eConditionalGoto));
1592   return aState.addGotoTarget(&condGoto->mTarget);
1593 }
1594 
1595 /*
1596   xsl:message
1597 
1598   txPushStringHandler
1599   [children]
1600   txMessage
1601 */
txFnStartMessage(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1602 static nsresult txFnStartMessage(int32_t aNamespaceID, nsAtom* aLocalName,
1603                                  nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1604                                  int32_t aAttrCount,
1605                                  txStylesheetCompilerState& aState) {
1606   UniquePtr<txInstruction> instr(new txPushStringHandler(false));
1607   aState.addInstruction(std::move(instr));
1608 
1609   txThreeState term;
1610   nsresult rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::terminate,
1611                              false, aState, term);
1612   NS_ENSURE_SUCCESS(rv, rv);
1613 
1614   instr = MakeUnique<txMessage>(term == eTrue);
1615   rv = aState.pushObject(instr.get());
1616   NS_ENSURE_SUCCESS(rv, rv);
1617 
1618   Unused << instr.release();
1619 
1620   return NS_OK;
1621 }
1622 
txFnEndMessage(txStylesheetCompilerState & aState)1623 static nsresult txFnEndMessage(txStylesheetCompilerState& aState) {
1624   UniquePtr<txInstruction> instr(
1625       static_cast<txInstruction*>(aState.popObject()));
1626   aState.addInstruction(std::move(instr));
1627 
1628   return NS_OK;
1629 }
1630 
1631 /*
1632   xsl:number
1633 
1634   txNumber
1635 */
txFnStartNumber(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1636 static nsresult txFnStartNumber(int32_t aNamespaceID, nsAtom* aLocalName,
1637                                 nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1638                                 int32_t aAttrCount,
1639                                 txStylesheetCompilerState& aState) {
1640   nsresult rv = NS_OK;
1641 
1642   RefPtr<nsAtom> levelAtom;
1643   rv = getAtomAttr(aAttributes, aAttrCount, nsGkAtoms::level, false, aState,
1644                    getter_AddRefs(levelAtom));
1645   NS_ENSURE_SUCCESS(rv, rv);
1646 
1647   txXSLTNumber::LevelType level = txXSLTNumber::eLevelSingle;
1648   if (levelAtom == nsGkAtoms::multiple) {
1649     level = txXSLTNumber::eLevelMultiple;
1650   } else if (levelAtom == nsGkAtoms::any) {
1651     level = txXSLTNumber::eLevelAny;
1652   } else if (levelAtom && levelAtom != nsGkAtoms::single && !aState.fcp()) {
1653     return NS_ERROR_XSLT_PARSE_FAILURE;
1654   }
1655 
1656   UniquePtr<txPattern> count;
1657   rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::count, false, aState,
1658                       count);
1659   NS_ENSURE_SUCCESS(rv, rv);
1660 
1661   UniquePtr<txPattern> from;
1662   rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::from, false, aState,
1663                       from);
1664   NS_ENSURE_SUCCESS(rv, rv);
1665 
1666   UniquePtr<Expr> value;
1667   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::value, false, aState,
1668                    value);
1669   NS_ENSURE_SUCCESS(rv, rv);
1670 
1671   UniquePtr<Expr> format;
1672   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::format, false, aState,
1673                   format);
1674   NS_ENSURE_SUCCESS(rv, rv);
1675 
1676   UniquePtr<Expr> lang;
1677   rv =
1678       getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::lang, false, aState, lang);
1679   NS_ENSURE_SUCCESS(rv, rv);
1680 
1681   UniquePtr<Expr> letterValue;
1682   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::letterValue, false,
1683                   aState, letterValue);
1684   NS_ENSURE_SUCCESS(rv, rv);
1685 
1686   UniquePtr<Expr> groupingSeparator;
1687   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSeparator, false,
1688                   aState, groupingSeparator);
1689   NS_ENSURE_SUCCESS(rv, rv);
1690 
1691   UniquePtr<Expr> groupingSize;
1692   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSize, false,
1693                   aState, groupingSize);
1694   NS_ENSURE_SUCCESS(rv, rv);
1695 
1696   UniquePtr<txInstruction> instr(
1697       new txNumber(level, std::move(count), std::move(from), std::move(value),
1698                    std::move(format), std::move(groupingSeparator),
1699                    std::move(groupingSize)));
1700   aState.addInstruction(std::move(instr));
1701 
1702   return aState.pushHandlerTable(gTxIgnoreHandler);
1703 }
1704 
txFnEndNumber(txStylesheetCompilerState & aState)1705 static nsresult txFnEndNumber(txStylesheetCompilerState& aState) {
1706   aState.popHandlerTable();
1707 
1708   return NS_OK;
1709 }
1710 
1711 /*
1712     xsl:otherwise
1713 
1714     (see xsl:choose)
1715 */
txFnStartOtherwise(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1716 static nsresult txFnStartOtherwise(int32_t aNamespaceID, nsAtom* aLocalName,
1717                                    nsAtom* aPrefix,
1718                                    txStylesheetAttr* aAttributes,
1719                                    int32_t aAttrCount,
1720                                    txStylesheetCompilerState& aState) {
1721   return aState.pushHandlerTable(gTxTemplateHandler);
1722 }
1723 
txFnEndOtherwise(txStylesheetCompilerState & aState)1724 static nsresult txFnEndOtherwise(txStylesheetCompilerState& aState) {
1725   aState.popHandlerTable();
1726   aState.mHandlerTable = gTxIgnoreHandler;  // XXX should be gTxErrorHandler
1727 
1728   return NS_OK;
1729 }
1730 
1731 /*
1732     xsl:param
1733 
1734     txCheckParam    --+
1735     txPushRTFHandler  |  --- (for RTF-parameters)
1736     [children]        |  /
1737     txSetVariable     |
1738                     <-+
1739 */
txFnStartParam(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1740 static nsresult txFnStartParam(int32_t aNamespaceID, nsAtom* aLocalName,
1741                                nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1742                                int32_t aAttrCount,
1743                                txStylesheetCompilerState& aState) {
1744   nsresult rv = NS_OK;
1745 
1746   txExpandedName name;
1747   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1748                     name);
1749   NS_ENSURE_SUCCESS(rv, rv);
1750 
1751   UniquePtr<txCheckParam> checkParam(new txCheckParam(name));
1752   NS_ENSURE_SUCCESS(rv, rv);
1753 
1754   rv = aState.pushPtr(checkParam.get(), aState.eCheckParam);
1755   NS_ENSURE_SUCCESS(rv, rv);
1756 
1757   UniquePtr<txInstruction> instr(checkParam.release());
1758   aState.addInstruction(std::move(instr));
1759 
1760   UniquePtr<Expr> select;
1761   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1762                    select);
1763   NS_ENSURE_SUCCESS(rv, rv);
1764 
1765   UniquePtr<txSetVariable> var(new txSetVariable(name, std::move(select)));
1766   if (var->mValue) {
1767     // XXX should be gTxErrorHandler?
1768     rv = aState.pushHandlerTable(gTxIgnoreHandler);
1769     NS_ENSURE_SUCCESS(rv, rv);
1770   } else {
1771     rv = aState.pushHandlerTable(gTxVariableHandler);
1772     NS_ENSURE_SUCCESS(rv, rv);
1773   }
1774 
1775   rv = aState.pushObject(var.get());
1776   NS_ENSURE_SUCCESS(rv, rv);
1777 
1778   Unused << var.release();
1779 
1780   return NS_OK;
1781 }
1782 
txFnEndParam(txStylesheetCompilerState & aState)1783 static nsresult txFnEndParam(txStylesheetCompilerState& aState) {
1784   UniquePtr<txSetVariable> var(static_cast<txSetVariable*>(aState.popObject()));
1785   txHandlerTable* prev = aState.mHandlerTable;
1786   aState.popHandlerTable();
1787 
1788   if (prev == gTxVariableHandler) {
1789     // No children were found.
1790     NS_ASSERTION(!var->mValue, "There shouldn't be a select-expression here");
1791     var->mValue = MakeUnique<txLiteralExpr>(EmptyString());
1792   }
1793 
1794   nsresult rv = aState.addVariable(var->mName);
1795   NS_ENSURE_SUCCESS(rv, rv);
1796 
1797   UniquePtr<txInstruction> instr(var.release());
1798   aState.addInstruction(std::move(instr));
1799 
1800   txCheckParam* checkParam =
1801       static_cast<txCheckParam*>(aState.popPtr(aState.eCheckParam));
1802   aState.addGotoTarget(&checkParam->mBailTarget);
1803 
1804   return NS_OK;
1805 }
1806 
1807 /*
1808   xsl:processing-instruction
1809 
1810   txPushStringHandler
1811   [children]
1812   txProcessingInstruction
1813 */
txFnStartPI(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1814 static nsresult txFnStartPI(int32_t aNamespaceID, nsAtom* aLocalName,
1815                             nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1816                             int32_t aAttrCount,
1817                             txStylesheetCompilerState& aState) {
1818   UniquePtr<txInstruction> instr(new txPushStringHandler(true));
1819   aState.addInstruction(std::move(instr));
1820 
1821   UniquePtr<Expr> name;
1822   nsresult rv =
1823       getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState, name);
1824   NS_ENSURE_SUCCESS(rv, rv);
1825 
1826   instr = MakeUnique<txProcessingInstruction>(std::move(name));
1827   rv = aState.pushObject(instr.get());
1828   NS_ENSURE_SUCCESS(rv, rv);
1829 
1830   Unused << instr.release();
1831 
1832   return NS_OK;
1833 }
1834 
txFnEndPI(txStylesheetCompilerState & aState)1835 static nsresult txFnEndPI(txStylesheetCompilerState& aState) {
1836   UniquePtr<txInstruction> instr(
1837       static_cast<txInstruction*>(aState.popObject()));
1838   aState.addInstruction(std::move(instr));
1839 
1840   return NS_OK;
1841 }
1842 
1843 /*
1844     xsl:sort
1845 
1846     (no instructions)
1847 */
txFnStartSort(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1848 static nsresult txFnStartSort(int32_t aNamespaceID, nsAtom* aLocalName,
1849                               nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1850                               int32_t aAttrCount,
1851                               txStylesheetCompilerState& aState) {
1852   nsresult rv = NS_OK;
1853 
1854   UniquePtr<Expr> select;
1855   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1856                    select);
1857   NS_ENSURE_SUCCESS(rv, rv);
1858 
1859   if (!select) {
1860     UniquePtr<txNodeTest> nt(new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
1861     select = MakeUnique<LocationStep>(nt.release(), LocationStep::SELF_AXIS);
1862   }
1863 
1864   UniquePtr<Expr> lang;
1865   rv =
1866       getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::lang, false, aState, lang);
1867   NS_ENSURE_SUCCESS(rv, rv);
1868 
1869   UniquePtr<Expr> dataType;
1870   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::dataType, false, aState,
1871                   dataType);
1872   NS_ENSURE_SUCCESS(rv, rv);
1873 
1874   UniquePtr<Expr> order;
1875   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::order, false, aState,
1876                   order);
1877   NS_ENSURE_SUCCESS(rv, rv);
1878 
1879   UniquePtr<Expr> caseOrder;
1880   rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::caseOrder, false, aState,
1881                   caseOrder);
1882   NS_ENSURE_SUCCESS(rv, rv);
1883 
1884   rv = aState.mSorter->addSort(std::move(select), std::move(lang),
1885                                std::move(dataType), std::move(order),
1886                                std::move(caseOrder));
1887   NS_ENSURE_SUCCESS(rv, rv);
1888 
1889   return aState.pushHandlerTable(gTxIgnoreHandler);
1890 }
1891 
txFnEndSort(txStylesheetCompilerState & aState)1892 static nsresult txFnEndSort(txStylesheetCompilerState& aState) {
1893   aState.popHandlerTable();
1894 
1895   return NS_OK;
1896 }
1897 
1898 /*
1899   xsl:text
1900 
1901   [children]     (only txText)
1902 */
txFnStartText(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1903 static nsresult txFnStartText(int32_t aNamespaceID, nsAtom* aLocalName,
1904                               nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1905                               int32_t aAttrCount,
1906                               txStylesheetCompilerState& aState) {
1907   NS_ASSERTION(!aState.mDOE, "nested d-o-e elements should not happen");
1908 
1909   nsresult rv = NS_OK;
1910   txThreeState doe;
1911   rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::disableOutputEscaping,
1912                     false, aState, doe);
1913   NS_ENSURE_SUCCESS(rv, rv);
1914 
1915   aState.mDOE = doe == eTrue;
1916 
1917   return aState.pushHandlerTable(gTxTextHandler);
1918 }
1919 
txFnEndText(txStylesheetCompilerState & aState)1920 static nsresult txFnEndText(txStylesheetCompilerState& aState) {
1921   aState.mDOE = false;
1922   aState.popHandlerTable();
1923   return NS_OK;
1924 }
1925 
txFnTextText(const nsAString & aStr,txStylesheetCompilerState & aState)1926 static nsresult txFnTextText(const nsAString& aStr,
1927                              txStylesheetCompilerState& aState) {
1928   UniquePtr<txInstruction> instr(new txText(aStr, aState.mDOE));
1929   aState.addInstruction(std::move(instr));
1930 
1931   return NS_OK;
1932 }
1933 
1934 /*
1935   xsl:value-of
1936 
1937   txValueOf
1938 */
txFnStartValueOf(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1939 static nsresult txFnStartValueOf(int32_t aNamespaceID, nsAtom* aLocalName,
1940                                  nsAtom* aPrefix, txStylesheetAttr* aAttributes,
1941                                  int32_t aAttrCount,
1942                                  txStylesheetCompilerState& aState) {
1943   nsresult rv = NS_OK;
1944 
1945   txThreeState doe;
1946   rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::disableOutputEscaping,
1947                     false, aState, doe);
1948   NS_ENSURE_SUCCESS(rv, rv);
1949 
1950   UniquePtr<Expr> select;
1951   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true, aState,
1952                    select);
1953   NS_ENSURE_SUCCESS(rv, rv);
1954 
1955   UniquePtr<txInstruction> instr(
1956       new txValueOf(std::move(select), doe == eTrue));
1957   aState.addInstruction(std::move(instr));
1958 
1959   return aState.pushHandlerTable(gTxIgnoreHandler);
1960 }
1961 
txFnEndValueOf(txStylesheetCompilerState & aState)1962 static nsresult txFnEndValueOf(txStylesheetCompilerState& aState) {
1963   aState.popHandlerTable();
1964   return NS_OK;
1965 }
1966 
1967 /*
1968     xsl:variable
1969 
1970     txPushRTFHandler     --- (for RTF-parameters)
1971     [children]           /
1972     txSetVariable
1973 */
txFnStartVariable(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)1974 static nsresult txFnStartVariable(int32_t aNamespaceID, nsAtom* aLocalName,
1975                                   nsAtom* aPrefix,
1976                                   txStylesheetAttr* aAttributes,
1977                                   int32_t aAttrCount,
1978                                   txStylesheetCompilerState& aState) {
1979   nsresult rv = NS_OK;
1980 
1981   txExpandedName name;
1982   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
1983                     name);
1984   NS_ENSURE_SUCCESS(rv, rv);
1985 
1986   UniquePtr<Expr> select;
1987   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
1988                    select);
1989   NS_ENSURE_SUCCESS(rv, rv);
1990 
1991   UniquePtr<txSetVariable> var(new txSetVariable(name, std::move(select)));
1992   if (var->mValue) {
1993     // XXX should be gTxErrorHandler?
1994     rv = aState.pushHandlerTable(gTxIgnoreHandler);
1995     NS_ENSURE_SUCCESS(rv, rv);
1996   } else {
1997     rv = aState.pushHandlerTable(gTxVariableHandler);
1998     NS_ENSURE_SUCCESS(rv, rv);
1999   }
2000 
2001   rv = aState.pushObject(var.get());
2002   NS_ENSURE_SUCCESS(rv, rv);
2003 
2004   Unused << var.release();
2005 
2006   return NS_OK;
2007 }
2008 
txFnEndVariable(txStylesheetCompilerState & aState)2009 static nsresult txFnEndVariable(txStylesheetCompilerState& aState) {
2010   UniquePtr<txSetVariable> var(static_cast<txSetVariable*>(aState.popObject()));
2011 
2012   txHandlerTable* prev = aState.mHandlerTable;
2013   aState.popHandlerTable();
2014 
2015   if (prev == gTxVariableHandler) {
2016     // No children were found.
2017     NS_ASSERTION(!var->mValue, "There shouldn't be a select-expression here");
2018     var->mValue = MakeUnique<txLiteralExpr>(EmptyString());
2019   }
2020 
2021   nsresult rv = aState.addVariable(var->mName);
2022   NS_ENSURE_SUCCESS(rv, rv);
2023 
2024   UniquePtr<txInstruction> instr(var.release());
2025   aState.addInstruction(std::move(instr));
2026 
2027   return NS_OK;
2028 }
2029 
txFnStartElementStartRTF(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)2030 static nsresult txFnStartElementStartRTF(int32_t aNamespaceID,
2031                                          nsAtom* aLocalName, nsAtom* aPrefix,
2032                                          txStylesheetAttr* aAttributes,
2033                                          int32_t aAttrCount,
2034                                          txStylesheetCompilerState& aState) {
2035   UniquePtr<txInstruction> instr(new txPushRTFHandler);
2036   aState.addInstruction(std::move(instr));
2037 
2038   aState.mHandlerTable = gTxTemplateHandler;
2039 
2040   return NS_XSLT_GET_NEW_HANDLER;
2041 }
2042 
txFnTextStartRTF(const nsAString & aStr,txStylesheetCompilerState & aState)2043 static nsresult txFnTextStartRTF(const nsAString& aStr,
2044                                  txStylesheetCompilerState& aState) {
2045   TX_RETURN_IF_WHITESPACE(aStr, aState);
2046 
2047   UniquePtr<txInstruction> instr(new txPushRTFHandler);
2048   aState.addInstruction(std::move(instr));
2049 
2050   aState.mHandlerTable = gTxTemplateHandler;
2051 
2052   return NS_XSLT_GET_NEW_HANDLER;
2053 }
2054 
2055 /*
2056     xsl:when
2057 
2058     (see xsl:choose)
2059 */
txFnStartWhen(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)2060 static nsresult txFnStartWhen(int32_t aNamespaceID, nsAtom* aLocalName,
2061                               nsAtom* aPrefix, txStylesheetAttr* aAttributes,
2062                               int32_t aAttrCount,
2063                               txStylesheetCompilerState& aState) {
2064   nsresult rv = NS_OK;
2065 
2066   UniquePtr<Expr> test;
2067   rv =
2068       getExprAttr(aAttributes, aAttrCount, nsGkAtoms::test, true, aState, test);
2069   NS_ENSURE_SUCCESS(rv, rv);
2070 
2071   UniquePtr<txConditionalGoto> condGoto(
2072       new txConditionalGoto(std::move(test), nullptr));
2073   rv = aState.pushPtr(condGoto.get(), aState.eConditionalGoto);
2074   NS_ENSURE_SUCCESS(rv, rv);
2075 
2076   UniquePtr<txInstruction> instr(condGoto.release());
2077   aState.addInstruction(std::move(instr));
2078 
2079   return aState.pushHandlerTable(gTxTemplateHandler);
2080 }
2081 
txFnEndWhen(txStylesheetCompilerState & aState)2082 static nsresult txFnEndWhen(txStylesheetCompilerState& aState) {
2083   aState.popHandlerTable();
2084   UniquePtr<txGoTo> gotoinstr(new txGoTo(nullptr));
2085   aState.mChooseGotoList->add(gotoinstr.get());
2086 
2087   UniquePtr<txInstruction> instr(gotoinstr.release());
2088   aState.addInstruction(std::move(instr));
2089 
2090   txConditionalGoto* condGoto =
2091       static_cast<txConditionalGoto*>(aState.popPtr(aState.eConditionalGoto));
2092   nsresult rv = aState.addGotoTarget(&condGoto->mTarget);
2093   NS_ENSURE_SUCCESS(rv, rv);
2094 
2095   return NS_OK;
2096 }
2097 
2098 /*
2099     xsl:with-param
2100 
2101     txPushRTFHandler   -- for RTF-parameters
2102     [children]         /
2103     txSetParam
2104 */
txFnStartWithParam(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)2105 static nsresult txFnStartWithParam(int32_t aNamespaceID, nsAtom* aLocalName,
2106                                    nsAtom* aPrefix,
2107                                    txStylesheetAttr* aAttributes,
2108                                    int32_t aAttrCount,
2109                                    txStylesheetCompilerState& aState) {
2110   nsresult rv = NS_OK;
2111 
2112   txExpandedName name;
2113   rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true, aState,
2114                     name);
2115   NS_ENSURE_SUCCESS(rv, rv);
2116 
2117   UniquePtr<Expr> select;
2118   rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false, aState,
2119                    select);
2120   NS_ENSURE_SUCCESS(rv, rv);
2121 
2122   UniquePtr<txSetParam> var(new txSetParam(name, std::move(select)));
2123   if (var->mValue) {
2124     // XXX should be gTxErrorHandler?
2125     rv = aState.pushHandlerTable(gTxIgnoreHandler);
2126     NS_ENSURE_SUCCESS(rv, rv);
2127   } else {
2128     rv = aState.pushHandlerTable(gTxVariableHandler);
2129     NS_ENSURE_SUCCESS(rv, rv);
2130   }
2131 
2132   rv = aState.pushObject(var.get());
2133   NS_ENSURE_SUCCESS(rv, rv);
2134 
2135   Unused << var.release();
2136 
2137   return NS_OK;
2138 }
2139 
txFnEndWithParam(txStylesheetCompilerState & aState)2140 static nsresult txFnEndWithParam(txStylesheetCompilerState& aState) {
2141   UniquePtr<txSetParam> var(static_cast<txSetParam*>(aState.popObject()));
2142   txHandlerTable* prev = aState.mHandlerTable;
2143   aState.popHandlerTable();
2144 
2145   if (prev == gTxVariableHandler) {
2146     // No children were found.
2147     NS_ASSERTION(!var->mValue, "There shouldn't be a select-expression here");
2148     var->mValue = MakeUnique<txLiteralExpr>(EmptyString());
2149   }
2150 
2151   UniquePtr<txInstruction> instr(var.release());
2152   aState.addInstruction(std::move(instr));
2153 
2154   return NS_OK;
2155 }
2156 
2157 /*
2158     Unknown instruction
2159 
2160     [fallbacks]           if one or more xsl:fallbacks are found
2161     or
2162     txErrorInstruction    otherwise
2163 */
txFnStartUnknownInstruction(int32_t aNamespaceID,nsAtom * aLocalName,nsAtom * aPrefix,txStylesheetAttr * aAttributes,int32_t aAttrCount,txStylesheetCompilerState & aState)2164 static nsresult txFnStartUnknownInstruction(int32_t aNamespaceID,
2165                                             nsAtom* aLocalName, nsAtom* aPrefix,
2166                                             txStylesheetAttr* aAttributes,
2167                                             int32_t aAttrCount,
2168                                             txStylesheetCompilerState& aState) {
2169   NS_ASSERTION(!aState.mSearchingForFallback,
2170                "bad nesting of unknown-instruction and fallback handlers");
2171 
2172   if (aNamespaceID == kNameSpaceID_XSLT && !aState.fcp()) {
2173     return NS_ERROR_XSLT_PARSE_FAILURE;
2174   }
2175 
2176   aState.mSearchingForFallback = true;
2177 
2178   return aState.pushHandlerTable(gTxFallbackHandler);
2179 }
2180 
txFnEndUnknownInstruction(txStylesheetCompilerState & aState)2181 static nsresult txFnEndUnknownInstruction(txStylesheetCompilerState& aState) {
2182   aState.popHandlerTable();
2183 
2184   if (aState.mSearchingForFallback) {
2185     UniquePtr<txInstruction> instr(new txErrorInstruction());
2186     aState.addInstruction(std::move(instr));
2187   }
2188 
2189   aState.mSearchingForFallback = false;
2190 
2191   return NS_OK;
2192 }
2193 
2194 /**
2195  * Table Datas
2196  */
2197 
2198 struct txHandlerTableData {
2199   txElementHandler mOtherHandler;
2200   txElementHandler mLREHandler;
2201   HandleTextFn mTextHandler;
2202 };
2203 
2204 const txHandlerTableData gTxIgnoreTableData = {
2205     // Other
2206     {0, 0, txFnStartElementIgnore, txFnEndElementIgnore},
2207     // LRE
2208     {0, 0, txFnStartElementIgnore, txFnEndElementIgnore},
2209     // Text
2210     txFnTextIgnore};
2211 
2212 const txElementHandler gTxRootElementHandlers[] = {
2213     {kNameSpaceID_XSLT, "stylesheet", txFnStartStylesheet, txFnEndStylesheet},
2214     {kNameSpaceID_XSLT, "transform", txFnStartStylesheet, txFnEndStylesheet}};
2215 
2216 const txHandlerTableData gTxRootTableData = {
2217     // Other
2218     {0, 0, txFnStartElementError, txFnEndElementError},
2219     // LRE
2220     {0, 0, txFnStartLREStylesheet, txFnEndLREStylesheet},
2221     // Text
2222     txFnTextError};
2223 
2224 const txHandlerTableData gTxEmbedTableData = {
2225     // Other
2226     {0, 0, txFnStartEmbed, txFnEndEmbed},
2227     // LRE
2228     {0, 0, txFnStartEmbed, txFnEndEmbed},
2229     // Text
2230     txFnTextIgnore};
2231 
2232 const txElementHandler gTxTopElementHandlers[] = {
2233     {kNameSpaceID_XSLT, "attribute-set", txFnStartAttributeSet,
2234      txFnEndAttributeSet},
2235     {kNameSpaceID_XSLT, "decimal-format", txFnStartDecimalFormat,
2236      txFnEndDecimalFormat},
2237     {kNameSpaceID_XSLT, "include", txFnStartInclude, txFnEndInclude},
2238     {kNameSpaceID_XSLT, "key", txFnStartKey, txFnEndKey},
2239     {kNameSpaceID_XSLT, "namespace-alias", txFnStartNamespaceAlias,
2240      txFnEndNamespaceAlias},
2241     {kNameSpaceID_XSLT, "output", txFnStartOutput, txFnEndOutput},
2242     {kNameSpaceID_XSLT, "param", txFnStartTopVariable, txFnEndTopVariable},
2243     {kNameSpaceID_XSLT, "preserve-space", txFnStartStripSpace,
2244      txFnEndStripSpace},
2245     {kNameSpaceID_XSLT, "strip-space", txFnStartStripSpace, txFnEndStripSpace},
2246     {kNameSpaceID_XSLT, "template", txFnStartTemplate, txFnEndTemplate},
2247     {kNameSpaceID_XSLT, "variable", txFnStartTopVariable, txFnEndTopVariable}};
2248 
2249 const txHandlerTableData gTxTopTableData = {
2250     // Other
2251     {0, 0, txFnStartOtherTop, txFnEndOtherTop},
2252     // LRE
2253     {0, 0, txFnStartOtherTop, txFnEndOtherTop},
2254     // Text
2255     txFnTextIgnore};
2256 
2257 const txElementHandler gTxTemplateElementHandlers[] = {
2258     {kNameSpaceID_XSLT, "apply-imports", txFnStartApplyImports,
2259      txFnEndApplyImports},
2260     {kNameSpaceID_XSLT, "apply-templates", txFnStartApplyTemplates,
2261      txFnEndApplyTemplates},
2262     {kNameSpaceID_XSLT, "attribute", txFnStartAttribute, txFnEndAttribute},
2263     {kNameSpaceID_XSLT, "call-template", txFnStartCallTemplate,
2264      txFnEndCallTemplate},
2265     {kNameSpaceID_XSLT, "choose", txFnStartChoose, txFnEndChoose},
2266     {kNameSpaceID_XSLT, "comment", txFnStartComment, txFnEndComment},
2267     {kNameSpaceID_XSLT, "copy", txFnStartCopy, txFnEndCopy},
2268     {kNameSpaceID_XSLT, "copy-of", txFnStartCopyOf, txFnEndCopyOf},
2269     {kNameSpaceID_XSLT, "element", txFnStartElement, txFnEndElement},
2270     {kNameSpaceID_XSLT, "fallback", txFnStartElementSetIgnore,
2271      txFnEndElementSetIgnore},
2272     {kNameSpaceID_XSLT, "for-each", txFnStartForEach, txFnEndForEach},
2273     {kNameSpaceID_XSLT, "if", txFnStartIf, txFnEndIf},
2274     {kNameSpaceID_XSLT, "message", txFnStartMessage, txFnEndMessage},
2275     {kNameSpaceID_XSLT, "number", txFnStartNumber, txFnEndNumber},
2276     {kNameSpaceID_XSLT, "processing-instruction", txFnStartPI, txFnEndPI},
2277     {kNameSpaceID_XSLT, "text", txFnStartText, txFnEndText},
2278     {kNameSpaceID_XSLT, "value-of", txFnStartValueOf, txFnEndValueOf},
2279     {kNameSpaceID_XSLT, "variable", txFnStartVariable, txFnEndVariable}};
2280 
2281 const txHandlerTableData gTxTemplateTableData = {
2282     // Other
2283     {0, 0, txFnStartUnknownInstruction, txFnEndUnknownInstruction},
2284     // LRE
2285     {0, 0, txFnStartLRE, txFnEndLRE},
2286     // Text
2287     txFnText};
2288 
2289 const txHandlerTableData gTxTextTableData = {
2290     // Other
2291     {0, 0, txFnStartElementError, txFnEndElementError},
2292     // LRE
2293     {0, 0, txFnStartElementError, txFnEndElementError},
2294     // Text
2295     txFnTextText};
2296 
2297 const txElementHandler gTxApplyTemplatesElementHandlers[] = {
2298     {kNameSpaceID_XSLT, "sort", txFnStartSort, txFnEndSort},
2299     {kNameSpaceID_XSLT, "with-param", txFnStartWithParam, txFnEndWithParam}};
2300 
2301 const txHandlerTableData gTxApplyTemplatesTableData = {
2302     // Other
2303     {0, 0, txFnStartElementSetIgnore,
2304      txFnEndElementSetIgnore},  // should this be error?
2305     // LRE
2306     {0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore},
2307     // Text
2308     txFnTextIgnore};
2309 
2310 const txElementHandler gTxCallTemplateElementHandlers[] = {
2311     {kNameSpaceID_XSLT, "with-param", txFnStartWithParam, txFnEndWithParam}};
2312 
2313 const txHandlerTableData gTxCallTemplateTableData = {
2314     // Other
2315     {0, 0, txFnStartElementSetIgnore,
2316      txFnEndElementSetIgnore},  // should this be error?
2317     // LRE
2318     {0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore},
2319     // Text
2320     txFnTextIgnore};
2321 
2322 const txHandlerTableData gTxVariableTableData = {
2323     // Other
2324     {0, 0, txFnStartElementStartRTF, 0},
2325     // LRE
2326     {0, 0, txFnStartElementStartRTF, 0},
2327     // Text
2328     txFnTextStartRTF};
2329 
2330 const txElementHandler gTxForEachElementHandlers[] = {
2331     {kNameSpaceID_XSLT, "sort", txFnStartSort, txFnEndSort}};
2332 
2333 const txHandlerTableData gTxForEachTableData = {
2334     // Other
2335     {0, 0, txFnStartElementContinueTemplate, 0},
2336     // LRE
2337     {0, 0, txFnStartElementContinueTemplate, 0},
2338     // Text
2339     txFnTextContinueTemplate};
2340 
2341 const txHandlerTableData gTxTopVariableTableData = {
2342     // Other
2343     {0, 0, txFnStartElementStartTopVar, 0},
2344     // LRE
2345     {0, 0, txFnStartElementStartTopVar, 0},
2346     // Text
2347     txFnTextStartTopVar};
2348 
2349 const txElementHandler gTxChooseElementHandlers[] = {
2350     {kNameSpaceID_XSLT, "otherwise", txFnStartOtherwise, txFnEndOtherwise},
2351     {kNameSpaceID_XSLT, "when", txFnStartWhen, txFnEndWhen}};
2352 
2353 const txHandlerTableData gTxChooseTableData = {
2354     // Other
2355     {0, 0, txFnStartElementError, 0},
2356     // LRE
2357     {0, 0, txFnStartElementError, 0},
2358     // Text
2359     txFnTextError};
2360 
2361 const txElementHandler gTxParamElementHandlers[] = {
2362     {kNameSpaceID_XSLT, "param", txFnStartParam, txFnEndParam}};
2363 
2364 const txHandlerTableData gTxParamTableData = {
2365     // Other
2366     {0, 0, txFnStartElementContinueTemplate, 0},
2367     // LRE
2368     {0, 0, txFnStartElementContinueTemplate, 0},
2369     // Text
2370     txFnTextContinueTemplate};
2371 
2372 const txElementHandler gTxImportElementHandlers[] = {
2373     {kNameSpaceID_XSLT, "import", txFnStartImport, txFnEndImport}};
2374 
2375 const txHandlerTableData gTxImportTableData = {
2376     // Other
2377     {0, 0, txFnStartElementContinueTopLevel, 0},
2378     // LRE
2379     {0, 0, txFnStartOtherTop, txFnEndOtherTop},  // XXX what should we do here?
2380     // Text
2381     txFnTextIgnore  // XXX what should we do here?
2382 };
2383 
2384 const txElementHandler gTxAttributeSetElementHandlers[] = {
2385     {kNameSpaceID_XSLT, "attribute", txFnStartAttribute, txFnEndAttribute}};
2386 
2387 const txHandlerTableData gTxAttributeSetTableData = {
2388     // Other
2389     {0, 0, txFnStartElementError, 0},
2390     // LRE
2391     {0, 0, txFnStartElementError, 0},
2392     // Text
2393     txFnTextError};
2394 
2395 const txElementHandler gTxFallbackElementHandlers[] = {
2396     {kNameSpaceID_XSLT, "fallback", txFnStartFallback, txFnEndFallback}};
2397 
2398 const txHandlerTableData gTxFallbackTableData = {
2399     // Other
2400     {0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore},
2401     // LRE
2402     {0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore},
2403     // Text
2404     txFnTextIgnore};
2405 
2406 /**
2407  * txHandlerTable
2408  */
txHandlerTable(const HandleTextFn aTextHandler,const txElementHandler * aLREHandler,const txElementHandler * aOtherHandler)2409 txHandlerTable::txHandlerTable(const HandleTextFn aTextHandler,
2410                                const txElementHandler* aLREHandler,
2411                                const txElementHandler* aOtherHandler)
2412     : mTextHandler(aTextHandler),
2413       mLREHandler(aLREHandler),
2414       mOtherHandler(aOtherHandler) {}
2415 
init(const txElementHandler * aHandlers,uint32_t aCount)2416 nsresult txHandlerTable::init(const txElementHandler* aHandlers,
2417                               uint32_t aCount) {
2418   nsresult rv = NS_OK;
2419 
2420   uint32_t i;
2421   for (i = 0; i < aCount; ++i) {
2422     RefPtr<nsAtom> nameAtom = NS_Atomize(aHandlers->mLocalName);
2423     txExpandedName name(aHandlers->mNamespaceID, nameAtom);
2424     rv = mHandlers.add(name, aHandlers);
2425     NS_ENSURE_SUCCESS(rv, rv);
2426 
2427     ++aHandlers;
2428   }
2429   return NS_OK;
2430 }
2431 
find(int32_t aNamespaceID,nsAtom * aLocalName)2432 const txElementHandler* txHandlerTable::find(int32_t aNamespaceID,
2433                                              nsAtom* aLocalName) {
2434   txExpandedName name(aNamespaceID, aLocalName);
2435   const txElementHandler* handler = mHandlers.get(name);
2436   if (!handler) {
2437     handler = mOtherHandler;
2438   }
2439   return handler;
2440 }
2441 
2442 #define INIT_HANDLER(_name)                                                   \
2443   gTx##_name##Handler = new txHandlerTable(                                   \
2444       gTx##_name##TableData.mTextHandler, &gTx##_name##TableData.mLREHandler, \
2445       &gTx##_name##TableData.mOtherHandler);                                  \
2446   if (!gTx##_name##Handler) return false
2447 
2448 #define INIT_HANDLER_WITH_ELEMENT_HANDLERS(_name)                           \
2449   INIT_HANDLER(_name);                                                      \
2450                                                                             \
2451   rv = gTx##_name##Handler->init(gTx##_name##ElementHandlers,               \
2452                                  ArrayLength(gTx##_name##ElementHandlers)); \
2453   if (NS_FAILED(rv)) return false
2454 
2455 #define SHUTDOWN_HANDLER(_name) \
2456   delete gTx##_name##Handler;   \
2457   gTx##_name##Handler = nullptr
2458 
2459 // static
init()2460 bool txHandlerTable::init() {
2461   nsresult rv = NS_OK;
2462 
2463   INIT_HANDLER_WITH_ELEMENT_HANDLERS(Root);
2464   INIT_HANDLER(Embed);
2465   INIT_HANDLER_WITH_ELEMENT_HANDLERS(Top);
2466   INIT_HANDLER(Ignore);
2467   INIT_HANDLER_WITH_ELEMENT_HANDLERS(Template);
2468   INIT_HANDLER(Text);
2469   INIT_HANDLER_WITH_ELEMENT_HANDLERS(ApplyTemplates);
2470   INIT_HANDLER_WITH_ELEMENT_HANDLERS(CallTemplate);
2471   INIT_HANDLER(Variable);
2472   INIT_HANDLER_WITH_ELEMENT_HANDLERS(ForEach);
2473   INIT_HANDLER(TopVariable);
2474   INIT_HANDLER_WITH_ELEMENT_HANDLERS(Choose);
2475   INIT_HANDLER_WITH_ELEMENT_HANDLERS(Param);
2476   INIT_HANDLER_WITH_ELEMENT_HANDLERS(Import);
2477   INIT_HANDLER_WITH_ELEMENT_HANDLERS(AttributeSet);
2478   INIT_HANDLER_WITH_ELEMENT_HANDLERS(Fallback);
2479 
2480   return true;
2481 }
2482 
2483 // static
shutdown()2484 void txHandlerTable::shutdown() {
2485   SHUTDOWN_HANDLER(Root);
2486   SHUTDOWN_HANDLER(Embed);
2487   SHUTDOWN_HANDLER(Top);
2488   SHUTDOWN_HANDLER(Ignore);
2489   SHUTDOWN_HANDLER(Template);
2490   SHUTDOWN_HANDLER(Text);
2491   SHUTDOWN_HANDLER(ApplyTemplates);
2492   SHUTDOWN_HANDLER(CallTemplate);
2493   SHUTDOWN_HANDLER(Variable);
2494   SHUTDOWN_HANDLER(ForEach);
2495   SHUTDOWN_HANDLER(TopVariable);
2496   SHUTDOWN_HANDLER(Choose);
2497   SHUTDOWN_HANDLER(Param);
2498   SHUTDOWN_HANDLER(Import);
2499   SHUTDOWN_HANDLER(AttributeSet);
2500   SHUTDOWN_HANDLER(Fallback);
2501 }
2502