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