diff --git a/mozilla/content/xul/content/src/nsXULElement.cpp b/mozilla/content/xul/content/src/nsXULElement.cpp index eadd7863d38..307a8c4cdc9 100644 --- a/mozilla/content/xul/content/src/nsXULElement.cpp +++ b/mozilla/content/xul/content/src/nsXULElement.cpp @@ -17,7 +17,7 @@ * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): * Chris Waterson * Pierre Phaneuf * Peter Annema @@ -565,7 +565,7 @@ nsXULElement::Create(nsINodeInfo *aNodeInfo, nsIContent** aResult) NS_ASSERTION(aNodeInfo, "need nodeinfo for non-proto Create"); element->mSlots->mNodeInfo = aNodeInfo; - + *aResult = NS_REINTERPRET_CAST(nsIStyledContent*, element); NS_ADDREF(*aResult); @@ -583,7 +583,7 @@ nsXULElement::Create(nsINodeInfo *aNodeInfo, nsIContent** aResult) backtrace_symbols_fd(back, sizeof(back) / sizeof(back[0]), 2); } #endif - + return NS_OK; } @@ -1177,11 +1177,11 @@ nsXULElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) NS_ASSERTION(attr != nsnull, "null ptr"); if (! attr) return NS_ERROR_UNEXPECTED; - + nsAutoString value; rv = attr->GetValue(value); if (NS_FAILED(rv)) return rv; - + rv = result->SetAttr(attr->GetNodeInfo(), value, PR_FALSE); if (NS_FAILED(rv)) return rv; @@ -1507,7 +1507,7 @@ nsXULElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI, if (!aNamespaceURI.Equals(NS_LITERAL_STRING("*"))) { nsContentUtils::GetNSManagerWeakRef()->GetNameSpaceID(aNamespaceURI, nameSpaceId); - + if (nameSpaceId == kNameSpaceID_Unknown) { // Unknown namespace means no matches, we create an empty list... NS_GetContentList(mDocument, nsnull, kNameSpaceID_None, nsnull, @@ -1786,63 +1786,28 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext, void** aHandler) { nsresult rv; + JSObject* scopeObject; XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheSets); - nsCOMPtr context; - JSObject* scopeObject; - PRBool shared; - if (mPrototype) { - // It'll be shared amonst the instances of the prototype - shared = PR_TRUE; - - // Use the prototype document's special context - nsCOMPtr xuldoc = do_QueryInterface(mDocument); - NS_ASSERTION(xuldoc != nsnull, "mDocument is not an nsIXULDocument"); - if (! xuldoc) - return NS_ERROR_UNEXPECTED; - - nsCOMPtr protodoc; - rv = xuldoc->GetMasterPrototype(getter_AddRefs(protodoc)); - if (NS_FAILED(rv)) return rv; - - NS_ASSERTION(protodoc != nsnull, "xul document has no prototype"); - if (! protodoc) - return NS_ERROR_UNEXPECTED; - - nsCOMPtr globalOwner = do_QueryInterface(protodoc); - nsCOMPtr global; - globalOwner->GetScriptGlobalObject(getter_AddRefs(global)); - NS_ASSERTION(global != nsnull, "prototype doc does not have a script global"); - if (! global) - return NS_ERROR_UNEXPECTED; - - rv = global->GetContext(getter_AddRefs(context)); - if (NS_FAILED(rv)) return rv; - - // Use the prototype script's special scope object - - scopeObject = global->GetGlobalJSObject(); - if (!scopeObject) - return NS_ERROR_UNEXPECTED; + // It'll be shared among the instances of the prototype. + // Use null for the scope object when precompiling shared + // prototype scripts. + scopeObject = nsnull; } else { // We don't have a prototype; do a one-off compile. - shared = PR_FALSE; - context = aContext; + NS_ASSERTION(aTarget != nsnull, "no prototype and no target?!"); scopeObject = NS_REINTERPRET_CAST(JSObject*, aTarget); } - NS_ASSERTION(context != nsnull, "no script context"); - if (! context) - return NS_ERROR_UNEXPECTED; - // Compile the event handler - rv = context->CompileEventHandler(scopeObject, aName, aBody, shared, aHandler); + rv = aContext->CompileEventHandler(scopeObject, aName, aBody, !scopeObject, + aHandler); if (NS_FAILED(rv)) return rv; - if (shared) { + if (! scopeObject) { // If it's a shared handler, we need to bind the shared // function object to the real target. rv = aContext->BindCompiledEventHandler(aTarget, aName, *aHandler); @@ -1859,7 +1824,7 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext, attr->mEventHandler = *aHandler; if (attr->mEventHandler) { - JSContext *cx = (JSContext*) context->GetNativeContext(); + JSContext *cx = (JSContext*) aContext->GetNativeContext(); if (!cx) return NS_ERROR_UNEXPECTED; @@ -1916,7 +1881,7 @@ nsXULElement::AddListenerFor(nsINodeInfo *aNodeInfo, nsIID iid; PRBool isHandler = PR_FALSE; GetEventHandlerIID(attr, &iid, &isHandler); - + if (isHandler) { nsAutoString value; GetAttr(nameSpaceID, attr, value); @@ -2146,7 +2111,7 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify, if (aNotify && mDocument) { mDocument->ContentInserted(NS_STATIC_CAST(nsIStyledContent*, this), aKid, aIndex); } - + return NS_OK; } @@ -2345,7 +2310,7 @@ nsXULElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify) controlElement->SetCurrentItem(nsnull); } } - + if (fireSelectionHandler) { nsCOMPtr doc(do_QueryInterface(mDocument)); nsCOMPtr event; @@ -2426,7 +2391,7 @@ void nsXULElement::UnregisterAccessKey(const nsAString& aOldValue) { // If someone changes the accesskey, unregister the old one - // + // if (mDocument && !aOldValue.IsEmpty()) { nsCOMPtr shell; mDocument->GetShellAt(0, getter_AddRefs(shell)); @@ -2540,7 +2505,7 @@ nsXULElement::SetAttr(nsINodeInfo* aNodeInfo, } else { modification = PR_FALSE; } - + rv = nsXULAttribute::Create(NS_STATIC_CAST(nsIStyledContent*, this), aNodeInfo, aValue, &attr); if (NS_FAILED(rv)) return rv; @@ -2599,7 +2564,7 @@ nsXULElement::SetAttr(nsINodeInfo* aNodeInfo, ? PRInt32(nsIDOMMutationEvent::MODIFICATION) : PRInt32(nsIDOMMutationEvent::ADDITION); - mDocument->AttributeChanged(this, attrns, attrName, modHint, + mDocument->AttributeChanged(this, attrns, attrName, modHint, StyleHintFor(NodeInfo())); // XXXwaterson do we need to mDocument->EndUpdate() here? @@ -2871,7 +2836,7 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, if (aNotify) { mDocument->AttributeChanged(this, aNameSpaceID, aName, - nsIDOMMutationEvent::REMOVAL, + nsIDOMMutationEvent::REMOVAL, StyleHintFor(NodeInfo())); // XXXwaterson do we need to mDocument->EndUpdate() here? @@ -2917,7 +2882,7 @@ nsXULElement::GetAttrNameAt(PRInt32 aIndex, if (aIndex >= 0 && aIndex < mPrototype->mNumAttributes) { PRBool skip; nsXULPrototypeAttribute* attr; - do { + do { attr = &(mPrototype->mAttributes[aIndex]); skip = haveLocalAttributes && FindLocalAttribute(attr->mNodeInfo); #ifdef DEBUG_ATTRIBUTE_STATS @@ -3390,7 +3355,7 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, aDOMEvent = nsnull; } } - + return ret; } @@ -3699,7 +3664,7 @@ nsXULElement::GetMappedAttributeImpact(const nsIAtom* aAttribute, PRInt32 aModTy { aHint = NS_STYLE_HINT_CONTENT; // by default, never map attributes to style - if (aAttribute == nsXULAtoms::value && + if (aAttribute == nsXULAtoms::value && (aModType == nsIDOMMutationEvent::REMOVAL || aModType == nsIDOMMutationEvent::ADDITION)) { nsCOMPtr tag; GetTag(*getter_AddRefs(tag)); @@ -4269,7 +4234,7 @@ nsXULElement::Focus() nsCOMPtr shell; mDocument->GetShellAt(0, getter_AddRefs(shell)); - + // Retrieve the context nsCOMPtr aPresContext; shell->GetPresContext(getter_AddRefs(aPresContext)); @@ -4292,7 +4257,7 @@ nsXULElement::Blur() nsCOMPtr shell; mDocument->GetShellAt(0, getter_AddRefs(shell)); - + // Retrieve the context nsCOMPtr aPresContext; shell->GetPresContext(getter_AddRefs(aPresContext)); @@ -4348,7 +4313,7 @@ nsXULElement::Click() HandleDOMEvent(context, &eventClick, nsnull, NS_EVENT_FLAG_INIT, &status); } } - + // oncommand is fired when an element is clicked... return DoCommand(); } @@ -4366,7 +4331,7 @@ nsXULElement::DoCommand() for (PRInt32 i=0; iGetShellAt(i, getter_AddRefs(shell)); shell->GetPresContext(getter_AddRefs(context)); - + nsEventStatus status = nsEventStatus_eIgnore; nsMouseEvent event; event.eventStructType = NS_EVENT; @@ -4648,21 +4613,21 @@ nsXULElement::HideWindowChrome(PRBool aShouldHide) { PRInt32 shellCount = mDocument->GetNumberOfShells(); if (shellCount > 0) { - nsCOMPtr shell; + nsCOMPtr shell; mDocument->GetShellAt(0, getter_AddRefs(shell)); if (shell) { nsIContent* content = NS_STATIC_CAST(nsIContent*, this); nsIFrame* frame = nsnull; shell->GetPrimaryFrameFor(content, &frame); - + nsCOMPtr presContext; shell->GetPresContext(getter_AddRefs(presContext)); - + if (frame && presContext) { nsIView* view = nsnull; frame->GetView(presContext, &view); - + if (!view) { frame->GetParentWithView(presContext, &frame); if (frame) @@ -4675,7 +4640,7 @@ nsXULElement::HideWindowChrome(PRBool aShouldHide) widget->HideWindowChrome(aShouldHide); } - } + } } } @@ -4736,7 +4701,7 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream, rv |= aStream->Write32(index); // Write Attributes - rv |= aStream->Write32(mNumAttributes); + rv |= aStream->Write32(mNumAttributes); nsAutoString attributeValue; PRInt32 i; @@ -4762,17 +4727,25 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream, rv |= aStream->Write32(child->mType); nsXULPrototypeScript* script = NS_STATIC_CAST(nsXULPrototypeScript*, child); - if (script) { - rv |= aStream->Write8(script->mOutOfLine); - if (! script->mOutOfLine) - rv |= script->Serialize(aStream, aContext, aNodeInfos); - else - rv |= aStream->WriteCompoundObject(script->mSrcURI, - NS_GET_IID(nsIURI), - PR_TRUE); + rv |= aStream->Write8(script->mOutOfLine); + if (! script->mOutOfLine) { + rv |= script->Serialize(aStream, aContext, aNodeInfos); + } else { + rv |= aStream->WriteCompoundObject(script->mSrcURI, + NS_GET_IID(nsIURI), + PR_TRUE); + + if (script->mJSObject) { + // This may return NS_OK without muxing script->mSrcURI's + // data into the FastLoad file, in the case where that + // muxed document is already there (written by a prior + // session, or by an earlier FastLoad episode during this + // session). + rv |= script->SerializeOutOfLine(aStream, aContext); + } } break; - } + } } return rv; @@ -4780,7 +4753,7 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream, nsresult nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream, - nsIScriptContext* aContext, + nsIScriptContext* aContext, nsIURI* aDocumentURI, nsISupportsArray* aNodeInfos) { @@ -4852,7 +4825,7 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream, switch (childType) { case eType_Element: child = new nsXULPrototypeElement(); - if (! child) + if (! child) return NS_ERROR_OUT_OF_MEMORY; child->mType = childType; @@ -4864,7 +4837,7 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream, if (! child) return NS_ERROR_OUT_OF_MEMORY; child->mType = childType; - + rv |= child->Deserialize(aStream, aContext, aDocumentURI, aNodeInfos); break; @@ -4884,7 +4857,7 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream, else { rv |= aStream->ReadObject(PR_TRUE, getter_AddRefs(script->mSrcURI)); - rv |= script->DeserializeOutOfLineScript(aStream, aContext); + rv |= script->DeserializeOutOfLine(aStream, aContext); } break; } @@ -4892,13 +4865,14 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream, mChildren[i] = child; - // Oh dear. Something failed during the deserialization. We don't know what. - // But likely consequences of failed deserializations included calls to - // |AbortFastLoads| which shuts down the FastLoadService and closes our - // streams. If that happens, next time through this loop, we die a messy - // death. So, let's just fail now, and propagate that failure upward so that - // the ChromeProtocolHandler knows it can't use a cached chrome channel for - // this. + // Oh dear. Something failed during the deserialization. + // We don't know what. But likely consequences of failed + // deserializations included calls to |AbortFastLoads| which + // shuts down the FastLoadService and closes our streams. + // If that happens, next time through this loop, we die a messy + // death. So, let's just fail now, and propagate that failure + // upward so that the ChromeProtocolHandler knows it can't use + // a cached chrome channel for this. if (NS_FAILED(rv)) return rv; } @@ -5011,9 +4985,67 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream, return NS_OK; } +nsresult +nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream, + nsIScriptContext* aContext) +{ + nsIXULPrototypeCache* cache = GetXULCache(); +#ifdef NS_DEBUG + PRBool useXULCache = PR_TRUE; + cache->GetEnabled(&useXULCache); + NS_ASSERTION(useXULCache, + "writing to the FastLoad file, but the XUL cache is off?"); +#endif + + nsCOMPtr fastLoadService; + cache->GetFastLoadService(getter_AddRefs(fastLoadService)); + + nsresult rv = NS_OK; + if (!fastLoadService) + return rv; + + nsCAutoString urispec; + rv = mSrcURI->GetAsciiSpec(urispec); + if (NS_FAILED(rv)) + return rv; + + PRBool exists = PR_FALSE; + fastLoadService->HasMuxedDocument(urispec.get(), &exists); + if (exists) + return rv; + + // Allow callers to pass null for aStream, meaning + // "use the FastLoad service's default output stream." + // See nsXULDocument.cpp for one use of this. + nsCOMPtr objectOutput = aStream; + if (! objectOutput) + fastLoadService->GetOutputStream(getter_AddRefs(objectOutput)); + + rv = fastLoadService-> + StartMuxedDocument(mSrcURI, urispec.get(), + nsIFastLoadService::NS_FASTLOAD_WRITE); + NS_ASSERTION(rv != NS_ERROR_NOT_AVAILABLE, "reading FastLoad?!"); + + nsCOMPtr oldURI; + rv |= fastLoadService->SelectMuxedDocument(mSrcURI, getter_AddRefs(oldURI)); + rv |= Serialize(objectOutput, aContext, nsnull); + rv |= fastLoadService->EndMuxedDocument(mSrcURI); + + if (oldURI) { + nsCOMPtr tempURI; + rv |= fastLoadService-> + SelectMuxedDocument(oldURI, getter_AddRefs(tempURI)); + } + + if (NS_FAILED(rv)) + cache->AbortFastLoads(); + return rv; +} + + nsresult nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream, - nsIScriptContext* aContext, + nsIScriptContext* aContext, nsIURI* aDocumentURI, nsISupportsArray* aNodeInfos) { @@ -5022,10 +5054,10 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream, // Read basic prototype data aStream->Read16(&mLineNo); - + NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull || !mJSObject, "prototype script not well-initialized when deserializing?!"); - + PRUint32 size; rv = aStream->Read32(&size); if (NS_FAILED(rv)) return rv; @@ -5098,8 +5130,8 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream, nsresult -nsXULPrototypeScript::DeserializeOutOfLineScript(nsIObjectInputStream* aInput, - nsIScriptContext* aContext) +nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput, + nsIScriptContext* aContext) { // Keep track of FastLoad failure via rv, so we can // AbortFastLoads if things look bad. @@ -5173,7 +5205,7 @@ nsXULPrototypeScript::DeserializeOutOfLineScript(nsIObjectInputStream* aInput, nsCOMPtr tempURI; rv = fastLoadService->SelectMuxedDocument(oldURI, getter_AddRefs(tempURI)); - NS_ASSERTION(NS_SUCCEEDED(rv) && (!tempURI || tempURI == mSrcURI), + NS_ASSERTION(NS_SUCCEEDED(rv) && (!tempURI || tempURI == mSrcURI), "not currently deserializing into the script we thought we were!"); } } @@ -5183,7 +5215,6 @@ nsXULPrototypeScript::DeserializeOutOfLineScript(nsIObjectInputStream* aInput, PRBool isChrome = PR_FALSE; mSrcURI->SchemeIs("chrome", &isChrome); if (isChrome) { - nsIXULPrototypeCache* cache = GetXULCache(); cache->PutScript(mSrcURI, NS_REINTERPRET_CAST(void*, mJSObject)); } } @@ -5218,16 +5249,12 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText, // __parent__ pointer to the first document's global. If that // happened, our script object would reference the first document, // and the first document would indirectly reference the prototype - // document because it keeps the prototype cache - // alive. Circularity! + // document because it keeps the prototype cache alive. Circularity! nsresult rv; // Use the prototype document's special context nsCOMPtr context; - // Use the prototype script's special scope object - JSObject* scopeObject; - { nsCOMPtr global; nsCOMPtr globalOwner @@ -5243,10 +5270,6 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText, NS_ASSERTION(context != nsnull, "no context for script global"); if (! context) return NS_ERROR_UNEXPECTED; - - scopeObject = global->GetGlobalJSObject(); - if (!scopeObject) - return NS_ERROR_UNEXPECTED; } // Use the enclosing document's principal @@ -5262,43 +5285,14 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText, // Ok, compile it to create a prototype script object! rv = context->CompileScript(aText, aTextLength, - scopeObject, + nsnull, principal, urlspec.get(), aLineNo, mLangVersion, (void**)&mJSObject); - if (NS_FAILED(rv)) return rv; - - if (mJSObject) { - // Root the compiled prototype script object. - JSContext* cx = NS_REINTERPRET_CAST(JSContext*, - context->GetNativeContext()); - if (!cx) - return NS_ERROR_UNEXPECTED; - - - if (mOutOfLine) { - nsCOMPtr fastLoadService; - - nsIXULPrototypeCache* cache = GetXULCache(); - cache->GetFastLoadService(getter_AddRefs(fastLoadService)); - - if (fastLoadService) { - nsCOMPtr objectOutput; - fastLoadService->GetOutputStream(getter_AddRefs(objectOutput)); - if (objectOutput) { - rv = Serialize(objectOutput, context, nsnull); - if (NS_FAILED(rv)) - cache->AbortFastLoads(); - } - } - } - } - - return NS_OK; - + return rv; } //---------------------------------------------------------------------- @@ -5323,7 +5317,7 @@ nsXULPrototypeText::Serialize(nsIObjectOutputStream* aStream, nsresult nsXULPrototypeText::Deserialize(nsIObjectInputStream* aStream, - nsIScriptContext* aContext, + nsIScriptContext* aContext, nsIURI* aDocumentURI, nsISupportsArray* aNodeInfos) { @@ -5331,6 +5325,6 @@ nsXULPrototypeText::Deserialize(nsIObjectInputStream* aStream, // Write basic prototype data rv = aStream->ReadString(mValue); - + return rv; } diff --git a/mozilla/content/xul/content/src/nsXULElement.h b/mozilla/content/xul/content/src/nsXULElement.h index 2ed9920f134..041746e4dcd 100644 --- a/mozilla/content/xul/content/src/nsXULElement.h +++ b/mozilla/content/xul/content/src/nsXULElement.h @@ -14,7 +14,7 @@ * * The Original Code is Mozilla Communicator client code. * - * The Initial Developer of the Original Code is + * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. @@ -195,7 +195,7 @@ public: Type mType; PRInt32 mRefCnt; - + virtual ~nsXULPrototypeNode() {} virtual nsresult Serialize(nsIObjectOutputStream* aStream, nsIScriptContext* aContext, @@ -206,11 +206,11 @@ public: nsISupportsArray* aNodeInfos) = 0; void AddRef() { ++mRefCnt; }; - void Release() - { - --mRefCnt; - if (mRefCnt == 0) - delete this; + void Release() + { + --mRefCnt; + if (mRefCnt == 0) + delete this; }; virtual void ReleaseSubtree() { Release(); }; @@ -242,7 +242,7 @@ public: delete[] mChildren; } - virtual void ReleaseSubtree() + virtual void ReleaseSubtree() { if (mChildren) { for (PRInt32 i = mNumChildren-1; i >= 0; i--) { @@ -277,8 +277,8 @@ public: nsresult GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsAString& aValue); - static void ReleaseGlobals() - { + static void ReleaseGlobals() + { NS_IF_RELEASE(sCSSParser); } @@ -305,12 +305,14 @@ public: virtual nsresult Serialize(nsIObjectOutputStream* aStream, nsIScriptContext* aContext, nsISupportsArray* aNodeInfos); + nsresult SerializeOutOfLine(nsIObjectOutputStream* aStream, + nsIScriptContext* aContext); virtual nsresult Deserialize(nsIObjectInputStream* aStream, nsIScriptContext* aContext, nsIURI* aDocumentURI, nsISupportsArray* aNodeInfos); - virtual nsresult DeserializeOutOfLineScript(nsIObjectInputStream* aInput, - nsIScriptContext* aContext); + nsresult DeserializeOutOfLine(nsIObjectInputStream* aInput, + nsIScriptContext* aContext); nsresult Compile(const PRUnichar* aText, PRInt32 aTextLength, nsIURI* aURI, PRUint16 aLineNo, @@ -325,9 +327,9 @@ public: JSObject* mJSObject; const char* mLangVersion; - static void ReleaseGlobals() - { - NS_IF_RELEASE(sXULPrototypeCache); + static void ReleaseGlobals() + { + NS_IF_RELEASE(sXULPrototypeCache); } protected: @@ -402,7 +404,7 @@ public: // nsISupports NS_DECL_ISUPPORTS - + // nsIContent (from nsIStyledContent) NS_IMETHOD GetDocument(nsIDocument*& aResult) const; NS_IMETHOD SetDocument(nsIDocument* aDocument, PRBool aDeep, PRBool aCompileEventHandlers); @@ -431,7 +433,7 @@ public: NS_IMETHOD GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom*& aPrefix, nsAString& aResult) const; NS_IMETHOD_(PRBool) HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const; NS_IMETHOD UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify); - NS_IMETHOD GetAttrNameAt(PRInt32 aIndex, PRInt32& aNameSpaceID, + NS_IMETHOD GetAttrNameAt(PRInt32 aIndex, PRInt32& aNameSpaceID, nsIAtom*& aName, nsIAtom*& aPrefix) const; NS_IMETHOD GetAttrCount(PRInt32& aResult) const; #ifdef DEBUG @@ -449,7 +451,7 @@ public: NS_IMETHOD SetContentID(PRUint32 aID); NS_IMETHOD RangeAdd(nsIDOMRange* aRange); - NS_IMETHOD RangeRemove(nsIDOMRange* aRange); + NS_IMETHOD RangeRemove(nsIDOMRange* aRange); NS_IMETHOD GetRangeList(nsVoidArray*& aResult) const; NS_IMETHOD SetFocus(nsIPresContext* aPresContext); NS_IMETHOD RemoveFocus(nsIPresContext* aPresContext); @@ -480,10 +482,10 @@ public: NS_IMETHOD ClearLazyState(LazyState aFlags); NS_IMETHOD GetLazyState(LazyState aFlag, PRBool& aValue); NS_IMETHOD AddScriptEventListener(nsIAtom* aName, const nsAString& aValue); - + // nsIDOMNode (from nsIDOMElement) NS_DECL_NSIDOMNODE - + // nsIDOMElement NS_DECL_NSIDOMELEMENT @@ -641,7 +643,7 @@ protected: nsresult AddListenerFor(nsINodeInfo *aNodeInfo, PRBool aCompileEventHandlers); - + nsresult HideWindowChrome(PRBool aShouldHide); protected: diff --git a/mozilla/content/xul/document/src/nsXULContentSink.cpp b/mozilla/content/xul/document/src/nsXULContentSink.cpp index e12af232f02..8c535459626 100644 --- a/mozilla/content/xul/document/src/nsXULContentSink.cpp +++ b/mozilla/content/xul/document/src/nsXULContentSink.cpp @@ -1443,7 +1443,7 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes, nsCOMPtr scriptContext; globalObject->GetContext(getter_AddRefs(scriptContext)); if (scriptContext) - script->DeserializeOutOfLineScript(nsnull, scriptContext); + script->DeserializeOutOfLine(nsnull, scriptContext); } } } diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index bf7dd7fec1a..608fca2cd62 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -14,7 +14,7 @@ * * The Original Code is Mozilla Communicator client code. * - * The Initial Developer of the Original Code is + * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. @@ -642,7 +642,10 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, getter_AddRefs(parser)); if (NS_FAILED(rv)) return rv; - mIsWritingFastLoad = PR_TRUE; + // Predicate mIsWritingFastLoad on the XUL cache being enabled, + // so we don't have to re-check whether the cache is enabled all + // the time. + mIsWritingFastLoad = useXULCache; nsCOMPtr listener = do_QueryInterface(parser, &rv); NS_ASSERTION(NS_SUCCEEDED(rv), "parser doesn't support nsIStreamListener"); @@ -740,7 +743,6 @@ nsXULDocument::EndLoad() // its load completion via proto->AwaitLoadDone(). rv = mCurrentPrototype->NotifyLoadDone(); if (NS_FAILED(rv)) return rv; - } // Now walk the prototype to build content. @@ -3081,21 +3083,21 @@ nsXULDocument::ResumeWalk() // - Ben Goodger // // We don't abort on failure here because there are too many valid - // cases that can return failure, and the null-ness of |proto| is enough - // to trigger the fail-safe parse-from-disk solution. Example failure cases - // (for reference) include: + // cases that can return failure, and the null-ness of |proto| is + // enough to trigger the fail-safe parse-from-disk solution. + // Example failure cases (for reference) include: // - // NS_ERROR_NOT_AVAILABLE: the URI cannot be found in the FastLoad cache, + // NS_ERROR_NOT_AVAILABLE: the URI was not found in the FastLoad file, // parse from disk - // other: the FastLoad cache file, XUL.mfl, could not be found, probably - // due to being accessed before a profile has been selected (e.g. - // loading chrome for the profile manager itself). This must be - // parsed from disk. + // other: the FastLoad file, XUL.mfl, could not be found, probably + // due to being accessed before a profile has been selected + // (e.g. loading chrome for the profile manager itself). + // The .xul file must be parsed from disk. - PRBool cache; - gXULCache->GetEnabled(&cache); + PRBool useXULCache; + gXULCache->GetEnabled(&useXULCache); - if (cache && mCurrentPrototype) { + if (useXULCache && mCurrentPrototype) { NS_ASSERTION(IsChromeURI(uri), "XUL cache hit on non-chrome URI?"); PRBool loaded; rv = mCurrentPrototype->AwaitLoadDone(this, &loaded); @@ -3127,7 +3129,10 @@ nsXULDocument::ResumeWalk() rv = PrepareToLoadPrototype(uri, "view", nsnull, getter_AddRefs(parser)); if (NS_FAILED(rv)) return rv; - mIsWritingFastLoad = PR_TRUE; + // Predicate mIsWritingFastLoad on the XUL cache being enabled, + // so we don't have to re-check whether the cache is enabled all + // the time. + mIsWritingFastLoad = useXULCache; nsCOMPtr listener = do_QueryInterface(parser); if (! listener) @@ -3153,7 +3158,7 @@ nsXULDocument::ResumeWalk() // each time. We must do this after NS_OpenURI and AsyncOpen, // or chrome code will wrongly create a cached chrome channel // instead of a real one. - if (cache && IsChromeURI(uri)) { + if (useXULCache && IsChromeURI(uri)) { rv = gXULCache->PutPrototype(mCurrentPrototype); if (NS_FAILED(rv)) return rv; } @@ -3179,10 +3184,7 @@ nsXULDocument::ResumeWalk() StartLayout(); - PRBool useXULCache; - gXULCache->GetEnabled(&useXULCache); - - if (useXULCache && mIsWritingFastLoad && IsChromeURI(mDocumentURL)) + if (mIsWritingFastLoad && IsChromeURI(mDocumentURL)) gXULCache->WritePrototype(mMasterPrototype); for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) { @@ -3325,43 +3327,12 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader, // nsXULContentSink.cpp) would have already deserialized a non-null // script->mJSObject, causing control flow at the top of LoadScript // not to reach here. - // - // Start and Select the .js document in the FastLoad multiplexor - // before serializing script data under scriptProto->Compile, and - // End muxing afterward. nsCOMPtr uri = scriptProto->mSrcURI; - nsCOMPtr fastLoadService; - PRBool useXULCache; - gXULCache->GetEnabled(&useXULCache); - if (useXULCache) - gXULCache->GetFastLoadService(getter_AddRefs(fastLoadService)); - - nsresult rv2 = NS_OK; - if (fastLoadService) { - nsCAutoString urispec; - uri->GetAsciiSpec(urispec); - rv2 = fastLoadService->StartMuxedDocument(uri, urispec.get(), - nsIFastLoadService::NS_FASTLOAD_WRITE); - NS_ASSERTION(rv2 != NS_ERROR_NOT_AVAILABLE, "reading FastLoad?!"); - if (NS_SUCCEEDED(rv2)) { - nsCOMPtr oldURI; - fastLoadService->SelectMuxedDocument(uri, getter_AddRefs(oldURI)); - } - } - nsString stringStr; stringStr.AssignWithConversion(string, stringLen); rv = scriptProto->Compile(stringStr.get(), stringLen, uri, 1, this, mCurrentPrototype); - // End muxing the .js file into the FastLoad file. We don't Abort - // the FastLoad process here, when writing, as we do when reading. - // XXXbe maybe we should... - // NB: we don't need to Select mDocumentURL again, because scripts - // load after their including prototype document has fully loaded. - if (fastLoadService && NS_SUCCEEDED(rv2)) - fastLoadService->EndMuxedDocument(uri); - aStatus = rv; if (NS_SUCCEEDED(rv) && scriptProto->mJSObject) { rv = ExecuteScript(scriptProto->mJSObject); @@ -3394,6 +3365,24 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader, gXULCache->PutScript(scriptProto->mSrcURI, NS_REINTERPRET_CAST(void*, scriptProto->mJSObject)); } + + if (mIsWritingFastLoad && mCurrentPrototype != mMasterPrototype) { + // If we are loading an overlay script, try to serialize + // it to the FastLoad file here. Master scripts will be + // serialized when the master prototype document gets + // written, at the bottom of ResumeWalk. That way, master + // out-of-line scripts are serialized in the same order that + // they'll be read, in the FastLoad file, which reduces the + // number of seeks that dump the underlying stream's buffer. + // + // Ignore the return value, as we don't need to propagate + // a failure to write to the FastLoad file, because this + // method aborts that whole process on error. + nsCOMPtr scriptContext; + mScriptGlobalObject->GetContext(getter_AddRefs(scriptContext)); + if (scriptContext) + scriptProto->SerializeOutOfLine(nsnull, scriptContext); + } } // ignore any evaluation errors } diff --git a/mozilla/netwerk/base/src/nsBufferedStreams.cpp b/mozilla/netwerk/base/src/nsBufferedStreams.cpp index 8493482938c..d3f7c481f52 100644 --- a/mozilla/netwerk/base/src/nsBufferedStreams.cpp +++ b/mozilla/netwerk/base/src/nsBufferedStreams.cpp @@ -110,6 +110,34 @@ nsBufferedStream::Close() mBufferStartOffset = 0; mCursor = 0; } +#ifdef METERING + { + static FILE *tfp; + if (!tfp) { + tfp = fopen("/tmp/bufstats", "w"); + if (tfp) + setvbuf(tfp, NULL, _IOLBF, 0); + } + if (tfp) { + fprintf(tfp, "seeks within buffer: %u\n", + bufstats.mSeeksWithinBuffer); + fprintf(tfp, "seeks outside buffer: %u\n", + bufstats.mSeeksOutsideBuffer); + fprintf(tfp, "buffer read on seek: %u\n", + bufstats.mBufferReadUponSeek); + fprintf(tfp, "buffer unread on seek: %u\n", + bufstats.mBufferUnreadUponSeek); + fprintf(tfp, "bytes read from buffer: %u\n", + bufstats.mBytesReadFromBuffer); + for (PRUint32 i = 0; i < bufstats.mBigSeekIndex; i++) { + fprintf(tfp, "bigseek[%u] = {old: %u, new: %u}\n", + i, + bufstats.mBigSeek[i].mOldOffset, + bufstats.mBigSeek[i].mNewOffset); + } + } + } +#endif return NS_OK; } diff --git a/mozilla/xpcom/io/nsFastLoadFile.cpp b/mozilla/xpcom/io/nsFastLoadFile.cpp index ffe4e2ad08e..3e84fa12ba5 100644 --- a/mozilla/xpcom/io/nsFastLoadFile.cpp +++ b/mozilla/xpcom/io/nsFastLoadFile.cpp @@ -14,7 +14,7 @@ * * The Original Code is Mozilla FastLoad code. * - * The Initial Developer of the Original Code is + * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. @@ -23,7 +23,7 @@ * Brendan Eich (original author) * * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or + * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only @@ -255,7 +255,7 @@ static const char magic[] = MFL_FILE_MAGIC; nsID nsFastLoadFileReader::nsFastLoadFooter::gDummyID; nsFastLoadFileReader::nsObjectMapEntry - nsFastLoadFileReader::nsFastLoadFooter::gDummySharpObjectEntry; + nsFastLoadFileReader::nsFastLoadFooter::gDummySharpObjectEntry; NS_IMPL_ISUPPORTS_INHERITED5(nsFastLoadFileReader, nsBinaryInputStream, @@ -317,7 +317,11 @@ struct nsDocumentMapEntry : public nsStringMapEntry { struct nsDocumentMapReadEntry : public nsDocumentMapEntry { PRUint32 mNextSegmentOffset; // offset of URI's next segment to read - PRUint32 mBytesLeft; // bytes remaining in current segment + PRUint32 mBytesLeft : 31, // bytes remaining in current segment + mNeedToSeek : 1; // flag to defer Seek from Select to + // Read, in case there is no Read before + // another entry is Selected (to improve + // input stream buffer utilization) PRUint32 mSaveOffset; // in case demux schedule differs from // mux schedule }; @@ -393,6 +397,18 @@ static const PLDHashTableOps objmap_DHashTableOps = { NULL }; +NS_IMETHODIMP +nsFastLoadFileReader::HasMuxedDocument(const char* aURISpec, PRBool *aResult) +{ + nsDocumentMapReadEntry* docMapEntry = + NS_STATIC_CAST(nsDocumentMapReadEntry*, + PL_DHashTableOperate(&mFooter.mDocumentMap, aURISpec, + PL_DHASH_LOOKUP)); + + *aResult = PL_DHASH_ENTRY_IS_BUSY(docMapEntry); + return NS_OK; +} + NS_IMETHODIMP nsFastLoadFileReader::StartMuxedDocument(nsISupports* aURI, const char* aURISpec) { @@ -447,9 +463,13 @@ nsFastLoadFileReader::SelectMuxedDocument(nsISupports* aURI, return NS_ERROR_NOT_AVAILABLE; // If we're interrupting another document's segment, save its offset so - // we can seek back when it's reselected. + // we can seek back when it's reselected. If prevDocMapEntry->mNeedToSeek + // is set, that means the stream is not positioned for prevDocMapEntry, to + // avoid buffer thrashing. See below in this function for more. nsDocumentMapReadEntry* prevDocMapEntry = mCurrentDocumentMapEntry; - if (prevDocMapEntry && prevDocMapEntry->mBytesLeft) { + if (prevDocMapEntry && + prevDocMapEntry->mBytesLeft && + !prevDocMapEntry->mNeedToSeek) { rv = Tell(&prevDocMapEntry->mSaveOffset); if (NS_FAILED(rv)) return rv; @@ -460,23 +480,22 @@ nsFastLoadFileReader::SelectMuxedDocument(nsISupports* aURI, // As more data gets FastLoaded, the number of these useless selects will // decline. nsDocumentMapReadEntry* docMapEntry = uriMapEntry->mDocMapEntry; - if (docMapEntry == mCurrentDocumentMapEntry) { + if (docMapEntry == prevDocMapEntry) { TRACE_MUX(('r', "select prev %s same as current!\n", docMapEntry->mString)); } // Invariant: docMapEntry->mBytesLeft implies docMapEntry->mSaveOffset has // been set non-zero by the Tell call above. - if (docMapEntry->mBytesLeft) { + else if (docMapEntry->mBytesLeft) { NS_ASSERTION(docMapEntry->mSaveOffset != 0, "reselecting from multiplex at unsaved offset?"); - // Don't call our Seek wrapper, as it clears mCurrentDocumentMapEntry. - nsCOMPtr seekable(do_QueryInterface(mInputStream)); - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - docMapEntry->mSaveOffset); - if (NS_FAILED(rv)) - return rv; + // Defer Seek till Read, in case of "ping-pong" Selects without any + // intervening Reads, to avoid dumping the underlying mInputStream's + // input buffer for cases where alternate "pongs" fall in the same + // buffer. + docMapEntry->mNeedToSeek = PR_TRUE; } *aResult = prevDocMapEntry ? prevDocMapEntry->mURI : nsnull; @@ -528,15 +547,23 @@ nsFastLoadFileReader::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead) nsresult rv; nsDocumentMapReadEntry* entry = mCurrentDocumentMapEntry; - if (entry && entry->mBytesLeft == 0) { + if (entry) { // Don't call our Seek wrapper, as it clears mCurrentDocumentMapEntry. nsCOMPtr seekable(do_QueryInterface(mInputStream)); + if (entry->mNeedToSeek) { + rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, + entry->mSaveOffset); + if (NS_FAILED(rv)) + return rv; + + entry->mNeedToSeek = PR_FALSE; + } // Loop to handle empty segments, which may be generated by the // writer, given Start A; Start B; Select A; Select B; write B data; // multiplexing schedules, which do tend to occur given non-blocking // i/o with LIFO scheduling. XXXbe investigate LIFO issues - do { + while (entry->mBytesLeft == 0) { // Check for unexpected end of multiplexed stream. NS_ASSERTION(entry->mNextSegmentOffset != 0, "document demuxed from FastLoad file more than once?"); @@ -552,8 +579,11 @@ nsFastLoadFileReader::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead) mCurrentDocumentMapEntry = nsnull; rv = Read32(&entry->mNextSegmentOffset); - if (NS_SUCCEEDED(rv)) - rv = Read32(&entry->mBytesLeft); + if (NS_SUCCEEDED(rv)) { + PRUint32 bytesLeft = 0; + rv = Read32(&bytesLeft); + entry->mBytesLeft = bytesLeft; + } mCurrentDocumentMapEntry = entry; if (NS_FAILED(rv)) @@ -561,13 +591,13 @@ nsFastLoadFileReader::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead) NS_ASSERTION(entry->mBytesLeft >= 8, "demux segment length botch!"); entry->mBytesLeft -= 8; - } while (entry->mBytesLeft == 0); + } } rv = mInputStream->Read(aBuffer, aCount, aBytesRead); if (NS_SUCCEEDED(rv) && entry) { - NS_ASSERTION(entry->mBytesLeft >= *aBytesRead, "demux underflow!"); + NS_ASSERTION(entry->mBytesLeft >= *aBytesRead, "demux Read underflow!"); entry->mBytesLeft -= *aBytesRead; #ifdef NS_DEBUG @@ -579,6 +609,31 @@ nsFastLoadFileReader::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead) return rv; } +NS_IMETHODIMP +nsFastLoadFileReader::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, + PRUint32 aCount, PRUint32 *aResult) +{ + nsDocumentMapReadEntry* entry = mCurrentDocumentMapEntry; + + NS_ASSERTION(!entry || (!entry->mNeedToSeek && entry->mBytesLeft != 0), + "ReadSegments called from above nsFastLoadFileReader layer?!"); + + nsresult rv = nsBinaryInputStream::ReadSegments(aWriter, aClosure, aCount, + aResult); + if (NS_SUCCEEDED(rv) && entry) { + NS_ASSERTION(entry->mBytesLeft >= *aResult, + "demux ReadSegments underflow!"); + entry->mBytesLeft -= *aResult; + +#ifdef NS_DEBUG + // Invariant: !entry->mBytesLeft implies entry->mSaveOffset == 0. + if (entry->mBytesLeft == 0) + entry->mSaveOffset = 0; +#endif + } + return rv; +} + /** * XXX tuneme */ @@ -735,6 +790,7 @@ nsFastLoadFileReader::ReadFooter(nsFastLoadFooter *aFooter) entry->mInitialSegmentOffset = info.mInitialSegmentOffset; entry->mNextSegmentOffset = info.mInitialSegmentOffset; entry->mBytesLeft = 0; + entry->mNeedToSeek = PR_FALSE; entry->mSaveOffset = 0; } @@ -852,7 +908,7 @@ nsFastLoadFileReader::ReadSharpObjectInfo(nsFastLoadSharpObjectInfo *aInfo) if (NS_FAILED(rv)) return rv; - NS_ASSERTION(aInfo->mCIDOffset != 0, + NS_ASSERTION(aInfo->mCIDOffset != 0, "fastload reader: mCIDOffset cannot be zero!"); rv = Read16(&aInfo->mStrongRefCnt); @@ -1027,8 +1083,10 @@ nsFastLoadFileReader::ReadObject(PRBool aIsStrongRef, nsISupports* *aObject) if (entry->mCIDOffset != saveOffset) { // We skipped deserialization of this object from its position // earlier in the input stream, presumably due to the reference - // there being an nsFastLoadPtr or some such thing. Seek back - // and read it now. + // there being an nsFastLoadPtr, or (more likely) because the + // object was muxed in another document, and deserialization + // order does not match serialization order. So we must seek + // back and read it now. NS_ASSERTION(entry->mCIDOffset < saveOffset, "out of order object?!"); @@ -1306,6 +1364,18 @@ struct nsURIMapWriteEntry : public nsObjectMapEntry { const char* mURISpec; }; +NS_IMETHODIMP +nsFastLoadFileWriter::HasMuxedDocument(const char* aURISpec, PRBool *aResult) +{ + nsDocumentMapWriteEntry* docMapEntry = + NS_STATIC_CAST(nsDocumentMapWriteEntry*, + PL_DHashTableOperate(&mDocumentMap, aURISpec, + PL_DHASH_LOOKUP)); + + *aResult = PL_DHASH_ENTRY_IS_BUSY(docMapEntry); + return NS_OK; +} + NS_IMETHODIMP nsFastLoadFileWriter::StartMuxedDocument(nsISupports* aURI, const char* aURISpec) @@ -1629,7 +1699,7 @@ nsFastLoadFileWriter::WriteSharpObjectInfo(const nsFastLoadSharpObjectInfo& aInf { nsresult rv; - NS_ASSERTION(aInfo.mCIDOffset != 0, + NS_ASSERTION(aInfo.mCIDOffset != 0, "fastload writer: mCIDOffset cannot be zero!"); rv = Write32(aInfo.mCIDOffset); @@ -1961,7 +2031,7 @@ nsFastLoadFileWriter::Close() PRUint32 checksum = 0; // Ok, we're finally ready to checksum the FastLoad file we just wrote! - while (NS_SUCCEEDED(rv = + while (NS_SUCCEEDED(rv = input->Read(buf + rem, sizeof buf - rem, &len)) && len) { len += rem; diff --git a/mozilla/xpcom/io/nsFastLoadFile.h b/mozilla/xpcom/io/nsFastLoadFile.h index 33de408deb4..25358df203b 100644 --- a/mozilla/xpcom/io/nsFastLoadFile.h +++ b/mozilla/xpcom/io/nsFastLoadFile.h @@ -290,6 +290,14 @@ class nsFastLoadFileReader // Override Read so we can demultiplex a document interleaved with others. NS_IMETHOD Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead); + // Override ReadSegments too, as nsBinaryInputStream::ReadSegments does + // not call through our overridden Read method -- it calls directly into + // the underlying input stream. + NS_IMETHODIMP nsFastLoadFileReader::ReadSegments(nsWriteSegmentFun aWriter, + void* aClosure, + PRUint32 aCount, + PRUint32 *aResult); + nsresult ReadHeader(nsFastLoadHeader *aHeader); /** diff --git a/mozilla/xpcom/io/nsFastLoadService.cpp b/mozilla/xpcom/io/nsFastLoadService.cpp index e16b4de7d79..879d7c123b4 100644 --- a/mozilla/xpcom/io/nsFastLoadService.cpp +++ b/mozilla/xpcom/io/nsFastLoadService.cpp @@ -231,6 +231,30 @@ nsFastLoadService::GetDirection(PRInt32 *aResult) return NS_OK; } +NS_IMETHODIMP +nsFastLoadService::HasMuxedDocument(const char* aURISpec, PRBool *aResult) +{ + nsresult rv = NS_ERROR_NOT_AVAILABLE; + nsCOMPtr control; + + *aResult = PR_FALSE; + nsAutoLock lock(mLock); + + if (mInputStream) { + control = do_QueryInterface(mInputStream); + if (control) + rv = control->HasMuxedDocument(aURISpec, aResult); + } + + if (! *aResult && mOutputStream) { + control = do_QueryInterface(mOutputStream); + if (control) + rv = control->HasMuxedDocument(aURISpec, aResult); + } + + return rv; +} + NS_IMETHODIMP nsFastLoadService::StartMuxedDocument(nsISupports* aURI, const char* aURISpec, PRInt32 aDirectionFlags) diff --git a/mozilla/xpcom/io/nsIFastLoadFileControl.idl b/mozilla/xpcom/io/nsIFastLoadFileControl.idl index 81e63e38865..04fb0b5625e 100644 --- a/mozilla/xpcom/io/nsIFastLoadFileControl.idl +++ b/mozilla/xpcom/io/nsIFastLoadFileControl.idl @@ -85,6 +85,12 @@ interface nsIFastLoadFileControl : nsISupports void startMuxedDocument(in nsISupports aURI, in string aURISpec); nsISupports selectMuxedDocument(in nsISupports aURI); void endMuxedDocument(in nsISupports aURI); + + /** + * Return true if aURISpec identifies a muxed document in the FastLoad + * file, false otherwise. + */ + boolean hasMuxedDocument(in string aURISpec); }; [scriptable, uuid(652ecec6-d40b-45b6-afef-641d6c63a35b)] diff --git a/mozilla/xpcom/io/nsIFastLoadService.idl b/mozilla/xpcom/io/nsIFastLoadService.idl index 57590350d64..a849886d4cb 100644 --- a/mozilla/xpcom/io/nsIFastLoadService.idl +++ b/mozilla/xpcom/io/nsIFastLoadService.idl @@ -106,6 +106,12 @@ interface nsIFastLoadService : nsISupports [noscript] void writeFastLoadPtr(in nsIObjectOutputStream aOutputStream, in nsISupports aPtr); + + /** + * Return true if aURISpec identifies a muxed document in the FastLoad + * file, false otherwise. + */ + boolean hasMuxedDocument(in string aURISpec); }; %{C++