merge autoland to mozilla-central. r=merge a=merge

MozReview-Commit-ID: JWKcdNfAFqk
This commit is contained in:
Sebastian Hengst 2017-09-13 11:25:59 +02:00
Родитель e76c0fee79 86c4053dd2
Коммит dd669d05e1
29 изменённых файлов: 309 добавлений и 226 удалений

Просмотреть файл

@ -7,6 +7,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://devtools/shared/Loader.jsm");
function isActiveSidebarTabTitle(inspector, expectedTabTitle, message) {
const actualTabTitle = inspector.panelDoc.querySelector(".tabs-menu-item.is-active").innerText;
is(actualTabTitle, expectedTabTitle, message);
}
add_task(async function test_devtools_panels_elements_sidebar() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/");
@ -70,6 +75,9 @@ add_task(async function test_devtools_panels_elements_sidebar() {
is(shownSidebarInstance, "sidebar1", "Got the shown event on the first extension sidebar");
isActiveSidebarTabTitle(inspector, "Test Sidebar 1",
"Got the expected title on the active sidebar tab");
const sidebarPanel1 = inspector.sidebar.getTabPanel(sidebarIds[0]);
ok(sidebarPanel1, "Got a rendered sidebar panel for the first registered extension sidebar");
@ -94,6 +102,9 @@ add_task(async function test_devtools_panels_elements_sidebar() {
is(shownSidebarInstance2, "sidebar2", "Got the shown event on the second extension sidebar");
is(hiddenSidebarInstance1, "sidebar1", "Got the hidden event on the first extension sidebar");
isActiveSidebarTabTitle(inspector, "Test Sidebar 2",
"Got the expected title on the active sidebar tab");
const sidebarPanel2 = inspector.sidebar.getTabPanel(sidebarIds[1]);
ok(sidebarPanel2, "Got a rendered sidebar panel for the second registered extension sidebar");

Просмотреть файл

@ -82,6 +82,7 @@
}
#main-window:not([tabsintitlebar]) > #titlebar {
-moz-appearance: -moz-window-titlebar;
height: 22px; /* The native titlebar on OS X is 22px tall. */
}

Просмотреть файл

@ -52,6 +52,7 @@ class ExtensionSidebar {
this._provider = createElement(Provider, {
store: this.store,
key: this.id,
title: this.title,
}, ExtensionSidebarComponent({
id: this.id,
}));

Просмотреть файл

@ -22,6 +22,8 @@ add_task(async function () {
is(sidebar.title, sidebarTitle,
"Got the expected title in the extension sidebar instance");
is(sidebar.provider.props.title, sidebarTitle,
"Got the expeted title in the provider props");
let inspectorStoreState = inspector.store.getState();

Просмотреть файл

@ -77,15 +77,6 @@ function shouldSkipTest(test) {
}
}
}
if (SpecialPowers.DOMWindowUtils.isStyledByServo &&
SpecialPowers.isDebugBuild &&
navigator.platform.indexOf('Mac') >= 0) {
if (test == "file_fullscreen-backdrop.html") {
todo(false, `${test} skipped due to bug 1387942`);
return true;
}
}
return false;
}

Просмотреть файл

@ -2156,6 +2156,13 @@ MediaCacheStream::GetLength()
return mStreamLength;
}
int64_t
MediaCacheStream::GetOffset() const
{
MOZ_ASSERT(NS_IsMainThread());
return mChannelOffset;
}
int64_t
MediaCacheStream::GetNextCachedData(int64_t aOffset)
{

Просмотреть файл

@ -285,6 +285,8 @@ public:
// If we've successfully read data beyond the originally reported length,
// we return the end of the data we've read.
int64_t GetLength();
// Return the offset where next channel data will write to. Main thread only.
int64_t GetOffset() const;
// Returns the unique resource ID. Call only on the main thread or while
// holding the media cache lock.
int64_t GetResourceID() { return mResourceID; }

Просмотреть файл

@ -80,7 +80,6 @@ ChannelMediaResource::ChannelMediaResource(MediaResourceCallback* aCallback,
nsIURI* aURI,
bool aIsPrivateBrowsing)
: BaseMediaResource(aCallback, aChannel, aURI)
, mOffset(0)
, mReopenOnError(false)
, mCacheStream(this, aIsPrivateBrowsing)
, mSuspendAgent(mChannel)
@ -93,7 +92,6 @@ ChannelMediaResource::ChannelMediaResource(
nsIURI* aURI,
const MediaChannelStatistics& aStatistics)
: BaseMediaResource(aCallback, aChannel, aURI)
, mOffset(0)
, mReopenOnError(false)
, mCacheStream(this, /* aIsPrivateBrowsing = */ false)
, mChannelStatistics(aStatistics)
@ -152,17 +150,20 @@ ChannelMediaResource::Listener::OnDataAvailable(nsIRequest* aRequest,
}
nsresult
ChannelMediaResource::Listener::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
nsIChannel* aNewChannel,
uint32_t aFlags,
nsIAsyncVerifyRedirectCallback* cb)
ChannelMediaResource::Listener::AsyncOnChannelRedirect(
nsIChannel* aOld,
nsIChannel* aNew,
uint32_t aFlags,
nsIAsyncVerifyRedirectCallback* cb)
{
nsresult rv = NS_OK;
if (mResource)
rv = mResource->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
if (mResource) {
rv = mResource->OnChannelRedirect(aOld, aNew, aFlags, mOffset);
}
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
return rv;
}
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
@ -284,26 +285,19 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
if (rangeTotal != -1) {
contentLength = std::max(contentLength, rangeTotal);
}
// Give some warnings if the ranges are unexpected.
// XXX These could be error conditions.
NS_WARNING_ASSERTION(
mOffset == rangeStart,
"response range start does not match current offset");
mOffset = rangeStart;
mCacheStream.NotifyDataStarted(rangeStart);
}
acceptsRanges = gotRangeHeader;
} else if (mOffset > 0 && responseStatus == HTTP_OK_CODE) {
} else if (GetOffset() > 0 && responseStatus == HTTP_OK_CODE) {
// If we get an OK response but we were seeking, or requesting a byte
// range, then we have to assume that seeking doesn't work. We also need
// to tell the cache that it's getting data for the start of the stream.
mCacheStream.NotifyDataStarted(0);
mOffset = 0;
// The server claimed it supported range requests. It lied.
acceptsRanges = false;
}
if (mOffset == 0 && contentLength >= 0 &&
if (GetOffset() == 0 && contentLength >= 0 &&
(responseStatus == HTTP_OK_CODE ||
responseStatus == HTTP_PARTIAL_RESPONSE_CODE)) {
mCacheStream.NotifyDataLength(contentLength);
@ -398,14 +392,14 @@ ChannelMediaResource::OnStopRequest(nsIRequest* aRequest, nsresult aStatus)
// cause us to just re-read the stream, which would be really bad.
if (mReopenOnError && aStatus != NS_ERROR_PARSED_DATA_CACHED &&
aStatus != NS_BINDING_ABORTED &&
(mOffset == 0 || (GetLength() > 0 && mOffset != GetLength() &&
mCacheStream.IsTransportSeekable()))) {
(GetOffset() == 0 || (GetLength() > 0 && GetOffset() != GetLength() &&
mCacheStream.IsTransportSeekable()))) {
// If the stream did close normally, restart the channel if we're either
// at the start of the resource, or if the server is seekable and we're
// not at the end of stream. We don't restart the stream if we're at the
// end because not all web servers handle this case consistently; see:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1373618#c36
nsresult rv = CacheClientSeek(mOffset, false);
nsresult rv = CacheClientSeek(GetOffset(), false);
if (NS_SUCCEEDED(rv)) {
return rv;
}
@ -430,12 +424,14 @@ ChannelMediaResource::OnStopRequest(nsIRequest* aRequest, nsresult aStatus)
}
nsresult
ChannelMediaResource::OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew,
uint32_t aFlags)
ChannelMediaResource::OnChannelRedirect(nsIChannel* aOld,
nsIChannel* aNew,
uint32_t aFlags,
int64_t aOffset)
{
mChannel = aNew;
mSuspendAgent.NotifyChannelOpened(mChannel);
return SetupChannelHeaders();
return SetupChannelHeaders(aOffset);
}
nsresult
@ -444,11 +440,6 @@ ChannelMediaResource::CopySegmentToCache(nsIPrincipal* aPrincipal,
uint32_t aCount,
uint32_t* aWriteCount)
{
// Keep track of where we're up to.
LOG("CopySegmentToCache at mOffset [%" PRId64 "] add "
"[%d] bytes for decoder[%p]",
mOffset, aCount, mCallback.get());
mOffset += aCount;
mCacheStream.NotifyDataReceived(aCount, aFromSegment, aPrincipal);
*aWriteCount = aCount;
return NS_OK;
@ -528,25 +519,25 @@ ChannelMediaResource::Open(nsIStreamListener** aStreamListener)
return rv;
}
MOZ_ASSERT(mOffset == 0, "Who set mOffset already?");
mListener = new Listener(this);
MOZ_ASSERT(GetOffset() == 0, "Who set offset already?");
mListener = new Listener(this, 0);
*aStreamListener = mListener;
NS_ADDREF(*aStreamListener);
return NS_OK;
}
nsresult
ChannelMediaResource::OpenChannel()
ChannelMediaResource::OpenChannel(int64_t aOffset)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mChannel);
MOZ_ASSERT(!mListener, "Listener should have been removed by now");
mListener = new Listener(this);
mListener = new Listener(this, aOffset);
nsresult rv = mChannel->SetNotificationCallbacks(mListener.get());
NS_ENSURE_SUCCESS(rv, rv);
rv = SetupChannelHeaders();
rv = SetupChannelHeaders(aOffset);
NS_ENSURE_SUCCESS(rv, rv);
rv = mChannel->AsyncOpen2(mListener);
@ -561,7 +552,8 @@ ChannelMediaResource::OpenChannel()
return NS_OK;
}
nsresult ChannelMediaResource::SetupChannelHeaders()
nsresult
ChannelMediaResource::SetupChannelHeaders(int64_t aOffset)
{
// Always use a byte range request even if we're reading from the start
// of the resource.
@ -571,7 +563,7 @@ nsresult ChannelMediaResource::SetupChannelHeaders()
if (hc) {
// Use |mOffset| if seeking in a complete file download.
nsAutoCString rangeString("bytes=");
rangeString.AppendInt(mOffset);
rangeString.AppendInt(aOffset);
rangeString.Append('-');
nsresult rv = hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, false);
NS_ENSURE_SUCCESS(rv, rv);
@ -584,7 +576,7 @@ nsresult ChannelMediaResource::SetupChannelHeaders()
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
element->SetRequestHeaders(hc);
} else {
NS_ASSERTION(mOffset == 0, "Don't know how to seek on this channel type");
NS_ASSERTION(aOffset == 0, "Don't know how to seek on this channel type");
return NS_ERROR_FAILURE;
}
return NS_OK;
@ -754,10 +746,10 @@ void ChannelMediaResource::Resume()
// the channel dead; if the media cache wants to read some other data
// in the future, it will call CacheClientSeek itself which will reopen the
// channel.
if (totalLength < 0 || mOffset < totalLength) {
if (totalLength < 0 || GetOffset() < totalLength) {
// There is (or may be) data to read at mOffset, so start reading it.
// Need to recreate the channel.
CacheClientSeek(mOffset, false);
CacheClientSeek(GetOffset(), false);
element->DownloadResumed();
} else {
// The channel remains dead. Do not notify DownloadResumed() which
@ -863,8 +855,6 @@ ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume)
CloseChannel();
mOffset = aOffset;
if (aResume) {
mSuspendAgent.Resume();
}
@ -878,7 +868,7 @@ ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume)
nsresult rv = RecreateChannel();
NS_ENSURE_SUCCESS(rv, rv);
return OpenChannel();
return OpenChannel(aOffset);
}
nsresult
@ -962,6 +952,12 @@ ChannelMediaResource::GetLength()
return mCacheStream.GetLength();
}
int64_t
ChannelMediaResource::GetOffset() const
{
return mCacheStream.GetOffset();
}
// ChannelSuspendAgent
bool

Просмотреть файл

@ -510,7 +510,10 @@ public:
{
~Listener() {}
public:
explicit Listener(ChannelMediaResource* aResource) : mResource(aResource) {}
Listener(ChannelMediaResource* aResource, int64_t aOffset)
: mResource(aResource)
, mOffset(aOffset)
{}
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
@ -523,6 +526,7 @@ public:
private:
RefPtr<ChannelMediaResource> mResource;
const int64_t mOffset;
};
friend class Listener;
@ -536,17 +540,22 @@ protected:
nsresult OnDataAvailable(nsIRequest* aRequest,
nsIInputStream* aStream,
uint32_t aCount);
nsresult OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew, uint32_t aFlags);
nsresult OnChannelRedirect(nsIChannel* aOld,
nsIChannel* aNew,
uint32_t aFlags,
int64_t aOffset);
// Opens the channel, using an HTTP byte range request to start at mOffset
// Opens the channel, using an HTTP byte range request to start at aOffset
// if possible. Main thread only.
nsresult OpenChannel();
nsresult OpenChannel(int64_t aOffset);
nsresult RecreateChannel();
// Add headers to HTTP request. Main thread only.
nsresult SetupChannelHeaders();
nsresult SetupChannelHeaders(int64_t aOffset);
// Closes the channel. Main thread only.
void CloseChannel();
int64_t GetOffset() const;
// Parses 'Content-Range' header and returns results via parameters.
// Returns error if header is not available, values are not parse-able or
// values are out of range.
@ -568,7 +577,6 @@ protected:
uint32_t* aWriteCount);
// Main thread access only
int64_t mOffset;
RefPtr<Listener> mListener;
// When this flag is set, if we get a network error we should silently
// reopen the stream.

Просмотреть файл

@ -14,6 +14,7 @@ namespace layers {
StackingContextHelper::StackingContextHelper()
: mBuilder(nullptr)
, mHasPerspectiveTransform(false)
, mXScale(1.0f)
, mYScale(1.0f)
{
@ -26,6 +27,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
const Maybe<gfx::Matrix4x4>& aTransform,
const nsTArray<wr::WrFilterOp>& aFilters)
: mBuilder(&aBuilder)
, mHasPerspectiveTransform(false)
, mXScale(1.0f)
, mYScale(1.0f)
{
@ -51,6 +53,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
gfx::Matrix4x4* aTransformPtr,
const nsTArray<wr::WrFilterOp>& aFilters)
: mBuilder(&aBuilder)
, mHasPerspectiveTransform(false)
, mXScale(1.0f)
, mYScale(1.0f)
{
@ -83,6 +86,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
const nsTArray<wr::WrFilterOp>& aFilters,
const gfx::CompositionOp& aMixBlendMode)
: mBuilder(&aBuilder)
, mHasPerspectiveTransform(false)
, mXScale(1.0f)
, mYScale(1.0f)
{
@ -92,6 +96,10 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
mTransform = *aTransformPtr;
}
if (aPerspectivePtr) {
mHasPerspectiveTransform = true;
}
bool is2d = !aTransformPtr || (aTransformPtr->Is2D() && !aPerspectivePtr);
if (is2d) {
nsRect itemBounds = aDisplayList->GetClippedBoundsWithRespectToASR(aDisplayListBuilder, aItem->GetActiveScrolledRoot());
@ -102,6 +110,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
mTransform.PostScale(aParentSC.mXScale, aParentSC.mYScale, 1.0);
mTransform.NudgeToIntegersFixedEpsilon();
// Calculate the correct scale for current stacking context
gfx::Size scale = mTransform.As2D().ScaleFactors(true);
// Restore the scale to default if the scale is too small
@ -112,7 +121,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
mTransform.PreScale(1.0f/scale.width, 1.0f/scale.height, 1.0);
// Store the inherited scale if has
// Store the inherited scale for child
this->mXScale = scale.width;
this->mYScale = scale.height;
} else {

Просмотреть файл

@ -83,13 +83,26 @@ public:
// Same but rounds the rectangle to ints after transforming.
wr::LayoutRect ToRelativeLayoutRectRounded(const LayoutDeviceRect& aRect) const;
// Export the inherited scale
gfx::Size GetInheritedScale() const {
return gfx::Size(mXScale, mYScale);
}
// Provide interface to setup the inherited scale to support
// special cases, like OMTA
void SetInheritedScale(const gfx::Size& aScale) {
mXScale = aScale.width;
mYScale = aScale.height;
}
bool IsBackfaceVisible() const { return mTransform.IsBackfaceVisible(); }
bool HasPerspectiveTransform() const { return mHasPerspectiveTransform; }
private:
wr::DisplayListBuilder* mBuilder;
LayerPoint mOrigin;
gfx::Matrix4x4 mTransform;
bool mHasPerspectiveTransform;
float mXScale;
float mYScale;
};

Просмотреть файл

@ -556,8 +556,10 @@ UpdateBackdropIfNeeded(nsIFrame* aFrame,
/* aPseudoElement = */ nullptr);
// NOTE(emilio): We can't use the changes handled for the owner of the
// backdrop frame, since it's out of flow, and parented to the viewport frame.
MOZ_ASSERT(backdropFrame->GetParent()->IsViewportFrame());
// backdrop frame, since it's out of flow, and parented to the viewport or
// canvas frame (depending on the `position` value).
MOZ_ASSERT(backdropFrame->GetParent()->IsViewportFrame() ||
backdropFrame->GetParent()->IsCanvasFrame());
nsTArray<nsIFrame*> wrappersToRestyle;
ServoRestyleState state(aStyleSet, aChangeList, wrappersToRestyle);
aFrame->UpdateStyleOfOwnedChildFrame(backdropFrame, newContext, state);

Просмотреть файл

@ -6494,15 +6494,8 @@ nsTextFrame::PaintOneShadow(const PaintShadowParams& aParams,
if (!shadowContext)
return;
nscolor shadowColor;
const nscolor* decorationOverrideColor;
if (aShadowDetails->mHasColor) {
shadowColor = aShadowDetails->mColor;
decorationOverrideColor = &shadowColor;
} else {
shadowColor = aParams.foregroundColor;
decorationOverrideColor = nullptr;
}
nscolor shadowColor = aShadowDetails->mHasColor ? aShadowDetails->mColor
: aParams.foregroundColor;
if (aParams.textDrawer) {
wr::TextShadow wrShadow;
@ -6538,7 +6531,8 @@ nsTextFrame::PaintOneShadow(const PaintShadowParams& aParams,
aParams.context == shadowContext ? shadowColor : NS_RGB(0, 0, 0);
params.clipEdges = aParams.clipEdges;
params.drawSoftHyphen = (GetStateBits() & TEXT_HYPHEN_BREAK) != 0;
params.decorationOverrideColor = decorationOverrideColor;
// Multi-color shadow is not allowed, so we use the same color of the text color.
params.decorationOverrideColor = &params.textColor;
DrawText(aParams.range, aParams.textBaselinePt + shadowOffset, params);
contextBoxBlur.DoPaint();

Просмотреть файл

@ -7812,15 +7812,6 @@ nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBu
// transform animation, the transform value will be resolved
// after animation sampling on the compositor
transformForSC = nullptr;
// Pass default transform to compositor in case gecko fails to
// get animated value after animation sampling.
OptionalTransform transformForCompositor = newTransformMatrix;
OpAddCompositorAnimations
anim(CompositorAnimations(animationInfo.GetAnimations(), animationsId),
transformForCompositor, void_t());
aManager->WrBridge()->AddWebRenderParentCommand(anim);
}
gfx::Matrix4x4Typed<LayerPixel, LayerPixel> boundTransform = ViewAs< gfx::Matrix4x4Typed<LayerPixel, LayerPixel> >(newTransformMatrix);
@ -7841,6 +7832,33 @@ nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBu
nullptr,
filters);
if (animationsId) {
// Get the inheritedScale from parent and pass the scale to compositor
// to get correct sampling result
gfx::Size scale = aSc.GetInheritedScale();
for (layers::Animation& animation : animationInfo.GetAnimations()) {
if (animation.property() == eCSSProperty_transform) {
TransformData& transformData = animation.data().get_TransformData();
transformData.inheritedXScale() = scale.width;
transformData.inheritedYScale() = scale.height;
transformData.hasPerspectiveParent() = aSc.HasPerspectiveTransform();
}
}
// Pass default transform to compositor in case gecko fails to
// get animated value after animation sampling.
OptionalTransform transformForCompositor = newTransformMatrix;
OpAddCompositorAnimations
anim(CompositorAnimations(animationInfo.GetAnimations(), animationsId),
transformForCompositor, void_t());
aManager->WrBridge()->AddWebRenderParentCommand(anim);
// Since we passed a nullptr transformForSC to the StackingContextHelper,
// we now set up the correct inherited scale for the stacking context.
newTransformMatrix.PostScale(scale.width, scale.height, 1.0f);
sc.SetInheritedScale(newTransformMatrix.As2D().ScaleFactors(true));
}
return mStoredList.CreateWebRenderCommands(aBuilder, sc, aParentCommands,
aManager, aDisplayListBuilder);
}

Просмотреть файл

@ -1651,11 +1651,13 @@ fuzzy-if(Android,8,300) fuzzy-if(skiaContent,1,40000) == 625409-1.html 625409-1-
fuzzy-if(skiaContent,1,500) == 630835-1.html about:blank
== 631352-1.html 631352-1-ref.html
skip-if(!haveTestPlugin) fails-if(Android) fuzzy-if(winWidget&&!layersGPUAccelerated,102,535) fuzzy-if(skiaContent&&!Android,102,11000) HTTP == 632423-1.html 632423-1-ref.html
pref(gfx.webrender.layers-free,true) skip-if(!webrender) == 632423-1.html 632423-1-ref.html
skip-if(Android) random-if(winWidget||OSX==1010) == 632781-verybig.html 632781-ref.html
== 632781-normalsize.html 632781-ref.html
fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,559) fuzzy-if(!isDebugBuild&&gtkWidget&&/^Linux\x20i686/.test(http.oscpu),102,140) == 633344-1.html 633344-1-ref.html # bug 1103623, Linux32 from GCC update
fuzzy-if(skiaContent,1,500) == 634232-1.html 634232-1-ref.html
fuzzy-if(skiaContent,3,120000) == 635302-1.html 635302-1-ref.html
pref(gfx.webrender.layers-free,true) skip-if(!webrender) == 635302-1.html 635302-1-ref.html
fuzzy(1,68) fuzzy-if(gtkWidget,1,70) fails-if(Android) fuzzy-if(skiaContent&&!Android,1,300) == 635373-1.html 635373-1-ref.html
random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,20,118) fuzzy-if(skiaContent&&!Android,2,550) == 635373-2.html 635373-2-ref.html
random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,20,116) fuzzy-if(skiaContent&&!Android,2,650) == 635373-3.html 635373-3-ref.html

Просмотреть файл

@ -43,6 +43,7 @@ fails == background-position-running.html background-position-ref.html # This te
fails == background-position-important.html background-position-ref.html # This test fails the reftest-opaque-layer check since animating background-position overridden by a non-animated !important style also creates an active layer, and reftest-opaque-layer only handles items that are assigned to PaintedLayers.
== mask-position-after-finish-1a.html mask-anim-ref.html
pref(gfx.webrender.layers-free,true) skip-if(!webrender) == mask-position-after-finish-1a.html mask-anim-ref.html
== mask-position-after-finish-1b.html mask-anim-ref.html
== mask-position-in-delay-1a.html mask-anim-ref.html
== mask-position-in-delay-1b.html mask-anim-ref.html

Просмотреть файл

@ -1,4 +1,5 @@
fuzzy-if(Android,8,30) == background-image-zoom-1.html background-image-zoom-1-ref.html
pref(gfx.webrender.layers-free,true) skip-if(!webrender) == background-image-zoom-1.html background-image-zoom-1-ref.html
fails-if(usesRepeatResampling) == background-image-zoom-2.html about:blank
== image-seam-1a.html image-seam-1-ref.html
== image-seam-1b.html image-seam-1-ref.html

Просмотреть файл

@ -86,6 +86,7 @@ pref(layers.single-tile.enabled,false) != fast-scrolling.html about:blank
== negative-w-component.html negative-w-component-ref.html
== mask-invalidation-1a.html mask-invalidation-1-ref.html
pref(gfx.webrender.layers-free,true) skip-if(!webrender) == mask-invalidation-1a.html mask-invalidation-1-ref.html
== mask-invalidation-1b.html mask-invalidation-1-ref.html
== mask-invalidation-2a.html mask-invalidation-2-ref.html

Просмотреть файл

@ -2,14 +2,23 @@
<!-- Shadows -->
<!-- Blue underline/text -->
<div style="position: absolute; top: 22px; left: 22px; color: blue; text-decoration: underline;"><span style="color: rgba(0, 0, 0, 0);">testforquirks</span></div>
<div style="position: absolute; top: 22px; left: 22px;"><span style="color: blue;">test</span></div>
<div style="position: absolute; top: 22px; left: 22px;"><span style="color: blue; text-decoration: underline">test</span></div>
<!-- Red overline/text -->
<div style="position: absolute; top: 22px; left: 22px; color: rgba(0, 0, 0, 0);">test<span style="text-decoration: overline; color: red;"><span style="color: rgba(0, 0, 0, 0);">forquirks</span></span></div>
<div style="position: absolute; top: 22px; left: 22px;"><span style="color: rgba(0, 0, 0, 0);">test</span><span style="color: red;">for</span></div>
<!--
There are some additional pixels appearing when two red texts are overlap. We
use transparent color for the first one to prevent the situation and the failure
of reftest.
-->
<div style="position: absolute; top: 22px; left: 22px;"><span style="color: rgba(0, 0, 0, 0);">test</span><span style="color: transparent; text-decoration: red underline;">for</span></div>
<div style="position: absolute; top: 22px; left: 22px;"><span style="color: rgba(0, 0, 0, 0);">test</span><span style="color: red; text-decoration: overline;">for</span></div>
<!-- Green text/underline -->
<div style="position: absolute; top: 22px; left: 22px;"><span style="color: rgba(0, 0, 0, 0);">testfor</span><span style="text-decoration: underline; color: green;"><span style="color: rgba(0, 0, 0, 0);">quirks</span></span></div>
<div style="position: absolute; top: 22px; left: 22px;"><span style="color: rgba(0, 0, 0, 0);">testfor</span><span style="color: green;">quirks</span></div>
<!--
There are some additional pixels appearing when two red texts are overlap. We
use transparent color for the first one to prevent the situation and the failure
of reftest.
-->
<div style="position: absolute; top: 22px; left: 22px;"><span style="color: rgba(0, 0, 0, 0);">testfor</span><span style="text-decoration: green underline; color: transparent;">quirks</span></div>
<div style="position: absolute; top: 22px; left: 22px;"><span style="color: rgba(0, 0, 0, 0);">testfor</span><span style="text-decoration: overline; color: green;">quirks</span></div>
<!-- "Real" text -->
<!-- Blue underline/text -->

Просмотреть файл

@ -31,6 +31,7 @@ fuzzy-if(webrender,1,27) == compound-1a.html compound-1-ref.html
== translate-1b.html translate-1-ref.html
== translate-1c.html translate-1-ref.html
== translate-1d.html translate-1-ref.html
pref(gfx.webrender.layers-free,true) skip-if(!webrender) == translate-1d.html translate-1-ref.html
== translate-1e.html translate-1-ref.html
== translate-2a.html translate-2-ref.html
== translate-3.html translate-3-ref.html
@ -46,6 +47,7 @@ random == rotate-1f.html rotate-1-ref.html
# rotate: 90deg rotations should be indistinguishable from objects constructed
# to look the same.
== rotate-2a.html rotate-2-ref.html
pref(gfx.webrender.layers-free,true) skip-if(!webrender) == rotate-2a.html rotate-2-ref.html
== rotate-2b.html rotate-2-ref.html
# -transform-origin: We should NOT get the same images when using different
# -transform-origins.

Просмотреть файл

@ -162,14 +162,14 @@ public class AnimatedProgressBar extends ThemedProgressBar {
} else {
canvas.getClipBounds(mRect);
final float clipWidth = mRect.width() * mClipRatio;
canvas.save();
final int saveCount = canvas.save();
if (mIsRtl) {
canvas.clipRect(mRect.left, mRect.top, mRect.right - clipWidth, mRect.bottom);
} else {
canvas.clipRect(mRect.left + clipWidth, mRect.top, mRect.right, mRect.bottom);
}
super.onDraw(canvas);
canvas.restore();
canvas.restoreToCount(saveCount);
}
}
@ -266,8 +266,11 @@ public class AnimatedProgressBar extends ThemedProgressBar {
mClosingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mClipRatio = (float) valueAnimator.getAnimatedValue();
invalidate();
final float ratio = (float) valueAnimator.getAnimatedValue();
if (mClipRatio != ratio) {
mClipRatio = ratio;
invalidate();
}
}
});
mClosingAnimator.addListener(new Animator.AnimatorListener() {

4
servo/Cargo.lock сгенерированный
Просмотреть файл

@ -3587,7 +3587,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.50.0"
source = "git+https://github.com/servo/webrender#3d58efaecdc5897de057beab57adc031bc2e187e"
source = "git+https://github.com/servo/webrender#cd1855550857b910f752359b48c5cc053419c358"
dependencies = [
"app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3615,7 +3615,7 @@ dependencies = [
[[package]]
name = "webrender_api"
version = "0.50.0"
source = "git+https://github.com/servo/webrender#3d58efaecdc5897de057beab57adc031bc2e187e"
source = "git+https://github.com/servo/webrender#cd1855550857b910f752359b48c5cc053419c358"
dependencies = [
"app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",

Просмотреть файл

@ -39,13 +39,22 @@ impl<K: Array> LRUCache<K> {
#[inline]
/// Touch a given entry, putting it first in the list.
pub fn touch(&mut self, pos: usize) {
let last_index = self.entries.len() - 1;
if pos != last_index {
if pos != 0 {
let entry = self.entries.remove(pos).unwrap();
self.entries.push_front(entry);
}
}
/// Returns the front entry in the list (most recently used).
pub fn front(&self) -> Option<&K::Item> {
self.entries.get(0)
}
/// Returns a mutable reference to the front entry in the list (most recently used).
pub fn front_mut(&mut self) -> Option<&mut K::Item> {
self.entries.get_mut(0)
}
/// Iterate over the contents of this cache, from more to less recently
/// used.
pub fn iter(&self) -> arraydeque::Iter<K::Item> {

Просмотреть файл

@ -26,7 +26,7 @@ use selectors::matching::ElementSelectorFlags;
use servo_arc::Arc;
#[cfg(feature = "servo")] use servo_atoms::Atom;
use shared_lock::StylesheetGuards;
use sharing::StyleSharingCandidateCache;
use sharing::StyleSharingCache;
use std::fmt;
use std::ops;
#[cfg(feature = "servo")] use std::sync::Mutex;
@ -679,7 +679,7 @@ impl StackLimitChecker {
/// thread in order to be able to mutate it without locking.
pub struct ThreadLocalStyleContext<E: TElement> {
/// A cache to share style among siblings.
pub style_sharing_candidate_cache: StyleSharingCandidateCache<E>,
pub sharing_cache: StyleSharingCache<E>,
/// The bloom filter used to fast-reject selector-matching.
pub bloom_filter: StyleBloom<E>,
/// A channel on which new animations that have been triggered by style
@ -716,7 +716,7 @@ impl<E: TElement> ThreadLocalStyleContext<E> {
#[cfg(feature = "servo")]
pub fn new(shared: &SharedStyleContext) -> Self {
ThreadLocalStyleContext {
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
sharing_cache: StyleSharingCache::new(),
bloom_filter: StyleBloom::new(),
new_animations_sender: shared.local_context_creation_data.lock().unwrap().new_animations_sender.clone(),
tasks: SequentialTaskList(Vec::new()),
@ -733,7 +733,7 @@ impl<E: TElement> ThreadLocalStyleContext<E> {
/// Creates a new `ThreadLocalStyleContext` from a shared one.
pub fn new(shared: &SharedStyleContext) -> Self {
ThreadLocalStyleContext {
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
sharing_cache: StyleSharingCache::new(),
bloom_filter: StyleBloom::new(),
tasks: SequentialTaskList(Vec::new()),
selector_flags: SelectorFlagsMap::new(),

Просмотреть файл

@ -68,7 +68,7 @@ use Atom;
use applicable_declarations::ApplicableDeclarationBlock;
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
use bloom::StyleBloom;
use cache::{LRUCache, LRUCacheMutIterator};
use cache::LRUCache;
use context::{SelectorFlagsMap, SharedStyleContext, StyleContext};
use data::ElementStyles;
use dom::{TElement, SendElement};
@ -342,8 +342,8 @@ impl<E: TElement> StyleSharingTarget<E> {
pub fn share_style_if_possible(
&mut self,
context: &mut StyleContext<E>,
) -> StyleSharingResult {
let cache = &mut context.thread_local.style_sharing_candidate_cache;
) -> Option<ElementStyles> {
let cache = &mut context.thread_local.sharing_cache;
let shared_context = &context.shared;
let selector_flags_map = &mut context.thread_local.selector_flags;
let bloom_filter = &context.thread_local.bloom_filter;
@ -351,7 +351,7 @@ impl<E: TElement> StyleSharingTarget<E> {
if cache.dom_depth != bloom_filter.matching_depth() {
debug!("Can't share style, because DOM depth changed from {:?} to {:?}, element: {:?}",
cache.dom_depth, bloom_filter.matching_depth(), self.element);
return StyleSharingResult::CannotShare;
return None;
}
debug_assert_eq!(bloom_filter.current_parent(),
self.element.traversal_parent());
@ -370,45 +370,58 @@ impl<E: TElement> StyleSharingTarget<E> {
}
}
/// A cache miss result.
#[derive(Clone, Debug)]
pub enum CacheMiss {
/// The parents don't match.
Parent,
/// One element was NAC, while the other wasn't.
NativeAnonymousContent,
/// The local name of the element and the candidate don't match.
LocalName,
/// The namespace of the element and the candidate don't match.
Namespace,
/// One of the element or the candidate was a link, but the other one
/// wasn't.
Link,
/// The element and the candidate match different kind of rules. This can
/// only happen in Gecko.
UserAndAuthorRules,
/// The element and the candidate are in a different state.
State,
/// The element had an id attribute, which qualifies for a unique style.
IdAttr,
/// The element had a style attribute, which qualifies for a unique style.
StyleAttr,
/// The element and the candidate class names didn't match.
Class,
/// The presentation hints didn't match.
PresHints,
/// The element and the candidate didn't match the same set of revalidation
/// selectors.
Revalidation,
struct SharingCacheBase<Candidate> {
entries: LRUCache<[Candidate; SHARING_CACHE_BACKING_STORE_SIZE]>,
}
/// The results of attempting to share a style.
pub enum StyleSharingResult {
/// We didn't find anybody to share the style with.
CannotShare,
/// The node's style can be shared. The integer specifies the index in the
/// LRU cache that was hit and the damage that was done.
StyleWasShared(usize, ElementStyles),
impl<Candidate> Default for SharingCacheBase<Candidate> {
fn default() -> Self {
Self {
entries: LRUCache::new(),
}
}
}
impl<Candidate> SharingCacheBase<Candidate> {
fn clear(&mut self) {
self.entries.evict_all();
}
fn is_empty(&self) -> bool {
self.entries.num_entries() == 0
}
}
impl<E: TElement> SharingCache<E> {
fn insert(&mut self, el: E, validation_data_holder: &mut StyleSharingTarget<E>) {
self.entries.insert(StyleSharingCandidate {
element: el,
validation_data: validation_data_holder.take_validation_data(),
});
}
fn lookup<F>(&mut self, mut is_match: F) -> Option<ElementStyles>
where
F: FnMut(&mut StyleSharingCandidate<E>) -> bool
{
let mut index = None;
for (i, candidate) in self.entries.iter_mut().enumerate() {
if is_match(candidate) {
index = Some(i);
break;
}
};
match index {
None => None,
Some(i) => {
self.entries.touch(i);
let front = self.entries.front_mut().unwrap();
debug_assert!(is_match(front));
Some(front.element.borrow_data().unwrap().styles.clone())
}
}
}
}
/// Style sharing caches are are large allocations, so we store them in thread-local
@ -423,20 +436,19 @@ pub enum StyleSharingResult {
///
/// [1] https://github.com/rust-lang/rust/issues/42763
/// [2] https://github.com/rust-lang/rust/issues/13707
type SharingCacheBase<Candidate> = LRUCache<[Candidate; SHARING_CACHE_BACKING_STORE_SIZE]>;
type SharingCache<E> = SharingCacheBase<StyleSharingCandidate<E>>;
type TypelessSharingCache = SharingCacheBase<FakeCandidate>;
type StoredSharingCache = Arc<AtomicRefCell<TypelessSharingCache>>;
thread_local!(static SHARING_CACHE_KEY: StoredSharingCache =
Arc::new(AtomicRefCell::new(LRUCache::new())));
Arc::new(AtomicRefCell::new(TypelessSharingCache::default())));
/// An LRU cache of the last few nodes seen, so that we can aggressively try to
/// reuse their styles.
///
/// Note that this cache is flushed every time we steal work from the queue, so
/// storing nodes here temporarily is safe.
pub struct StyleSharingCandidateCache<E: TElement> {
pub struct StyleSharingCache<E: TElement> {
/// The LRU cache, with the type cast away to allow persisting the allocation.
cache_typeless: OwningHandle<StoredSharingCache, AtomicRefMut<'static, TypelessSharingCache>>,
/// Bind this structure to the lifetime of E, since that's what we effectively store.
@ -447,13 +459,14 @@ pub struct StyleSharingCandidateCache<E: TElement> {
dom_depth: usize,
}
impl<E: TElement> Drop for StyleSharingCandidateCache<E> {
impl<E: TElement> Drop for StyleSharingCache<E> {
fn drop(&mut self) {
self.clear();
}
}
impl<E: TElement> StyleSharingCandidateCache<E> {
impl<E: TElement> StyleSharingCache<E> {
#[allow(dead_code)]
fn cache(&self) -> &SharingCache<E> {
let base: &TypelessSharingCache = &*self.cache_typeless;
unsafe { mem::transmute(base) }
@ -470,31 +483,25 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
assert_eq!(mem::align_of::<SharingCache<E>>(), mem::align_of::<TypelessSharingCache>());
let cache_arc = SHARING_CACHE_KEY.with(|c| c.clone());
let cache = OwningHandle::new_with_fn(cache_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
debug_assert_eq!(cache.num_entries(), 0);
debug_assert!(cache.is_empty());
StyleSharingCandidateCache {
StyleSharingCache {
cache_typeless: cache,
marker: PhantomData,
dom_depth: 0,
}
}
/// Returns the number of entries in the cache.
pub fn num_entries(&self) -> usize {
self.cache().num_entries()
}
fn iter_mut(&mut self) -> LRUCacheMutIterator<StyleSharingCandidate<E>> {
self.cache_mut().iter_mut()
}
/// Tries to insert an element in the style sharing cache.
///
/// Fails if we know it should never be in the cache.
///
/// NB: We pass a source for the validation data, rather than the data itself,
/// to avoid memmoving at each function call. See rust issue #42763.
pub fn insert_if_possible(&mut self,
element: &E,
style: &ComputedValues,
validation_data: ValidationData,
validation_data_holder: &mut StyleSharingTarget<E>,
dom_depth: usize) {
let parent = match element.traversal_parent() {
Some(element) => element,
@ -547,20 +554,12 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
self.clear();
self.dom_depth = dom_depth;
}
self.cache_mut().insert(StyleSharingCandidate {
element: *element,
validation_data: validation_data,
});
}
/// Touch a given index in the style sharing candidate cache.
pub fn touch(&mut self, index: usize) {
self.cache_mut().touch(index);
self.cache_mut().insert(*element, validation_data_holder);
}
/// Clear the style sharing candidate cache.
pub fn clear(&mut self) {
self.cache_mut().evict_all()
self.cache_mut().clear();
}
/// Attempts to share a style with another node.
@ -570,48 +569,33 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
selector_flags_map: &mut SelectorFlagsMap<E>,
bloom_filter: &StyleBloom<E>,
target: &mut StyleSharingTarget<E>,
) -> StyleSharingResult {
) -> Option<ElementStyles> {
if shared_context.options.disable_style_sharing_cache {
debug!("{:?} Cannot share style: style sharing cache disabled",
target.element);
return StyleSharingResult::CannotShare
return None;
}
if target.traversal_parent().is_none() {
debug!("{:?} Cannot share style: element has no parent",
target.element);
return StyleSharingResult::CannotShare
return None;
}
if target.is_native_anonymous() {
debug!("{:?} Cannot share style: NAC", target.element);
return StyleSharingResult::CannotShare;
return None;
}
for (i, candidate) in self.iter_mut().enumerate() {
let sharing_result =
Self::test_candidate(
target,
candidate,
&shared_context,
bloom_filter,
selector_flags_map
);
match sharing_result {
Ok(shared_styles) => {
return StyleSharingResult::StyleWasShared(i, shared_styles)
}
Err(miss) => {
debug!("Cache miss: {:?}", miss);
}
}
}
debug!("{:?} Cannot share style: {} cache entries", target.element,
self.cache().num_entries());
StyleSharingResult::CannotShare
self.cache_mut().lookup(|candidate| {
Self::test_candidate(
target,
candidate,
&shared_context,
bloom_filter,
selector_flags_map
)
})
}
fn test_candidate(
@ -620,13 +604,7 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
shared: &SharedStyleContext,
bloom: &StyleBloom<E>,
selector_flags_map: &mut SelectorFlagsMap<E>
) -> Result<ElementStyles, CacheMiss> {
macro_rules! miss {
($miss: ident) => {
return Err(CacheMiss::$miss);
}
}
) -> bool {
// Check that we have the same parent, or at least that the parents
// share styles and permit sharing across their children. The latter
// check allows us to share style between cousins if the parents
@ -635,37 +613,44 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
let candidate_parent = candidate.element.traversal_parent();
if parent != candidate_parent &&
!checks::can_share_style_across_parents(parent, candidate_parent) {
miss!(Parent)
trace!("Miss: Parent");
return false;
}
if target.is_native_anonymous() {
debug_assert!(!candidate.element.is_native_anonymous(),
"Why inserting NAC into the cache?");
miss!(NativeAnonymousContent)
trace!("Miss: Native Anonymous Content");
return false;
}
if *target.get_local_name() != *candidate.element.get_local_name() {
miss!(LocalName)
trace!("Miss: Local Name");
return false;
}
if *target.get_namespace() != *candidate.element.get_namespace() {
miss!(Namespace)
trace!("Miss: Namespace");
return false;
}
if target.is_link() != candidate.element.is_link() {
miss!(Link)
trace!("Miss: Link");
return false;
}
if target.matches_user_and_author_rules() !=
candidate.element.matches_user_and_author_rules() {
miss!(UserAndAuthorRules)
trace!("Miss: User and Author Rules");
return false;
}
// We do not ignore visited state here, because Gecko
// needs to store extra bits on visited style contexts,
// so these contexts cannot be shared
if target.element.get_state() != candidate.get_state() {
miss!(State)
trace!("Miss: User and Author State");
return false;
}
let element_id = target.element.get_id();
@ -674,32 +659,38 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
// It's possible that there are no styles for either id.
if checks::may_have_rules_for_ids(shared, element_id.as_ref(),
candidate_id.as_ref()) {
miss!(IdAttr)
trace!("Miss: ID Attr");
return false;
}
}
if !checks::have_same_style_attribute(target, candidate) {
miss!(StyleAttr)
trace!("Miss: Style Attr");
return false;
}
if !checks::have_same_class(target, candidate) {
miss!(Class)
trace!("Miss: Class");
return false;
}
if !checks::have_same_presentational_hints(target, candidate) {
miss!(PresHints)
trace!("Miss: Pres Hints");
return false;
}
if !checks::revalidate(target, candidate, shared, bloom,
selector_flags_map) {
miss!(Revalidation)
trace!("Miss: Revalidation");
return false;
}
let data = candidate.element.borrow_data().unwrap();
debug_assert!(target.has_current_styles_for_traversal(&data, shared.traversal_flags));
debug_assert!(target.has_current_styles_for_traversal(
&candidate.element.borrow_data().unwrap(),
shared.traversal_flags)
);
debug!("Sharing allowed between {:?} and {:?}", target.element, candidate.element);
debug!("Sharing style between {:?} and {:?}",
target.element, candidate.element);
Ok(data.styles.clone())
true
}
}

Просмотреть файл

@ -624,7 +624,6 @@ where
E: TElement,
{
use data::RestyleKind::*;
use sharing::StyleSharingResult::*;
context.thread_local.statistics.elements_styled += 1;
let kind = data.restyle_kind(context.shared);
@ -656,12 +655,11 @@ where
// Now that our bloom filter is set up, try the style sharing
// cache.
match target.share_style_if_possible(context) {
StyleWasShared(index, styles) => {
Some(styles) => {
context.thread_local.statistics.styles_shared += 1;
context.thread_local.style_sharing_candidate_cache.touch(index);
styles
}
CannotShare => {
None => {
context.thread_local.statistics.elements_matched += 1;
// Perform the matching and cascading.
let new_styles = {
@ -677,11 +675,11 @@ where
};
context.thread_local
.style_sharing_candidate_cache
.sharing_cache
.insert_if_possible(
&element,
new_styles.primary(),
target.take_validation_data(),
&mut target,
context.thread_local.bloom_filter.matching_depth(),
);

Просмотреть файл

@ -31,6 +31,9 @@ fn size_of_selectors_dummy_types() {
// selectors (with the inline hashes) with as few cache misses as possible.
size_of_test!(test_size_of_rule, style::stylist::Rule, 32);
// Large pages generate tens of thousands of ComputedValues.
size_of_test!(test_size_of_cv, ComputedValues, 272);
size_of_test!(test_size_of_option_arc_cv, Option<Arc<ComputedValues>>, 8);
size_of_test!(test_size_of_option_rule_node, Option<StrongRuleNode>, 8);

Просмотреть файл

@ -11767,7 +11767,7 @@
},
"READER_MODE_PARSE_RESULT" : {
"record_in_processes": ["main", "content"],
"expires_in_version": "58",
"expires_in_version": "never",
"alert_emails": ["firefox-dev@mozilla.org", "gijs@mozilla.com"],
"kind": "enumerated",
"n_values": 5,
@ -11775,7 +11775,7 @@
},
"READER_MODE_DOWNLOAD_RESULT" : {
"record_in_processes": ["main", "content"],
"expires_in_version": "58",
"expires_in_version": "never",
"alert_emails": ["firefox-dev@mozilla.org", "gijs@mozilla.com"],
"kind": "enumerated",
"n_values": 5,

Просмотреть файл

@ -54,6 +54,14 @@ MOZ_ReportCrash(const char* aStr, const char* aFilename, int aLine)
#define NS_RUNTIMEABORT(msg) __coverity_panic__()
// Kills Structurally dead code (UNREACHABLE)
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(_class) \
NS_IMETHODIMP_(bool) \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipThisReal(void* p) \
{ \
__coverity_panic__(); \
_class* tmp = DowncastCCParticipant<_class>(p);
int
GET_JUMP_OFFSET(jsbytecode* pc)
{