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(©->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