2017-10-27 20:33:53 +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: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
2006-03-25 08:47:31 +03:00
|
|
|
|
|
|
|
/* atom list for CSS pseudo-elements */
|
|
|
|
|
2017-02-14 22:23:11 +03:00
|
|
|
#include "nsCSSPseudoElements.h"
|
|
|
|
|
2013-12-09 06:52:54 +04:00
|
|
|
#include "mozilla/ArrayUtils.h"
|
2011-10-11 09:50:08 +04:00
|
|
|
|
2009-10-08 07:22:42 +04:00
|
|
|
#include "nsCSSAnonBoxes.h"
|
2017-04-18 06:15:47 +03:00
|
|
|
#include "nsDOMString.h"
|
2018-08-15 08:46:00 +03:00
|
|
|
#include "nsGkAtomConsts.h"
|
2018-08-15 08:46:42 +03:00
|
|
|
#include "nsStaticAtomUtils.h"
|
1998-12-11 05:51:05 +03:00
|
|
|
|
2011-10-11 09:50:08 +04:00
|
|
|
using namespace mozilla;
|
|
|
|
|
Bug 1449395 - Remove nsStaticAtomSetup. r=froydnj
Each nsStaticAtomSetup contains a pointer to a static atom, and also a pointer
to the canonical pointer to that static atom. Which is pretty weird! The
notable thing thing about it is that these structs are in an array, and that
gives us the only way to iterate over all static atoms in a single class, for
registration and lookups.
But thanks to various other recent changes to the implementation of static
atoms, we can now put the static atoms themselves into an array, which can be
iterated over. So this patch does that. With that done, nsStaticAtomSetup is no
longer necessary.
According to the `size` utility, on Linux64 this reduces the size of libxul.so
by the following amounts:
> text: 62008 bytes
> data: 20992 bytes
> bss: 21040 bytes
> total: 104040 bytes
- The bss reduction is one word per atom, because the canonical static atom
pointers (e.g. nsGkAtoms::foo) have moved from .bss to .data, because they're
now initialized at compile time instead of runtime.
- The data reduction is one word per atom, because we remove two words per atom
for the nsStaticAtomSetup removal, but gain one word per atom from the
previous bullet point.
- I'm not sure about the text reduction. It's three words per atom. Maybe
because there is one less relocation per atom?
Other notable things in the patch:
- nsICSSAnonBoxPseudo and nsICSSPseudoElement now inherit from nsStaticAtom,
not nsAtom, because that's more precise.
- Each static atoms array now has an enum associated with it, which is used in
various ways.
- In the big comment about the macros at the top of nsStaticAtom.h, the pre-
and post-expansion forms are now shown interleaved. The interleaving reduces
duplication and makes the comment much easier to read and maintain. The
comment also has an introduction that explains the constraints and goals of
the implementation.
- The SUBCLASS macro variations are gone. There are few enough users of these
macros now that always passing the atom type has become simpler.
MozReview-Commit-ID: 1GmfKidLjaU
--HG--
extra : rebase_source : 2352590101fc6693ba388f885ca4714a42963943
2018-03-29 03:48:18 +03:00
|
|
|
// Flags data for each of the pseudo-elements.
|
2016-05-10 11:44:05 +03:00
|
|
|
/* static */ const uint32_t
|
|
|
|
nsCSSPseudoElements::kPseudoElementFlags[] = {
|
2009-08-11 02:52:29 +04:00
|
|
|
#define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
|
|
|
|
flags_,
|
|
|
|
#include "nsCSSPseudoElementList.h"
|
|
|
|
#undef CSS_PSEUDO_ELEMENT
|
|
|
|
};
|
|
|
|
|
2018-08-15 08:46:00 +03:00
|
|
|
static nsStaticAtom*
|
|
|
|
GetAtomBase()
|
1998-12-11 05:51:05 +03:00
|
|
|
{
|
2018-08-15 08:46:00 +03:00
|
|
|
return const_cast<nsStaticAtom*>(
|
|
|
|
nsGkAtoms::GetAtomByIndex(kAtomIndex_PseudoElements));
|
1998-12-11 05:51:05 +03:00
|
|
|
}
|
|
|
|
|
2018-08-15 08:46:00 +03:00
|
|
|
bool
|
|
|
|
nsCSSPseudoElements::IsPseudoElement(nsAtom* aAtom)
|
2002-11-17 18:37:56 +03:00
|
|
|
{
|
2018-08-15 08:46:00 +03:00
|
|
|
return nsStaticAtomUtils::IsMember(aAtom, GetAtomBase(),
|
|
|
|
kAtomCount_PseudoElements);
|
2002-11-17 18:37:56 +03:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
/* static */ bool
|
2017-10-03 01:05:19 +03:00
|
|
|
nsCSSPseudoElements::IsCSS2PseudoElement(nsAtom *aAtom)
|
2009-10-08 07:22:42 +04:00
|
|
|
{
|
|
|
|
// We don't implement this using PseudoElementHasFlags because callers
|
|
|
|
// want to pass things that could be anon boxes.
|
|
|
|
NS_ASSERTION(nsCSSPseudoElements::IsPseudoElement(aAtom) ||
|
|
|
|
nsCSSAnonBoxes::IsAnonBox(aAtom),
|
|
|
|
"must be pseudo element or anon box");
|
2018-08-15 08:46:00 +03:00
|
|
|
bool result = aAtom == nsCSSPseudoElements::after() ||
|
|
|
|
aAtom == nsCSSPseudoElements::before() ||
|
|
|
|
aAtom == nsCSSPseudoElements::firstLetter() ||
|
|
|
|
aAtom == nsCSSPseudoElements::firstLine();
|
2009-10-08 07:22:42 +04:00
|
|
|
NS_ASSERTION(nsCSSAnonBoxes::IsAnonBox(aAtom) ||
|
2016-05-10 11:44:05 +03:00
|
|
|
result == PseudoElementHasFlags(
|
|
|
|
GetPseudoType(aAtom, EnabledState::eIgnoreEnabledState),
|
|
|
|
CSS_PSEUDO_ELEMENT_IS_CSS2),
|
2009-10-08 07:22:42 +04:00
|
|
|
"result doesn't match flags");
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-02-17 01:07:00 +03:00
|
|
|
/* static */ CSSPseudoElementType
|
2018-08-01 12:57:45 +03:00
|
|
|
nsCSSPseudoElements::GetPseudoType(nsAtom* aAtom, EnabledState aEnabledState)
|
2009-12-11 10:37:40 +03:00
|
|
|
{
|
2018-08-15 08:46:00 +03:00
|
|
|
Maybe<uint32_t> index =
|
|
|
|
nsStaticAtomUtils::Lookup(aAtom, GetAtomBase(), kAtomCount_PseudoElements);
|
2018-03-20 05:01:28 +03:00
|
|
|
if (index.isSome()) {
|
|
|
|
auto type = static_cast<Type>(*index);
|
|
|
|
return IsEnabled(type, aEnabledState) ? type : Type::NotPseudo;
|
2009-12-11 10:37:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (nsCSSAnonBoxes::IsAnonBox(aAtom)) {
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (nsCSSAnonBoxes::IsTreePseudoElement(aAtom)) {
|
2016-02-17 01:07:00 +03:00
|
|
|
return Type::XULTree;
|
2009-12-11 10:37:40 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-03-09 07:41:04 +03:00
|
|
|
if (nsCSSAnonBoxes::IsNonInheritingAnonBox(aAtom)) {
|
|
|
|
return Type::NonInheritingAnonBox;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Type::InheritingAnonBox;
|
2009-12-11 10:37:40 +03:00
|
|
|
}
|
|
|
|
|
2016-02-17 01:07:00 +03:00
|
|
|
return Type::NotPseudo;
|
2009-12-11 10:37:40 +03:00
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
/* static */ nsAtom*
|
2009-12-11 10:37:40 +03:00
|
|
|
nsCSSPseudoElements::GetPseudoAtom(Type aType)
|
|
|
|
{
|
Bug 1449395 - Remove nsStaticAtomSetup. r=froydnj
Each nsStaticAtomSetup contains a pointer to a static atom, and also a pointer
to the canonical pointer to that static atom. Which is pretty weird! The
notable thing thing about it is that these structs are in an array, and that
gives us the only way to iterate over all static atoms in a single class, for
registration and lookups.
But thanks to various other recent changes to the implementation of static
atoms, we can now put the static atoms themselves into an array, which can be
iterated over. So this patch does that. With that done, nsStaticAtomSetup is no
longer necessary.
According to the `size` utility, on Linux64 this reduces the size of libxul.so
by the following amounts:
> text: 62008 bytes
> data: 20992 bytes
> bss: 21040 bytes
> total: 104040 bytes
- The bss reduction is one word per atom, because the canonical static atom
pointers (e.g. nsGkAtoms::foo) have moved from .bss to .data, because they're
now initialized at compile time instead of runtime.
- The data reduction is one word per atom, because we remove two words per atom
for the nsStaticAtomSetup removal, but gain one word per atom from the
previous bullet point.
- I'm not sure about the text reduction. It's three words per atom. Maybe
because there is one less relocation per atom?
Other notable things in the patch:
- nsICSSAnonBoxPseudo and nsICSSPseudoElement now inherit from nsStaticAtom,
not nsAtom, because that's more precise.
- Each static atoms array now has an enum associated with it, which is used in
various ways.
- In the big comment about the macros at the top of nsStaticAtom.h, the pre-
and post-expansion forms are now shown interleaved. The interleaving reduces
duplication and makes the comment much easier to read and maintain. The
comment also has an introduction that explains the constraints and goals of
the implementation.
- The SUBCLASS macro variations are gone. There are few enough users of these
macros now that always passing the atom type has become simpler.
MozReview-Commit-ID: 1GmfKidLjaU
--HG--
extra : rebase_source : 2352590101fc6693ba388f885ca4714a42963943
2018-03-29 03:48:18 +03:00
|
|
|
MOZ_ASSERT(aType < Type::Count, "Unexpected type");
|
2018-08-15 08:46:00 +03:00
|
|
|
size_t index = kAtomIndex_PseudoElements + static_cast<size_t>(aType);
|
|
|
|
return nsGkAtoms::GetAtomByIndex(index);
|
2009-12-11 10:37:40 +03:00
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
/* static */ already_AddRefed<nsAtom>
|
2017-04-18 06:15:47 +03:00
|
|
|
nsCSSPseudoElements::GetPseudoAtom(const nsAString& aPseudoElement)
|
|
|
|
{
|
|
|
|
if (DOMStringIsNull(aPseudoElement) || aPseudoElement.IsEmpty() ||
|
|
|
|
aPseudoElement.First() != char16_t(':')) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// deal with two-colon forms of aPseudoElt
|
|
|
|
nsAString::const_iterator start, end;
|
|
|
|
aPseudoElement.BeginReading(start);
|
|
|
|
aPseudoElement.EndReading(end);
|
|
|
|
NS_ASSERTION(start != end, "aPseudoElement is not empty!");
|
|
|
|
++start;
|
|
|
|
bool haveTwoColons = true;
|
|
|
|
if (start == end || *start != char16_t(':')) {
|
|
|
|
--start;
|
|
|
|
haveTwoColons = false;
|
|
|
|
}
|
2017-10-03 01:05:19 +03:00
|
|
|
RefPtr<nsAtom> pseudo = NS_Atomize(Substring(start, end));
|
2017-04-18 06:15:47 +03:00
|
|
|
MOZ_ASSERT(pseudo);
|
|
|
|
|
|
|
|
// There aren't any non-CSS2 pseudo-elements with a single ':'
|
|
|
|
if (!haveTwoColons &&
|
|
|
|
(!IsPseudoElement(pseudo) || !IsCSS2PseudoElement(pseudo))) {
|
|
|
|
// XXXbz I'd really rather we threw an exception or something, but
|
|
|
|
// the DOM spec sucks.
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-08-17 21:37:32 +03:00
|
|
|
return pseudo.forget();
|
2017-04-18 06:15:47 +03:00
|
|
|
}
|
|
|
|
|
2013-11-28 10:46:38 +04:00
|
|
|
/* static */ bool
|
|
|
|
nsCSSPseudoElements::PseudoElementSupportsUserActionState(const Type aType)
|
|
|
|
{
|
|
|
|
return PseudoElementHasFlags(aType,
|
|
|
|
CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE);
|
|
|
|
}
|
2018-01-27 15:17:26 +03:00
|
|
|
|
|
|
|
/* static */ nsString
|
|
|
|
nsCSSPseudoElements::PseudoTypeAsString(Type aPseudoType)
|
|
|
|
{
|
|
|
|
switch (aPseudoType) {
|
|
|
|
case CSSPseudoElementType::before:
|
|
|
|
return NS_LITERAL_STRING("::before");
|
|
|
|
case CSSPseudoElementType::after:
|
|
|
|
return NS_LITERAL_STRING("::after");
|
|
|
|
default:
|
|
|
|
MOZ_ASSERT(aPseudoType == CSSPseudoElementType::NotPseudo,
|
|
|
|
"Unexpected pseudo type");
|
|
|
|
return EmptyString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-15 08:46:00 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
/* static */ void
|
|
|
|
nsCSSPseudoElements::AssertAtoms()
|
|
|
|
{
|
|
|
|
nsStaticAtom* base = GetAtomBase();
|
|
|
|
#define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
|
|
|
|
{ \
|
|
|
|
RefPtr<nsAtom> atom = NS_Atomize(value_); \
|
|
|
|
size_t index = static_cast<size_t>(CSSPseudoElementType::name_); \
|
|
|
|
MOZ_ASSERT(atom == nsGkAtoms::PseudoElement_##name_, \
|
|
|
|
"Static atom for " #name_ " has incorrect value"); \
|
|
|
|
MOZ_ASSERT(atom == &base[index], \
|
|
|
|
"Static atom for " #name_ " not at expected index"); \
|
|
|
|
}
|
|
|
|
#include "nsCSSPseudoElementList.h"
|
|
|
|
#undef CSS_PSEUDO_ELEMENT
|
|
|
|
}
|
|
|
|
#endif
|