LCOV - code coverage report
Current view: top level - dom/xslt/xslt - txExecutionState.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 264 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 33 0.0 %
Legend: Lines: hit not hit

          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 "txExecutionState.h"
       7             : #include "txSingleNodeContext.h"
       8             : #include "txInstructions.h"
       9             : #include "txStylesheet.h"
      10             : #include "txVariableMap.h"
      11             : #include "txRtfHandler.h"
      12             : #include "txXSLTProcessor.h"
      13             : #include "txLog.h"
      14             : #include "txURIUtils.h"
      15             : #include "txXMLParser.h"
      16             : 
      17             : const int32_t txExecutionState::kMaxRecursionDepth = 20000;
      18             : 
      19             : nsresult
      20           0 : txLoadedDocumentsHash::init(txXPathNode* aSourceDocument)
      21             : {
      22           0 :     mSourceDocument = aSourceDocument;
      23             : 
      24           0 :     nsAutoString baseURI;
      25           0 :     nsresult rv = txXPathNodeUtils::getBaseURI(*mSourceDocument, baseURI);
      26           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
      27           0 :         return rv;
      28             :     }
      29             : 
      30           0 :     PutEntry(baseURI)->mDocument = mSourceDocument;
      31           0 :     return NS_OK;
      32             : }
      33             : 
      34           0 : txLoadedDocumentsHash::~txLoadedDocumentsHash()
      35             : {
      36           0 :     if (mSourceDocument) {
      37           0 :         nsAutoString baseURI;
      38           0 :         nsresult rv = txXPathNodeUtils::getBaseURI(*mSourceDocument, baseURI);
      39           0 :         if (NS_SUCCEEDED(rv)) {
      40           0 :             txLoadedDocumentEntry* entry = GetEntry(baseURI);
      41           0 :             if (entry) {
      42           0 :                 delete entry->mDocument.forget();
      43             :             }
      44             :        }
      45             :     }
      46           0 : }
      47             : 
      48           0 : txExecutionState::txExecutionState(txStylesheet* aStylesheet,
      49           0 :                                    bool aDisableLoads)
      50             :     : mOutputHandler(nullptr),
      51             :       mResultHandler(nullptr),
      52             :       mStylesheet(aStylesheet),
      53             :       mNextInstruction(nullptr),
      54             :       mLocalVariables(nullptr),
      55             :       mRecursionDepth(0),
      56             :       mEvalContext(nullptr),
      57             :       mInitialEvalContext(nullptr),
      58             :       mGlobalParams(nullptr),
      59             :       mKeyHash(aStylesheet->getKeyMap()),
      60           0 :       mDisableLoads(aDisableLoads)
      61             : {
      62           0 :     MOZ_COUNT_CTOR(txExecutionState);
      63           0 : }
      64             : 
      65           0 : txExecutionState::~txExecutionState()
      66             : {
      67           0 :     MOZ_COUNT_DTOR(txExecutionState);
      68             : 
      69           0 :     delete mResultHandler;
      70           0 :     delete mLocalVariables;
      71           0 :     if (mEvalContext != mInitialEvalContext) {
      72           0 :         delete mEvalContext;
      73             :     }
      74             : 
      75           0 :     txStackIterator varsIter(&mLocalVarsStack);
      76           0 :     while (varsIter.hasNext()) {
      77           0 :         delete (txVariableMap*)varsIter.next();
      78             :     }
      79             : 
      80           0 :     txStackIterator contextIter(&mEvalContextStack);
      81           0 :     while (contextIter.hasNext()) {
      82           0 :         txIEvalContext* context = (txIEvalContext*)contextIter.next();
      83           0 :         if (context != mInitialEvalContext) {
      84           0 :             delete context;
      85             :         }
      86             :     }
      87             : 
      88           0 :     txStackIterator handlerIter(&mResultHandlerStack);
      89           0 :     while (handlerIter.hasNext()) {
      90           0 :         delete (txAXMLEventHandler*)handlerIter.next();
      91             :     }
      92             : 
      93           0 :     txStackIterator paramIter(&mParamStack);
      94           0 :     while (paramIter.hasNext()) {
      95           0 :         delete (txVariableMap*)paramIter.next();
      96             :     }
      97             : 
      98           0 :     delete mInitialEvalContext;
      99           0 : }
     100             : 
     101             : nsresult
     102           0 : txExecutionState::init(const txXPathNode& aNode,
     103             :                        txOwningExpandedNameMap<txIGlobalParameter>* aGlobalParams)
     104             : {
     105           0 :     nsresult rv = NS_OK;
     106             : 
     107           0 :     mGlobalParams = aGlobalParams;
     108             : 
     109             :     // Set up initial context
     110           0 :     mEvalContext = new txSingleNodeContext(aNode, this);
     111           0 :     mInitialEvalContext = mEvalContext;
     112             : 
     113             :     // Set up output and result-handler
     114             :     txAXMLEventHandler* handler;
     115           0 :     rv = mOutputHandlerFactory->
     116           0 :         createHandlerWith(mStylesheet->getOutputFormat(), &handler);
     117           0 :     NS_ENSURE_SUCCESS(rv, rv);
     118             : 
     119           0 :     mOutputHandler = handler;
     120           0 :     mResultHandler = handler;
     121           0 :     mOutputHandler->startDocument();
     122             : 
     123             :     // Set up loaded-documents-hash
     124           0 :     rv = mLoadedDocuments.init(txXPathNodeUtils::getOwnerDocument(aNode));
     125           0 :     NS_ENSURE_SUCCESS(rv, rv);
     126             : 
     127             :     // Init members
     128           0 :     rv = mKeyHash.init();
     129           0 :     NS_ENSURE_SUCCESS(rv, rv);
     130             : 
     131           0 :     mRecycler = new txResultRecycler;
     132             : 
     133             :     // The actual value here doesn't really matter since noone should use this
     134             :     // value. But lets put something errorlike in just in case
     135           0 :     mGlobalVarPlaceholderValue = new StringResult(NS_LITERAL_STRING("Error"), nullptr);
     136             : 
     137             :     // Initiate first instruction. This has to be done last since findTemplate
     138             :     // might use us.
     139           0 :     txStylesheet::ImportFrame* frame = 0;
     140           0 :     txExpandedName nullName;
     141             :     txInstruction* templ;
     142           0 :     rv = mStylesheet->findTemplate(aNode, nullName, this, nullptr, &templ,
     143           0 :                                    &frame);
     144           0 :     NS_ENSURE_SUCCESS(rv, rv);
     145             : 
     146           0 :     pushTemplateRule(frame, nullName, nullptr);
     147             : 
     148           0 :     return runTemplate(templ);
     149             : }
     150             : 
     151             : nsresult
     152           0 : txExecutionState::end(nsresult aResult)
     153             : {
     154           0 :     NS_ASSERTION(NS_FAILED(aResult) || mTemplateRules.Length() == 1,
     155             :                  "Didn't clean up template rules properly");
     156           0 :     if (NS_SUCCEEDED(aResult)) {
     157           0 :         popTemplateRule();
     158             :     }
     159           0 :     else if (!mOutputHandler) {
     160           0 :         return NS_OK;
     161             :     }
     162           0 :     return mOutputHandler->endDocument(aResult);
     163             : }
     164             : 
     165             : void
     166           0 : txExecutionState::popAndDeleteEvalContextUntil(txIEvalContext* aContext)
     167             : {
     168           0 :   auto ctx = popEvalContext();
     169           0 :   while (ctx && ctx != aContext) {
     170           0 :     MOZ_RELEASE_ASSERT(ctx != mInitialEvalContext);
     171           0 :     delete ctx;
     172           0 :     ctx = popEvalContext();
     173             :   }
     174           0 : }
     175             : 
     176             : nsresult
     177           0 : txExecutionState::getVariable(int32_t aNamespace, nsIAtom* aLName,
     178             :                               txAExprResult*& aResult)
     179             : {
     180           0 :     nsresult rv = NS_OK;
     181           0 :     txExpandedName name(aNamespace, aLName);
     182             : 
     183             :     // look for a local variable
     184           0 :     if (mLocalVariables) {
     185           0 :         mLocalVariables->getVariable(name, &aResult);
     186           0 :         if (aResult) {
     187           0 :             return NS_OK;
     188             :         }
     189             :     }
     190             : 
     191             :     // look for an evaluated global variable
     192           0 :     mGlobalVariableValues.getVariable(name, &aResult);
     193           0 :     if (aResult) {
     194           0 :         if (aResult == mGlobalVarPlaceholderValue) {
     195             :             // XXX ErrorReport: cyclic variable-value
     196           0 :             NS_RELEASE(aResult);
     197           0 :             return NS_ERROR_XSLT_BAD_RECURSION;
     198             :         }
     199           0 :         return NS_OK;
     200             :     }
     201             : 
     202             :     // Is there perchance a global variable not evaluated yet?
     203           0 :     txStylesheet::GlobalVariable* var = mStylesheet->getGlobalVariable(name);
     204           0 :     if (!var) {
     205             :         // XXX ErrorReport: variable doesn't exist in this scope
     206           0 :         return NS_ERROR_FAILURE;
     207             :     }
     208             : 
     209           0 :     NS_ASSERTION((var->mExpr && !var->mFirstInstruction) ||
     210             :                  (!var->mExpr && var->mFirstInstruction),
     211             :                  "global variable should have either instruction or expression");
     212             : 
     213             :     // Is this a stylesheet parameter that has a value?
     214           0 :     if (var->mIsParam && mGlobalParams) {
     215           0 :         txIGlobalParameter* param = mGlobalParams->get(name);
     216           0 :         if (param) {
     217           0 :             rv = param->getValue(&aResult);
     218           0 :             NS_ENSURE_SUCCESS(rv, rv);
     219             : 
     220           0 :             rv = mGlobalVariableValues.bindVariable(name, aResult);
     221           0 :             if (NS_FAILED(rv)) {
     222           0 :                 NS_RELEASE(aResult);
     223           0 :                 return rv;
     224             :             }
     225             : 
     226           0 :             return NS_OK;
     227             :         }
     228             :     }
     229             : 
     230             :     // Insert a placeholdervalue to protect against recursion
     231           0 :     rv = mGlobalVariableValues.bindVariable(name, mGlobalVarPlaceholderValue);
     232           0 :     NS_ENSURE_SUCCESS(rv, rv);
     233             : 
     234             :     // evaluate the global variable
     235           0 :     pushEvalContext(mInitialEvalContext);
     236           0 :     if (var->mExpr) {
     237           0 :         txVariableMap* oldVars = mLocalVariables;
     238           0 :         mLocalVariables = nullptr;
     239           0 :         rv = var->mExpr->evaluate(getEvalContext(), &aResult);
     240           0 :         mLocalVariables = oldVars;
     241             : 
     242           0 :         if (NS_FAILED(rv)) {
     243           0 :           popAndDeleteEvalContextUntil(mInitialEvalContext);
     244           0 :           return rv;
     245             :         }
     246             :     }
     247             :     else {
     248           0 :         nsAutoPtr<txRtfHandler> rtfHandler(new txRtfHandler);
     249             : 
     250           0 :         rv = pushResultHandler(rtfHandler);
     251           0 :         if (NS_FAILED(rv)) {
     252           0 :           popAndDeleteEvalContextUntil(mInitialEvalContext);
     253           0 :           return rv;
     254             :         }
     255             : 
     256           0 :         rtfHandler.forget();
     257             : 
     258           0 :         txInstruction* prevInstr = mNextInstruction;
     259             :         // set return to nullptr to stop execution
     260           0 :         mNextInstruction = nullptr;
     261           0 :         rv = runTemplate(var->mFirstInstruction);
     262           0 :         if (NS_FAILED(rv)) {
     263           0 :           popAndDeleteEvalContextUntil(mInitialEvalContext);
     264           0 :           return rv;
     265             :         }
     266             : 
     267           0 :         pushTemplateRule(nullptr, txExpandedName(), nullptr);
     268           0 :         rv = txXSLTProcessor::execute(*this);
     269           0 :         if (NS_FAILED(rv)) {
     270           0 :           popAndDeleteEvalContextUntil(mInitialEvalContext);
     271           0 :           return rv;
     272             :         }
     273             : 
     274           0 :         popTemplateRule();
     275             : 
     276           0 :         mNextInstruction = prevInstr;
     277           0 :         rtfHandler = (txRtfHandler*)popResultHandler();
     278           0 :         rv = rtfHandler->getAsRTF(&aResult);
     279           0 :         if (NS_FAILED(rv)) {
     280           0 :           popAndDeleteEvalContextUntil(mInitialEvalContext);
     281           0 :           return rv;
     282             :         }
     283             :     }
     284           0 :     popEvalContext();
     285             : 
     286             :     // Remove the placeholder and insert the calculated value
     287           0 :     mGlobalVariableValues.removeVariable(name);
     288           0 :     rv = mGlobalVariableValues.bindVariable(name, aResult);
     289           0 :     if (NS_FAILED(rv)) {
     290           0 :         NS_RELEASE(aResult);
     291             : 
     292           0 :         return rv;
     293             :     }
     294             : 
     295           0 :     return NS_OK;
     296             : }
     297             : 
     298             : nsresult
     299           0 : txExecutionState::isStripSpaceAllowed(const txXPathNode& aNode, bool& aAllowed)
     300             : {
     301           0 :     return mStylesheet->isStripSpaceAllowed(aNode, this, aAllowed);
     302             : }
     303             : 
     304             : void*
     305           0 : txExecutionState::getPrivateContext()
     306             : {
     307           0 :     return this;
     308             : }
     309             : 
     310             : txResultRecycler*
     311           0 : txExecutionState::recycler()
     312             : {
     313           0 :     return mRecycler;
     314             : }
     315             : 
     316             : void
     317           0 : txExecutionState::receiveError(const nsAString& aMsg, nsresult aRes)
     318             : {
     319             :     // XXX implement me
     320           0 : }
     321             : 
     322             : nsresult
     323           0 : txExecutionState::pushEvalContext(txIEvalContext* aContext)
     324             : {
     325           0 :     nsresult rv = mEvalContextStack.push(mEvalContext);
     326           0 :     NS_ENSURE_SUCCESS(rv, rv);
     327             : 
     328           0 :     mEvalContext = aContext;
     329             : 
     330           0 :     return NS_OK;
     331             : }
     332             : 
     333             : txIEvalContext*
     334           0 : txExecutionState::popEvalContext()
     335             : {
     336           0 :     txIEvalContext* prev = mEvalContext;
     337           0 :     mEvalContext = (txIEvalContext*)mEvalContextStack.pop();
     338             : 
     339           0 :     return prev;
     340             : }
     341             : 
     342             : nsresult
     343           0 : txExecutionState::pushBool(bool aBool)
     344             : {
     345           0 :     return mBoolStack.AppendElement(aBool) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     346             : }
     347             : 
     348             : bool
     349           0 : txExecutionState::popBool()
     350             : {
     351           0 :     NS_ASSERTION(mBoolStack.Length(), "popping from empty stack");
     352           0 :     uint32_t last = mBoolStack.Length() - 1;
     353           0 :     NS_ENSURE_TRUE(last != (uint32_t)-1, false);
     354             : 
     355           0 :     bool res = mBoolStack.ElementAt(last);
     356           0 :     mBoolStack.RemoveElementAt(last);
     357             : 
     358           0 :     return res;
     359             : }
     360             : 
     361             : nsresult
     362           0 : txExecutionState::pushResultHandler(txAXMLEventHandler* aHandler)
     363             : {
     364           0 :     nsresult rv = mResultHandlerStack.push(mResultHandler);
     365           0 :     NS_ENSURE_SUCCESS(rv, rv);
     366             : 
     367           0 :     mResultHandler = aHandler;
     368             : 
     369           0 :     return NS_OK;
     370             : }
     371             : 
     372             : txAXMLEventHandler*
     373           0 : txExecutionState::popResultHandler()
     374             : {
     375           0 :     txAXMLEventHandler* oldHandler = mResultHandler;
     376           0 :     mResultHandler = (txAXMLEventHandler*)mResultHandlerStack.pop();
     377             : 
     378           0 :     return oldHandler;
     379             : }
     380             : 
     381             : void
     382           0 : txExecutionState::pushTemplateRule(txStylesheet::ImportFrame* aFrame,
     383             :                                    const txExpandedName& aMode,
     384             :                                    txVariableMap* aParams)
     385             : {
     386           0 :     TemplateRule* rule = mTemplateRules.AppendElement();
     387           0 :     rule->mFrame = aFrame;
     388           0 :     rule->mModeNsId = aMode.mNamespaceID;
     389           0 :     rule->mModeLocalName = aMode.mLocalName;
     390           0 :     rule->mParams = aParams;
     391           0 : }
     392             : 
     393             : void
     394           0 : txExecutionState::popTemplateRule()
     395             : {
     396           0 :     NS_PRECONDITION(!mTemplateRules.IsEmpty(), "No rules to pop");
     397           0 :     mTemplateRules.RemoveElementAt(mTemplateRules.Length() - 1);
     398           0 : }
     399             : 
     400             : txIEvalContext*
     401           0 : txExecutionState::getEvalContext()
     402             : {
     403           0 :     return mEvalContext;
     404             : }
     405             : 
     406             : const txXPathNode*
     407           0 : txExecutionState::retrieveDocument(const nsAString& aUri)
     408             : {
     409           0 :     NS_ASSERTION(!aUri.Contains(char16_t('#')),
     410             :                  "Remove the fragment.");
     411             : 
     412           0 :     if (mDisableLoads) {
     413           0 :         return nullptr;
     414             :     }
     415             : 
     416           0 :     MOZ_LOG(txLog::xslt, LogLevel::Debug,
     417             :            ("Retrieve Document %s", NS_LossyConvertUTF16toASCII(aUri).get()));
     418             : 
     419             :     // try to get already loaded document
     420           0 :     txLoadedDocumentEntry *entry = mLoadedDocuments.PutEntry(aUri);
     421           0 :     if (!entry) {
     422           0 :         return nullptr;
     423             :     }
     424             : 
     425           0 :     if (!entry->mDocument && !entry->LoadingFailed()) {
     426             :         // open URI
     427           0 :         nsAutoString errMsg;
     428             :         // XXX we should get the loader from the actual node
     429             :         // triggering the load, but this will do for the time being
     430           0 :         entry->mLoadResult =
     431           0 :             txParseDocumentFromURI(aUri, *mLoadedDocuments.mSourceDocument,
     432           0 :                                    errMsg, getter_Transfers(entry->mDocument));
     433             : 
     434           0 :         if (entry->LoadingFailed()) {
     435           0 :             receiveError(NS_LITERAL_STRING("Couldn't load document '") +
     436           0 :                          aUri + NS_LITERAL_STRING("': ") + errMsg,
     437           0 :                          entry->mLoadResult);
     438             :         }
     439             :     }
     440             : 
     441           0 :     return entry->mDocument;
     442             : }
     443             : 
     444             : nsresult
     445           0 : txExecutionState::getKeyNodes(const txExpandedName& aKeyName,
     446             :                               const txXPathNode& aRoot,
     447             :                               const nsAString& aKeyValue,
     448             :                               bool aIndexIfNotFound,
     449             :                               txNodeSet** aResult)
     450             : {
     451           0 :     return mKeyHash.getKeyNodes(aKeyName, aRoot, aKeyValue,
     452           0 :                                 aIndexIfNotFound, *this, aResult);
     453             : }
     454             : 
     455             : txExecutionState::TemplateRule*
     456           0 : txExecutionState::getCurrentTemplateRule()
     457             : {
     458           0 :     NS_PRECONDITION(!mTemplateRules.IsEmpty(), "No current rule!");
     459           0 :     return &mTemplateRules[mTemplateRules.Length() - 1];
     460             : }
     461             : 
     462             : txInstruction*
     463           0 : txExecutionState::getNextInstruction()
     464             : {
     465           0 :     txInstruction* instr = mNextInstruction;
     466           0 :     if (instr) {
     467           0 :         mNextInstruction = instr->mNext;
     468             :     }
     469             : 
     470           0 :     return instr;
     471             : }
     472             : 
     473             : nsresult
     474           0 : txExecutionState::runTemplate(txInstruction* aTemplate)
     475             : {
     476           0 :     NS_ENSURE_TRUE(++mRecursionDepth < kMaxRecursionDepth,
     477             :                    NS_ERROR_XSLT_BAD_RECURSION);
     478             : 
     479           0 :     nsresult rv = mLocalVarsStack.push(mLocalVariables);
     480           0 :     NS_ENSURE_SUCCESS(rv, rv);
     481             : 
     482           0 :     rv = mReturnStack.push(mNextInstruction);
     483           0 :     NS_ENSURE_SUCCESS(rv, rv);
     484             : 
     485           0 :     mLocalVariables = nullptr;
     486           0 :     mNextInstruction = aTemplate;
     487             : 
     488           0 :     return NS_OK;
     489             : }
     490             : 
     491             : void
     492           0 : txExecutionState::gotoInstruction(txInstruction* aNext)
     493             : {
     494           0 :     mNextInstruction = aNext;
     495           0 : }
     496             : 
     497             : void
     498           0 : txExecutionState::returnFromTemplate()
     499             : {
     500           0 :     --mRecursionDepth;
     501           0 :     NS_ASSERTION(!mReturnStack.isEmpty() && !mLocalVarsStack.isEmpty(),
     502             :                  "return or variable stack is empty");
     503           0 :     delete mLocalVariables;
     504           0 :     mNextInstruction = (txInstruction*)mReturnStack.pop();
     505           0 :     mLocalVariables = (txVariableMap*)mLocalVarsStack.pop();
     506           0 : }
     507             : 
     508             : nsresult
     509           0 : txExecutionState::bindVariable(const txExpandedName& aName,
     510             :                                txAExprResult* aValue)
     511             : {
     512           0 :     if (!mLocalVariables) {
     513           0 :         mLocalVariables = new txVariableMap;
     514             :     }
     515           0 :     return mLocalVariables->bindVariable(aName, aValue);
     516             : }
     517             : 
     518             : void
     519           0 : txExecutionState::removeVariable(const txExpandedName& aName)
     520             : {
     521           0 :     mLocalVariables->removeVariable(aName);
     522           0 : }
     523             : 
     524             : nsresult
     525           0 : txExecutionState::pushParamMap(txVariableMap* aParams)
     526             : {
     527           0 :     nsresult rv = mParamStack.push(mTemplateParams);
     528           0 :     NS_ENSURE_SUCCESS(rv, rv);
     529             : 
     530           0 :     mTemplateParams.forget();
     531           0 :     mTemplateParams = aParams;
     532             : 
     533           0 :     return NS_OK;
     534             : }
     535             : 
     536             : txVariableMap*
     537           0 : txExecutionState::popParamMap()
     538             : {
     539           0 :     txVariableMap* oldParams = mTemplateParams.forget();
     540           0 :     mTemplateParams = (txVariableMap*)mParamStack.pop();
     541             : 
     542           0 :     return oldParams;
     543             : }

Generated by: LCOV version 1.13