mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
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:
parent
a9f5350d66
commit
785ebbeab9
@ -16,6 +16,7 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "mozilla/StaticPrefs_full_screen_api.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/Attr.h"
|
||||
#include "mozilla/dom/BindContext.h"
|
||||
@ -2517,6 +2518,12 @@ bool Element::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::exportparts &&
|
||||
StaticPrefs::layout_css_shadow_parts_enabled()) {
|
||||
aResult.ParsePartMapping(aValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::id) {
|
||||
// Store id as an atom. id="" means that the element has no id,
|
||||
// not that it has an emptystring as the id.
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/ServoBindingTypes.h"
|
||||
#include "mozilla/ServoUtils.h"
|
||||
#include "mozilla/ShadowParts.h"
|
||||
#include "mozilla/DeclarationBlock.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
@ -281,6 +282,7 @@ void nsAttrValue::SetTo(const nsAttrValue& aOther) {
|
||||
cont->mValue.mColor = otherCont->mValue.mColor;
|
||||
break;
|
||||
}
|
||||
case eShadowParts:
|
||||
case eCSSDeclaration: {
|
||||
MOZ_CRASH("These should be refcounted!");
|
||||
}
|
||||
@ -301,9 +303,10 @@ void nsAttrValue::SetTo(const nsAttrValue& aOther) {
|
||||
break;
|
||||
}
|
||||
case eIntMarginValue: {
|
||||
if (otherCont->mValue.mIntMargin)
|
||||
if (otherCont->mValue.mIntMargin) {
|
||||
cont->mValue.mIntMargin =
|
||||
new nsIntMargin(*otherCont->mValue.mIntMargin);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -1155,7 +1158,7 @@ void nsAttrValue::ParseAtomArray(const nsAString& aValue) {
|
||||
void nsAttrValue::ParseStringOrAtom(const nsAString& aValue) {
|
||||
uint32_t len = aValue.Length();
|
||||
// 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) {
|
||||
ParseAtom(aValue);
|
||||
} 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,
|
||||
const nsAString* aStringValue) {
|
||||
if (aStringValue || aValue > NS_ATTRVALUE_INTEGERTYPE_MAXVALUE ||
|
||||
@ -1740,6 +1754,12 @@ MiscContainer* nsAttrValue::ClearMiscContainer() {
|
||||
NS_RELEASE(cont->mValue.mCSSDeclaration);
|
||||
break;
|
||||
}
|
||||
case eShadowParts: {
|
||||
MOZ_ASSERT(cont->mValue.mRefCount == 1);
|
||||
cont->Release();
|
||||
delete cont->mValue.mShadowParts;
|
||||
break;
|
||||
}
|
||||
case eURL: {
|
||||
NS_RELEASE(cont->mValue.mURL);
|
||||
break;
|
||||
|
@ -101,6 +101,10 @@ class nsAttrValue {
|
||||
eAtomArray,
|
||||
eDoubleValue,
|
||||
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,
|
||||
eSVGTypesBegin = eSVGIntegerPair,
|
||||
eSVGOrient,
|
||||
@ -256,6 +260,13 @@ class nsAttrValue {
|
||||
void ParseAtomArray(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
|
||||
* it you generally create an array of them.
|
||||
|
@ -14,6 +14,10 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ServoUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
class ShadowParts;
|
||||
}
|
||||
|
||||
struct MiscContainer final {
|
||||
typedef nsAttrValue::ValueType ValueType;
|
||||
|
||||
@ -41,6 +45,7 @@ struct MiscContainer final {
|
||||
nsIURI* mURL;
|
||||
mozilla::AtomArray* mAtomArray;
|
||||
nsIntMargin* mIntMargin;
|
||||
const mozilla::ShadowParts* mShadowParts;
|
||||
const mozilla::SVGAnimatedIntegerPair* mSVGAnimatedIntegerPair;
|
||||
const mozilla::SVGAnimatedLength* mSVGLength;
|
||||
const mozilla::SVGAnimatedNumberPair* mSVGAnimatedNumberPair;
|
||||
@ -95,7 +100,8 @@ struct MiscContainer final {
|
||||
// Nothing stops us from refcounting (and sharing) other types of
|
||||
// MiscContainer (except eDoubleValue types) but there's no compelling
|
||||
// reason to.
|
||||
return mType == nsAttrValue::eCSSDeclaration;
|
||||
return mType == nsAttrValue::eCSSDeclaration ||
|
||||
mType == nsAttrValue::eShadowParts;
|
||||
}
|
||||
|
||||
inline int32_t AddRef() {
|
||||
|
114
layout/style/ShadowParts.cpp
Normal file
114
layout/style/ShadowParts.cpp
Normal file
@ -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
|
32
layout/style/ShadowParts.h
Normal file
32
layout/style/ShadowParts.h
Normal file
@ -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',
|
||||
'ServoTypes.h',
|
||||
'ServoUtils.h',
|
||||
'ShadowParts.h',
|
||||
'StyleAnimationValue.h',
|
||||
'StyleColorInlines.h',
|
||||
'StyleSheet.h',
|
||||
@ -221,6 +222,7 @@ UNIFIED_SOURCES += [
|
||||
'ServoCSSRuleList.cpp',
|
||||
'ServoElementSnapshot.cpp',
|
||||
'ServoStyleSet.cpp',
|
||||
'ShadowParts.cpp',
|
||||
'StreamLoader.cpp',
|
||||
'StyleAnimationValue.cpp',
|
||||
'StyleColor.cpp',
|
||||
|
@ -424,7 +424,7 @@ void nsLayoutStylesheetCache::InitSharedSheetsInParent() {
|
||||
// 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
|
||||
// committed.
|
||||
size_t pageSize = ipc::SharedMemory::SystemPageSize();
|
||||
size_t pageSize = mozilla::ipc::SharedMemory::SystemPageSize();
|
||||
mUsedSharedMemory =
|
||||
(Servo_SharedMemoryBuilder_GetLength(builder.get()) + pageSize - 1) &
|
||||
~(pageSize - 1);
|
||||
|
@ -413,6 +413,7 @@ STATIC_ATOMS = [
|
||||
Atom("event", "event"),
|
||||
Atom("events", "events"),
|
||||
Atom("excludeResultPrefixes", "exclude-result-prefixes"),
|
||||
Atom("exportparts", "exportparts"),
|
||||
Atom("extends", "extends"),
|
||||
Atom("extensionElementPrefixes", "extension-element-prefixes"),
|
||||
Atom("face", "face"),
|
||||
|
Loading…
Reference in New Issue
Block a user