Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "mozilla/Move.h"
7 : #include "txInstructions.h"
8 : #include "nsError.h"
9 : #include "txExpr.h"
10 : #include "txStylesheet.h"
11 : #include "txNodeSetContext.h"
12 : #include "txTextHandler.h"
13 : #include "nsIConsoleService.h"
14 : #include "nsServiceManagerUtils.h"
15 : #include "txStringUtils.h"
16 : #include "nsGkAtoms.h"
17 : #include "txRtfHandler.h"
18 : #include "txNodeSorter.h"
19 : #include "txXSLTNumber.h"
20 : #include "txExecutionState.h"
21 :
22 : using mozilla::Move;
23 :
24 : nsresult
25 0 : txApplyDefaultElementTemplate::execute(txExecutionState& aEs)
26 : {
27 0 : txExecutionState::TemplateRule* rule = aEs.getCurrentTemplateRule();
28 0 : txExpandedName mode(rule->mModeNsId, rule->mModeLocalName);
29 0 : txStylesheet::ImportFrame* frame = 0;
30 : txInstruction* templ;
31 : nsresult rv =
32 0 : aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(),
33 0 : mode, &aEs, nullptr, &templ, &frame);
34 0 : NS_ENSURE_SUCCESS(rv, rv);
35 :
36 0 : aEs.pushTemplateRule(frame, mode, aEs.mTemplateParams);
37 :
38 0 : return aEs.runTemplate(templ);
39 : }
40 :
41 : nsresult
42 0 : txApplyImports::execute(txExecutionState& aEs)
43 : {
44 0 : txExecutionState::TemplateRule* rule = aEs.getCurrentTemplateRule();
45 : // The frame is set to null when there is no current template rule, or
46 : // when the current template rule is a default template. However this
47 : // instruction isn't used in default templates.
48 0 : if (!rule->mFrame) {
49 : // XXX ErrorReport: apply-imports instantiated without a current rule
50 0 : return NS_ERROR_XSLT_EXECUTION_FAILURE;
51 : }
52 :
53 0 : nsresult rv = aEs.pushParamMap(rule->mParams);
54 0 : NS_ENSURE_SUCCESS(rv, rv);
55 :
56 0 : txStylesheet::ImportFrame* frame = 0;
57 0 : txExpandedName mode(rule->mModeNsId, rule->mModeLocalName);
58 : txInstruction* templ;
59 0 : rv = aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(),
60 : mode, &aEs, rule->mFrame, &templ,
61 0 : &frame);
62 0 : NS_ENSURE_SUCCESS(rv, rv);
63 :
64 0 : aEs.pushTemplateRule(frame, mode, rule->mParams);
65 :
66 0 : rv = aEs.runTemplate(templ);
67 :
68 0 : aEs.popTemplateRule();
69 0 : aEs.popParamMap();
70 :
71 0 : return rv;
72 : }
73 :
74 0 : txApplyTemplates::txApplyTemplates(const txExpandedName& aMode)
75 0 : : mMode(aMode)
76 : {
77 0 : }
78 :
79 : nsresult
80 0 : txApplyTemplates::execute(txExecutionState& aEs)
81 : {
82 0 : txStylesheet::ImportFrame* frame = 0;
83 : txInstruction* templ;
84 : nsresult rv =
85 0 : aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(),
86 0 : mMode, &aEs, nullptr, &templ, &frame);
87 0 : NS_ENSURE_SUCCESS(rv, rv);
88 :
89 0 : aEs.pushTemplateRule(frame, mMode, aEs.mTemplateParams);
90 :
91 0 : return aEs.runTemplate(templ);
92 : }
93 :
94 0 : txAttribute::txAttribute(nsAutoPtr<Expr>&& aName, nsAutoPtr<Expr>&& aNamespace,
95 0 : txNamespaceMap* aMappings)
96 0 : : mName(Move(aName)), mNamespace(Move(aNamespace)), mMappings(aMappings)
97 : {
98 0 : }
99 :
100 : nsresult
101 0 : txAttribute::execute(txExecutionState& aEs)
102 : {
103 : nsAutoPtr<txTextHandler> handler(
104 0 : static_cast<txTextHandler*>(aEs.popResultHandler()));
105 :
106 0 : nsAutoString name;
107 0 : nsresult rv = mName->evaluateToString(aEs.getEvalContext(), name);
108 0 : NS_ENSURE_SUCCESS(rv, rv);
109 :
110 : const char16_t* colon;
111 0 : if (!XMLUtils::isValidQName(name, &colon) ||
112 0 : TX_StringEqualsAtom(name, nsGkAtoms::xmlns)) {
113 0 : return NS_OK;
114 : }
115 :
116 0 : nsCOMPtr<nsIAtom> prefix;
117 0 : uint32_t lnameStart = 0;
118 0 : if (colon) {
119 0 : prefix = NS_Atomize(Substring(name.get(), colon));
120 0 : lnameStart = colon - name.get() + 1;
121 : }
122 :
123 0 : int32_t nsId = kNameSpaceID_None;
124 0 : if (mNamespace) {
125 0 : nsAutoString nspace;
126 0 : rv = mNamespace->evaluateToString(aEs.getEvalContext(),
127 0 : nspace);
128 0 : NS_ENSURE_SUCCESS(rv, rv);
129 :
130 0 : if (!nspace.IsEmpty()) {
131 0 : nsId = txNamespaceManager::getNamespaceID(nspace);
132 : }
133 : }
134 0 : else if (colon) {
135 0 : nsId = mMappings->lookupNamespace(prefix);
136 : }
137 :
138 : // add attribute if everything was ok
139 0 : return nsId != kNameSpaceID_Unknown ?
140 0 : aEs.mResultHandler->attribute(prefix, Substring(name, lnameStart),
141 0 : nsId, handler->mValue) :
142 0 : NS_OK;
143 : }
144 :
145 0 : txCallTemplate::txCallTemplate(const txExpandedName& aName)
146 0 : : mName(aName)
147 : {
148 0 : }
149 :
150 : nsresult
151 0 : txCallTemplate::execute(txExecutionState& aEs)
152 : {
153 0 : txInstruction* instr = aEs.mStylesheet->getNamedTemplate(mName);
154 0 : NS_ENSURE_TRUE(instr, NS_ERROR_XSLT_EXECUTION_FAILURE);
155 :
156 0 : nsresult rv = aEs.runTemplate(instr);
157 0 : NS_ENSURE_SUCCESS(rv, rv);
158 :
159 0 : return NS_OK;
160 : }
161 :
162 0 : txCheckParam::txCheckParam(const txExpandedName& aName)
163 0 : : mName(aName), mBailTarget(nullptr)
164 : {
165 0 : }
166 :
167 : nsresult
168 0 : txCheckParam::execute(txExecutionState& aEs)
169 : {
170 0 : nsresult rv = NS_OK;
171 0 : if (aEs.mTemplateParams) {
172 0 : RefPtr<txAExprResult> exprRes;
173 0 : aEs.mTemplateParams->getVariable(mName, getter_AddRefs(exprRes));
174 0 : if (exprRes) {
175 0 : rv = aEs.bindVariable(mName, exprRes);
176 0 : NS_ENSURE_SUCCESS(rv, rv);
177 :
178 0 : aEs.gotoInstruction(mBailTarget);
179 : }
180 : }
181 :
182 0 : return NS_OK;
183 : }
184 :
185 0 : txConditionalGoto::txConditionalGoto(nsAutoPtr<Expr>&& aCondition,
186 0 : txInstruction* aTarget)
187 0 : : mCondition(Move(aCondition)), mTarget(aTarget)
188 : {
189 0 : }
190 :
191 : nsresult
192 0 : txConditionalGoto::execute(txExecutionState& aEs)
193 : {
194 : bool exprRes;
195 0 : nsresult rv = mCondition->evaluateToBool(aEs.getEvalContext(), exprRes);
196 0 : NS_ENSURE_SUCCESS(rv, rv);
197 :
198 0 : if (!exprRes) {
199 0 : aEs.gotoInstruction(mTarget);
200 : }
201 :
202 0 : return NS_OK;
203 : }
204 :
205 : nsresult
206 0 : txComment::execute(txExecutionState& aEs)
207 : {
208 : nsAutoPtr<txTextHandler> handler(
209 0 : static_cast<txTextHandler*>(aEs.popResultHandler()));
210 0 : uint32_t length = handler->mValue.Length();
211 0 : int32_t pos = 0;
212 0 : while ((pos = handler->mValue.FindChar('-', (uint32_t)pos)) != kNotFound) {
213 0 : ++pos;
214 0 : if ((uint32_t)pos == length || handler->mValue.CharAt(pos) == '-') {
215 0 : handler->mValue.Insert(char16_t(' '), pos++);
216 0 : ++length;
217 : }
218 : }
219 :
220 0 : return aEs.mResultHandler->comment(handler->mValue);
221 : }
222 :
223 : nsresult
224 0 : txCopyBase::copyNode(const txXPathNode& aNode, txExecutionState& aEs)
225 : {
226 0 : switch (txXPathNodeUtils::getNodeType(aNode)) {
227 : case txXPathNodeType::ATTRIBUTE_NODE:
228 : {
229 0 : nsAutoString nodeValue;
230 0 : txXPathNodeUtils::appendNodeValue(aNode, nodeValue);
231 :
232 : nsCOMPtr<nsIAtom> localName =
233 0 : txXPathNodeUtils::getLocalName(aNode);
234 0 : return aEs.mResultHandler->
235 0 : attribute(txXPathNodeUtils::getPrefix(aNode),
236 : localName, nullptr,
237 : txXPathNodeUtils::getNamespaceID(aNode),
238 0 : nodeValue);
239 : }
240 : case txXPathNodeType::COMMENT_NODE:
241 : {
242 0 : nsAutoString nodeValue;
243 0 : txXPathNodeUtils::appendNodeValue(aNode, nodeValue);
244 0 : return aEs.mResultHandler->comment(nodeValue);
245 : }
246 : case txXPathNodeType::DOCUMENT_NODE:
247 : case txXPathNodeType::DOCUMENT_FRAGMENT_NODE:
248 : {
249 : // Copy children
250 0 : txXPathTreeWalker walker(aNode);
251 0 : bool hasChild = walker.moveToFirstChild();
252 0 : while (hasChild) {
253 0 : copyNode(walker.getCurrentPosition(), aEs);
254 0 : hasChild = walker.moveToNextSibling();
255 : }
256 0 : break;
257 : }
258 : case txXPathNodeType::ELEMENT_NODE:
259 : {
260 : nsCOMPtr<nsIAtom> localName =
261 0 : txXPathNodeUtils::getLocalName(aNode);
262 0 : nsresult rv = aEs.mResultHandler->
263 0 : startElement(txXPathNodeUtils::getPrefix(aNode),
264 : localName, nullptr,
265 0 : txXPathNodeUtils::getNamespaceID(aNode));
266 0 : NS_ENSURE_SUCCESS(rv, rv);
267 :
268 : // Copy attributes
269 0 : txXPathTreeWalker walker(aNode);
270 0 : if (walker.moveToFirstAttribute()) {
271 0 : do {
272 0 : nsAutoString nodeValue;
273 0 : walker.appendNodeValue(nodeValue);
274 :
275 0 : const txXPathNode& attr = walker.getCurrentPosition();
276 0 : localName = txXPathNodeUtils::getLocalName(attr);
277 0 : rv = aEs.mResultHandler->
278 0 : attribute(txXPathNodeUtils::getPrefix(attr),
279 : localName, nullptr,
280 : txXPathNodeUtils::getNamespaceID(attr),
281 0 : nodeValue);
282 0 : NS_ENSURE_SUCCESS(rv, rv);
283 : } while (walker.moveToNextAttribute());
284 0 : walker.moveToParent();
285 : }
286 :
287 : // Copy children
288 0 : bool hasChild = walker.moveToFirstChild();
289 0 : while (hasChild) {
290 0 : copyNode(walker.getCurrentPosition(), aEs);
291 0 : hasChild = walker.moveToNextSibling();
292 : }
293 :
294 0 : return aEs.mResultHandler->endElement();
295 : }
296 : case txXPathNodeType::PROCESSING_INSTRUCTION_NODE:
297 : {
298 0 : nsAutoString target, data;
299 0 : txXPathNodeUtils::getNodeName(aNode, target);
300 0 : txXPathNodeUtils::appendNodeValue(aNode, data);
301 0 : return aEs.mResultHandler->processingInstruction(target, data);
302 : }
303 : case txXPathNodeType::TEXT_NODE:
304 : case txXPathNodeType::CDATA_SECTION_NODE:
305 : {
306 0 : nsAutoString nodeValue;
307 0 : txXPathNodeUtils::appendNodeValue(aNode, nodeValue);
308 0 : return aEs.mResultHandler->characters(nodeValue, false);
309 : }
310 : }
311 :
312 0 : return NS_OK;
313 : }
314 :
315 0 : txCopy::txCopy()
316 0 : : mBailTarget(nullptr)
317 : {
318 0 : }
319 :
320 : nsresult
321 0 : txCopy::execute(txExecutionState& aEs)
322 : {
323 0 : nsresult rv = NS_OK;
324 0 : const txXPathNode& node = aEs.getEvalContext()->getContextNode();
325 :
326 0 : switch (txXPathNodeUtils::getNodeType(node)) {
327 : case txXPathNodeType::DOCUMENT_NODE:
328 : case txXPathNodeType::DOCUMENT_FRAGMENT_NODE:
329 : {
330 0 : const nsString& empty = EmptyString();
331 :
332 : // "close" current element to ensure that no attributes are added
333 0 : rv = aEs.mResultHandler->characters(empty, false);
334 0 : NS_ENSURE_SUCCESS(rv, rv);
335 :
336 0 : rv = aEs.pushBool(false);
337 0 : NS_ENSURE_SUCCESS(rv, rv);
338 :
339 0 : break;
340 : }
341 : case txXPathNodeType::ELEMENT_NODE:
342 : {
343 : nsCOMPtr<nsIAtom> localName =
344 0 : txXPathNodeUtils::getLocalName(node);
345 0 : rv = aEs.mResultHandler->
346 0 : startElement(txXPathNodeUtils::getPrefix(node),
347 : localName, nullptr,
348 0 : txXPathNodeUtils::getNamespaceID(node));
349 0 : NS_ENSURE_SUCCESS(rv, rv);
350 :
351 : // XXX copy namespace nodes once we have them
352 :
353 0 : rv = aEs.pushBool(true);
354 0 : NS_ENSURE_SUCCESS(rv, rv);
355 :
356 0 : break;
357 : }
358 : default:
359 : {
360 0 : rv = copyNode(node, aEs);
361 0 : NS_ENSURE_SUCCESS(rv, rv);
362 :
363 0 : aEs.gotoInstruction(mBailTarget);
364 : }
365 : }
366 :
367 0 : return NS_OK;
368 : }
369 :
370 0 : txCopyOf::txCopyOf(nsAutoPtr<Expr>&& aSelect)
371 0 : : mSelect(Move(aSelect))
372 : {
373 0 : }
374 :
375 : nsresult
376 0 : txCopyOf::execute(txExecutionState& aEs)
377 : {
378 0 : RefPtr<txAExprResult> exprRes;
379 0 : nsresult rv = mSelect->evaluate(aEs.getEvalContext(),
380 0 : getter_AddRefs(exprRes));
381 0 : NS_ENSURE_SUCCESS(rv, rv);
382 :
383 0 : switch (exprRes->getResultType()) {
384 : case txAExprResult::NODESET:
385 : {
386 : txNodeSet* nodes = static_cast<txNodeSet*>
387 : (static_cast<txAExprResult*>
388 0 : (exprRes));
389 : int32_t i;
390 0 : for (i = 0; i < nodes->size(); ++i) {
391 0 : rv = copyNode(nodes->get(i), aEs);
392 0 : NS_ENSURE_SUCCESS(rv, rv);
393 : }
394 0 : break;
395 : }
396 : case txAExprResult::RESULT_TREE_FRAGMENT:
397 : {
398 : txResultTreeFragment* rtf =
399 : static_cast<txResultTreeFragment*>
400 0 : (static_cast<txAExprResult*>(exprRes));
401 0 : return rtf->flushToHandler(aEs.mResultHandler);
402 : }
403 : default:
404 : {
405 0 : nsAutoString value;
406 0 : exprRes->stringValue(value);
407 0 : if (!value.IsEmpty()) {
408 0 : return aEs.mResultHandler->characters(value, false);
409 : }
410 0 : break;
411 : }
412 : }
413 :
414 0 : return NS_OK;
415 : }
416 :
417 : nsresult
418 0 : txEndElement::execute(txExecutionState& aEs)
419 : {
420 : // This will return false if startElement was not called. This happens
421 : // when <xsl:element> produces a bad name, or when <xsl:copy> copies a
422 : // document node.
423 0 : if (aEs.popBool()) {
424 0 : return aEs.mResultHandler->endElement();
425 : }
426 :
427 0 : return NS_OK;
428 : }
429 :
430 : nsresult
431 0 : txErrorInstruction::execute(txExecutionState& aEs)
432 : {
433 : // XXX ErrorReport: unknown instruction executed
434 0 : return NS_ERROR_XSLT_EXECUTION_FAILURE;
435 : }
436 :
437 0 : txGoTo::txGoTo(txInstruction* aTarget)
438 0 : : mTarget(aTarget)
439 : {
440 0 : }
441 :
442 : nsresult
443 0 : txGoTo::execute(txExecutionState& aEs)
444 : {
445 0 : aEs.gotoInstruction(mTarget);
446 :
447 0 : return NS_OK;
448 : }
449 :
450 0 : txInsertAttrSet::txInsertAttrSet(const txExpandedName& aName)
451 0 : : mName(aName)
452 : {
453 0 : }
454 :
455 : nsresult
456 0 : txInsertAttrSet::execute(txExecutionState& aEs)
457 : {
458 0 : txInstruction* instr = aEs.mStylesheet->getAttributeSet(mName);
459 0 : NS_ENSURE_TRUE(instr, NS_ERROR_XSLT_EXECUTION_FAILURE);
460 :
461 0 : nsresult rv = aEs.runTemplate(instr);
462 0 : NS_ENSURE_SUCCESS(rv, rv);
463 :
464 0 : return NS_OK;
465 : }
466 :
467 0 : txLoopNodeSet::txLoopNodeSet(txInstruction* aTarget)
468 0 : : mTarget(aTarget)
469 : {
470 0 : }
471 :
472 : nsresult
473 0 : txLoopNodeSet::execute(txExecutionState& aEs)
474 : {
475 0 : aEs.popTemplateRule();
476 : txNodeSetContext* context =
477 0 : static_cast<txNodeSetContext*>(aEs.getEvalContext());
478 0 : if (!context->hasNext()) {
479 0 : delete aEs.popEvalContext();
480 :
481 0 : return NS_OK;
482 : }
483 :
484 0 : context->next();
485 0 : aEs.gotoInstruction(mTarget);
486 :
487 0 : return NS_OK;
488 : }
489 :
490 0 : txLREAttribute::txLREAttribute(int32_t aNamespaceID, nsIAtom* aLocalName,
491 0 : nsIAtom* aPrefix, nsAutoPtr<Expr>&& aValue)
492 : : mNamespaceID(aNamespaceID),
493 : mLocalName(aLocalName),
494 : mPrefix(aPrefix),
495 0 : mValue(Move(aValue))
496 : {
497 0 : if (aNamespaceID == kNameSpaceID_None) {
498 0 : mLowercaseLocalName = TX_ToLowerCaseAtom(aLocalName);
499 : }
500 0 : }
501 :
502 : nsresult
503 0 : txLREAttribute::execute(txExecutionState& aEs)
504 : {
505 0 : RefPtr<txAExprResult> exprRes;
506 0 : nsresult rv = mValue->evaluate(aEs.getEvalContext(),
507 0 : getter_AddRefs(exprRes));
508 0 : NS_ENSURE_SUCCESS(rv, rv);
509 :
510 0 : const nsString* value = exprRes->stringValuePointer();
511 0 : if (value) {
512 0 : return aEs.mResultHandler->attribute(mPrefix, mLocalName,
513 : mLowercaseLocalName,
514 0 : mNamespaceID, *value);
515 : }
516 :
517 0 : nsAutoString valueStr;
518 0 : exprRes->stringValue(valueStr);
519 0 : return aEs.mResultHandler->attribute(mPrefix, mLocalName,
520 : mLowercaseLocalName,
521 0 : mNamespaceID, valueStr);
522 : }
523 :
524 0 : txMessage::txMessage(bool aTerminate)
525 0 : : mTerminate(aTerminate)
526 : {
527 0 : }
528 :
529 : nsresult
530 0 : txMessage::execute(txExecutionState& aEs)
531 : {
532 : nsAutoPtr<txTextHandler> handler(
533 0 : static_cast<txTextHandler*>(aEs.popResultHandler()));
534 :
535 : nsCOMPtr<nsIConsoleService> consoleSvc =
536 0 : do_GetService("@mozilla.org/consoleservice;1");
537 0 : if (consoleSvc) {
538 0 : nsAutoString logString(NS_LITERAL_STRING("xsl:message - "));
539 0 : logString.Append(handler->mValue);
540 0 : consoleSvc->LogStringMessage(logString.get());
541 : }
542 :
543 0 : return mTerminate ? NS_ERROR_XSLT_ABORTED : NS_OK;
544 : }
545 :
546 0 : txNumber::txNumber(txXSLTNumber::LevelType aLevel,
547 : nsAutoPtr<txPattern>&& aCount, nsAutoPtr<txPattern>&& aFrom,
548 : nsAutoPtr<Expr>&& aValue, nsAutoPtr<Expr>&& aFormat,
549 : nsAutoPtr<Expr>&& aGroupingSeparator,
550 0 : nsAutoPtr<Expr>&& aGroupingSize)
551 0 : : mLevel(aLevel), mCount(Move(aCount)),
552 0 : mFrom(Move(aFrom)),
553 0 : mValue(Move(aValue)),
554 0 : mFormat(Move(aFormat)),
555 0 : mGroupingSeparator(Move(aGroupingSeparator)),
556 0 : mGroupingSize(Move(aGroupingSize))
557 : {
558 0 : }
559 :
560 : nsresult
561 0 : txNumber::execute(txExecutionState& aEs)
562 : {
563 0 : nsAutoString res;
564 : nsresult rv =
565 0 : txXSLTNumber::createNumber(mValue, mCount, mFrom, mLevel, mGroupingSize,
566 : mGroupingSeparator, mFormat,
567 0 : aEs.getEvalContext(), res);
568 0 : NS_ENSURE_SUCCESS(rv, rv);
569 :
570 0 : return aEs.mResultHandler->characters(res, false);
571 : }
572 :
573 : nsresult
574 0 : txPopParams::execute(txExecutionState& aEs)
575 : {
576 0 : delete aEs.popParamMap();
577 :
578 0 : return NS_OK;
579 : }
580 :
581 0 : txProcessingInstruction::txProcessingInstruction(nsAutoPtr<Expr>&& aName)
582 0 : : mName(Move(aName))
583 : {
584 0 : }
585 :
586 : nsresult
587 0 : txProcessingInstruction::execute(txExecutionState& aEs)
588 : {
589 : nsAutoPtr<txTextHandler> handler(
590 0 : static_cast<txTextHandler*>(aEs.popResultHandler()));
591 0 : XMLUtils::normalizePIValue(handler->mValue);
592 :
593 0 : nsAutoString name;
594 0 : nsresult rv = mName->evaluateToString(aEs.getEvalContext(), name);
595 0 : NS_ENSURE_SUCCESS(rv, rv);
596 :
597 : // Check name validity (must be valid NCName and a PITarget)
598 : // XXX Need to check for NCName and PITarget
599 : const char16_t* colon;
600 0 : if (!XMLUtils::isValidQName(name, &colon)) {
601 : // XXX ErrorReport: bad PI-target
602 0 : return NS_ERROR_FAILURE;
603 : }
604 :
605 0 : return aEs.mResultHandler->processingInstruction(name, handler->mValue);
606 : }
607 :
608 0 : txPushNewContext::txPushNewContext(nsAutoPtr<Expr>&& aSelect)
609 0 : : mSelect(Move(aSelect)), mBailTarget(nullptr)
610 : {
611 0 : }
612 :
613 0 : txPushNewContext::~txPushNewContext()
614 : {
615 0 : }
616 :
617 : nsresult
618 0 : txPushNewContext::execute(txExecutionState& aEs)
619 : {
620 0 : RefPtr<txAExprResult> exprRes;
621 0 : nsresult rv = mSelect->evaluate(aEs.getEvalContext(),
622 0 : getter_AddRefs(exprRes));
623 0 : NS_ENSURE_SUCCESS(rv, rv);
624 :
625 0 : if (exprRes->getResultType() != txAExprResult::NODESET) {
626 : // XXX ErrorReport: nodeset expected
627 0 : return NS_ERROR_XSLT_NODESET_EXPECTED;
628 : }
629 :
630 : txNodeSet* nodes = static_cast<txNodeSet*>
631 : (static_cast<txAExprResult*>
632 0 : (exprRes));
633 :
634 0 : if (nodes->isEmpty()) {
635 0 : aEs.gotoInstruction(mBailTarget);
636 :
637 0 : return NS_OK;
638 : }
639 :
640 0 : txNodeSorter sorter;
641 0 : uint32_t i, count = mSortKeys.Length();
642 0 : for (i = 0; i < count; ++i) {
643 0 : SortKey& sort = mSortKeys[i];
644 0 : rv = sorter.addSortElement(sort.mSelectExpr, sort.mLangExpr,
645 : sort.mDataTypeExpr, sort.mOrderExpr,
646 : sort.mCaseOrderExpr,
647 0 : aEs.getEvalContext());
648 0 : NS_ENSURE_SUCCESS(rv, rv);
649 : }
650 0 : RefPtr<txNodeSet> sortedNodes;
651 0 : rv = sorter.sortNodeSet(nodes, &aEs, getter_AddRefs(sortedNodes));
652 0 : NS_ENSURE_SUCCESS(rv, rv);
653 :
654 0 : txNodeSetContext* context = new txNodeSetContext(sortedNodes, &aEs);
655 0 : NS_ENSURE_TRUE(context, NS_ERROR_OUT_OF_MEMORY);
656 :
657 0 : context->next();
658 :
659 0 : rv = aEs.pushEvalContext(context);
660 0 : if (NS_FAILED(rv)) {
661 0 : delete context;
662 0 : return rv;
663 : }
664 :
665 0 : return NS_OK;
666 : }
667 :
668 : nsresult
669 0 : txPushNewContext::addSort(nsAutoPtr<Expr>&& aSelectExpr,
670 : nsAutoPtr<Expr>&& aLangExpr,
671 : nsAutoPtr<Expr>&& aDataTypeExpr,
672 : nsAutoPtr<Expr>&& aOrderExpr,
673 : nsAutoPtr<Expr>&& aCaseOrderExpr)
674 : {
675 0 : if (SortKey *key = mSortKeys.AppendElement()) {
676 : // workaround for not triggering the Copy Constructor
677 0 : key->mSelectExpr = Move(aSelectExpr);
678 0 : key->mLangExpr = Move(aLangExpr);
679 0 : key->mDataTypeExpr = Move(aDataTypeExpr);
680 0 : key->mOrderExpr = Move(aOrderExpr);
681 0 : key->mCaseOrderExpr = Move(aCaseOrderExpr);
682 0 : return NS_OK;
683 : }
684 0 : return NS_ERROR_OUT_OF_MEMORY;
685 : }
686 :
687 : nsresult
688 0 : txPushNullTemplateRule::execute(txExecutionState& aEs)
689 : {
690 0 : aEs.pushTemplateRule(nullptr, txExpandedName(), nullptr);
691 0 : return NS_OK;
692 : }
693 :
694 : nsresult
695 0 : txPushParams::execute(txExecutionState& aEs)
696 : {
697 0 : return aEs.pushParamMap(nullptr);
698 : }
699 :
700 : nsresult
701 0 : txPushRTFHandler::execute(txExecutionState& aEs)
702 : {
703 0 : txAXMLEventHandler* handler = new txRtfHandler;
704 0 : nsresult rv = aEs.pushResultHandler(handler);
705 0 : if (NS_FAILED(rv)) {
706 0 : delete handler;
707 0 : return rv;
708 : }
709 :
710 0 : return NS_OK;
711 : }
712 :
713 0 : txPushStringHandler::txPushStringHandler(bool aOnlyText)
714 0 : : mOnlyText(aOnlyText)
715 : {
716 0 : }
717 :
718 : nsresult
719 0 : txPushStringHandler::execute(txExecutionState& aEs)
720 : {
721 0 : txAXMLEventHandler* handler = new txTextHandler(mOnlyText);
722 0 : nsresult rv = aEs.pushResultHandler(handler);
723 0 : if (NS_FAILED(rv)) {
724 0 : delete handler;
725 0 : return rv;
726 : }
727 :
728 0 : return NS_OK;
729 : }
730 :
731 0 : txRemoveVariable::txRemoveVariable(const txExpandedName& aName)
732 0 : : mName(aName)
733 : {
734 0 : }
735 :
736 : nsresult
737 0 : txRemoveVariable::execute(txExecutionState& aEs)
738 : {
739 0 : aEs.removeVariable(mName);
740 :
741 0 : return NS_OK;
742 : }
743 :
744 : nsresult
745 0 : txReturn::execute(txExecutionState& aEs)
746 : {
747 0 : NS_ASSERTION(!mNext, "instructions exist after txReturn");
748 0 : aEs.returnFromTemplate();
749 :
750 0 : return NS_OK;
751 : }
752 :
753 0 : txSetParam::txSetParam(const txExpandedName& aName, nsAutoPtr<Expr>&& aValue)
754 0 : : mName(aName), mValue(Move(aValue))
755 : {
756 0 : }
757 :
758 : nsresult
759 0 : txSetParam::execute(txExecutionState& aEs)
760 : {
761 0 : nsresult rv = NS_OK;
762 0 : if (!aEs.mTemplateParams) {
763 0 : aEs.mTemplateParams = new txVariableMap;
764 0 : NS_ENSURE_TRUE(aEs.mTemplateParams, NS_ERROR_OUT_OF_MEMORY);
765 : }
766 :
767 0 : RefPtr<txAExprResult> exprRes;
768 0 : if (mValue) {
769 0 : rv = mValue->evaluate(aEs.getEvalContext(),
770 0 : getter_AddRefs(exprRes));
771 0 : NS_ENSURE_SUCCESS(rv, rv);
772 : }
773 : else {
774 : nsAutoPtr<txRtfHandler> rtfHandler(
775 0 : static_cast<txRtfHandler*>(aEs.popResultHandler()));
776 0 : rv = rtfHandler->getAsRTF(getter_AddRefs(exprRes));
777 0 : NS_ENSURE_SUCCESS(rv, rv);
778 : }
779 :
780 0 : rv = aEs.mTemplateParams->bindVariable(mName, exprRes);
781 0 : NS_ENSURE_SUCCESS(rv, rv);
782 :
783 0 : return NS_OK;
784 : }
785 :
786 0 : txSetVariable::txSetVariable(const txExpandedName& aName,
787 0 : nsAutoPtr<Expr>&& aValue)
788 0 : : mName(aName), mValue(Move(aValue))
789 : {
790 0 : }
791 :
792 : nsresult
793 0 : txSetVariable::execute(txExecutionState& aEs)
794 : {
795 0 : nsresult rv = NS_OK;
796 0 : RefPtr<txAExprResult> exprRes;
797 0 : if (mValue) {
798 0 : rv = mValue->evaluate(aEs.getEvalContext(), getter_AddRefs(exprRes));
799 0 : NS_ENSURE_SUCCESS(rv, rv);
800 : }
801 : else {
802 : nsAutoPtr<txRtfHandler> rtfHandler(
803 0 : static_cast<txRtfHandler*>(aEs.popResultHandler()));
804 0 : rv = rtfHandler->getAsRTF(getter_AddRefs(exprRes));
805 0 : NS_ENSURE_SUCCESS(rv, rv);
806 : }
807 :
808 0 : return aEs.bindVariable(mName, exprRes);
809 : }
810 :
811 0 : txStartElement::txStartElement(nsAutoPtr<Expr>&& aName,
812 : nsAutoPtr<Expr>&& aNamespace,
813 0 : txNamespaceMap* aMappings)
814 0 : : mName(Move(aName)),
815 0 : mNamespace(Move(aNamespace)),
816 0 : mMappings(aMappings)
817 : {
818 0 : }
819 :
820 : nsresult
821 0 : txStartElement::execute(txExecutionState& aEs)
822 : {
823 0 : nsAutoString name;
824 0 : nsresult rv = mName->evaluateToString(aEs.getEvalContext(), name);
825 0 : NS_ENSURE_SUCCESS(rv, rv);
826 :
827 :
828 0 : int32_t nsId = kNameSpaceID_None;
829 0 : nsCOMPtr<nsIAtom> prefix;
830 0 : uint32_t lnameStart = 0;
831 :
832 : const char16_t* colon;
833 0 : if (XMLUtils::isValidQName(name, &colon)) {
834 0 : if (colon) {
835 0 : prefix = NS_Atomize(Substring(name.get(), colon));
836 0 : lnameStart = colon - name.get() + 1;
837 : }
838 :
839 0 : if (mNamespace) {
840 0 : nsAutoString nspace;
841 0 : rv = mNamespace->evaluateToString(aEs.getEvalContext(),
842 0 : nspace);
843 0 : NS_ENSURE_SUCCESS(rv, rv);
844 :
845 0 : if (!nspace.IsEmpty()) {
846 0 : nsId = txNamespaceManager::getNamespaceID(nspace);
847 : }
848 : }
849 : else {
850 0 : nsId = mMappings->lookupNamespace(prefix);
851 : }
852 : }
853 : else {
854 0 : nsId = kNameSpaceID_Unknown;
855 : }
856 :
857 0 : bool success = true;
858 :
859 0 : if (nsId != kNameSpaceID_Unknown) {
860 0 : rv = aEs.mResultHandler->startElement(prefix,
861 0 : Substring(name, lnameStart),
862 0 : nsId);
863 : }
864 : else {
865 0 : rv = NS_ERROR_XSLT_BAD_NODE_NAME;
866 : }
867 :
868 0 : if (rv == NS_ERROR_XSLT_BAD_NODE_NAME) {
869 0 : success = false;
870 : // we call characters with an empty string to "close" any element to
871 : // make sure that no attributes are added
872 0 : rv = aEs.mResultHandler->characters(EmptyString(), false);
873 : }
874 0 : NS_ENSURE_SUCCESS(rv, rv);
875 :
876 0 : rv = aEs.pushBool(success);
877 0 : NS_ENSURE_SUCCESS(rv, rv);
878 :
879 0 : return NS_OK;
880 : }
881 :
882 :
883 0 : txStartLREElement::txStartLREElement(int32_t aNamespaceID,
884 : nsIAtom* aLocalName,
885 0 : nsIAtom* aPrefix)
886 : : mNamespaceID(aNamespaceID),
887 : mLocalName(aLocalName),
888 0 : mPrefix(aPrefix)
889 : {
890 0 : if (aNamespaceID == kNameSpaceID_None) {
891 0 : mLowercaseLocalName = TX_ToLowerCaseAtom(aLocalName);
892 : }
893 0 : }
894 :
895 : nsresult
896 0 : txStartLREElement::execute(txExecutionState& aEs)
897 : {
898 0 : nsresult rv = aEs.mResultHandler->startElement(mPrefix, mLocalName,
899 : mLowercaseLocalName,
900 0 : mNamespaceID);
901 0 : NS_ENSURE_SUCCESS(rv, rv);
902 :
903 0 : rv = aEs.pushBool(true);
904 0 : NS_ENSURE_SUCCESS(rv, rv);
905 :
906 0 : return NS_OK;
907 : }
908 :
909 0 : txText::txText(const nsAString& aStr, bool aDOE)
910 : : mStr(aStr),
911 0 : mDOE(aDOE)
912 : {
913 0 : }
914 :
915 : nsresult
916 0 : txText::execute(txExecutionState& aEs)
917 : {
918 0 : return aEs.mResultHandler->characters(mStr, mDOE);
919 : }
920 :
921 0 : txValueOf::txValueOf(nsAutoPtr<Expr>&& aExpr, bool aDOE)
922 0 : : mExpr(Move(aExpr)),
923 0 : mDOE(aDOE)
924 : {
925 0 : }
926 :
927 : nsresult
928 0 : txValueOf::execute(txExecutionState& aEs)
929 : {
930 0 : RefPtr<txAExprResult> exprRes;
931 0 : nsresult rv = mExpr->evaluate(aEs.getEvalContext(),
932 0 : getter_AddRefs(exprRes));
933 0 : NS_ENSURE_SUCCESS(rv, rv);
934 :
935 0 : const nsString* value = exprRes->stringValuePointer();
936 0 : if (value) {
937 0 : if (!value->IsEmpty()) {
938 0 : return aEs.mResultHandler->characters(*value, mDOE);
939 : }
940 : }
941 : else {
942 0 : nsAutoString valueStr;
943 0 : exprRes->stringValue(valueStr);
944 0 : if (!valueStr.IsEmpty()) {
945 0 : return aEs.mResultHandler->characters(valueStr, mDOE);
946 : }
947 : }
948 :
949 0 : return NS_OK;
950 : }
|