diff options
Diffstat (limited to 'layout/style')
-rw-r--r-- | layout/style/FontFaceSet.cpp | 12 | ||||
-rw-r--r-- | layout/style/nsCSSKeywordList.h | 2 | ||||
-rw-r--r-- | layout/style/nsCSSParser.cpp | 7 | ||||
-rw-r--r-- | layout/style/nsCSSProps.cpp | 2 | ||||
-rw-r--r-- | layout/style/nsCSSPseudoElements.h | 3 | ||||
-rw-r--r-- | layout/style/nsCSSRuleProcessor.cpp | 10 | ||||
-rw-r--r-- | layout/style/nsLayoutStylesheetCache.cpp | 293 | ||||
-rw-r--r-- | layout/style/nsMediaFeatures.cpp | 18 | ||||
-rw-r--r-- | layout/style/nsRuleNode.cpp | 3 | ||||
-rw-r--r-- | layout/style/nsStyleStruct.cpp | 23 | ||||
-rw-r--r-- | layout/style/nsStyleStruct.h | 11 | ||||
-rw-r--r-- | layout/style/res/forms.css | 5 | ||||
-rw-r--r-- | layout/style/res/html.css | 5 | ||||
-rw-r--r-- | layout/style/test/chrome/bug418986-2.js | 2 | ||||
-rw-r--r-- | layout/style/test/mochitest.ini | 1 | ||||
-rw-r--r-- | layout/style/test/property_database.js | 14 | ||||
-rw-r--r-- | layout/style/test/test_dynamic_change_causing_reflow.html | 107 | ||||
-rw-r--r-- | layout/style/test/test_media_queries.html | 7 | ||||
-rw-r--r-- | layout/style/test/test_viewport_scrollbar_causing_reflow.html | 125 |
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> |