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