2016-07-19 04:02:55 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#ifndef mozilla_ServoElementSnapshot_h
|
|
|
|
#define mozilla_ServoElementSnapshot_h
|
|
|
|
|
2020-11-23 19:21:38 +03:00
|
|
|
#include "AttrArray.h"
|
2016-07-19 04:02:55 +03:00
|
|
|
#include "mozilla/TypedEnumBits.h"
|
2016-07-23 00:11:41 +03:00
|
|
|
#include "mozilla/dom/BorrowedAttrInfo.h"
|
2022-06-08 02:09:52 +03:00
|
|
|
#include "mozilla/dom/RustTypes.h"
|
2016-07-19 04:02:55 +03:00
|
|
|
#include "nsAttrName.h"
|
|
|
|
#include "nsAttrValue.h"
|
|
|
|
#include "nsChangeHint.h"
|
2017-06-27 20:55:03 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2017-10-03 01:05:19 +03:00
|
|
|
#include "nsAtom.h"
|
2021-12-14 18:39:38 +03:00
|
|
|
#include "MainThreadUtils.h"
|
2016-07-19 04:02:55 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
2020-11-23 19:08:40 +03:00
|
|
|
namespace dom {
|
|
|
|
class Element;
|
|
|
|
}
|
2016-07-19 04:02:55 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A bitflags enum class used to determine what data does a ServoElementSnapshot
|
|
|
|
* contains.
|
|
|
|
*/
|
|
|
|
enum class ServoElementSnapshotFlags : uint8_t {
|
|
|
|
State = 1 << 0,
|
|
|
|
Attributes = 1 << 1,
|
2017-05-18 18:31:54 +03:00
|
|
|
Id = 1 << 2,
|
|
|
|
MaybeClass = 1 << 3,
|
2017-06-05 09:19:30 +03:00
|
|
|
OtherPseudoClassState = 1 << 4,
|
2016-07-19 04:02:55 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ServoElementSnapshotFlags)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class holds all non-tree-structural state of an element that might be
|
|
|
|
* used for selector matching eventually.
|
|
|
|
*
|
|
|
|
* This means the attributes, and the element state, such as :hover, :active,
|
|
|
|
* etc...
|
|
|
|
*/
|
|
|
|
class ServoElementSnapshot {
|
2016-07-23 00:11:41 +03:00
|
|
|
typedef dom::BorrowedAttrInfo BorrowedAttrInfo;
|
2016-07-19 04:02:55 +03:00
|
|
|
typedef dom::Element Element;
|
2022-06-08 02:09:52 +03:00
|
|
|
|
|
|
|
// TODO: Now that the element state shares a representation with rust we
|
|
|
|
// should be able to do better and not use the internal type.
|
|
|
|
typedef dom::ElementState::InternalType ServoStateType;
|
2016-07-19 04:02:55 +03:00
|
|
|
|
|
|
|
public:
|
|
|
|
typedef ServoElementSnapshotFlags Flags;
|
|
|
|
|
2018-08-07 02:44:56 +03:00
|
|
|
explicit ServoElementSnapshot(const Element&);
|
2017-12-03 01:12:41 +03:00
|
|
|
|
|
|
|
~ServoElementSnapshot() {
|
2018-08-07 02:44:56 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-12-03 01:12:41 +03:00
|
|
|
MOZ_COUNT_DTOR(ServoElementSnapshot);
|
|
|
|
}
|
2016-07-19 04:02:55 +03:00
|
|
|
|
2017-05-05 23:48:53 +03:00
|
|
|
bool HasAttrs() const { return HasAny(Flags::Attributes); }
|
2016-07-19 04:02:55 +03:00
|
|
|
|
2017-05-05 23:48:53 +03:00
|
|
|
bool HasState() const { return HasAny(Flags::State); }
|
2016-07-19 04:02:55 +03:00
|
|
|
|
2017-06-05 09:19:30 +03:00
|
|
|
bool HasOtherPseudoClassState() const {
|
|
|
|
return HasAny(Flags::OtherPseudoClassState);
|
|
|
|
}
|
|
|
|
|
2016-07-19 04:02:55 +03:00
|
|
|
/**
|
|
|
|
* Captures the given state (if not previously captured).
|
|
|
|
*/
|
2022-06-08 02:09:52 +03:00
|
|
|
void AddState(dom::ElementState aState) {
|
2016-07-19 04:02:55 +03:00
|
|
|
if (!HasAny(Flags::State)) {
|
2022-06-08 02:09:52 +03:00
|
|
|
mState = aState.GetInternalValue();
|
2016-07-19 04:02:55 +03:00
|
|
|
mContains |= Flags::State;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Captures the given element attributes (if not previously captured).
|
2017-06-09 18:16:29 +03:00
|
|
|
*
|
|
|
|
* The attribute name and namespace are used to note which kind of attribute
|
|
|
|
* has changed.
|
2016-07-19 04:02:55 +03:00
|
|
|
*/
|
2020-11-23 19:08:40 +03:00
|
|
|
void AddAttrs(const Element&, int32_t aNameSpaceID, nsAtom* aAttribute);
|
2016-07-19 04:02:55 +03:00
|
|
|
|
2017-06-05 09:19:30 +03:00
|
|
|
/**
|
|
|
|
* Captures some other pseudo-class matching state not included in
|
2022-06-08 02:09:52 +03:00
|
|
|
* ElementState.
|
2017-06-05 09:19:30 +03:00
|
|
|
*/
|
2018-08-07 02:44:56 +03:00
|
|
|
void AddOtherPseudoClassState(const Element&);
|
2017-06-05 09:19:30 +03:00
|
|
|
|
2016-07-19 04:02:55 +03:00
|
|
|
/**
|
|
|
|
* Needed methods for attribute matching.
|
|
|
|
*/
|
2016-07-23 00:11:41 +03:00
|
|
|
BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const {
|
2017-05-05 23:48:53 +03:00
|
|
|
MOZ_ASSERT(HasAttrs());
|
2016-07-19 04:02:55 +03:00
|
|
|
if (aIndex >= mAttrs.Length()) {
|
2016-07-23 00:11:41 +03:00
|
|
|
return BorrowedAttrInfo(nullptr, nullptr);
|
2016-07-19 04:02:55 +03:00
|
|
|
}
|
2016-07-23 00:11:41 +03:00
|
|
|
return BorrowedAttrInfo(&mAttrs[aIndex].mName, &mAttrs[aIndex].mValue);
|
2016-07-19 04:02:55 +03:00
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
const nsAttrValue* GetParsedAttr(nsAtom* aLocalName) const {
|
2016-07-19 04:02:55 +03:00
|
|
|
return GetParsedAttr(aLocalName, kNameSpaceID_None);
|
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
const nsAttrValue* GetParsedAttr(nsAtom* aLocalName,
|
2016-07-19 04:02:55 +03:00
|
|
|
int32_t aNamespaceID) const {
|
2017-05-05 23:48:53 +03:00
|
|
|
MOZ_ASSERT(HasAttrs());
|
2016-07-19 04:02:55 +03:00
|
|
|
uint32_t i, len = mAttrs.Length();
|
|
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
|
|
|
// This should be the common case so lets make an optimized loop
|
|
|
|
for (i = 0; i < len; ++i) {
|
|
|
|
if (mAttrs[i].mName.Equals(aLocalName)) {
|
|
|
|
return &mAttrs[i].mValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < len; ++i) {
|
|
|
|
if (mAttrs[i].mName.Equals(aLocalName, aNamespaceID)) {
|
|
|
|
return &mAttrs[i].mValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-06-07 06:11:44 +03:00
|
|
|
bool IsInChromeDocument() const { return mIsInChromeDocument; }
|
|
|
|
bool SupportsLangAttr() const { return mSupportsLangAttr; }
|
2016-06-28 17:24:48 +03:00
|
|
|
|
2017-05-05 23:48:53 +03:00
|
|
|
bool HasAny(Flags aFlags) const { return bool(mContains & aFlags); }
|
2016-07-19 04:02:55 +03:00
|
|
|
|
2017-06-05 09:19:30 +03:00
|
|
|
bool IsTableBorderNonzero() const {
|
|
|
|
MOZ_ASSERT(HasOtherPseudoClassState());
|
|
|
|
return mIsTableBorderNonzero;
|
|
|
|
}
|
|
|
|
|
2020-07-17 12:56:53 +03:00
|
|
|
bool IsSelectListBox() const {
|
|
|
|
MOZ_ASSERT(HasOtherPseudoClassState());
|
|
|
|
return mIsSelectListBox;
|
|
|
|
}
|
|
|
|
|
2016-07-19 04:02:55 +03:00
|
|
|
private:
|
|
|
|
// TODO: Profile, a 1 or 2 element AutoTArray could be worth it, given we know
|
|
|
|
// we're dealing with attribute changes when we take snapshots of attributes,
|
|
|
|
// though it can be wasted space if we deal with a lot of state-only
|
|
|
|
// snapshots.
|
2018-08-14 19:43:26 +03:00
|
|
|
nsTArray<AttrArray::InternalAttr> mAttrs;
|
2020-05-27 12:17:47 +03:00
|
|
|
nsTArray<RefPtr<nsAtom>> mChangedAttrNames;
|
2017-06-27 20:55:03 +03:00
|
|
|
nsAttrValue mClass;
|
2016-07-19 04:02:55 +03:00
|
|
|
ServoStateType mState;
|
2017-05-18 18:30:42 +03:00
|
|
|
Flags mContains;
|
2017-06-05 09:19:30 +03:00
|
|
|
bool mIsInChromeDocument : 1;
|
2017-06-07 06:11:44 +03:00
|
|
|
bool mSupportsLangAttr : 1;
|
2017-06-05 09:19:30 +03:00
|
|
|
bool mIsTableBorderNonzero : 1;
|
2020-07-17 12:56:53 +03:00
|
|
|
bool mIsSelectListBox : 1;
|
2017-06-09 18:16:29 +03:00
|
|
|
bool mClassAttributeChanged : 1;
|
|
|
|
bool mIdAttributeChanged : 1;
|
2016-07-19 04:02:55 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif
|