Merge inbound to mozilla-central. a=merge

This commit is contained in:
Brindusan Cristian 2019-01-14 23:51:26 +02:00
commit 2e2984f826
25 changed files with 318 additions and 95 deletions

View file

@ -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.

View file

@ -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),

View file

@ -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.

View file

@ -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

View file

@ -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");

View file

@ -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;
}

View file

@ -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({

View file

@ -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": [

View file

@ -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) {

View file

@ -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

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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) {

View file

@ -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()) {

View file

@ -202,8 +202,6 @@ class imgFrame {
bool GetCompositingFailed() const;
void SetCompositingFailed(bool val);
bool ShouldRecycle() const { return mShouldRecycle; }
void SetOptimizable();
void FinalizeSurface();

View file

@ -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());
}

View file

@ -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
}

View file

@ -63,6 +63,7 @@ class SharedPreferenceDeserializer final {
Maybe<FileDescriptor> mPrefMapHandle;
Maybe<size_t> mPrefsLen;
Maybe<size_t> mPrefMapSize;
base::SharedMemory mShmem;
};
#ifdef ANDROID

View file

@ -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

View file

@ -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();
}

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);