зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1123523 - Part 6: Listen for nsIAnimationObserver notifications and translate them to MutationObserver notifications. r=smaug
This commit is contained in:
Родитель
3496ca27f3
Коммит
d068522170
|
@ -269,7 +269,7 @@ nsMutationReceiver::ContentRemoved(nsIDocument* aDocument,
|
|||
// Try to avoid creating transient observer if the node
|
||||
// already has an observer observing the same set of nodes.
|
||||
nsMutationReceiver* orig = GetParent() ? GetParent() : this;
|
||||
if (Observer()->GetReceiverFor(aChild, false) != orig) {
|
||||
if (Observer()->GetReceiverFor(aChild, false, false) != orig) {
|
||||
bool transientExists = false;
|
||||
nsCOMArray<nsMutationReceiver>* transientReceivers = nullptr;
|
||||
Observer()->mTransientReceivers.Get(aChild, &transientReceivers);
|
||||
|
@ -287,7 +287,13 @@ nsMutationReceiver::ContentRemoved(nsIDocument* aDocument,
|
|||
if (!transientExists) {
|
||||
// Make sure the elements which are removed from the
|
||||
// subtree are kept in the same observation set.
|
||||
transientReceivers->AppendObject(new nsMutationReceiver(aChild, orig));
|
||||
nsMutationReceiver* tr;
|
||||
if (orig->Animations()) {
|
||||
tr = nsAnimationReceiver::Create(aChild, orig);
|
||||
} else {
|
||||
tr = nsMutationReceiver::Create(aChild, orig);
|
||||
}
|
||||
transientReceivers->AppendObject(tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -316,6 +322,87 @@ void nsMutationReceiver::NodeWillBeDestroyed(const nsINode *aNode)
|
|||
Disconnect(true);
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationReceiver::RecordAnimationMutation(AnimationPlayer* aPlayer,
|
||||
AnimationMutation aMutationType)
|
||||
{
|
||||
Animation* source = aPlayer->GetSource();
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
Element* animationTarget = source->GetTarget();
|
||||
if (!animationTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Animations() || !(Subtree() || animationTarget == Target()) ||
|
||||
animationTarget->ChromeOnlyAccess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsAutoAnimationMutationBatch::IsBatching()) {
|
||||
if (nsAutoAnimationMutationBatch::GetBatchTarget() != animationTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aMutationType) {
|
||||
case eAnimationMutation_Added:
|
||||
nsAutoAnimationMutationBatch::AnimationAdded(aPlayer);
|
||||
break;
|
||||
case eAnimationMutation_Changed:
|
||||
nsAutoAnimationMutationBatch::AnimationChanged(aPlayer);
|
||||
break;
|
||||
case eAnimationMutation_Removed:
|
||||
nsAutoAnimationMutationBatch::AnimationRemoved(aPlayer);
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoAnimationMutationBatch::AddObserver(Observer());
|
||||
return;
|
||||
}
|
||||
|
||||
nsDOMMutationRecord* m =
|
||||
Observer()->CurrentRecord(nsGkAtoms::animations);
|
||||
|
||||
NS_ASSERTION(!m->mTarget, "Wrong target!");
|
||||
|
||||
m->mTarget = animationTarget;
|
||||
|
||||
switch (aMutationType) {
|
||||
case eAnimationMutation_Added:
|
||||
m->mAddedAnimations.AppendElement(aPlayer);
|
||||
break;
|
||||
case eAnimationMutation_Changed:
|
||||
m->mChangedAnimations.AppendElement(aPlayer);
|
||||
break;
|
||||
case eAnimationMutation_Removed:
|
||||
m->mRemovedAnimations.AppendElement(aPlayer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationReceiver::AnimationAdded(AnimationPlayer* aPlayer)
|
||||
{
|
||||
RecordAnimationMutation(aPlayer, eAnimationMutation_Added);
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationReceiver::AnimationChanged(AnimationPlayer* aPlayer)
|
||||
{
|
||||
RecordAnimationMutation(aPlayer, eAnimationMutation_Changed);
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationReceiver::AnimationRemoved(AnimationPlayer* aPlayer)
|
||||
{
|
||||
RecordAnimationMutation(aPlayer, eAnimationMutation_Removed);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsAnimationReceiver, nsMutationReceiver,
|
||||
nsIAnimationObserver)
|
||||
|
||||
// Observer
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMMutationObserver)
|
||||
|
@ -355,8 +442,13 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMMutationObserver)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
nsMutationReceiver*
|
||||
nsDOMMutationObserver::GetReceiverFor(nsINode* aNode, bool aMayCreate)
|
||||
nsDOMMutationObserver::GetReceiverFor(nsINode* aNode, bool aMayCreate,
|
||||
bool aWantsAnimations)
|
||||
{
|
||||
MOZ_ASSERT(aMayCreate || !aWantsAnimations,
|
||||
"the value of aWantsAnimations doesn't matter when aMayCreate is "
|
||||
"false, so just pass in false for it");
|
||||
|
||||
if (!aMayCreate && !aNode->MayHaveDOMMutationObserver()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -370,7 +462,12 @@ nsDOMMutationObserver::GetReceiverFor(nsINode* aNode, bool aMayCreate)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsMutationReceiver* r = new nsMutationReceiver(aNode, this);
|
||||
nsMutationReceiver* r;
|
||||
if (aWantsAnimations) {
|
||||
r = nsAnimationReceiver::Create(aNode, this);
|
||||
} else {
|
||||
r = nsMutationReceiver::Create(aNode, this);
|
||||
}
|
||||
mReceivers.AppendObject(r);
|
||||
return r;
|
||||
}
|
||||
|
@ -389,7 +486,7 @@ nsDOMMutationObserver::GetAllSubtreeObserversFor(nsINode* aNode,
|
|||
nsINode* n = aNode;
|
||||
while (n) {
|
||||
if (n->MayHaveDOMMutationObserver()) {
|
||||
nsMutationReceiver* r = GetReceiverFor(n, false);
|
||||
nsMutationReceiver* r = GetReceiverFor(n, false, false);
|
||||
if (r && r->Subtree() && !aReceivers.Contains(r)) {
|
||||
aReceivers.AppendElement(r);
|
||||
// If we've found all the receivers the observer has,
|
||||
|
@ -528,7 +625,7 @@ nsDOMMutationObserver::Observe(nsINode& aTarget,
|
|||
}
|
||||
}
|
||||
|
||||
nsMutationReceiver* r = GetReceiverFor(&aTarget, true);
|
||||
nsMutationReceiver* r = GetReceiverFor(&aTarget, true, animations);
|
||||
r->SetChildList(childList);
|
||||
r->SetAttributes(attributes);
|
||||
r->SetCharacterData(characterData);
|
||||
|
@ -860,10 +957,16 @@ nsAutoMutationBatch::Done()
|
|||
for (uint32_t k = 0; k < allObservers.Length(); ++k) {
|
||||
nsMutationReceiver* r = allObservers[k];
|
||||
nsMutationReceiver* orig = r->GetParent() ? r->GetParent() : r;
|
||||
if (ob->GetReceiverFor(removed, false) != orig) {
|
||||
if (ob->GetReceiverFor(removed, false, false) != orig) {
|
||||
// Make sure the elements which are removed from the
|
||||
// subtree are kept in the same observation set.
|
||||
transientReceivers->AppendObject(new nsMutationReceiver(removed, orig));
|
||||
nsMutationReceiver* tr;
|
||||
if (orig->Animations()) {
|
||||
tr = nsAnimationReceiver::Create(removed, orig);
|
||||
} else {
|
||||
tr = nsMutationReceiver::Create(removed, orig);
|
||||
}
|
||||
transientReceivers->AppendObject(tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -890,3 +993,45 @@ nsAutoMutationBatch::Done()
|
|||
}
|
||||
nsDOMMutationObserver::LeaveMutationHandling();
|
||||
}
|
||||
|
||||
nsAutoAnimationMutationBatch*
|
||||
nsAutoAnimationMutationBatch::sCurrentBatch = nullptr;
|
||||
|
||||
void
|
||||
nsAutoAnimationMutationBatch::Done()
|
||||
{
|
||||
if (sCurrentBatch != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
sCurrentBatch = mPreviousBatch;
|
||||
if (mObservers.IsEmpty()) {
|
||||
nsDOMMutationObserver::LeaveMutationHandling();
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
for (nsDOMMutationObserver* ob : mObservers) {
|
||||
nsRefPtr<nsDOMMutationRecord> m =
|
||||
new nsDOMMutationRecord(nsGkAtoms::animations, ob->GetParentObject());
|
||||
m->mTarget = mBatchTarget;
|
||||
|
||||
for (const Entry& e : mEntries) {
|
||||
if (e.mState == eState_Added) {
|
||||
m->mAddedAnimations.AppendElement(e.mPlayer);
|
||||
} else if (e.mState == eState_Removed) {
|
||||
m->mRemovedAnimations.AppendElement(e.mPlayer);
|
||||
} else if (e.mState == eState_RemainedPresent && e.mChanged) {
|
||||
m->mChangedAnimations.AppendElement(e.mPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m->mAddedAnimations.IsEmpty() ||
|
||||
!m->mChangedAnimations.IsEmpty() ||
|
||||
!m->mRemovedAnimations.IsEmpty()) {
|
||||
ob->AppendMutationRecord(m.forget());
|
||||
ob->ScheduleForRun();
|
||||
}
|
||||
}
|
||||
nsDOMMutationObserver::LeaveMutationHandling();
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
#include "nsStubAnimationObserver.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
@ -25,6 +25,7 @@
|
|||
#include "mozilla/dom/MutationObserverBinding.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "mozilla/dom/AnimationPlayer.h"
|
||||
#include "nsIAnimationObserver.h"
|
||||
|
||||
class nsDOMMutationObserver;
|
||||
using mozilla::dom::MutationObservingInfo;
|
||||
|
@ -128,7 +129,7 @@ public:
|
|||
|
||||
// Base class just prevents direct access to
|
||||
// members to make sure we go through getters/setters.
|
||||
class nsMutationReceiverBase : public nsStubMutationObserver
|
||||
class nsMutationReceiverBase : public nsStubAnimationObserver
|
||||
{
|
||||
public:
|
||||
virtual ~nsMutationReceiverBase() { }
|
||||
|
@ -228,9 +229,6 @@ protected:
|
|||
nsMutationReceiverBase(nsINode* aTarget, nsDOMMutationObserver* aObserver)
|
||||
: mTarget(aTarget), mObserver(aObserver), mRegisterTarget(aTarget)
|
||||
{
|
||||
mRegisterTarget->AddMutationObserver(this);
|
||||
mRegisterTarget->SetMayHaveDOMMutationObserver();
|
||||
mRegisterTarget->OwnerDoc()->SetMayHaveDOMMutationObservers();
|
||||
}
|
||||
|
||||
nsMutationReceiverBase(nsINode* aRegisterTarget,
|
||||
|
@ -239,7 +237,13 @@ protected:
|
|||
mRegisterTarget(aRegisterTarget), mKungFuDeathGrip(aParent->Target())
|
||||
{
|
||||
NS_ASSERTION(mParent->Subtree(), "Should clone a non-subtree observer!");
|
||||
mRegisterTarget->AddMutationObserver(this);
|
||||
}
|
||||
|
||||
virtual void AddMutationObserver() = 0;
|
||||
|
||||
void AddObserver()
|
||||
{
|
||||
AddMutationObserver();
|
||||
mRegisterTarget->SetMayHaveDOMMutationObserver();
|
||||
mRegisterTarget->OwnerDoc()->SetMayHaveDOMMutationObservers();
|
||||
}
|
||||
|
@ -302,14 +306,20 @@ protected:
|
|||
virtual ~nsMutationReceiver() { Disconnect(false); }
|
||||
|
||||
public:
|
||||
nsMutationReceiver(nsINode* aTarget, nsDOMMutationObserver* aObserver);
|
||||
|
||||
nsMutationReceiver(nsINode* aRegisterTarget, nsMutationReceiverBase* aParent)
|
||||
: nsMutationReceiverBase(aRegisterTarget, aParent)
|
||||
static nsMutationReceiver* Create(nsINode* aTarget,
|
||||
nsDOMMutationObserver* aObserver)
|
||||
{
|
||||
NS_ASSERTION(!static_cast<nsMutationReceiver*>(aParent)->GetParent(),
|
||||
"Shouldn't create deep observer hierarchies!");
|
||||
aParent->AddClone(this);
|
||||
nsMutationReceiver* r = new nsMutationReceiver(aTarget, aObserver);
|
||||
r->AddObserver();
|
||||
return r;
|
||||
}
|
||||
|
||||
static nsMutationReceiver* Create(nsINode* aRegisterTarget,
|
||||
nsMutationReceiverBase* aParent)
|
||||
{
|
||||
nsMutationReceiver* r = new nsMutationReceiver(aRegisterTarget, aParent);
|
||||
r->AddObserver();
|
||||
return r;
|
||||
}
|
||||
|
||||
nsMutationReceiver* GetParent()
|
||||
|
@ -360,6 +370,72 @@ public:
|
|||
AttributeWillChange(aDocument, aElement, aNameSpaceID, aAttribute,
|
||||
nsIDOMMutationEvent::MODIFICATION);
|
||||
}
|
||||
|
||||
protected:
|
||||
nsMutationReceiver(nsINode* aTarget, nsDOMMutationObserver* aObserver);
|
||||
|
||||
nsMutationReceiver(nsINode* aRegisterTarget, nsMutationReceiverBase* aParent)
|
||||
: nsMutationReceiverBase(aRegisterTarget, aParent)
|
||||
{
|
||||
NS_ASSERTION(!static_cast<nsMutationReceiver*>(aParent)->GetParent(),
|
||||
"Shouldn't create deep observer hierarchies!");
|
||||
aParent->AddClone(this);
|
||||
}
|
||||
|
||||
virtual void AddMutationObserver() MOZ_OVERRIDE
|
||||
{
|
||||
mRegisterTarget->AddMutationObserver(this);
|
||||
}
|
||||
};
|
||||
|
||||
class nsAnimationReceiver : public nsMutationReceiver
|
||||
{
|
||||
public:
|
||||
static nsAnimationReceiver* Create(nsINode* aTarget,
|
||||
nsDOMMutationObserver* aObserver)
|
||||
{
|
||||
nsAnimationReceiver* r = new nsAnimationReceiver(aTarget, aObserver);
|
||||
r->AddObserver();
|
||||
return r;
|
||||
}
|
||||
|
||||
static nsAnimationReceiver* Create(nsINode* aRegisterTarget,
|
||||
nsMutationReceiverBase* aParent)
|
||||
{
|
||||
nsAnimationReceiver* r = new nsAnimationReceiver(aRegisterTarget, aParent);
|
||||
r->AddObserver();
|
||||
return r;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONADDED
|
||||
NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONCHANGED
|
||||
NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONREMOVED
|
||||
|
||||
protected:
|
||||
virtual ~nsAnimationReceiver() {}
|
||||
|
||||
nsAnimationReceiver(nsINode* aTarget, nsDOMMutationObserver* aObserver)
|
||||
: nsMutationReceiver(aTarget, aObserver) {}
|
||||
|
||||
nsAnimationReceiver(nsINode* aRegisterTarget, nsMutationReceiverBase* aParent)
|
||||
: nsMutationReceiver(aRegisterTarget, aParent) {}
|
||||
|
||||
virtual void AddMutationObserver() MOZ_OVERRIDE
|
||||
{
|
||||
mRegisterTarget->AddAnimationObserver(this);
|
||||
}
|
||||
|
||||
private:
|
||||
enum AnimationMutation {
|
||||
eAnimationMutation_Added,
|
||||
eAnimationMutation_Changed,
|
||||
eAnimationMutation_Removed
|
||||
};
|
||||
|
||||
void RecordAnimationMutation(mozilla::dom::AnimationPlayer* aPlayer,
|
||||
AnimationMutation aMutationType);
|
||||
};
|
||||
|
||||
#define NS_DOM_MUTATION_OBSERVER_IID \
|
||||
|
@ -448,8 +524,12 @@ protected:
|
|||
virtual ~nsDOMMutationObserver();
|
||||
|
||||
friend class nsMutationReceiver;
|
||||
friend class nsAnimationReceiver;
|
||||
friend class nsAutoMutationBatch;
|
||||
nsMutationReceiver* GetReceiverFor(nsINode* aNode, bool aMayCreate);
|
||||
friend class nsAutoAnimationMutationBatch;
|
||||
nsMutationReceiver* GetReceiverFor(nsINode* aNode,
|
||||
bool aMayCreate,
|
||||
bool aWantsAnimations);
|
||||
void RemoveReceiver(nsMutationReceiver* aReceiver);
|
||||
|
||||
already_AddRefed<nsIVariant> TakeRecords();
|
||||
|
@ -625,6 +705,156 @@ private:
|
|||
nsCOMPtr<nsINode> mNextSibling;
|
||||
};
|
||||
|
||||
class nsAutoAnimationMutationBatch
|
||||
{
|
||||
struct Entry;
|
||||
|
||||
public:
|
||||
nsAutoAnimationMutationBatch(nsINode* aTarget)
|
||||
: mBatchTarget(nullptr)
|
||||
{
|
||||
Init(aTarget);
|
||||
}
|
||||
|
||||
void Init(nsINode* aTarget)
|
||||
{
|
||||
if (aTarget && aTarget->OwnerDoc()->MayHaveDOMMutationObservers()) {
|
||||
mBatchTarget = aTarget;
|
||||
mPreviousBatch = sCurrentBatch;
|
||||
sCurrentBatch = this;
|
||||
nsDOMMutationObserver::EnterMutationHandling();
|
||||
}
|
||||
}
|
||||
|
||||
~nsAutoAnimationMutationBatch()
|
||||
{
|
||||
Done();
|
||||
}
|
||||
|
||||
void Done();
|
||||
|
||||
static bool IsBatching()
|
||||
{
|
||||
return !!sCurrentBatch;
|
||||
}
|
||||
|
||||
static nsAutoAnimationMutationBatch* GetCurrentBatch()
|
||||
{
|
||||
return sCurrentBatch;
|
||||
}
|
||||
|
||||
static void AddObserver(nsDOMMutationObserver* aObserver)
|
||||
{
|
||||
if (sCurrentBatch->mObservers.Contains(aObserver)) {
|
||||
return;
|
||||
}
|
||||
sCurrentBatch->mObservers.AppendElement(aObserver);
|
||||
}
|
||||
|
||||
static nsINode* GetBatchTarget()
|
||||
{
|
||||
return sCurrentBatch->mBatchTarget;
|
||||
}
|
||||
|
||||
static void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer)
|
||||
{
|
||||
if (!IsBatching()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Entry* entry = sCurrentBatch->FindEntry(aPlayer);
|
||||
if (entry) {
|
||||
switch (entry->mState) {
|
||||
case eState_RemainedAbsent:
|
||||
entry->mState = eState_Added;
|
||||
break;
|
||||
case eState_Removed:
|
||||
entry->mState = eState_RemainedPresent;
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("shouldn't have observed an animation being added "
|
||||
"twice");
|
||||
}
|
||||
} else {
|
||||
entry = sCurrentBatch->mEntries.AppendElement();
|
||||
entry->mPlayer = aPlayer;
|
||||
entry->mState = eState_Added;
|
||||
entry->mChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer)
|
||||
{
|
||||
Entry* entry = sCurrentBatch->FindEntry(aPlayer);
|
||||
if (entry) {
|
||||
NS_ASSERTION(entry->mState == eState_RemainedPresent ||
|
||||
entry->mState == eState_Added,
|
||||
"shouldn't have observed an animation being changed after "
|
||||
"being removed");
|
||||
entry->mChanged = true;
|
||||
} else {
|
||||
entry = sCurrentBatch->mEntries.AppendElement();
|
||||
entry->mPlayer = aPlayer;
|
||||
entry->mState = eState_RemainedPresent;
|
||||
entry->mChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer)
|
||||
{
|
||||
Entry* entry = sCurrentBatch->FindEntry(aPlayer);
|
||||
if (entry) {
|
||||
switch (entry->mState) {
|
||||
case eState_RemainedPresent:
|
||||
entry->mState = eState_Removed;
|
||||
break;
|
||||
case eState_Added:
|
||||
entry->mState = eState_RemainedAbsent;
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("shouldn't have observed an animation being removed "
|
||||
"twice");
|
||||
}
|
||||
} else {
|
||||
entry = sCurrentBatch->mEntries.AppendElement();
|
||||
entry->mPlayer = aPlayer;
|
||||
entry->mState = eState_Removed;
|
||||
entry->mChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Entry* FindEntry(mozilla::dom::AnimationPlayer* aPlayer)
|
||||
{
|
||||
for (Entry& e : mEntries) {
|
||||
if (e.mPlayer == aPlayer) {
|
||||
return &e;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
enum State {
|
||||
eState_RemainedPresent,
|
||||
eState_RemainedAbsent,
|
||||
eState_Added,
|
||||
eState_Removed
|
||||
};
|
||||
|
||||
struct Entry
|
||||
{
|
||||
nsRefPtr<mozilla::dom::AnimationPlayer> mPlayer;
|
||||
State mState;
|
||||
bool mChanged;
|
||||
};
|
||||
|
||||
static nsAutoAnimationMutationBatch* sCurrentBatch;
|
||||
nsAutoAnimationMutationBatch* mPreviousBatch;
|
||||
nsAutoTArray<nsDOMMutationObserver*, 2> mObservers;
|
||||
nsTArray<Entry> mEntries;
|
||||
nsINode* mBatchTarget;
|
||||
};
|
||||
|
||||
inline
|
||||
nsDOMMutationObserver*
|
||||
nsMutationReceiverBase::Observer()
|
||||
|
|
|
@ -88,6 +88,7 @@ GK_ATOM(ancestor, "ancestor")
|
|||
GK_ATOM(ancestorOrSelf, "ancestor-or-self")
|
||||
GK_ATOM(anchor, "anchor")
|
||||
GK_ATOM(_and, "and")
|
||||
GK_ATOM(animations, "animations")
|
||||
GK_ATOM(anonid, "anonid")
|
||||
GK_ATOM(any, "any")
|
||||
GK_ATOM(mozapp, "mozapp")
|
||||
|
|
Загрузка…
Ссылка в новой задаче