Bug 199331: Recompile stylesheet if the underlying DOM is modified after .importStylesheet is called

r=Pike sr=peterv a=mkaply
This commit is contained in:
sicking%bigfoot.com 2003-05-23 15:02:08 +00:00
parent bee83d7a31
commit 57097a2753
2 changed files with 172 additions and 7 deletions

View File

@ -243,17 +243,23 @@ NS_INTERFACE_MAP_BEGIN(txMozillaXSLTProcessor)
NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessor)
NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessorObsolete)
NS_INTERFACE_MAP_ENTRY(nsIDocumentTransformer)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXSLTProcessor)
NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(XSLTProcessor)
NS_INTERFACE_MAP_END
txMozillaXSLTProcessor::txMozillaXSLTProcessor() : mTransformResult(NS_OK),
txMozillaXSLTProcessor::txMozillaXSLTProcessor() : mStylesheetDocument(nsnull),
mTransformResult(NS_OK),
mCompileResult(NS_OK),
mVariables(PR_TRUE)
{
}
txMozillaXSLTProcessor::~txMozillaXSLTProcessor()
{
if (mStylesheetDocument) {
mStylesheetDocument->RemoveObserver(this);
}
}
NS_IMETHODIMP
@ -374,6 +380,12 @@ txMozillaXSLTProcessor::DoTransform()
NS_IMETHODIMP
txMozillaXSLTProcessor::ImportStylesheet(nsIDOMNode *aStyle)
{
NS_ENSURE_TRUE(aStyle, NS_ERROR_NULL_POINTER);
// We don't support importing multiple stylesheets yet.
NS_ENSURE_TRUE(!mStylesheetDocument && !mStylesheet,
NS_ERROR_NOT_IMPLEMENTED);
if (!URIUtils::CanCallerAccess(aStyle)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
@ -386,7 +398,25 @@ txMozillaXSLTProcessor::ImportStylesheet(nsIDOMNode *aStyle)
nsresult rv = TX_CompileStylesheet(aStyle, getter_AddRefs(mStylesheet));
// XXX set up exception context, bug 204658
return rv;
NS_ENSURE_SUCCESS(rv, rv);
if (type == nsIDOMNode::ELEMENT_NODE) {
nsCOMPtr<nsIDOMDocument> domDoc;
aStyle->GetOwnerDocument(getter_AddRefs(domDoc));
NS_ENSURE_TRUE(domDoc, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIDocument> styleDoc = do_QueryInterface(domDoc);
mStylesheetDocument = styleDoc;
mEmbeddedStylesheetRoot = do_QueryInterface(aStyle);
}
else {
nsCOMPtr<nsIDocument> styleDoc = do_QueryInterface(aStyle);
mStylesheetDocument = styleDoc;
}
mStylesheetDocument->AddObserver(this);
return NS_OK;
}
NS_IMETHODIMP
@ -395,12 +425,15 @@ txMozillaXSLTProcessor::TransformToDocument(nsIDOMNode *aSource,
{
NS_ENSURE_ARG(aSource);
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_TRUE(mStylesheet, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_SUCCESS(mCompileResult, mCompileResult);
if (!URIUtils::CanCallerAccess(aSource)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsresult rv = ensureStylesheet();
NS_ENSURE_SUCCESS(rv, rv);
// Create wrapper for the source document.
nsCOMPtr<nsIDOMDocument> sourceDOMDocument;
aSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument));
@ -423,7 +456,7 @@ txMozillaXSLTProcessor::TransformToDocument(nsIDOMNode *aSource,
es.init(sourceNode, &mVariables);
// Process root of XML source document
nsresult rv = txXSLTProcessor::execute(es);
rv = txXSLTProcessor::execute(es);
// XXX setup exception context, bug 204658
es.end();
@ -444,13 +477,16 @@ txMozillaXSLTProcessor::TransformToFragment(nsIDOMNode *aSource,
NS_ENSURE_ARG(aSource);
NS_ENSURE_ARG(aOutput);
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_TRUE(mStylesheet, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_SUCCESS(mCompileResult, mCompileResult);
if (!URIUtils::CanCallerAccess(aSource) ||
!URIUtils::CanCallerAccess(aOutput)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsresult rv = ensureStylesheet();
NS_ENSURE_SUCCESS(rv, rv);
// Create wrapper for the source document.
nsCOMPtr<nsIDOMDocument> sourceDOMDocument;
aSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument));
@ -466,7 +502,7 @@ txMozillaXSLTProcessor::TransformToFragment(nsIDOMNode *aSource,
// XXX Need to add error observers
nsresult rv = aOutput->CreateDocumentFragment(aResult);
rv = aOutput->CreateDocumentFragment(aResult);
NS_ENSURE_SUCCESS(rv, rv);
txToFragmentHandlerFactory handlerFactory(*aResult);
es.mOutputHandlerFactory = &handlerFactory;
@ -594,7 +630,13 @@ txMozillaXSLTProcessor::ClearParameters()
NS_IMETHODIMP
txMozillaXSLTProcessor::Reset()
{
if (mStylesheetDocument) {
mStylesheetDocument->RemoveObserver(this);
}
mStylesheet = nsnull;
mStylesheetDocument = nsnull;
mEmbeddedStylesheetRoot = nsnull;
mCompileResult = NS_OK;
mVariables.clear();
return NS_OK;
@ -778,6 +820,119 @@ txMozillaXSLTProcessor::notifyError()
mObserver->OnTransformDone(mTransformResult, errorDocument);
}
nsresult
txMozillaXSLTProcessor::ensureStylesheet()
{
if (mStylesheet) {
return NS_OK;
}
NS_ENSURE_TRUE(mStylesheetDocument, NS_ERROR_NOT_INITIALIZED);
nsCOMPtr<nsIDOMNode> style = do_QueryInterface(mEmbeddedStylesheetRoot);
if (!style) {
style = do_QueryInterface(mStylesheetDocument);
}
return TX_CompileStylesheet(style, getter_AddRefs(mStylesheet));
}
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(txMozillaXSLTProcessor)
NS_IMPL_NSIDOCUMENTOBSERVER_REFLOW_STUB(txMozillaXSLTProcessor)
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(txMozillaXSLTProcessor)
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(txMozillaXSLTProcessor)
NS_IMETHODIMP
txMozillaXSLTProcessor::BeginUpdate(nsIDocument* aDocument)
{
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::EndUpdate(nsIDocument* aDocument)
{
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::DocumentWillBeDestroyed(nsIDocument* aDocument)
{
if (NS_FAILED(mCompileResult)) {
return NS_OK;
}
mCompileResult = ensureStylesheet();
mStylesheetDocument = nsnull;
mEmbeddedStylesheetRoot = nsnull;
// This might not be neccesary, but just in case some element ends up
// causing a notification as the document goes away we don't want to
// invalidate the stylesheet.
aDocument->RemoveObserver(this);
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::ContentChanged(nsIDocument* aDocument,
nsIContent *aContent,
nsISupports *aSubContent)
{
mStylesheet = nsnull;
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType,
nsChangeHint aHint)
{
mStylesheet = nsnull;
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
mStylesheet = nsnull;
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
mStylesheet = nsnull;
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::ContentReplaced(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer)
{
mStylesheet = nsnull;
return NS_OK;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
mStylesheet = nsnull;
return NS_OK;
}
/* static*/
nsresult
txVariable::Convert(nsIVariant *aValue, ExprResult** aResult)

View File

@ -55,6 +55,7 @@
#include "nsVoidArray.h"
#include "txStylesheet.h"
#include "nsAutoPtr.h"
#include "nsIDocumentObserver.h"
class nsIURI;
class nsIXMLContentSink;
@ -118,7 +119,8 @@ private:
*/
class txMozillaXSLTProcessor : public nsIXSLTProcessor,
public nsIXSLTProcessorObsolete,
public nsIDocumentTransformer
public nsIDocumentTransformer,
public nsIDocumentObserver
{
public:
/**
@ -147,6 +149,9 @@ public:
NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource);
NS_IMETHOD CancelLoads() {return NS_OK;};
// nsIDocumentObserver interface
NS_DECL_NSIDOCUMENTOBSERVER
nsresult setStylesheet(txStylesheet* aStylesheet);
void reportError(nsresult aResult, const PRUnichar *aErrorText,
const PRUnichar *aSourceText);
@ -154,10 +159,15 @@ public:
private:
nsresult DoTransform();
void notifyError();
nsresult ensureStylesheet();
nsRefPtr<txStylesheet> mStylesheet;
nsIDocument* mStylesheetDocument; // weak
nsCOMPtr<nsIContent> mEmbeddedStylesheetRoot;
nsCOMPtr<nsIDOMNode> mSource;
nsresult mTransformResult;
nsresult mCompileResult;
nsString mErrorText, mSourceText;
nsCOMPtr<nsITransformObserver> mObserver;
txExpandedNameMap mVariables;