зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1517880 - Add ability to rebuild an element prototype from an element. r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D38971 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
90adb39db2
Коммит
742dc1c8e2
|
@ -3747,6 +3747,11 @@ void Document::InitialDocumentTranslationCompleted() {
|
|||
mPendingInitialTranslation = false;
|
||||
|
||||
mL10nProtoElements.Clear();
|
||||
|
||||
nsXULPrototypeDocument* proto = GetPrototype();
|
||||
if (proto) {
|
||||
proto->SetIsL10nCached();
|
||||
}
|
||||
}
|
||||
|
||||
bool Document::IsWebAnimationsEnabled(JSContext* aCx, JSObject* /*unused*/) {
|
||||
|
|
|
@ -27,7 +27,13 @@
|
|||
#include "nsCCUncollectableMarker.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "nsXULPrototypeCache.h"
|
||||
#include "mozilla/DeclarationBlock.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Text.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using mozilla::dom::DestroyProtoAndIfaceCache;
|
||||
using mozilla::dom::XULDocument;
|
||||
|
||||
|
@ -39,7 +45,11 @@ uint32_t nsXULPrototypeDocument::gRefCnt;
|
|||
//
|
||||
|
||||
nsXULPrototypeDocument::nsXULPrototypeDocument()
|
||||
: mRoot(nullptr), mLoaded(false), mCCGeneration(0), mGCNumber(0) {
|
||||
: mRoot(nullptr),
|
||||
mLoaded(false),
|
||||
mCCGeneration(0),
|
||||
mGCNumber(0),
|
||||
mWasL10nCached(false) {
|
||||
++gRefCnt;
|
||||
}
|
||||
|
||||
|
@ -112,6 +122,11 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream) {
|
|||
// Better safe than sorry....
|
||||
mNodeInfoManager->SetDocumentPrincipal(principal);
|
||||
|
||||
rv = aStream->ReadBoolean(&mWasL10nCached);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRoot = new nsXULPrototypeElement();
|
||||
|
||||
// mozilla::dom::NodeInfo table
|
||||
|
@ -255,6 +270,11 @@ nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream) {
|
|||
}
|
||||
#endif
|
||||
|
||||
tmp = aStream->WriteBoolean(mWasL10nCached);
|
||||
if (NS_FAILED(tmp)) {
|
||||
rv = tmp;
|
||||
}
|
||||
|
||||
// mozilla::dom::NodeInfo table
|
||||
nsTArray<RefPtr<mozilla::dom::NodeInfo>> nodeInfos;
|
||||
if (mRoot) {
|
||||
|
@ -425,3 +445,91 @@ void nsXULPrototypeDocument::TraceProtos(JSTracer* aTrc) {
|
|||
mRoot->TraceAllScripts(aTrc);
|
||||
}
|
||||
}
|
||||
|
||||
void nsXULPrototypeDocument::SetIsL10nCached() { mWasL10nCached = true; }
|
||||
|
||||
void nsXULPrototypeDocument::RebuildPrototypeFromElement(
|
||||
nsXULPrototypeElement* aPrototype, Element* aElement, bool aDeep) {
|
||||
aPrototype->mHasIdAttribute = aElement->HasID();
|
||||
aPrototype->mHasClassAttribute = aElement->MayHaveClass();
|
||||
aPrototype->mHasStyleAttribute = aElement->MayHaveStyle();
|
||||
NodeInfo* oldNodeInfo = aElement->NodeInfo();
|
||||
RefPtr<NodeInfo> newNodeInfo = mNodeInfoManager->GetNodeInfo(
|
||||
oldNodeInfo->NameAtom(), oldNodeInfo->GetPrefixAtom(),
|
||||
oldNodeInfo->NamespaceID(), nsINode::ELEMENT_NODE);
|
||||
aPrototype->mNodeInfo = newNodeInfo;
|
||||
|
||||
// First replace the prototype attributes with the new ones from this element.
|
||||
aPrototype->mAttributes.Clear();
|
||||
|
||||
uint32_t count = aElement->GetAttrCount();
|
||||
nsXULPrototypeAttribute* protoAttr =
|
||||
aPrototype->mAttributes.AppendElements(count);
|
||||
for (uint32_t index = 0; index < count; index++) {
|
||||
BorrowedAttrInfo attr = aElement->GetAttrInfoAt(index);
|
||||
|
||||
if (attr.mName->IsAtom()) {
|
||||
protoAttr->mName.SetTo(attr.mName->Atom());
|
||||
} else {
|
||||
NodeInfo* oldNodeInfo = attr.mName->NodeInfo();
|
||||
RefPtr<NodeInfo> newNodeInfo = mNodeInfoManager->GetNodeInfo(
|
||||
oldNodeInfo->NameAtom(), oldNodeInfo->GetPrefixAtom(),
|
||||
oldNodeInfo->NamespaceID(), nsINode::ATTRIBUTE_NODE);
|
||||
protoAttr->mName.SetTo(newNodeInfo);
|
||||
}
|
||||
protoAttr->mValue.SetTo(*attr.mValue);
|
||||
|
||||
if (protoAttr->mName.Equals(nsGkAtoms::is)) {
|
||||
aPrototype->mIsAtom = protoAttr->mValue.GetAtomValue();
|
||||
}
|
||||
|
||||
protoAttr++;
|
||||
}
|
||||
|
||||
if (aDeep) {
|
||||
// We have to rebuild the prototype children from this element.
|
||||
// First release the tree under this element.
|
||||
aPrototype->ReleaseSubtree();
|
||||
|
||||
RefPtr<nsXULPrototypeNode>* children =
|
||||
aPrototype->mChildren.AppendElements(aElement->GetChildCount());
|
||||
for (nsIContent* child = aElement->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
if (child->IsElement()) {
|
||||
Element* element = child->AsElement();
|
||||
RefPtr<nsXULPrototypeElement> elemProto = new nsXULPrototypeElement;
|
||||
RebuildPrototypeFromElement(elemProto, element, true);
|
||||
*children = elemProto;
|
||||
} else if (child->IsText()) {
|
||||
Text* text = child->AsText();
|
||||
RefPtr<nsXULPrototypeText> textProto = new nsXULPrototypeText();
|
||||
text->AppendTextTo(textProto->mValue);
|
||||
*children = textProto;
|
||||
} else {
|
||||
MOZ_ASSERT(false, "We handle only elements and text nodes here.");
|
||||
}
|
||||
|
||||
children++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsXULPrototypeDocument::RebuildL10nPrototype(Element* aElement,
|
||||
bool aDeep) {
|
||||
if (mWasL10nCached) {
|
||||
return;
|
||||
}
|
||||
|
||||
Document* doc = aElement->OwnerDoc();
|
||||
|
||||
nsAutoString id;
|
||||
MOZ_RELEASE_ASSERT(aElement->GetAttr(nsGkAtoms::datal10nid, id));
|
||||
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<nsXULPrototypeElement> proto = doc->mL10nProtoElements.Get(aElement);
|
||||
MOZ_RELEASE_ASSERT(proto);
|
||||
RebuildPrototypeFromElement(proto, aElement, aDeep);
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
#include "nsISerializable.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include <functional>
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
class nsAtom;
|
||||
class nsIPrincipal;
|
||||
|
@ -93,6 +94,13 @@ class nsXULPrototypeDocument final : public nsISerializable {
|
|||
|
||||
void TraceProtos(JSTracer* aTrc);
|
||||
|
||||
bool WasL10nCached() { return mWasL10nCached; };
|
||||
|
||||
void SetIsL10nCached();
|
||||
void RebuildPrototypeFromElement(nsXULPrototypeElement* aPrototype,
|
||||
mozilla::dom::Element* aElement, bool aDeep);
|
||||
void RebuildL10nPrototype(mozilla::dom::Element* aElement, bool aDeep);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
RefPtr<nsXULPrototypeElement> mRoot;
|
||||
|
@ -114,6 +122,7 @@ class nsXULPrototypeDocument final : public nsISerializable {
|
|||
nsXULPrototypeDocument** aResult);
|
||||
|
||||
static uint32_t gRefCnt;
|
||||
bool mWasL10nCached;
|
||||
};
|
||||
|
||||
#endif // nsXULPrototypeDocument_h__
|
||||
|
|
Загрузка…
Ссылка в новой задаче