Merge inbound to mozilla-central. a=merge

This commit is contained in:
shindli 2019-06-21 12:34:14 +03:00
Родитель 90ecafd3e1 d96d24e199
Коммит c0ca77697c
48 изменённых файлов: 741 добавлений и 236 удалений

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

@ -1822,8 +1822,8 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(
}
nsEventStatus AsyncPanZoomController::HandleEndOfPan() {
MOZ_ASSERT(GetCurrentTouchBlock());
GetCurrentTouchBlock()->GetOverscrollHandoffChain()->FlushRepaints();
MOZ_ASSERT(GetCurrentTouchBlock() || GetCurrentPanGestureBlock());
GetCurrentInputBlock()->GetOverscrollHandoffChain()->FlushRepaints();
ParentLayerPoint flingVelocity = GetVelocityVector();
// Clear our velocities; if DispatchFling() gives the fling to us,
@ -1845,7 +1845,7 @@ nsEventStatus AsyncPanZoomController::HandleEndOfPan() {
if (flingVelocity.Length() < StaticPrefs::APZFlingMinVelocityThreshold()) {
// Relieve overscroll now if needed, since we will not transition to a fling
// animation and then an overscroll animation, and relieve it then.
GetCurrentTouchBlock()
GetCurrentInputBlock()
->GetOverscrollHandoffChain()
->SnapBackOverscrolledApzc(this);
return nsEventStatus_eConsumeNoDefault;
@ -1856,8 +1856,8 @@ nsEventStatus AsyncPanZoomController::HandleEndOfPan() {
// which nulls out mTreeManager, could be called concurrently.
if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
const FlingHandoffState handoffState{
flingVelocity, GetCurrentTouchBlock()->GetOverscrollHandoffChain(),
false /* not handoff */, GetCurrentTouchBlock()->GetScrolledApzc()};
flingVelocity, GetCurrentInputBlock()->GetOverscrollHandoffChain(),
false /* not handoff */, GetCurrentInputBlock()->GetScrolledApzc()};
treeManagerLocal->DispatchFling(this, handoffState);
}
return nsEventStatus_eConsumeNoDefault;
@ -2556,6 +2556,35 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent,
ScreenPoint physicalPanDisplacement = aEvent.mPanDisplacement;
ParentLayerPoint logicalPanDisplacement =
aEvent.UserMultipliedLocalPanDisplacement();
if (aEvent.mDeltaType == PanGestureInput::PANDELTA_PAGE) {
// Pan events with page units are used by Gtk, so this replicates Gtk:
// https://gitlab.gnome.org/GNOME/gtk/blob/c734c7e9188b56f56c3a504abee05fa40c5475ac/gtk/gtkrange.c#L3065-3073
CSSSize pageScrollSize;
CSSToParentLayerScale2D zoom;
{
// Grab the lock to access the frame metrics.
RecursiveMutexAutoLock lock(mRecursiveMutex);
pageScrollSize = mScrollMetadata.GetPageScrollAmount() /
Metrics().GetDevPixelsPerCSSPixel();
zoom = Metrics().GetZoom();
}
// scrollUnit* is in units of "ParentLayer pixels per page proportion"...
auto scrollUnitWidth = std::min(std::pow(pageScrollSize.width, 2.0 / 3.0),
pageScrollSize.width / 2.0) *
zoom.xScale;
auto scrollUnitHeight = std::min(std::pow(pageScrollSize.height, 2.0 / 3.0),
pageScrollSize.height / 2.0) *
zoom.yScale;
// ... and pan displacements are in units of "page proportion count"
// here, so the products of them and scrollUnit* are in ParentLayer pixels
ParentLayerPoint physicalPanDisplacementPL(
physicalPanDisplacement.x * scrollUnitWidth,
physicalPanDisplacement.y * scrollUnitHeight);
physicalPanDisplacement = ToScreenCoordinates(physicalPanDisplacementPL,
aEvent.mLocalPanStartPoint);
logicalPanDisplacement.x *= scrollUnitWidth;
logicalPanDisplacement.y *= scrollUnitHeight;
}
MOZ_ASSERT(GetCurrentPanGestureBlock());
AdjustDeltaForAllowedScrollDirections(
@ -2609,6 +2638,12 @@ nsEventStatus AsyncPanZoomController::OnPanEnd(const PanGestureInput& aEvent) {
mX.EndTouch(aEvent.mTime);
mY.EndTouch(aEvent.mTime);
// Use HandleEndOfPan for fling on platforms that don't
// emit momentum events (Gtk).
if (aEvent.mSimulateMomentum) {
return HandleEndOfPan();
}
// Drop any velocity on axes where we don't have room to scroll anyways
// (in this APZC, or an APZC further in the handoff chain).
// This ensures that we don't enlarge the display port unnecessarily.

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

@ -167,25 +167,6 @@ struct ParamTraits<mozilla::layers::CompositableHandle> {
}
};
// Helper class for reading bitfields.
// If T has bitfields members, derive ParamTraits<T> from BitfieldHelper<T>.
template <typename ParamType>
struct BitfieldHelper {
// We need this helper because we can't get the address of a bitfield to
// pass directly to ReadParam. So instead we read it into a temporary bool
// and set the bitfield using a setter function
static bool ReadBoolForBitfield(const Message* aMsg, PickleIterator* aIter,
ParamType* aResult,
void (ParamType::*aSetter)(bool)) {
bool value;
if (ReadParam(aMsg, aIter, &value)) {
(aResult->*aSetter)(value);
return true;
}
return false;
}
};
template <>
struct ParamTraits<mozilla::layers::FrameMetrics>
: BitfieldHelper<mozilla::layers::FrameMetrics> {

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

@ -1088,6 +1088,25 @@ struct ParamTraits<nsILoadInfo::CrossOriginPolicy>
: EnumSerializer<nsILoadInfo::CrossOriginPolicy,
CrossOriginPolicyValidator> {};
// Helper class for reading bitfields.
// If T has bitfields members, derive ParamTraits<T> from BitfieldHelper<T>.
template <typename ParamType>
struct BitfieldHelper {
// We need this helper because we can't get the address of a bitfield to
// pass directly to ReadParam. So instead we read it into a temporary bool
// and set the bitfield using a setter function
static bool ReadBoolForBitfield(const Message* aMsg, PickleIterator* aIter,
ParamType* aResult,
void (ParamType::*aSetter)(bool)) {
bool value;
if (ReadParam(aMsg, aIter, &value)) {
(aResult->*aSetter)(value);
return true;
}
return false;
}
};
} /* namespace IPC */
#endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */

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

@ -112,7 +112,14 @@ enum class ZealMode {
_(RegExpStatics) \
_(RegExpSharedBytecode) \
_(TypedArrayElements) \
_(TypeDescrTraceList)
_(TypeDescrTraceList) \
_(NativeIterator) \
_(JitScript) \
_(ObjectGroupAddendum) \
_(ScriptDebugScript) \
_(BreakpointSite) \
_(ForOfPIC) \
_(ForOfPICStub)
#define JS_FOR_EACH_MEMORY_USE(_) \
JS_FOR_EACH_PUBLIC_MEMORY_USE(_) \

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

@ -701,7 +701,8 @@ void MemoryTracker::checkEmptyOnDestroy() {
inline bool MemoryTracker::allowMultipleAssociations(MemoryUse use) const {
// For most uses only one association is possible for each GC thing. Allow a
// one-to-many relationship only where necessary.
return use == MemoryUse::RegExpSharedBytecode;
return use == MemoryUse::RegExpSharedBytecode ||
use == MemoryUse::BreakpointSite || use == MemoryUse::ForOfPICStub;
}
void MemoryTracker::trackMemory(Cell* cell, size_t nbytes, MemoryUse use) {

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

@ -1831,7 +1831,7 @@ bool BaselineCacheIRCompiler::emitGuardAndGetIterator() {
EmitPreBarrier(masm, iterObjAddr, MIRType::Object);
// Mark iterator as active.
Address iterFlagsAddr(niScratch, NativeIterator::offsetOfFlags());
Address iterFlagsAddr(niScratch, NativeIterator::offsetOfFlagsAndCount());
masm.storePtr(obj, iterObjAddr);
masm.or32(Imm32(NativeIterator::Flags::Active), iterFlagsAddr);

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

@ -3145,7 +3145,7 @@ void jit::DestroyJitScripts(FreeOp* fop, JSScript* script) {
}
if (script->hasJitScript()) {
JitScript::Destroy(script->zone(), script->jitScript());
script->releaseJitScript();
}
}

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

@ -2210,7 +2210,7 @@ bool IonCacheIRCompiler::emitGuardAndGetIterator() {
EmitPreBarrier(masm, iterObjAddr, MIRType::Object);
// Mark iterator as active.
Address iterFlagsAddr(niScratch, NativeIterator::offsetOfFlags());
Address iterFlagsAddr(niScratch, NativeIterator::offsetOfFlagsAndCount());
masm.storePtr(obj, iterObjAddr);
masm.or32(Imm32(NativeIterator::Flags::Active), iterFlagsAddr);

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

@ -40,9 +40,10 @@ static size_t NumTypeSets(JSScript* script) {
}
JitScript::JitScript(JSScript* script, uint32_t typeSetOffset,
uint32_t bytecodeTypeMapOffset)
uint32_t bytecodeTypeMapOffset, uint32_t allocBytes)
: typeSetOffset_(typeSetOffset),
bytecodeTypeMapOffset_(bytecodeTypeMapOffset) {
bytecodeTypeMapOffset_(bytecodeTypeMapOffset),
allocBytes_(allocBytes) {
setTypesGeneration(script->zone()->types.generation);
uint8_t* base = reinterpret_cast<uint8_t*>(this);
@ -98,8 +99,8 @@ bool JSScript::createJitScript(JSContext* cx) {
uint32_t typeSetOffset = sizeof(JitScript) + numICEntries() * sizeof(ICEntry);
uint32_t bytecodeTypeMapOffset =
typeSetOffset + numTypeSets * sizeof(StackTypeSet);
UniquePtr<JitScript> jitScript(
new (raw) JitScript(this, typeSetOffset, bytecodeTypeMapOffset));
UniquePtr<JitScript> jitScript(new (raw) JitScript(
this, typeSetOffset, bytecodeTypeMapOffset, allocSize.value()));
// Sanity check the length computations.
MOZ_ASSERT(jitScript->numICEntries() == numICEntries());
@ -116,6 +117,7 @@ bool JSScript::createJitScript(JSContext* cx) {
MOZ_ASSERT(!jitScript_);
prepareForDestruction.release();
jitScript_ = jitScript.release();
AddCellMemory(this, allocSize.value(), MemoryUse::JitScript);
// We have a JitScript so we can set the script's jitCodeRaw_ pointer to the
// Baseline Interpreter code.
@ -150,8 +152,14 @@ void JSScript::maybeReleaseJitScript() {
return;
}
releaseJitScript();
}
void JSScript::releaseJitScript() {
MOZ_ASSERT(!hasIonScript());
RemoveCellMemory(this, jitScript_->allocBytes(), MemoryUse::JitScript);
JitScript::Destroy(zone(), jitScript_);
jitScript_ = nullptr;
updateJitCodeRaw(runtimeFromMainThread());

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

@ -115,6 +115,9 @@ class alignas(uintptr_t) JitScript final {
// bytecode map queries are in linear order.
uint32_t bytecodeTypeMapHint_ = 0;
// The size of this allocation.
uint32_t allocBytes_ = 0;
struct Flags {
// Flag set when discarding JIT code to indicate this script is on the stack
// and type information and JIT code should not be discarded.
@ -147,7 +150,7 @@ class alignas(uintptr_t) JitScript final {
public:
JitScript(JSScript* script, uint32_t typeSetOffset,
uint32_t bytecodeTypeMapOffset);
uint32_t bytecodeTypeMapOffset, uint32_t allocBytes);
#ifdef DEBUG
~JitScript() {
@ -327,6 +330,8 @@ class alignas(uintptr_t) JitScript final {
uint32_t idx);
void removeDependentWasmImport(wasm::Instance& instance, uint32_t idx);
void unlinkDependentWasmImports();
size_t allocBytes() const { return allocBytes_; }
};
// Ensures no JitScripts are purged in the current zone.

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

@ -3462,7 +3462,7 @@ void MacroAssembler::debugAssertObjHasFixedSlots(Register obj,
void MacroAssembler::branchIfNativeIteratorNotReusable(Register ni,
Label* notReusable) {
// See NativeIterator::isReusable.
Address flagsAddr(ni, NativeIterator::offsetOfFlags());
Address flagsAddr(ni, NativeIterator::offsetOfFlagsAndCount());
#ifdef DEBUG
Label niIsInitialized;
@ -3530,7 +3530,7 @@ void MacroAssembler::iteratorClose(Register obj, Register temp1, Register temp2,
// Clear active bit.
and32(Imm32(~NativeIterator::Flags::Active),
Address(temp1, NativeIterator::offsetOfFlags()));
Address(temp1, NativeIterator::offsetOfFlagsAndCount()));
// Reset property cursor.
loadPtr(Address(temp1, NativeIterator::offsetOfGuardsEnd()), temp2);

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

@ -592,14 +592,7 @@ static PropertyIteratorObject* NewPropertyIteratorObject(JSContext* cx) {
return res;
}
static PropertyIteratorObject* CreatePropertyIterator(
JSContext* cx, Handle<JSObject*> objBeingIterated, HandleIdVector props,
uint32_t numGuards, uint32_t guardKey) {
Rooted<PropertyIteratorObject*> propIter(cx, NewPropertyIteratorObject(cx));
if (!propIter) {
return nullptr;
}
static inline size_t ExtraStringCount(size_t propertyCount, size_t guardCount) {
static_assert(sizeof(ReceiverGuard) == 2 * sizeof(GCPtrFlatString),
"NativeIterators are allocated in space for 1) themselves, "
"2) the properties a NativeIterator iterates (as "
@ -608,9 +601,24 @@ static PropertyIteratorObject* CreatePropertyIterator(
"this size-relationship when determining the extra space to "
"allocate");
size_t extraCount = props.length() + numGuards * 2;
void* mem =
cx->pod_malloc_with_extra<NativeIterator, GCPtrFlatString>(extraCount);
return propertyCount + guardCount * 2;
}
static inline size_t AllocationSize(size_t propertyCount, size_t guardCount) {
return sizeof(NativeIterator) +
ExtraStringCount(propertyCount, guardCount) * sizeof(GCPtrFlatString);
}
static PropertyIteratorObject* CreatePropertyIterator(
JSContext* cx, Handle<JSObject*> objBeingIterated, HandleIdVector props,
uint32_t numGuards, uint32_t guardKey) {
Rooted<PropertyIteratorObject*> propIter(cx, NewPropertyIteratorObject(cx));
if (!propIter) {
return nullptr;
}
void* mem = cx->pod_malloc_with_extra<NativeIterator, GCPtrFlatString>(
ExtraStringCount(props.length(), numGuards));
if (!mem) {
return nullptr;
}
@ -680,7 +688,7 @@ NativeIterator::NativeIterator(JSContext* cx,
reinterpret_cast<GCPtrFlatString*>(guardsBegin() + numGuards)),
propertiesEnd_(propertyCursor_),
guardKey_(guardKey),
flags_(0) // note: no Flags::Initialized
flagsAndCount_(0) // note: no Flags::Initialized
{
MOZ_ASSERT(!*hadError);
@ -688,6 +696,15 @@ NativeIterator::NativeIterator(JSContext* cx,
// can only free |this| (and not leak it) if this has happened.
propIter->setNativeIterator(this);
if (!setInitialPropertyCount(props.length())) {
ReportAllocationOverflow(cx);
*hadError = true;
return;
}
size_t nbytes = AllocationSize(props.length(), numGuards);
AddCellMemory(propIter, nbytes, MemoryUse::NativeIterator);
for (size_t i = 0, len = props.length(); i < len; i++) {
JSFlatString* str = IdToString(cx, props[i]);
if (!str) {
@ -754,6 +771,11 @@ NativeIterator::NativeIterator(JSContext* cx,
MOZ_ASSERT(!*hadError);
}
inline size_t NativeIterator::allocationSize() const {
size_t numGuards = guardsEnd() - guardsBegin();
return AllocationSize(initialPropertyCount(), numGuards);
}
/* static */
bool IteratorHashPolicy::match(PropertyIteratorObject* obj,
const Lookup& lookup) {
@ -1059,7 +1081,7 @@ void PropertyIteratorObject::trace(JSTracer* trc, JSObject* obj) {
void PropertyIteratorObject::finalize(FreeOp* fop, JSObject* obj) {
if (NativeIterator* ni =
obj->as<PropertyIteratorObject>().getNativeIterator()) {
fop->free_(ni);
fop->free_(obj, ni, ni->allocationSize(), MemoryUse::NativeIterator);
}
}

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

@ -87,7 +87,13 @@ struct NativeIterator {
};
private:
uint32_t flags_ = 0; // consists of Flags bits
static constexpr uint32_t FlagsBits = 3;
static constexpr uint32_t FlagsMask = (1 << FlagsBits) - 1;
static constexpr uint32_t PropCountLimit = 1 << (32 - FlagsBits);
// Stores Flags bits in the lower bits and the initial property count above
// them.
uint32_t flagsAndCount_ = 0;
/* While in compartment->enumerators, these form a doubly linked list. */
NativeIterator* next_ = nullptr;
@ -223,31 +229,50 @@ struct NativeIterator {
uint32_t guardKey() const { return guardKey_; }
bool isInitialized() const { return flags_ & Flags::Initialized; }
bool isInitialized() const { return flags() & Flags::Initialized; }
size_t allocationSize() const;
private:
uint32_t flags() const { return flagsAndCount_ & FlagsMask; }
uint32_t initialPropertyCount() const { return flagsAndCount_ >> FlagsBits; }
void setFlags(uint32_t flags) {
MOZ_ASSERT((flags & ~FlagsMask) == 0);
flagsAndCount_ = (initialPropertyCount() << FlagsBits) | flags;
}
MOZ_MUST_USE bool setInitialPropertyCount(uint32_t count) {
if (count >= PropCountLimit) {
return false;
}
flagsAndCount_ = (count << FlagsBits) | flags();
return true;
}
void markInitialized() {
MOZ_ASSERT(flags_ == 0);
flags_ = Flags::Initialized;
MOZ_ASSERT(flags() == 0);
setFlags(Flags::Initialized);
}
public:
bool isActive() const {
MOZ_ASSERT(isInitialized());
return flags_ & Flags::Active;
return flags() & Flags::Active;
}
void markActive() {
MOZ_ASSERT(isInitialized());
flags_ |= Flags::Active;
flagsAndCount_ |= Flags::Active;
}
void markInactive() {
MOZ_ASSERT(isInitialized());
flags_ &= ~Flags::Active;
flagsAndCount_ &= ~Flags::Active;
}
bool isReusable() const {
@ -258,13 +283,13 @@ struct NativeIterator {
// |Flags::Initialized| is set. Using |Flags::NotReusable| to test
// would also work, but this formulation is safer against memory
// corruption.
return flags_ == Flags::Initialized;
return flags() == Flags::Initialized;
}
void markHasUnvisitedPropertyDeletion() {
MOZ_ASSERT(isInitialized());
flags_ |= Flags::HasUnvisitedPropertyDeletion;
flagsAndCount_ |= Flags::HasUnvisitedPropertyDeletion;
}
void link(NativeIterator* other) {
@ -310,8 +335,8 @@ struct NativeIterator {
return offsetof(NativeIterator, propertiesEnd_);
}
static constexpr size_t offsetOfFlags() {
return offsetof(NativeIterator, flags_);
static constexpr size_t offsetOfFlagsAndCount() {
return offsetof(NativeIterator, flagsAndCount_);
}
static constexpr size_t offsetOfNext() {

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

@ -4657,24 +4657,25 @@ void JSScript::destroyDebugScript(FreeOp* fop) {
if (hasDebugScript()) {
#ifdef DEBUG
for (jsbytecode* pc = code(); pc < codeEnd(); pc++) {
if (BreakpointSite* site = getBreakpointSite(pc)) {
/* Breakpoints are swept before finalization. */
MOZ_ASSERT(site->firstBreakpoint() == nullptr);
MOZ_ASSERT(getBreakpointSite(pc) == nullptr);
}
MOZ_ASSERT(!getBreakpointSite(pc));
}
#endif
fop->free_(releaseDebugScript());
freeDebugScript(fop);
}
}
void JSScript::freeDebugScript(FreeOp* fop) {
MOZ_ASSERT(hasDebugScript());
fop->free_(this, releaseDebugScript(), DebugScript::allocSize(length()),
MemoryUse::ScriptDebugScript);
}
DebugScript* JSScript::getOrCreateDebugScript(JSContext* cx) {
if (hasDebugScript()) {
return debugScript();
}
size_t nbytes =
offsetof(DebugScript, breakpoints) + length() * sizeof(BreakpointSite*);
size_t nbytes = DebugScript::allocSize(length());
UniqueDebugScript debug(
reinterpret_cast<DebugScript*>(cx->pod_calloc<uint8_t>(nbytes)));
if (!debug) {
@ -4699,6 +4700,7 @@ DebugScript* JSScript::getOrCreateDebugScript(JSContext* cx) {
setFlag(MutableFlags::HasDebugScript); // safe to set this; we can't fail
// after this point
AddCellMemory(this, nbytes, MemoryUse::ScriptDebugScript);
/*
* Ensure that any Interpret() instances running on this script have
@ -4744,7 +4746,7 @@ void JSScript::decrementGeneratorObserverCount(js::FreeOp* fop) {
debug->generatorObserverCount--;
if (!debug->needed()) {
fop->free_(releaseDebugScript());
destroyDebugScript(fop);
}
}
@ -4783,7 +4785,7 @@ void JSScript::decrementStepperCount(FreeOp* fop) {
}
if (!debug->needed()) {
fop->free_(releaseDebugScript());
freeDebugScript(fop);
}
}
}
@ -4805,6 +4807,7 @@ BreakpointSite* JSScript::getOrCreateBreakpointSite(JSContext* cx,
return nullptr;
}
debug->numSites++;
AddCellMemory(this, sizeof(JSBreakpointSite), MemoryUse::BreakpointSite);
}
return site;
@ -4815,12 +4818,14 @@ void JSScript::destroyBreakpointSite(FreeOp* fop, jsbytecode* pc) {
BreakpointSite*& site = debug->breakpoints[pcToOffset(pc)];
MOZ_ASSERT(site);
RemoveCellMemory(this, sizeof(JSBreakpointSite), MemoryUse::BreakpointSite);
fop->delete_(site);
site = nullptr;
debug->numSites--;
if (!debug->needed()) {
fop->free_(releaseDebugScript());
freeDebugScript(fop);
}
}

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

@ -298,6 +298,11 @@ class DebugScript {
bool needed() const {
return generatorObserverCount > 0 || stepperCount > 0 || numSites > 0;
}
static size_t allocSize(size_t codeLength) {
return offsetof(DebugScript, breakpoints) +
codeLength * sizeof(BreakpointSite*);
}
};
using UniqueDebugScript = js::UniquePtr<DebugScript, JS::FreePolicy>;
@ -2661,6 +2666,7 @@ class JSScript : public js::gc::TenuredCell {
js::jit::JitScript* jitScript() { return jitScript_; }
void maybeReleaseJitScript();
void releaseJitScript();
inline js::GlobalObject& global() const;
inline bool hasGlobal(const js::GlobalObject* global) const;
@ -2958,6 +2964,7 @@ class JSScript : public js::gc::TenuredCell {
js::DebugScript* debugScript();
js::DebugScript* releaseDebugScript();
void destroyDebugScript(js::FreeOp* fop);
void freeDebugScript(js::FreeOp* fop);
bool hasDebugScript() const { return hasFlag(MutableFlags::HasDebugScript); }

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

@ -48,14 +48,16 @@ ObjectGroup::ObjectGroup(const Class* clasp, TaggedProto proto,
}
void ObjectGroup::finalize(FreeOp* fop) {
if (newScriptDontCheckGeneration()) {
newScriptDontCheckGeneration()->clear();
if (auto newScript = newScriptDontCheckGeneration()) {
newScript->clear();
fop->delete_(this, newScript, newScript->gcMallocBytes(),
MemoryUse::ObjectGroupAddendum);
}
fop->delete_(newScriptDontCheckGeneration());
if (maybePreliminaryObjectsDontCheckGeneration()) {
maybePreliminaryObjectsDontCheckGeneration()->clear();
}
fop->delete_(maybePreliminaryObjectsDontCheckGeneration());
fop->delete_(this, maybePreliminaryObjectsDontCheckGeneration(),
MemoryUse::ObjectGroupAddendum);
}
void ObjectGroup::setProtoUnchecked(TaggedProto proto) {
@ -78,11 +80,27 @@ size_t ObjectGroup::sizeOfExcludingThis(
return n;
}
static inline size_t AddendumAllocSize(ObjectGroup::AddendumKind kind,
void* addendum) {
if (kind == ObjectGroup::Addendum_NewScript) {
auto newScript = static_cast<TypeNewScript*>(addendum);
return newScript->gcMallocBytes();
}
if (kind == ObjectGroup::Addendum_PreliminaryObjects) {
return sizeof(PreliminaryObjectArrayWithTemplate);
}
// Other addendum kinds point to GC memory tracked elsewhere.
return 0;
}
void ObjectGroup::setAddendum(AddendumKind kind, void* addendum,
bool writeBarrier /* = true */) {
MOZ_ASSERT(!needsSweep());
MOZ_ASSERT(kind <= (OBJECT_FLAG_ADDENDUM_MASK >> OBJECT_FLAG_ADDENDUM_SHIFT));
RemoveCellMemory(this, AddendumAllocSize(addendumKind(), addendum_),
MemoryUse::ObjectGroupAddendum);
if (writeBarrier) {
// Manually trigger barriers if we are clearing new script or
// preliminary object information. Other addendums are immutable.
@ -105,6 +123,9 @@ void ObjectGroup::setAddendum(AddendumKind kind, void* addendum,
flags_ &= ~OBJECT_FLAG_ADDENDUM_MASK;
flags_ |= kind << OBJECT_FLAG_ADDENDUM_SHIFT;
addendum_ = addendum;
AddCellMemory(this, AddendumAllocSize(kind, addendum),
MemoryUse::ObjectGroupAddendum);
}
/* static */

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

@ -19,6 +19,25 @@
using namespace js;
template <typename Category>
void PICChain<Category>::addStub(JSObject* obj, CatStub* stub) {
MOZ_ASSERT(stub);
MOZ_ASSERT(!stub->next());
AddCellMemory(obj, sizeof(CatStub), MemoryUse::ForOfPICStub);
if (!stubs_) {
stubs_ = stub;
return;
}
CatStub* cur = stubs_;
while (cur->next()) {
cur = cur->next();
}
cur->append(stub);
}
bool js::ForOfPIC::Chain::initialize(JSContext* cx) {
MOZ_ASSERT(!initialized_);
@ -106,7 +125,7 @@ bool js::ForOfPIC::Chain::tryOptimizeArray(JSContext* cx,
} else if (!disabled_ && !isArrayStateStillSane()) {
// Otherwise, if array state is no longer sane, reinitialize.
reset();
reset(cx);
if (!initialize(cx)) {
return false;
@ -142,7 +161,7 @@ bool js::ForOfPIC::Chain::tryOptimizeArray(JSContext* cx,
// existing cache before adding new stubs. We shouldn't really have heavy
// churn on these.
if (numStubs() >= MAX_STUBS) {
eraseChain();
eraseChain(cx);
}
// Good to optimize now, create stub to add.
@ -153,7 +172,7 @@ bool js::ForOfPIC::Chain::tryOptimizeArray(JSContext* cx,
}
// Add the stub.
addStub(stub);
addStub(picObject_, stub);
*optimized = true;
return true;
@ -172,7 +191,7 @@ bool js::ForOfPIC::Chain::tryOptimizeArrayIteratorNext(JSContext* cx,
}
} else if (!disabled_ && !isArrayNextStillSane()) {
// Otherwise, if array iterator state is no longer sane, reinitialize.
reset();
reset(cx);
if (!initialize(cx)) {
return false;
@ -222,12 +241,12 @@ bool js::ForOfPIC::Chain::isArrayStateStillSane() {
return isArrayNextStillSane();
}
void js::ForOfPIC::Chain::reset() {
void js::ForOfPIC::Chain::reset(JSContext* cx) {
// Should never reset a disabled_ stub.
MOZ_ASSERT(!disabled_);
// Erase the chain.
eraseChain();
eraseChain(cx);
arrayProto_ = nullptr;
arrayIteratorProto_ = nullptr;
@ -243,22 +262,16 @@ void js::ForOfPIC::Chain::reset() {
initialized_ = false;
}
void js::ForOfPIC::Chain::eraseChain() {
void js::ForOfPIC::Chain::eraseChain(JSContext* cx) {
// Should never need to clear the chain of a disabled stub.
MOZ_ASSERT(!disabled_);
// Free all stubs.
Stub* stub = stubs_;
while (stub) {
Stub* next = stub->next();
js_delete(stub);
stub = next;
}
stubs_ = nullptr;
freeAllStubs(cx->defaultFreeOp());
}
// Trace the pointers stored directly on the stub.
void js::ForOfPIC::Chain::trace(JSTracer* trc) {
TraceEdge(trc, &picObject_, "ForOfPIC object");
if (!initialized_ || disabled_) {
return;
}
@ -274,30 +287,35 @@ void js::ForOfPIC::Chain::trace(JSTracer* trc) {
TraceEdge(trc, &canonicalNextFunc_,
"ForOfPIC ArrayIterator.prototype.next builtin.");
// Free all the stubs in the chain.
while (stubs_) {
removeStub(stubs_, nullptr);
if (trc->isMarkingTracer()) {
// Free all the stubs in the chain.
freeAllStubs(trc->runtime()->defaultFreeOp());
}
}
void js::ForOfPIC::Chain::sweep(FreeOp* fop) {
// Free all the stubs in the chain.
while (stubs_) {
Stub* next = stubs_->next();
fop->delete_(stubs_);
stubs_ = next;
}
fop->delete_(this);
}
static void ForOfPIC_finalize(FreeOp* fop, JSObject* obj) {
MOZ_ASSERT(fop->maybeOnHelperThread());
if (ForOfPIC::Chain* chain =
ForOfPIC::fromJSObject(&obj->as<NativeObject>())) {
chain->sweep(fop);
chain->finalize(fop, obj);
}
}
void js::ForOfPIC::Chain::finalize(FreeOp* fop, JSObject* obj) {
freeAllStubs(fop);
fop->delete_(obj, this, MemoryUse::ForOfPIC);
}
void js::ForOfPIC::Chain::freeAllStubs(FreeOp* fop) {
Stub* stub = stubs_;
while (stub) {
Stub* next = stub->next();
fop->delete_(picObject_, stub, MemoryUse::ForOfPICStub);
stub = next;
}
stubs_ = nullptr;
}
static void ForOfPIC_traceObject(JSTracer* trc, JSObject* obj) {
if (ForOfPIC::Chain* chain =
ForOfPIC::fromJSObject(&obj->as<NativeObject>())) {
@ -330,10 +348,11 @@ NativeObject* js::ForOfPIC::createForOfPICObject(JSContext* cx,
if (!obj) {
return nullptr;
}
ForOfPIC::Chain* chain = cx->new_<ForOfPIC::Chain>();
ForOfPIC::Chain* chain = cx->new_<ForOfPIC::Chain>(obj);
if (!chain) {
return nullptr;
}
InitObjectPrivate(obj, chain, MemoryUse::ForOfPIC);
obj->setPrivate(chain);
return obj;
}

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

@ -64,20 +64,7 @@ class PICChain {
public:
CatStub* stubs() const { return stubs_; }
void addStub(CatStub* stub) {
MOZ_ASSERT(stub);
MOZ_ASSERT(!stub->next());
if (!stubs_) {
stubs_ = stub;
return;
}
CatStub* cur = stubs_;
while (cur->next()) {
cur = cur->next();
}
cur->append(stub);
}
void addStub(JSObject* obj, CatStub* stub);
unsigned numStubs() const {
unsigned count = 0;
@ -86,17 +73,6 @@ class PICChain {
}
return count;
}
void removeStub(CatStub* stub, CatStub* previous) {
if (previous) {
MOZ_ASSERT(previous->next() == stub);
previous->next_ = stub->next();
} else {
MOZ_ASSERT(stub == stubs_);
stubs_ = stub->next();
}
js_delete(stub);
}
};
/*
@ -158,6 +134,9 @@ struct ForOfPIC {
*/
class Chain : public BaseChain {
private:
// Pointer to owning JSObject for memory accounting purposes.
GCPtrObject picObject_;
// Pointer to canonical Array.prototype and ArrayIterator.prototype
GCPtrNativeObject arrayProto_;
GCPtrNativeObject arrayIteratorProto_;
@ -184,8 +163,9 @@ struct ForOfPIC {
static const unsigned MAX_STUBS = 10;
public:
Chain()
explicit Chain(JSObject* picObject)
: BaseChain(),
picObject_(picObject),
arrayProto_(nullptr),
arrayIteratorProto_(nullptr),
arrayProtoShape_(nullptr),
@ -207,7 +187,7 @@ struct ForOfPIC {
bool tryOptimizeArrayIteratorNext(JSContext* cx, bool* optimized);
void trace(JSTracer* trc);
void sweep(FreeOp* fop);
void finalize(FreeOp* fop, JSObject* obj);
private:
// Check if the global array-related objects have not been messed with
@ -226,10 +206,12 @@ struct ForOfPIC {
bool hasMatchingStub(ArrayObject* obj);
// Reset the PIC and all info associated with it.
void reset();
void reset(JSContext* cx);
// Erase the stub chain.
void eraseChain();
void eraseChain(JSContext* cx);
void freeAllStubs(FreeOp* fop);
};
// Class for object that holds ForOfPIC chain.

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

@ -282,6 +282,12 @@ static inline const char* TypeIdString(jsid id) {
// complex ways which can't be understood statically.
class TypeNewScript {
private:
// Variable-length list of TypeNewScriptInitializer pointers.
struct InitializerList {
size_t length;
TypeNewScriptInitializer entries[1];
};
// Scripted function which this information was computed for.
HeapPtr<JSFunction*> function_ = {};
@ -303,7 +309,7 @@ class TypeNewScript {
// shape. Property assignments in inner frames are preceded by a series of
// SETPROP_FRAME entries specifying the stack down to the frame containing
// the write.
TypeNewScriptInitializer* initializerList = nullptr;
InitializerList* initializerList = nullptr;
// If there are additional properties found by the acquired properties
// analysis which were not found by the definite properties analysis, this
@ -356,9 +362,13 @@ class TypeNewScript {
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t gcMallocBytes() const;
static size_t offsetOfPreliminaryObjects() {
return offsetof(TypeNewScript, preliminaryObjects);
}
static size_t sizeOfInitializerList(size_t length);
};
inline bool ObjectGroup::hasUnanalyzedPreliminaryObjects() {

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

@ -3679,6 +3679,26 @@ size_t TypeNewScript::sizeOfIncludingThis(
return n;
}
/* static */ size_t TypeNewScript::sizeOfInitializerList(size_t length) {
// TypeNewScriptInitializer struct contains [1] element in its size.
size_t size = sizeof(TypeNewScript::InitializerList);
if (length > 0) {
size += (length - 1) * sizeof(TypeNewScriptInitializer);
}
return size;
}
size_t TypeNewScript::gcMallocBytes() const {
size_t size = sizeof(TypeNewScript);
if (preliminaryObjects) {
size += sizeof(PreliminaryObjectArray);
}
if (initializerList) {
size += sizeOfInitializerList(initializerList->length);
}
return size;
}
void TypeNewScript::registerNewObject(PlainObject* res) {
MOZ_ASSERT(!analyzed());
@ -3835,6 +3855,8 @@ bool TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group,
MOZ_ASSERT(OnlyHasDataProperties(templateObject()->lastProperty()));
MOZ_ASSERT(!initializerList);
InitializerList* newInitializerList = nullptr;
if (templateObject()->slotSpan() != 0) {
// Make sure that all definite properties found are reflected in the
// prefix shape. Otherwise, the constructor behaved differently before
@ -3866,25 +3888,27 @@ bool TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group,
}
}
TypeNewScriptInitializer done(TypeNewScriptInitializer::DONE, 0);
if (!initializerVector.append(done)) {
return false;
}
initializerList = group->zone()->pod_calloc<TypeNewScriptInitializer>(
initializerVector.length());
if (!initializerList) {
size_t nbytes = sizeOfInitializerList(initializerVector.length());
newInitializerList = reinterpret_cast<InitializerList*>(
group->zone()->pod_calloc<uint8_t>(nbytes));
if (!newInitializerList) {
ReportOutOfMemory(cx);
return false;
}
PodCopy(initializerList, initializerVector.begin(),
newInitializerList->length = initializerVector.length();
PodCopy(newInitializerList->entries, initializerVector.begin(),
initializerVector.length());
}
RemoveCellMemory(group, gcMallocBytes(), MemoryUse::ObjectGroupAddendum);
initializerList = newInitializerList;
js_delete(preliminaryObjects);
preliminaryObjects = nullptr;
AddCellMemory(group, gcMallocBytes(), MemoryUse::ObjectGroupAddendum);
if (prefixShape->slotSpan() == templateObject()->slotSpan()) {
// The definite properties analysis found exactly the properties that
// are held in common by the preliminary objects. No further analysis
@ -4006,9 +4030,10 @@ bool TypeNewScript::rollbackPartiallyInitializedObjects(JSContext* cx,
// Index in pcOffsets of the frame currently being checked for a SETPROP.
int setpropDepth = callDepth;
for (TypeNewScriptInitializer* init = initializerList;; init++) {
if (init->kind == TypeNewScriptInitializer::SETPROP) {
if (!pastProperty && pcOffsets[setpropDepth] < init->offset) {
for (size_t i = 0; i < initializerList->length; i++) {
const TypeNewScriptInitializer init = initializerList->entries[i];
if (init.kind == TypeNewScriptInitializer::SETPROP) {
if (!pastProperty && pcOffsets[setpropDepth] < init.offset) {
// Have not yet reached this setprop.
break;
}
@ -4016,12 +4041,12 @@ bool TypeNewScript::rollbackPartiallyInitializedObjects(JSContext* cx,
numProperties++;
pastProperty = false;
setpropDepth = callDepth;
} else if (init->kind == TypeNewScriptInitializer::SETPROP_FRAME) {
} else if (init.kind == TypeNewScriptInitializer::SETPROP_FRAME) {
if (!pastProperty) {
if (pcOffsets[setpropDepth] < init->offset) {
if (pcOffsets[setpropDepth] < init.offset) {
// Have not yet reached this inner call.
break;
} else if (pcOffsets[setpropDepth] > init->offset) {
} else if (pcOffsets[setpropDepth] > init.offset) {
// Have advanced past this inner call.
pastProperty = true;
} else if (setpropDepth == 0) {
@ -4033,7 +4058,7 @@ bool TypeNewScript::rollbackPartiallyInitializedObjects(JSContext* cx,
}
}
} else {
MOZ_ASSERT(init->kind == TypeNewScriptInitializer::DONE);
MOZ_ASSERT(init.kind == TypeNewScriptInitializer::DONE);
finished = true;
break;
}

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

@ -808,7 +808,7 @@ struct nsGridContainerFrame::UsedTrackSizes {
/** Helper function for the above method */
void ResolveSubgridTrackSizesForAxis(nsGridContainerFrame* aFrame,
LogicalAxis aAxis, Subgrid* aSubgrid,
gfxContext& aRC, nscoord aCBSize);
gfxContext& aRC, nscoord aContentBoxSize);
// This only has valid sizes when mCanResolveLineRangeSize is true in
// the same axis. It may have zero tracks (a grid with only abs.pos.
@ -2021,7 +2021,7 @@ struct nsGridContainerFrame::Tracks {
void CalculateSizes(GridReflowInput& aState,
nsTArray<GridItemInfo>& aGridItems,
const TrackSizingFunctions& aFunctions,
nscoord aContentSize, LineRange GridArea::*aRange,
nscoord aContentBoxSize, LineRange GridArea::*aRange,
SizingConstraint aConstraint);
/**
@ -2029,7 +2029,7 @@ struct nsGridContainerFrame::Tracks {
* https://drafts.csswg.org/css-align-3/#propdef-align-content
*/
void AlignJustifyContent(const nsStylePosition* aStyle, WritingMode aWM,
nscoord aContentSize, bool aIsSubgridded);
nscoord aContentBoxSize, bool aIsSubgridded);
nscoord GridLineEdge(uint32_t aLine, GridLineSide aSide) const {
if (MOZ_UNLIKELY(mSizes.IsEmpty())) {
@ -3010,20 +3010,23 @@ void nsGridContainerFrame::UsedTrackSizes::ResolveTrackSizesForAxis(
mCanResolveLineRangeSize[aAxis] = true;
} else {
const auto& range = subgrid->mArea.LineRangeForAxis(parentAxis);
nscoord cbSize = range.ToLength(parentSizes->mSizes[parentAxis]);
ResolveSubgridTrackSizesForAxis(aFrame, aAxis, subgrid, aRC, cbSize);
nscoord contentBoxSize = range.ToLength(parentSizes->mSizes[parentAxis]);
auto parentWM = aFrame->GetParent()->GetWritingMode();
contentBoxSize -= subgrid->mMarginBorderPadding.StartEnd(parentAxis, parentWM);
contentBoxSize = std::max(nscoord(0), contentBoxSize);
ResolveSubgridTrackSizesForAxis(aFrame, aAxis, subgrid, aRC, contentBoxSize);
}
}
void nsGridContainerFrame::UsedTrackSizes::ResolveSubgridTrackSizesForAxis(
nsGridContainerFrame* aFrame, LogicalAxis aAxis, Subgrid* aSubgrid,
gfxContext& aRC, nscoord aCBSize) {
gfxContext& aRC, nscoord aContentBoxSize) {
GridReflowInput state(aFrame, aRC);
state.mGridItems = aSubgrid->mGridItems;
Grid grid;
grid.mGridColEnd = aSubgrid->mGridColEnd;
grid.mGridRowEnd = aSubgrid->mGridRowEnd;
state.CalculateTrackSizesForAxis(aAxis, grid, aCBSize,
state.CalculateTrackSizesForAxis(aAxis, grid, aContentBoxSize,
SizingConstraint::NoConstraint);
const auto& tracks = aAxis == eLogicalAxisInline ? state.mCols : state.mRows;
mSizes[aAxis] = tracks.mSizes;
@ -3032,7 +3035,7 @@ void nsGridContainerFrame::UsedTrackSizes::ResolveSubgridTrackSizesForAxis(
}
void nsGridContainerFrame::GridReflowInput::CalculateTrackSizesForAxis(
LogicalAxis aAxis, const Grid& aGrid, nscoord aContentSize,
LogicalAxis aAxis, const Grid& aGrid, nscoord aContentBoxSize,
SizingConstraint aConstraint) {
auto& tracks = aAxis == eLogicalAxisInline ? mCols : mRows;
const auto& sizingFunctions =
@ -3046,10 +3049,10 @@ void nsGridContainerFrame::GridReflowInput::CalculateTrackSizesForAxis(
bool useParentGaps = false;
const bool isSubgriddedAxis = mFrame->IsSubgrid(aAxis);
if (MOZ_LIKELY(!isSubgriddedAxis)) {
tracks.Initialize(sizingFunctions, gapStyle, gridEnd, aContentSize);
tracks.Initialize(sizingFunctions, gapStyle, gridEnd, aContentBoxSize);
} else {
tracks.mGridGap = nsLayoutUtils::ResolveGapToLength(gapStyle, aContentSize);
tracks.mContentBoxSize = aContentSize;
tracks.mGridGap = nsLayoutUtils::ResolveGapToLength(gapStyle, aContentBoxSize);
tracks.mContentBoxSize = aContentBoxSize;
const auto* subgrid = mFrame->GetProperty(Subgrid::Prop());
tracks.mSizes.SetLength(gridEnd);
auto* parent = mFrame->ParentGridContainerForSubgrid();
@ -3068,7 +3071,7 @@ void nsGridContainerFrame::GridReflowInput::CalculateTrackSizesForAxis(
*fallbackTrackSizing->mAutoMaxSizing,
fallbackTrackSizing->mHasRepeatAuto,
fallbackTrackSizing->mRepeatAutoIndex),
gapStyle, gridEnd, aContentSize);
gapStyle, gridEnd, aContentBoxSize);
}
}
@ -3089,7 +3092,7 @@ void nsGridContainerFrame::GridReflowInput::CalculateTrackSizesForAxis(
fallbackTrackSizing->mHasRepeatAuto,
fallbackTrackSizing->mRepeatAutoIndex)
: sizingFunctions,
aContentSize,
aContentBoxSize,
aAxis == eLogicalAxisInline ? &GridArea::mCols : &GridArea::mRows,
aConstraint);
// XXXmats we're losing the baseline state of subgrid descendants that
@ -3098,8 +3101,8 @@ void nsGridContainerFrame::GridReflowInput::CalculateTrackSizesForAxis(
mGridItems.TruncateLength(origGridItemCount);
}
if (aContentSize != NS_UNCONSTRAINEDSIZE) {
tracks.AlignJustifyContent(mGridStyle, mWM, aContentSize, isSubgriddedAxis);
if (aContentBoxSize != NS_UNCONSTRAINEDSIZE) {
tracks.AlignJustifyContent(mGridStyle, mWM, aContentBoxSize, isSubgriddedAxis);
} else if (!useParentGaps) {
const nscoord gridGap = tracks.mGridGap;
nscoord pos = 0;
@ -5612,7 +5615,7 @@ void nsGridContainerFrame::Tracks::StretchFlexibleTracks(
}
void nsGridContainerFrame::Tracks::AlignJustifyContent(
const nsStylePosition* aStyle, WritingMode aWM, nscoord aContentSize,
const nsStylePosition* aStyle, WritingMode aWM, nscoord aContentBoxSize,
bool aIsSubgriddedAxis) {
const bool isAlign = mAxis == eLogicalAxisBlock;
// Align-/justify-content doesn't apply in a subgridded axis.
@ -5702,7 +5705,7 @@ void nsGridContainerFrame::Tracks::AlignJustifyContent(
}
}
}
space = aContentSize - trackSizeSum - SumOfGridGaps();
space = aContentBoxSize - trackSizeSum - SumOfGridGaps();
// Use the fallback value instead when applicable.
if (space < 0 ||
(alignment == NS_STYLE_ALIGN_SPACE_BETWEEN && mSizes.Length() == 1)) {

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

@ -406,6 +406,15 @@ VARCACHE_PREF(
RelaxedAtomicBool, false
)
#ifdef MOZ_WIDGET_GTK
VARCACHE_PREF(
Live,
"apz.gtk.kinetic_scroll.enabled",
APZGTKKineticScrollEnabled,
RelaxedAtomicBool, false
)
#endif
#if !defined(MOZ_WIDGET_ANDROID)
# define PREF_VALUE true
#else

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

@ -340,7 +340,7 @@ Classes = [
{
'cid': '{a181af0d-68b8-4308-94db-d4f859058215}',
'contract_ids': ['@mozilla.org/network/safe-file-output-stream;1'],
'type': 'nsAtomicFileOutputStream',
'type': 'nsSafeFileOutputStream',
'headers': ['nsFileStreams.h'],
},
{

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

@ -3,3 +3,4 @@
if os == "win": FAIL
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360

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

@ -1,6 +1,7 @@
[appearance-button-bevel-001.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if (os == "win") and debug and (processor == "x86_64"): FAIL
if (os == "win") and not debug: FAIL

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

@ -3,3 +3,4 @@
if os == "win": FAIL
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360

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

@ -3,3 +3,4 @@
if os == "win": FAIL
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360

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

@ -3,3 +3,4 @@
if os == "win": FAIL
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360

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

@ -1,6 +1,7 @@
[appearance-menulist-button-001.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if (os == "win") and debug and (processor == "x86_64"): FAIL
if (os == "win") and not debug: FAIL

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

@ -1,6 +1,7 @@
[appearance-menulist-button-002.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if os == "win": PASS
FAIL

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

@ -1,5 +1,6 @@
[appearance-meter-001.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if os == "win": FAIL

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

@ -1,5 +1,6 @@
[appearance-progress-bar-001.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if os == "win": FAIL

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

@ -1,3 +1,6 @@
[appearance-push-button-001.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if os == "win": FAIL

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

@ -1,4 +1,7 @@
[appearance-radio-001.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if (os == "win") and debug and (processor == "x86_64"): FAIL
if (os == "win") and not debug: FAIL

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

@ -1,4 +1,7 @@
[appearance-searchfield-001.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if (os == "win") and debug and (processor == "x86_64"): FAIL
if (os == "win") and not debug: FAIL

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

@ -1,4 +1,7 @@
[appearance-slider-horizontal-001.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if (os == "win") and debug and (processor == "x86_64"): FAIL
if (os == "win") and not debug: FAIL

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

@ -1,4 +1,7 @@
[appearance-square-button-001.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if (os == "win") and debug and (processor == "x86_64"): FAIL
if (os == "win") and not debug: FAIL

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

@ -1,4 +1,7 @@
[appearance-textarea-001.html]
disabled:
if debug and os == "win" and version == "6.1.7601": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
if os == "win" and processor == "aarch64": https://bugzilla.mozilla.org/show_bug.cgi?id=1560360
expected:
if (os == "win") and debug and (processor == "x86_64"): FAIL
if (os == "win") and not debug: FAIL

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

@ -0,0 +1,65 @@
<!DOCTYPE HTML>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html><head>
<meta charset="utf-8">
<title>Reference: subgrid auto track sizing</title>
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1558705">
<style>
html,body {
color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
}
.grid {
display: grid;
max-width: 260px;
padding: 1px 5px;
border: 1px solid;
}
.subgrid {
display: grid;
padding: 3px 5px 7px 11px;
border-style: solid;
border-width: 5px 7px 11px 3px;
margin: 7px 11px 3px 5px;
background: grey;
}
</style>
</head>
<body>
<article class="grid">
<div class="subgrid">
The cat can not be separated from milk
</div>
</article>
<article class="grid" style="grid-template-columns: 100px auto">
<div class="subgrid">
The cat can not be separated from milk
</div>
</article>
<article class="grid" style="grid-template-columns: auto 100px">
<div class="subgrid" style="grid-column:2">
The cat can not be separated from milk
</div>
</article>
<article class="grid" style="grid-template-columns: auto 100px auto">
<div class="subgrid" style="grid-column:2 span 2">
The cat can not be separated from milk
</div>
</article>
<article class="grid" style="grid-template-columns: auto 100px auto">
<div class="subgrid" style="grid-column:1 span 3">
The cat can not be separated from milk
</div>
</article>
</body>
</html>

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

@ -0,0 +1,68 @@
<!DOCTYPE HTML>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html><head>
<meta charset="utf-8">
<title>Test: subgrid auto track sizing</title>
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1558705">
<link rel="help" href="https://drafts.csswg.org/css-grid-2">
<link rel="match" href="auto-track-sizing-001-ref.html">
<style>
html,body {
color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
}
.grid {
display: grid;
max-width: 260px;
padding: 1px 5px;
border: 1px solid;
}
.subgrid {
display: grid;
grid-template-rows: subgrid;
padding: 3px 5px 7px 11px;
border-style: solid;
border-width: 5px 7px 11px 3px;
margin: 7px 11px 3px 5px;
background: grey;
}
</style>
</head>
<body>
<article class="grid">
<div class="subgrid">
The cat can not be separated from milk
</div>
</article>
<article class="grid" style="grid-template-columns: 100px auto">
<div class="subgrid">
The cat can not be separated from milk
</div>
</article>
<article class="grid" style="grid-template-columns: auto 100px">
<div class="subgrid" style="grid-column:2">
The cat can not be separated from milk
</div>
</article>
<article class="grid" style="grid-template-columns: auto 100px auto">
<div class="subgrid" style="grid-column:2 span 2">
The cat can not be separated from milk
</div>
</article>
<article class="grid" style="grid-template-columns: auto 100px auto">
<div class="subgrid" style="grid-column:1 span 3">
The cat can not be separated from milk
</div>
</article>
</body>
</html>

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

@ -18,29 +18,56 @@ var EXPORTED_SYMBOLS = ["ContentDOMReference"];
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
"@mozilla.org/uuid-generator;1",
"nsIUUIDGenerator");
XPCOMUtils.defineLazyServiceGetter(this, "finalizationService",
"@mozilla.org/toolkit/finalizationwitness;1",
"nsIFinalizationWitnessService");
/**
* @typedef {number} ElementID
* @typedef {Object} ElementIdentifier
*/
const FINALIZATION_TOPIC = "content-dom-reference-finalized";
// A WeakMap which ties finalization witness objects to the lifetime of the DOM
// nodes they're meant to witness. When the DOM node in the map key is
// finalized, the WeakMap stops holding the finalization witness in its value
// alive, which alerts our observer that the element has been destroyed.
const finalizerRoots = new WeakMap();
/**
* An identifier generated by ContentDOMReference is a unique pair of BrowsingContext
* ID and a UUID. gRegistry maps BrowsingContext's to an object with the following
* ID and a numeric ID. gRegistry maps BrowsingContext's to an object with the following
* properties:
*
* UUIDToElement:
* A Map of UUID strings to WeakReference's to the elements they refer to.
* IDToElement:
* A Map of IDs to WeakReference's to the elements they refer to.
*
* elementToUUID:
* A WeakMap from a DOM element to a UUID that refers to it.
* elementToID:
* A WeakMap from a DOM element to an ID that refers to it.
*/
var gRegistry = new WeakMap();
var ContentDOMReference = {
_init() {
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Services.obs.addObserver(this, FINALIZATION_TOPIC);
},
observe(subject, topic, data) {
if (topic !== FINALIZATION_TOPIC) {
throw new Error("Unexpected observer topic");
}
let identifier = JSON.parse(data);
this._revoke(identifier);
},
/**
* Generate and return an identifier for a given DOM element.
*
* @param {Element} element The DOM element to generate the identifier for.
* @return {Object} The identifier for the DOM element that can be passed between
* @return {ElementIdentifier} The identifier for the DOM element that can be passed between
* processes as a message.
*/
get(element) {
@ -53,85 +80,85 @@ var ContentDOMReference = {
let mappings = gRegistry.get(browsingContext);
if (!mappings) {
mappings = {
UUIDToElement: new Map(),
elementToUUID: new WeakMap(),
IDToElement: new Map(),
elementToID: new WeakMap(),
};
gRegistry.set(browsingContext, mappings);
}
let uuid = mappings.elementToUUID.get(element);
if (uuid) {
// We already had this element registered, so return the pre-existing UUID.
return { browsingContextId: browsingContext.id, uuid };
let id = mappings.elementToID.get(element);
if (id) {
// We already had this element registered, so return the pre-existing ID.
return { browsingContextId: browsingContext.id, id };
}
// We must be registering a new element at this point.
uuid = gUUIDGenerator.generateUUID().toString();
mappings.elementToUUID.set(element, uuid);
mappings.UUIDToElement.set(uuid, Cu.getWeakReference(element));
id = Math.random();
mappings.elementToID.set(element, id);
mappings.IDToElement.set(id, Cu.getWeakReference(element));
return { browsingContextId: browsingContext.id, uuid };
let identifier = { browsingContextId: browsingContext.id, id };
finalizerRoots.set(
element,
finalizationService.make(FINALIZATION_TOPIC,
JSON.stringify(identifier)));
return identifier;
},
/**
* Resolves an identifier back into the DOM Element that it was generated from.
*
* @param {Object} The identifier generated via ContentDOMReference.get for a
* @param {ElementIdentifier} The identifier generated via ContentDOMReference.get for a
* DOM element.
* @return {Element} The DOM element that the identifier was generated for, or
* null if the element does not still exist.
*/
resolve(identifier) {
let browsingContext = BrowsingContext.get(identifier.browsingContextId);
let uuid = identifier.uuid;
return this._resolveUUIDToElement(browsingContext, uuid);
let {id} = identifier;
return this._resolveIDToElement(browsingContext, id);
},
/**
* Removes an identifier from the registry so that subsequent attempts
* to resolve it will result in null. This is generally a good idea to avoid
* identifiers lying around taking up space (identifiers don't keep the
* DOM element alive, but the weak pointers themselves consume memory, and
* that's what we reclaim when revoking).
* to resolve it will result in null. This is done automatically when the
* target node is GCed.
*
* @param {Object} The identifier to revoke, issued by ContentDOMReference.get for
* @param {ElementIdentifier} The identifier to revoke, issued by ContentDOMReference.get for
* a DOM element.
*/
revoke(identifier) {
_revoke(identifier) {
let browsingContext = BrowsingContext.get(identifier.browsingContextId);
let uuid = identifier.uuid;
let {id} = identifier;
let mappings = gRegistry.get(browsingContext);
if (!mappings) {
return;
}
let element = this._resolveUUIDToElement(browsingContext, uuid);
if (element) {
mappings.elementToUUID.delete(element);
}
mappings.UUIDToElement.delete(uuid);
mappings.IDToElement.delete(id);
},
/**
* Private helper function that resolves a BrowsingContext and UUID (the
* Private helper function that resolves a BrowsingContext and ID (the
* pair that makes up an identifier) to a DOM element.
*
* @param {BrowsingContext} browsingContext The BrowsingContext that was hosting
* the DOM element at the time that the identifier was generated.
* @param {String} uuid The UUID generated for the DOM element.
* @param {ElementID} id The ID generated for the DOM element.
*
* @return {Element} The DOM element that the identifier was generated for, or
* null if the element does not still exist.
*/
_resolveUUIDToElement(browsingContext, uuid) {
_resolveIDToElement(browsingContext, id) {
let mappings = gRegistry.get(browsingContext);
if (!mappings) {
return null;
}
let weakReference = mappings.UUIDToElement.get(uuid);
let weakReference = mappings.IDToElement.get(id);
if (!weakReference) {
return null;
}
@ -139,3 +166,5 @@ var ContentDOMReference = {
return weakReference.get();
},
};
ContentDOMReference._init();

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

@ -437,7 +437,8 @@ PanGestureInput::PanGestureInput()
mHandledByAPZ(false),
mFollowedByMomentum(false),
mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
mOverscrollBehaviorAllowsSwipe(false) {}
mOverscrollBehaviorAllowsSwipe(false),
mSimulateMomentum(false) {}
PanGestureInput::PanGestureInput(PanGestureType aType, uint32_t aTime,
TimeStamp aTimeStamp,
@ -455,7 +456,8 @@ PanGestureInput::PanGestureInput(PanGestureType aType, uint32_t aTime,
mHandledByAPZ(false),
mFollowedByMomentum(false),
mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
mOverscrollBehaviorAllowsSwipe(false) {}
mOverscrollBehaviorAllowsSwipe(false),
mSimulateMomentum(false) {}
bool PanGestureInput::IsMomentum() const {
switch (mType) {
@ -477,7 +479,6 @@ WidgetWheelEvent PanGestureInput::ToWidgetWheelEvent(nsIWidget* aWidget) const {
mPanStartPoint,
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
wheelEvent.mButtons = 0;
wheelEvent.mDeltaMode = WheelEvent_Binding::DOM_DELTA_PIXEL;
wheelEvent.mMayHaveMomentum = true; // pan inputs may have momentum
wheelEvent.mIsMomentum = IsMomentum();
wheelEvent.mLineOrPageDeltaX = mLineOrPageDeltaX;
@ -486,6 +487,16 @@ WidgetWheelEvent PanGestureInput::ToWidgetWheelEvent(nsIWidget* aWidget) const {
wheelEvent.mDeltaY = mPanDisplacement.y;
wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
wheelEvent.mFocusSequenceNumber = mFocusSequenceNumber;
if (mDeltaType == PanGestureInput::PANDELTA_PAGE) {
// Emulate legacy widget/gtk behavior
wheelEvent.mDeltaMode = WheelEvent_Binding::DOM_DELTA_LINE;
wheelEvent.mIsNoLineOrPageDelta = true;
wheelEvent.mScrollType = WidgetWheelEvent::SCROLL_ASYNCHRONOUSELY;
wheelEvent.mDeltaX *= 3;
wheelEvent.mDeltaY *= 3;
} else {
wheelEvent.mDeltaMode = WheelEvent_Binding::DOM_DELTA_PIXEL;
}
return wheelEvent;
}
@ -498,6 +509,14 @@ bool PanGestureInput::TransformToLocal(
}
mLocalPanStartPoint = *panStartPoint;
if (mDeltaType == PanGestureInput::PANDELTA_PAGE) {
// Skip transforming the pan displacement because we want
// raw page proportion counts.
mLocalPanDisplacement.x = mPanDisplacement.x;
mLocalPanDisplacement.y = mPanDisplacement.y;
return true;
}
Maybe<ParentLayerPoint> panDisplacement =
UntransformVector(aTransform, mPanDisplacement, mPanStartPoint);
if (!panDisplacement) {

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

@ -332,6 +332,17 @@ class PanGestureInput : public InputData {
// user has stopped the animation by putting their fingers on a touchpad.
PANGESTURE_MOMENTUMEND
));
MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
PanDeltaType, (
// There are three kinds of scroll delta modes in Gecko: "page", "line"
// and "pixel". Touchpad pan gestures only support "page" and "pixel".
//
// NOTE: PANDELTA_PAGE currently replicates Gtk behavior
// (see AsyncPanZoomController::OnPan).
PANDELTA_PAGE,
PANDELTA_PIXEL
));
// clang-format on
PanGestureInput(PanGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
@ -368,11 +379,13 @@ class PanGestureInput : public InputData {
double mUserDeltaMultiplierX;
double mUserDeltaMultiplierY;
bool mHandledByAPZ;
PanDeltaType mDeltaType = PANDELTA_PIXEL;
bool mHandledByAPZ: 1;
// true if this is a PANGESTURE_END event that will be followed by a
// PANGESTURE_MOMENTUMSTART event.
bool mFollowedByMomentum;
bool mFollowedByMomentum: 1;
// If this is true, and this event started a new input block that couldn't
// find a scrollable target which is scrollable in the horizontal component
@ -380,15 +393,25 @@ class PanGestureInput : public InputData {
// hold until a content response has arrived, even if the block has a
// confirmed target.
// This is used by events that can result in a swipe instead of a scroll.
bool mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection;
bool mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection: 1;
// This is used by APZ to communicate to the macOS widget code whether
// the overscroll-behavior of the scroll frame handling this swipe allows
// non-local overscroll behaviors in the horizontal direction (such as
// swipe navigation).
bool mOverscrollBehaviorAllowsSwipe;
bool mOverscrollBehaviorAllowsSwipe: 1;
// XXX: If adding any more bools, switch to using bitfields instead.
// true if APZ should do a fling animation after this pan ends, like
// it would with touchscreens. (For platforms that don't emit momentum events.)
bool mSimulateMomentum: 1;
void SetHandledByAPZ(bool aHandled) { mHandledByAPZ = aHandled; }
void SetFollowedByMomentum(bool aFollowed) { mFollowedByMomentum = aFollowed; }
void SetRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(bool aRequires) {
mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection = aRequires;
}
void SetOverscrollBehaviorAllowsSwipe(bool aAllows) { mOverscrollBehaviorAllowsSwipe = aAllows; }
void SetSimulateMomentum(bool aSimulate) { mSimulateMomentum = aSimulate; }
};
/**

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

@ -119,6 +119,9 @@ using namespace mozilla::widget;
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/KnowsCompositor.h"
#include "mozilla/layers/APZInputBridge.h"
#include "mozilla/layers/IAPZCTreeManager.h"
#ifdef MOZ_X11
# include "GLContextGLX.h" // for GLContextGLX::FindVisual()
# include "GtkCompositorWidget.h"
@ -3034,8 +3037,11 @@ void nsWindow::OnScrollEvent(GdkEventScroll* aEvent) {
#if GTK_CHECK_VERSION(3, 4, 0)
// check for duplicate legacy scroll event, see GNOME bug 726878
if (aEvent->direction != GDK_SCROLL_SMOOTH &&
mLastScrollEventTime == aEvent->time)
mLastScrollEventTime == aEvent->time) {
LOG(("[%d] duplicate legacy scroll event %d\n", aEvent->time,
aEvent->direction));
return;
}
#endif
WidgetWheelEvent wheelEvent(true, eWheel, this);
wheelEvent.mDeltaMode = dom::WheelEvent_Binding::DOM_DELTA_LINE;
@ -3043,21 +3049,56 @@ void nsWindow::OnScrollEvent(GdkEventScroll* aEvent) {
#if GTK_CHECK_VERSION(3, 4, 0)
case GDK_SCROLL_SMOOTH: {
// As of GTK 3.4, all directional scroll events are provided by
// the GDK_SCROLL_SMOOTH direction on XInput2 devices.
// the GDK_SCROLL_SMOOTH direction on XInput2 and Wayland devices.
mLastScrollEventTime = aEvent->time;
// Special handling for touchpads to support flings
// (also known as kinetic/inertial/momentum scrolling)
GdkDevice* device = gdk_event_get_source_device((GdkEvent*)aEvent);
GdkInputSource source = gdk_device_get_source(device);
if (source == GDK_SOURCE_TOUCHSCREEN || source == GDK_SOURCE_TOUCHPAD) {
if (StaticPrefs::APZGTKKineticScrollEnabled() &&
gtk_check_version(3, 20, 0) == nullptr) {
static auto sGdkEventIsScrollStopEvent =
(gboolean(*)(const GdkEvent*))dlsym(
RTLD_DEFAULT, "gdk_event_is_scroll_stop_event");
LOG(("[%d] pan smooth event dx=%f dy=%f inprogress=%d\n",
aEvent->time, aEvent->delta_x, aEvent->delta_y, mPanInProgress));
PanGestureInput::PanGestureType eventType =
PanGestureInput::PANGESTURE_PAN;
if (sGdkEventIsScrollStopEvent((GdkEvent*)aEvent)) {
eventType = PanGestureInput::PANGESTURE_END;
mPanInProgress = false;
} else if (!mPanInProgress) {
eventType = PanGestureInput::PANGESTURE_START;
mPanInProgress = true;
}
LayoutDeviceIntPoint touchPoint = GetRefPoint(this, aEvent);
PanGestureInput panEvent(
eventType, aEvent->time, GetEventTimeStamp(aEvent->time),
ScreenPoint(touchPoint.x, touchPoint.y),
ScreenPoint(aEvent->delta_x, aEvent->delta_y),
KeymapWrapper::ComputeKeyModifiers(aEvent->state));
panEvent.mDeltaType = PanGestureInput::PANDELTA_PAGE;
panEvent.mSimulateMomentum = true;
DispatchPanGestureInput(panEvent);
return;
}
// Older GTK doesn't support stop events, so we can't support fling
wheelEvent.mScrollType = WidgetWheelEvent::SCROLL_ASYNCHRONOUSELY;
}
// TODO - use a more appropriate scrolling unit than lines.
// Multiply event deltas by 3 to emulate legacy behaviour.
wheelEvent.mDeltaX = aEvent->delta_x * 3;
wheelEvent.mDeltaY = aEvent->delta_y * 3;
wheelEvent.mIsNoLineOrPageDelta = true;
// This next step manually unsets smooth scrolling for touch devices
// that trigger GDK_SCROLL_SMOOTH. We use the slave device, which
// represents the actual input.
GdkDevice* device = gdk_event_get_source_device((GdkEvent*)aEvent);
GdkInputSource source = gdk_device_get_source(device);
if (source == GDK_SOURCE_TOUCHSCREEN || source == GDK_SOURCE_TOUCHPAD) {
wheelEvent.mScrollType = WidgetWheelEvent::SCROLL_ASYNCHRONOUSELY;
}
break;
}
#endif

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

@ -492,6 +492,8 @@ class nsWindow final : public nsBaseWidget {
// This field omits duplicate scroll events caused by GNOME bug 726878.
guint32 mLastScrollEventTime;
bool mPanInProgress = false;
// for touch event handling
nsRefPtrHashtable<nsPtrHashKey<GdkEventSequence>, mozilla::dom::Touch>
mTouches;

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

@ -1132,6 +1132,29 @@ void nsBaseWidget::DispatchTouchInput(MultiTouchInput& aInput) {
}
}
void nsBaseWidget::DispatchPanGestureInput(PanGestureInput& aInput) {
MOZ_ASSERT(NS_IsMainThread());
if (mAPZC) {
MOZ_ASSERT(APZThreadUtils::IsControllerThread());
uint64_t inputBlockId = 0;
ScrollableLayerGuid guid;
nsEventStatus result =
mAPZC->InputBridge()->ReceiveInputEvent(aInput, &guid, &inputBlockId);
if (result == nsEventStatus_eConsumeNoDefault) {
return;
}
WidgetWheelEvent event = aInput.ToWidgetWheelEvent(this);
ProcessUntransformedAPZEvent(&event, guid, inputBlockId, result);
} else {
WidgetWheelEvent event = aInput.ToWidgetWheelEvent(this);
nsEventStatus status;
DispatchEvent(&event, status);
}
}
nsEventStatus nsBaseWidget::DispatchInputEvent(WidgetInputEvent* aEvent) {
MOZ_ASSERT(NS_IsMainThread());
if (mAPZC) {

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

@ -619,6 +619,14 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
*/
void DispatchTouchInput(mozilla::MultiTouchInput& aInput);
/**
* Dispatch the given PanGestureInput through APZ to Gecko (if APZ is enabled)
* or directly to gecko (if APZ is not enabled). This function must only
* be called from the main thread, and if APZ is enabled, that must also be
* the APZ controller thread.
*/
void DispatchPanGestureInput(mozilla::PanGestureInput& aInput);
#if defined(XP_WIN)
void UpdateScrollCapture() override;

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

@ -1211,7 +1211,15 @@ struct ParamTraits<mozilla::PanGestureInput::PanGestureType>
mozilla::PanGestureInput::sHighestPanGestureType> {};
template <>
struct ParamTraits<mozilla::PanGestureInput> {
struct ParamTraits<mozilla::PanGestureInput::PanDeltaType>
: public ContiguousEnumSerializerInclusive<
mozilla::PanGestureInput::PanDeltaType,
mozilla::PanGestureInput::PanDeltaType::PANDELTA_PAGE,
mozilla::PanGestureInput::sHighestPanDeltaType> {};
template <>
struct ParamTraits<mozilla::PanGestureInput>
: BitfieldHelper<mozilla::PanGestureInput> {
typedef mozilla::PanGestureInput paramType;
static void Write(Message* aMsg, const paramType& aParam) {
@ -1225,6 +1233,7 @@ struct ParamTraits<mozilla::PanGestureInput> {
WriteParam(aMsg, aParam.mLineOrPageDeltaY);
WriteParam(aMsg, aParam.mUserDeltaMultiplierX);
WriteParam(aMsg, aParam.mUserDeltaMultiplierY);
WriteParam(aMsg, aParam.mDeltaType);
WriteParam(aMsg, aParam.mHandledByAPZ);
WriteParam(aMsg, aParam.mFollowedByMomentum);
WriteParam(
@ -1232,6 +1241,7 @@ struct ParamTraits<mozilla::PanGestureInput> {
aParam
.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection);
WriteParam(aMsg, aParam.mOverscrollBehaviorAllowsSwipe);
WriteParam(aMsg, aParam.mSimulateMomentum);
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
@ -1246,13 +1256,19 @@ struct ParamTraits<mozilla::PanGestureInput> {
ReadParam(aMsg, aIter, &aResult->mLineOrPageDeltaY) &&
ReadParam(aMsg, aIter, &aResult->mUserDeltaMultiplierX) &&
ReadParam(aMsg, aIter, &aResult->mUserDeltaMultiplierY) &&
ReadParam(aMsg, aIter, &aResult->mHandledByAPZ) &&
ReadParam(aMsg, aIter, &aResult->mFollowedByMomentum) &&
ReadParam(
aMsg, aIter,
&aResult
->mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection) &&
ReadParam(aMsg, aIter, &aResult->mOverscrollBehaviorAllowsSwipe);
ReadParam(aMsg, aIter, &aResult->mDeltaType) &&
ReadBoolForBitfield(aMsg, aIter, aResult,
&paramType::SetHandledByAPZ) &&
ReadBoolForBitfield(aMsg, aIter, aResult,
&paramType::SetFollowedByMomentum) &&
ReadBoolForBitfield(
aMsg, aIter, aResult,
&paramType::
SetRequiresContentResponseIfCannotScrollHorizontallyInStartDirection) &&
ReadBoolForBitfield(aMsg, aIter, aResult,
&paramType::SetOverscrollBehaviorAllowsSwipe) &&
ReadBoolForBitfield(aMsg, aIter, aResult,
&paramType::SetSimulateMomentum);
}
};