Bug 1337258 - Support ServoStyleSheets in nsStyleSheetService. r=xidorn

MozReview-Commit-ID: 4vaHzDBZHFg

--HG--
extra : rebase_source : cb6e075e88c66a89bf6711db4ba913d62fd421ad
This commit is contained in:
Cameron McCormack 2017-02-21 10:42:27 +08:00
parent 154a17d29f
commit 6a09f48246
10 changed files with 156 additions and 134 deletions

View File

@ -2287,13 +2287,9 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
RemoveStyleSheetsFromStyleSets(mAdditionalSheets[eUserSheet], SheetType::User);
RemoveStyleSheetsFromStyleSets(mAdditionalSheets[eAuthorSheet], SheetType::Doc);
if (GetStyleBackendType() == StyleBackendType::Gecko) {
nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
if (sheetService) {
RemoveStyleSheetsFromStyleSets(*sheetService->AuthorStyleSheets(), SheetType::Doc);
}
} else {
NS_WARNING("stylo: nsStyleSheetService doesn't handle ServoStyleSheets yet");
if (nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance()) {
RemoveStyleSheetsFromStyleSets(
*sheetService->AuthorStyleSheets(GetStyleBackendType()), SheetType::Doc);
}
mStyleSetFilled = false;
@ -2360,23 +2356,19 @@ nsDocument::FillStyleSet(StyleSetHandle aStyleSet)
}
}
if (aStyleSet->IsGecko()) {
nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
if (sheetService) {
for (StyleSheet* sheet : *sheetService->AuthorStyleSheets()) {
aStyleSet->AppendStyleSheet(SheetType::Doc, sheet);
}
if (nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance()) {
nsTArray<RefPtr<StyleSheet>>& sheets =
*sheetService->AuthorStyleSheets(aStyleSet->BackendType());
for (StyleSheet* sheet : sheets) {
aStyleSet->AppendStyleSheet(SheetType::Doc, sheet);
}
}
// Iterate backwards to maintain order
for (StyleSheet* sheet : Reversed(mOnDemandBuiltInUASheets)) {
if (sheet->IsApplicable()) {
aStyleSet->PrependStyleSheet(SheetType::Agent, sheet);
}
// Iterate backwards to maintain order
for (StyleSheet* sheet : Reversed(mOnDemandBuiltInUASheets)) {
if (sheet->IsApplicable()) {
aStyleSet->PrependStyleSheet(SheetType::Agent, sheet);
}
} else {
NS_WARNING("stylo: Not yet checking nsStyleSheetService for Servo-backed "
"documents. See bug 1290224");
}
AppendSheetsToStyleSet(aStyleSet, mAdditionalSheets[eAgentSheet],

View File

@ -43,7 +43,8 @@ nsIDocument::FindDocStyleSheetInsertionPoint(
// doc sheet should end up before it.
if (sheetDocIndex < 0) {
if (sheetService) {
auto& authorSheets = *sheetService->AuthorStyleSheets();
auto& authorSheets =
*sheetService->AuthorStyleSheets(GetStyleBackendType());
if (authorSheets.IndexOf(sheetHandle) != authorSheets.NoIndex) {
break;
}

View File

@ -2119,20 +2119,27 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
if (sheetService) {
// This looks like a lot of work, but in a normal browser session we just
// send two loads.
//
// The URIs of the Gecko and Servo sheets should be the same, so it
// shouldn't matter which we look at. (The Servo sheets don't exist
// in non-MOZ-STYLO builds, though, so look at the Gecko ones.)
for (StyleSheet* sheet : *sheetService->AgentStyleSheets()) {
for (StyleSheet* sheet :
*sheetService->AgentStyleSheets(StyleBackendType::Gecko)) {
URIParams uri;
SerializeURI(sheet->GetSheetURI(), uri);
Unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AGENT_SHEET);
}
for (StyleSheet* sheet : *sheetService->UserStyleSheets()) {
for (StyleSheet* sheet :
*sheetService->UserStyleSheets(StyleBackendType::Gecko)) {
URIParams uri;
SerializeURI(sheet->GetSheetURI(), uri);
Unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::USER_SHEET);
}
for (StyleSheet* sheet : *sheetService->AuthorStyleSheets()) {
for (StyleSheet* sheet :
*sheetService->AuthorStyleSheets(StyleBackendType::Gecko)) {
URIParams uri;
SerializeURI(sheet->GetSheetURI(), uri);
Unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AUTHOR_SHEET);

View File

@ -1477,13 +1477,8 @@ PresShell::RemovePreferenceStyles()
}
void
PresShell::AddUserSheet(nsISupports* aSheet)
PresShell::AddUserSheet(StyleSheet* aSheet)
{
if (mStyleSet->IsServo()) {
NS_ERROR("stylo: nsStyleSheetService doesn't handle ServoStyleSheets yet");
return;
}
// Make sure this does what nsDocumentViewer::CreateStyleSet does wrt
// ordering. We want this new sheet to come after all the existing stylesheet
// service sheets, but before other user sheets; see nsIStyleSheetService.idl
@ -1495,7 +1490,8 @@ PresShell::AddUserSheet(nsISupports* aSheet)
mStyleSet->BeginUpdate();
nsStyleSheetService* sheetService = nsStyleSheetService::gInstance;
nsTArray<RefPtr<StyleSheet>>& userSheets = *sheetService->UserStyleSheets();
nsTArray<RefPtr<StyleSheet>>& userSheets =
*sheetService->UserStyleSheets(mStyleSet->BackendType());
// Iterate forwards when removing so the searches for RemoveStyleSheet are as
// short as possible.
for (StyleSheet* sheet : userSheets) {
@ -1514,54 +1510,34 @@ PresShell::AddUserSheet(nsISupports* aSheet)
}
void
PresShell::AddAgentSheet(nsISupports* aSheet)
PresShell::AddAgentSheet(StyleSheet* aSheet)
{
// Make sure this does what nsDocumentViewer::CreateStyleSet does
// wrt ordering.
// XXXheycam This needs to work with ServoStyleSheets too.
RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
if (!sheet) {
NS_ERROR("stylo: AddAgentSheet needs to support ServoStyleSheets");
return;
}
mStyleSet->AppendStyleSheet(SheetType::Agent, sheet);
mStyleSet->AppendStyleSheet(SheetType::Agent, aSheet);
RestyleForCSSRuleChanges();
}
void
PresShell::AddAuthorSheet(nsISupports* aSheet)
PresShell::AddAuthorSheet(StyleSheet* aSheet)
{
// XXXheycam This needs to work with ServoStyleSheets too.
RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
if (!sheet) {
NS_ERROR("stylo: AddAuthorSheet needs to support ServoStyleSheets");
return;
}
// Document specific "additional" Author sheets should be stronger than the
// ones added with the StyleSheetService.
StyleSheet* firstAuthorSheet =
mDocument->GetFirstAdditionalAuthorSheet();
if (firstAuthorSheet) {
mStyleSet->InsertStyleSheetBefore(SheetType::Doc, sheet, firstAuthorSheet);
mStyleSet->InsertStyleSheetBefore(SheetType::Doc, aSheet, firstAuthorSheet);
} else {
mStyleSet->AppendStyleSheet(SheetType::Doc, sheet);
mStyleSet->AppendStyleSheet(SheetType::Doc, aSheet);
}
RestyleForCSSRuleChanges();
}
void
PresShell::RemoveSheet(SheetType aType, nsISupports* aSheet)
PresShell::RemoveSheet(SheetType aType, StyleSheet* aSheet)
{
RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
if (!sheet) {
NS_ERROR("stylo: RemoveSheet needs to support ServoStyleSheets");
return;
}
mStyleSet->RemoveStyleSheet(aType, sheet);
mStyleSet->RemoveStyleSheet(aType, aSheet);
RestyleForCSSRuleChanges();
}

View File

@ -568,10 +568,10 @@ protected:
* Methods to handle changes to user and UA sheet lists that we get
* notified about.
*/
void AddUserSheet(nsISupports* aSheet);
void AddAgentSheet(nsISupports* aSheet);
void AddAuthorSheet(nsISupports* aSheet);
void RemoveSheet(mozilla::SheetType aType, nsISupports* aSheet);
void AddUserSheet(StyleSheet* aSheet);
void AddAgentSheet(StyleSheet* aSheet);
void AddAuthorSheet(StyleSheet* aSheet);
void RemoveSheet(mozilla::SheetType aType, StyleSheet* aSheet);
// Hide a view if it is a popup
void HideViewIfPopup(nsView* aView);

View File

@ -2403,19 +2403,15 @@ nsDocumentViewer::CreateStyleSet(nsIDocument* aDocument)
}
}
if (styleSet->IsGecko()) {
nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
if (sheetService) {
for (StyleSheet* sheet : *sheetService->AgentStyleSheets()) {
styleSet->AppendStyleSheet(SheetType::Agent, sheet);
}
for (StyleSheet* sheet : Reversed(*sheetService->UserStyleSheets())) {
styleSet->PrependStyleSheet(SheetType::User, sheet);
}
nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
if (sheetService) {
for (StyleSheet* sheet : *sheetService->AgentStyleSheets(backendType)) {
styleSet->AppendStyleSheet(SheetType::Agent, sheet);
}
for (StyleSheet* sheet :
Reversed(*sheetService->UserStyleSheets(backendType))) {
styleSet->PrependStyleSheet(SheetType::User, sheet);
}
} else {
NS_WARNING("stylo: Not yet checking nsStyleSheetService for Servo-backed "
"documents. See bug 1290224");
}
// Caller will handle calling EndUpdate, per contract.

View File

@ -82,16 +82,31 @@ nsStyleSheetService::RegisterFromEnumerator(nsICategoryManager *aManager,
}
}
static bool
SheetHasURI(StyleSheet* aSheet, nsIURI* aSheetURI)
{
MOZ_ASSERT(aSheetURI);
bool result;
nsIURI* uri = aSheet->GetSheetURI();
return uri &&
NS_SUCCEEDED(uri->Equals(aSheetURI, &result)) &&
result;
}
int32_t
nsStyleSheetService::FindSheetByURI(const nsTArray<RefPtr<StyleSheet>>& aSheets,
nsStyleSheetService::FindSheetByURI(uint32_t aSheetType,
nsIURI* aSheetURI)
{
for (int32_t i = aSheets.Length() - 1; i >= 0; i-- ) {
bool bEqual;
nsIURI* uri = aSheets[i]->GetSheetURI();
if (uri
&& NS_SUCCEEDED(uri->Equals(aSheetURI, &bEqual))
&& bEqual) {
MOZ_ASSERT(mGeckoSheets[aSheetType].Length() ==
mServoSheets[aSheetType].Length());
SheetArray& sheets = mGeckoSheets[aSheetType];
for (int32_t i = sheets.Length() - 1; i >= 0; i-- ) {
if (SheetHasURI(sheets[i], aSheetURI)) {
#ifdef MOZ_STYLO
MOZ_ASSERT(SheetHasURI(mServoSheets[aSheetType][i], aSheetURI));
#endif
return i;
}
}
@ -160,21 +175,22 @@ nsStyleSheetService::LoadAndRegisterSheet(nsIURI *aSheetURI,
rv = LoadAndRegisterSheetInternal(aSheetURI, aSheetType);
if (NS_SUCCEEDED(rv)) {
// We're guaranteed that the new sheet is the last sheet in
// mSheets[aSheetType]
// m{Gecko,Servo}Sheets[aSheetType]
// XXXheycam Once the nsStyleSheetService can hold ServoStyleSheets too,
// we'll need to include them in the notification.
RefPtr<StyleSheet> sheet = mSheets[aSheetType].LastElement();
if (sheet->IsGecko()) {
// Hold on to a copy of the registered PresShells.
nsTArray<nsCOMPtr<nsIPresShell>> toNotify(mPresShells);
for (nsIPresShell* presShell : toNotify) {
if (presShell->StyleSet() && presShell->StyleSet()->IsGecko()) {
presShell->NotifyStyleSheetServiceSheetAdded(sheet, aSheetType);
}
MOZ_ASSERT(mGeckoSheets[aSheetType].Length() ==
mServoSheets[aSheetType].Length());
RefPtr<StyleSheet> geckoSheet = mGeckoSheets[aSheetType].LastElement();
RefPtr<StyleSheet> servoSheet = mServoSheets[aSheetType].LastElement();
// Hold on to a copy of the registered PresShells.
nsTArray<nsCOMPtr<nsIPresShell>> toNotify(mPresShells);
for (nsIPresShell* presShell : toNotify) {
if (presShell->StyleSet()) {
StyleSheet* sheet = presShell->StyleSet()->IsGecko() ? geckoSheet
: servoSheet;
presShell->NotifyStyleSheetServiceSheetAdded(sheet, aSheetType);
}
} else {
NS_ERROR("stylo: can't notify observers of ServoStyleSheets");
}
if (XRE_IsParentProcess()) {
@ -196,6 +212,16 @@ nsStyleSheetService::LoadAndRegisterSheet(nsIURI *aSheetURI,
return rv;
}
static nsresult
LoadSheet(nsIURI* aURI,
css::SheetParsingMode aParsingMode,
StyleBackendType aType,
RefPtr<StyleSheet>* aResult)
{
RefPtr<css::Loader> loader = new css::Loader(aType);
return loader->LoadSheetSync(aURI, aParsingMode, true, aResult);
}
nsresult
nsStyleSheetService::LoadAndRegisterSheetInternal(nsIURI *aSheetURI,
uint32_t aSheetType)
@ -221,17 +247,25 @@ nsStyleSheetService::LoadAndRegisterSheetInternal(nsIURI *aSheetURI,
return NS_ERROR_INVALID_ARG;
}
// XXXheycam We'll need to load and register both a Gecko- and Servo-backed
// style sheet.
RefPtr<css::Loader> loader = new css::Loader(StyleBackendType::Gecko);
nsresult rv;
RefPtr<StyleSheet> sheet;
nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true, &sheet);
RefPtr<StyleSheet> geckoSheet;
RefPtr<StyleSheet> servoSheet;
rv = LoadSheet(aSheetURI, parsingMode, StyleBackendType::Gecko, &geckoSheet);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(geckoSheet);
mSheets[aSheetType].AppendElement(sheet);
#ifdef MOZ_STYLO
rv = LoadSheet(aSheetURI, parsingMode, StyleBackendType::Servo, &servoSheet);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(servoSheet);
#endif
return rv;
mGeckoSheets[aSheetType].AppendElement(geckoSheet);
mServoSheets[aSheetType].AppendElement(servoSheet);
return NS_OK;
}
NS_IMETHODIMP
@ -244,7 +278,7 @@ nsStyleSheetService::SheetRegistered(nsIURI *sheetURI,
NS_ENSURE_ARG_POINTER(sheetURI);
NS_PRECONDITION(_retval, "Null out param");
*_retval = (FindSheetByURI(mSheets[aSheetType], sheetURI) >= 0);
*_retval = (FindSheetByURI(aSheetType, sheetURI) >= 0);
return NS_OK;
}
@ -294,23 +328,26 @@ nsStyleSheetService::UnregisterSheet(nsIURI *aSheetURI, uint32_t aSheetType)
aSheetType == AUTHOR_SHEET);
NS_ENSURE_ARG_POINTER(aSheetURI);
int32_t foundIndex = FindSheetByURI(mSheets[aSheetType], aSheetURI);
NS_ENSURE_TRUE(foundIndex >= 0, NS_ERROR_INVALID_ARG);
RefPtr<StyleSheet> sheet = mSheets[aSheetType][foundIndex];
mSheets[aSheetType].RemoveElementAt(foundIndex);
MOZ_ASSERT(mGeckoSheets[aSheetType].Length() ==
mServoSheets[aSheetType].Length());
// XXXheycam Once the nsStyleSheetService can hold ServoStyleSheets too,
// we'll need to include them in the notification.
if (sheet->IsGecko()) {
// Hold on to a copy of the registered PresShells.
nsTArray<nsCOMPtr<nsIPresShell>> toNotify(mPresShells);
for (nsIPresShell* presShell : toNotify) {
if (presShell->StyleSet() && presShell->StyleSet()->IsGecko()) {
presShell->NotifyStyleSheetServiceSheetRemoved(sheet, aSheetType);
}
int32_t foundIndex = FindSheetByURI(aSheetType, aSheetURI);
NS_ENSURE_TRUE(foundIndex >= 0, NS_ERROR_INVALID_ARG);
RefPtr<StyleSheet> geckoSheet = mGeckoSheets[aSheetType][foundIndex];
RefPtr<StyleSheet> servoSheet = mServoSheets[aSheetType][foundIndex];
mGeckoSheets[aSheetType].RemoveElementAt(foundIndex);
mServoSheets[aSheetType].RemoveElementAt(foundIndex);
// Hold on to a copy of the registered PresShells.
nsTArray<nsCOMPtr<nsIPresShell>> toNotify(mPresShells);
for (nsIPresShell* presShell : toNotify) {
if (presShell->StyleSet()) {
StyleSheet* sheet = presShell->StyleSet()->IsGecko() ? geckoSheet
: servoSheet;
presShell->NotifyStyleSheetServiceSheetRemoved(sheet, aSheetType);
}
} else {
NS_ERROR("stylo: can't notify observers of ServoStyleSheets");
}
if (XRE_IsParentProcess()) {
@ -365,10 +402,14 @@ size_t
nsStyleSheetService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
for (auto& sheetArray : mSheets) {
n += sheetArray.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (StyleSheet* sheet : sheetArray) {
n += sheet->SizeOfIncludingThis(aMallocSizeOf);
for (auto* sheetArrays : { &mGeckoSheets, &mServoSheets }) {
for (auto& sheetArray : *sheetArrays) {
n += sheetArray.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (StyleSheet* sheet : sheetArray) {
if (sheet) {
n += sheet->SizeOfIncludingThis(aMallocSizeOf);
}
}
}
}
return n;

View File

@ -13,6 +13,7 @@
#include "nsCOMPtr.h"
#include "nsIMemoryReporter.h"
#include "nsIStyleSheetService.h"
#include "mozilla/Array.h"
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/StyleSheet.h"
@ -33,7 +34,9 @@ class nsStyleSheetService final
: public nsIStyleSheetService
, public nsIMemoryReporter
{
public:
public:
typedef nsTArray<RefPtr<mozilla::StyleSheet>> SheetArray;
nsStyleSheetService();
NS_DECL_ISUPPORTS
@ -42,17 +45,17 @@ class nsStyleSheetService final
nsresult Init();
nsTArray<RefPtr<mozilla::StyleSheet>>* AgentStyleSheets()
SheetArray* AgentStyleSheets(mozilla::StyleBackendType aType)
{
return &mSheets[AGENT_SHEET];
return &Sheets(aType)[AGENT_SHEET];
}
nsTArray<RefPtr<mozilla::StyleSheet>>* UserStyleSheets()
SheetArray* UserStyleSheets(mozilla::StyleBackendType aType)
{
return &mSheets[USER_SHEET];
return &Sheets(aType)[USER_SHEET];
}
nsTArray<RefPtr<mozilla::StyleSheet>>* AuthorStyleSheets()
SheetArray* AuthorStyleSheets(mozilla::StyleBackendType aType)
{
return &mSheets[AUTHOR_SHEET];
return &Sheets(aType)[AUTHOR_SHEET];
}
void RegisterPresShell(nsIPresShell* aPresShell);
@ -63,7 +66,7 @@ class nsStyleSheetService final
static nsStyleSheetService *GetInstance();
static nsStyleSheetService *gInstance;
private:
private:
~nsStyleSheetService();
void RegisterFromEnumerator(nsICategoryManager *aManager,
@ -71,15 +74,21 @@ class nsStyleSheetService final
nsISimpleEnumerator *aEnumerator,
uint32_t aSheetType);
int32_t FindSheetByURI(const nsTArray<RefPtr<mozilla::StyleSheet>>& aSheets,
nsIURI* aSheetURI);
int32_t FindSheetByURI(uint32_t aSheetType, nsIURI* aSheetURI);
// Like LoadAndRegisterSheet, but doesn't notify. If successful, the
// new sheet will be the last sheet in mSheets[aSheetType].
nsresult LoadAndRegisterSheetInternal(nsIURI *aSheetURI,
uint32_t aSheetType);
nsTArray<RefPtr<mozilla::StyleSheet>> mSheets[3];
mozilla::Array<SheetArray, 3>& Sheets(mozilla::StyleBackendType aType)
{
return aType == mozilla::StyleBackendType::Gecko ? mGeckoSheets
: mServoSheets;
}
mozilla::Array<SheetArray, 3> mGeckoSheets;
mozilla::Array<SheetArray, 3> mServoSheets;
// Registered PresShells that will be notified when sheets are added and
// removed from the style sheet service.

View File

@ -38,7 +38,6 @@ support-files =
[test_addSheet.html]
support-files = additional_sheets_helper.html
[test_additional_sheets.html]
skip-if = stylo # bug 1337258
support-files = additional_sheets_helper.html
[test_align_justify_computed_values.html]
[test_align_shorthand_serialization.html]

View File

@ -566,6 +566,7 @@ Any line which doesn't follow the format above would be ignored like comment.
* border-width/padding failure
* test_compute_data_with_start_struct.html `-width` [4]
* ... `padding-` [4]
* test_additional_sheets.html: one sub-test cascade order is wrong [1]
* test_selectors.html `:nth-child`: &lt;an+b&gt; parsing difference [14]
* test_selectors_on_anonymous_content.html: xbl and :nth-child [1]
* test_variables.html `url`: url in custom property [1]