forked from mirrors/gecko-dev
Merge inbound to mozilla-central. a=merge
This commit is contained in:
commit
2e2984f826
25 changed files with 318 additions and 95 deletions
|
|
@ -66,6 +66,8 @@ function getRuleState(rule) {
|
|||
isUserAgentStyle: rule.isSystem,
|
||||
// An object containing information about the CSS keyframes rules.
|
||||
keyframesRule: rule.keyframesRule,
|
||||
// The pseudo-element keyword used in the rule.
|
||||
pseudoElement: rule.pseudoElement,
|
||||
// An object containing information about the CSS rule's selector.
|
||||
selector: rule.selector,
|
||||
// An object containing information about the CSS rule's stylesheet source.
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ exports.rule = {
|
|||
keyframesName: PropTypes.string,
|
||||
}),
|
||||
|
||||
// The pseudo-element keyword used in the rule.
|
||||
pseudoElement: PropTypes.string,
|
||||
|
||||
// An object containing information about the CSS rule's selector.
|
||||
selector: PropTypes.shape(selector),
|
||||
|
||||
|
|
|
|||
|
|
@ -192,6 +192,11 @@ webconsole.menu.selectAll.accesskey=A
|
|||
webconsole.menu.openInSidebar.label=Open in sidebar
|
||||
webconsole.menu.openInSidebar.accesskey=V
|
||||
|
||||
# LOCALIZATION NOTE (webconsole.menu.exportClipboard.label)
|
||||
# Label used for a context-menu item displayed on the output. Clicking on it
|
||||
# copies the entire output of the console to the clipboard.
|
||||
webconsole.menu.exportClipboard.label=Export visible messages to clipboard
|
||||
|
||||
# LOCALIZATION NOTE (webconsole.menu.timeWarp.label)
|
||||
# Label used for a context-menu item displayed for any log. Clicking on it will
|
||||
# jump to the execution point where the log item was generated.
|
||||
|
|
|
|||
|
|
@ -283,6 +283,8 @@ skip-if = true # Bug 1405250
|
|||
skip-if = e10s # SharedWorkers console events are not received on the current process because they could run on any process.
|
||||
[browser_webconsole_console_table.js]
|
||||
[browser_webconsole_console_trace_duplicates.js]
|
||||
[browser_webconsole_context_menu_export_console_output_clipboard.js]
|
||||
subsuite = clipboard
|
||||
[browser_webconsole_context_menu_copy_entire_message.js]
|
||||
subsuite = clipboard
|
||||
skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ async function performTests() {
|
|||
"#console-menu-copy (C)",
|
||||
"#console-menu-copy-object (o) [disabled]",
|
||||
"#console-menu-select (A)",
|
||||
"#console-menu-export-clipboard ()",
|
||||
]);
|
||||
is(getSimplifiedContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
|
||||
"The context menu has the expected entries for a network message");
|
||||
|
|
@ -63,6 +64,7 @@ async function performTests() {
|
|||
"#console-menu-copy (C)",
|
||||
"#console-menu-copy-object (o) [disabled]",
|
||||
"#console-menu-select (A)",
|
||||
"#console-menu-export-clipboard ()",
|
||||
]);
|
||||
is(getSimplifiedContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
|
||||
"The context menu has the expected entries for a simple log message");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI =
|
||||
`data:text/html;charset=utf-8,` +
|
||||
`<script>window.logStuff = function () {console.log("hello");};</script>`;
|
||||
const TEST_DATA = {
|
||||
msg: "simple text message",
|
||||
msg2: "second message test",
|
||||
};
|
||||
|
||||
// Test the export visible messages to clipboard of the webconsole copies the expected
|
||||
// clipboard text for different log messages to find if everything is copied to clipboard.
|
||||
|
||||
add_task(async function() {
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
hud.ui.clearOutput();
|
||||
|
||||
info("Call the log function defined in the test page");
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, TEST_DATA, function(testData) {
|
||||
content.wrappedJSObject.console.log(testData.msg);
|
||||
content.wrappedJSObject.console.log(testData.msg2);
|
||||
content.wrappedJSObject.console.log("object:", {a: 1},
|
||||
"array:", ["b", "c"]);
|
||||
content.wrappedJSObject.logStuff();
|
||||
});
|
||||
|
||||
info("Test export to clipboard ");
|
||||
await waitFor(() => findMessages(hud, "").length === 4);
|
||||
const message = findMessage(hud, TEST_DATA.msg);
|
||||
const clipboardText = await exportAllToClipboard(hud, message);
|
||||
ok(true, "Clipboard text was found and saved");
|
||||
|
||||
const clipboardLines = clipboardText.split("\n");
|
||||
info("Check if all messages where copied to clipboard");
|
||||
is(clipboardLines[0].trim(), TEST_DATA.msg,
|
||||
"found first text message in clipboard");
|
||||
is(clipboardLines[1].trim(), TEST_DATA.msg2,
|
||||
"found second text message in clipboard");
|
||||
is(clipboardLines[2].trim(), 'object: Object { a: 1 } array: Array [ "b", "c" ]',
|
||||
"found object and array in clipboard");
|
||||
const CLEAN_URI = TEST_URI.replace("text/html;charset=utf-8,", "");
|
||||
is(clipboardLines[3].trim(), `hello ${CLEAN_URI}:1:32`,
|
||||
"found text from data uri");
|
||||
});
|
||||
|
||||
/**
|
||||
* Simple helper method to open the context menu on a given message, and click on the
|
||||
* export visible messages to clipboard.
|
||||
*/
|
||||
async function exportAllToClipboard(hud, message) {
|
||||
const menuPopup = await openContextMenu(hud, message);
|
||||
const exportClipboard = menuPopup.querySelector("#console-menu-export-clipboard");
|
||||
ok(exportClipboard, "copy menu item is enabled");
|
||||
|
||||
let clipboardText;
|
||||
await waitForClipboardPromise(
|
||||
() => exportClipboard.click(),
|
||||
data => {
|
||||
clipboardText = data;
|
||||
return data;
|
||||
}
|
||||
);
|
||||
return clipboardText;
|
||||
}
|
||||
|
|
@ -170,6 +170,17 @@ function createContextMenu(hud, parentNode, {
|
|||
},
|
||||
}));
|
||||
|
||||
// Export to clipboard
|
||||
menu.append(new MenuItem({
|
||||
id: "console-menu-export-clipboard",
|
||||
label: l10n.getStr("webconsole.menu.exportClipboard.label"),
|
||||
disabled: false,
|
||||
click: () => {
|
||||
const webconsoleOutput = parentNode.querySelector(".webconsole-output");
|
||||
clipboardHelper.copyString(webconsoleOutput.textContent);
|
||||
},
|
||||
}));
|
||||
|
||||
// Open object in sidebar.
|
||||
if (openSidebar) {
|
||||
menu.append(new MenuItem({
|
||||
|
|
|
|||
|
|
@ -7768,6 +7768,19 @@ exports.CSS_PROPERTIES = {
|
|||
"unset"
|
||||
]
|
||||
},
|
||||
"padding-block": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"padding-block-start",
|
||||
"padding-block-end"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"padding-block-end": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
|
|
@ -7804,6 +7817,19 @@ exports.CSS_PROPERTIES = {
|
|||
"unset"
|
||||
]
|
||||
},
|
||||
"padding-inline": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"padding-inline-start",
|
||||
"padding-inline-end"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"padding-inline-end": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
|
|
|
|||
|
|
@ -308,6 +308,21 @@ SharedSurfacesChild::AsSourceSurfaceSharedData(SourceSurface* aSurface) {
|
|||
return rv;
|
||||
}
|
||||
|
||||
/* static */ nsresult SharedSurfacesChild::Share(
|
||||
SourceSurface* aSurface, RenderRootStateManager* aManager,
|
||||
wr::IpcResourceUpdateQueue& aResources, wr::ImageKey& aKey) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aSurface);
|
||||
MOZ_ASSERT(aManager);
|
||||
|
||||
auto sharedSurface = AsSourceSurfaceSharedData(aSurface);
|
||||
if (!sharedSurface) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return Share(sharedSurface, aManager, aResources, aKey);
|
||||
}
|
||||
|
||||
/* static */ nsresult SharedSurfacesChild::Share(
|
||||
ImageContainer* aContainer, RenderRootStateManager* aManager,
|
||||
wr::IpcResourceUpdateQueue& aResources, wr::ImageKey& aKey) {
|
||||
|
|
|
|||
|
|
@ -71,6 +71,16 @@ class SharedSurfacesChild final {
|
|||
wr::IpcResourceUpdateQueue& aResources,
|
||||
wr::ImageKey& aKey);
|
||||
|
||||
/**
|
||||
* Request that the surface be mapped into the compositor thread's memory
|
||||
* space, and a valid ImageKey be generated for it for use with WebRender.
|
||||
* This must be called from the main thread.
|
||||
*/
|
||||
static nsresult Share(gfx::SourceSurface* aSurface,
|
||||
RenderRootStateManager* aManager,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
wr::ImageKey& aKey);
|
||||
|
||||
/**
|
||||
* Request that the first surface in the image container's current images be
|
||||
* mapped into the compositor thread's memory space, and a valid ImageKey be
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "BasicLayers.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
|
|
@ -184,18 +185,14 @@ static void TakeExternalSurfaces(
|
|||
aRecorder->TakeExternalSurfaces(aExternalSurfaces);
|
||||
|
||||
for (auto& surface : aExternalSurfaces) {
|
||||
if (surface->GetType() != SurfaceType::DATA_SHARED) {
|
||||
MOZ_ASSERT_UNREACHABLE("External surface that is not a shared surface!");
|
||||
continue;
|
||||
}
|
||||
|
||||
// While we don't use the image key with the surface, because the blob image
|
||||
// renderer doesn't have easy access to the resource set, we still want to
|
||||
// ensure one is generated. That will ensure the surface remains alive until
|
||||
// at least the last epoch which the blob image could be used in.
|
||||
wr::ImageKey key;
|
||||
auto sharedSurface = static_cast<SourceSurfaceSharedData*>(surface.get());
|
||||
SharedSurfacesChild::Share(sharedSurface, aManager, aResources, key);
|
||||
DebugOnly<nsresult> rv =
|
||||
SharedSurfacesChild::Share(surface, aManager, aResources, key);
|
||||
MOZ_ASSERT(rv.value != NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -352,9 +352,7 @@ void AnimationFrameRecyclingQueue::AdvanceInternal() {
|
|||
|
||||
// If we are allowed to recycle the frame, then we should save it before the
|
||||
// base class's AdvanceInternal discards it.
|
||||
if (front->ShouldRecycle()) {
|
||||
newEntry.mFrame = std::move(front);
|
||||
}
|
||||
newEntry.mFrame = std::move(front);
|
||||
|
||||
// Even if the frame itself isn't saved, we want the dirty rect to calculate
|
||||
// the recycle rect for future recycled frames.
|
||||
|
|
@ -393,11 +391,9 @@ bool AnimationFrameRecyclingQueue::ResetInternal() {
|
|||
// existing mRecycle entries, because that will happen in RecycleFrame when
|
||||
// we try to pull out a frame to redecode the first frame.
|
||||
for (RefPtr<imgFrame>& frame : mDisplay) {
|
||||
if (frame->ShouldRecycle()) {
|
||||
RecycleEntry newEntry(mFirstFrameRefreshArea);
|
||||
newEntry.mFrame = std::move(frame);
|
||||
mRecycle.push_back(std::move(newEntry));
|
||||
}
|
||||
RecycleEntry newEntry(mFirstFrameRefreshArea);
|
||||
newEntry.mFrame = std::move(frame);
|
||||
mRecycle.push_back(std::move(newEntry));
|
||||
}
|
||||
|
||||
return AnimationFrameDiscardingQueue::ResetInternal();
|
||||
|
|
|
|||
|
|
@ -350,8 +350,7 @@ RawAccessFrameRef Decoder::AllocateFrameInternal(
|
|||
// animation parameters elsewhere. For now we just drop it.
|
||||
bool blocked = ref.get() == mRestoreFrame.get();
|
||||
if (!blocked) {
|
||||
nsresult rv = ref->InitForDecoderRecycle(aAnimParams.ref());
|
||||
blocked = NS_WARN_IF(NS_FAILED(rv));
|
||||
blocked = NS_FAILED(ref->InitForDecoderRecycle(aAnimParams.ref()));
|
||||
}
|
||||
|
||||
if (blocked) {
|
||||
|
|
|
|||
|
|
@ -305,7 +305,12 @@ nsresult imgFrame::InitForDecoderRecycle(const AnimationParams& aAnimParams) {
|
|||
MOZ_ASSERT(mIsFullFrame);
|
||||
MOZ_ASSERT(mLockCount > 0);
|
||||
MOZ_ASSERT(mLockedSurface);
|
||||
MOZ_ASSERT(mShouldRecycle);
|
||||
|
||||
if (!mShouldRecycle) {
|
||||
// This frame either was never marked as recyclable, or the flag was cleared
|
||||
// for a caller which does not support recycling.
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (mRecycleLockCount > 0) {
|
||||
if (NS_IsMainThread()) {
|
||||
|
|
@ -624,8 +629,8 @@ bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion,
|
|||
// this frame is the current frame of the animation. Since we can only
|
||||
// advance on the main thread, we know nothing else will try to use it.
|
||||
DrawTarget* drawTarget = aContext->GetDrawTarget();
|
||||
bool temporary = !drawTarget->IsCaptureDT() &&
|
||||
drawTarget->GetBackendType() != BackendType::RECORDING;
|
||||
bool recording = drawTarget->GetBackendType() == BackendType::RECORDING;
|
||||
bool temporary = !drawTarget->IsCaptureDT() && !recording;
|
||||
RefPtr<SourceSurface> surf = GetSourceSurfaceInternal(temporary);
|
||||
if (!surf) {
|
||||
return false;
|
||||
|
|
@ -635,6 +640,14 @@ bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion,
|
|||
!(aImageFlags & imgIContainer::FLAG_CLAMP);
|
||||
|
||||
surfaceResult = SurfaceForDrawing(doPartialDecode, doTile, region, surf);
|
||||
|
||||
// If we are recording, then we cannot recycle the surface. The blob
|
||||
// rasterizer is not properly synchronized for recycling in the compositor
|
||||
// process. The easiest thing to do is just mark the frames it consumes as
|
||||
// non-recyclable.
|
||||
if (recording && surfaceResult.IsValid()) {
|
||||
mShouldRecycle = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (surfaceResult.IsValid()) {
|
||||
|
|
|
|||
|
|
@ -202,8 +202,6 @@ class imgFrame {
|
|||
bool GetCompositingFailed() const;
|
||||
void SetCompositingFailed(bool val);
|
||||
|
||||
bool ShouldRecycle() const { return mShouldRecycle; }
|
||||
|
||||
void SetOptimizable();
|
||||
|
||||
void FinalizeSurface();
|
||||
|
|
|
|||
|
|
@ -31,6 +31,17 @@ static already_AddRefed<imgFrame> CreateEmptyFrame(
|
|||
return frame.forget();
|
||||
}
|
||||
|
||||
static bool ReinitForRecycle(RawAccessFrameRef& aFrame) {
|
||||
if (!aFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AnimationParams animParams{aFrame->GetRect(), FrameTimeout::Forever(),
|
||||
/* aFrameNum */ 1, BlendMethod::OVER,
|
||||
DisposalMethod::NOT_SPECIFIED};
|
||||
return NS_SUCCEEDED(aFrame->InitForDecoderRecycle(animParams));
|
||||
}
|
||||
|
||||
static void PrepareForDiscardingQueue(AnimationFrameRetainedBuffer& aQueue) {
|
||||
ASSERT_EQ(size_t(0), aQueue.Size());
|
||||
ASSERT_LT(size_t(1), aQueue.Batch());
|
||||
|
|
@ -100,11 +111,7 @@ static void VerifyAdvance(AnimationFrameBuffer& aQueue, size_t aExpectedFrame,
|
|||
EXPECT_TRUE(
|
||||
queue.Recycle().back().mDirtyRect.Contains(oldFrame->GetDirtyRect()));
|
||||
EXPECT_EQ(totalRecycled + 1, queue.Recycle().size());
|
||||
if (oldFrame->ShouldRecycle()) {
|
||||
EXPECT_EQ(oldFrame.get(), queue.Recycle().back().mFrame.get());
|
||||
} else {
|
||||
EXPECT_EQ(nullptr, queue.Recycle().back().mFrame.get());
|
||||
}
|
||||
EXPECT_EQ(oldFrame.get(), queue.Recycle().back().mFrame.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -564,13 +571,14 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingLoop) {
|
|||
RawAccessFrameRef gotFrame = buffer.RecycleFrame(gotRect);
|
||||
EXPECT_EQ(expectedFrame.get(), gotFrame.get());
|
||||
EXPECT_EQ(expectedRect, gotRect);
|
||||
EXPECT_TRUE(ReinitForRecycle(gotFrame));
|
||||
}
|
||||
|
||||
// Trying to pull a recycled frame when we have nothing should be safe too.
|
||||
IntRect gotRect;
|
||||
RawAccessFrameRef gotFrame = buffer.RecycleFrame(gotRect);
|
||||
EXPECT_TRUE(gotFrame.get() == nullptr);
|
||||
EXPECT_TRUE(gotRect.IsEmpty());
|
||||
EXPECT_FALSE(ReinitForRecycle(gotFrame));
|
||||
}
|
||||
|
||||
static void TestDiscardingQueueReset(AnimationFrameDiscardingQueue& aQueue,
|
||||
|
|
@ -745,7 +753,13 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingResetBeforeComplete) {
|
|||
EXPECT_TRUE(restartDecoding);
|
||||
|
||||
// None of the buffers were recyclable.
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
while (!buffer.Recycle().empty()) {
|
||||
IntRect recycleRect;
|
||||
RawAccessFrameRef frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_TRUE(frameRef);
|
||||
EXPECT_FALSE(ReinitForRecycle(frameRef));
|
||||
}
|
||||
|
||||
// Reinsert the first two frames as recyclable and reset again.
|
||||
frame = CreateEmptyFrame(kImageSize, kImageRect, true);
|
||||
|
|
@ -773,28 +787,25 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingRect) {
|
|||
const size_t kBatch = 2;
|
||||
const size_t kStartFrame = 0;
|
||||
const IntSize kImageSize(100, 100);
|
||||
const IntRect kImageRect(IntPoint(0, 0), kImageSize);
|
||||
AnimationFrameRetainedBuffer retained(kThreshold, kBatch, kStartFrame);
|
||||
|
||||
// Let's get to the recycling state while marking all of the frames as not
|
||||
// recyclable, just like AnimationFrameBuffer / the decoders would do.
|
||||
RefPtr<imgFrame> frame;
|
||||
frame =
|
||||
CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
frame = CreateEmptyFrame(kImageSize, kImageRect, false);
|
||||
AnimationFrameBuffer::InsertStatus status = retained.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::CONTINUE, status);
|
||||
|
||||
frame =
|
||||
CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
frame = CreateEmptyFrame(kImageSize, kImageRect, false);
|
||||
status = retained.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::CONTINUE, status);
|
||||
|
||||
frame =
|
||||
CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
frame = CreateEmptyFrame(kImageSize, kImageRect, false);
|
||||
status = retained.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::CONTINUE, status);
|
||||
|
||||
frame =
|
||||
CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
frame = CreateEmptyFrame(kImageSize, kImageRect, false);
|
||||
status = retained.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::YIELD, status);
|
||||
|
||||
|
|
@ -802,8 +813,7 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingRect) {
|
|||
VerifyAdvance(retained, 2, true);
|
||||
VerifyAdvance(retained, 3, false);
|
||||
|
||||
frame =
|
||||
CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
frame = CreateEmptyFrame(kImageSize, kImageRect, false);
|
||||
status = retained.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::DISCARD_CONTINUE, status);
|
||||
|
||||
|
|
@ -816,8 +826,8 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingRect) {
|
|||
IntRect recycleRect;
|
||||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
RawAccessFrameRef frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_FALSE(frameRef);
|
||||
EXPECT_TRUE(recycleRect.IsEmpty());
|
||||
EXPECT_TRUE(frameRef);
|
||||
EXPECT_FALSE(ReinitForRecycle(frameRef));
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
|
||||
// Insert a recyclable partial frame. Its dirty rect shouldn't matter since
|
||||
|
|
@ -829,8 +839,8 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingRect) {
|
|||
VerifyAdvance(buffer, 5, true);
|
||||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_FALSE(frameRef);
|
||||
EXPECT_TRUE(recycleRect.IsEmpty());
|
||||
EXPECT_TRUE(frameRef);
|
||||
EXPECT_FALSE(ReinitForRecycle(frameRef));
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
|
||||
// Insert a recyclable partial frame. Its dirty rect should match the recycle
|
||||
|
|
@ -843,6 +853,7 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingRect) {
|
|||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_TRUE(frameRef);
|
||||
EXPECT_TRUE(ReinitForRecycle(frameRef));
|
||||
EXPECT_EQ(IntRect(25, 0, 50, 50), recycleRect);
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
|
||||
|
|
@ -860,14 +871,14 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingRect) {
|
|||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_TRUE(frameRef);
|
||||
EXPECT_TRUE(ReinitForRecycle(frameRef));
|
||||
EXPECT_EQ(IntRect(0, 0, 75, 50), recycleRect);
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
|
||||
// Now let's reinsert the first frame. The recycle rect should still be the
|
||||
// first frame refresh area instead of the dirty rect of the first frame (e.g.
|
||||
// the full frame).
|
||||
frame =
|
||||
CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
frame = CreateEmptyFrame(kImageSize, kImageRect, false);
|
||||
status = buffer.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::YIELD, status);
|
||||
|
||||
|
|
@ -875,6 +886,7 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingRect) {
|
|||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_TRUE(frameRef);
|
||||
EXPECT_TRUE(ReinitForRecycle(frameRef));
|
||||
EXPECT_EQ(IntRect(0, 0, 75, 50), recycleRect);
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1044,14 +1044,18 @@ bool GeckoChildProcessHost::PerformAsyncLaunch(
|
|||
#ifdef MOZ_SANDBOX
|
||||
// We need to be able to duplicate handles to some types of non-sandboxed
|
||||
// child processes.
|
||||
if (mProcessType == GeckoProcessType_Content ||
|
||||
mProcessType == GeckoProcessType_GPU ||
|
||||
mProcessType == GeckoProcessType_RDD ||
|
||||
mProcessType == GeckoProcessType_VR ||
|
||||
mProcessType == GeckoProcessType_GMPlugin) {
|
||||
if (!mSandboxBroker.AddTargetPeer(process)) {
|
||||
NS_WARNING("Failed to add content process as target peer.");
|
||||
}
|
||||
switch (mProcessType) {
|
||||
case GeckoProcessType_Default:
|
||||
MOZ_CRASH("shouldn't be launching a parent process");
|
||||
case GeckoProcessType_Plugin:
|
||||
case GeckoProcessType_IPDLUnitTest:
|
||||
// No handle duplication necessary.
|
||||
break;
|
||||
default:
|
||||
if (!mSandboxBroker.AddTargetPeer(process)) {
|
||||
NS_WARNING("Failed to add child process as target peer.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif // MOZ_SANDBOX
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ class SharedPreferenceDeserializer final {
|
|||
Maybe<FileDescriptor> mPrefMapHandle;
|
||||
Maybe<size_t> mPrefsLen;
|
||||
Maybe<size_t> mPrefMapSize;
|
||||
base::SharedMemory mShmem;
|
||||
};
|
||||
|
||||
#ifdef ANDROID
|
||||
|
|
|
|||
|
|
@ -139,16 +139,15 @@ bool SharedPreferenceDeserializer::DeserializeFromSharedMemory(
|
|||
Preferences::InitSnapshot(mPrefMapHandle.ref(), *mPrefMapSize);
|
||||
|
||||
// Set up early prefs from the shared memory.
|
||||
base::SharedMemory shm;
|
||||
if (!shm.SetHandle(*mPrefsHandle, /* read_only */ true)) {
|
||||
if (!mShmem.SetHandle(*mPrefsHandle, /* read_only */ true)) {
|
||||
NS_ERROR("failed to open shared memory in the child");
|
||||
return false;
|
||||
}
|
||||
if (!shm.Map(*mPrefsLen)) {
|
||||
if (!mShmem.Map(*mPrefsLen)) {
|
||||
NS_ERROR("failed to map shared memory in the child");
|
||||
return false;
|
||||
}
|
||||
Preferences::DeserializePreferences(static_cast<char*>(shm.memory()),
|
||||
Preferences::DeserializePreferences(static_cast<char*>(mShmem.memory()),
|
||||
*mPrefsLen);
|
||||
|
||||
return true;
|
||||
|
|
@ -168,4 +167,4 @@ const FileDescriptor& SharedPreferenceDeserializer::GetPrefMapHandle() const {
|
|||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
} // namespace mozilla
|
||||
|
|
|
|||
|
|
@ -7249,9 +7249,12 @@ GCRuntime::IncrementalResult GCRuntime::budgetIncrementalGC(
|
|||
if (mallocCounter.shouldTriggerGC(tunables) == NonIncrementalTrigger) {
|
||||
budget.makeUnlimited();
|
||||
stats().nonincremental(AbortReason::MallocBytesTrigger);
|
||||
if (isIncrementalGCInProgress() && state() > State::Sweep) {
|
||||
return resetIncrementalGC(AbortReason::MallocBytesTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
bool reset = false;
|
||||
AbortReason resetReason = AbortReason::None;
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||
if (!zone->canCollect()) {
|
||||
continue;
|
||||
|
|
@ -7261,23 +7264,29 @@ GCRuntime::IncrementalResult GCRuntime::budgetIncrementalGC(
|
|||
CheckZoneIsScheduled(zone, reason, "GC bytes");
|
||||
budget.makeUnlimited();
|
||||
stats().nonincremental(AbortReason::GCBytesTrigger);
|
||||
if (zone->wasGCStarted() && zone->gcState() > Zone::Sweep) {
|
||||
resetReason = AbortReason::GCBytesTrigger;
|
||||
}
|
||||
}
|
||||
|
||||
if (zone->shouldTriggerGCForTooMuchMalloc() == NonIncrementalTrigger) {
|
||||
CheckZoneIsScheduled(zone, reason, "malloc bytes");
|
||||
budget.makeUnlimited();
|
||||
stats().nonincremental(AbortReason::MallocBytesTrigger);
|
||||
if (zone->wasGCStarted() && zone->gcState() > Zone::Sweep) {
|
||||
resetReason = AbortReason::MallocBytesTrigger;
|
||||
}
|
||||
}
|
||||
|
||||
if (isIncrementalGCInProgress() &&
|
||||
zone->isGCScheduled() != zone->wasGCStarted()) {
|
||||
reset = true;
|
||||
budget.makeUnlimited();
|
||||
resetReason = AbortReason::ZoneChange;
|
||||
}
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
budget.makeUnlimited();
|
||||
return resetIncrementalGC(AbortReason::ZoneChange);
|
||||
if (resetReason != AbortReason::None) {
|
||||
return resetIncrementalGC(resetReason);
|
||||
}
|
||||
|
||||
return IncrementalResult::Ok;
|
||||
|
|
@ -7631,6 +7640,15 @@ void GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget,
|
|||
}
|
||||
} while (repeat);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!isIncrementalGCInProgress()) {
|
||||
for (ZonesIter zone(rt, WithAtoms); zone.done(); zone.next()) {
|
||||
MOZ_ASSERT(!zone->gcMallocCounter.triggered());
|
||||
MOZ_ASSERT(!zone->jitCodeCounter.triggered());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (reason == JS::gcreason::COMPARTMENT_REVIVED) {
|
||||
maybeDoCycleCollection();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4270,6 +4270,26 @@ var gCSSProperties = {
|
|||
unbalanced_values: [ "1px calc(" ],
|
||||
quirks_values: { "5": "5px", "3px 6px 2 5px": "3px 6px 2px 5px" },
|
||||
},
|
||||
"padding-block": {
|
||||
domProp: "paddingBlock",
|
||||
inherited: false,
|
||||
type: CSS_TYPE_TRUE_SHORTHAND,
|
||||
subproperties: [ "padding-block-start", "padding-block-end" ],
|
||||
initial_values: [ "0", "0px 0em" ],
|
||||
other_values: [ "3px 0", "2% 4px", "1em", "calc(1px) calc(-1%)" ],
|
||||
invalid_values: [ "1px calc(nonsense)", "1px red", "-1px", "auto", "none" ],
|
||||
unbalanced_values: [ "1px calc(" ],
|
||||
},
|
||||
"padding-inline": {
|
||||
domProp: "paddingInline",
|
||||
inherited: false,
|
||||
type: CSS_TYPE_TRUE_SHORTHAND,
|
||||
subproperties: [ "padding-inline-start", "padding-inline-end" ],
|
||||
initial_values: [ "0", "0px 0em" ],
|
||||
other_values: [ "3px 0", "2% 4px", "1em", "calc(1px) calc(-1%)" ],
|
||||
invalid_values: [ "1px calc(nonsense)", "1px red", "-1px", "auto", "none" ],
|
||||
unbalanced_values: [ "1px calc(" ],
|
||||
},
|
||||
"padding-bottom": {
|
||||
domProp: "paddingBottom",
|
||||
inherited: false,
|
||||
|
|
|
|||
|
|
@ -7,3 +7,46 @@
|
|||
${helpers.four_sides_shorthand("padding", "padding-%s", "specified::NonNegativeLengthPercentage::parse",
|
||||
spec="https://drafts.csswg.org/css-box-3/#propdef-padding",
|
||||
allow_quirks=True)}
|
||||
|
||||
% for axis in ["block", "inline"]:
|
||||
<%
|
||||
spec = "https://drafts.csswg.org/css-logical/#propdef-padding-%s" % axis
|
||||
%>
|
||||
<%helpers:shorthand
|
||||
name="padding-${axis}"
|
||||
sub_properties="${' '.join(
|
||||
'padding-%s-%s' % (axis, side)
|
||||
for side in ['start', 'end']
|
||||
)}"
|
||||
spec="${spec}">
|
||||
|
||||
use crate::parser::Parse;
|
||||
use crate::values::specified::length::NonNegativeLengthPercentage;
|
||||
pub fn parse_value<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Longhands, ParseError<'i>> {
|
||||
let start_value = NonNegativeLengthPercentage::parse(context, input)?;
|
||||
let end_value =
|
||||
input.try(|input| NonNegativeLengthPercentage::parse(context, input)).unwrap_or_else(|_| start_value.clone());
|
||||
|
||||
Ok(expanded! {
|
||||
padding_${axis}_start: start_value,
|
||||
padding_${axis}_end: end_value,
|
||||
})
|
||||
}
|
||||
|
||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
||||
self.padding_${axis}_start.to_css(dest)?;
|
||||
|
||||
if self.padding_${axis}_end != self.padding_${axis}_start {
|
||||
dest.write_str(" ")?;
|
||||
self.padding_${axis}_end.to_css(dest)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
</%helpers:shorthand>
|
||||
% endfor
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ For developers
|
|||
Communication
|
||||
=============
|
||||
|
||||
The mailing list for Marionette discussion is
|
||||
The mailing list for geckodriver discussion is
|
||||
tools-marionette@lists.mozilla.org (`subscribe`_, `archive`_).
|
||||
|
||||
If you prefer real-time chat, there is often someone in the #ateam IRC
|
||||
|
|
|
|||
|
|
@ -1,40 +1,13 @@
|
|||
[logical-box-padding.html]
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: horizontal-tb; direction: ltr; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: vertical-rl; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: sideways-rl; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: vertical-rl; direction: ltr; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: sideways-rl; direction: ltr; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: vertical-lr; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: sideways-lr; direction: ltr; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: vertical-lr; direction: ltr; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: sideways-lr; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding shorthand sets longhands and serializes correctly.]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=137688
|
||||
|
||||
[Test that padding-inline shorthand sets longhands and serializes correctly.]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=137688
|
||||
|
||||
[Test that padding-block shorthand sets longhands and serializes correctly.]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=137688
|
||||
|
||||
|
|
|
|||
|
|
@ -454,7 +454,12 @@ nsThreadManager::NewNamedThread(const nsACString& aName, uint32_t aStackSize,
|
|||
NS_IMETHODIMP
|
||||
nsThreadManager::GetMainThread(nsIThread** aResult) {
|
||||
// Keep this functioning during Shutdown
|
||||
if (NS_WARN_IF(!mMainThread)) {
|
||||
if (!mMainThread) {
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_WARNING(
|
||||
"Called GetMainThread but there isn't a main thread and "
|
||||
"we're not the main thread.");
|
||||
}
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
NS_ADDREF(*aResult = mMainThread);
|
||||
|
|
|
|||
Loading…
Reference in a new issue