# HG changeset patch # User Dan Fabulich # Date 1231521129 28800 # Node ID e81d437218544cde1f811fb3706e95ff1c9e3f38 # Parent 4f196841ba1a99a30b2918b85fc16aed968abb45 b=347174, implement document.readystate == 'complete'; r=sicking diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -615,16 +615,20 @@ public: // Observation hooks used to propagate notifications to document observers. // BeginUpdate must be called before any batch of modifications of the // content model or of style data, EndUpdate must be called afterward. // To make this easy and painless, use the mozAutoDocUpdate helper class. virtual void BeginUpdate(nsUpdateType aUpdateType) = 0; virtual void EndUpdate(nsUpdateType aUpdateType) = 0; virtual void BeginLoad() = 0; virtual void EndLoad() = 0; + + enum ReadyState { READYSTATE_UNINITIALIZED = 0, READYSTATE_LOADING = 1, READYSTATE_INTERACTIVE = 3, READYSTATE_COMPLETE = 4}; + virtual void SetReadyStateInternal(ReadyState rs) = 0; + // notify that one or two content nodes changed state // either may be nsnull, but not both virtual void ContentStatesChanged(nsIContent* aContent1, nsIContent* aContent2, PRInt32 aStateMask) = 0; // Observation hooks for style data to propagate notifications // to document observers diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -3610,16 +3610,19 @@ nsContentUtils::CreateDocument(const nsA { nsresult rv = NS_NewDOMDocument(aResult, aNamespaceURI, aQualifiedName, aDoctype, aDocumentURI, aBaseURI, aPrincipal, PR_TRUE); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr document = do_QueryInterface(*aResult); document->SetScriptHandlingObject(aEventObject); + + // created documents are immediately "complete" (ready to use) + document->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); return NS_OK; } /* static */ nsresult nsContentUtils::SetNodeTextContent(nsIContent* aContent, const nsAString& aValue, PRBool aTryReuse) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -2172,16 +2172,18 @@ nsDocument::StartDocumentLoad(const char aChannel->GetURI(getter_AddRefs(uri)); nsCAutoString spec; if (uri) uri->GetSpec(spec); PR_LogPrint("DOCUMENT %p StartDocumentLoad %s", this, spec.get()); } #endif + SetReadyStateInternal(READYSTATE_LOADING); + if (nsCRT::strcmp(kLoadAsData, aCommand) == 0) { mLoadedAsData = PR_TRUE; // We need to disable script & style loading in this case. // We leave them disabled even in EndLoad(), and let anyone // who puts the document on display to worry about enabling. // Do not load/process scripts when loading as data ScriptLoader()->SetEnabled(PR_FALSE); @@ -3956,16 +3958,18 @@ nsDocument::EndLoad() // can flush it from FlushPendingNotifications as needed. We might have to // do that to get a StartLayout() to happen. if (mParser) { mWeakSink = do_GetWeakReference(mParser->GetContentSink()); mParser = nsnull; } NS_DOCUMENT_NOTIFY_OBSERVERS(EndLoad, (this)); + + SetReadyStateInternal(READYSTATE_INTERACTIVE); if (!mSynchronousDOMContentLoaded) { nsRefPtr ev = new nsRunnableMethod(this, &nsDocument::DispatchContentLoadedEvents); NS_DispatchToCurrentThread(ev); } else { DispatchContentLoadedEvents(); @@ -7372,11 +7376,37 @@ nsDocument::CloneDocHelper(nsDocument* c clone->mContentLanguage = mContentLanguage; clone->mContentType = mContentType; clone->mSecurityInfo = mSecurityInfo; // State from nsDocument clone->mIsRegularHTML = mIsRegularHTML; clone->mXMLDeclarationBits = mXMLDeclarationBits; clone->mBaseTarget = mBaseTarget; - - return NS_OK; -} + return NS_OK; +} + +void +nsDocument::SetReadyStateInternal(ReadyState rs) +{ + mReadyState = rs; + // TODO fire "readystatechange" +} + + +NS_IMETHODIMP +nsDocument::GetReadyState(nsAString& aReadyState) +{ + switch(mReadyState) { + case READYSTATE_LOADING : + aReadyState.Assign(NS_LITERAL_STRING("loading")); + break; + case READYSTATE_INTERACTIVE : + aReadyState.Assign(NS_LITERAL_STRING("interactive")); + break; + case READYSTATE_COMPLETE : + aReadyState.Assign(NS_LITERAL_STRING("complete")); + break; + default: + aReadyState.Assign(NS_LITERAL_STRING("uninitialized")); + } + return NS_OK; +} diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -767,16 +767,19 @@ public: virtual PRBool RemoveObserver(nsIDocumentObserver* aObserver); // Observation hooks used to propagate notifications to document // observers. virtual void BeginUpdate(nsUpdateType aUpdateType); virtual void EndUpdate(nsUpdateType aUpdateType); virtual void BeginLoad(); virtual void EndLoad(); + + virtual void SetReadyStateInternal(ReadyState rs); + virtual void ContentStatesChanged(nsIContent* aContent1, nsIContent* aContent2, PRInt32 aStateMask); virtual void AttributeWillChange(nsIContent* aChild, PRInt32 aNameSpaceID, nsIAtom* aAttribute); @@ -1245,16 +1248,17 @@ private: // The layout history state that should be used by nodes in this // document. We only actually store a pointer to it when: // 1) We have no script global object. // 2) We haven't had Destroy() called on us yet. nsCOMPtr mLayoutHistoryState; PRUint32 mOnloadBlockCount; nsCOMPtr mOnloadBlocker; + ReadyState mReadyState; // A map from unvisited URI hashes to content elements nsTHashtable mLinkMap; // URIs whose visitedness has changed while we were hidden nsCOMArray mVisitednessChangedURIs; // Member to store out last-selected stylesheet set. nsString mLastStyleSheetSet; diff --git a/content/html/content/test/347174transform.xsl b/content/html/content/test/347174transform.xsl new file mode 100644 --- /dev/null +++ b/content/html/content/test/347174transform.xsl @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/html/content/test/347174transformable.xml b/content/html/content/test/347174transformable.xml new file mode 100644 --- /dev/null +++ b/content/html/content/test/347174transformable.xml @@ -0,0 +1,3 @@ + + +This is a sample document. diff --git a/content/html/content/test/Makefile.in b/content/html/content/test/Makefile.in --- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -119,12 +119,18 @@ _TEST_FILES = test_bug589.html \ test_bug428135.xhtml \ test_bug430351.html \ test_bug430392.html \ bug441930_iframe.html \ test_bug441930.html \ test_bug442801.html \ test_bug448166.html \ test_bug460568.html \ + test_bug347174.html \ + test_bug347174_write.html \ + test_bug347174_xsl.html \ + test_bug347174_xslp.html \ + 347174transformable.xml \ + 347174transform.xsl \ $(NULL) libs:: $(_TEST_FILES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) diff --git a/content/html/content/test/test_bug347174.html b/content/html/content/test/test_bug347174.html new file mode 100644 --- /dev/null +++ b/content/html/content/test/test_bug347174.html @@ -0,0 +1,65 @@ + + + + + Test for Bug 347174 + + + + + +Mozilla Bug 347174 +

+ +
+
+
+ + diff --git a/content/html/content/test/test_bug347174_write.html b/content/html/content/test/test_bug347174_write.html new file mode 100644 --- /dev/null +++ b/content/html/content/test/test_bug347174_write.html @@ -0,0 +1,74 @@ + + + + + Test for Bug 347174 + + + + + +Mozilla Bug 347174 +

+ + +
+
+
+ + + diff --git a/content/html/content/test/test_bug347174_xsl.html b/content/html/content/test/test_bug347174_xsl.html new file mode 100644 --- /dev/null +++ b/content/html/content/test/test_bug347174_xsl.html @@ -0,0 +1,56 @@ + + + + + Test for Bug 347174 + + + + + +Mozilla Bug 347174 +

+ +
+
+
+ + diff --git a/content/html/content/test/test_bug347174_xslp.html b/content/html/content/test/test_bug347174_xslp.html new file mode 100644 --- /dev/null +++ b/content/html/content/test/test_bug347174_xslp.html @@ -0,0 +1,62 @@ + + + + + Test for Bug 347174 + + + + + + +Mozilla Bug 347174 +

+ +
+
+
+ + diff --git a/content/xml/document/src/nsXMLDocument.cpp b/content/xml/document/src/nsXMLDocument.cpp --- a/content/xml/document/src/nsXMLDocument.cpp +++ b/content/xml/document/src/nsXMLDocument.cpp @@ -539,16 +539,17 @@ nsXMLDocument::EndLoad() { mChannelIsPending = PR_FALSE; mLoopingForSyncLoad = PR_FALSE; mSynchronousDOMContentLoaded = (mLoadedAsData || mLoadedAsInteractiveData); nsDocument::EndLoad(); if (mSynchronousDOMContentLoaded) { mSynchronousDOMContentLoaded = PR_FALSE; + nsDocument::SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); // Generate a document load event for the case when an XML // document was loaded as pure data without any presentation // attached to it. nsEvent event(PR_TRUE, NS_LOAD); nsEventDispatcher::Dispatch(static_cast(this), nsnull, &event); } } diff --git a/content/xslt/src/xslt/txMozillaXMLOutput.cpp b/content/xslt/src/xslt/txMozillaXMLOutput.cpp --- a/content/xslt/src/xslt/txMozillaXMLOutput.cpp +++ b/content/xslt/src/xslt/txMozillaXMLOutput.cpp @@ -253,16 +253,18 @@ txMozillaXMLOutput::endDocument(nsresult nsresult rv = closePrevious(PR_TRUE); if (NS_FAILED(rv)) { if (mNotifier) { mNotifier->OnTransformEnd(rv); } return rv; } + // This should really be handled by nsIDocument::EndLoad + mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE); if (!mRefreshString.IsEmpty()) { nsPIDOMWindow *win = mDocument->GetWindow(); if (win) { nsCOMPtr refURI = do_QueryInterface(win->GetDocShell()); if (refURI) { refURI->SetupRefreshURIFromHeader(mDocument->GetBaseURI(), @@ -827,16 +829,18 @@ txMozillaXMLOutput::createResultDocument NS_ENSURE_SUCCESS(rv, rv); } else { // We should check the root name/namespace here and create the // appropriate document rv = NS_NewXMLDocument(getter_AddRefs(mDocument)); NS_ENSURE_SUCCESS(rv, rv); } + // This should really be handled by nsIDocument::BeginLoad + mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_LOADING); nsCOMPtr source = do_QueryInterface(aSourceDocument); NS_ENSURE_STATE(source); PRBool hasHadScriptObject = PR_FALSE; nsIScriptGlobalObject* sgo = source->GetScriptHandlingObject(hasHadScriptObject); NS_ENSURE_STATE(sgo || !hasHadScriptObject); mDocument->SetScriptHandlingObject(sgo); } diff --git a/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp b/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp --- a/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp +++ b/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp @@ -687,16 +687,18 @@ txMozillaXSLTProcessor::TransformToDoc(n rv = endRv; } if (NS_SUCCEEDED(rv)) { if (aResult) { txAOutputXMLEventHandler* handler = static_cast(es.mOutputHandler); handler->getOutputDocument(aResult); + nsCOMPtr doc = do_QueryInterface(*aResult); + doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); } } else if (mObserver) { // XXX set up context information, bug 204655 reportError(rv, nsnull, nsnull); } return rv; diff --git a/dom/public/idl/core/nsIDOMNSDocument.idl b/dom/public/idl/core/nsIDOMNSDocument.idl --- a/dom/public/idl/core/nsIDOMNSDocument.idl +++ b/dom/public/idl/core/nsIDOMNSDocument.idl @@ -49,16 +49,17 @@ interface nsIDOMNSDocument : nsISupports readonly attribute DOMString characterSet; attribute DOMString dir; readonly attribute nsIDOMLocation location; attribute DOMString title; readonly attribute DOMString contentType; + readonly attribute DOMString readyState; readonly attribute DOMString lastModified; readonly attribute DOMString referrer; nsIBoxObject getBoxObjectFor(in nsIDOMElement elt); boolean hasFocus(); readonly attribute nsIDOMElement activeElement; diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -964,16 +964,18 @@ DocumentViewerImpl::LoadComplete(nsresul // Now, fire either an OnLoad or OnError event to the document... PRBool restoring = PR_FALSE; // XXXbz imagelib kills off the document load for a full-page image with // NS_IMAGELIB_ERROR_LOAD_ABORTED if it's in the cache. So we want to treat // that one as a success code; otherwise whether we fire onload for the image // will depend on whether it's cached! if(window && (NS_SUCCEEDED(aStatus) || aStatus == NS_IMAGELIB_ERROR_LOAD_ABORTED)) { + if (mDocument) + mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); nsEventStatus status = nsEventStatus_eIgnore; nsEvent event(PR_TRUE, NS_LOAD); event.flags |= NS_EVENT_FLAG_CANT_BUBBLE; // XXX Dispatching to |window|, but using |document| as the target. event.target = mDocument; // If the document presentation is being restored, we don't want to fire // onload to the document content since that would likely confuse scripts