Back to index

lightning-sunbird  0.9+nobinonly
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Protected Member Functions | Static Protected Attributes
nsXULPrototypeScript Class Reference

#include <nsXULElement.h>

Inheritance diagram for nsXULPrototypeScript:
Inheritance graph
[legend]
Collaboration diagram for nsXULPrototypeScript:
Collaboration graph
[legend]

List of all members.

Public Types

enum  Type { eType_Element, eType_Script, eType_Text }

Public Member Functions

 nsXULPrototypeScript (PRUint32 aLineNo, const char *aVersion, PRBool aHasE4XOption, nsresult *rv)
virtual ~nsXULPrototypeScript ()
virtual nsresult Serialize (nsIObjectOutputStream *aStream, nsIScriptContext *aContext, const nsCOMArray< nsINodeInfo > *aNodeInfos)
nsresult SerializeOutOfLine (nsIObjectOutputStream *aStream, nsIScriptContext *aContext)
virtual nsresult Deserialize (nsIObjectInputStream *aStream, nsIScriptContext *aContext, nsIURI *aDocumentURI, const nsCOMArray< nsINodeInfo > *aNodeInfos)
nsresult DeserializeOutOfLine (nsIObjectInputStream *aInput, nsIScriptContext *aContext)
nsresult Compile (const PRUnichar *aText, PRInt32 aTextLength, nsIURI *aURI, PRUint32 aLineNo, nsIDocument *aDocument, nsIXULPrototypeDocument *aPrototypeDocument)
void AddRef ()
void Release ()
virtual void ReleaseSubtree ()

Static Public Member Functions

static void ReleaseGlobals ()

Public Attributes

nsCOMPtr< nsIURImSrcURI
PRUint32 mLineNo
PRPackedBool mSrcLoading
PRPackedBool mOutOfLine
PRPackedBool mHasE4XOption
PRPackedBool mAddedGCRoot
nsXULDocumentmSrcLoadWaiters
JSObjectmJSObject
const char * mLangVersion
Type mType
PRInt32 mRefCnt

Static Protected Member Functions

static nsIXULPrototypeCacheGetXULCache ()

Static Protected Attributes

static nsIXULPrototypeCachesXULPrototypeCache = nsnull

Detailed Description

Definition at line 311 of file nsXULElement.h.


Member Enumeration Documentation

enum nsXULPrototypeNode::Type [inherited]
Enumerator:
eType_Element 
eType_Script 
eType_Text 

Definition at line 195 of file nsXULElement.h.


Constructor & Destructor Documentation

nsXULPrototypeScript::nsXULPrototypeScript ( PRUint32  aLineNo,
const char *  aVersion,
PRBool  aHasE4XOption,
nsresult rv 
)

Definition at line 3310 of file nsXULElement.cpp.

    : nsXULPrototypeNode(eType_Script),
      mLineNo(aLineNo),
      mSrcLoading(PR_FALSE),
      mOutOfLine(PR_TRUE),
      mHasE4XOption(aHasE4XOption),
      mSrcLoadWaiters(nsnull),
      mJSObject(nsnull),
      mLangVersion(aVersion)
{
    NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
    *rv = nsContentUtils::AddJSGCRoot(&mJSObject,
                                      "nsXULPrototypeScript::mJSObject");
    mAddedGCRoot = NS_SUCCEEDED(*rv);
}

Here is the call graph for this function:

Definition at line 3330 of file nsXULElement.cpp.

Here is the call graph for this function:


Member Function Documentation

void nsXULPrototypeNode::AddRef ( void  ) [inline, inherited]

Definition at line 215 of file nsXULElement.h.

                  {
        ++mRefCnt;
        NS_LOG_ADDREF(this, mRefCnt, ClassName(), ClassSize());
    }

Here is the caller graph for this function:

nsresult nsXULPrototypeScript::Compile ( const PRUnichar aText,
PRInt32  aTextLength,
nsIURI aURI,
PRUint32  aLineNo,
nsIDocument aDocument,
nsIXULPrototypeDocument aPrototypeDocument 
)

Definition at line 3657 of file nsXULElement.cpp.

{
    // We'll compile the script using the prototype document's special
    // script object as the parent. This ensures that we won't end up
    // with an uncollectable reference.
    //
    // Compiling it using (for example) the first document's global
    // object would cause JS to keep a reference via the __proto__ or
    // __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!
    nsresult rv;

    // Use the prototype document's special context
    nsIScriptContext *context;

    {
        nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner =
            do_QueryInterface(aPrototypeDocument);
        nsIScriptGlobalObject* global = globalOwner->GetScriptGlobalObject();
        NS_ASSERTION(global != nsnull, "prototype doc has no script global");
        if (! global)
            return NS_ERROR_UNEXPECTED;

        context = global->GetContext();

        NS_ASSERTION(context != nsnull, "no context for script global");
        if (! context)
            return NS_ERROR_UNEXPECTED;
    }

    // Use the enclosing document's principal
    // XXX is this right? or should we use the protodoc's?
    // If we start using the protodoc's, make sure
    // the DowngradePrincipalIfNeeded stuff in
    // nsXULDocument::OnStreamComplete still works!
    nsIPrincipal *principal = aDocument->GetPrincipal();
    if (!principal)
        return NS_ERROR_FAILURE;

    nsCAutoString urlspec;
    aURI->GetSpec(urlspec);

    // Ok, compile it to create a prototype script object!

    // XXXbe violate nsIScriptContext layering because its version parameter
    // is mis-typed as const char * -- if it were uint32, we could more easily
    // extend version to include compile-time option, as the JS engine does.
    // It'd also be more efficient than converting to and from a C string.

    JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
                                        context->GetNativeContext());
    uint32 options = ::JS_GetOptions(cx);
    JSBool changed = (mHasE4XOption ^ !!(options & JSOPTION_XML));
    if (changed) {
        ::JS_SetOptions(cx,
                        mHasE4XOption
                        ? options | JSOPTION_XML
                        : options & ~JSOPTION_XML);
    }

    rv = context->CompileScript(aText,
                                aTextLength,
                                nsnull,
                                principal,
                                urlspec.get(),
                                aLineNo,
                                mLangVersion,
                                (void**)&mJSObject);

    if (changed) {
        ::JS_SetOptions(cx, options);
    }
    return rv;
}

Here is the call graph for this function:

nsresult nsXULPrototypeScript::Deserialize ( nsIObjectInputStream aStream,
nsIScriptContext aContext,
nsIURI aDocumentURI,
const nsCOMArray< nsINodeInfo > *  aNodeInfos 
) [virtual]

Implements nsXULPrototypeNode.

Definition at line 3468 of file nsXULElement.cpp.

{
    NS_TIMELINE_MARK_FUNCTION("chrome js deserialize");
    nsresult rv;

    // Read basic prototype data
    aStream->Read32(&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;

    char* data;
    rv = aStream->ReadBytes(size, &data);
    if (NS_SUCCEEDED(rv)) {
        JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
                                            aContext->GetNativeContext());

        JSXDRState *xdr = ::JS_XDRNewMem(cx, JSXDR_DECODE);
        if (! xdr) {
            rv = NS_ERROR_OUT_OF_MEMORY;
        } else {
            xdr->userdata = (void*) aStream;
            ::JS_XDRMemSetData(xdr, data, size);

            JSScript *script = nsnull;
            if (! ::JS_XDRScript(xdr, &script)) {
                rv = NS_ERROR_FAILURE;  // principals deserialization error?
            } else {
                mJSObject = ::JS_NewScriptObject(cx, script);
                if (! mJSObject) {
                    rv = NS_ERROR_OUT_OF_MEMORY;    // certain error
                    ::JS_DestroyScript(cx, script);
                }
            }

            // Update data in case ::JS_XDRScript called back into C++ code to
            // read an XPCOM object.
            //
            // In that case, the serialization process must have flushed a run
            // of counted bytes containing JS data at the point where the XPCOM
            // object starts, after which an encoding C++ callback from the JS
            // XDR code must have written the XPCOM object directly into the
            // nsIObjectOutputStream.
            //
            // The deserialization process will XDR-decode counted bytes up to
            // but not including the XPCOM object, then call back into C++ to
            // read the object, then read more counted bytes and hand them off
            // to the JSXDRState, so more JS data can be decoded.
            //
            // This interleaving of JS XDR data and XPCOM object data may occur
            // several times beneath the call to ::JS_XDRScript, above.  At the
            // end of the day, we need to free (via nsMemory) the data owned by
            // the JSXDRState.  So we steal it back, nulling xdr's buffer so it
            // doesn't get passed to ::JS_free by ::JS_XDRDestroy.

            uint32 junk;
            data = (char*) ::JS_XDRMemGetData(xdr, &junk);
            if (data)
                ::JS_XDRMemSetData(xdr, NULL, 0);
            ::JS_XDRDestroy(xdr);
        }

        // If data is null now, it must have been freed while deserializing an
        // XPCOM object (e.g., a principal) beneath ::JS_XDRScript.
        if (data)
            nsMemory::Free(data);
    }
    if (NS_FAILED(rv)) return rv;

    PRUint32 version;
    rv = aStream->Read32(&version);
    if (NS_FAILED(rv)) return rv;

    mLangVersion = ::JS_VersionToString(JSVersion(version));
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3554 of file nsXULElement.cpp.

{
    // Keep track of FastLoad failure via rv, so we can
    // AbortFastLoads if things look bad.
    nsresult rv = NS_OK;

    nsIXULPrototypeCache* cache = GetXULCache();
    nsCOMPtr<nsIFastLoadService> fastLoadService;
    cache->GetFastLoadService(getter_AddRefs(fastLoadService));

    // Allow callers to pass null for aInput, meaning
    // "use the FastLoad service's default input stream."
    // See nsXULContentSink.cpp for one use of this.
    nsCOMPtr<nsIObjectInputStream> objectInput = aInput;
    if (! objectInput && fastLoadService)
        fastLoadService->GetInputStream(getter_AddRefs(objectInput));

    if (objectInput) {
        PRBool useXULCache = PR_TRUE;
        if (mSrcURI) {
            // NB: we must check the XUL script cache early, to avoid
            // multiple deserialization attempts for a given script, which
            // would exhaust the multiplexed stream containing the singly
            // serialized script.  Note that nsXULDocument::LoadScript
            // checks the XUL script cache too, in order to handle the
            // serialization case.
            //
            // We need do this only for <script src='strres.js'> and the
            // like, i.e., out-of-line scripts that are included by several
            // different XUL documents multiplexed in the FastLoad file.
            cache->GetEnabled(&useXULCache);

            if (useXULCache) {
                cache->GetScript(mSrcURI, NS_REINTERPRET_CAST(void**, &mJSObject));
            }
        }

        if (! mJSObject) {
            nsCOMPtr<nsIURI> oldURI;

            if (mSrcURI) {
                nsCAutoString spec;
                mSrcURI->GetAsciiSpec(spec);
                rv = fastLoadService->StartMuxedDocument(mSrcURI, spec.get(),
                                                         nsIFastLoadService::NS_FASTLOAD_READ);
                if (NS_SUCCEEDED(rv))
                    rv = fastLoadService->SelectMuxedDocument(mSrcURI, getter_AddRefs(oldURI));
            } else {
                // An inline script: check FastLoad multiplexing direction
                // and skip Deserialize if we're not reading from a
                // muxed stream to get inline objects that are contained in
                // the current document.
                PRInt32 direction;
                fastLoadService->GetDirection(&direction);
                if (direction != nsIFastLoadService::NS_FASTLOAD_READ)
                    rv = NS_ERROR_NOT_AVAILABLE;
            }

            // We do reflect errors into rv, but our caller may want to
            // ignore our return value, because mJSObject will be null
            // after any error, and that suffices to cause the script to
            // be reloaded (from the src= URI, if any) and recompiled.
            // We're better off slow-loading than bailing out due to a
            // FastLoad error.
            if (NS_SUCCEEDED(rv))
                rv = Deserialize(objectInput, aContext, nsnull, nsnull);

            if (NS_SUCCEEDED(rv) && mSrcURI) {
                rv = fastLoadService->EndMuxedDocument(mSrcURI);

                if (NS_SUCCEEDED(rv) && oldURI) {
                    nsCOMPtr<nsIURI> tempURI;
                    rv = fastLoadService->SelectMuxedDocument(oldURI, getter_AddRefs(tempURI));

                    NS_ASSERTION(NS_SUCCEEDED(rv) && (!tempURI || tempURI == mSrcURI),
                                 "not currently deserializing into the script we thought we were!");
                }
            }

            if (NS_SUCCEEDED(rv)) {
                if (useXULCache && mSrcURI) {
                    PRBool isChrome = PR_FALSE;
                    mSrcURI->SchemeIs("chrome", &isChrome);
                    if (isChrome) {
                        cache->PutScript(mSrcURI, NS_REINTERPRET_CAST(void*, mJSObject));
                    }
                }
            } else {
                // If mSrcURI is not in the FastLoad multiplex,
                // rv will be NS_ERROR_NOT_AVAILABLE and we'll try to
                // update the FastLoad file to hold a serialization of
                // this script, once it has finished loading.
                if (rv != NS_ERROR_NOT_AVAILABLE)
                    cache->AbortFastLoads();
            }
        }
    }

    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static nsIXULPrototypeCache* nsXULPrototypeScript::GetXULCache ( ) [inline, static, protected]

Definition at line 358 of file nsXULElement.h.

    {
        if (!sXULPrototypeCache)
            CallGetService("@mozilla.org/xul/xul-prototype-cache;1", &sXULPrototypeCache);

        return sXULPrototypeCache;
    }

Here is the call graph for this function:

Here is the caller graph for this function:

void nsXULPrototypeNode::Release ( void  ) [inline, inherited]

Definition at line 219 of file nsXULElement.h.

    {
        --mRefCnt;
        NS_LOG_RELEASE(this, mRefCnt, ClassName());
        if (mRefCnt == 0)
            delete this;
    }

Here is the caller graph for this function:

static void nsXULPrototypeScript::ReleaseGlobals ( ) [inline, static]

Definition at line 352 of file nsXULElement.h.

Here is the caller graph for this function:

virtual void nsXULPrototypeNode::ReleaseSubtree ( ) [inline, virtual, inherited]

Reimplemented in nsXULPrototypeElement.

Definition at line 226 of file nsXULElement.h.

{ Release(); }

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsXULPrototypeScript::Serialize ( nsIObjectOutputStream aStream,
nsIScriptContext aContext,
const nsCOMArray< nsINodeInfo > *  aNodeInfos 
) [virtual]

Implements nsXULPrototypeNode.

Definition at line 3339 of file nsXULElement.cpp.

{
    NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull || !mJSObject,
                 "script source still loading when serializing?!");
    if (!mJSObject)
        return NS_ERROR_FAILURE;

    nsresult rv;

    // Write basic prototype data
    aStream->Write32(mLineNo);

    JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
                                        aContext->GetNativeContext());
    JSXDRState *xdr = ::JS_XDRNewMem(cx, JSXDR_ENCODE);
    if (! xdr)
        return NS_ERROR_OUT_OF_MEMORY;
    xdr->userdata = (void*) aStream;

    JSScript *script = NS_REINTERPRET_CAST(JSScript*,
                                           ::JS_GetPrivate(cx, mJSObject));
    if (! ::JS_XDRScript(xdr, &script)) {
        rv = NS_ERROR_FAILURE;  // likely to be a principals serialization error
    } else {
        // Get the encoded JSXDRState data and write it.  The JSXDRState owns
        // this buffer memory and will free it beneath ::JS_XDRDestroy.
        //
        // If an XPCOM object needs to be written in the midst of the JS XDR
        // encoding process, the C++ code called back from the JS engine (e.g.,
        // nsEncodeJSPrincipals in caps/src/nsJSPrincipals.cpp) will flush data
        // from the JSXDRState to aStream, then write the object, then return
        // to JS XDR code with xdr reset so new JS data is encoded at the front
        // of the xdr's data buffer.
        //
        // However many XPCOM objects are interleaved with JS XDR data in the
        // stream, when control returns here from ::JS_XDRScript, we'll have
        // one last buffer of data to write to aStream.

        uint32 size;
        const char* data = NS_REINTERPRET_CAST(const char*,
                                               ::JS_XDRMemGetData(xdr, &size));
        NS_ASSERTION(data, "no decoded JSXDRState data!");

        rv = aStream->Write32(size);
        if (NS_SUCCEEDED(rv))
            rv = aStream->WriteBytes(data, size);
    }

    ::JS_XDRDestroy(xdr);
    if (NS_FAILED(rv)) return rv;

    PRUint32 version = PRUint32(mLangVersion
                                ? ::JS_StringToVersion(mLangVersion)
                                : JSVERSION_DEFAULT);
    rv = aStream->Write32(version);
    if (NS_FAILED(rv)) return rv;

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3402 of file nsXULElement.cpp.

{
    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<nsIFastLoadService> fastLoadService;
    cache->GetFastLoadService(getter_AddRefs(fastLoadService));

    nsresult rv = NS_OK;
    if (!fastLoadService)
        return NS_ERROR_NOT_AVAILABLE;

    nsCAutoString urispec;
    rv = mSrcURI->GetAsciiSpec(urispec);
    if (NS_FAILED(rv))
        return rv;

    PRBool exists = PR_FALSE;
    fastLoadService->HasMuxedDocument(urispec.get(), &exists);
    /* return will be NS_OK from GetAsciiSpec.
     * that makes no sense.
     * nor does returning NS_OK from HasMuxedDocument.
     * XXX return something meaningful.
     */
    if (exists)
        return NS_OK;

    // 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<nsIObjectOutputStream> objectOutput = aStream;
    if (! objectOutput) {
        fastLoadService->GetOutputStream(getter_AddRefs(objectOutput));
        if (! objectOutput)
            return NS_ERROR_NOT_AVAILABLE;
    }

    rv = fastLoadService->
         StartMuxedDocument(mSrcURI, urispec.get(),
                            nsIFastLoadService::NS_FASTLOAD_WRITE);
    NS_ASSERTION(rv != NS_ERROR_NOT_AVAILABLE, "reading FastLoad?!");

    nsCOMPtr<nsIURI> oldURI;
    rv |= fastLoadService->SelectMuxedDocument(mSrcURI, getter_AddRefs(oldURI));
    rv |= Serialize(objectOutput, aContext, nsnull);
    rv |= fastLoadService->EndMuxedDocument(mSrcURI);

    if (oldURI) {
        nsCOMPtr<nsIURI> tempURI;
        rv |= fastLoadService->
              SelectMuxedDocument(oldURI, getter_AddRefs(tempURI));
    }

    if (NS_FAILED(rv))
        cache->AbortFastLoads();
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 347 of file nsXULElement.h.

Definition at line 346 of file nsXULElement.h.

Definition at line 349 of file nsXULElement.h.

Definition at line 350 of file nsXULElement.h.

Definition at line 343 of file nsXULElement.h.

Definition at line 345 of file nsXULElement.h.

Definition at line 199 of file nsXULElement.h.

Definition at line 344 of file nsXULElement.h.

Definition at line 348 of file nsXULElement.h.

Definition at line 342 of file nsXULElement.h.

Definition at line 197 of file nsXULElement.h.

Definition at line 365 of file nsXULElement.h.


The documentation for this class was generated from the following files: