2017-03-07 07:19:03 +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/. */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* internal interface representing CSS style rules that contain other
|
|
|
|
* rules, such as @media rules
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "mozilla/css/GroupRule.h"
|
|
|
|
|
|
|
|
#include "mozilla/dom/CSSRuleList.h"
|
|
|
|
|
|
|
|
using namespace mozilla::dom;
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace css {
|
|
|
|
|
2017-07-24 16:07:07 +03:00
|
|
|
GroupRule::GroupRule(already_AddRefed<ServoCssRules> aRules,
|
|
|
|
uint32_t aLineNumber, uint32_t aColumnNumber)
|
|
|
|
: Rule(aLineNumber, aColumnNumber)
|
2018-05-30 22:15:35 +03:00
|
|
|
, mRuleList(new ServoCSSRuleList(std::move(aRules), nullptr))
|
2017-03-09 14:02:26 +03:00
|
|
|
{
|
2018-03-28 04:25:36 +03:00
|
|
|
mRuleList->SetParentRule(this);
|
2017-03-09 14:02:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
GroupRule::~GroupRule()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!mSheet, "SetStyleSheet should have been called");
|
2018-03-28 04:25:36 +03:00
|
|
|
if (mRuleList) {
|
|
|
|
mRuleList->DropReference();
|
|
|
|
}
|
2017-03-09 14:02:26 +03:00
|
|
|
}
|
|
|
|
|
2017-03-07 07:19:03 +03:00
|
|
|
NS_IMPL_ADDREF_INHERITED(GroupRule, Rule)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(GroupRule, Rule)
|
|
|
|
|
2017-08-30 02:02:48 +03:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GroupRule)
|
2017-03-07 07:19:03 +03:00
|
|
|
NS_INTERFACE_MAP_END_INHERITING(Rule)
|
|
|
|
|
|
|
|
bool
|
|
|
|
GroupRule::IsCCLeaf() const
|
|
|
|
{
|
|
|
|
// Let's not worry for now about sorting out whether we're a leaf or not.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(GroupRule)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(GroupRule, Rule)
|
2018-03-28 04:25:36 +03:00
|
|
|
if (tmp->mRuleList) {
|
|
|
|
tmp->mRuleList->SetParentRule(nullptr);
|
|
|
|
// If tmp does not have a stylesheet, neither do its descendants.
|
|
|
|
// In that case, don't try to null out their stylesheet, to avoid
|
|
|
|
// O(N^2) behavior in depth of group rule nesting. But if tmp
|
|
|
|
// _does_ have a stylesheet (which can happen if it gets unlinked
|
|
|
|
// earlier than its owning stylesheet), then we need to null out the
|
|
|
|
// stylesheet pointer on descendants now, before we clear mRuleList.
|
|
|
|
if (tmp->GetStyleSheet()) {
|
|
|
|
tmp->mRuleList->SetStyleSheet(nullptr);
|
|
|
|
}
|
|
|
|
tmp->mRuleList->DropReference();
|
|
|
|
tmp->mRuleList = nullptr;
|
2017-03-07 07:19:03 +03:00
|
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GroupRule, Rule)
|
2018-03-28 04:25:36 +03:00
|
|
|
ImplCycleCollectionTraverse(cb, tmp->mRuleList, "mRuleList");
|
2017-03-07 07:19:03 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
2018-03-28 04:25:36 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
void
|
|
|
|
GroupRule::List(FILE* out, int32_t aIndent) const
|
|
|
|
{
|
|
|
|
// TODO list something reasonable?
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-03-07 07:19:03 +03:00
|
|
|
/* virtual */ void
|
|
|
|
GroupRule::SetStyleSheet(StyleSheet* aSheet)
|
|
|
|
{
|
|
|
|
// Don't set the sheet on the kids if it's already the same as the sheet we
|
|
|
|
// already have. This is needed to avoid O(N^2) behavior in group nesting
|
|
|
|
// depth when seting the sheet to null during unlink, if we happen to unlin in
|
|
|
|
// order from most nested rule up to least nested rule.
|
|
|
|
if (aSheet != GetStyleSheet()) {
|
2018-03-28 04:25:36 +03:00
|
|
|
if (mRuleList) {
|
|
|
|
mRuleList->SetStyleSheet(aSheet);
|
|
|
|
}
|
2017-03-07 07:19:03 +03:00
|
|
|
Rule::SetStyleSheet(aSheet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
GroupRule::InsertRule(const nsAString& aRule, uint32_t aIndex, ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
StyleSheet* sheet = GetStyleSheet();
|
|
|
|
if (NS_WARN_IF(!sheet)) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-09 14:02:26 +03:00
|
|
|
uint32_t count = StyleRuleCount();
|
|
|
|
if (aIndex > count) {
|
2017-03-07 07:19:03 +03:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-09 14:02:26 +03:00
|
|
|
NS_ASSERTION(count <= INT32_MAX, "Too many style rules!");
|
2017-03-07 07:19:03 +03:00
|
|
|
|
2017-03-08 10:04:15 +03:00
|
|
|
nsresult rv = sheet->InsertRuleIntoGroup(aRule, this, aIndex);
|
2017-03-07 07:19:03 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRv.Throw(rv);
|
|
|
|
return 0;
|
|
|
|
}
|
2017-03-08 09:11:42 +03:00
|
|
|
return aIndex;
|
2017-03-07 07:19:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GroupRule::DeleteRule(uint32_t aIndex, ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
StyleSheet* sheet = GetStyleSheet();
|
|
|
|
if (NS_WARN_IF(!sheet)) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-09 14:02:26 +03:00
|
|
|
uint32_t count = StyleRuleCount();
|
|
|
|
if (aIndex >= count) {
|
2017-03-07 07:19:03 +03:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-09 14:02:26 +03:00
|
|
|
NS_ASSERTION(count <= INT32_MAX, "Too many style rules!");
|
2017-03-07 07:19:03 +03:00
|
|
|
|
2017-03-08 10:04:15 +03:00
|
|
|
nsresult rv = sheet->DeleteRuleFromGroup(this, aIndex);
|
2017-03-07 07:19:03 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRv.Throw(rv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-28 04:25:36 +03:00
|
|
|
size_t
|
|
|
|
GroupRule::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
|
|
|
{
|
|
|
|
// TODO how to implement?
|
|
|
|
return 0;
|
|
|
|
}
|
2017-03-07 07:19:03 +03:00
|
|
|
|
|
|
|
} // namespace css
|
2017-03-09 14:02:26 +03:00
|
|
|
} // namespace mozilla
|