summaryrefslogtreecommitdiffstats
path: root/layout/style
diff options
context:
space:
mode:
Diffstat (limited to 'layout/style')
-rw-r--r--layout/style/FontFaceSet.cpp12
-rw-r--r--layout/style/nsCSSKeywordList.h2
-rw-r--r--layout/style/nsCSSParser.cpp7
-rw-r--r--layout/style/nsCSSProps.cpp2
-rw-r--r--layout/style/nsCSSPseudoElements.h3
-rw-r--r--layout/style/nsCSSRuleProcessor.cpp10
-rw-r--r--layout/style/nsLayoutStylesheetCache.cpp293
-rw-r--r--layout/style/nsMediaFeatures.cpp18
-rw-r--r--layout/style/nsRuleNode.cpp3
-rw-r--r--layout/style/nsStyleStruct.cpp23
-rw-r--r--layout/style/nsStyleStruct.h11
-rw-r--r--layout/style/res/forms.css5
-rw-r--r--layout/style/res/html.css5
-rw-r--r--layout/style/test/chrome/bug418986-2.js2
-rw-r--r--layout/style/test/mochitest.ini1
-rw-r--r--layout/style/test/property_database.js14
-rw-r--r--layout/style/test/test_dynamic_change_causing_reflow.html107
-rw-r--r--layout/style/test/test_media_queries.html7
-rw-r--r--layout/style/test/test_viewport_scrollbar_causing_reflow.html125
19 files changed, 306 insertions, 344 deletions
diff --git a/layout/style/FontFaceSet.cpp b/layout/style/FontFaceSet.cpp
index 59626fba4..550a7d71a 100644
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -343,17 +343,7 @@ FontFaceSet::Load(JSContext* aCx,
}
}
- nsIGlobalObject* globalObject = GetParentObject();
- if (!globalObject) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
-
- JS::Rooted<JSObject*> jsGlobal(aCx, globalObject->GetGlobalJSObject());
- GlobalObject global(aCx, jsGlobal);
-
- RefPtr<Promise> result = Promise::All(global, promises, aRv);
- return result.forget();
+ return Promise::All(aCx, promises, aRv);
}
bool
diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h
index febdd32c6..933ff6e7b 100644
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -742,6 +742,8 @@ CSS_KEY(button-focus, button_focus)
CSS_KEY(-moz-win-media-toolbox, _moz_win_media_toolbox)
CSS_KEY(-moz-win-communications-toolbox, _moz_win_communications_toolbox)
CSS_KEY(-moz-win-browsertabbar-toolbox, _moz_win_browsertabbar_toolbox)
+CSS_KEY(-moz-win-accentcolor, _moz_win_accentcolor)
+CSS_KEY(-moz-win-accentcolortext, _moz_win_accentcolortext)
CSS_KEY(-moz-win-mediatext, _moz_win_mediatext)
CSS_KEY(-moz-win-communicationstext, _moz_win_communicationstext)
CSS_KEY(-moz-win-glass, _moz_win_glass)
diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp
index 1108ce5b5..b361cf0c2 100644
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -8918,6 +8918,10 @@ CSSParserImpl::ParseGridTrackSize(nsCSSValue& aValue,
return CSSParseResult::NotFound;
}
if (mToken.mIdent.LowerCaseEqualsLiteral("fit-content")) {
+ if (requireFixedSize) {
+ UngetToken();
+ return CSSParseResult::Error;
+ }
nsCSSValue::Array* func = aValue.InitFunction(eCSSKeyword_fit_content, 1);
if (ParseGridTrackBreadth(func->Item(1)) == CSSParseResult::Ok &&
func->Item(1).IsLengthPercentCalcUnit() &&
@@ -10400,7 +10404,8 @@ CSSParserImpl::ParseLinearGradient(nsCSSValue& aValue,
UngetToken();
// <angle> ,
- if (ParseSingleTokenVariant(cssGradient->mAngle, VARIANT_ANGLE, nullptr) &&
+ if (ParseSingleTokenVariant(cssGradient->mAngle,
+ VARIANT_ANGLE_OR_ZERO, nullptr) &&
!ExpectSymbol(',', true)) {
SkipUntil(')');
return false;
diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp
index ec28d06f8..f3a7f898d 100644
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1174,6 +1174,8 @@ const KTableEntry nsCSSProps::kColorKTable[] = {
{ eCSSKeyword__moz_oddtreerow, LookAndFeel::eColorID__moz_oddtreerow },
{ eCSSKeyword__moz_visitedhyperlinktext, NS_COLOR_MOZ_VISITEDHYPERLINKTEXT },
{ eCSSKeyword_currentcolor, NS_COLOR_CURRENTCOLOR },
+ { eCSSKeyword__moz_win_accentcolor, LookAndFeel::eColorID__moz_win_accentcolor },
+ { eCSSKeyword__moz_win_accentcolortext, LookAndFeel::eColorID__moz_win_accentcolortext },
{ eCSSKeyword__moz_win_mediatext, LookAndFeel::eColorID__moz_win_mediatext },
{ eCSSKeyword__moz_win_communicationstext, LookAndFeel::eColorID__moz_win_communicationstext },
{ eCSSKeyword__moz_nativehyperlinktext, LookAndFeel::eColorID__moz_nativehyperlinktext },
diff --git a/layout/style/nsCSSPseudoElements.h b/layout/style/nsCSSPseudoElements.h
index 657ef663e..eaf8d966b 100644
--- a/layout/style/nsCSSPseudoElements.h
+++ b/layout/style/nsCSSPseudoElements.h
@@ -111,8 +111,7 @@ private:
// which is a general gcc bug that we seem to have hit only on Android/x86.
#if defined(ANDROID) && defined(__i386__) && defined(__GNUC__) && \
!defined(__clang__)
-#if (MOZ_GCC_VERSION_AT_LEAST(4,8,0) && MOZ_GCC_VERSION_AT_MOST(4,8,4)) || \
- (MOZ_GCC_VERSION_AT_LEAST(4,9,0) && MOZ_GCC_VERSION_AT_MOST(4,9,2))
+#if (MOZ_GCC_VERSION_AT_LEAST(4,9,0) && MOZ_GCC_VERSION_AT_MOST(4,9,2))
__attribute__((noinline))
#endif
#endif
diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp
index 07a4ef57b..8760a330e 100644
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -1127,6 +1127,16 @@ InitSystemMetrics()
sSystemMetrics->AppendElement(nsGkAtoms::mac_yosemite_theme);
}
+ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_WindowsAccentColorApplies, &metricResult);
+ if (NS_SUCCEEDED(rv) && metricResult) {
+ sSystemMetrics->AppendElement(nsGkAtoms::windows_accent_color_applies);
+ }
+
+ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_WindowsAccentColorIsDark, &metricResult);
+ if (NS_SUCCEEDED(rv) && metricResult) {
+ sSystemMetrics->AppendElement(nsGkAtoms::windows_accent_color_is_dark);
+ }
+
rv = LookAndFeel::GetInt(LookAndFeel::eIntID_DWMCompositor, &metricResult);
if (NS_SUCCEEDED(rv) && metricResult) {
sSystemMetrics->AppendElement(nsGkAtoms::windows_compositor);
diff --git a/layout/style/nsLayoutStylesheetCache.cpp b/layout/style/nsLayoutStylesheetCache.cpp
index f8aea5541..e8c6d09d7 100644
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -23,19 +23,6 @@
#include "nsPrintfCString.h"
#include "nsXULAppAPI.h"
-// Includes for the crash report annotation in ErrorLoadingSheet.
-#ifdef MOZ_CRASHREPORTER
-#include "mozilla/Omnijar.h"
-#include "nsDirectoryService.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsExceptionHandler.h"
-#include "nsIChromeRegistry.h"
-#include "nsISimpleEnumerator.h"
-#include "nsISubstitutingProtocolHandler.h"
-#include "zlib.h"
-#include "nsZipArchive.h"
-#endif
-
using namespace mozilla;
using namespace mozilla::css;
@@ -463,280 +450,6 @@ nsLayoutStylesheetCache::LoadSheetFile(nsIFile* aFile,
LoadSheet(uri, aSheet, aParsingMode, aFailureAction);
}
-#ifdef MOZ_CRASHREPORTER
-static inline nsresult
-ComputeCRC32(nsIFile* aFile, uint32_t* aResult)
-{
- PRFileDesc* fd;
- nsresult rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t crc = crc32(0, nullptr, 0);
-
- unsigned char buf[512];
- int32_t n;
- while ((n = PR_Read(fd, buf, sizeof(buf))) > 0) {
- crc = crc32(crc, buf, n);
- }
- PR_Close(fd);
-
- if (n < 0) {
- return NS_ERROR_FAILURE;
- }
-
- *aResult = crc;
- return NS_OK;
-}
-
-static void
-ListInterestingFiles(nsString& aAnnotation, nsIFile* aFile,
- const nsTArray<nsString>& aInterestingFilenames)
-{
- nsString filename;
- aFile->GetLeafName(filename);
- for (const nsString& interestingFilename : aInterestingFilenames) {
- if (interestingFilename == filename) {
- nsString path;
- aFile->GetPath(path);
- aAnnotation.AppendLiteral(" ");
- aAnnotation.Append(path);
- aAnnotation.AppendLiteral(" (");
- int64_t size;
- if (NS_SUCCEEDED(aFile->GetFileSize(&size))) {
- aAnnotation.AppendPrintf("%ld", size);
- } else {
- aAnnotation.AppendLiteral("???");
- }
- aAnnotation.AppendLiteral(" bytes, crc32 = ");
- uint32_t crc;
- nsresult rv = ComputeCRC32(aFile, &crc);
- if (NS_SUCCEEDED(rv)) {
- aAnnotation.AppendPrintf("0x%08x)\n", crc);
- } else {
- aAnnotation.AppendPrintf("error 0x%08x)\n", uint32_t(rv));
- }
- return;
- }
- }
-
- bool isDir = false;
- aFile->IsDirectory(&isDir);
-
- if (!isDir) {
- return;
- }
-
- nsCOMPtr<nsISimpleEnumerator> entries;
- if (NS_FAILED(aFile->GetDirectoryEntries(getter_AddRefs(entries)))) {
- aAnnotation.AppendLiteral(" (failed to enumerated directory)\n");
- return;
- }
-
- for (;;) {
- bool hasMore = false;
- if (NS_FAILED(entries->HasMoreElements(&hasMore))) {
- aAnnotation.AppendLiteral(" (failed during directory enumeration)\n");
- return;
- }
- if (!hasMore) {
- break;
- }
-
- nsCOMPtr<nsISupports> entry;
- if (NS_FAILED(entries->GetNext(getter_AddRefs(entry)))) {
- aAnnotation.AppendLiteral(" (failed during directory enumeration)\n");
- return;
- }
-
- nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
- if (file) {
- ListInterestingFiles(aAnnotation, file, aInterestingFilenames);
- }
- }
-}
-
-// Generate a crash report annotation to help debug issues with style
-// sheets failing to load (bug 1194856).
-static void
-AnnotateCrashReport(nsIURI* aURI)
-{
- nsAutoCString spec;
- nsAutoCString scheme;
- nsDependentCSubstring filename;
- if (aURI) {
- spec = aURI->GetSpecOrDefault();
- aURI->GetScheme(scheme);
- int32_t i = spec.RFindChar('/');
- if (i != -1) {
- filename.Rebind(spec, i + 1);
- }
- }
-
- nsString annotation;
-
- // The URL of the sheet that failed to load.
- annotation.AppendLiteral("Error loading sheet: ");
- annotation.Append(NS_ConvertUTF8toUTF16(spec).get());
- annotation.Append('\n');
-
- annotation.AppendLiteral("NS_ERROR_FILE_CORRUPTION reason: ");
- if (nsZipArchive::sFileCorruptedReason) {
- annotation.Append(NS_ConvertUTF8toUTF16(nsZipArchive::sFileCorruptedReason).get());
- annotation.Append('\n');
- } else {
- annotation.AppendLiteral("(none)\n");
- }
-
- // The jar: or file: URL that the sheet's resource: or chrome: URL
- // resolves to.
- if (scheme.EqualsLiteral("resource")) {
- annotation.AppendLiteral("Real location: ");
- nsCOMPtr<nsISubstitutingProtocolHandler> handler;
- nsCOMPtr<nsIIOService> io(do_GetIOService());
- if (io) {
- nsCOMPtr<nsIProtocolHandler> ph;
- io->GetProtocolHandler(scheme.get(), getter_AddRefs(ph));
- if (ph) {
- handler = do_QueryInterface(ph);
- }
- }
- if (!handler) {
- annotation.AppendLiteral("(ResolveURI failed)\n");
- } else {
- nsAutoCString resolvedSpec;
- handler->ResolveURI(aURI, resolvedSpec);
- annotation.Append(NS_ConvertUTF8toUTF16(resolvedSpec));
- annotation.Append('\n');
- }
- } else if (scheme.EqualsLiteral("chrome")) {
- annotation.AppendLiteral("Real location: ");
- nsCOMPtr<nsIChromeRegistry> reg =
- mozilla::services::GetChromeRegistryService();
- if (!reg) {
- annotation.AppendLiteral("(no chrome registry)\n");
- } else {
- nsCOMPtr<nsIURI> resolvedURI;
- reg->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI));
- if (!resolvedURI) {
- annotation.AppendLiteral("(ConvertChromeURL failed)\n");
- } else {
- annotation.Append(
- NS_ConvertUTF8toUTF16(resolvedURI->GetSpecOrDefault()));
- annotation.Append('\n');
- }
- }
- }
-
- nsTArray<nsString> interestingFiles;
- interestingFiles.AppendElement(NS_LITERAL_STRING("chrome.manifest"));
- interestingFiles.AppendElement(NS_LITERAL_STRING("omni.ja"));
- interestingFiles.AppendElement(NS_ConvertUTF8toUTF16(filename));
-
- annotation.AppendLiteral("GRE directory: ");
- nsCOMPtr<nsIFile> file;
- nsDirectoryService::gService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile),
- getter_AddRefs(file));
- if (file) {
- // The Firefox installation directory.
- nsString path;
- file->GetPath(path);
- annotation.Append(path);
- annotation.Append('\n');
-
- // List interesting files -- any chrome.manifest or omni.ja file or any file
- // whose name is the sheet's filename -- under the Firefox installation
- // directory.
- annotation.AppendLiteral("Interesting files in the GRE directory:\n");
- ListInterestingFiles(annotation, file, interestingFiles);
-
- // If the Firefox installation directory has a chrome.manifest file, let's
- // see what's in it.
- file->Append(NS_LITERAL_STRING("chrome.manifest"));
- bool exists = false;
- file->Exists(&exists);
- if (exists) {
- annotation.AppendLiteral("Contents of chrome.manifest:\n[[[\n");
- PRFileDesc* fd;
- if (NS_SUCCEEDED(file->OpenNSPRFileDesc(PR_RDONLY, 0, &fd))) {
- nsCString contents;
- char buf[512];
- int32_t n;
- while ((n = PR_Read(fd, buf, sizeof(buf))) > 0) {
- contents.Append(buf, n);
- }
- if (n < 0) {
- annotation.AppendLiteral(" (error while reading)\n");
- } else {
- annotation.Append(NS_ConvertUTF8toUTF16(contents));
- }
- PR_Close(fd);
- }
- annotation.AppendLiteral("]]]\n");
- }
- } else {
- annotation.AppendLiteral("(none)\n");
- }
-
- // The jar: or file: URL prefix that chrome: and resource: URLs get translated
- // to.
- annotation.AppendLiteral("GRE omnijar URI string: ");
- nsCString uri;
- nsresult rv = Omnijar::GetURIString(Omnijar::GRE, uri);
- if (NS_FAILED(rv)) {
- annotation.AppendLiteral("(failed)\n");
- } else {
- annotation.Append(NS_ConvertUTF8toUTF16(uri));
- annotation.Append('\n');
- }
-
- RefPtr<nsZipArchive> zip = Omnijar::GetReader(Omnijar::GRE);
- if (zip) {
- // List interesting files in the GRE omnijar.
- annotation.AppendLiteral("Interesting files in the GRE omnijar:\n");
- nsZipFind* find;
- rv = zip->FindInit(nullptr, &find);
- if (NS_FAILED(rv)) {
- annotation.AppendPrintf(" (FindInit failed with 0x%08x)\n", rv);
- } else if (!find) {
- annotation.AppendLiteral(" (FindInit returned null)\n");
- } else {
- const char* result;
- uint16_t len;
- while (NS_SUCCEEDED(find->FindNext(&result, &len))) {
- nsCString itemPathname;
- nsString itemFilename;
- itemPathname.Append(result, len);
- int32_t i = itemPathname.RFindChar('/');
- if (i != -1) {
- itemFilename = NS_ConvertUTF8toUTF16(Substring(itemPathname, i + 1));
- }
- for (const nsString& interestingFile : interestingFiles) {
- if (interestingFile == itemFilename) {
- annotation.AppendLiteral(" ");
- annotation.Append(NS_ConvertUTF8toUTF16(itemPathname));
- nsZipItem* item = zip->GetItem(itemPathname.get());
- if (!item) {
- annotation.AppendLiteral(" (GetItem failed)\n");
- } else {
- annotation.AppendPrintf(" (%d bytes, crc32 = 0x%08x)\n",
- item->RealSize(),
- item->CRC32());
- }
- break;
- }
- }
- }
- delete find;
- }
- } else {
- annotation.AppendLiteral("No GRE omnijar\n");
- }
-
- CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("SheetLoadFailure"),
- NS_ConvertUTF16toUTF8(annotation));
-}
-#endif
-
static void
ErrorLoadingSheet(nsIURI* aURI, const char* aMsg, FailureAction aFailureAction)
{
@@ -751,9 +464,6 @@ ErrorLoadingSheet(nsIURI* aURI, const char* aMsg, FailureAction aFailureAction)
}
}
-#ifdef MOZ_CRASHREPORTER
- AnnotateCrashReport(aURI);
-#endif
NS_RUNTIMEABORT(errorMessage.get());
}
@@ -780,9 +490,6 @@ nsLayoutStylesheetCache::LoadSheet(nsIURI* aURI,
}
}
-#ifdef MOZ_CRASHREPORTER
- nsZipArchive::sFileCorruptedReason = nullptr;
-#endif
nsresult rv = loader->LoadSheetSync(aURI, aParsingMode, true, aSheet);
if (NS_FAILED(rv)) {
ErrorLoadingSheet(aURI,
diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp
index c07a4123e..5a54d5455 100644
--- a/layout/style/nsMediaFeatures.cpp
+++ b/layout/style/nsMediaFeatures.cpp
@@ -70,8 +70,6 @@ struct OperatingSystemVersionInfo {
// Os version identities used in the -moz-os-version media query.
const OperatingSystemVersionInfo osVersionStrings[] = {
- { LookAndFeel::eOperatingSystemVersion_WindowsXP, L"windows-xp" },
- { LookAndFeel::eOperatingSystemVersion_WindowsVista, L"windows-vista" },
{ LookAndFeel::eOperatingSystemVersion_Windows7, L"windows-win7" },
{ LookAndFeel::eOperatingSystemVersion_Windows8, L"windows-win8" },
{ LookAndFeel::eOperatingSystemVersion_Windows10, L"windows-win10" }
@@ -716,6 +714,22 @@ nsMediaFeatures::features[] = {
GetSystemMetric
},
{
+ &nsGkAtoms::_moz_windows_accent_color_applies,
+ nsMediaFeature::eMinMaxNotAllowed,
+ nsMediaFeature::eBoolInteger,
+ nsMediaFeature::eNoRequirements,
+ { &nsGkAtoms::windows_accent_color_applies },
+ GetSystemMetric
+ },
+ {
+ &nsGkAtoms::_moz_windows_accent_color_is_dark,
+ nsMediaFeature::eMinMaxNotAllowed,
+ nsMediaFeature::eBoolInteger,
+ nsMediaFeature::eNoRequirements,
+ { &nsGkAtoms::windows_accent_color_is_dark },
+ GetSystemMetric
+ },
+ {
&nsGkAtoms::_moz_windows_compositor,
nsMediaFeature::eMinMaxNotAllowed,
nsMediaFeature::eBoolInteger,
diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp
index b22002d87..fa29fe0f1 100644
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -4686,7 +4686,8 @@ nsRuleNode::ComputeTextData(void* aStartStruct,
if (font->mSize != 0) {
lh = nscoord(float(lh) * float(font->mFont.size) / float(font->mSize));
} else {
- lh = minimumFontSize;
+ // Never shrink line heights as a result of minFontSize
+ lh = std::max(lh, minimumFontSize);
}
}
text->mLineHeight.SetCoordValue(lh);
diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp
index 2f12d6201..553239e0e 100644
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1629,23 +1629,11 @@ nsStylePosition::CalcDifference(const nsStylePosition& aNewData,
if (aOldStyleVisibility) {
bool isVertical = WritingMode(aOldStyleVisibility).IsVertical();
if (isVertical ? widthChanged : heightChanged) {
- // Block-size changes can affect descendant intrinsic sizes due to
- // replaced elements with percentage bsizes in descendants which
- // also have percentage bsizes. This is handled via
- // nsChangeHint_UpdateComputedBSize which clears intrinsic sizes
- // for frames that have such replaced elements.
- hint |= nsChangeHint_NeedReflow |
- nsChangeHint_UpdateComputedBSize |
- nsChangeHint_ReflowChangesSizeOrPosition;
+ hint |= nsChangeHint_ReflowHintsForBSizeChange;
}
if (isVertical ? heightChanged : widthChanged) {
- // None of our inline-size differences can affect descendant
- // intrinsic sizes and none of them need to force children to
- // reflow.
- hint |= nsChangeHint_AllReflowHints &
- ~(nsChangeHint_ClearDescendantIntrinsics |
- nsChangeHint_NeedDirtyReflow);
+ hint |= nsChangeHint_ReflowHintsForISizeChange;
}
} else {
if (widthChanged || heightChanged) {
@@ -3258,8 +3246,6 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
|| mDisplay != aNewData.mDisplay
|| mContain != aNewData.mContain
|| (mFloat == StyleFloat::None) != (aNewData.mFloat == StyleFloat::None)
- || mOverflowX != aNewData.mOverflowX
- || mOverflowY != aNewData.mOverflowY
|| mScrollBehavior != aNewData.mScrollBehavior
|| mScrollSnapTypeX != aNewData.mScrollSnapTypeX
|| mScrollSnapTypeY != aNewData.mScrollSnapTypeY
@@ -3271,6 +3257,11 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
hint |= nsChangeHint_ReconstructFrame;
}
+ if (mOverflowX != aNewData.mOverflowX
+ || mOverflowY != aNewData.mOverflowY) {
+ hint |= nsChangeHint_CSSOverflowChange;
+ }
+
/* Note: When mScrollBehavior, mScrollSnapTypeX, mScrollSnapTypeY,
* mScrollSnapPointsX, mScrollSnapPointsY, or mScrollSnapDestination are
* changed, nsChangeHint_NeutralChange is not sufficient to enter
diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h
index ca5d03056..05a6be91e 100644
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1197,11 +1197,14 @@ private:
nsCSSShadowItem mArray[1]; // This MUST be the last item
};
-// Border widths are rounded to the nearest-below integer number of pixels,
-// but values between zero and one device pixels are always rounded up to
-// one device pixel.
+// Border widths are rounded to the nearest integer number of pixels, but values
+// between zero and one device pixels are always rounded up to one device pixel.
#define NS_ROUND_BORDER_TO_PIXELS(l,tpp) \
- ((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp))
+ ((l) == 0) ? 0 : std::max((tpp), ((l) + ((tpp) / 2)) / (tpp) * (tpp))
+// Caret widths are rounded to the nearest-below integer number of pixels, but values
+// between zero and one device pixels are always rounded up to one device pixel.
+#define NS_ROUND_CARET_TO_PIXELS(l,tpp) \
+ ((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp))
// Outline offset is rounded to the nearest integer number of pixels, but values
// between zero and one device pixels are always rounded up to one device pixel.
// Note that the offset can be negative.
diff --git a/layout/style/res/forms.css b/layout/style/res/forms.css
index f045540b1..e7566e183 100644
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -1135,3 +1135,8 @@ input[type="number"] > div > div > div:hover {
/* give some indication of hover state for the up/down buttons */
background-color: lightblue;
}
+
+input[type="date"],
+input[type="time"] {
+ overflow: hidden !important;
+}
diff --git a/layout/style/res/html.css b/layout/style/res/html.css
index a779461de..bc3f08210 100644
--- a/layout/style/res/html.css
+++ b/layout/style/res/html.css
@@ -774,6 +774,11 @@ input[type="time"] > xul|datetimebox {
-moz-binding: url("chrome://global/content/bindings/datetimebox.xml#time-input");
}
+input[type="date"] > xul|datetimebox {
+ display: flex;
+ -moz-binding: url("chrome://global/content/bindings/datetimebox.xml#date-input");
+}
+
/* details & summary */
/* Need to revert Bug 1259889 Part 2 when removing details preference. */
@supports -moz-bool-pref("dom.details_element.enabled") {
diff --git a/layout/style/test/chrome/bug418986-2.js b/layout/style/test/chrome/bug418986-2.js
index 4336f4abd..b083f48ee 100644
--- a/layout/style/test/chrome/bug418986-2.js
+++ b/layout/style/test/chrome/bug418986-2.js
@@ -53,8 +53,6 @@ var suppressed_toggles = [
// Possible values for '-moz-os-version'
var windows_versions = [
- "windows-xp",
- "windows-vista",
"windows-win7",
"windows-win8",
"windows-win10",
diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini
index 406c6f901..8182691ca 100644
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -295,6 +295,7 @@ skip-if = toolkit == 'android'
[test_variables.html]
support-files = support/external-variable-url.css
[test_video_object_fit.html]
+[test_viewport_scrollbar_causing_reflow.html]
[test_viewport_units.html]
[test_visited_image_loading.html]
skip-if = toolkit == 'android' #TIMED_OUT
diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js
index 9c69e7d10..62d413d98 100644
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -132,6 +132,9 @@ var validGradientAndElementValues = [
"linear-gradient(to right bottom, red, 50%, green 50%, 50%, blue)",
"linear-gradient(to right bottom, red, 0%, green 50%, 100%, blue)",
+ /* Unitless 0 is valid as an <angle> */
+ "linear-gradient(0, red, blue)",
+
"-moz-linear-gradient(red, blue)",
"-moz-linear-gradient(red, yellow, blue)",
"-moz-linear-gradient(red 1px, yellow 20%, blue 24em, green)",
@@ -388,10 +391,8 @@ var invalidGradientAndElementValues = [
"-moz-linear-gradient(10 10px -45deg, red, blue) repeat",
"-moz-linear-gradient(10px 10 -45deg, red, blue) repeat",
"linear-gradient(red -99, yellow, green, blue 120%)",
- /* Unitless 0 is invalid as an <angle> */
- "-moz-linear-gradient(top left 0, red, blue)",
- "-moz-linear-gradient(5px 5px 0, red, blue)",
- "linear-gradient(0, red, blue)",
+ /* Unitless nonzero numbers are valid as an <angle> */
+ "linear-gradient(30, red, blue)",
/* Invalid color, calc() or -moz-image-rect() function */
"linear-gradient(red, rgb(0, rubbish, 0) 50%, red)",
"linear-gradient(red, red calc(50% + rubbish), red)",
@@ -6270,6 +6271,7 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
"repeat(auto-fill,minmax(1%,auto))",
"repeat(auto-fill,minmax(1em,min-content)) minmax(min-content,0)",
"repeat(auto-fill,minmax(max-content,1mm))",
+ "repeat(2, fit-content(1px))",
"fit-content(1px) 1fr",
"[a] fit-content(calc(1px - 99%)) [b]",
"[a] fit-content(10%) [b c] fit-content(1em)",
@@ -6314,6 +6316,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
"repeat(1, repeat(1, 20px))",
"repeat(auto-fill, auto)",
"repeat(auto-fit,auto)",
+ "repeat(auto-fill, fit-content(1px))",
+ "repeat(auto-fit, fit-content(1px))",
"repeat(auto-fit,[])",
"repeat(auto-fill, 0) repeat(auto-fit, 0) ",
"repeat(auto-fit, 0) repeat(auto-fill, 0) ",
@@ -6335,6 +6339,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
"fit-content(-1px)",
"fit-content(auto)",
"fit-content(min-content)",
+ "fit-content(1px) repeat(auto-fit, 1px)",
+ "fit-content(1px) repeat(auto-fill, 1px)",
],
unbalanced_values: [
"(foo] 40px",
diff --git a/layout/style/test/test_dynamic_change_causing_reflow.html b/layout/style/test/test_dynamic_change_causing_reflow.html
index a941191f6..a5bb3045c 100644
--- a/layout/style/test/test_dynamic_change_causing_reflow.html
+++ b/layout/style/test/test_dynamic_change_causing_reflow.html
@@ -95,6 +95,90 @@ const gTestcases = [
expectReflow: true,
},
+ // * Changing 'overflow' on <body> should cause reflow,
+ // but not frame reconstruction
+ {
+ elem: document.body,
+ /* beforeStyle: implicitly 'overflow:visible' */
+ afterStyle: "overflow: hidden",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ /* beforeStyle: implicitly 'overflow:visible' */
+ afterStyle: "overflow: scroll",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ beforeStyle: "overflow: hidden",
+ afterStyle: "overflow: auto",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ beforeStyle: "overflow: hidden",
+ afterStyle: "overflow: scroll",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ beforeStyle: "overflow: hidden",
+ afterStyle: "overflow: visible",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ beforeStyle: "overflow: auto",
+ afterStyle: "overflow: hidden",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ beforeStyle: "overflow: visible",
+ afterStyle: "overflow: hidden",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+
+ // * Changing 'overflow' on <html> should cause reflow,
+ // but not frame reconstruction
+ {
+ elem: document.documentElement,
+ /* beforeStyle: implicitly 'overflow:visible' */
+ afterStyle: "overflow: auto",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.documentElement,
+ beforeStyle: "overflow: visible",
+ afterStyle: "overflow: auto",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+
+ // * Setting 'overflow' on arbitrary node should cause reflow as well as
+ // frame reconstruction
+ {
+ /* beforeStyle: implicitly 'overflow:visible' */
+ afterStyle: "overflow: auto",
+ expectConstruction: true,
+ expectReflow: true,
+ },
+ {
+ beforeStyle: "overflow: auto",
+ afterStyle: "overflow: visible",
+ expectConstruction: true,
+ expectReflow: true,
+ },
+
// * Changing 'display' should cause frame construction and reflow.
{
beforeStyle: "display: inline",
@@ -135,23 +219,34 @@ function runOneTest(aTestcase)
return;
}
+ // Figure out which element we'll be tweaking (defaulting to gElem)
+ let elem = aTestcase.elem ?
+ aTestcase.elem : gElem;
+
+ // Verify that 'style' attribute is unset (avoid causing ourselves trouble):
+ if (elem.hasAttribute("style")) {
+ ok(false,
+ "test element has 'style' attribute already set! We're going to stomp " +
+ "on whatever's there when we clean up...");
+ }
+
// Set the "before" style, and compose the first part of the message
// to be used in our "is"/"isnot" invocations:
let msgPrefix = "Changing style ";
if (aTestcase.beforeStyle) {
- gElem.setAttribute("style", aTestcase.beforeStyle);
+ elem.setAttribute("style", aTestcase.beforeStyle);
msgPrefix += "from '" + aTestcase.beforeStyle + "' ";
}
- msgPrefix += "to '" + aTestcase.afterStyle + "' ";
+ msgPrefix += "on " + elem.nodeName + " ";
// Establish initial counts:
- let unusedVal = gElem.offsetHeight; // flush layout
+ let unusedVal = elem.offsetHeight; // flush layout
let origFramesConstructed = gUtils.framesConstructed;
let origFramesReflowed = gUtils.framesReflowed;
// Make the change and flush:
- gElem.setAttribute("style", aTestcase.afterStyle);
- unusedVal = gElem.offsetHeight; // flush layout
+ elem.setAttribute("style", aTestcase.afterStyle);
+ unusedVal = elem.offsetHeight; // flush layout
// Make our is/isnot assertions about whether things should have changed:
checkFinalCount(gUtils.framesConstructed, origFramesConstructed,
@@ -162,7 +257,7 @@ function runOneTest(aTestcase)
"reflow");
// Clean up!
- gElem.removeAttribute("style");
+ elem.removeAttribute("style");
}
gTestcases.forEach(runOneTest);
diff --git a/layout/style/test/test_media_queries.html b/layout/style/test/test_media_queries.html
index 1edac15ae..d503fad0b 100644
--- a/layout/style/test/test_media_queries.html
+++ b/layout/style/test/test_media_queries.html
@@ -628,6 +628,7 @@ function run() {
expression_should_be_parseable("-moz-windows-default-theme");
expression_should_be_parseable("-moz-mac-graphite-theme");
expression_should_be_parseable("-moz-mac-yosemite-theme");
+ expression_should_be_parseable("-moz-windows-accent-color-applies");
expression_should_be_parseable("-moz-windows-compositor");
expression_should_be_parseable("-moz-windows-classic");
expression_should_be_parseable("-moz-windows-glass");
@@ -643,6 +644,7 @@ function run() {
expression_should_be_parseable("-moz-windows-default-theme: 0");
expression_should_be_parseable("-moz-mac-graphite-theme: 0");
expression_should_be_parseable("-moz-mac-yosemite-theme: 0");
+ expression_should_be_parseable("-moz-windows-accent-color-applies: 0");
expression_should_be_parseable("-moz-windows-compositor: 0");
expression_should_be_parseable("-moz-windows-classic: 0");
expression_should_be_parseable("-moz-windows-glass: 0");
@@ -658,6 +660,7 @@ function run() {
expression_should_be_parseable("-moz-windows-default-theme: 1");
expression_should_be_parseable("-moz-mac-graphite-theme: 1");
expression_should_be_parseable("-moz-mac-yosemite-theme: 1");
+ expression_should_be_parseable("-moz-windows-accent-color-applies: 1");
expression_should_be_parseable("-moz-windows-compositor: 1");
expression_should_be_parseable("-moz-windows-classic: 1");
expression_should_be_parseable("-moz-windows-glass: 1");
@@ -673,6 +676,7 @@ function run() {
expression_should_not_be_parseable("-moz-windows-default-theme: -1");
expression_should_not_be_parseable("-moz-mac-graphite-theme: -1");
expression_should_not_be_parseable("-moz-mac-yosemite-theme: -1");
+ expression_should_not_be_parseable("-moz-windows-accent-color-applies: -1");
expression_should_not_be_parseable("-moz-windows-compositor: -1");
expression_should_not_be_parseable("-moz-windows-classic: -1");
expression_should_not_be_parseable("-moz-windows-glass: -1");
@@ -688,6 +692,7 @@ function run() {
expression_should_not_be_parseable("-moz-windows-default-theme: true");
expression_should_not_be_parseable("-moz-mac-graphite-theme: true");
expression_should_not_be_parseable("-moz-mac-yosemite-theme: true");
+ expression_should_not_be_parseable("-moz-windows-accent-color-applies: true");
expression_should_not_be_parseable("-moz-windows-compositor: true");
expression_should_not_be_parseable("-moz-windows-classic: true");
expression_should_not_be_parseable("-moz-windows-glass: true");
@@ -708,8 +713,6 @@ function run() {
expression_should_not_be_parseable("-moz-windows-theme: ");
// os version media queries (currently windows only)
- expression_should_be_parseable("-moz-os-version: windows-xp");
- expression_should_be_parseable("-moz-os-version: windows-vista");
expression_should_be_parseable("-moz-os-version: windows-win7");
expression_should_be_parseable("-moz-os-version: windows-win8");
expression_should_be_parseable("-moz-os-version: windows-win10");
diff --git a/layout/style/test/test_viewport_scrollbar_causing_reflow.html b/layout/style/test/test_viewport_scrollbar_causing_reflow.html
new file mode 100644
index 000000000..dfd7ec450
--- /dev/null
+++ b/layout/style/test/test_viewport_scrollbar_causing_reflow.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1367568
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1367568</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug 1367568</a>
+<div id="content">
+ <!-- Some fixed-width divs that we shouldn't have to reflow when the viewport
+ changes: -->
+ <div style="width: 100px">
+ fixed-width
+ <div>(child)</div>
+ </div>
+ <div style="position: absolute; width: 150px">
+ abs-fixed-width
+ <div>(child)</div>
+ </div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+"use strict";
+
+/** Test for Bug 1367568 **/
+
+/**
+ * This test verifies that "overflow" changes on the <body> don't cause
+ * an unnecessarily large amount of reflow.
+ */
+
+// Vars used in setStyleAndMeasure that we really only have to look up once:
+const gUtils = SpecialPowers.getDOMWindowUtils(window);
+
+function setStyleAndMeasure(initialStyle, finalStyle) {
+ is(document.body.style.length, 0,
+ "Bug in test - body should start with empty style");
+ let unusedVal = document.body.offsetHeight; // flush layout
+ let constructCount = gUtils.framesConstructed;
+
+ document.body.style = initialStyle;
+ unusedVal = document.body.offsetHeight; // flush layout
+ let reflowCountBeforeTweak = gUtils.framesReflowed;
+
+ document.body.style = finalStyle;
+ unusedVal = document.body.offsetHeight; // flush layout
+ let reflowCountAfterTweak = gUtils.framesReflowed;
+
+ // Clean up:
+ document.body.style = "";
+
+ is(gUtils.framesConstructed, constructCount,
+ "Style tweak shouldn't have triggered frame construction");
+
+ // ...and return the delta:
+ return reflowCountAfterTweak - reflowCountBeforeTweak;
+}
+
+function main() {
+ // First, we sanity-check that our measurement make sense -- if we leave
+ // styles unchanged, we should measure no frames being reflowed:
+ let count = setStyleAndMeasure("width: 50px; height: 80px",
+ "width: 50px; height: 80px");
+ is(count, 0,
+ "Shouldn't reflow anything when we leave 'width' & 'height' unchanged");
+
+ // Now: see how many frames are reflowed when the "width" & "height" change.
+ // We'll use this as the reference when measuring reflow counts for various
+ // changes to "overflow" below.
+ count = setStyleAndMeasure("width: 50px; height: 80px",
+ "width: 90px; height: 60px");
+ ok(count > 0,
+ "Should reflow some frames when 'width' & 'height' change");
+
+ // Expected maximum number of frames reflowed for "overflow" changes
+ // (+2 is to allow for reflowing scrollbars themselves):
+ const expectedMax = count + 2;
+
+ // Shared ending for messages in all ok() checks below:
+ const messageSuffix =
+ " shouldn't be greater than count for tweaking width/height on body (" +
+ expectedMax + ")";
+
+ // OK, here is where the relevant tests actually begin!!
+ // See how many frames we reflow for various tweaks to "overflow" on
+ // the body -- we expect the count to be no larger than |expectedMax|.
+ count = setStyleAndMeasure("", "overflow: scroll");
+ ok(count <= expectedMax,
+ "Reflow count when setting 'overflow: scroll' on body (" + count + ")" +
+ messageSuffix);
+
+ count = setStyleAndMeasure("", "overflow: hidden");
+ ok(count <= expectedMax,
+ "Reflow count when setting 'overflow: hidden' on body (" + count + ")" +
+ messageSuffix);
+
+ // Test removal of "overflow: scroll":
+ count = setStyleAndMeasure("overflow: scroll", "");
+ ok(count <= expectedMax,
+ "Reflow count when removing 'overflow: scroll' from body (" + count + ")" +
+ messageSuffix);
+
+ count = setStyleAndMeasure("overflow: hidden", "");
+ ok(count <= expectedMax,
+ "Reflow count when removing 'overflow: hidden' from body (" + count + ")" +
+ messageSuffix);
+
+ // Test change between two non-'visible' overflow values:
+ count = setStyleAndMeasure("overflow: scroll", "overflow: hidden");
+ ok(count <= expectedMax,
+ "Reflow count when changing 'overflow' on body (" + count + ")" +
+ messageSuffix);
+}
+
+main();
+
+</script>
+</pre>
+</body>
+</html>