зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central r=merge a=merge
This commit is contained in:
Коммит
7bcf901c3b
|
@ -24,6 +24,7 @@ using mozilla::wr::ImageKey from "mozilla/webrender/WebRenderTypes.h";
|
|||
using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
|
||||
using mozilla::gfx::MaybeIntSize from "mozilla/gfx/Point.h";
|
||||
using mozilla::LayoutDeviceRect from "Units.h";
|
||||
using mozilla::ImageIntRect from "Units.h";
|
||||
using class mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h";
|
||||
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
|
||||
|
||||
|
@ -96,6 +97,7 @@ struct OpUpdateBlobImage {
|
|||
ImageDescriptor descriptor;
|
||||
OffsetRange bytes;
|
||||
ImageKey key;
|
||||
ImageIntRect dirtyRect;
|
||||
};
|
||||
|
||||
struct OpDeleteImage {
|
||||
|
|
|
@ -279,13 +279,14 @@ IpcResourceUpdateQueue::UpdateImageBuffer(ImageKey aKey,
|
|||
bool
|
||||
IpcResourceUpdateQueue::UpdateBlobImage(ImageKey aKey,
|
||||
const ImageDescriptor& aDescriptor,
|
||||
Range<uint8_t> aBytes)
|
||||
Range<uint8_t> aBytes,
|
||||
ImageIntRect aDirtyRect)
|
||||
{
|
||||
auto bytes = mWriter.Write(aBytes);
|
||||
if (!bytes.length()) {
|
||||
return false;
|
||||
}
|
||||
mUpdates.AppendElement(layers::OpUpdateBlobImage(aDescriptor, bytes, aKey));
|
||||
mUpdates.AppendElement(layers::OpUpdateBlobImage(aDescriptor, bytes, aKey, aDirtyRect));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,8 @@ public:
|
|||
|
||||
bool UpdateBlobImage(wr::ImageKey aKey,
|
||||
const ImageDescriptor& aDescriptor,
|
||||
Range<uint8_t> aBytes);
|
||||
Range<uint8_t> aBytes,
|
||||
ImageIntRect aDirtyRect);
|
||||
|
||||
void UpdateExternalImage(ImageKey aKey,
|
||||
const ImageDescriptor& aDescriptor,
|
||||
|
|
|
@ -285,7 +285,7 @@ WebRenderBridgeParent::UpdateResources(const nsTArray<OpUpdateResource>& aResour
|
|||
if (!reader.Read(op.bytes(), bytes)) {
|
||||
return false;
|
||||
}
|
||||
aUpdates.UpdateBlobImage(op.key(), op.descriptor(), bytes);
|
||||
aUpdates.UpdateBlobImage(op.key(), op.descriptor(), bytes, wr::ToDeviceUintRect(op.dirtyRect()));
|
||||
break;
|
||||
}
|
||||
case OpUpdateResource::TOpAddExternalImage: {
|
||||
|
|
|
@ -528,12 +528,14 @@ ResourceUpdateQueue::UpdateImageBuffer(ImageKey aKey,
|
|||
void
|
||||
ResourceUpdateQueue::UpdateBlobImage(ImageKey aKey,
|
||||
const ImageDescriptor& aDescriptor,
|
||||
wr::Vec_u8& aBytes)
|
||||
wr::Vec_u8& aBytes,
|
||||
const wr::DeviceUintRect& aDirtyRect)
|
||||
{
|
||||
wr_resource_updates_update_blob_image(mUpdates,
|
||||
aKey,
|
||||
&aDescriptor,
|
||||
&aBytes.inner);
|
||||
&aBytes.inner,
|
||||
aDirtyRect);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -86,7 +86,8 @@ public:
|
|||
|
||||
void UpdateBlobImage(wr::ImageKey aKey,
|
||||
const ImageDescriptor& aDescriptor,
|
||||
wr::Vec_u8& aBytes);
|
||||
wr::Vec_u8& aBytes,
|
||||
const wr::DeviceUintRect& aDirtyRect);
|
||||
|
||||
void UpdateExternalImage(ImageKey aKey,
|
||||
const ImageDescriptor& aDescriptor,
|
||||
|
|
|
@ -304,6 +304,16 @@ static inline wr::LayoutRect ToLayoutRect(const gfxRect rect)
|
|||
return r;
|
||||
}
|
||||
|
||||
static inline wr::DeviceUintRect ToDeviceUintRect(const mozilla::ImageIntRect& rect)
|
||||
{
|
||||
wr::DeviceUintRect r;
|
||||
r.origin.x = rect.x;
|
||||
r.origin.y = rect.y;
|
||||
r.size.width = rect.width;
|
||||
r.size.height = rect.height;
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline wr::LayoutRect ToLayoutRect(const mozilla::LayoutDeviceIntRect& rect)
|
||||
{
|
||||
return ToLayoutRect(IntRectToRect(rect));
|
||||
|
|
|
@ -794,12 +794,13 @@ pub extern "C" fn wr_resource_updates_update_blob_image(
|
|||
image_key: WrImageKey,
|
||||
descriptor: &WrImageDescriptor,
|
||||
bytes: &mut WrVecU8,
|
||||
dirty_rect: DeviceUintRect,
|
||||
) {
|
||||
resources.update_image(
|
||||
image_key,
|
||||
descriptor.into(),
|
||||
ImageData::new_blob_image(bytes.flush_into_vec()),
|
||||
None
|
||||
Some(dirty_rect)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -832,6 +832,40 @@ struct FontInstancePlatformOptions {
|
|||
};
|
||||
#endif
|
||||
|
||||
// A 2d Point tagged with a unit.
|
||||
struct TypedPoint2D_u32__DevicePixel {
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
|
||||
bool operator==(const TypedPoint2D_u32__DevicePixel& aOther) const {
|
||||
return x == aOther.x &&
|
||||
y == aOther.y;
|
||||
}
|
||||
};
|
||||
|
||||
struct TypedSize2D_u32__DevicePixel {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
bool operator==(const TypedSize2D_u32__DevicePixel& aOther) const {
|
||||
return width == aOther.width &&
|
||||
height == aOther.height;
|
||||
}
|
||||
};
|
||||
|
||||
// A 2d Rectangle optionally tagged with a unit.
|
||||
struct TypedRect_u32__DevicePixel {
|
||||
TypedPoint2D_u32__DevicePixel origin;
|
||||
TypedSize2D_u32__DevicePixel size;
|
||||
|
||||
bool operator==(const TypedRect_u32__DevicePixel& aOther) const {
|
||||
return origin == aOther.origin &&
|
||||
size == aOther.size;
|
||||
}
|
||||
};
|
||||
|
||||
typedef TypedRect_u32__DevicePixel DeviceUintRect;
|
||||
|
||||
/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
|
||||
* To generate this file:
|
||||
* 1. Get the latest cbindgen using `cargo install --force cbindgen`
|
||||
|
@ -1374,7 +1408,8 @@ WR_INLINE
|
|||
void wr_resource_updates_update_blob_image(ResourceUpdates *aResources,
|
||||
WrImageKey aImageKey,
|
||||
const WrImageDescriptor *aDescriptor,
|
||||
WrVecU8 *aBytes)
|
||||
WrVecU8 *aBytes,
|
||||
DeviceUintRect aDirtyRect)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
|
|
|
@ -2884,6 +2884,36 @@ js::str_replace_string_raw(JSContext* cx, HandleString string, HandleString patt
|
|||
return BuildFlatReplacement(cx, string, repl, match, patternLength);
|
||||
}
|
||||
|
||||
static ArrayObject*
|
||||
NewFullyAllocatedStringArray(JSContext* cx, HandleObjectGroup group, uint32_t length)
|
||||
{
|
||||
ArrayObject* array = NewFullyAllocatedArrayTryUseGroup(cx, group, length);
|
||||
if (!array)
|
||||
return nullptr;
|
||||
|
||||
// Only string values will be added to this array. Inform TI early about
|
||||
// the element type, so we can directly initialize all elements using
|
||||
// NativeObject::initDenseElement() instead of the slightly more expensive
|
||||
// NativeObject::initDenseElementWithType() method.
|
||||
// Since this function is never called to create a zero-length array, it's
|
||||
// always necessary and correct to call AddTypePropertyId here.
|
||||
MOZ_ASSERT(length > 0);
|
||||
AddTypePropertyId(cx, array, JSID_VOID, TypeSet::StringType());
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
static ArrayObject*
|
||||
SingleElementStringArray(JSContext* cx, HandleObjectGroup group, HandleLinearString str)
|
||||
{
|
||||
ArrayObject* array = NewFullyAllocatedStringArray(cx, group, 1);
|
||||
if (!array)
|
||||
return nullptr;
|
||||
array->setDenseInitializedLength(1);
|
||||
array->initDenseElement(0, StringValue(str));
|
||||
return array;
|
||||
}
|
||||
|
||||
// ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
|
||||
static ArrayObject*
|
||||
SplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleLinearString sep,
|
||||
|
@ -2903,8 +2933,7 @@ SplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleLinearS
|
|||
return NewFullyAllocatedArrayTryUseGroup(cx, group, 0);
|
||||
|
||||
// Steps 12.c-e.
|
||||
RootedValue v(cx, StringValue(str));
|
||||
return NewCopiedArrayTryUseGroup(cx, group, v.address(), 1);
|
||||
return SingleElementStringArray(cx, group, str);
|
||||
}
|
||||
|
||||
// Step 3 (reordered).
|
||||
|
@ -2991,19 +3020,22 @@ CharSplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleObj
|
|||
|
||||
js::StaticStrings& staticStrings = cx->staticStrings();
|
||||
uint32_t resultlen = (limit < strLength ? limit : strLength);
|
||||
MOZ_ASSERT(limit > 0 && resultlen > 0,
|
||||
"Neither limit nor strLength is zero, so resultlen is greater than zero.");
|
||||
|
||||
AutoValueVector splits(cx);
|
||||
if (!splits.reserve(resultlen))
|
||||
RootedArrayObject splits(cx, NewFullyAllocatedStringArray(cx, group, resultlen));
|
||||
if (!splits)
|
||||
return nullptr;
|
||||
splits->ensureDenseInitializedLength(cx, 0, resultlen);
|
||||
|
||||
for (size_t i = 0; i < resultlen; ++i) {
|
||||
JSString* sub = staticStrings.getUnitStringForElement(cx, str, i);
|
||||
if (!sub)
|
||||
return nullptr;
|
||||
splits.infallibleAppend(StringValue(sub));
|
||||
splits->initDenseElement(i, StringValue(sub));
|
||||
}
|
||||
|
||||
return NewCopiedArrayTryUseGroup(cx, group, splits.begin(), splits.length());
|
||||
return splits;
|
||||
}
|
||||
|
||||
template <typename TextChar>
|
||||
|
@ -3019,34 +3051,36 @@ SplitSingleCharHelper(JSContext* cx, HandleLinearString str, const TextChar* tex
|
|||
}
|
||||
|
||||
// Handle zero-occurrence case - return input string in an array.
|
||||
if (count == 0) {
|
||||
RootedValue strValue(cx, StringValue(str.get()));
|
||||
return NewCopiedArrayTryUseGroup(cx, group, &strValue.get(), 1);
|
||||
}
|
||||
if (count == 0)
|
||||
return SingleElementStringArray(cx, group, str);
|
||||
|
||||
// Reserve memory for substring values.
|
||||
AutoValueVector splits(cx);
|
||||
if (!splits.reserve(count + 1))
|
||||
// Create the result array for the substring values.
|
||||
RootedArrayObject splits(cx, NewFullyAllocatedStringArray(cx, group, count + 1));
|
||||
if (!splits)
|
||||
return nullptr;
|
||||
splits->ensureDenseInitializedLength(cx, 0, count + 1);
|
||||
|
||||
// Add substrings.
|
||||
uint32_t splitsIndex = 0;
|
||||
size_t lastEndIndex = 0;
|
||||
for (size_t index = 0; index < textLen; index++) {
|
||||
if (static_cast<char16_t>(text[index]) == patCh) {
|
||||
size_t subLength = size_t(index - lastEndIndex);
|
||||
JSString* sub = NewDependentString(cx, str, lastEndIndex, subLength);
|
||||
if (!sub || !splits.append(StringValue(sub)))
|
||||
if (!sub)
|
||||
return nullptr;
|
||||
splits->initDenseElement(splitsIndex++, StringValue(sub));
|
||||
lastEndIndex = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add substring for tail of string (after last match).
|
||||
JSString* sub = NewDependentString(cx, str, lastEndIndex, textLen - lastEndIndex);
|
||||
if (!sub || !splits.append(StringValue(sub)))
|
||||
if (!sub)
|
||||
return nullptr;
|
||||
splits->initDenseElement(splitsIndex++, StringValue(sub));
|
||||
|
||||
return NewCopiedArrayTryUseGroup(cx, group, splits.begin(), splits.length());
|
||||
return splits;
|
||||
}
|
||||
|
||||
// ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
|
||||
|
@ -3071,6 +3105,8 @@ ArrayObject*
|
|||
js::str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep,
|
||||
uint32_t limit)
|
||||
{
|
||||
MOZ_ASSERT(limit > 0, "Only called for strictly positive limit.");
|
||||
|
||||
RootedLinearString linearStr(cx, str->ensureLinear(cx));
|
||||
if (!linearStr)
|
||||
return nullptr;
|
||||
|
|
|
@ -4411,8 +4411,7 @@ js::LambdaArrow(JSContext* cx, HandleFunction fun, HandleObject parent, HandleVa
|
|||
{
|
||||
MOZ_ASSERT(fun->isArrow());
|
||||
|
||||
JSFunction* clone = CloneFunctionObjectIfNotSingleton(cx, fun, parent, nullptr,
|
||||
TenuredObject);
|
||||
JSFunction* clone = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
|
||||
if (!clone)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -1721,6 +1721,7 @@ intrinsic_StringSplitStringLimit(JSContext* cx, unsigned argc, Value* vp)
|
|||
// args[2] should be already in UInt32 range, but it could be double typed,
|
||||
// because of Ion optimization.
|
||||
uint32_t limit = uint32_t(args[2].toNumber());
|
||||
MOZ_ASSERT(limit > 0, "Zero limit case is already handled in self-hosted code.");
|
||||
|
||||
RootedObjectGroup group(cx, ObjectGroupCompartment::getStringSplitStringGroup(cx));
|
||||
if (!group)
|
||||
|
|
|
@ -288,12 +288,12 @@ public:
|
|||
* Remove and destroy all property values for the frame.
|
||||
*/
|
||||
void DeleteAll(const nsIFrame* aFrame) {
|
||||
mozilla::DebugOnly<size_t> len = mProperties.Length();
|
||||
for (auto& prop : mProperties) {
|
||||
nsTArray<PropertyValue> toDelete;
|
||||
toDelete.SwapElements(mProperties);
|
||||
for (auto& prop : toDelete) {
|
||||
prop.DestroyValueFor(aFrame);
|
||||
MOZ_ASSERT(mProperties.Length() == len);
|
||||
}
|
||||
mProperties.Clear();
|
||||
MOZ_ASSERT(mProperties.IsEmpty(), "a property dtor added new properties");
|
||||
}
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
|
||||
|
|
|
@ -32,12 +32,14 @@ struct RenderTargetPixel;
|
|||
struct ScreenPixel;
|
||||
struct ParentLayerPixel;
|
||||
struct DesktopPixel;
|
||||
struct ImagePixel;
|
||||
|
||||
template<> struct IsPixel<CSSPixel> : TrueType {};
|
||||
template<> struct IsPixel<LayoutDevicePixel> : TrueType {};
|
||||
template<> struct IsPixel<LayerPixel> : TrueType {};
|
||||
template<> struct IsPixel<CSSTransformedLayerPixel> : TrueType {};
|
||||
template<> struct IsPixel<RenderTargetPixel> : TrueType {};
|
||||
template<> struct IsPixel<ImagePixel> : TrueType {};
|
||||
template<> struct IsPixel<ScreenPixel> : TrueType {};
|
||||
template<> struct IsPixel<ParentLayerPixel> : TrueType {};
|
||||
template<> struct IsPixel<DesktopPixel> : TrueType {};
|
||||
|
@ -100,6 +102,8 @@ typedef gfx::MarginTyped<RenderTargetPixel> RenderTargetMargin;
|
|||
typedef gfx::IntMarginTyped<RenderTargetPixel> RenderTargetIntMargin;
|
||||
typedef gfx::IntRegionTyped<RenderTargetPixel> RenderTargetIntRegion;
|
||||
|
||||
typedef gfx::IntRectTyped<ImagePixel> ImageIntRect;
|
||||
|
||||
typedef gfx::CoordTyped<ScreenPixel> ScreenCoord;
|
||||
typedef gfx::IntCoordTyped<ScreenPixel> ScreenIntCoord;
|
||||
typedef gfx::PointTyped<ScreenPixel> ScreenPoint;
|
||||
|
@ -408,6 +412,13 @@ struct CSSTransformedLayerPixel {
|
|||
struct RenderTargetPixel {
|
||||
};
|
||||
|
||||
/*
|
||||
* This unit represents one pixel in an image. Image space
|
||||
* is largely independent of any other space.
|
||||
*/
|
||||
struct ImagePixel {
|
||||
};
|
||||
|
||||
/*
|
||||
* The pixels that are displayed on the screen.
|
||||
* On non-OMTC platforms this should be equivalent to LayerPixel units.
|
||||
|
|
|
@ -121,7 +121,7 @@ BuildDisplayListForTopLayerFrame(nsDisplayListBuilder* aBuilder,
|
|||
clipState.SetClipChainForContainingBlockDescendants(
|
||||
savedOutOfFlowData->mCombinedClipChain);
|
||||
clipState.ClipContainingBlockDescendantsExtra(
|
||||
dirty + aBuilder->ToReferenceFrame(aFrame), nullptr);
|
||||
visible + aBuilder->ToReferenceFrame(aFrame), nullptr);
|
||||
asrSetter.SetCurrentActiveScrolledRoot(
|
||||
savedOutOfFlowData->mContainingBlockActiveScrolledRoot);
|
||||
}
|
||||
|
|
|
@ -957,8 +957,12 @@ nsIFrame::RemoveDisplayItemDataForDeletion()
|
|||
|
||||
DisplayItemArray* items = RemoveProperty(DisplayItems());
|
||||
if (items) {
|
||||
for (nsDisplayItem* item : *items) {
|
||||
item->RemoveFrame(this);
|
||||
for (nsDisplayItem* i : *items) {
|
||||
if (i->GetDependentFrame() == this &&
|
||||
!i->HasDeletedFrame()) {
|
||||
i->Frame()->MarkNeedsDisplayItemRebuild();
|
||||
}
|
||||
i->RemoveFrame(this);
|
||||
}
|
||||
delete items;
|
||||
}
|
||||
|
@ -2518,7 +2522,8 @@ WrapSeparatorTransform(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
|||
|
||||
void
|
||||
nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList) {
|
||||
nsDisplayList* aList,
|
||||
bool* aCreatedContainerItem) {
|
||||
if (GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
|
||||
return;
|
||||
|
||||
|
@ -2897,6 +2902,10 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
// Get the ASR to use for the container items that we create here.
|
||||
const ActiveScrolledRoot* containerItemASR = contASRTracker.GetContainerASR();
|
||||
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = false;
|
||||
}
|
||||
|
||||
/* If adding both a nsDisplayBlendContainer and a nsDisplayBlendMode to the
|
||||
* same list, the nsDisplayBlendContainer should be added first. This only
|
||||
* happens when the element creating this stacking context has mix-blend-mode
|
||||
|
@ -2910,6 +2919,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
resultList.AppendNewToTop(
|
||||
nsDisplayBlendContainer::CreateForMixBlendMode(aBuilder, this, &resultList,
|
||||
containerItemASR));
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there are any SVG effects, wrap the list up in an SVG effects item
|
||||
|
@ -2953,6 +2965,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
// because nsDisplayMask items can't build active layers.
|
||||
aBuilder->ExitSVGEffectsContents();
|
||||
resultList.AppendToTop(&hoistedScrollInfoItemsStorage);
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the list is non-empty and there is CSS group opacity without SVG
|
||||
|
@ -2968,6 +2983,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
new (aBuilder) nsDisplayOpacity(aBuilder, this, &resultList,
|
||||
containerItemASR,
|
||||
opacityItemForEventsAndPluginsOnly));
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're going to apply a transformation and don't have preserve-3d set, wrap
|
||||
|
@ -3043,6 +3061,10 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
GetContainingBlock(0, disp)->GetContent()->GetPrimaryFrame(),
|
||||
&resultList));
|
||||
}
|
||||
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (clipCapturedBy == ContainerItemType::eOwnLayerForTransformWithRoundedClip) {
|
||||
|
@ -3052,6 +3074,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
aBuilder->CurrentActiveScrolledRoot(), 0,
|
||||
mozilla::layers::FrameMetrics::NULL_SCROLL_ID,
|
||||
ScrollThumbData{}, /* aForceActive = */ false));
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have sticky positioning, wrap it in a sticky position item.
|
||||
|
@ -3068,6 +3093,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
ActiveScrolledRoot::PickAncestor(containerItemASR, aBuilder->CurrentActiveScrolledRoot());
|
||||
resultList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplayFixedPosition(aBuilder, this, &resultList, fixedASR));
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = true;
|
||||
}
|
||||
} else if (useStickyPosition) {
|
||||
// For position:sticky, the clip needs to be applied both to the sticky
|
||||
// container item and to the contents. The container item needs the clip
|
||||
|
@ -3081,6 +3109,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
ActiveScrolledRoot::PickAncestor(containerItemASR, aBuilder->CurrentActiveScrolledRoot());
|
||||
resultList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplayStickyPosition(aBuilder, this, &resultList, stickyASR));
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there's blending, wrap up the list in a blend-mode item. Note
|
||||
|
@ -3095,9 +3126,12 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
new (aBuilder) nsDisplayBlendMode(aBuilder, this, &resultList,
|
||||
effects->mMixBlendMode,
|
||||
containerItemASR));
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = true;
|
||||
}
|
||||
}
|
||||
|
||||
CreateOwnLayerIfNeeded(aBuilder, &resultList);
|
||||
CreateOwnLayerIfNeeded(aBuilder, &resultList, aCreatedContainerItem);
|
||||
|
||||
aList->AppendToTop(&resultList);
|
||||
}
|
||||
|
@ -3105,28 +3139,21 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
static nsDisplayItem*
|
||||
WrapInWrapList(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
const ActiveScrolledRoot* aContainerASR)
|
||||
const ActiveScrolledRoot* aContainerASR,
|
||||
bool aCanSkipWrapList = false)
|
||||
{
|
||||
nsDisplayItem* item = aList->GetBottom();
|
||||
if (!item) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// For perspective items we want to treat the 'frame' as being the transform
|
||||
// frame that created it. This stops the transform frame from wrapping another
|
||||
// nsDisplayWrapList around it (with mismatching reference frames), but still
|
||||
// makes the perspective frame create one (so we have an atomic entry for z-index
|
||||
// sorting).
|
||||
nsIFrame *itemFrame = item->Frame();
|
||||
if (item->GetType() == DisplayItemType::TYPE_PERSPECTIVE) {
|
||||
itemFrame = static_cast<nsDisplayPerspective*>(item)->TransformFrame();
|
||||
}
|
||||
|
||||
if (item->GetAbove() || itemFrame != aFrame) {
|
||||
return new (aBuilder) nsDisplayWrapList(aBuilder, aFrame, aList, aContainerASR);
|
||||
}
|
||||
if (aCanSkipWrapList) {
|
||||
MOZ_ASSERT(!item->GetAbove());
|
||||
aList->RemoveBottom();
|
||||
return item;
|
||||
}
|
||||
|
||||
return new (aBuilder) nsDisplayWrapList(aBuilder, aFrame, aList, aContainerASR);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3416,6 +3443,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayList list(aBuilder);
|
||||
nsDisplayList extraPositionedDescendants(aBuilder);
|
||||
const ActiveScrolledRoot* wrapListASR = aBuilder->CurrentActiveScrolledRoot();
|
||||
bool canSkipWrapList = false;
|
||||
if (isStackingContext) {
|
||||
if (effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
|
||||
aBuilder->SetContainsBlendMode(true);
|
||||
|
@ -3424,7 +3452,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
// For stacking contexts, BuildDisplayListForStackingContext handles
|
||||
// clipping and MarkAbsoluteFramesForDisplayList.
|
||||
nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
|
||||
child->BuildDisplayListForStackingContext(aBuilder, &list);
|
||||
child->BuildDisplayListForStackingContext(aBuilder, &list, &canSkipWrapList);
|
||||
wrapListASR = contASRTracker.GetContainerASR();
|
||||
aBuilder->DisplayCaret(child, &list);
|
||||
} else {
|
||||
|
@ -3517,7 +3545,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
// Genuine stacking contexts, and positioned pseudo-stacking-contexts,
|
||||
// go in this level.
|
||||
if (!list.IsEmpty()) {
|
||||
nsDisplayItem* item = WrapInWrapList(aBuilder, child, &list, wrapListASR);
|
||||
nsDisplayItem* item = WrapInWrapList(aBuilder, child, &list, wrapListASR, canSkipWrapList);
|
||||
if (isSVG) {
|
||||
aLists.Content()->AppendNewToTop(item);
|
||||
} else {
|
||||
|
@ -10643,13 +10671,17 @@ nsIFrame::SetParent(nsContainerFrame* aParent)
|
|||
|
||||
void
|
||||
nsIFrame::CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList)
|
||||
nsDisplayList* aList,
|
||||
bool* aCreatedContainerItem)
|
||||
{
|
||||
if (GetContent() &&
|
||||
GetContent()->IsXULElement() &&
|
||||
GetContent()->HasAttr(kNameSpaceID_None, nsGkAtoms::layer)) {
|
||||
aList->AppendNewToTop(new (aBuilder)
|
||||
nsDisplayOwnLayer(aBuilder, this, aList, aBuilder->CurrentActiveScrolledRoot()));
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1701,9 +1701,13 @@ public:
|
|||
/**
|
||||
* Builds a display list for the content represented by this frame,
|
||||
* treating this frame as the root of a stacking context.
|
||||
* Optionally sets aCreatedContainerItem to true if we created a
|
||||
* single container display item for the stacking context, and no
|
||||
* other wrapping items are needed.
|
||||
*/
|
||||
void BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList);
|
||||
nsDisplayList* aList,
|
||||
bool* aCreatedContainerItem = nullptr);
|
||||
|
||||
enum {
|
||||
DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
|
||||
|
@ -3938,7 +3942,8 @@ public:
|
|||
uint8_t VerticalAlignEnum() const;
|
||||
enum { eInvalidVerticalAlign = 0xFF };
|
||||
|
||||
void CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder, nsDisplayList* aList);
|
||||
void CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
|
||||
bool* aCreatedContainerItem = nullptr);
|
||||
|
||||
/**
|
||||
* Adds the NS_FRAME_IN_POPUP state bit to aFrame, and
|
||||
|
|
|
@ -1129,15 +1129,14 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
|
|||
if (ps->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
dirtyRectRelativeToDirtyFrame =
|
||||
nsRect(nsPoint(0, 0), ps->GetScrollPositionClampingScrollPortSize());
|
||||
visible = dirtyRectRelativeToDirtyFrame;
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
} else {
|
||||
dirtyRectRelativeToDirtyFrame =
|
||||
nsRect(nsPoint(0, 0), aDirtyFrame->GetSize());
|
||||
visible = dirtyRectRelativeToDirtyFrame;
|
||||
#endif
|
||||
}
|
||||
// TODO: We probably don't want visible and dirty to be the same here, figure
|
||||
// out what to do.
|
||||
visible = dirtyRectRelativeToDirtyFrame;
|
||||
}
|
||||
nsPoint offset = aFrame->GetOffsetTo(aDirtyFrame);
|
||||
visible -= offset;
|
||||
|
|
|
@ -196,6 +196,7 @@ protected:
|
|||
static void DetachAGR(AnimatedGeometryRoot* aAGR) {
|
||||
aAGR->mFrame = nullptr;
|
||||
aAGR->mParentAGR = nullptr;
|
||||
NS_RELEASE(aAGR);
|
||||
}
|
||||
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(AnimatedGeometryRootCache, AnimatedGeometryRoot, DetachAGR)
|
||||
|
||||
|
@ -207,6 +208,7 @@ protected:
|
|||
{
|
||||
MOZ_ASSERT(mParentAGR || mIsAsync, "The root AGR should always be treated as an async AGR.");
|
||||
if (mIsRetained) {
|
||||
NS_ADDREF(this);
|
||||
aFrame->SetProperty(AnimatedGeometryRootCache(), this);
|
||||
}
|
||||
}
|
||||
|
@ -254,7 +256,8 @@ struct ActiveScrolledRoot {
|
|||
asr = new ActiveScrolledRoot();
|
||||
|
||||
if (aIsRetained) {
|
||||
f->SetProperty(ActiveScrolledRootCache(), asr);
|
||||
RefPtr<ActiveScrolledRoot> ref = asr;
|
||||
f->SetProperty(ActiveScrolledRootCache(), ref.forget().take());
|
||||
}
|
||||
}
|
||||
asr->mParent = aParent;
|
||||
|
@ -308,6 +311,7 @@ private:
|
|||
static void DetachASR(ActiveScrolledRoot* aASR) {
|
||||
aASR->mParent = nullptr;
|
||||
aASR->mScrollableFrame = nullptr;
|
||||
NS_RELEASE(aASR);
|
||||
}
|
||||
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache, ActiveScrolledRoot, DetachASR)
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@ skip-if(!retainedDisplayList) == retained-dl-remove-for-ancestor-change-1.html r
|
|||
skip-if(!retainedDisplayList) == retained-dl-scroll-out-of-view-1.html retained-dl-scroll-out-of-view-1-ref.html
|
||||
skip-if(!retainedDisplayList) == retained-dl-displayport-1.html retained-dl-displayport-1-ref.html
|
||||
skip-if(!retainedDisplayList) == retained-dl-prerender-transform-1.html retained-dl-prerender-transform-1-ref.html
|
||||
== retained-dl-wrap-list.html retained-dl-wrap-list-ref.html
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
#hover {
|
||||
background-color:blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="float:left; width:200px; height:200px; background-color: red">
|
||||
<div style="width:100px; height:100px; " id="hover"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<html class="reftest-wait">
|
||||
<body>
|
||||
<div style="float:left; width:200px; height:200px; background-color: red">
|
||||
<div style="width:100px; height:100px;" id="hover"></div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
function doTest() {
|
||||
document.getElementById("hover").style.backgroundColor = "blue";
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
window.addEventListener("MozReftestInvalidate", doTest);
|
||||
</script>
|
||||
</html>
|
|
@ -136,9 +136,12 @@ class ReftestRunner(MozbuildObject):
|
|||
args.ignoreWindowSize = True
|
||||
args.printDeviceInfo = False
|
||||
|
||||
from mozrunner.devices.android_device import grant_runtime_permissions
|
||||
from mozrunner.devices.android_device import grant_runtime_permissions, get_adb_path
|
||||
grant_runtime_permissions(self)
|
||||
|
||||
if not args.adb_path:
|
||||
args.adb_path = get_adb_path(self)
|
||||
|
||||
# A symlink and some path manipulations are required so that test
|
||||
# manifests can be found both locally and remotely (via a url)
|
||||
# using the same relative path.
|
||||
|
|
|
@ -418,7 +418,7 @@ class RemoteArgumentsParser(ReftestArgumentsParser):
|
|||
action="store",
|
||||
type=str,
|
||||
dest="adb_path",
|
||||
default="adb",
|
||||
default=None,
|
||||
help="path to adb")
|
||||
|
||||
self.add_argument("--deviceIP",
|
||||
|
|
|
@ -98,7 +98,8 @@ using namespace mozilla;
|
|||
if (MOZ_UNLIKELY(!XRE_IsParentProcess())) { \
|
||||
nsPrintfCString msg( \
|
||||
"ENSURE_MAIN_PROCESS: called %s on %s in a non-main process", \
|
||||
func, pref); \
|
||||
func, \
|
||||
pref); \
|
||||
NS_ERROR(msg.get()); \
|
||||
return NS_ERROR_NOT_AVAILABLE; \
|
||||
} \
|
||||
|
@ -109,7 +110,8 @@ using namespace mozilla;
|
|||
if (MOZ_UNLIKELY(!XRE_IsParentProcess())) { \
|
||||
nsPrintfCString msg( \
|
||||
"ENSURE_MAIN_PROCESS: called %s on %s in a non-main process", \
|
||||
func, pref); \
|
||||
func, \
|
||||
pref); \
|
||||
NS_WARNING(msg.get()); \
|
||||
return NS_ERROR_NOT_AVAILABLE; \
|
||||
} \
|
||||
|
@ -243,11 +245,8 @@ private:
|
|||
{
|
||||
PREF_FLAG_LOCKED = 4,
|
||||
PREF_FLAG_USERSET = 8,
|
||||
PREF_FLAG_CONFIG = 16,
|
||||
PREF_FLAG_REMOTE = 32,
|
||||
PREF_FLAG_LILOCAL = 64,
|
||||
PREF_FLAG_HAS_DEFAULT = 128,
|
||||
PREF_FLAG_STICKY_DEFAULT = 256,
|
||||
PREF_FLAG_HAS_DEFAULT = 16,
|
||||
PREF_FLAG_STICKY_DEFAULT = 32,
|
||||
};
|
||||
uint16_t mValue;
|
||||
};
|
||||
|
@ -2176,8 +2175,6 @@ public:
|
|||
|
||||
int32_t GetRootLength() const { return mPrefRoot.Length(); }
|
||||
|
||||
nsresult RemoveObserverFromMap(const char* aDomain, nsISupports* aObserver);
|
||||
|
||||
static void NotifyObserver(const char* aNewpref, void* aData);
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
|
||||
|
@ -2261,8 +2258,7 @@ private:
|
|||
nsClassHashtable<PrefCallback, PrefCallback> mObservers;
|
||||
};
|
||||
|
||||
class nsPrefLocalizedString final
|
||||
: public nsIPrefLocalizedString
|
||||
class nsPrefLocalizedString final : public nsIPrefLocalizedString
|
||||
{
|
||||
public:
|
||||
nsPrefLocalizedString();
|
||||
|
|
|
@ -50,16 +50,16 @@ with Files('**/Makefile.in'):
|
|||
FINAL = True
|
||||
|
||||
with Files("**/*.js"):
|
||||
SCHEDULES.inclusive += ['test-verification']
|
||||
SCHEDULES.inclusive += ['test-verify']
|
||||
|
||||
with Files("**/*.html"):
|
||||
SCHEDULES.inclusive += ['test-verification']
|
||||
SCHEDULES.inclusive += ['test-verify']
|
||||
|
||||
with Files("**/*.xhtml"):
|
||||
SCHEDULES.inclusive += ['test-verification']
|
||||
SCHEDULES.inclusive += ['test-verify']
|
||||
|
||||
with Files("**/*.xul"):
|
||||
SCHEDULES.inclusive += ['test-verification']
|
||||
SCHEDULES.inclusive += ['test-verify']
|
||||
|
||||
FILES_PER_UNIFIED_FILE = 1
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ INCLUSIVE_COMPONENTS = [
|
|||
'yaml-lint',
|
||||
# test suites that only run when certain files have changed
|
||||
'jittest',
|
||||
'test-verification',
|
||||
'test-verify',
|
||||
# test flavors (narrower than suites)
|
||||
'jsreftest',
|
||||
]
|
||||
|
|
|
@ -50,7 +50,7 @@ telemetry-tests-client:
|
|||
|
||||
test-verify:
|
||||
description: "Extra verification of tests modified on this push"
|
||||
suite: test-verification
|
||||
suite: test-verify
|
||||
treeherder-symbol: tc(TV)
|
||||
loopback-video: true
|
||||
max-run-time: 5400
|
||||
|
|
|
@ -640,7 +640,7 @@ def handle_suite_category(config, tests):
|
|||
|
||||
script = test['mozharness']['script']
|
||||
category_arg = None
|
||||
if suite == 'test-verification':
|
||||
if suite == 'test-verify':
|
||||
pass
|
||||
elif script == 'android_emulator_unittest.py':
|
||||
category_arg = '--test-suite'
|
||||
|
|
|
@ -388,6 +388,9 @@ class MachCommands(MachCommandBase):
|
|||
commandline.add_logging_group(parser)
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if not options.adb_path:
|
||||
from mozrunner.devices.android_device import get_adb_path
|
||||
options.adb_path = get_adb_path(self)
|
||||
options.symbols_path = symbols_path
|
||||
options.manifest_path = manifest_path
|
||||
options.xre_path = self.bindir
|
||||
|
|
|
@ -172,6 +172,10 @@ class MochitestRunner(MozbuildObject):
|
|||
('.py', 'r', imp.PY_SOURCE))
|
||||
import runtestsremote
|
||||
|
||||
from mozrunner.devices.android_device import get_adb_path
|
||||
if not kwargs['adbPath']:
|
||||
kwargs['adbPath'] = get_adb_path(self)
|
||||
|
||||
options = Namespace(**kwargs)
|
||||
|
||||
from manifestparser import TestManifest
|
||||
|
@ -455,9 +459,12 @@ class RobocopCommands(MachCommandBase):
|
|||
sorted(list(test_paths)))))
|
||||
return 1
|
||||
|
||||
from mozrunner.devices.android_device import grant_runtime_permissions
|
||||
from mozrunner.devices.android_device import grant_runtime_permissions, get_adb_path
|
||||
grant_runtime_permissions(self)
|
||||
|
||||
if not kwargs['adbPath']:
|
||||
kwargs['adbPath'] = get_adb_path(self)
|
||||
|
||||
mochitest = self._spawn(MochitestRunner)
|
||||
return mochitest.run_robocop_test(self._mach_context, tests, 'robocop', **kwargs)
|
||||
|
||||
|
|
|
@ -248,6 +248,10 @@ def verify_android_device(build_obj, install=False, xre=False, debugger=False, v
|
|||
return device_verified
|
||||
|
||||
|
||||
def get_adb_path(build_obj):
|
||||
return _find_sdk_exe(build_obj.substs, 'adb', False)
|
||||
|
||||
|
||||
def run_firefox_for_android(build_obj, params):
|
||||
"""
|
||||
Launch Firefox for Android on the connected device.
|
||||
|
|
|
@ -178,6 +178,11 @@ class RemoteCPPUnittestOptions(cppunittests.CPPUnittestOptions):
|
|||
help="port of remote device to test")
|
||||
defaults["device_port"] = 20701
|
||||
|
||||
self.add_option("--adbPath", action="store",
|
||||
type="string", dest="adb_path",
|
||||
help="Path to adb")
|
||||
defaults["adb_path"] = None
|
||||
|
||||
self.add_option("--noSetup", action="store_false",
|
||||
dest="setup",
|
||||
help="do not copy any files to device (to be used only if "
|
||||
|
@ -238,6 +243,8 @@ def run_test_harness(options, args):
|
|||
if options.device_ip:
|
||||
dm_args['host'] = options.device_ip
|
||||
dm_args['port'] = options.device_port
|
||||
if options.adb_path:
|
||||
dm_args['adbPath'] = options.adb_path
|
||||
if options.log_tbpl_level == 'debug' or options.log_mach_level == 'debug':
|
||||
dm_args['logLevel'] = logging.DEBUG # noqa python 2 / 3
|
||||
dm = devicemanagerADB.DeviceManagerADB(**dm_args)
|
||||
|
|
|
@ -248,7 +248,7 @@ RunnerManagerState = _RunnerManagerState()
|
|||
|
||||
class TestRunnerManager(threading.Thread):
|
||||
def __init__(self, suite_name, test_queue, test_source_cls, browser_cls, browser_kwargs,
|
||||
executor_cls, executor_kwargs, stop_flag, pause_after_test=False,
|
||||
executor_cls, executor_kwargs, stop_flag, rerun=1, pause_after_test=False,
|
||||
pause_on_unexpected=False, restart_on_unexpected=True, debug_info=None):
|
||||
"""Thread that owns a single TestRunner process and any processes required
|
||||
by the TestRunner (e.g. the Firefox binary).
|
||||
|
@ -279,6 +279,8 @@ class TestRunnerManager(threading.Thread):
|
|||
self.parent_stop_flag = stop_flag
|
||||
self.child_stop_flag = multiprocessing.Event()
|
||||
|
||||
self.rerun = rerun
|
||||
self.run_count = 0
|
||||
self.pause_after_test = pause_after_test
|
||||
self.pause_on_unexpected = pause_on_unexpected
|
||||
self.restart_on_unexpected = restart_on_unexpected
|
||||
|
@ -502,9 +504,9 @@ class TestRunnerManager(threading.Thread):
|
|||
self.logger.info("No more tests")
|
||||
return None, None, None
|
||||
test = test_group.popleft()
|
||||
self.run_count = 0
|
||||
return test, test_group, group_metadata
|
||||
|
||||
|
||||
def run_test(self):
|
||||
assert isinstance(self.state, RunnerManagerState.running)
|
||||
assert self.state.test is not None
|
||||
|
@ -516,6 +518,9 @@ class TestRunnerManager(threading.Thread):
|
|||
self.state.group_metadata)
|
||||
|
||||
self.logger.test_start(self.state.test.id)
|
||||
if self.rerun > 1:
|
||||
self.logger.info("Run %d/%d" % (self.run_count, self.rerun))
|
||||
self.run_count += 1
|
||||
self.send_message("run_test", self.state.test)
|
||||
|
||||
def test_ended(self, test, results):
|
||||
|
@ -579,7 +584,7 @@ class TestRunnerManager(threading.Thread):
|
|||
self.logger.info("Pausing until the browser exits")
|
||||
self.send_message("wait")
|
||||
else:
|
||||
return self.after_test_end(restart_before_next)
|
||||
return self.after_test_end(test, restart_before_next)
|
||||
|
||||
def wait_finished(self):
|
||||
assert isinstance(self.state, RunnerManagerState.running)
|
||||
|
@ -589,14 +594,19 @@ class TestRunnerManager(threading.Thread):
|
|||
|
||||
return self.after_test_end(True)
|
||||
|
||||
def after_test_end(self, restart):
|
||||
def after_test_end(self, test, restart):
|
||||
assert isinstance(self.state, RunnerManagerState.running)
|
||||
if self.run_count == self.rerun:
|
||||
test, test_group, group_metadata = self.get_next_test()
|
||||
if test is None:
|
||||
return RunnerManagerState.stop()
|
||||
if test_group != self.state.test_group:
|
||||
# We are starting a new group of tests, so force a restart
|
||||
restart = True
|
||||
else:
|
||||
test = test
|
||||
test_group = self.state.test_group
|
||||
group_metadata = self.state.group_metadata
|
||||
if restart:
|
||||
return RunnerManagerState.restarting(test, test_group, group_metadata)
|
||||
else:
|
||||
|
@ -685,6 +695,7 @@ class ManagerGroup(object):
|
|||
def __init__(self, suite_name, size, test_source_cls, test_source_kwargs,
|
||||
browser_cls, browser_kwargs,
|
||||
executor_cls, executor_kwargs,
|
||||
rerun=1,
|
||||
pause_after_test=False,
|
||||
pause_on_unexpected=False,
|
||||
restart_on_unexpected=True,
|
||||
|
@ -702,6 +713,7 @@ class ManagerGroup(object):
|
|||
self.pause_on_unexpected = pause_on_unexpected
|
||||
self.restart_on_unexpected = restart_on_unexpected
|
||||
self.debug_info = debug_info
|
||||
self.rerun = rerun
|
||||
|
||||
self.pool = set()
|
||||
# Event that is polled by threads so that they can gracefully exit in the face
|
||||
|
@ -734,6 +746,7 @@ class ManagerGroup(object):
|
|||
self.executor_cls,
|
||||
self.executor_kwargs,
|
||||
self.stop_flag,
|
||||
self.rerun,
|
||||
self.pause_after_test,
|
||||
self.pause_on_unexpected,
|
||||
self.restart_on_unexpected,
|
||||
|
|
|
@ -74,6 +74,9 @@ scheme host and port.""")
|
|||
mode_group.add_argument("--list-tests", action="store_true",
|
||||
default=False,
|
||||
help="List all tests that will run")
|
||||
mode_group.add_argument("--verify", action="store_true",
|
||||
default=False,
|
||||
help="Run a stability check on the selected tests")
|
||||
|
||||
test_selection_group = parser.add_argument_group("Test Selection")
|
||||
test_selection_group.add_argument("--test-types", action="store",
|
||||
|
@ -93,8 +96,10 @@ scheme host and port.""")
|
|||
debugging_group.add_argument('--debugger', const="__default__", nargs="?",
|
||||
help="run under a debugger, e.g. gdb or valgrind")
|
||||
debugging_group.add_argument('--debugger-args', help="arguments to the debugger")
|
||||
debugging_group.add_argument("--rerun", action="store", type=int, default=1,
|
||||
help="Number of times to re run each test without restarts")
|
||||
debugging_group.add_argument("--repeat", action="store", type=int, default=1,
|
||||
help="Number of times to run the tests")
|
||||
help="Number of times to run the tests, restarting between each run")
|
||||
debugging_group.add_argument("--repeat-until-unexpected", action="store_true", default=None,
|
||||
help="Run tests in a loop until one returns an unexpected result")
|
||||
debugging_group.add_argument('--pause-after-test', action="store_true", default=None,
|
||||
|
|
|
@ -122,7 +122,7 @@ def get_pause_after_test(test_loader, **kwargs):
|
|||
if kwargs["pause_after_test"] is None:
|
||||
if kwargs["repeat_until_unexpected"]:
|
||||
return False
|
||||
if kwargs["repeat"] == 1 and total_tests == 1:
|
||||
if kwargs["repeat"] == 1 and kwargs["rerun"] == 1 and total_tests == 1:
|
||||
return True
|
||||
return False
|
||||
return kwargs["pause_after_test"]
|
||||
|
@ -241,6 +241,7 @@ def run_tests(config, test_paths, product, **kwargs):
|
|||
browser_kwargs,
|
||||
executor_cls,
|
||||
executor_kwargs,
|
||||
kwargs["rerun"],
|
||||
kwargs["pause_after_test"],
|
||||
kwargs["pause_on_unexpected"],
|
||||
kwargs["restart_on_unexpected"],
|
||||
|
@ -260,6 +261,12 @@ def run_tests(config, test_paths, product, **kwargs):
|
|||
logger.suite_end()
|
||||
return unexpected_total == 0
|
||||
|
||||
|
||||
def check_stability(**kwargs):
|
||||
import stability
|
||||
return stability.check_stability(logger, **kwargs)
|
||||
|
||||
|
||||
def start(**kwargs):
|
||||
if kwargs["list_test_groups"]:
|
||||
list_test_groups(**kwargs)
|
||||
|
@ -267,9 +274,12 @@ def start(**kwargs):
|
|||
list_disabled(**kwargs)
|
||||
elif kwargs["list_tests"]:
|
||||
list_tests(**kwargs)
|
||||
elif kwargs["verify"]:
|
||||
check_stability(**kwargs)
|
||||
else:
|
||||
return not run_tests(**kwargs)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point when calling from the command line"""
|
||||
kwargs = wptcommandline.parse_args()
|
||||
|
|
|
@ -145,13 +145,15 @@ class XPCShellRunner(MozbuildObject):
|
|||
|
||||
class AndroidXPCShellRunner(MozbuildObject):
|
||||
"""Get specified DeviceManager"""
|
||||
def get_devicemanager(self, ip, port, remote_test_root):
|
||||
def get_devicemanager(self, ip, port, remote_test_root, adb_path):
|
||||
import mozdevice
|
||||
dm = None
|
||||
if ip:
|
||||
dm = mozdevice.DroidADB(ip, port, packageName=None, deviceRoot=remote_test_root)
|
||||
dm = mozdevice.DroidADB(ip, port, packageName=None, deviceRoot=remote_test_root,
|
||||
adbPath=adb_path)
|
||||
else:
|
||||
dm = mozdevice.DroidADB(packageName=None, deviceRoot=remote_test_root)
|
||||
dm = mozdevice.DroidADB(packageName=None, deviceRoot=remote_test_root,
|
||||
adbPath=adb_path)
|
||||
return dm
|
||||
|
||||
"""Run Android xpcshell tests."""
|
||||
|
@ -164,7 +166,7 @@ class AndroidXPCShellRunner(MozbuildObject):
|
|||
import remotexpcshelltests
|
||||
|
||||
dm = self.get_devicemanager(kwargs["deviceIP"], kwargs["devicePort"],
|
||||
kwargs["remoteTestRoot"])
|
||||
kwargs["remoteTestRoot"], kwargs["adbPath"])
|
||||
|
||||
log = kwargs.pop("log")
|
||||
self.log_manager.enable_unstructured()
|
||||
|
@ -255,8 +257,10 @@ class MachCommands(MachCommandBase):
|
|||
params['threadCount'] = int((cpu_count() * 3) / 2)
|
||||
|
||||
if conditions.is_android(self):
|
||||
from mozrunner.devices.android_device import verify_android_device
|
||||
from mozrunner.devices.android_device import verify_android_device, get_adb_path
|
||||
verify_android_device(self)
|
||||
if not params['adbPath']:
|
||||
params['adbPath'] = get_adb_path(self)
|
||||
xpcshell = self._spawn(AndroidXPCShellRunner)
|
||||
else:
|
||||
xpcshell = self._spawn(XPCShellRunner)
|
||||
|
|
|
@ -601,6 +601,8 @@ def main():
|
|||
dm_args['port'] = options['devicePort']
|
||||
if options['log_tbpl_level'] == 'debug' or options['log_mach_level'] == 'debug':
|
||||
dm_args['logLevel'] = logging.DEBUG
|
||||
if options['adbPath']:
|
||||
dm_args['adbPath'] = options['adbPath']
|
||||
dm = mozdevice.DroidADB(**dm_args)
|
||||
|
||||
if options['interactive'] and not options['testPath']:
|
||||
|
|
|
@ -149,6 +149,9 @@ def add_remote_arguments(parser):
|
|||
parser.add_argument("--apk", action="store", type=str, dest="localAPK",
|
||||
help="local path to Fennec APK")
|
||||
|
||||
parser.add_argument("--adbPath", action="store", type=str, dest="adbPath",
|
||||
help="Path to adb")
|
||||
|
||||
parser.add_argument("--noSetup", action="store_false", dest="setup", default=True,
|
||||
help="do not copy any files to device (to be used only if "
|
||||
"device is already setup)")
|
||||
|
|
|
@ -212,7 +212,7 @@ var Settings = {
|
|||
|
||||
getStatusStringForSetting(setting) {
|
||||
let enabled = Preferences.get(setting.pref, setting.defaultPrefValue);
|
||||
let status = bundle.GetStringFromName(enabled ? "telemetryEnabled" : "telemetryDisabled");
|
||||
let status = bundle.GetStringFromName(enabled ? "telemetryUploadEnabled" : "telemetryUploadDisabled");
|
||||
return status;
|
||||
},
|
||||
|
||||
|
@ -220,17 +220,19 @@ var Settings = {
|
|||
* Updates the button & text at the top of the page to reflect Telemetry state.
|
||||
*/
|
||||
render() {
|
||||
let homeExplanation = document.getElementById("home-explanation");
|
||||
let fhrEnabled = Preferences.get(this.SETTINGS[0].pref, this.SETTINGS[0].defaultPrefValue);
|
||||
fhrEnabled = bundle.GetStringFromName(fhrEnabled ? "telemetryEnabled" : "telemetryDisabled");
|
||||
let extendedEnabled = Preferences.get(this.SETTINGS[1].pref, this.SETTINGS[1].defaultPrefValue);
|
||||
extendedEnabled = bundle.GetStringFromName(extendedEnabled ? "extendedTelemetryEnabled" : "extendedTelemetryDisabled");
|
||||
let parameters = [fhrEnabled, extendedEnabled].map(this.convertStringToLink);
|
||||
let settingsExplanation = document.getElementById("settings-explanation");
|
||||
let uploadEnabled = this.getStatusStringForSetting(this.SETTINGS[0]);
|
||||
let extendedEnabled = Services.telemetry.canRecordExtended;
|
||||
let collectedData = bundle.GetStringFromName(extendedEnabled ? "prereleaseData" : "releaseData");
|
||||
|
||||
let explanation = bundle.formatStringFromName("homeExplanation", parameters, 2);
|
||||
let parameters = [
|
||||
collectedData,
|
||||
this.convertStringToLink(uploadEnabled),
|
||||
];
|
||||
let explanation = bundle.formatStringFromName("settingsExplanation", parameters, 2);
|
||||
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
homeExplanation.innerHTML = explanation;
|
||||
settingsExplanation.innerHTML = explanation;
|
||||
this.attachObservers();
|
||||
},
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@
|
|||
|
||||
<section id="home-section" class="active">
|
||||
<p id="page-subtitle"></p>
|
||||
<p id="home-explanation"></p>
|
||||
<p id="settings-explanation"></p>
|
||||
<p id="ping-explanation"></p>
|
||||
<p>&aboutTelemetry.moreInformations;</p>
|
||||
<ul>
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
# - %2$S is replaced by brandFullName
|
||||
pageSubtitle = This page shows the information about performance, hardware, usage and customizations collected by Telemetry. This information is submitted to %1$S to help improve %2$S.
|
||||
|
||||
# LOCALIZATION NOTE(homeExplanation):
|
||||
# - %1$S is either telemetryEnabled or telemetryDisabled
|
||||
# - %2$S is either extendedTelemetryEnabled or extendedTelemetryDisabled
|
||||
homeExplanation = Telemetry is %1$S and extended telemetry is %2$S.
|
||||
telemetryEnabled = enabled
|
||||
telemetryDisabled = disabled
|
||||
extendedTelemetryEnabled = enabled
|
||||
extendedTelemetryDisabled = disabled
|
||||
# LOCALIZATION NOTE(settingsExplanation):
|
||||
# - %1$S is either releaseData or prereleaseData
|
||||
# - %2$S is either telemetryUploadEnabled or telemetryUploadDisabled
|
||||
settingsExplanation = Telemetry is collecting %1$S and upload is %2$S.
|
||||
releaseData = release data
|
||||
prereleaseData = pre-release data
|
||||
telemetryUploadEnabled = enabled
|
||||
telemetryUploadDisabled = disabled
|
||||
|
||||
# LOCALIZATION NOTE(pingDetails):
|
||||
# - %1$S is replaced by a link with pingExplanationLink as text
|
||||
|
|
Загрузка…
Ссылка в новой задаче