зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1594275
- Parse the exportparts attribute. r=bzbarsky
But don't hook it into style yet, that'll be a follow-up patch. I had this patch in my local queue for a bit and there was no point in not landing it I guess. The value of this attribute could be stored only in the shadow root (as this only applies to shadow hosts), but that would make invalidation harder, I think, so do the obvious thing for now. Differential Revision: https://phabricator.services.mozilla.com/D51963 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
a9f5350d66
Коммит
785ebbeab9
|
@ -16,6 +16,7 @@
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/StaticPrefs_dom.h"
|
#include "mozilla/StaticPrefs_dom.h"
|
||||||
#include "mozilla/StaticPrefs_layout.h"
|
#include "mozilla/StaticPrefs_layout.h"
|
||||||
|
#include "mozilla/StaticPrefs_full_screen_api.h"
|
||||||
#include "mozilla/dom/Animation.h"
|
#include "mozilla/dom/Animation.h"
|
||||||
#include "mozilla/dom/Attr.h"
|
#include "mozilla/dom/Attr.h"
|
||||||
#include "mozilla/dom/BindContext.h"
|
#include "mozilla/dom/BindContext.h"
|
||||||
|
@ -2517,6 +2518,12 @@ bool Element::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aAttribute == nsGkAtoms::exportparts &&
|
||||||
|
StaticPrefs::layout_css_shadow_parts_enabled()) {
|
||||||
|
aResult.ParsePartMapping(aValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (aAttribute == nsGkAtoms::id) {
|
if (aAttribute == nsGkAtoms::id) {
|
||||||
// Store id as an atom. id="" means that the element has no id,
|
// Store id as an atom. id="" means that the element has no id,
|
||||||
// not that it has an emptystring as the id.
|
// not that it has an emptystring as the id.
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/ServoBindingTypes.h"
|
#include "mozilla/ServoBindingTypes.h"
|
||||||
#include "mozilla/ServoUtils.h"
|
#include "mozilla/ServoUtils.h"
|
||||||
|
#include "mozilla/ShadowParts.h"
|
||||||
#include "mozilla/DeclarationBlock.h"
|
#include "mozilla/DeclarationBlock.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
|
@ -281,6 +282,7 @@ void nsAttrValue::SetTo(const nsAttrValue& aOther) {
|
||||||
cont->mValue.mColor = otherCont->mValue.mColor;
|
cont->mValue.mColor = otherCont->mValue.mColor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case eShadowParts:
|
||||||
case eCSSDeclaration: {
|
case eCSSDeclaration: {
|
||||||
MOZ_CRASH("These should be refcounted!");
|
MOZ_CRASH("These should be refcounted!");
|
||||||
}
|
}
|
||||||
|
@ -301,9 +303,10 @@ void nsAttrValue::SetTo(const nsAttrValue& aOther) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eIntMarginValue: {
|
case eIntMarginValue: {
|
||||||
if (otherCont->mValue.mIntMargin)
|
if (otherCont->mValue.mIntMargin) {
|
||||||
cont->mValue.mIntMargin =
|
cont->mValue.mIntMargin =
|
||||||
new nsIntMargin(*otherCont->mValue.mIntMargin);
|
new nsIntMargin(*otherCont->mValue.mIntMargin);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
@ -1155,7 +1158,7 @@ void nsAttrValue::ParseAtomArray(const nsAString& aValue) {
|
||||||
void nsAttrValue::ParseStringOrAtom(const nsAString& aValue) {
|
void nsAttrValue::ParseStringOrAtom(const nsAString& aValue) {
|
||||||
uint32_t len = aValue.Length();
|
uint32_t len = aValue.Length();
|
||||||
// Don't bother with atoms if it's an empty string since
|
// Don't bother with atoms if it's an empty string since
|
||||||
// we can store those efficently anyway.
|
// we can store those efficiently anyway.
|
||||||
if (len && len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
|
if (len && len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
|
||||||
ParseAtom(aValue);
|
ParseAtom(aValue);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1163,6 +1166,17 @@ void nsAttrValue::ParseStringOrAtom(const nsAString& aValue) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsAttrValue::ParsePartMapping(const nsAString& aValue) {
|
||||||
|
ResetIfSet();
|
||||||
|
MiscContainer* cont = EnsureEmptyMiscContainer();
|
||||||
|
|
||||||
|
cont->mType = eShadowParts;
|
||||||
|
cont->mValue.mShadowParts = new ShadowParts(ShadowParts::Parse(aValue));
|
||||||
|
NS_ADDREF(cont);
|
||||||
|
SetMiscAtomOrString(&aValue);
|
||||||
|
MOZ_ASSERT(cont->mValue.mRefCount == 1);
|
||||||
|
}
|
||||||
|
|
||||||
void nsAttrValue::SetIntValueAndType(int32_t aValue, ValueType aType,
|
void nsAttrValue::SetIntValueAndType(int32_t aValue, ValueType aType,
|
||||||
const nsAString* aStringValue) {
|
const nsAString* aStringValue) {
|
||||||
if (aStringValue || aValue > NS_ATTRVALUE_INTEGERTYPE_MAXVALUE ||
|
if (aStringValue || aValue > NS_ATTRVALUE_INTEGERTYPE_MAXVALUE ||
|
||||||
|
@ -1740,6 +1754,12 @@ MiscContainer* nsAttrValue::ClearMiscContainer() {
|
||||||
NS_RELEASE(cont->mValue.mCSSDeclaration);
|
NS_RELEASE(cont->mValue.mCSSDeclaration);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case eShadowParts: {
|
||||||
|
MOZ_ASSERT(cont->mValue.mRefCount == 1);
|
||||||
|
cont->Release();
|
||||||
|
delete cont->mValue.mShadowParts;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case eURL: {
|
case eURL: {
|
||||||
NS_RELEASE(cont->mValue.mURL);
|
NS_RELEASE(cont->mValue.mURL);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -101,6 +101,10 @@ class nsAttrValue {
|
||||||
eAtomArray,
|
eAtomArray,
|
||||||
eDoubleValue,
|
eDoubleValue,
|
||||||
eIntMarginValue,
|
eIntMarginValue,
|
||||||
|
// eShadowParts is refcounted in the misc container, as we do copy attribute
|
||||||
|
// values quite a bit (for example to process style invalidation), and the
|
||||||
|
// underlying value could get expensive to copy.
|
||||||
|
eShadowParts,
|
||||||
eSVGIntegerPair,
|
eSVGIntegerPair,
|
||||||
eSVGTypesBegin = eSVGIntegerPair,
|
eSVGTypesBegin = eSVGIntegerPair,
|
||||||
eSVGOrient,
|
eSVGOrient,
|
||||||
|
@ -256,6 +260,13 @@ class nsAttrValue {
|
||||||
void ParseAtomArray(const nsAString& aValue);
|
void ParseAtomArray(const nsAString& aValue);
|
||||||
void ParseStringOrAtom(const nsAString& aValue);
|
void ParseStringOrAtom(const nsAString& aValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an exportparts attribute.
|
||||||
|
*
|
||||||
|
* https://drafts.csswg.org/css-shadow-parts/#parsing-mapping-list
|
||||||
|
*/
|
||||||
|
void ParsePartMapping(const nsAString&);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Structure for a mapping from int (enum) values to strings. When you use
|
* Structure for a mapping from int (enum) values to strings. When you use
|
||||||
* it you generally create an array of them.
|
* it you generally create an array of them.
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/ServoUtils.h"
|
#include "mozilla/ServoUtils.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
class ShadowParts;
|
||||||
|
}
|
||||||
|
|
||||||
struct MiscContainer final {
|
struct MiscContainer final {
|
||||||
typedef nsAttrValue::ValueType ValueType;
|
typedef nsAttrValue::ValueType ValueType;
|
||||||
|
|
||||||
|
@ -41,6 +45,7 @@ struct MiscContainer final {
|
||||||
nsIURI* mURL;
|
nsIURI* mURL;
|
||||||
mozilla::AtomArray* mAtomArray;
|
mozilla::AtomArray* mAtomArray;
|
||||||
nsIntMargin* mIntMargin;
|
nsIntMargin* mIntMargin;
|
||||||
|
const mozilla::ShadowParts* mShadowParts;
|
||||||
const mozilla::SVGAnimatedIntegerPair* mSVGAnimatedIntegerPair;
|
const mozilla::SVGAnimatedIntegerPair* mSVGAnimatedIntegerPair;
|
||||||
const mozilla::SVGAnimatedLength* mSVGLength;
|
const mozilla::SVGAnimatedLength* mSVGLength;
|
||||||
const mozilla::SVGAnimatedNumberPair* mSVGAnimatedNumberPair;
|
const mozilla::SVGAnimatedNumberPair* mSVGAnimatedNumberPair;
|
||||||
|
@ -95,7 +100,8 @@ struct MiscContainer final {
|
||||||
// Nothing stops us from refcounting (and sharing) other types of
|
// Nothing stops us from refcounting (and sharing) other types of
|
||||||
// MiscContainer (except eDoubleValue types) but there's no compelling
|
// MiscContainer (except eDoubleValue types) but there's no compelling
|
||||||
// reason to.
|
// reason to.
|
||||||
return mType == nsAttrValue::eCSSDeclaration;
|
return mType == nsAttrValue::eCSSDeclaration ||
|
||||||
|
mType == nsAttrValue::eShadowParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int32_t AddRef() {
|
inline int32_t AddRef() {
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/* -*- 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/. */
|
||||||
|
|
||||||
|
#include "ShadowParts.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
static bool IsSpace(char16_t aChar) {
|
||||||
|
return nsContentUtils::IsHTMLWhitespace(aChar);
|
||||||
|
};
|
||||||
|
|
||||||
|
using SingleMapping = std::pair<RefPtr<nsAtom>, RefPtr<nsAtom>>;
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-shadow-parts/#parsing-mapping
|
||||||
|
//
|
||||||
|
// Returns null on both tokens to signal an error.
|
||||||
|
static SingleMapping ParseSingleMapping(const nsAString& aString) {
|
||||||
|
const char16_t* c = aString.BeginReading();
|
||||||
|
const char16_t* end = aString.EndReading();
|
||||||
|
|
||||||
|
const auto CollectASequenceOfSpaces = [&c, end]() {
|
||||||
|
while (c != end && IsSpace(*c)) {
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto CollectToken = [&c, end]() -> RefPtr<nsAtom> {
|
||||||
|
const char16_t* t = c;
|
||||||
|
while (c != end && !IsSpace(*c) && *c != ':') {
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
if (c == t) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return NS_AtomizeMainThread(Substring(t, c));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Steps 1 and 2 are variable declarations.
|
||||||
|
//
|
||||||
|
// 3. Collect a sequence of code points that are space characters.
|
||||||
|
CollectASequenceOfSpaces();
|
||||||
|
|
||||||
|
// 4. Collect a sequence of code points that are not space characters or
|
||||||
|
// U+003A COLON characters, and call the result first token.
|
||||||
|
RefPtr<nsAtom> firstToken = CollectToken();
|
||||||
|
|
||||||
|
// 5. If first token is empty then return error.
|
||||||
|
if (!firstToken) {
|
||||||
|
return {nullptr, nullptr};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Collect a sequence of code points that are space characters.
|
||||||
|
CollectASequenceOfSpaces();
|
||||||
|
|
||||||
|
// 7. If the end of the input has been reached, return the pair first
|
||||||
|
// token/first token.
|
||||||
|
if (c == end) {
|
||||||
|
return {firstToken, firstToken};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. If character at position is not a U+003A COLON character, return error.
|
||||||
|
if (*c != ':') {
|
||||||
|
return {nullptr, nullptr};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9. Consume the U+003A COLON character.
|
||||||
|
++c;
|
||||||
|
|
||||||
|
// 10. Collect a sequence of code points that are space characters.
|
||||||
|
CollectASequenceOfSpaces();
|
||||||
|
|
||||||
|
// 11. Collect a sequence of code points that are not space characters or
|
||||||
|
// U+003A COLON characters. and let second token be the result.
|
||||||
|
RefPtr<nsAtom> secondToken = CollectToken();
|
||||||
|
|
||||||
|
// 12. If second token is empty then return error.
|
||||||
|
if (!secondToken) {
|
||||||
|
return {nullptr, nullptr};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13. Collect a sequence of code points that are space characters.
|
||||||
|
CollectASequenceOfSpaces();
|
||||||
|
|
||||||
|
// 14. If position is not past the end of input then return error.
|
||||||
|
if (c != end) {
|
||||||
|
return {nullptr, nullptr};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 15. Return the pair first token/second token.
|
||||||
|
return {std::move(firstToken), std::move(secondToken)};
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-shadow-parts/#parsing-mapping-list
|
||||||
|
ShadowParts ShadowParts::Parse(const nsAString& aString) {
|
||||||
|
ShadowParts parts;
|
||||||
|
|
||||||
|
for (const auto& substring : aString.Split(',')) {
|
||||||
|
auto mapping = ParseSingleMapping(substring);
|
||||||
|
if (!mapping.first) {
|
||||||
|
MOZ_ASSERT(!mapping.second);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parts.mMappings.GetOrInsert(mapping.first) = std::move(mapping.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,32 @@
|
||||||
|
/* -*- 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_ShadowParts_h
|
||||||
|
#define mozilla_ShadowParts_h
|
||||||
|
|
||||||
|
#include "nsAtom.h"
|
||||||
|
#include "nsTHashtable.h"
|
||||||
|
#include "nsRefPtrHashtable.h"
|
||||||
|
#include "nsStringFwd.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class ShadowParts final {
|
||||||
|
public:
|
||||||
|
ShadowParts(ShadowParts&&) = default;
|
||||||
|
ShadowParts(const ShadowParts&) = delete;
|
||||||
|
|
||||||
|
static ShadowParts Parse(const nsAString&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ShadowParts() = default;
|
||||||
|
|
||||||
|
nsRefPtrHashtable<nsRefPtrHashKey<nsAtom>, nsAtom> mMappings;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_ShadowParts_h
|
|
@ -107,6 +107,7 @@ EXPORTS.mozilla += [
|
||||||
'ServoTraversalStatistics.h',
|
'ServoTraversalStatistics.h',
|
||||||
'ServoTypes.h',
|
'ServoTypes.h',
|
||||||
'ServoUtils.h',
|
'ServoUtils.h',
|
||||||
|
'ShadowParts.h',
|
||||||
'StyleAnimationValue.h',
|
'StyleAnimationValue.h',
|
||||||
'StyleColorInlines.h',
|
'StyleColorInlines.h',
|
||||||
'StyleSheet.h',
|
'StyleSheet.h',
|
||||||
|
@ -221,6 +222,7 @@ UNIFIED_SOURCES += [
|
||||||
'ServoCSSRuleList.cpp',
|
'ServoCSSRuleList.cpp',
|
||||||
'ServoElementSnapshot.cpp',
|
'ServoElementSnapshot.cpp',
|
||||||
'ServoStyleSet.cpp',
|
'ServoStyleSet.cpp',
|
||||||
|
'ShadowParts.cpp',
|
||||||
'StreamLoader.cpp',
|
'StreamLoader.cpp',
|
||||||
'StyleAnimationValue.cpp',
|
'StyleAnimationValue.cpp',
|
||||||
'StyleColor.cpp',
|
'StyleColor.cpp',
|
||||||
|
|
|
@ -424,7 +424,7 @@ void nsLayoutStylesheetCache::InitSharedSheetsInParent() {
|
||||||
// TODO(heycam): This won't be true on Windows unless we allow creating the
|
// TODO(heycam): This won't be true on Windows unless we allow creating the
|
||||||
// shared memory with SEC_RESERVE so that the pages are reserved but not
|
// shared memory with SEC_RESERVE so that the pages are reserved but not
|
||||||
// committed.
|
// committed.
|
||||||
size_t pageSize = ipc::SharedMemory::SystemPageSize();
|
size_t pageSize = mozilla::ipc::SharedMemory::SystemPageSize();
|
||||||
mUsedSharedMemory =
|
mUsedSharedMemory =
|
||||||
(Servo_SharedMemoryBuilder_GetLength(builder.get()) + pageSize - 1) &
|
(Servo_SharedMemoryBuilder_GetLength(builder.get()) + pageSize - 1) &
|
||||||
~(pageSize - 1);
|
~(pageSize - 1);
|
||||||
|
|
|
@ -413,6 +413,7 @@ STATIC_ATOMS = [
|
||||||
Atom("event", "event"),
|
Atom("event", "event"),
|
||||||
Atom("events", "events"),
|
Atom("events", "events"),
|
||||||
Atom("excludeResultPrefixes", "exclude-result-prefixes"),
|
Atom("excludeResultPrefixes", "exclude-result-prefixes"),
|
||||||
|
Atom("exportparts", "exportparts"),
|
||||||
Atom("extends", "extends"),
|
Atom("extends", "extends"),
|
||||||
Atom("extensionElementPrefixes", "extension-element-prefixes"),
|
Atom("extensionElementPrefixes", "extension-element-prefixes"),
|
||||||
Atom("face", "face"),
|
Atom("face", "face"),
|
||||||
|
|
Загрузка…
Ссылка в новой задаче