Bug 1309630 - Use a request to stop transforming. r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D134250
This commit is contained in:
Peter Van der Beken 2021-12-21 17:56:02 +00:00
parent 37df566280
commit bc9819f41c
4 changed files with 121 additions and 10 deletions

View File

@ -395,7 +395,12 @@ txExecutionState::TemplateRule* txExecutionState::getCurrentTemplateRule() {
return &mTemplateRules[mTemplateRules.Length() - 1];
}
txInstruction* txExecutionState::getNextInstruction() {
mozilla::Result<txInstruction*, nsresult>
txExecutionState::getNextInstruction() {
if (mStopProcessing) {
return mozilla::Err(NS_ERROR_FAILURE);
}
txInstruction* instr = mNextInstruction;
if (instr) {
mNextInstruction = instr->mNext.get();

View File

@ -17,6 +17,7 @@
#include "txStylesheet.h"
#include "txXPathTreeWalker.h"
#include "nsTArray.h"
#include "mozilla/Result.h"
class txAOutputHandlerFactory;
class txAXMLEventHandler;
@ -115,13 +116,14 @@ class txExecutionState : public txIMatchContext {
}
// state-modification functions
txInstruction* getNextInstruction();
mozilla::Result<txInstruction*, nsresult> getNextInstruction();
nsresult runTemplate(txInstruction* aInstruction);
nsresult runTemplate(txInstruction* aInstruction, txInstruction* aReturnTo);
void gotoInstruction(txInstruction* aNext);
void returnFromTemplate();
nsresult bindVariable(const txExpandedName& aName, txAExprResult* aValue);
void removeVariable(const txExpandedName& aName);
void stopProcessing() { mStopProcessing = true; }
txAXMLEventHandler* mOutputHandler;
txAXMLEventHandler* mResultHandler;
@ -156,6 +158,7 @@ class txExecutionState : public txIMatchContext {
txKeyHash mKeyHash;
RefPtr<txResultRecycler> mRecycler;
bool mDisableLoads;
bool mStopProcessing = false;
static const int32_t kMaxRecursionDepth;
};

View File

@ -538,6 +538,79 @@ already_AddRefed<Document> txMozillaXSLTProcessor::TransformToDocument(
return doc.forget();
}
class XSLTProcessRequest final : public nsIRequest {
public:
explicit XSLTProcessRequest(txExecutionState* aState) : mState(aState) {}
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUEST
void Done() { mState = nullptr; }
private:
~XSLTProcessRequest() {}
txExecutionState* mState;
};
NS_IMPL_ISUPPORTS(XSLTProcessRequest, nsIRequest)
NS_IMETHODIMP
XSLTProcessRequest::GetName(nsACString& aResult) {
aResult.AssignLiteral("about:xslt-load-blocker");
return NS_OK;
}
NS_IMETHODIMP
XSLTProcessRequest::IsPending(bool* _retval) {
*_retval = true;
return NS_OK;
}
NS_IMETHODIMP
XSLTProcessRequest::GetStatus(nsresult* status) {
*status = NS_OK;
return NS_OK;
}
NS_IMETHODIMP
XSLTProcessRequest::Cancel(nsresult status) {
mState->stopProcessing();
return NS_OK;
}
NS_IMETHODIMP
XSLTProcessRequest::Suspend(void) { return NS_OK; }
NS_IMETHODIMP
XSLTProcessRequest::Resume(void) { return NS_OK; }
NS_IMETHODIMP
XSLTProcessRequest::GetLoadGroup(nsILoadGroup** aLoadGroup) {
*aLoadGroup = nullptr;
return NS_OK;
}
NS_IMETHODIMP
XSLTProcessRequest::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; }
NS_IMETHODIMP
XSLTProcessRequest::GetLoadFlags(nsLoadFlags* aLoadFlags) {
*aLoadFlags = nsIRequest::LOAD_NORMAL;
return NS_OK;
}
NS_IMETHODIMP
XSLTProcessRequest::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; }
NS_IMETHODIMP
XSLTProcessRequest::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
return GetTRRModeImpl(aTRRMode);
}
NS_IMETHODIMP
XSLTProcessRequest::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
return SetTRRModeImpl(aTRRMode);
}
nsresult txMozillaXSLTProcessor::TransformToDoc(Document** aResult,
bool aCreateDataDocument) {
UniquePtr<txXPathNode> sourceNode(
@ -548,10 +621,29 @@ nsresult txMozillaXSLTProcessor::TransformToDoc(Document** aResult,
txExecutionState es(mStylesheet, IsLoadDisabled());
Document* sourceDoc = mSource->OwnerDoc();
nsCOMPtr<nsILoadGroup> loadGroup = sourceDoc->GetDocumentLoadGroup();
if (!loadGroup) {
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(mOwner);
if (win && win->IsCurrentInnerWindow()) {
Document* doc = win->GetDoc();
if (doc) {
loadGroup = doc->GetDocumentLoadGroup();
}
}
if (!loadGroup) {
return NS_ERROR_FAILURE;
}
}
RefPtr<XSLTProcessRequest> xsltProcessRequest = new XSLTProcessRequest(&es);
loadGroup->AddRequest(xsltProcessRequest, nullptr);
// XXX Need to add error observers
// If aResult is non-null, we're a data document
txToDocHandlerFactory handlerFactory(&es, mSource->OwnerDoc(), mObserver,
txToDocHandlerFactory handlerFactory(&es, sourceDoc, mObserver,
aCreateDataDocument);
es.mOutputHandlerFactory = &handlerFactory;
@ -562,6 +654,9 @@ nsresult txMozillaXSLTProcessor::TransformToDoc(Document** aResult,
rv = txXSLTProcessor::execute(es);
}
xsltProcessRequest->Done();
loadGroup->RemoveRequest(xsltProcessRequest, nullptr, NS_OK);
nsresult endRv = es.end(rv);
if (NS_SUCCEEDED(rv)) {
rv = endRv;

View File

@ -31,12 +31,20 @@ void txXSLTProcessor::shutdown() { txHandlerTable::shutdown(); }
/* static */
nsresult txXSLTProcessor::execute(txExecutionState& aEs) {
nsresult rv = NS_OK;
txInstruction* instr;
while ((instr = aEs.getNextInstruction())) {
rv = instr->execute(aEs);
NS_ENSURE_SUCCESS(rv, rv);
}
nsresult rv;
do {
mozilla::Result<txInstruction*, nsresult> result = aEs.getNextInstruction();
if (result.isErr()) {
return result.unwrapErr();
}
return NS_OK;
txInstruction* instr = result.unwrap();
if (!instr) {
return NS_OK;
}
rv = instr->execute(aEs);
} while (NS_SUCCEEDED(rv));
return rv;
}