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:
Zibi Braniecki 2019-07-26 20:17:09 +00:00
Родитель 90adb39db2
Коммит 742dc1c8e2
3 изменённых файлов: 123 добавлений и 1 удалений

Просмотреть файл

@ -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__