2016-11-23 02:26:20 +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/. */
|
|
|
|
|
|
|
|
/* representation of CSSRuleList for stylo */
|
|
|
|
|
|
|
|
#include "mozilla/ServoCSSRuleList.h"
|
|
|
|
|
2017-05-30 04:10:25 +03:00
|
|
|
#include "mozilla/IntegerRange.h"
|
2016-11-23 02:26:20 +03:00
|
|
|
#include "mozilla/ServoBindings.h"
|
2018-04-05 01:41:28 +03:00
|
|
|
#include "mozilla/ServoCounterStyleRule.h"
|
2017-05-11 15:11:16 +03:00
|
|
|
#include "mozilla/ServoDocumentRule.h"
|
2017-05-30 04:10:25 +03:00
|
|
|
#include "mozilla/ServoImportRule.h"
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
#include "mozilla/ServoFontFaceRule.h"
|
2017-07-26 04:30:15 +03:00
|
|
|
#include "mozilla/ServoFontFeatureValuesRule.h"
|
2017-05-19 09:12:34 +03:00
|
|
|
#include "mozilla/ServoKeyframesRule.h"
|
2017-03-09 09:37:45 +03:00
|
|
|
#include "mozilla/ServoMediaRule.h"
|
2017-03-14 10:51:59 +03:00
|
|
|
#include "mozilla/ServoNamespaceRule.h"
|
2017-03-31 05:25:22 +03:00
|
|
|
#include "mozilla/ServoPageRule.h"
|
2017-05-11 15:11:16 +03:00
|
|
|
#include "mozilla/ServoStyleRule.h"
|
2017-04-26 10:59:29 +03:00
|
|
|
#include "mozilla/ServoSupportsRule.h"
|
2018-04-30 20:23:14 +03:00
|
|
|
#include "mozilla/StyleSheet.h"
|
2016-11-23 02:26:20 +03:00
|
|
|
|
2018-02-13 03:53:44 +03:00
|
|
|
using namespace mozilla::dom;
|
|
|
|
|
2016-11-23 02:26:20 +03:00
|
|
|
namespace mozilla {
|
|
|
|
|
2017-05-30 04:10:25 +03:00
|
|
|
ServoCSSRuleList::ServoCSSRuleList(already_AddRefed<ServoCssRules> aRawRules,
|
2018-04-30 20:23:14 +03:00
|
|
|
StyleSheet* aDirectOwnerStyleSheet)
|
2017-05-30 04:10:25 +03:00
|
|
|
: mStyleSheet(aDirectOwnerStyleSheet)
|
|
|
|
, mRawRules(aRawRules)
|
2016-11-23 02:26:20 +03:00
|
|
|
{
|
|
|
|
Servo_CssRules_ListTypes(mRawRules, &mRules);
|
|
|
|
}
|
|
|
|
|
2017-01-06 07:14:28 +03:00
|
|
|
// QueryInterface implementation for ServoCSSRuleList
|
2017-08-30 02:02:48 +03:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServoCSSRuleList)
|
2017-01-06 07:14:28 +03:00
|
|
|
NS_INTERFACE_MAP_END_INHERITING(dom::CSSRuleList)
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(ServoCSSRuleList)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ServoCSSRuleList)
|
2017-03-09 12:53:34 +03:00
|
|
|
tmp->DropAllRules();
|
2017-01-06 07:14:28 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(dom::CSSRuleList)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoCSSRuleList,
|
|
|
|
dom::CSSRuleList)
|
|
|
|
tmp->EnumerateInstantiatedRules([&](css::Rule* aRule) {
|
2016-12-01 02:18:14 +03:00
|
|
|
if (!aRule->IsCCLeaf()) {
|
|
|
|
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
|
|
|
|
cb.NoteXPCOMChild(aRule);
|
|
|
|
}
|
2017-01-06 07:14:28 +03:00
|
|
|
});
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
2017-03-09 12:53:34 +03:00
|
|
|
void
|
|
|
|
ServoCSSRuleList::SetParentRule(css::GroupRule* aParentRule)
|
|
|
|
{
|
|
|
|
mParentRule = aParentRule;
|
|
|
|
EnumerateInstantiatedRules([aParentRule](css::Rule* rule) {
|
|
|
|
rule->SetParentRule(aParentRule);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ServoCSSRuleList::SetStyleSheet(StyleSheet* aStyleSheet)
|
|
|
|
{
|
2018-04-30 19:19:44 +03:00
|
|
|
mStyleSheet = aStyleSheet;
|
2017-05-19 01:48:48 +03:00
|
|
|
EnumerateInstantiatedRules([this](css::Rule* rule) {
|
|
|
|
rule->SetStyleSheet(mStyleSheet);
|
2017-03-09 12:53:34 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-11-29 14:59:55 +03:00
|
|
|
css::Rule*
|
|
|
|
ServoCSSRuleList::GetRule(uint32_t aIndex)
|
2016-11-23 02:26:20 +03:00
|
|
|
{
|
|
|
|
uintptr_t rule = mRules[aIndex];
|
|
|
|
if (rule <= kMaxRuleType) {
|
|
|
|
RefPtr<css::Rule> ruleObj = nullptr;
|
|
|
|
switch (rule) {
|
2017-03-14 09:52:37 +03:00
|
|
|
#define CASE_RULE(const_, name_) \
|
2018-01-11 11:17:56 +03:00
|
|
|
case CSSRuleBinding::const_##_RULE: { \
|
2017-04-25 17:24:39 +03:00
|
|
|
uint32_t line = 0, column = 0; \
|
|
|
|
RefPtr<RawServo##name_##Rule> rule = \
|
|
|
|
Servo_CssRules_Get##name_##RuleAt( \
|
|
|
|
mRawRules, aIndex, &line, &column \
|
|
|
|
).Consume(); \
|
2017-06-29 20:09:56 +03:00
|
|
|
MOZ_ASSERT(rule); \
|
2017-04-25 17:24:39 +03:00
|
|
|
ruleObj = new Servo##name_##Rule(rule.forget(), line, column); \
|
2017-03-14 09:52:37 +03:00
|
|
|
break; \
|
2017-03-09 09:37:45 +03:00
|
|
|
}
|
2017-03-14 09:52:37 +03:00
|
|
|
CASE_RULE(STYLE, Style)
|
2017-05-19 09:12:34 +03:00
|
|
|
CASE_RULE(KEYFRAMES, Keyframes)
|
2017-03-14 09:52:37 +03:00
|
|
|
CASE_RULE(MEDIA, Media)
|
2017-03-14 10:51:59 +03:00
|
|
|
CASE_RULE(NAMESPACE, Namespace)
|
2017-03-31 05:25:22 +03:00
|
|
|
CASE_RULE(PAGE, Page)
|
2017-04-26 10:59:29 +03:00
|
|
|
CASE_RULE(SUPPORTS, Supports)
|
2017-05-11 15:11:16 +03:00
|
|
|
CASE_RULE(DOCUMENT, Document)
|
2017-06-29 20:09:56 +03:00
|
|
|
CASE_RULE(IMPORT, Import)
|
2017-07-26 04:30:15 +03:00
|
|
|
CASE_RULE(FONT_FEATURE_VALUES, FontFeatureValues)
|
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio
This patch does the following things:
* Create a new class ServoFontFaceRule for CSSOM of @font-face rule
which mostly follows how nsCSSFontFaceRule was implemented.
* Remove the old nsCSSFontFaceRule and binding code to create it.
* Have FontFace backed by Servo data via making mRule and mDescriptors
of the class hold RawServoFontFaceRule like ServoFontFaceRule.
To keep this patch small, it effectively just delays the conversion
from Servo data to nsCSSValue from parsing to using. This may cause
worse performance if the font set is flushed repeatedly. Supposing we
don't flush font set very frequently, it may not be a big deal.
We may still want to remove the intermediate nsCSSValue conversion at
some point, and have everything converted to their final form directly
when used, but that can happen in followups.
There are some unfortunate bits from this change:
* We lose style sheet for logging in FontFaceSet. This is probably not
all that worse, because we wouldn't have that before either if the
page doesn't use CSSOM to visit it. But we should figure out some
approach to fix it anyway.
* InspectorFontFace no longer shares the same rule object as CSSOM.
This isn't really a problem if the @font-face rule isn't very mutable.
Unless we want to make the rule returned from InspectorFontFace to be
mutable (i.e. via inspector), not using the same object probably isn't
too bad.
This patch switches the code we use to serialize stuff in FontFace and
CSSFontFaceRule, which leads to some failures in tests. Specifically,
the expected changes including:
* Value of font-family now can be serialized to identifier sequence like
font-family property. The old code always serializes it to string,
but it doesn't seem to have different requirement than the property.
Blink can serialize to identifier as well.
* Family name inside local() is also changed to use the same way as
family names elsewhere (i.e. can be identifier sequence). Blink has
the same behavior as the old code, but I don't think it's a big deal.
* The order of descriptors serialized gets changed. I don't think it
matters at all.
* Empty string as font-family via using string syntax is no longer
considered invalid for FontFace. I don't find it is mentioned anywhere
that it should be specifically treated invalid.
MozReview-Commit-ID: 32Fk3Fi9uTs
--HG--
extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
|
|
|
CASE_RULE(FONT_FACE, FontFace)
|
2018-04-05 01:41:28 +03:00
|
|
|
CASE_RULE(COUNTER_STYLE, CounterStyle)
|
2017-03-14 09:52:37 +03:00
|
|
|
#undef CASE_RULE
|
2018-01-11 11:17:56 +03:00
|
|
|
case CSSRuleBinding::KEYFRAME_RULE:
|
2017-05-19 09:12:34 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("keyframe rule cannot be here");
|
|
|
|
return nullptr;
|
2016-11-23 02:26:20 +03:00
|
|
|
default:
|
2017-02-14 04:19:54 +03:00
|
|
|
NS_WARNING("stylo: not implemented yet");
|
2016-11-24 08:28:28 +03:00
|
|
|
return nullptr;
|
2016-11-23 02:26:20 +03:00
|
|
|
}
|
|
|
|
ruleObj->SetStyleSheet(mStyleSheet);
|
2017-03-09 12:53:34 +03:00
|
|
|
ruleObj->SetParentRule(mParentRule);
|
2016-11-23 02:26:20 +03:00
|
|
|
rule = CastToUint(ruleObj.forget().take());
|
|
|
|
mRules[aIndex] = rule;
|
|
|
|
}
|
2016-11-29 14:59:55 +03:00
|
|
|
return CastToPtr(rule);
|
|
|
|
}
|
|
|
|
|
2017-01-13 18:41:03 +03:00
|
|
|
css::Rule*
|
2016-11-29 14:59:55 +03:00
|
|
|
ServoCSSRuleList::IndexedGetter(uint32_t aIndex, bool& aFound)
|
|
|
|
{
|
|
|
|
if (aIndex >= mRules.Length()) {
|
|
|
|
aFound = false;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
aFound = true;
|
2017-01-13 18:41:03 +03:00
|
|
|
return GetRule(aIndex);
|
2016-11-23 02:26:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Func>
|
|
|
|
void
|
|
|
|
ServoCSSRuleList::EnumerateInstantiatedRules(Func aCallback)
|
|
|
|
{
|
|
|
|
for (uintptr_t rule : mRules) {
|
|
|
|
if (rule > kMaxRuleType) {
|
|
|
|
aCallback(CastToPtr(rule));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-09 12:53:34 +03:00
|
|
|
static void
|
|
|
|
DropRule(already_AddRefed<css::Rule> aRule)
|
|
|
|
{
|
|
|
|
RefPtr<css::Rule> rule = aRule;
|
|
|
|
rule->SetStyleSheet(nullptr);
|
|
|
|
rule->SetParentRule(nullptr);
|
|
|
|
}
|
|
|
|
|
2016-11-23 02:26:20 +03:00
|
|
|
void
|
2017-03-09 12:53:34 +03:00
|
|
|
ServoCSSRuleList::DropAllRules()
|
2016-11-23 02:26:20 +03:00
|
|
|
{
|
|
|
|
EnumerateInstantiatedRules([](css::Rule* rule) {
|
2017-03-09 12:53:34 +03:00
|
|
|
DropRule(already_AddRefed<css::Rule>(rule));
|
2016-11-23 02:26:20 +03:00
|
|
|
});
|
2017-03-09 12:53:34 +03:00
|
|
|
mRules.Clear();
|
Bug 1345696 part 6 - Fix cycle collection for font-face rule. r=heycam,mccr8
Having Servo's FontFaceRule owning Gecko's nsCSSFontFaceRule object opens an
untracked edge, because we generally don't track the reference through Servo
objects, so there is a chance that nsCSSFontFaceRule can form a undroppable
reference cycle.
This patch adds a workaround that we track @font-face rule twice in CSS rule
list. This is not perfect, but the idea is that, if someone wants to put some
reference on the @font-face rule, the rule itself and its parent list should
have been constructed in the CSSOM tree. If they are not there, we are
probably safe from cycle reference.
For @font-face rule, that assumption isn't strictly true. Script can still
get a font-face rule via layout inspector's nsIDOMFontFace::rule. If some
script puts an object which references the stylesheet of the rule or any of
its parent rule / rule list into font-face rule's expando, we would leak
again... But as far as that is an internal interface, we are probably safe?
MozReview-Commit-ID: DDMJh3mxDCH
--HG--
extra : rebase_source : 646fcf076195151e6890ebffb7597e58c8a7d522
2017-03-28 08:11:44 +03:00
|
|
|
mRawRules = nullptr;
|
2017-03-09 12:53:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ServoCSSRuleList::DropReference()
|
|
|
|
{
|
|
|
|
mStyleSheet = nullptr;
|
|
|
|
mParentRule = nullptr;
|
|
|
|
DropAllRules();
|
2016-11-23 02:26:20 +03:00
|
|
|
}
|
|
|
|
|
2016-11-29 14:59:55 +03:00
|
|
|
nsresult
|
|
|
|
ServoCSSRuleList::InsertRule(const nsAString& aRule, uint32_t aIndex)
|
|
|
|
{
|
2017-04-03 13:04:32 +03:00
|
|
|
MOZ_ASSERT(mStyleSheet, "Caller must ensure that "
|
|
|
|
"the list is not unlinked from stylesheet");
|
2016-11-29 14:59:55 +03:00
|
|
|
NS_ConvertUTF16toUTF8 rule(aRule);
|
2017-03-09 12:53:34 +03:00
|
|
|
bool nested = !!mParentRule;
|
2017-04-03 13:04:32 +03:00
|
|
|
css::Loader* loader = nullptr;
|
|
|
|
if (nsIDocument* doc = mStyleSheet->GetAssociatedDocument()) {
|
|
|
|
loader = doc->CSSLoader();
|
|
|
|
}
|
2016-11-29 14:59:55 +03:00
|
|
|
uint16_t type;
|
2017-06-29 04:07:06 +03:00
|
|
|
nsresult rv = Servo_CssRules_InsertRule(mRawRules, mStyleSheet->RawContents(),
|
2017-04-03 13:04:32 +03:00
|
|
|
&rule, aIndex, nested,
|
|
|
|
loader, mStyleSheet, &type);
|
2017-05-30 04:10:25 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
mRules.InsertElementAt(aIndex, type);
|
2016-11-29 14:59:55 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
ServoCSSRuleList::DeleteRule(uint32_t aIndex)
|
|
|
|
{
|
|
|
|
nsresult rv = Servo_CssRules_DeleteRule(mRawRules, aIndex);
|
|
|
|
if (!NS_FAILED(rv)) {
|
2017-02-08 06:19:08 +03:00
|
|
|
uintptr_t rule = mRules[aIndex];
|
|
|
|
if (rule > kMaxRuleType) {
|
2017-03-09 12:53:34 +03:00
|
|
|
DropRule(already_AddRefed<css::Rule>(CastToPtr(rule)));
|
2017-02-08 06:19:08 +03:00
|
|
|
}
|
2016-11-29 14:59:55 +03:00
|
|
|
mRules.RemoveElementAt(aIndex);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2017-04-03 12:55:06 +03:00
|
|
|
uint16_t
|
2017-09-07 02:58:42 +03:00
|
|
|
ServoCSSRuleList::GetDOMCSSRuleType(uint32_t aIndex) const
|
2017-04-03 12:55:06 +03:00
|
|
|
{
|
|
|
|
uintptr_t rule = mRules[aIndex];
|
|
|
|
if (rule <= kMaxRuleType) {
|
|
|
|
return rule;
|
|
|
|
}
|
|
|
|
return CastToPtr(rule)->Type();
|
|
|
|
}
|
|
|
|
|
2016-11-23 02:26:20 +03:00
|
|
|
ServoCSSRuleList::~ServoCSSRuleList()
|
|
|
|
{
|
2017-11-29 02:06:51 +03:00
|
|
|
MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared");
|
|
|
|
MOZ_ASSERT(!mParentRule, "Backpointer should have been cleared");
|
2017-03-09 12:53:34 +03:00
|
|
|
DropAllRules();
|
2016-11-23 02:26:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace mozilla
|