зеркало из https://github.com/mozilla/pjs.git
Bug 94199, part 4, serialize/deserialize xbl to startup cache, r=bz
This commit is contained in:
Родитель
16336f7b86
Коммит
16faece69e
|
@ -1878,6 +1878,15 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
|
|||
bool aLoadedAsData,
|
||||
nsIScriptGlobalObject* aEventObject,
|
||||
bool aSVGDocument);
|
||||
|
||||
// This is used only for xbl documents created from the startup cache.
|
||||
// Non-cached documents are created in the same manner as xml documents.
|
||||
nsresult
|
||||
NS_NewXBLDocument(nsIDOMDocument** aInstancePtrResult,
|
||||
nsIURI* aDocumentURI,
|
||||
nsIURI* aBaseURI,
|
||||
nsIPrincipal* aPrincipal);
|
||||
|
||||
nsresult
|
||||
NS_NewPluginDocument(nsIDocument** aInstancePtrResult);
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@ class nsString;
|
|||
#define kNameSpaceID_Unknown -1
|
||||
// 0 is special at C++, so use a static const PRInt32 for
|
||||
// kNameSpaceID_None to keep if from being cast to pointers
|
||||
// Note that the XBL cache assumes (and asserts) that it can treat a
|
||||
// single-byte value higher than kNameSpaceID_LastBuiltin specially.
|
||||
static const PRInt32 kNameSpaceID_None = 0;
|
||||
#define kNameSpaceID_XMLNS 1 // not really a namespace, but it needs to play the game
|
||||
#define kNameSpaceID_XML 2
|
||||
|
@ -60,7 +62,7 @@ static const PRInt32 kNameSpaceID_None = 0;
|
|||
#define kNameSpaceID_SVG 10
|
||||
#define kNameSpaceID_XMLEvents 11
|
||||
#define kNameSpaceID_LastBuiltin 11 // last 'built-in' namespace
|
||||
|
||||
|
||||
#define NS_NAMESPACEMANAGER_CONTRACTID "@mozilla.org/content/namespacemanager;1"
|
||||
|
||||
#define NS_INAMESPACEMANAGER_IID \
|
||||
|
|
|
@ -893,6 +893,10 @@ public:
|
|||
}
|
||||
|
||||
void SetLoadedAsData(bool aLoadedAsData) { mLoadedAsData = aLoadedAsData; }
|
||||
void SetLoadedAsInteractiveData(bool aLoadedAsInteractiveData)
|
||||
{
|
||||
mLoadedAsInteractiveData = aLoadedAsInteractiveData;
|
||||
}
|
||||
|
||||
nsresult CloneDocHelper(nsDocument* clone) const;
|
||||
|
||||
|
|
|
@ -566,7 +566,9 @@ nsXBLContentSink::ConstructBinding(PRUint32 aLineNumber)
|
|||
NS_ConvertUTF16toUTF8 cid(id);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
||||
// Don't create a binding with no id. nsXBLPrototypeBinding::Read also
|
||||
// performs this check.
|
||||
if (!cid.IsEmpty()) {
|
||||
mBinding = new nsXBLPrototypeBinding();
|
||||
if (!mBinding)
|
||||
|
@ -894,6 +896,8 @@ nsXBLContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
|
|||
#ifdef MOZ_XUL
|
||||
}
|
||||
|
||||
// Note that this needs to match the code in nsXBLPrototypeBinding::ReadContentNode.
|
||||
|
||||
*aAppendContent = true;
|
||||
nsRefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement();
|
||||
if (!prototype)
|
||||
|
|
|
@ -56,7 +56,13 @@
|
|||
#include "nsDOMJSUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "xpcpublic.h"
|
||||
|
||||
#include "mozilla/scache/StartupCache.h"
|
||||
#include "mozilla/scache/StartupCacheUtils.h"
|
||||
|
||||
using namespace mozilla::scache;
|
||||
|
||||
static const char kXBLCachePrefix[] = "xblcache";
|
||||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
// An XBLDocumentInfo object has a special context associated with it which we can use to pre-compile
|
||||
|
@ -561,6 +567,138 @@ nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBin
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLDocumentInfo::RemovePrototypeBinding(const nsACString& aRef)
|
||||
{
|
||||
if (mBindingTable) {
|
||||
// Use a flat string to avoid making a copy.
|
||||
const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
|
||||
nsCStringKey key(flat);
|
||||
mBindingTable->Remove(&key);
|
||||
}
|
||||
}
|
||||
|
||||
// Callback to enumerate over the bindings from this document and write them
|
||||
// out to the cache.
|
||||
bool
|
||||
WriteBinding(nsHashKey *aKey, void *aData, void* aClosure)
|
||||
{
|
||||
nsXBLPrototypeBinding* binding = static_cast<nsXBLPrototypeBinding *>(aData);
|
||||
binding->Write((nsIObjectOutputStream*)aClosure);
|
||||
|
||||
return kHashEnumerateNext;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsXBLDocumentInfo::ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo)
|
||||
{
|
||||
*aDocInfo = nsnull;
|
||||
|
||||
nsCAutoString spec(kXBLCachePrefix);
|
||||
nsresult rv = PathifyURI(aURI, spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
StartupCache* startupCache = StartupCache::GetSingleton();
|
||||
NS_ENSURE_TRUE(startupCache, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoArrayPtr<char> buf;
|
||||
PRUint32 len;
|
||||
rv = startupCache->GetBuffer(spec.get(), getter_Transfers(buf), &len);
|
||||
// GetBuffer will fail if the binding is not in the cache.
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIObjectInputStream> stream;
|
||||
rv = NewObjectInputStreamFromBuffer(buf, len, getter_AddRefs(stream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
buf.forget();
|
||||
|
||||
// The file compatibility.ini stores the build id. This is checked in
|
||||
// nsAppRunner.cpp and will delete the cache if a different build is
|
||||
// present. However, we check that the version matches here to be safe.
|
||||
PRUint32 version;
|
||||
rv = stream->Read32(&version);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (version != XBLBinding_Serialize_Version) {
|
||||
// The version that exists is different than expected, likely created with a
|
||||
// different build, so invalidate the cache.
|
||||
startupCache->InvalidateCache();
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsContentUtils::GetSecurityManager()->
|
||||
GetSystemPrincipal(getter_AddRefs(principal));
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domdoc;
|
||||
rv = NS_NewXBLDocument(getter_AddRefs(domdoc), aURI, nsnull, principal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
|
||||
nsRefPtr<nsXBLDocumentInfo> docInfo = NS_NewXBLDocumentInfo(doc);
|
||||
|
||||
while (1) {
|
||||
PRUint8 flags;
|
||||
nsresult rv = stream->Read8(&flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (flags == XBLBinding_Serialize_NoMoreBindings)
|
||||
break;
|
||||
|
||||
nsXBLPrototypeBinding* binding = new nsXBLPrototypeBinding();
|
||||
rv = binding->Read(stream, docInfo, doc, flags);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete binding;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
docInfo.swap(*aDocInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLDocumentInfo::WritePrototypeBindings()
|
||||
{
|
||||
// Only write out bindings with the system principal
|
||||
if (!nsContentUtils::IsSystemPrincipal(mDocument->NodePrincipal()))
|
||||
return NS_OK;
|
||||
|
||||
nsCAutoString spec(kXBLCachePrefix);
|
||||
nsresult rv = PathifyURI(DocumentURI(), spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
StartupCache* startupCache = StartupCache::GetSingleton();
|
||||
NS_ENSURE_TRUE(startupCache, rv);
|
||||
|
||||
nsCOMPtr<nsIObjectOutputStream> stream;
|
||||
nsCOMPtr<nsIStorageStream> storageStream;
|
||||
rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(stream),
|
||||
getter_AddRefs(storageStream),
|
||||
true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = stream->Write32(XBLBinding_Serialize_Version);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mBindingTable)
|
||||
mBindingTable->Enumerate(WriteBinding, stream);
|
||||
|
||||
// write a end marker at the end
|
||||
rv = stream->Write8(XBLBinding_Serialize_NoMoreBindings);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
stream->Close();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 len;
|
||||
nsAutoArrayPtr<char> buf;
|
||||
rv = NewBufferFromStorageStream(storageStream, getter_Transfers(buf), &len);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return startupCache->PutBuffer(spec.get(), buf, len);
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLDocumentInfo::SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding)
|
||||
{
|
||||
|
|
|
@ -68,6 +68,11 @@ public:
|
|||
nsresult SetPrototypeBinding(const nsACString& aRef,
|
||||
nsXBLPrototypeBinding* aBinding);
|
||||
|
||||
// This removes the binding without deleting it
|
||||
void RemovePrototypeBinding(const nsACString& aRef);
|
||||
|
||||
nsresult WritePrototypeBindings();
|
||||
|
||||
void SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding);
|
||||
|
||||
void FlushSkinStylesheets();
|
||||
|
@ -77,6 +82,8 @@ public:
|
|||
// nsIScriptGlobalObjectOwner methods
|
||||
virtual nsIScriptGlobalObject* GetScriptGlobalObject();
|
||||
|
||||
static nsresult ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsXBLDocumentInfo,
|
||||
nsIScriptGlobalObjectOwner)
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsXBLProtoImplProperty.h"
|
||||
|
||||
// Checks that the version is not modified in a given scope.
|
||||
class AutoVersionChecker
|
||||
|
@ -299,6 +300,159 @@ nsXBLProtoImpl::DestroyMembers()
|
|||
mDestructor = nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLProtoImpl::Read(nsIScriptContext* aContext,
|
||||
nsIObjectInputStream* aStream,
|
||||
nsXBLPrototypeBinding* aBinding,
|
||||
nsIScriptGlobalObject* aGlobal)
|
||||
{
|
||||
// Set up a class object first so that deserialization is possible
|
||||
JSContext *cx = static_cast<JSContext *>(aContext->GetNativeContext());
|
||||
JSObject *global = aGlobal->GetGlobalJSObject();
|
||||
|
||||
void* classObject;
|
||||
nsresult rv = aBinding->InitClass(mClassName, cx, global, global, &classObject);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(classObject, NS_ERROR_FAILURE);
|
||||
|
||||
mClassObject = (JSObject*) classObject;
|
||||
|
||||
nsXBLProtoImplField* previousField = nsnull;
|
||||
nsXBLProtoImplMember* previousMember = nsnull;
|
||||
|
||||
do {
|
||||
XBLBindingSerializeDetails type;
|
||||
rv = aStream->Read8(&type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (type == XBLBinding_Serialize_NoMoreItems)
|
||||
break;
|
||||
|
||||
switch (type & XBLBinding_Serialize_Mask) {
|
||||
case XBLBinding_Serialize_Field:
|
||||
{
|
||||
nsXBLProtoImplField* field =
|
||||
new nsXBLProtoImplField(type & XBLBinding_Serialize_ReadOnly);
|
||||
rv = field->Read(aContext, aStream);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete field;
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (previousField) {
|
||||
previousField->SetNext(field);
|
||||
}
|
||||
else {
|
||||
mFields = field;
|
||||
}
|
||||
previousField = field;
|
||||
|
||||
break;
|
||||
}
|
||||
case XBLBinding_Serialize_GetterProperty:
|
||||
case XBLBinding_Serialize_SetterProperty:
|
||||
case XBLBinding_Serialize_GetterSetterProperty:
|
||||
{
|
||||
nsAutoString name;
|
||||
nsresult rv = aStream->ReadString(name);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXBLProtoImplProperty* prop =
|
||||
new nsXBLProtoImplProperty(name.get(), type & XBLBinding_Serialize_ReadOnly);
|
||||
rv = prop->Read(aContext, aStream, type & XBLBinding_Serialize_Mask);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete prop;
|
||||
return rv;
|
||||
}
|
||||
|
||||
previousMember = AddMember(prop, previousMember);
|
||||
break;
|
||||
}
|
||||
case XBLBinding_Serialize_Method:
|
||||
{
|
||||
nsAutoString name;
|
||||
rv = aStream->ReadString(name);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXBLProtoImplMethod* method = new nsXBLProtoImplMethod(name.get());
|
||||
rv = method->Read(aContext, aStream);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete method;
|
||||
return rv;
|
||||
}
|
||||
|
||||
previousMember = AddMember(method, previousMember);
|
||||
break;
|
||||
}
|
||||
case XBLBinding_Serialize_Constructor:
|
||||
{
|
||||
mConstructor = new nsXBLProtoImplAnonymousMethod();
|
||||
rv = mConstructor->Read(aContext, aStream);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete mConstructor;
|
||||
mConstructor = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
previousMember = AddMember(mConstructor, previousMember);
|
||||
break;
|
||||
}
|
||||
case XBLBinding_Serialize_Destructor:
|
||||
{
|
||||
mDestructor = new nsXBLProtoImplAnonymousMethod();
|
||||
rv = mDestructor->Read(aContext, aStream);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete mDestructor;
|
||||
mDestructor = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
previousMember = AddMember(mDestructor, previousMember);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_ERROR("Unexpected binding member type");
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLProtoImpl::Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream,
|
||||
nsXBLPrototypeBinding* aBinding)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!mClassObject) {
|
||||
rv = CompilePrototypeMembers(aBinding);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = aStream->WriteStringZ(mClassName.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (nsXBLProtoImplField* curr = mFields; curr; curr = curr->GetNext()) {
|
||||
rv = curr->Write(aContext, aStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
for (nsXBLProtoImplMember* curr = mMembers; curr; curr = curr->GetNext()) {
|
||||
if (curr == mConstructor) {
|
||||
rv = mConstructor->Write(aContext, aStream, XBLBinding_Serialize_Constructor);
|
||||
}
|
||||
else if (curr == mDestructor) {
|
||||
rv = mDestructor->Write(aContext, aStream, XBLBinding_Serialize_Destructor);
|
||||
}
|
||||
else {
|
||||
rv = curr->Write(aContext, aStream);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return aStream->Write8(XBLBinding_Serialize_NoMoreItems);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewXBLProtoImpl(nsXBLPrototypeBinding* aBinding,
|
||||
const PRUnichar* aClassName,
|
||||
|
|
|
@ -105,7 +105,26 @@ public:
|
|||
return mClassObject != nsnull;
|
||||
}
|
||||
|
||||
nsresult Read(nsIScriptContext* aContext,
|
||||
nsIObjectInputStream* aStream,
|
||||
nsXBLPrototypeBinding* aBinding,
|
||||
nsIScriptGlobalObject* aGlobal);
|
||||
nsresult Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream,
|
||||
nsXBLPrototypeBinding* aBinding);
|
||||
|
||||
protected:
|
||||
// used by Read to add each member
|
||||
nsXBLProtoImplMember* AddMember(nsXBLProtoImplMember* aMember,
|
||||
nsXBLProtoImplMember* aPreviousMember)
|
||||
{
|
||||
if (aPreviousMember)
|
||||
aPreviousMember->SetNext(aMember);
|
||||
else
|
||||
mMembers = aMember;
|
||||
return aMember;
|
||||
}
|
||||
|
||||
void DestroyMembers();
|
||||
|
||||
public:
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#include "nsIScriptContext.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsXBLSerialize.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
|
||||
nsXBLProtoImplField::nsXBLProtoImplField(const PRUnichar* aName, const PRUnichar* aReadOnly)
|
||||
: mNext(nsnull),
|
||||
|
@ -66,6 +68,20 @@ nsXBLProtoImplField::nsXBLProtoImplField(const PRUnichar* aName, const PRUnichar
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
nsXBLProtoImplField::nsXBLProtoImplField(bool aIsReadOnly)
|
||||
: mNext(nsnull),
|
||||
mFieldText(nsnull),
|
||||
mFieldTextLength(0),
|
||||
mLineNumber(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXBLProtoImplField);
|
||||
|
||||
mJSAttributes = JSPROP_ENUMERATE;
|
||||
if (aIsReadOnly)
|
||||
mJSAttributes |= JSPROP_READONLY;
|
||||
}
|
||||
|
||||
nsXBLProtoImplField::~nsXBLProtoImplField()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsXBLProtoImplField);
|
||||
|
@ -152,3 +168,45 @@ nsXBLProtoImplField::InstallField(nsIScriptContext* aContext,
|
|||
*aDidInstall = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLProtoImplField::Read(nsIScriptContext* aContext,
|
||||
nsIObjectInputStream* aStream)
|
||||
{
|
||||
nsAutoString name;
|
||||
nsresult rv = aStream->ReadString(name);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mName = ToNewUnicode(name);
|
||||
|
||||
rv = aStream->Read32(&mLineNumber);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString fieldText;
|
||||
rv = aStream->ReadString(fieldText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mFieldTextLength = fieldText.Length();
|
||||
if (mFieldTextLength)
|
||||
mFieldText = ToNewUnicode(fieldText);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLProtoImplField::Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream)
|
||||
{
|
||||
XBLBindingSerializeDetails type = XBLBinding_Serialize_Field;
|
||||
|
||||
if (mJSAttributes & JSPROP_READONLY) {
|
||||
type |= XBLBinding_Serialize_ReadOnly;
|
||||
}
|
||||
|
||||
nsresult rv = aStream->Write8(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStream->WriteWStringZ(mName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStream->Write32(mLineNumber);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return aStream->WriteWStringZ(mFieldText ? mFieldText : EmptyString().get());
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ class nsXBLProtoImplField
|
|||
{
|
||||
public:
|
||||
nsXBLProtoImplField(const PRUnichar* aName, const PRUnichar* aReadOnly);
|
||||
nsXBLProtoImplField(const bool aIsReadOnly);
|
||||
~nsXBLProtoImplField();
|
||||
|
||||
void AppendFieldText(const nsAString& aText);
|
||||
|
@ -68,6 +69,9 @@ public:
|
|||
nsIURI* aBindingDocURI,
|
||||
bool* aDidInstall) const;
|
||||
|
||||
nsresult Read(nsIScriptContext* aContext, nsIObjectInputStream* aStream);
|
||||
nsresult Write(nsIScriptContext* aContext, nsIObjectOutputStream* aStream);
|
||||
|
||||
const PRUnichar* GetName() const { return mName; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -119,6 +119,12 @@ public:
|
|||
|
||||
virtual void Trace(TraceCallback aCallback, void *aClosure) const = 0;
|
||||
|
||||
virtual nsresult Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsXBLProtoImplMember* mNext; // The members of an implementation are chained.
|
||||
PRUnichar* mName; // The name of the field, method, or property.
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
|
||||
nsXBLProtoImplMethod::nsXBLProtoImplMethod(const PRUnichar* aName) :
|
||||
nsXBLProtoImplMember(aName),
|
||||
|
@ -267,6 +268,41 @@ nsXBLProtoImplMethod::Trace(TraceCallback aCallback, void *aClosure) const
|
|||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLProtoImplMethod::Read(nsIScriptContext* aContext,
|
||||
nsIObjectInputStream* aStream)
|
||||
{
|
||||
void* methodCode;
|
||||
PRUint32 lineNumber;
|
||||
nsresult rv = XBL_DeserializeFunction(aContext, aStream, this,
|
||||
&lineNumber, &methodCode);
|
||||
mJSMethodObject = (JSObject *)methodCode;
|
||||
if (NS_FAILED(rv)) {
|
||||
SetUncompiledMethod(nsnull);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
mIsCompiled = true;
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLProtoImplMethod::Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream)
|
||||
{
|
||||
nsresult rv = aStream->Write8(XBLBinding_Serialize_Method);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aStream->WriteWStringZ(mName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// XXXndeakin fix line number
|
||||
return XBL_SerializeFunction(aContext, aStream, mJSMethodObject, 0);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement)
|
||||
{
|
||||
|
@ -348,3 +384,20 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement)
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLProtoImplAnonymousMethod::Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream,
|
||||
XBLBindingSerializeDetails aType)
|
||||
{
|
||||
if (mJSMethodObject) {
|
||||
nsresult rv = aStream->Write8(aType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// XXXndeakin write out line number
|
||||
rv = XBL_SerializeFunction(aContext, aStream, mJSMethodObject, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXBLProtoImplMember.h"
|
||||
#include "nsXBLSerialize.h"
|
||||
|
||||
struct nsXBLParameter {
|
||||
nsXBLParameter* mNext;
|
||||
|
@ -130,6 +131,9 @@ public:
|
|||
|
||||
virtual void Trace(TraceCallback aCallback, void *aClosure) const;
|
||||
|
||||
nsresult Read(nsIScriptContext* aContext, nsIObjectInputStream* aStream);
|
||||
virtual nsresult Write(nsIScriptContext* aContext, nsIObjectOutputStream* aStream);
|
||||
|
||||
bool IsCompiled() const
|
||||
{
|
||||
return !(mUncompiledMethod & BIT_UNCOMPILED);
|
||||
|
@ -175,6 +179,10 @@ public:
|
|||
const nsCString& aClassStr) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream,
|
||||
XBLBindingSerializeDetails aType);
|
||||
};
|
||||
|
||||
#endif // nsXBLProtoImplMethod_h__
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsXBLSerialize.h"
|
||||
|
||||
nsXBLProtoImplProperty::nsXBLProtoImplProperty(const PRUnichar* aName,
|
||||
const PRUnichar* aGetter,
|
||||
|
@ -75,6 +77,22 @@ nsXBLProtoImplProperty::nsXBLProtoImplProperty(const PRUnichar* aName,
|
|||
AppendSetterText(nsDependentString(aSetter));
|
||||
}
|
||||
|
||||
nsXBLProtoImplProperty::nsXBLProtoImplProperty(const PRUnichar* aName,
|
||||
const bool aIsReadOnly)
|
||||
: nsXBLProtoImplMember(aName),
|
||||
mGetterText(nsnull),
|
||||
mSetterText(nsnull),
|
||||
mJSAttributes(JSPROP_ENUMERATE)
|
||||
#ifdef DEBUG
|
||||
, mIsCompiled(false)
|
||||
#endif
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXBLProtoImplProperty);
|
||||
|
||||
if (aIsReadOnly)
|
||||
mJSAttributes |= JSPROP_READONLY;
|
||||
}
|
||||
|
||||
nsXBLProtoImplProperty::~nsXBLProtoImplProperty()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsXBLProtoImplProperty);
|
||||
|
@ -336,3 +354,76 @@ nsXBLProtoImplProperty::Trace(TraceCallback aCallback, void *aClosure) const
|
|||
"mJSSetterObject", aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLProtoImplProperty::Read(nsIScriptContext* aContext,
|
||||
nsIObjectInputStream* aStream,
|
||||
XBLBindingSerializeDetails aType)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 lineNumber;
|
||||
void* scriptObject;
|
||||
|
||||
if (aType == XBLBinding_Serialize_GetterProperty ||
|
||||
aType == XBLBinding_Serialize_GetterSetterProperty) {
|
||||
rv = XBL_DeserializeFunction(aContext, aStream, this, &lineNumber, &scriptObject);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mJSGetterObject = (JSObject *)scriptObject;
|
||||
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
|
||||
}
|
||||
|
||||
if (aType == XBLBinding_Serialize_SetterProperty ||
|
||||
aType == XBLBinding_Serialize_GetterSetterProperty) {
|
||||
rv = XBL_DeserializeFunction(aContext, aStream, this, &lineNumber, &scriptObject);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mJSSetterObject = (JSObject *)scriptObject;
|
||||
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
mIsCompiled = true;
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLProtoImplProperty::Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream)
|
||||
{
|
||||
XBLBindingSerializeDetails type;
|
||||
|
||||
if (mJSAttributes & JSPROP_GETTER) {
|
||||
type = mJSAttributes & JSPROP_SETTER ?
|
||||
XBLBinding_Serialize_GetterSetterProperty :
|
||||
XBLBinding_Serialize_GetterProperty;
|
||||
}
|
||||
else {
|
||||
type = XBLBinding_Serialize_SetterProperty;
|
||||
}
|
||||
|
||||
if (mJSAttributes & JSPROP_READONLY) {
|
||||
type |= XBLBinding_Serialize_ReadOnly;
|
||||
}
|
||||
|
||||
nsresult rv = aStream->Write8(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStream->WriteWStringZ(mName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mJSAttributes & JSPROP_GETTER) {
|
||||
// XXXndeakin write out line number
|
||||
rv = XBL_SerializeFunction(aContext, aStream, mJSGetterObject, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (mJSAttributes & JSPROP_SETTER) {
|
||||
// XXXndeakin write out line number
|
||||
rv = XBL_SerializeFunction(aContext, aStream, mJSSetterObject, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "jsapi.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXBLSerialize.h"
|
||||
#include "nsXBLProtoImplMember.h"
|
||||
|
||||
class nsXBLProtoImplProperty: public nsXBLProtoImplMember
|
||||
|
@ -53,6 +54,8 @@ public:
|
|||
const PRUnichar* aGetter,
|
||||
const PRUnichar* aSetter,
|
||||
const PRUnichar* aReadOnly);
|
||||
|
||||
nsXBLProtoImplProperty(const PRUnichar* aName, bool aIsReadOnly);
|
||||
|
||||
virtual ~nsXBLProtoImplProperty();
|
||||
|
||||
|
@ -73,6 +76,12 @@ public:
|
|||
|
||||
virtual void Trace(TraceCallback aCallback, void *aClosure) const;
|
||||
|
||||
nsresult Read(nsIScriptContext* aContext,
|
||||
nsIObjectInputStream* aStream,
|
||||
XBLBindingSerializeDetails aType);
|
||||
virtual nsresult Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream);
|
||||
|
||||
protected:
|
||||
union {
|
||||
// The raw text for the getter (prior to compilation).
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -47,6 +47,7 @@
|
|||
#include "nsWeakReference.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsXBLDocumentInfo.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsXBLProtoImpl.h"
|
||||
|
@ -61,6 +62,34 @@ class nsXBLProtoImplField;
|
|||
class nsXBLBinding;
|
||||
class nsCSSStyleSheet;
|
||||
|
||||
// This structure represents an insertion point, and is used when writing out
|
||||
// insertion points. It contains comparison operators so that it can be stored
|
||||
// in an array sorted by index.
|
||||
struct InsertionItem {
|
||||
PRUint32 insertionIndex;
|
||||
nsIAtom* tag;
|
||||
nsIContent* defaultContent;
|
||||
|
||||
InsertionItem(PRUint32 aInsertionIndex, nsIAtom* aTag, nsIContent* aDefaultContent)
|
||||
: insertionIndex(aInsertionIndex), tag(aTag), defaultContent(aDefaultContent) { }
|
||||
|
||||
bool operator<(const InsertionItem& item) const
|
||||
{
|
||||
NS_ASSERTION(insertionIndex != item.insertionIndex || defaultContent == item.defaultContent,
|
||||
"default content is different for same index");
|
||||
return insertionIndex < item.insertionIndex;
|
||||
}
|
||||
|
||||
bool operator==(const InsertionItem& item) const
|
||||
{
|
||||
NS_ASSERTION(insertionIndex != item.insertionIndex || defaultContent == item.defaultContent,
|
||||
"default content is different for same index");
|
||||
return insertionIndex == item.insertionIndex;
|
||||
}
|
||||
};
|
||||
|
||||
typedef nsClassHashtable<nsISupportsHashKey, nsAutoTArray<InsertionItem, 1> > ArrayOfInsertionPointsByContent;
|
||||
|
||||
// *********************************************************************/
|
||||
// The XBLPrototypeBinding class
|
||||
|
||||
|
@ -191,6 +220,84 @@ public:
|
|||
return &mKeyHandlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read this binding from the stream aStream into the xbl document aDocument.
|
||||
* aDocInfo should be the xbl document info for the binding document.
|
||||
* aFlags can contain XBLBinding_Serialize_InheritStyle to indicate that
|
||||
* mInheritStyle flag should be set, and XBLBinding_Serialize_IsFirstBinding
|
||||
* to indicate the first binding in a document.
|
||||
*/
|
||||
nsresult Read(nsIObjectInputStream* aStream,
|
||||
nsXBLDocumentInfo* aDocInfo,
|
||||
nsIDocument* aDocument,
|
||||
PRUint8 aFlags);
|
||||
|
||||
/**
|
||||
* Write this binding to the stream.
|
||||
*/
|
||||
nsresult Write(nsIObjectOutputStream* aStream);
|
||||
|
||||
/**
|
||||
* Read a content node from aStream and return it in aChild.
|
||||
* aDocument and aNim are the document and node info manager for the document
|
||||
* the child will be inserted into.
|
||||
*/
|
||||
nsresult ReadContentNode(nsIObjectInputStream* aStream,
|
||||
nsIDocument* aDocument,
|
||||
nsNodeInfoManager* aNim,
|
||||
nsIContent** aChild);
|
||||
|
||||
/**
|
||||
* Write the content node aNode to aStream.
|
||||
* aInsertionPointsByContent is a hash of the insertion points in the binding,
|
||||
* keyed by where there are in the content hierarchy.
|
||||
*
|
||||
* This method is called recursively for each child descendant. For the topmost
|
||||
* call, aNode must be an element.
|
||||
*
|
||||
* Text, CDATA and comment nodes are serialized as:
|
||||
* the constant XBLBinding_Serialize_TextNode, XBLBinding_Serialize_CDATANode
|
||||
* or XBLBinding_Serialize_CommentNode
|
||||
* the text for the node
|
||||
* Elements are serialized in the following format:
|
||||
* node's namespace, written with WriteNamespace
|
||||
* node's namespace prefix
|
||||
* node's tag
|
||||
* 32-bit attribute count
|
||||
* table of attributes:
|
||||
* attribute's namespace, written with WriteNamespace
|
||||
* attribute's namespace prefix
|
||||
* attribute's tag
|
||||
* attribute's value
|
||||
* attribute forwarding table:
|
||||
* source namespace
|
||||
* source attribute
|
||||
* destination namespace
|
||||
* destination attribute
|
||||
* the constant XBLBinding_Serialize_NoMoreAttributes
|
||||
* insertion points within this node:
|
||||
* child index to insert within node
|
||||
* default content serialized in the same manner or XBLBinding_Serialize_NoContent
|
||||
* count of insertion points at that index
|
||||
* that number of string tags (those in the <children>'s includes attribute)
|
||||
* the constant XBLBinding_Serialize_NoMoreInsertionPoints
|
||||
* 32-bit count of the number of child nodes
|
||||
* each child node is serialized in the same manner in sequence
|
||||
* the constant XBLBinding_Serialize_NoContent
|
||||
*/
|
||||
nsresult WriteContentNode(nsIObjectOutputStream* aStream,
|
||||
nsIContent* aNode,
|
||||
ArrayOfInsertionPointsByContent& aInsertionPointsByContent);
|
||||
|
||||
/**
|
||||
* Read or write a namespace id from or to aStream. If the namespace matches
|
||||
* one of the built-in ones defined in nsINameSpaceManager.h, it will be written as
|
||||
* a single byte with that value. Otherwise, XBLBinding_Serialize_CustomNamespace is
|
||||
* written out, followed by a string written with writeWStringZ.
|
||||
*/
|
||||
nsresult ReadNamespace(nsIObjectInputStream* aStream, PRInt32& aNameSpaceID);
|
||||
nsresult WriteNamespace(nsIObjectOutputStream* aStream, PRInt32 aNameSpaceID);
|
||||
|
||||
public:
|
||||
nsXBLPrototypeBinding();
|
||||
~nsXBLPrototypeBinding();
|
||||
|
@ -228,7 +335,13 @@ public:
|
|||
nsIContent* aCopyRoot,
|
||||
nsIContent* aTemplChild);
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// Ensure that mAttributeTable has been created.
|
||||
void EnsureAttributeTable();
|
||||
// Ad an entry to the attribute table
|
||||
void AddToAttributeTable(PRInt32 aSourceNamespaceID, nsIAtom* aSourceTag,
|
||||
PRInt32 aDestNamespaceID, nsIAtom* aDestTag,
|
||||
nsIContent* aContent);
|
||||
void ConstructAttributeTable(nsIContent* aElement);
|
||||
void ConstructInsertionTable(nsIContent* aElement);
|
||||
void GetNestedChildren(nsIAtom* aTag, PRInt32 aNamespace,
|
||||
|
@ -236,30 +349,6 @@ protected:
|
|||
nsCOMArray<nsIContent> & aList);
|
||||
void CreateKeyHandlers();
|
||||
|
||||
protected:
|
||||
// Internal helper class for managing our IID table.
|
||||
class nsIIDKey : public nsHashKey {
|
||||
protected:
|
||||
nsIID mKey;
|
||||
|
||||
public:
|
||||
nsIIDKey(REFNSIID key) : mKey(key) {}
|
||||
~nsIIDKey(void) {}
|
||||
|
||||
PRUint32 HashCode(void) const {
|
||||
// Just use the 32-bit m0 field.
|
||||
return mKey.m0;
|
||||
}
|
||||
|
||||
bool Equals(const nsHashKey *aKey) const {
|
||||
return mKey.Equals( ((nsIIDKey*) aKey)->mKey);
|
||||
}
|
||||
|
||||
nsHashKey *Clone(void) const {
|
||||
return new nsIIDKey(mKey);
|
||||
}
|
||||
};
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mBindingURI;
|
||||
|
@ -298,4 +387,3 @@ protected:
|
|||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#include "nsReadableUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsXBLEventHandler.h"
|
||||
#include "nsXBLSerialize.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
|
@ -123,10 +124,7 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(const PRUnichar* aEvent,
|
|||
mNextHandler(nsnull),
|
||||
mPrototypeBinding(aBinding)
|
||||
{
|
||||
++gRefCnt;
|
||||
if (gRefCnt == 1)
|
||||
// Get the primary accelerator key.
|
||||
InitAccessKeys();
|
||||
Init();
|
||||
|
||||
ConstructPrototype(nsnull, aEvent, aPhase, aAction, aCommand, aKeyCode,
|
||||
aCharCode, aModifiers, aButton, aClickCount,
|
||||
|
@ -139,15 +137,21 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement)
|
|||
mNextHandler(nsnull),
|
||||
mPrototypeBinding(nsnull)
|
||||
{
|
||||
++gRefCnt;
|
||||
if (gRefCnt == 1)
|
||||
// Get the primary accelerator key.
|
||||
InitAccessKeys();
|
||||
Init();
|
||||
|
||||
// Make sure our prototype is initialized.
|
||||
ConstructPrototype(aHandlerElement);
|
||||
}
|
||||
|
||||
nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding)
|
||||
: mHandlerText(nsnull),
|
||||
mLineNumber(nsnull),
|
||||
mNextHandler(nsnull),
|
||||
mPrototypeBinding(aBinding)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
nsXBLPrototypeHandler::~nsXBLPrototypeHandler()
|
||||
{
|
||||
--gRefCnt;
|
||||
|
@ -1030,3 +1034,67 @@ nsXBLPrototypeHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent,
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLPrototypeHandler::Read(nsIScriptContext* aContext, nsIObjectInputStream* aStream)
|
||||
{
|
||||
nsresult rv = aStream->Read8(&mPhase);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStream->Read8(&mKeyMask);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStream->Read8(&mType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStream->Read8(&mMisc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 detail;
|
||||
rv = aStream->Read32(&detail);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mDetail = detail;
|
||||
|
||||
nsAutoString name;
|
||||
rv = aStream->ReadString(name);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mEventName = do_GetAtom(name);
|
||||
|
||||
rv = aStream->Read32(&mLineNumber);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString handlerText;
|
||||
rv = aStream->ReadString(handlerText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!handlerText.IsEmpty())
|
||||
mHandlerText = ToNewUnicode(handlerText);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLPrototypeHandler::Write(nsIScriptContext* aContext, nsIObjectOutputStream* aStream)
|
||||
{
|
||||
// Make sure we don't write out NS_HANDLER_TYPE_XUL types, as they are used
|
||||
// for <keyset> elements.
|
||||
if (mType & NS_HANDLER_TYPE_XUL)
|
||||
return NS_OK;
|
||||
|
||||
XBLBindingSerializeDetails type = XBLBinding_Serialize_Handler;
|
||||
|
||||
nsresult rv = aStream->Write8(type);
|
||||
rv = aStream->Write8(mPhase);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStream->Write8(mKeyMask);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStream->Write8(mType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStream->Write8(mMisc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStream->Write32(mDetail);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aStream->WriteWStringZ(nsDependentAtomString(mEventName).get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aStream->Write32(mLineNumber);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return aStream->WriteWStringZ(mHandlerText ? mHandlerText : EmptyString().get());
|
||||
}
|
||||
|
|
|
@ -88,6 +88,9 @@ public:
|
|||
// This constructor is used only by XUL key handlers (e.g., <key>)
|
||||
nsXBLPrototypeHandler(nsIContent* aKeyElement);
|
||||
|
||||
// This constructor is used for handlers loaded from the cache
|
||||
nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding);
|
||||
|
||||
~nsXBLPrototypeHandler();
|
||||
|
||||
// if aCharCode is not zero, it is used instead of the charCode of aKeyEvent.
|
||||
|
@ -157,10 +160,20 @@ public:
|
|||
return (mType & NS_HANDLER_ALLOW_UNTRUSTED) != 0;
|
||||
}
|
||||
|
||||
nsresult Read(nsIScriptContext* aContext, nsIObjectInputStream* aStream);
|
||||
nsresult Write(nsIScriptContext* aContext, nsIObjectOutputStream* aStream);
|
||||
|
||||
public:
|
||||
static PRUint32 gRefCnt;
|
||||
|
||||
protected:
|
||||
void Init() {
|
||||
++gRefCnt;
|
||||
if (gRefCnt == 1)
|
||||
// Get the primary accelerator key.
|
||||
InitAccessKeys();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIController> GetController(nsIDOMEventTarget* aTarget);
|
||||
|
||||
inline PRInt32 GetMatchingKeyCode(const nsAString& aKeyName);
|
||||
|
|
|
@ -139,3 +139,11 @@ nsXBLPrototypeResources::FlushSkinSheets()
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLPrototypeResources::Write(nsIObjectOutputStream* aStream)
|
||||
{
|
||||
if (mLoader)
|
||||
return mLoader->Write(aStream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@ public:
|
|||
void AddResourceListener(nsIContent* aElement);
|
||||
nsresult FlushSkinSheets();
|
||||
|
||||
nsresult Write(nsIObjectOutputStream* aStream);
|
||||
|
||||
nsXBLPrototypeResources(nsXBLPrototypeBinding* aBinding);
|
||||
~nsXBLPrototypeResources();
|
||||
|
||||
|
|
|
@ -290,3 +290,25 @@ nsXBLResourceLoader::NotifyBoundElements()
|
|||
// Delete ourselves.
|
||||
NS_RELEASE(mResources->mLoader);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLResourceLoader::Write(nsIObjectOutputStream* aStream)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
for (nsXBLResource* curr = mResourceList; curr; curr = curr->mNext) {
|
||||
if (curr->mType == nsGkAtoms::image)
|
||||
rv = aStream->Write8(XBLBinding_Serialize_Image);
|
||||
else if (curr->mType == nsGkAtoms::stylesheet)
|
||||
rv = aStream->Write8(XBLBinding_Serialize_Stylesheet);
|
||||
else
|
||||
continue;
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aStream->WriteWStringZ(curr->mSrc.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -91,6 +91,8 @@ public:
|
|||
|
||||
void NotifyBoundElements();
|
||||
|
||||
nsresult Write(nsIObjectOutputStream* aStream);
|
||||
|
||||
// MEMBER VARIABLES
|
||||
nsXBLPrototypeBinding* mBinding; // A pointer back to our binding.
|
||||
nsXBLPrototypeResources* mResources; // A pointer back to our resources
|
||||
|
|
|
@ -43,9 +43,11 @@
|
|||
nsresult
|
||||
XBL_SerializeFunction(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream,
|
||||
JSObject* aFunctionObject)
|
||||
JSObject* aFunctionObject,
|
||||
PRUint32 aLineNumber)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsresult rv = aStream->Write32(aLineNumber);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSContext* cx = (JSContext*) aContext->GetNativeContext();
|
||||
JSXDRState *xdr = ::JS_XDRNewMem(cx, JSXDR_ENCODE);
|
||||
|
|
|
@ -43,11 +43,73 @@
|
|||
#include "nsIScriptContext.h"
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
||||
typedef PRUint8 XBLBindingSerializeDetails;
|
||||
|
||||
// A version number to ensure we don't load cached data in a different
|
||||
// file format.
|
||||
#define XBLBinding_Serialize_Version 0x00000001
|
||||
|
||||
// Set for the first binding in a document
|
||||
#define XBLBinding_Serialize_IsFirstBinding 1
|
||||
|
||||
// Set to indicate that nsXBLPrototypeBinding::mInheritStyle should be true
|
||||
#define XBLBinding_Serialize_InheritStyle 2
|
||||
|
||||
// Appears at the end of the serialized data to indicate that no more bindings
|
||||
// are present for this document.
|
||||
#define XBLBinding_Serialize_NoMoreBindings 0x80
|
||||
|
||||
// Implementation member types. The serialized value for each member contains one
|
||||
// of these values, combined with the read-only flag XBLBinding_Serialize_ReadOnly.
|
||||
// Use XBLBinding_Serialize_Mask to filter out the read-only flag and check for
|
||||
// just the member type.
|
||||
#define XBLBinding_Serialize_NoMoreItems 0 // appears at the end of the members list
|
||||
#define XBLBinding_Serialize_Field 1
|
||||
#define XBLBinding_Serialize_GetterProperty 2
|
||||
#define XBLBinding_Serialize_SetterProperty 3
|
||||
#define XBLBinding_Serialize_GetterSetterProperty 4
|
||||
#define XBLBinding_Serialize_Method 5
|
||||
#define XBLBinding_Serialize_Constructor 6
|
||||
#define XBLBinding_Serialize_Destructor 7
|
||||
#define XBLBinding_Serialize_Handler 8
|
||||
#define XBLBinding_Serialize_Image 9
|
||||
#define XBLBinding_Serialize_Stylesheet 10
|
||||
#define XBLBinding_Serialize_Mask 0x0F
|
||||
#define XBLBinding_Serialize_ReadOnly 0x80
|
||||
|
||||
// Appears at the end of the list of insertion points to indicate that there
|
||||
// are no more.
|
||||
#define XBLBinding_Serialize_NoMoreInsertionPoints 0xFFFFFFFF
|
||||
|
||||
// When serializing content nodes, a single-byte namespace id is written out
|
||||
// first. The special values below can appear in place of a namespace id.
|
||||
|
||||
// Indicates that this is not one of the built-in namespaces defined in
|
||||
// nsINameSpaceManager.h. The string form will be serialized immediately
|
||||
// following.
|
||||
#define XBLBinding_Serialize_CustomNamespace 0xFE
|
||||
|
||||
// Flags to indicate a non-element node. Otherwise, it is an element.
|
||||
#define XBLBinding_Serialize_TextNode 0xFB
|
||||
#define XBLBinding_Serialize_CDATANode 0xFC
|
||||
#define XBLBinding_Serialize_CommentNode 0xFD
|
||||
|
||||
// Indicates that there is no content to serialize/deserialize
|
||||
#define XBLBinding_Serialize_NoContent 0xFF
|
||||
|
||||
// Appears at the end of the forwarded attributes list to indicate that there
|
||||
// are no more attributes.
|
||||
#define XBLBinding_Serialize_NoMoreAttributes 0xFF
|
||||
|
||||
PR_STATIC_ASSERT(XBLBinding_Serialize_CustomNamespace >= kNameSpaceID_LastBuiltin);
|
||||
|
||||
nsresult
|
||||
XBL_SerializeFunction(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream,
|
||||
JSObject* aFunctionObject);
|
||||
JSObject* aFunctionObject,
|
||||
PRUint32 aLineNumber);
|
||||
|
||||
nsresult
|
||||
XBL_DeserializeFunction(nsIScriptContext* aContext,
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include "nsStyleContext.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsXBLSerialize.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPrototypeCache.h"
|
||||
|
@ -840,9 +841,6 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
|
|||
if (!docInfo)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Get our doc info and determine our script access.
|
||||
nsCOMPtr<nsIDocument> doc = docInfo->GetDocument();
|
||||
|
||||
nsXBLPrototypeBinding* protoBinding = docInfo->GetPrototypeBinding(ref);
|
||||
|
||||
NS_WARN_IF_FALSE(protoBinding, "Unable to locate an XBL binding");
|
||||
|
@ -1059,7 +1057,23 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
|
|||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
// Next, look in the startup cache
|
||||
bool useStartupCache = useXULCache && IsChromeOrResourceURI(documentURI);
|
||||
if (!info && useStartupCache) {
|
||||
rv = nsXBLDocumentInfo::ReadPrototypeBindings(documentURI, getter_AddRefs(info));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
cache->PutXBLDocumentInfo(info);
|
||||
|
||||
if (bindingManager) {
|
||||
// Cache it in our binding manager's document table.
|
||||
bindingManager->PutXBLDocumentInfo(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!info) {
|
||||
// Finally, if all lines of defense fail, we go and fetch the binding
|
||||
// document.
|
||||
|
@ -1072,7 +1086,7 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
|
|||
nsCOMPtr<nsIDocument> document;
|
||||
FetchBindingDocument(aBoundElement, aBoundDocument, documentURI,
|
||||
aBindingURI, aForceSyncLoad, getter_AddRefs(document));
|
||||
|
||||
|
||||
if (document) {
|
||||
nsBindingManager *xblDocBindingManager = document->BindingManager();
|
||||
info = xblDocBindingManager->GetXBLDocumentInfo(documentURI);
|
||||
|
@ -1084,8 +1098,11 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
|
|||
|
||||
// If the doc is a chrome URI, then we put it into the XUL cache.
|
||||
#ifdef MOZ_XUL
|
||||
if (useXULCache && IsChromeOrResourceURI(documentURI)) {
|
||||
if (useStartupCache) {
|
||||
cache->PutXBLDocumentInfo(info);
|
||||
|
||||
// now write the bindings into the startup cache
|
||||
info->WritePrototypeBindings();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -219,6 +219,27 @@ NS_NewXMLDocument(nsIDocument** aInstancePtrResult)
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewXBLDocument(nsIDOMDocument** aInstancePtrResult,
|
||||
nsIURI* aDocumentURI,
|
||||
nsIURI* aBaseURI,
|
||||
nsIPrincipal* aPrincipal)
|
||||
{
|
||||
nsresult rv = NS_NewDOMDocument(aInstancePtrResult,
|
||||
NS_LITERAL_STRING("http://www.mozilla.org/xbl"),
|
||||
NS_LITERAL_STRING("bindings"), nsnull,
|
||||
aDocumentURI, aBaseURI, aPrincipal, false,
|
||||
nsnull, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> idoc = do_QueryInterface(*aInstancePtrResult);
|
||||
nsDocument* doc = static_cast<nsDocument*>(idoc.get());
|
||||
doc->SetLoadedAsInteractiveData(true);
|
||||
doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// NOTE! nsDocument::operator new() zeroes out all members, so don't
|
||||
// bother initializing members to 0.
|
||||
|
||||
|
|
|
@ -60,6 +60,9 @@ NewObjectOutputWrappedStorageStream(nsIObjectOutputStream **wrapperStream,
|
|||
nsIStorageStream** stream,
|
||||
bool wantDebugStream);
|
||||
|
||||
// Creates a buffer for storing the stream into the cache. The buffer is
|
||||
// allocated with 'new []'. Typically, the caller would store the buffer in
|
||||
// an nsAutoArrayPtr<char> and then call nsIStartupCache::PutBuffer with it.
|
||||
NS_EXPORT nsresult
|
||||
NewBufferFromStorageStream(nsIStorageStream *storageStream,
|
||||
char** buffer, PRUint32* len);
|
||||
|
|
Загрузка…
Ссылка в новой задаче