forked from mirrors/gecko-dev
		
	This commit adds class ServoStyleRuleMap which caches the mapping from raw Servo style rule to Gecko's wrapper object. It is a per-document object, and is added as an observer of document when constructed, so that it updates data inside when possible. For safety consideration, this change also makes ServoStyleRule support weak pointer, and use weak pointer inside ServoStyleRuleMap. MozReview-Commit-ID: YxBnZ88tjf --HG-- extra : source : 0f2bc306d27b8ab22f1aa08aa9d44af0dba4694d
		
			
				
	
	
		
			182 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- 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 "mozilla/ServoStyleRuleMap.h"
 | 
						|
 | 
						|
#include "mozilla/css/GroupRule.h"
 | 
						|
#include "mozilla/IntegerRange.h"
 | 
						|
#include "mozilla/ServoStyleRule.h"
 | 
						|
#include "mozilla/ServoStyleSet.h"
 | 
						|
#include "mozilla/ServoImportRule.h"
 | 
						|
 | 
						|
#include "nsDocument.h"
 | 
						|
#include "nsStyleSheetService.h"
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
 | 
						|
ServoStyleRuleMap::ServoStyleRuleMap(ServoStyleSet* aStyleSet)
 | 
						|
  : mStyleSet(aStyleSet)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
ServoStyleRuleMap::~ServoStyleRuleMap()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
NS_IMPL_ISUPPORTS(ServoStyleRuleMap, nsIDocumentObserver, nsICSSLoaderObserver)
 | 
						|
 | 
						|
void
 | 
						|
ServoStyleRuleMap::EnsureTable()
 | 
						|
{
 | 
						|
  if (!IsEmpty()) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  mStyleSet->EnumerateStyleSheetArrays(
 | 
						|
    [this](const nsTArray<RefPtr<ServoStyleSheet>>& aArray) {
 | 
						|
      for (auto& sheet : aArray) {
 | 
						|
        FillTableFromStyleSheet(sheet);
 | 
						|
      }
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ServoStyleRuleMap::StyleSheetAdded(StyleSheet* aStyleSheet,
 | 
						|
                                   bool aDocumentSheet)
 | 
						|
{
 | 
						|
  if (!IsEmpty()) {
 | 
						|
    FillTableFromStyleSheet(aStyleSheet->AsServo());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ServoStyleRuleMap::StyleSheetRemoved(StyleSheet* aStyleSheet,
 | 
						|
                                     bool aDocumentSheet)
 | 
						|
{
 | 
						|
  // Invalidate all data inside. This isn't strictly necessary since
 | 
						|
  // we should always get update from document before new queries come.
 | 
						|
  // But it is probably still safer if we try to avoid having invalid
 | 
						|
  // pointers inside. Also if the document keep adding and removing
 | 
						|
  // stylesheets, this would also prevent us from infinitely growing
 | 
						|
  // memory usage.
 | 
						|
  mTable.Clear();
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ServoStyleRuleMap::StyleSheetApplicableStateChanged(StyleSheet* aStyleSheet)
 | 
						|
{
 | 
						|
  // We don't care if the stylesheet is disabled. Not removing no longer
 | 
						|
  // applicable stylesheets wouldn't make anything wrong.
 | 
						|
  if (!IsEmpty() && aStyleSheet->IsApplicable()) {
 | 
						|
    FillTableFromStyleSheet(aStyleSheet->AsServo());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ServoStyleRuleMap::StyleRuleAdded(StyleSheet* aStyleSheet,
 | 
						|
                                  css::Rule* aStyleRule)
 | 
						|
{
 | 
						|
  if (!IsEmpty()) {
 | 
						|
    FillTableFromRule(aStyleRule);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ServoStyleRuleMap::StyleRuleRemoved(StyleSheet* aStyleSheet,
 | 
						|
                                    css::Rule* aStyleRule)
 | 
						|
{
 | 
						|
  if (IsEmpty()) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (aStyleRule->Type()) {
 | 
						|
    case nsIDOMCSSRule::STYLE_RULE: {
 | 
						|
      auto rule = static_cast<ServoStyleRule*>(aStyleRule);
 | 
						|
      mTable.Remove(rule->Raw());
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    case nsIDOMCSSRule::IMPORT_RULE:
 | 
						|
    case nsIDOMCSSRule::MEDIA_RULE:
 | 
						|
    case nsIDOMCSSRule::SUPPORTS_RULE:
 | 
						|
    case nsIDOMCSSRule::DOCUMENT_RULE: {
 | 
						|
      // See the comment in StyleSheetRemoved.
 | 
						|
      mTable.Clear();
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    case nsIDOMCSSRule::FONT_FACE_RULE:
 | 
						|
    case nsIDOMCSSRule::PAGE_RULE:
 | 
						|
    case nsIDOMCSSRule::KEYFRAMES_RULE:
 | 
						|
    case nsIDOMCSSRule::KEYFRAME_RULE:
 | 
						|
    case nsIDOMCSSRule::NAMESPACE_RULE:
 | 
						|
    case nsIDOMCSSRule::COUNTER_STYLE_RULE:
 | 
						|
    case nsIDOMCSSRule::FONT_FEATURE_VALUES_RULE:
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      MOZ_ASSERT_UNREACHABLE("Unhandled rule");
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
ServoStyleRuleMap::StyleSheetLoaded(StyleSheet* aSheet,
 | 
						|
                                    bool aWasAlternate,
 | 
						|
                                    nsresult aStatus)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(aSheet->IsServo());
 | 
						|
  if (!IsEmpty()) {
 | 
						|
    FillTableFromStyleSheet(aSheet->AsServo());
 | 
						|
  }
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
size_t
 | 
						|
ServoStyleRuleMap::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 | 
						|
{
 | 
						|
  size_t n = aMallocSizeOf(this);
 | 
						|
  n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
 | 
						|
  return n;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ServoStyleRuleMap::FillTableFromRule(css::Rule* aRule)
 | 
						|
{
 | 
						|
  switch (aRule->Type()) {
 | 
						|
    case nsIDOMCSSRule::STYLE_RULE: {
 | 
						|
      auto rule = static_cast<ServoStyleRule*>(aRule);
 | 
						|
      mTable.Put(rule->Raw(), rule);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    case nsIDOMCSSRule::MEDIA_RULE:
 | 
						|
    case nsIDOMCSSRule::SUPPORTS_RULE:
 | 
						|
    case nsIDOMCSSRule::DOCUMENT_RULE: {
 | 
						|
      auto rule = static_cast<css::GroupRule*>(aRule);
 | 
						|
      auto ruleList = static_cast<ServoCSSRuleList*>(rule->CssRules());
 | 
						|
      FillTableFromRuleList(ruleList);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    case nsIDOMCSSRule::IMPORT_RULE: {
 | 
						|
      auto rule = static_cast<ServoImportRule*>(aRule);
 | 
						|
      FillTableFromStyleSheet(rule->GetStyleSheet()->AsServo());
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ServoStyleRuleMap::FillTableFromRuleList(ServoCSSRuleList* aRuleList)
 | 
						|
{
 | 
						|
  for (uint32_t i : IntegerRange(aRuleList->Length())) {
 | 
						|
    FillTableFromRule(aRuleList->GetRule(i));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ServoStyleRuleMap::FillTableFromStyleSheet(ServoStyleSheet* aSheet)
 | 
						|
{
 | 
						|
  if (aSheet->IsComplete()) {
 | 
						|
    FillTableFromRuleList(aSheet->GetCssRulesInternal());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
} // namespace mozilla
 |