mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
merge mozilla-central to autoland. r=merge a=merge
This commit is contained in:
commit
5a95ac34b4
@ -5363,8 +5363,23 @@ nsBrowserAccess.prototype = {
|
||||
return newWindow;
|
||||
},
|
||||
|
||||
createContentWindowInFrame: function browser_createContentWindowInFrame(
|
||||
aURI, aParams, aWhere, aFlags, aNextTabParentId,
|
||||
aName) {
|
||||
// Passing a null-URI to only create the content window.
|
||||
return this.getContentWindowOrOpenURIInFrame(null, aParams, aWhere, aFlags,
|
||||
aNextTabParentId, aName);
|
||||
},
|
||||
|
||||
openURIInFrame: function browser_openURIInFrame(aURI, aParams, aWhere, aFlags,
|
||||
aNextTabParentId, aName) {
|
||||
return this.getContentWindowOrOpenURIInFrame(aURI, aParams, aWhere, aFlags,
|
||||
aNextTabParentId, aName);
|
||||
},
|
||||
|
||||
getContentWindowOrOpenURIInFrame: function browser_getContentWindowOrOpenURIInFrame(
|
||||
aURI, aParams, aWhere, aFlags,
|
||||
aNextTabParentId, aName) {
|
||||
if (aWhere != Ci.nsIBrowserDOMWindow.OPEN_NEWTAB) {
|
||||
dump("Error: openURIInFrame can only open in new tabs");
|
||||
return null;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "mozilla/dom/ElementBinding.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/dom/PointerEventHandler.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "Units.h"
|
||||
#include "DOMIntersectionObserver.h"
|
||||
@ -997,7 +998,7 @@ public:
|
||||
void SetPointerCapture(int32_t aPointerId, ErrorResult& aError)
|
||||
{
|
||||
bool activeState = false;
|
||||
if (!nsIPresShell::GetPointerInfo(aPointerId, activeState)) {
|
||||
if (!PointerEventHandler::GetPointerInfo(aPointerId, activeState)) {
|
||||
aError.Throw(NS_ERROR_DOM_INVALID_POINTER_ERR);
|
||||
return;
|
||||
}
|
||||
@ -1008,23 +1009,23 @@ public:
|
||||
if (!activeState) {
|
||||
return;
|
||||
}
|
||||
nsIPresShell::SetPointerCapturingContent(aPointerId, this);
|
||||
PointerEventHandler::SetPointerCaptureById(aPointerId, this);
|
||||
}
|
||||
void ReleasePointerCapture(int32_t aPointerId, ErrorResult& aError)
|
||||
{
|
||||
bool activeState = false;
|
||||
if (!nsIPresShell::GetPointerInfo(aPointerId, activeState)) {
|
||||
if (!PointerEventHandler::GetPointerInfo(aPointerId, activeState)) {
|
||||
aError.Throw(NS_ERROR_DOM_INVALID_POINTER_ERR);
|
||||
return;
|
||||
}
|
||||
if (HasPointerCapture(aPointerId)) {
|
||||
nsIPresShell::ReleasePointerCapturingContent(aPointerId);
|
||||
PointerEventHandler::ReleasePointerCaptureById(aPointerId);
|
||||
}
|
||||
}
|
||||
bool HasPointerCapture(long aPointerId)
|
||||
{
|
||||
nsIPresShell::PointerCaptureInfo* pointerCaptureInfo =
|
||||
nsIPresShell::GetPointerCaptureInfo(aPointerId);
|
||||
PointerCaptureInfo* pointerCaptureInfo =
|
||||
PointerEventHandler::GetPointerCaptureInfo(aPointerId);
|
||||
if (pointerCaptureInfo && pointerCaptureInfo->mPendingContent == this) {
|
||||
return true;
|
||||
}
|
||||
|
@ -262,7 +262,6 @@ NS_INTERFACE_MAP_END
|
||||
/******************************************************************/
|
||||
|
||||
static uint32_t sESMInstanceCount = 0;
|
||||
static bool sPointerEventEnabled = false;
|
||||
|
||||
uint64_t EventStateManager::sUserInputCounter = 0;
|
||||
int32_t EventStateManager::sUserInputEventDepth = 0;
|
||||
@ -310,13 +309,6 @@ EventStateManager::EventStateManager()
|
||||
UpdateUserActivityTimer();
|
||||
}
|
||||
++sESMInstanceCount;
|
||||
|
||||
static bool sAddedPointerEventEnabled = false;
|
||||
if (!sAddedPointerEventEnabled) {
|
||||
Preferences::AddBoolVarCache(&sPointerEventEnabled,
|
||||
"dom.w3c_pointer_events.enabled", false);
|
||||
sAddedPointerEventEnabled = true;
|
||||
}
|
||||
WheelTransaction::InitializeStatics();
|
||||
}
|
||||
|
||||
@ -624,6 +616,8 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
PointerEventHandler::UpdateActivePointerState(mouseEvent);
|
||||
|
||||
switch (aEvent->mMessage) {
|
||||
case eContextMenu:
|
||||
if (sIsPointerLocked) {
|
||||
@ -708,10 +702,8 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
mouseEvent->mReason = WidgetMouseEvent::eSynthesized;
|
||||
// then fall through...
|
||||
} else {
|
||||
if (sPointerEventEnabled) {
|
||||
// We should synthetize corresponding pointer events
|
||||
GeneratePointerEnterExit(ePointerLeave, mouseEvent);
|
||||
}
|
||||
// We should synthetize corresponding pointer events
|
||||
GeneratePointerEnterExit(ePointerLeave, mouseEvent);
|
||||
GenerateMouseEnterExit(mouseEvent);
|
||||
//This is a window level mouse exit event and should stop here
|
||||
aEvent->mMessage = eVoidEvent;
|
||||
@ -720,6 +712,10 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
MOZ_FALLTHROUGH;
|
||||
case eMouseMove:
|
||||
case ePointerDown:
|
||||
if (aEvent->mMessage == ePointerDown) {
|
||||
PointerEventHandler::ImplicitlyCapturePointer(aTargetFrame, aEvent);
|
||||
}
|
||||
MOZ_FALLTHROUGH;
|
||||
case ePointerMove: {
|
||||
// on the Mac, GenerateDragGesture() may not return until the drag
|
||||
// has completed and so |aTargetFrame| may have been deleted (moving
|
||||
@ -3207,15 +3203,28 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
}
|
||||
break;
|
||||
case ePointerCancel: {
|
||||
if(WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) {
|
||||
GenerateMouseEnterExit(mouseEvent);
|
||||
if(WidgetMouseEvent* pointerEvent = aEvent->AsPointerEvent()) {
|
||||
// Implicitly releasing capture for given pointer. ePointerLostCapture
|
||||
// should be send after ePointerUp or ePointerCancel.
|
||||
PointerEventHandler::ImplicitlyReleasePointerCapture(pointerEvent);
|
||||
GenerateMouseEnterExit(pointerEvent);
|
||||
// After UP/Cancel Touch pointers become invalid so we can remove relevant
|
||||
// helper from Table. Mouse/Pen pointers are valid all the time (not only
|
||||
// between down/up)
|
||||
if (pointerEvent->inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
|
||||
mPointersEnterLeaveHelper.Remove(pointerEvent->pointerId);
|
||||
GenerateMouseEnterExit(pointerEvent);
|
||||
}
|
||||
}
|
||||
// After firing the pointercancel event, a user agent must also fire a
|
||||
// pointerout event followed by a pointerleave event.
|
||||
MOZ_FALLTHROUGH;
|
||||
break;
|
||||
}
|
||||
case ePointerUp: {
|
||||
WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent();
|
||||
|
||||
// Implicitly releasing capture for given pointer. ePointerLostCapture
|
||||
// should be send after ePointerUp or ePointerCancel.
|
||||
PointerEventHandler::ImplicitlyReleasePointerCapture(pointerEvent);
|
||||
|
||||
// After UP/Cancel Touch pointers become invalid so we can remove relevant helper from Table
|
||||
// Mouse/Pen pointers are valid all the time (not only between down/up)
|
||||
if (pointerEvent->inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
|
||||
@ -4263,6 +4272,9 @@ void
|
||||
EventStateManager::GeneratePointerEnterExit(EventMessage aMessage,
|
||||
WidgetMouseEvent* aEvent)
|
||||
{
|
||||
if (!PointerEventHandler::IsPointerEventEnabled()) {
|
||||
return;
|
||||
}
|
||||
WidgetPointerEvent pointerEvent(*aEvent);
|
||||
pointerEvent.mMessage = aMessage;
|
||||
GenerateMouseEnterExit(&pointerEvent);
|
||||
@ -5068,7 +5080,9 @@ EventStateManager::ResetLastOverForContent(
|
||||
}
|
||||
|
||||
void
|
||||
EventStateManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent)
|
||||
EventStateManager::ContentRemoved(nsIDocument* aDocument,
|
||||
nsIContent* aMaybeContainer,
|
||||
nsIContent* aContent)
|
||||
{
|
||||
/*
|
||||
* Anchor and area elements when focused or hovered might make the UI to show
|
||||
@ -5111,6 +5125,8 @@ EventStateManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent)
|
||||
sDragOverContent = nullptr;
|
||||
}
|
||||
|
||||
PointerEventHandler::ReleaseIfCaptureByDescendant(aContent);
|
||||
|
||||
// See bug 292146 for why we want to null this out
|
||||
ResetLastOverForContent(0, mMouseEnterLeaveHelper, aContent);
|
||||
for (auto iter = mPointersEnterLeaveHelper.Iter();
|
||||
|
@ -140,7 +140,9 @@ public:
|
||||
* affect the return value.
|
||||
*/
|
||||
bool SetContentState(nsIContent* aContent, EventStates aState);
|
||||
void ContentRemoved(nsIDocument* aDocument, nsIContent* aContent);
|
||||
void ContentRemoved(nsIDocument* aDocument, nsIContent* aMaybeContainer,
|
||||
nsIContent* aContent);
|
||||
|
||||
bool EventStatusOK(WidgetGUIEvent* aEvent);
|
||||
|
||||
/**
|
||||
|
543
dom/events/PointerEventHandler.cpp
Normal file
543
dom/events/PointerEventHandler.cpp
Normal file
@ -0,0 +1,543 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "PointerEventHandler.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "PointerEvent.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
static bool sPointerEventEnabled = true;
|
||||
static bool sPointerEventImplicitCapture = false;
|
||||
|
||||
class PointerInfo final
|
||||
{
|
||||
public:
|
||||
uint16_t mPointerType;
|
||||
bool mActiveState;
|
||||
bool mPrimaryState;
|
||||
bool mPreventMouseEventByContent;
|
||||
explicit PointerInfo(bool aActiveState, uint16_t aPointerType,
|
||||
bool aPrimaryState)
|
||||
: mPointerType(aPointerType)
|
||||
, mActiveState(aActiveState)
|
||||
, mPrimaryState(aPrimaryState)
|
||||
, mPreventMouseEventByContent(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Keeps a map between pointerId and element that currently capturing pointer
|
||||
// with such pointerId. If pointerId is absent in this map then nobody is
|
||||
// capturing it. Additionally keep information about pending capturing content.
|
||||
static nsClassHashtable<nsUint32HashKey,
|
||||
PointerCaptureInfo>* sPointerCaptureList;
|
||||
|
||||
// Keeps information about pointers such as pointerId, activeState, pointerType,
|
||||
// primaryState
|
||||
static nsClassHashtable<nsUint32HashKey, PointerInfo>* sActivePointersIds;
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::Initialize()
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
Preferences::AddBoolVarCache(&sPointerEventEnabled,
|
||||
"dom.w3c_pointer_events.enabled", true);
|
||||
Preferences::AddBoolVarCache(&sPointerEventImplicitCapture,
|
||||
"dom.w3c_pointer_events.implicit_capture", true);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::InitializeStatics()
|
||||
{
|
||||
MOZ_ASSERT(!sPointerCaptureList, "InitializeStatics called multiple times!");
|
||||
sPointerCaptureList =
|
||||
new nsClassHashtable<nsUint32HashKey, PointerCaptureInfo>;
|
||||
sActivePointersIds = new nsClassHashtable<nsUint32HashKey, PointerInfo>;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::ReleaseStatics()
|
||||
{
|
||||
MOZ_ASSERT(sPointerCaptureList, "ReleaseStatics called without Initialize!");
|
||||
delete sPointerCaptureList;
|
||||
sPointerCaptureList = nullptr;
|
||||
delete sActivePointersIds;
|
||||
sActivePointersIds = nullptr;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
PointerEventHandler::IsPointerEventEnabled()
|
||||
{
|
||||
return sPointerEventEnabled;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
PointerEventHandler::IsPointerEventImplicitCaptureForTouchEnabled()
|
||||
{
|
||||
return sPointerEventEnabled && sPointerEventImplicitCapture;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::UpdateActivePointerState(WidgetMouseEvent* aEvent)
|
||||
{
|
||||
if (!IsPointerEventEnabled() || !aEvent) {
|
||||
return;
|
||||
}
|
||||
switch (aEvent->mMessage) {
|
||||
case eMouseEnterIntoWidget:
|
||||
// In this case we have to know information about available mouse pointers
|
||||
sActivePointersIds->Put(aEvent->pointerId,
|
||||
new PointerInfo(false, aEvent->inputSource, true));
|
||||
break;
|
||||
case ePointerDown:
|
||||
// In this case we switch pointer to active state
|
||||
if (WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent()) {
|
||||
sActivePointersIds->Put(pointerEvent->pointerId,
|
||||
new PointerInfo(true, pointerEvent->inputSource,
|
||||
pointerEvent->mIsPrimary));
|
||||
}
|
||||
break;
|
||||
case ePointerUp:
|
||||
// In this case we remove information about pointer or turn off active state
|
||||
if (WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent()) {
|
||||
if(pointerEvent->inputSource != nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
|
||||
sActivePointersIds->Put(pointerEvent->pointerId,
|
||||
new PointerInfo(false,
|
||||
pointerEvent->inputSource,
|
||||
pointerEvent->mIsPrimary));
|
||||
} else {
|
||||
sActivePointersIds->Remove(pointerEvent->pointerId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case eMouseExitFromWidget:
|
||||
// In this case we have to remove information about disappeared mouse
|
||||
// pointers
|
||||
sActivePointersIds->Remove(aEvent->pointerId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::SetPointerCaptureById(uint32_t aPointerId,
|
||||
nsIContent* aContent)
|
||||
{
|
||||
MOZ_ASSERT(aContent);
|
||||
if (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == GetPointerType(aPointerId)) {
|
||||
nsIPresShell::SetCapturingContent(aContent, CAPTURE_PREVENTDRAG);
|
||||
}
|
||||
|
||||
PointerCaptureInfo* pointerCaptureInfo = GetPointerCaptureInfo(aPointerId);
|
||||
if (pointerCaptureInfo) {
|
||||
pointerCaptureInfo->mPendingContent = aContent;
|
||||
} else {
|
||||
sPointerCaptureList->Put(aPointerId, new PointerCaptureInfo(aContent));
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ PointerCaptureInfo*
|
||||
PointerEventHandler::GetPointerCaptureInfo(uint32_t aPointerId)
|
||||
{
|
||||
PointerCaptureInfo* pointerCaptureInfo = nullptr;
|
||||
sPointerCaptureList->Get(aPointerId, &pointerCaptureInfo);
|
||||
return pointerCaptureInfo;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::ReleasePointerCaptureById(uint32_t aPointerId)
|
||||
{
|
||||
PointerCaptureInfo* pointerCaptureInfo = GetPointerCaptureInfo(aPointerId);
|
||||
if (pointerCaptureInfo && pointerCaptureInfo->mPendingContent) {
|
||||
if (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == GetPointerType(aPointerId)) {
|
||||
nsIPresShell::SetCapturingContent(nullptr, CAPTURE_PREVENTDRAG);
|
||||
}
|
||||
pointerCaptureInfo->mPendingContent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
PointerEventHandler::GetPointerInfo(uint32_t aPointerId, bool& aActiveState)
|
||||
{
|
||||
PointerInfo* pointerInfo = nullptr;
|
||||
if (sActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
|
||||
aActiveState = pointerInfo->mActiveState;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::CheckPointerCaptureState(WidgetPointerEvent* aEvent)
|
||||
{
|
||||
// Handle pending pointer capture before any pointer events except
|
||||
// gotpointercapture / lostpointercapture.
|
||||
if (!aEvent) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(IsPointerEventEnabled());
|
||||
MOZ_ASSERT(aEvent->mClass == ePointerEventClass);
|
||||
|
||||
PointerCaptureInfo* captureInfo = GetPointerCaptureInfo(aEvent->pointerId);
|
||||
|
||||
if (captureInfo &&
|
||||
captureInfo->mPendingContent != captureInfo->mOverrideContent) {
|
||||
// cache captureInfo->mPendingContent since it may be changed in the pointer
|
||||
// event listener
|
||||
nsIContent* pendingContent = captureInfo->mPendingContent.get();
|
||||
if (captureInfo->mOverrideContent) {
|
||||
DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ false, aEvent,
|
||||
captureInfo->mOverrideContent);
|
||||
}
|
||||
if (pendingContent) {
|
||||
DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ true, aEvent,
|
||||
pendingContent);
|
||||
}
|
||||
|
||||
captureInfo->mOverrideContent = pendingContent;
|
||||
if (captureInfo->Empty()) {
|
||||
sPointerCaptureList->Remove(aEvent->pointerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::ImplicitlyCapturePointer(nsIFrame* aFrame,
|
||||
WidgetEvent* aEvent)
|
||||
{
|
||||
MOZ_ASSERT(aEvent->mMessage == ePointerDown);
|
||||
if (!aFrame || !IsPointerEventEnabled() ||
|
||||
!IsPointerEventImplicitCaptureForTouchEnabled()) {
|
||||
return;
|
||||
}
|
||||
WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent();
|
||||
NS_WARNING_ASSERTION(pointerEvent,
|
||||
"Call ImplicitlyCapturePointer with non-pointer event");
|
||||
if (pointerEvent->inputSource != nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
|
||||
// We only implicitly capture the pointer for touch device.
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIContent> target;
|
||||
aFrame->GetContentForEvent(aEvent, getter_AddRefs(target));
|
||||
while (target && !target->IsElement()) {
|
||||
target = target->GetParent();
|
||||
}
|
||||
if (NS_WARN_IF(!target)) {
|
||||
return;
|
||||
}
|
||||
SetPointerCaptureById(pointerEvent->pointerId, target);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::ImplicitlyReleasePointerCapture(WidgetEvent* aEvent)
|
||||
{
|
||||
MOZ_ASSERT(aEvent);
|
||||
if (aEvent->mMessage != ePointerUp && aEvent->mMessage != ePointerCancel) {
|
||||
return;
|
||||
}
|
||||
WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent();
|
||||
ReleasePointerCaptureById(pointerEvent->pointerId);
|
||||
CheckPointerCaptureState(pointerEvent);
|
||||
}
|
||||
|
||||
/* static */ nsIContent*
|
||||
PointerEventHandler::GetPointerCapturingContent(uint32_t aPointerId)
|
||||
{
|
||||
PointerCaptureInfo* pointerCaptureInfo = GetPointerCaptureInfo(aPointerId);
|
||||
if (pointerCaptureInfo) {
|
||||
return pointerCaptureInfo->mOverrideContent;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */ nsIFrame*
|
||||
PointerEventHandler::GetPointerCapturingFrame(nsIFrame* aFrameUnderCursor,
|
||||
WidgetGUIEvent* aEvent)
|
||||
{
|
||||
if (!IsPointerEventEnabled() || (aEvent->mClass != ePointerEventClass &&
|
||||
aEvent->mClass != eMouseEventClass) ||
|
||||
aEvent->mMessage == ePointerDown || aEvent->mMessage == eMouseDown) {
|
||||
// Pointer capture should only be applied to all pointer events and mouse
|
||||
// events except ePointerDown and eMouseDown;
|
||||
return aFrameUnderCursor;
|
||||
}
|
||||
|
||||
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
|
||||
if (!mouseEvent) {
|
||||
return aFrameUnderCursor;
|
||||
}
|
||||
|
||||
// Find the content which captures the pointer.
|
||||
nsIContent* capturingContent =
|
||||
GetPointerCapturingContent(mouseEvent->pointerId);
|
||||
|
||||
if (!capturingContent) {
|
||||
return aFrameUnderCursor;
|
||||
}
|
||||
// Return the content's primary frame as the target frame.
|
||||
nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
|
||||
return capturingFrame ? capturingFrame : aFrameUnderCursor;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::ReleaseIfCaptureByDescendant(nsIContent* aContent)
|
||||
{
|
||||
// We should check that aChild does not contain pointer capturing elements.
|
||||
// If it does we should release the pointer capture for the elements.
|
||||
for (auto iter = sPointerCaptureList->Iter(); !iter.Done(); iter.Next()) {
|
||||
PointerCaptureInfo* data = iter.UserData();
|
||||
if (data && data->mPendingContent &&
|
||||
nsContentUtils::ContentIsDescendantOf(data->mPendingContent,
|
||||
aContent)) {
|
||||
ReleasePointerCaptureById(iter.Key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::PreHandlePointerEventsPreventDefault(
|
||||
WidgetPointerEvent* aPointerEvent,
|
||||
WidgetGUIEvent* aMouseOrTouchEvent)
|
||||
{
|
||||
if (!aPointerEvent->mIsPrimary || aPointerEvent->mMessage == ePointerDown) {
|
||||
return;
|
||||
}
|
||||
PointerInfo* pointerInfo = nullptr;
|
||||
if (!sActivePointersIds->Get(aPointerEvent->pointerId, &pointerInfo) ||
|
||||
!pointerInfo) {
|
||||
// The PointerInfo for active pointer should be added for normal cases. But
|
||||
// in some cases, we may receive mouse events before adding PointerInfo in
|
||||
// sActivePointersIds. (e.g. receive mousemove before eMouseEnterIntoWidget
|
||||
// or change preference 'dom.w3c_pointer_events.enabled' from off to on).
|
||||
// In these cases, we could ignore them because they are not the events
|
||||
// between a DefaultPrevented pointerdown and the corresponding pointerup.
|
||||
return;
|
||||
}
|
||||
if (!pointerInfo->mPreventMouseEventByContent) {
|
||||
return;
|
||||
}
|
||||
aMouseOrTouchEvent->PreventDefault(false);
|
||||
if (aPointerEvent->mMessage == ePointerUp) {
|
||||
pointerInfo->mPreventMouseEventByContent = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::PostHandlePointerEventsPreventDefault(
|
||||
WidgetPointerEvent* aPointerEvent,
|
||||
WidgetGUIEvent* aMouseOrTouchEvent)
|
||||
{
|
||||
if (!aPointerEvent->mIsPrimary || aPointerEvent->mMessage != ePointerDown ||
|
||||
!aPointerEvent->DefaultPreventedByContent()) {
|
||||
return;
|
||||
}
|
||||
PointerInfo* pointerInfo = nullptr;
|
||||
if (!sActivePointersIds->Get(aPointerEvent->pointerId, &pointerInfo) ||
|
||||
!pointerInfo) {
|
||||
// We already added the PointerInfo for active pointer when
|
||||
// PresShell::HandleEvent handling pointerdown event.
|
||||
#ifdef DEBUG
|
||||
MOZ_CRASH("Got ePointerDown w/o active pointer info!!");
|
||||
#endif // #ifdef DEBUG
|
||||
return;
|
||||
}
|
||||
// PreventDefault only applied for active pointers.
|
||||
if (!pointerInfo->mActiveState) {
|
||||
return;
|
||||
}
|
||||
aMouseOrTouchEvent->PreventDefault(false);
|
||||
pointerInfo->mPreventMouseEventByContent = true;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::DispatchPointerFromMouseOrTouch(
|
||||
PresShell* aShell,
|
||||
nsIFrame* aFrame,
|
||||
WidgetGUIEvent* aEvent,
|
||||
bool aDontRetargetEvents,
|
||||
nsEventStatus* aStatus,
|
||||
nsIContent** aTargetContent)
|
||||
{
|
||||
MOZ_ASSERT(IsPointerEventEnabled());
|
||||
MOZ_ASSERT(aFrame);
|
||||
MOZ_ASSERT(aEvent);
|
||||
|
||||
EventMessage pointerMessage = eVoidEvent;
|
||||
if (aEvent->mClass == eMouseEventClass) {
|
||||
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
|
||||
// 1. If it is not mouse then it is likely will come as touch event
|
||||
// 2. We don't synthesize pointer events for those events that are not
|
||||
// dispatched to DOM.
|
||||
if (!mouseEvent->convertToPointer ||
|
||||
!aEvent->IsAllowedToDispatchDOMEvent()) {
|
||||
return;
|
||||
}
|
||||
int16_t button = mouseEvent->button;
|
||||
switch (mouseEvent->mMessage) {
|
||||
case eMouseMove:
|
||||
button = WidgetMouseEvent::eNoButton;
|
||||
pointerMessage = ePointerMove;
|
||||
break;
|
||||
case eMouseUp:
|
||||
pointerMessage = mouseEvent->buttons ? ePointerMove : ePointerUp;
|
||||
break;
|
||||
case eMouseDown:
|
||||
pointerMessage =
|
||||
mouseEvent->buttons & ~nsContentUtils::GetButtonsFlagForButton(button) ?
|
||||
ePointerMove : ePointerDown;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
WidgetPointerEvent event(*mouseEvent);
|
||||
event.pointerId = mouseEvent->pointerId;
|
||||
event.inputSource = mouseEvent->inputSource;
|
||||
event.mMessage = pointerMessage;
|
||||
event.button = button;
|
||||
event.buttons = mouseEvent->buttons;
|
||||
event.pressure = event.buttons ?
|
||||
mouseEvent->pressure ? mouseEvent->pressure : 0.5f :
|
||||
0.0f;
|
||||
event.convertToPointer = mouseEvent->convertToPointer = false;
|
||||
PreHandlePointerEventsPreventDefault(&event, aEvent);
|
||||
RefPtr<PresShell> shell(aShell);
|
||||
shell->HandleEvent(aFrame, &event, aDontRetargetEvents, aStatus,
|
||||
aTargetContent);
|
||||
PostHandlePointerEventsPreventDefault(&event, aEvent);
|
||||
} else if (aEvent->mClass == eTouchEventClass) {
|
||||
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
|
||||
int16_t button = WidgetMouseEvent::eLeftButton;
|
||||
int16_t buttons = WidgetMouseEvent::eLeftButtonFlag;
|
||||
// loop over all touches and dispatch pointer events on each touch
|
||||
// copy the event
|
||||
switch (touchEvent->mMessage) {
|
||||
case eTouchMove:
|
||||
pointerMessage = ePointerMove;
|
||||
button = WidgetMouseEvent::eNoButton;
|
||||
break;
|
||||
case eTouchEnd:
|
||||
pointerMessage = ePointerUp;
|
||||
buttons = WidgetMouseEvent::eNoButtonFlag;
|
||||
break;
|
||||
case eTouchStart:
|
||||
pointerMessage = ePointerDown;
|
||||
break;
|
||||
case eTouchCancel:
|
||||
case eTouchPointerCancel:
|
||||
pointerMessage = ePointerCancel;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<PresShell> shell(aShell);
|
||||
for (uint32_t i = 0; i < touchEvent->mTouches.Length(); ++i) {
|
||||
Touch* touch = touchEvent->mTouches[i];
|
||||
if (!TouchManager::ShouldConvertTouchToPointer(touch, touchEvent)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WidgetPointerEvent event(touchEvent->IsTrusted(), pointerMessage,
|
||||
touchEvent->mWidget);
|
||||
event.mIsPrimary = i == 0;
|
||||
event.pointerId = touch->Identifier();
|
||||
event.mRefPoint = touch->mRefPoint;
|
||||
event.mModifiers = touchEvent->mModifiers;
|
||||
event.mWidth = touch->RadiusX(CallerType::System);
|
||||
event.mHeight = touch->RadiusY(CallerType::System);
|
||||
event.tiltX = touch->tiltX;
|
||||
event.tiltY = touch->tiltY;
|
||||
event.mTime = touchEvent->mTime;
|
||||
event.mTimeStamp = touchEvent->mTimeStamp;
|
||||
event.mFlags = touchEvent->mFlags;
|
||||
event.button = button;
|
||||
event.buttons = buttons;
|
||||
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||
event.convertToPointer = touch->convertToPointer = false;
|
||||
PreHandlePointerEventsPreventDefault(&event, aEvent);
|
||||
shell->HandleEvent(aFrame, &event, aDontRetargetEvents, aStatus,
|
||||
aTargetContent);
|
||||
PostHandlePointerEventsPreventDefault(&event, aEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ uint16_t
|
||||
PointerEventHandler::GetPointerType(uint32_t aPointerId)
|
||||
{
|
||||
PointerInfo* pointerInfo = nullptr;
|
||||
if (sActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
|
||||
return pointerInfo->mPointerType;
|
||||
}
|
||||
return nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
PointerEventHandler::GetPointerPrimaryState(uint32_t aPointerId)
|
||||
{
|
||||
PointerInfo* pointerInfo = nullptr;
|
||||
if (sActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
|
||||
return pointerInfo->mPrimaryState;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PointerEventHandler::DispatchGotOrLostPointerCaptureEvent(
|
||||
bool aIsGotCapture,
|
||||
const WidgetPointerEvent* aPointerEvent,
|
||||
nsIContent* aCaptureTarget)
|
||||
{
|
||||
nsIDocument* targetDoc = aCaptureTarget->OwnerDoc();
|
||||
nsCOMPtr<nsIPresShell> shell = targetDoc->GetShell();
|
||||
if (NS_WARN_IF(!shell)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aIsGotCapture && !aCaptureTarget->IsInUncomposedDoc()) {
|
||||
// If the capturing element was removed from the DOM tree, fire
|
||||
// ePointerLostCapture at the document.
|
||||
PointerEventInit init;
|
||||
init.mPointerId = aPointerEvent->pointerId;
|
||||
init.mBubbles = true;
|
||||
init.mComposed = true;
|
||||
ConvertPointerTypeToString(aPointerEvent->inputSource, init.mPointerType);
|
||||
init.mIsPrimary = aPointerEvent->mIsPrimary;
|
||||
RefPtr<PointerEvent> event;
|
||||
event = PointerEvent::Constructor(aCaptureTarget,
|
||||
NS_LITERAL_STRING("lostpointercapture"),
|
||||
init);
|
||||
bool dummy;
|
||||
targetDoc->DispatchEvent(event->InternalDOMEvent(), &dummy);
|
||||
return;
|
||||
}
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
WidgetPointerEvent localEvent(aPointerEvent->IsTrusted(),
|
||||
aIsGotCapture ? ePointerGotCapture :
|
||||
ePointerLostCapture,
|
||||
aPointerEvent->mWidget);
|
||||
|
||||
localEvent.AssignPointerEventData(*aPointerEvent, true);
|
||||
DebugOnly<nsresult> rv = shell->HandleEventWithTarget(
|
||||
&localEvent,
|
||||
aCaptureTarget->GetPrimaryFrame(),
|
||||
aCaptureTarget, &status);
|
||||
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"DispatchGotOrLostPointerCaptureEvent failed");
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
163
dom/events/PointerEventHandler.h
Normal file
163
dom/events/PointerEventHandler.h
Normal file
@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_PointerEventHandler_h
|
||||
#define mozilla_PointerEventHandler_h
|
||||
|
||||
#include "mozilla/EventForwards.h"
|
||||
|
||||
class nsIFrame;
|
||||
class nsIContent;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class PresShell;
|
||||
|
||||
class PointerCaptureInfo final
|
||||
{
|
||||
public:
|
||||
nsCOMPtr<nsIContent> mPendingContent;
|
||||
nsCOMPtr<nsIContent> mOverrideContent;
|
||||
|
||||
explicit PointerCaptureInfo(nsIContent* aPendingContent)
|
||||
: mPendingContent(aPendingContent)
|
||||
{
|
||||
MOZ_COUNT_CTOR(PointerCaptureInfo);
|
||||
}
|
||||
|
||||
~PointerCaptureInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(PointerCaptureInfo);
|
||||
}
|
||||
|
||||
bool Empty()
|
||||
{
|
||||
return !(mPendingContent || mOverrideContent);
|
||||
}
|
||||
};
|
||||
|
||||
class PointerEventHandler final
|
||||
{
|
||||
public:
|
||||
// Called in PresShell::Initialize to initialize pointer event related
|
||||
// preferences.
|
||||
static void Initialize();
|
||||
|
||||
// Called in nsLayoutStatics::Initialize/Shutdown to initialize pointer event
|
||||
// related static variables.
|
||||
static void InitializeStatics();
|
||||
static void ReleaseStatics();
|
||||
|
||||
// Return the preference value of pointer event enabled.
|
||||
static bool IsPointerEventEnabled();
|
||||
|
||||
// Return the preference value of implicit capture.
|
||||
static bool IsPointerEventImplicitCaptureForTouchEnabled();
|
||||
|
||||
// Called in ESM::PreHandleEvent to update current active pointers in a hash
|
||||
// table.
|
||||
static void UpdateActivePointerState(WidgetMouseEvent* aEvent);
|
||||
|
||||
// Got/release pointer capture of the specified pointer by the content.
|
||||
static void SetPointerCaptureById(uint32_t aPointerId, nsIContent* aContent);
|
||||
static void ReleasePointerCaptureById(uint32_t aPointerId);
|
||||
|
||||
// Get the pointer captured info of the specified pointer.
|
||||
static PointerCaptureInfo* GetPointerCaptureInfo(uint32_t aPointerId);
|
||||
|
||||
// GetPointerInfo returns true if pointer with aPointerId is situated in
|
||||
// device, false otherwise.
|
||||
// aActiveState is additional information, which shows state of pointer like
|
||||
// button state for mouse.
|
||||
static bool GetPointerInfo(uint32_t aPointerId, bool& aActiveState);
|
||||
|
||||
// CheckPointerCaptureState checks cases, when got/lostpointercapture events
|
||||
// should be fired.
|
||||
static void CheckPointerCaptureState(WidgetPointerEvent* aEvent);
|
||||
|
||||
// Implicitly get and release capture of current pointer for touch.
|
||||
static void ImplicitlyCapturePointer(nsIFrame* aFrame, WidgetEvent* aEvent);
|
||||
static void ImplicitlyReleasePointerCapture(WidgetEvent* aEvent);
|
||||
|
||||
/**
|
||||
* GetPointerCapturingFrame returns a target frame of aEvent. If the event is
|
||||
* a mouse or pointer event (except mousedown and pointerdown), the pointer
|
||||
* may be captured by a content. This method returns the capturing content's
|
||||
* primary frame. Otherwise, aFrameUnderCursor.
|
||||
*
|
||||
* @param aFrameUnderCursor A frame under cursor.
|
||||
* @param aEvent A mouse event or pointer event which may be
|
||||
* captured.
|
||||
*
|
||||
* @return Target frame for aEvent.
|
||||
*/
|
||||
static nsIFrame* GetPointerCapturingFrame(nsIFrame* aFrameUnderCursor,
|
||||
WidgetGUIEvent* aEvent);
|
||||
|
||||
static nsIContent* GetPointerCapturingContent(uint32_t aPointerId);
|
||||
|
||||
// Release pointer capture if captured by the specified content or it's
|
||||
// descendant. This is called to handle the case that the pointer capturing
|
||||
// content or it's parent is removed from the document.
|
||||
static void ReleaseIfCaptureByDescendant(nsIContent* aContent);
|
||||
|
||||
/*
|
||||
* This function handles the case when content had called preventDefault on
|
||||
* the active pointer. In that case we have to prevent firing subsequent mouse
|
||||
* to content. We check the flag PointerInfo::mPreventMouseEventByContent and
|
||||
* call PreventDefault(false) to stop default behaviors and stop firing mouse
|
||||
* events to content and chrome.
|
||||
*
|
||||
* note: mouse transition events are excluded
|
||||
* note: we have to clean mPreventMouseEventByContent on pointerup for those
|
||||
* devices support hover
|
||||
* note: we don't suppress firing mouse events to chrome and system group
|
||||
* handlers because they may implement default behaviors
|
||||
*/
|
||||
static void PreHandlePointerEventsPreventDefault(
|
||||
WidgetPointerEvent* aPointerEvent,
|
||||
WidgetGUIEvent* aMouseOrTouchEvent);
|
||||
|
||||
/*
|
||||
* This function handles the preventDefault behavior of pointerdown. When user
|
||||
* preventDefault on pointerdown, We have to mark the active pointer to
|
||||
* prevent sebsequent mouse events (except mouse transition events) and
|
||||
* default behaviors.
|
||||
*
|
||||
* We add mPreventMouseEventByContent flag in PointerInfo to represent the
|
||||
* active pointer won't firing compatible mouse events. It's set to true when
|
||||
* content preventDefault on pointerdown
|
||||
*/
|
||||
static void PostHandlePointerEventsPreventDefault(
|
||||
WidgetPointerEvent* aPointerEvent,
|
||||
WidgetGUIEvent* aMouseOrTouchEvent);
|
||||
|
||||
static void DispatchPointerFromMouseOrTouch(PresShell* aShell,
|
||||
nsIFrame* aFrame,
|
||||
WidgetGUIEvent* aEvent,
|
||||
bool aDontRetargetEvents,
|
||||
nsEventStatus* aStatus,
|
||||
nsIContent** aTargetContent);
|
||||
|
||||
private:
|
||||
// GetPointerType returns pointer type like mouse, pen or touch for pointer
|
||||
// event with pointerId. The return value must be one of
|
||||
// nsIDOMMouseEvent::MOZ_SOURCE_*
|
||||
static uint16_t GetPointerType(uint32_t aPointerId);
|
||||
|
||||
// GetPointerPrimaryState returns state of attribute isPrimary for pointer
|
||||
// event with pointerId
|
||||
static bool GetPointerPrimaryState(uint32_t aPointerId);
|
||||
|
||||
static void DispatchGotOrLostPointerCaptureEvent(
|
||||
bool aIsGotCapture,
|
||||
const WidgetPointerEvent* aPointerEvent,
|
||||
nsIContent* aCaptureTarget);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_PointerEventHandler_h
|
@ -62,6 +62,7 @@ EXPORTS.mozilla.dom += [
|
||||
'NotifyPaintEvent.h',
|
||||
'PaintRequest.h',
|
||||
'PointerEvent.h',
|
||||
'PointerEventHandler.h',
|
||||
'ScrollAreaEvent.h',
|
||||
'SimpleGestureEvent.h',
|
||||
'StorageEvent.h',
|
||||
@ -111,6 +112,7 @@ UNIFIED_SOURCES += [
|
||||
'NotifyPaintEvent.cpp',
|
||||
'PaintRequest.cpp',
|
||||
'PointerEvent.cpp',
|
||||
'PointerEventHandler.cpp',
|
||||
'ScrollAreaEvent.cpp',
|
||||
'SimpleGestureEvent.cpp',
|
||||
'StorageEvent.cpp',
|
||||
|
@ -239,6 +239,11 @@ IDBTransaction::Create(JSContext* aCx, IDBDatabase* aDatabase,
|
||||
nsAutoPtr<WorkerHolder> workerHolder(
|
||||
new WorkerHolder(workerPrivate, transaction));
|
||||
if (NS_WARN_IF(!workerHolder->HoldWorker(workerPrivate, Canceling))) {
|
||||
// Silence the destructor assertion if we never made this object live.
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!transaction->mSentCommitOrAbort);
|
||||
transaction->mSentCommitOrAbort = true;
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,20 @@ interface nsIBrowserDOMWindow : nsISupports
|
||||
in short aWhere, in long aFlags,
|
||||
in nsIPrincipal aTriggeringPrincipal);
|
||||
|
||||
/**
|
||||
* As above, but return the nsIFrameLoaderOwner for the new window.
|
||||
*
|
||||
* Additional Parameters:
|
||||
* @param aNextTabParentId The TabParent to associate the window with.
|
||||
* @param aName The name to give the window opened in the new tab.
|
||||
* @return The nsIFrameLoaderOwner for the newly opened window.
|
||||
*/
|
||||
nsIFrameLoaderOwner
|
||||
createContentWindowInFrame(in nsIURI aURI, in nsIOpenURIInFrameParams params,
|
||||
in short aWhere, in long aFlags,
|
||||
in unsigned long long aNextTabParentId,
|
||||
in AString aName);
|
||||
|
||||
/**
|
||||
* Load a URI.
|
||||
|
||||
@ -132,16 +146,17 @@ interface nsIBrowserDOMWindow : nsISupports
|
||||
* As above, but return the nsIFrameLoaderOwner for the new window.
|
||||
*
|
||||
* Additional Parameters:
|
||||
* @param aNextTabParentId The TabParent to associate the window with
|
||||
* @param aNextTabParentId The TabParent to associate the window with.
|
||||
* @param aName The name to give the window opened in the new tab.
|
||||
* @return The nsIFrameLoaderOwner for the newly opened window.
|
||||
// XXXbz is this the right API?
|
||||
// See bug 537428
|
||||
*/
|
||||
nsIFrameLoaderOwner openURIInFrame(in nsIURI aURI, in nsIOpenURIInFrameParams params,
|
||||
in short aWhere, in long aFlags,
|
||||
in unsigned long long aNextTabParentId,
|
||||
in AString aName);
|
||||
nsIFrameLoaderOwner
|
||||
openURIInFrame(in nsIURI aURI, in nsIOpenURIInFrameParams params,
|
||||
in short aWhere, in long aFlags,
|
||||
in unsigned long long aNextTabParentId,
|
||||
in AString aName);
|
||||
|
||||
/**
|
||||
* @param aWindow the window to test.
|
||||
|
@ -954,10 +954,18 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
|
||||
return rv;
|
||||
}
|
||||
|
||||
OptionalURIParams uriToLoad;
|
||||
if (aURI) {
|
||||
SerializeURI(aURI, uriToLoad);
|
||||
} else {
|
||||
uriToLoad = mozilla::void_t();
|
||||
}
|
||||
|
||||
windowCreated =
|
||||
SendCreateWindow(aTabOpener, newChild, renderFrame,
|
||||
aChromeFlags, aCalledFromJS, aPositionSpecified,
|
||||
aSizeSpecified,
|
||||
uriToLoad,
|
||||
features,
|
||||
baseURIString,
|
||||
fullZoom,
|
||||
|
@ -4490,7 +4490,8 @@ ContentParent::CommonCreateWindow(PBrowserParent* aThisTab,
|
||||
nsresult& aResult,
|
||||
nsCOMPtr<nsITabParent>& aNewTabParent,
|
||||
bool* aWindowIsNew,
|
||||
nsIPrincipal* aTriggeringPrincipal)
|
||||
nsIPrincipal* aTriggeringPrincipal,
|
||||
bool aLoadURI)
|
||||
|
||||
{
|
||||
// The content process should never be in charge of computing whether or
|
||||
@ -4574,10 +4575,19 @@ ContentParent::CommonCreateWindow(PBrowserParent* aThisTab,
|
||||
params->SetTriggeringPrincipal(aTriggeringPrincipal);
|
||||
|
||||
nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
|
||||
aResult = browserDOMWin->OpenURIInFrame(aURIToLoad, params, openLocation,
|
||||
nsIBrowserDOMWindow::OPEN_NEW,
|
||||
aNextTabParentId, aName,
|
||||
getter_AddRefs(frameLoaderOwner));
|
||||
if (aLoadURI) {
|
||||
aResult = browserDOMWin->OpenURIInFrame(aURIToLoad,
|
||||
params, openLocation,
|
||||
nsIBrowserDOMWindow::OPEN_NEW,
|
||||
aNextTabParentId, aName,
|
||||
getter_AddRefs(frameLoaderOwner));
|
||||
} else {
|
||||
aResult = browserDOMWin->CreateContentWindowInFrame(aURIToLoad,
|
||||
params, openLocation,
|
||||
nsIBrowserDOMWindow::OPEN_NEW,
|
||||
aNextTabParentId, aName,
|
||||
getter_AddRefs(frameLoaderOwner));
|
||||
}
|
||||
if (NS_SUCCEEDED(aResult) && frameLoaderOwner) {
|
||||
RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
|
||||
if (frameLoader) {
|
||||
@ -4622,7 +4632,7 @@ ContentParent::CommonCreateWindow(PBrowserParent* aThisTab,
|
||||
->SendSetOriginAttributes(openerOriginAttributes);
|
||||
}
|
||||
|
||||
if (aURIToLoad) {
|
||||
if (aURIToLoad && aLoadURI) {
|
||||
nsCOMPtr<mozIDOMWindowProxy> openerWindow;
|
||||
if (aSetOpener && thisTabParent) {
|
||||
openerWindow = thisTabParent->GetParentWindowOuter();
|
||||
@ -4652,6 +4662,7 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
|
||||
const bool& aCalledFromJS,
|
||||
const bool& aPositionSpecified,
|
||||
const bool& aSizeSpecified,
|
||||
const OptionalURIParams& aURIToLoad,
|
||||
const nsCString& aFeatures,
|
||||
const nsCString& aBaseURI,
|
||||
const float& aFullZoom,
|
||||
@ -4694,19 +4705,21 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
|
||||
const uint64_t nextTabParentId = ++sNextTabParentId;
|
||||
sNextTabParents.Put(nextTabParentId, newTab);
|
||||
|
||||
const nsCOMPtr<nsIURI> uriToLoad = DeserializeURI(aURIToLoad);
|
||||
|
||||
nsCOMPtr<nsITabParent> newRemoteTab;
|
||||
mozilla::ipc::IPCResult ipcResult =
|
||||
CommonCreateWindow(aThisTab, /* aSetOpener = */ true, aChromeFlags,
|
||||
aCalledFromJS, aPositionSpecified, aSizeSpecified,
|
||||
nullptr, aFeatures, aBaseURI, aFullZoom,
|
||||
uriToLoad, aFeatures, aBaseURI, aFullZoom,
|
||||
nextTabParentId, VoidString(), rv,
|
||||
newRemoteTab, &cwi.windowOpened(),
|
||||
aTriggeringPrincipal);
|
||||
aTriggeringPrincipal, /* aLoadUri = */ false);
|
||||
if (!ipcResult) {
|
||||
return ipcResult;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || !newRemoteTab) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
@ -4756,7 +4769,8 @@ ContentParent::RecvCreateWindowInDifferentProcess(
|
||||
aCalledFromJS, aPositionSpecified, aSizeSpecified,
|
||||
uriToLoad, aFeatures, aBaseURI, aFullZoom,
|
||||
/* aNextTabParentId = */ 0, aName, rv,
|
||||
newRemoteTab, &windowIsNew, aTriggeringPrincipal);
|
||||
newRemoteTab, &windowIsNew, aTriggeringPrincipal,
|
||||
/* aLoadUri = */ true);
|
||||
if (!ipcResult) {
|
||||
return ipcResult;
|
||||
}
|
||||
|
@ -532,6 +532,7 @@ public:
|
||||
const bool& aCalledFromJS,
|
||||
const bool& aPositionSpecified,
|
||||
const bool& aSizeSpecified,
|
||||
const OptionalURIParams& aURIToLoad,
|
||||
const nsCString& aFeatures,
|
||||
const nsCString& aBaseURI,
|
||||
const float& aFullZoom,
|
||||
@ -687,6 +688,9 @@ private:
|
||||
const bool& aIsForBrowser) override;
|
||||
using PContentParent::SendPTestShellConstructor;
|
||||
|
||||
// Set aLoadUri to true to load aURIToLoad and to false to only create the
|
||||
// window. aURIToLoad should always be provided, if available, to ensure
|
||||
// compatibility with GeckoView.
|
||||
mozilla::ipc::IPCResult
|
||||
CommonCreateWindow(PBrowserParent* aThisTab,
|
||||
bool aSetOpener,
|
||||
@ -703,7 +707,8 @@ private:
|
||||
nsresult& aResult,
|
||||
nsCOMPtr<nsITabParent>& aNewTabParent,
|
||||
bool* aWindowIsNew,
|
||||
nsIPrincipal* aTriggeringPrincipal);
|
||||
nsIPrincipal* aTriggeringPrincipal,
|
||||
bool aLoadUri);
|
||||
|
||||
FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)
|
||||
|
||||
|
@ -990,6 +990,7 @@ parent:
|
||||
bool aCalledFromJS,
|
||||
bool aPositionSpecified,
|
||||
bool aSizeSpecified,
|
||||
OptionalURIParams aURIToLoad,
|
||||
nsCString aFeatures,
|
||||
nsCString aBaseURI,
|
||||
float aFullZoom,
|
||||
|
@ -122,6 +122,7 @@ AudioStream::AudioStream(DataSource& aSource)
|
||||
, mDumpFile(nullptr)
|
||||
, mState(INITIALIZED)
|
||||
, mDataSource(aSource)
|
||||
, mPrefillQuirk(false)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
if (XRE_IsContentProcess()) {
|
||||
@ -356,6 +357,10 @@ AudioStream::Init(uint32_t aNumChannels, uint32_t aChannelMap, uint32_t aRate)
|
||||
return NS_ERROR_DOM_MEDIA_CUBEB_INITIALIZATION_ERR;
|
||||
}
|
||||
|
||||
// cubeb's winmm backend prefills buffers on init rather than stream start.
|
||||
// See https://github.com/kinetiknz/cubeb/issues/150
|
||||
mPrefillQuirk = !strcmp(cubeb_get_backend_id(cubebContext), "winmm");
|
||||
|
||||
return OpenCubeb(cubebContext, params, startTime, CubebUtils::GetFirstStream());
|
||||
}
|
||||
|
||||
@ -630,7 +635,7 @@ AudioStream::DataCallback(void* aBuffer, long aFrames)
|
||||
auto writer = AudioBufferWriter(
|
||||
reinterpret_cast<AudioDataValue*>(aBuffer), mOutChannels, aFrames);
|
||||
|
||||
if (!strcmp(cubeb_get_backend_id(CubebUtils::GetCubebContext()), "winmm")) {
|
||||
if (mPrefillQuirk) {
|
||||
// Don't consume audio data until Start() is called.
|
||||
// Expected only with cubeb winmm backend.
|
||||
if (mState == INITIALIZED) {
|
||||
|
@ -317,6 +317,8 @@ private:
|
||||
StreamState mState;
|
||||
|
||||
DataSource& mDataSource;
|
||||
|
||||
bool mPrefillQuirk;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
#include "mozilla/ErrorNames.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
@ -1124,7 +1126,29 @@ ServiceWorkerRegistrar::GetShutdownPhase() const
|
||||
MOZ_RELEASE_ASSERT(svc);
|
||||
|
||||
nsCOMPtr<nsIAsyncShutdownClient> client;
|
||||
Unused << svc->GetProfileBeforeChange(getter_AddRefs(client));
|
||||
nsresult rv = svc->GetProfileBeforeChange(getter_AddRefs(client));
|
||||
// If this fails, something is very wrong on the JS side (or we're out of
|
||||
// memory), and there's no point in continuing startup. Include as much
|
||||
// information as possible in the crash report.
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS) {
|
||||
if (auto* context = CycleCollectedJSContext::Get()) {
|
||||
if (nsCOMPtr<nsIException> exn = context->GetPendingException()) {
|
||||
nsAutoCString msg;
|
||||
if (NS_SUCCEEDED(exn->GetMessageMoz(msg))) {
|
||||
MOZ_CRASH_UNSAFE_PRINTF("Failed to get profileBeforeChange shutdown blocker: %s",
|
||||
msg.get());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString errorName;
|
||||
GetErrorName(rv, errorName);
|
||||
MOZ_CRASH_UNSAFE_PRINTF("Failed to get profileBeforeChange shutdown blocker: %s",
|
||||
errorName.get());
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(client);
|
||||
return Move(client);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace layers {
|
||||
|
||||
StackingContextHelper::StackingContextHelper()
|
||||
: mBuilder(nullptr)
|
||||
, mScale(1.0f, 1.0f)
|
||||
{
|
||||
// mOrigin remains at 0,0
|
||||
}
|
||||
@ -24,6 +25,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
|
||||
const Maybe<gfx::Matrix4x4>& aTransform,
|
||||
const nsTArray<wr::WrFilterOp>& aFilters)
|
||||
: mBuilder(&aBuilder)
|
||||
, mScale(1.0f, 1.0f)
|
||||
{
|
||||
wr::LayoutRect scBounds = aParentSC.ToRelativeLayoutRect(aLayer->BoundsForStackingContext());
|
||||
Layer* layer = aLayer->GetLayer();
|
||||
@ -48,6 +50,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
|
||||
gfx::Matrix4x4* aTransformPtr,
|
||||
const nsTArray<wr::WrFilterOp>& aFilters)
|
||||
: mBuilder(&aBuilder)
|
||||
, mScale(1.0f, 1.0f)
|
||||
{
|
||||
wr::LayoutRect scBounds = aParentSC.ToRelativeLayoutRect(aLayer->BoundsForStackingContext());
|
||||
if (aTransformPtr) {
|
||||
@ -71,7 +74,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
nsDisplayList* aDisplayList,
|
||||
gfx::Matrix4x4Typed<LayerPixel, LayerPixel>* aBoundTransform,
|
||||
const gfx::Matrix4x4* aBoundTransform,
|
||||
uint64_t aAnimationsId,
|
||||
float* aOpacityPtr,
|
||||
gfx::Matrix4x4* aTransformPtr,
|
||||
@ -80,12 +83,19 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
|
||||
const gfx::CompositionOp& aMixBlendMode,
|
||||
bool aBackfaceVisible)
|
||||
: mBuilder(&aBuilder)
|
||||
, mScale(1.0f, 1.0f)
|
||||
{
|
||||
bool is2d = !aTransformPtr || (aTransformPtr->Is2D() && !aPerspectivePtr);
|
||||
if (aTransformPtr) {
|
||||
mTransform = *aTransformPtr;
|
||||
}
|
||||
|
||||
// Compute scale for fallback rendering.
|
||||
gfx::Matrix transform2d;
|
||||
if (aBoundTransform && aBoundTransform->CanDraw2D(&transform2d)) {
|
||||
mScale = transform2d.ScaleFactors(true) * aParentSC.mScale;
|
||||
}
|
||||
|
||||
mBuilder->PushStackingContext(wr::LayoutRect(),
|
||||
aAnimationsId,
|
||||
aOpacityPtr,
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
nsDisplayList* aDisplayList,
|
||||
gfx::Matrix4x4Typed<LayerPixel, LayerPixel>* aBoundTransform,
|
||||
const gfx::Matrix4x4* aBoundTransform,
|
||||
uint64_t aAnimationsId,
|
||||
float* aOpacityPtr,
|
||||
gfx::Matrix4x4* aTransformPtr,
|
||||
@ -86,12 +86,16 @@ public:
|
||||
// Same but for points
|
||||
wr::LayoutPoint ToRelativeLayoutPoint(const LayerPoint& aPoint) const;
|
||||
|
||||
// Export the inherited scale
|
||||
gfx::Size GetInheritedScale() const { return mScale; }
|
||||
|
||||
bool IsBackfaceVisible() const { return mTransform.IsBackfaceVisible(); }
|
||||
|
||||
private:
|
||||
wr::DisplayListBuilder* mBuilder;
|
||||
LayerPoint mOrigin;
|
||||
gfx::Matrix4x4 mTransform;
|
||||
gfx::Size mScale;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
@ -472,7 +472,8 @@ PaintItemByDrawTarget(nsDisplayItem* aItem,
|
||||
const LayerPoint& aOffset,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
RefPtr<BasicLayerManager>& aManager,
|
||||
WebRenderLayerManager* aWrManager)
|
||||
WebRenderLayerManager* aWrManager,
|
||||
const gfx::Size& aScale)
|
||||
{
|
||||
MOZ_ASSERT(aDT);
|
||||
|
||||
@ -480,7 +481,8 @@ PaintItemByDrawTarget(nsDisplayItem* aItem,
|
||||
RefPtr<gfxContext> context = gfxContext::CreateOrNull(aDT);
|
||||
MOZ_ASSERT(context);
|
||||
|
||||
context->SetMatrix(gfxMatrix::Translation(-aOffset.x, -aOffset.y));
|
||||
context->SetMatrix(context->CurrentMatrix().PreScale(aScale.width, aScale.height).PreTranslate(-aOffset.x, -aOffset.y));
|
||||
|
||||
switch (aItem->GetType()) {
|
||||
case DisplayItemType::TYPE_MASK:
|
||||
static_cast<nsDisplayMask*>(aItem)->PaintMask(aDisplayListBuilder, context);
|
||||
@ -548,9 +550,9 @@ already_AddRefed<WebRenderFallbackData>
|
||||
WebRenderLayerManager::GenerateFallbackData(nsDisplayItem* aItem,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
const StackingContextHelper& aSc,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
LayerRect& aImageRect,
|
||||
LayerPoint& aOffset)
|
||||
LayerRect& aImageRect)
|
||||
{
|
||||
RefPtr<WebRenderFallbackData> fallbackData = CreateOrRecycleWebRenderUserData<WebRenderFallbackData>(aItem);
|
||||
|
||||
@ -577,18 +579,18 @@ WebRenderLayerManager::GenerateFallbackData(nsDisplayItem* aItem,
|
||||
LayoutDeviceRect::FromAppUnits(clippedBounds, appUnitsPerDevPixel),
|
||||
PixelCastJustification::WebRenderHasUnitResolution);
|
||||
|
||||
LayerIntSize imageSize = RoundedToInt(bounds.Size());
|
||||
aImageRect = LayerRect(LayerPoint(0, 0), LayerSize(imageSize));
|
||||
if (imageSize.width == 0 || imageSize.height == 0) {
|
||||
gfx::Size scale = aSc.GetInheritedScale();
|
||||
LayerIntSize paintSize = RoundedToInt(LayerSize(bounds.width * scale.width, bounds.height * scale.height));
|
||||
if (paintSize.width == 0 || paintSize.height == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
aOffset = RoundedToInt(bounds.TopLeft());
|
||||
|
||||
bool needPaint = true;
|
||||
LayerIntPoint offset = RoundedToInt(bounds.TopLeft());
|
||||
aImageRect = LayerRect(offset, LayerSize(RoundedToInt(bounds.Size())));
|
||||
LayerRect paintRect = LayerRect(LayerPoint(0, 0), LayerSize(paintSize));
|
||||
nsAutoPtr<nsDisplayItemGeometry> geometry = fallbackData->GetGeometry();
|
||||
|
||||
|
||||
// nsDisplayFilter is rendered via BasicLayerManager which means the invalidate
|
||||
// region is unknown until we traverse the displaylist contained by it.
|
||||
if (geometry && !fallbackData->IsInvalid() &&
|
||||
@ -624,14 +626,14 @@ WebRenderLayerManager::GenerateFallbackData(nsDisplayItem* aItem,
|
||||
RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>();
|
||||
RefPtr<gfx::DrawTarget> dummyDt =
|
||||
gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), format);
|
||||
RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, imageSize.ToUnknownSize());
|
||||
PaintItemByDrawTarget(aItem, dt, aImageRect, aOffset, aDisplayListBuilder,
|
||||
fallbackData->mBasicLayerManager, this);
|
||||
RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, paintSize.ToUnknownSize());
|
||||
PaintItemByDrawTarget(aItem, dt, paintRect, offset, aDisplayListBuilder,
|
||||
fallbackData->mBasicLayerManager, this, scale);
|
||||
recorder->Finish();
|
||||
|
||||
Range<uint8_t> bytes((uint8_t*)recorder->mOutputStream.mData, recorder->mOutputStream.mLength);
|
||||
wr::ImageKey key = WrBridge()->GetNextImageKey();
|
||||
wr::ImageDescriptor descriptor(imageSize.ToUnknownSize(), 0, dt->GetFormat(), isOpaque);
|
||||
wr::ImageDescriptor descriptor(paintSize.ToUnknownSize(), 0, dt->GetFormat(), isOpaque);
|
||||
aResources.AddBlobImage(key, descriptor, bytes);
|
||||
fallbackData->SetKey(key);
|
||||
} else {
|
||||
@ -640,15 +642,15 @@ WebRenderLayerManager::GenerateFallbackData(nsDisplayItem* aItem,
|
||||
RefPtr<ImageContainer> imageContainer = LayerManager::CreateImageContainer();
|
||||
|
||||
{
|
||||
UpdateImageHelper helper(imageContainer, imageClient, imageSize.ToUnknownSize(), format);
|
||||
UpdateImageHelper helper(imageContainer, imageClient, paintSize.ToUnknownSize(), format);
|
||||
{
|
||||
RefPtr<gfx::DrawTarget> dt = helper.GetDrawTarget();
|
||||
if (!dt) {
|
||||
return nullptr;
|
||||
}
|
||||
PaintItemByDrawTarget(aItem, dt, aImageRect, aOffset,
|
||||
PaintItemByDrawTarget(aItem, dt, paintRect, offset,
|
||||
aDisplayListBuilder,
|
||||
fallbackData->mBasicLayerManager, this);
|
||||
fallbackData->mBasicLayerManager, this, scale);
|
||||
}
|
||||
if (!helper.UpdateImage()) {
|
||||
return nullptr;
|
||||
@ -685,10 +687,9 @@ WebRenderLayerManager::BuildWrMaskImage(nsDisplayItem* aItem,
|
||||
const LayerRect& aBounds)
|
||||
{
|
||||
LayerRect imageRect;
|
||||
LayerPoint offset;
|
||||
RefPtr<WebRenderFallbackData> fallbackData = GenerateFallbackData(aItem, aBuilder, aResources,
|
||||
aDisplayListBuilder,
|
||||
imageRect, offset);
|
||||
aSc, aDisplayListBuilder,
|
||||
imageRect);
|
||||
if (!fallbackData) {
|
||||
return Nothing();
|
||||
}
|
||||
@ -708,15 +709,14 @@ WebRenderLayerManager::PushItemAsImage(nsDisplayItem* aItem,
|
||||
nsDisplayListBuilder* aDisplayListBuilder)
|
||||
{
|
||||
LayerRect imageRect;
|
||||
LayerPoint offset;
|
||||
RefPtr<WebRenderFallbackData> fallbackData = GenerateFallbackData(aItem, aBuilder, aResources,
|
||||
aDisplayListBuilder,
|
||||
imageRect, offset);
|
||||
aSc, aDisplayListBuilder,
|
||||
imageRect);
|
||||
if (!fallbackData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wr::LayoutRect dest = aSc.ToRelativeLayoutRect(imageRect + offset);
|
||||
wr::LayoutRect dest = aSc.ToRelativeLayoutRect(imageRect);
|
||||
SamplingFilter sampleFilter = nsLayoutUtils::GetSamplingFilterForFrame(aItem->Frame());
|
||||
aBuilder.PushImage(dest,
|
||||
dest,
|
||||
|
@ -80,9 +80,9 @@ public:
|
||||
GenerateFallbackData(nsDisplayItem* aItem,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
wr::IpcResourceUpdateQueue& aResourceUpdates,
|
||||
const StackingContextHelper& aSc,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
LayerRect& aImageRect,
|
||||
LayerPoint& aOffset);
|
||||
LayerRect& aImageRect);
|
||||
|
||||
Maybe<wr::WrImageMask> BuildWrMaskImage(nsDisplayItem* aItem,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
@ -212,13 +212,14 @@ public:
|
||||
*aOutIsRecycled = true;
|
||||
}
|
||||
|
||||
if (!frame->HasProperty(nsIFrame::WebRenderUserDataProperty())) {
|
||||
frame->AddProperty(nsIFrame::WebRenderUserDataProperty(),
|
||||
new nsIFrame::WebRenderUserDataTable());
|
||||
}
|
||||
|
||||
nsIFrame::WebRenderUserDataTable* userDataTable =
|
||||
frame->GetProperty(nsIFrame::WebRenderUserDataProperty());
|
||||
|
||||
if (!userDataTable) {
|
||||
userDataTable = new nsIFrame::WebRenderUserDataTable();
|
||||
frame->AddProperty(nsIFrame::WebRenderUserDataProperty(), userDataTable);
|
||||
}
|
||||
|
||||
RefPtr<WebRenderUserData>& data = userDataTable->GetOrInsert(aItem->GetPerFrameKey());
|
||||
if (!data || (data->GetType() != T::Type()) || !data->IsDataValid(this)) {
|
||||
// To recreate a new user data, we should remove the data from the table first.
|
||||
|
@ -6,4 +6,4 @@ skip-if(!asyncPan) == 1086723.html 1086723-ref.html
|
||||
== 853889-1.html 853889-1-ref.html
|
||||
skip-if(Android) fuzzy-if(skiaContent,1,587) fails-if(webrender) == 1143303-1.svg pass.svg
|
||||
fuzzy(100,30) == 1149923.html 1149923-ref.html # use fuzzy due to few distorted pixels caused by border-radius
|
||||
fails-if(webrender) == 1131264-1.svg pass.svg
|
||||
== 1131264-1.svg pass.svg
|
||||
|
@ -101,6 +101,27 @@ AssemblerMIPSShared::appendRawCode(const uint8_t* code, size_t numBytes)
|
||||
return m_buffer.appendRawCode(code, numBytes);
|
||||
}
|
||||
|
||||
bool
|
||||
AssemblerMIPSShared::reserve(size_t size)
|
||||
{
|
||||
// This buffer uses fixed-size chunks so there's no point in reserving
|
||||
// now vs. on-demand.
|
||||
return !oom();
|
||||
}
|
||||
|
||||
bool
|
||||
AssemblerMIPSShared::swapBuffer(wasm::Bytes& bytes)
|
||||
{
|
||||
// For now, specialize to the one use case. As long as wasm::Bytes is a
|
||||
// Vector, not a linked-list of chunks, there's not much we can do other
|
||||
// than copy.
|
||||
MOZ_ASSERT(bytes.empty());
|
||||
if (!bytes.resize(bytesNeeded()))
|
||||
return false;
|
||||
m_buffer.executableCopy(bytes.begin());
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
AssemblerMIPSShared::actualIndex(uint32_t idx_) const
|
||||
{
|
||||
@ -127,15 +148,6 @@ AssemblerMIPSShared::copyDataRelocationTable(uint8_t* dest)
|
||||
memcpy(dest, dataRelocations_.buffer(), dataRelocations_.length());
|
||||
}
|
||||
|
||||
void
|
||||
AssemblerMIPSShared::processCodeLabels(uint8_t* rawCode)
|
||||
{
|
||||
for (size_t i = 0; i < codeLabels_.length(); i++) {
|
||||
CodeLabel label = codeLabels_[i];
|
||||
Bind(rawCode, *label.patchAt(), *label.target());
|
||||
}
|
||||
}
|
||||
|
||||
AssemblerMIPSShared::Condition
|
||||
AssemblerMIPSShared::InvertCondition(Condition cond)
|
||||
{
|
||||
|
@ -954,6 +954,8 @@ class AssemblerMIPSShared : public AssemblerShared
|
||||
public:
|
||||
void finish();
|
||||
bool appendRawCode(const uint8_t* code, size_t numBytes);
|
||||
bool reserve(size_t size);
|
||||
bool swapBuffer(wasm::Bytes& bytes);
|
||||
void executableCopy(void* buffer, bool flushICache = true);
|
||||
void copyJumpRelocationTable(uint8_t* dest);
|
||||
void copyDataRelocationTable(uint8_t* dest);
|
||||
@ -1228,7 +1230,6 @@ class AssemblerMIPSShared : public AssemblerShared
|
||||
void bind(Label* label, BufferOffset boff = BufferOffset());
|
||||
void bindLater(Label* label, wasm::TrapDesc target);
|
||||
virtual void bind(InstImm* inst, uintptr_t branch, uintptr_t target) = 0;
|
||||
virtual void Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target) = 0;
|
||||
void bind(CodeOffset* label) {
|
||||
label->bind(currentOffset());
|
||||
}
|
||||
@ -1308,8 +1309,6 @@ class AssemblerMIPSShared : public AssemblerShared
|
||||
|
||||
static void UpdateLuiOriValue(Instruction* inst0, Instruction* inst1, uint32_t value);
|
||||
|
||||
void processCodeLabels(uint8_t* rawCode);
|
||||
|
||||
bool bailed() {
|
||||
return m_buffer.bail();
|
||||
}
|
||||
|
@ -429,6 +429,15 @@ Assembler::bind(RepatchLabel* label)
|
||||
label->bind(dest.getOffset());
|
||||
}
|
||||
|
||||
void
|
||||
Assembler::processCodeLabels(uint8_t* rawCode)
|
||||
{
|
||||
for (size_t i = 0; i < codeLabels_.length(); i++) {
|
||||
CodeLabel label = codeLabels_[i];
|
||||
Bind(rawCode, *label.patchAt(), *label.target());
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Assembler::PatchWrite_NearCallSize()
|
||||
{
|
||||
|
@ -157,6 +157,8 @@ class Assembler : public AssemblerMIPSShared
|
||||
void bind(RepatchLabel* label);
|
||||
static void Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target);
|
||||
|
||||
void processCodeLabels(uint8_t* rawCode);
|
||||
|
||||
static void TraceJumpRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader);
|
||||
static void TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader);
|
||||
|
||||
|
@ -367,6 +367,15 @@ Assembler::bind(RepatchLabel* label)
|
||||
label->bind(dest.getOffset());
|
||||
}
|
||||
|
||||
void
|
||||
Assembler::processCodeLabels(uint8_t* rawCode)
|
||||
{
|
||||
for (size_t i = 0; i < codeLabels_.length(); i++) {
|
||||
CodeLabel label = codeLabels_[i];
|
||||
Bind(rawCode, *label.patchAt(), *label.target());
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Assembler::PatchWrite_NearCallSize()
|
||||
{
|
||||
|
@ -149,6 +149,8 @@ class Assembler : public AssemblerMIPSShared
|
||||
void bind(RepatchLabel* label);
|
||||
static void Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target);
|
||||
|
||||
void processCodeLabels(uint8_t* rawCode);
|
||||
|
||||
static void TraceJumpRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader);
|
||||
static void TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader);
|
||||
|
||||
|
@ -976,7 +976,6 @@ const char* gc::ZealModeHelpText =
|
||||
" 3: (FrameGC) Collect when the window paints (browser only)\n"
|
||||
" 4: (VerifierPre) Verify pre write barriers between instructions\n"
|
||||
" 5: (FrameVerifierPre) Verify pre write barriers between paints\n"
|
||||
" 6: (StackRooting) Verify stack rooting\n"
|
||||
" 7: (GenerationalGC) Collect the nursery every N nursery allocations\n"
|
||||
" 8: (IncrementalRootsThenFinish) Incremental GC in two slices: 1) mark roots 2) finish collection\n"
|
||||
" 9: (IncrementalMarkAllThenFinish) Incremental GC in two slices: 1) mark all 2) new marking and finish\n"
|
||||
|
@ -1169,7 +1169,6 @@ inline void CheckValueAfterMovingGC(const JS::Value& value);
|
||||
D(FrameGC, 3) \
|
||||
D(VerifierPre, 4) \
|
||||
D(FrameVerifierPre, 5) \
|
||||
D(StackRooting, 6) \
|
||||
D(GenerationalGC, 7) \
|
||||
D(IncrementalRootsThenFinish, 8) \
|
||||
D(IncrementalMarkAllThenFinish, 9) \
|
||||
|
@ -20,73 +20,81 @@ ReportDead(JSContext *cx)
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc) const
|
||||
DeadObjectProxy<CC, BF>::getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
Handle<PropertyDescriptor> desc,
|
||||
ObjectOpResult& result) const
|
||||
DeadObjectProxy<CC, BF>::defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
Handle<PropertyDescriptor> desc,
|
||||
ObjectOpResult& result) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::ownPropertyKeys(JSContext* cx, HandleObject wrapper,
|
||||
AutoIdVector& props) const
|
||||
DeadObjectProxy<CC, BF>::ownPropertyKeys(JSContext* cx, HandleObject wrapper,
|
||||
AutoIdVector& props) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::delete_(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
ObjectOpResult& result) const
|
||||
DeadObjectProxy<CC, BF>::delete_(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
ObjectOpResult& result) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::getPrototype(JSContext* cx, HandleObject proxy,
|
||||
MutableHandleObject protop) const
|
||||
DeadObjectProxy<CC, BF>::getPrototype(JSContext* cx, HandleObject proxy,
|
||||
MutableHandleObject protop) const
|
||||
{
|
||||
protop.set(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
|
||||
MutableHandleObject protop) const
|
||||
DeadObjectProxy<CC, BF>::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
|
||||
MutableHandleObject protop) const
|
||||
{
|
||||
*isOrdinary = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::preventExtensions(JSContext* cx, HandleObject proxy,
|
||||
ObjectOpResult& result) const
|
||||
DeadObjectProxy<CC, BF>::preventExtensions(JSContext* cx, HandleObject proxy,
|
||||
ObjectOpResult& result) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const
|
||||
DeadObjectProxy<CC, BF>::isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const
|
||||
{
|
||||
// This is kind of meaningless, but dead-object semantics aside,
|
||||
// [[Extensible]] always being true is consistent with other proxy types.
|
||||
@ -94,95 +102,141 @@ DeadObjectProxy<CC>::isExtensible(JSContext* cx, HandleObject proxy, bool* exten
|
||||
return true;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::call(JSContext* cx, HandleObject wrapper, const CallArgs& args) const
|
||||
DeadObjectProxy<CC, BF>::call(JSContext* cx, HandleObject wrapper, const CallArgs& args) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::construct(JSContext* cx, HandleObject wrapper, const CallArgs& args) const
|
||||
DeadObjectProxy<CC, BF>::construct(JSContext* cx, HandleObject wrapper, const CallArgs& args) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
|
||||
const CallArgs& args) const
|
||||
DeadObjectProxy<CC, BF>::nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
|
||||
const CallArgs& args) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v,
|
||||
bool* bp) const
|
||||
DeadObjectProxy<CC, BF>::hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v,
|
||||
bool* bp) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::getBuiltinClass(JSContext* cx, HandleObject proxy, ESClass* cls) const
|
||||
DeadObjectProxy<CC, BF>::getBuiltinClass(JSContext* cx, HandleObject proxy, ESClass* cls) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
bool
|
||||
DeadObjectProxy<CC>::isArray(JSContext* cx, HandleObject obj, JS::IsArrayAnswer* answer) const
|
||||
DeadObjectProxy<CC, BF>::isArray(JSContext* cx, HandleObject obj, JS::IsArrayAnswer* answer) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
const char*
|
||||
DeadObjectProxy<CC>::className(JSContext* cx, HandleObject wrapper) const
|
||||
DeadObjectProxy<CC, BF>::className(JSContext* cx, HandleObject wrapper) const
|
||||
{
|
||||
return "DeadObject";
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
JSString*
|
||||
DeadObjectProxy<CC>::fun_toString(JSContext* cx, HandleObject proxy, bool isToSource) const
|
||||
DeadObjectProxy<CC, BF>::fun_toString(JSContext* cx, HandleObject proxy, bool isToSource) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BF>
|
||||
RegExpShared*
|
||||
DeadObjectProxy<CC>::regexp_toShared(JSContext* cx, HandleObject proxy) const
|
||||
DeadObjectProxy<CC, BF>::regexp_toShared(JSContext* cx, HandleObject proxy) const
|
||||
{
|
||||
ReportDead(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <>
|
||||
const char DeadObjectProxy<DeadProxyNotCallableNotConstructor>::family = 0;
|
||||
const char DeadObjectProxy<DeadProxyNotCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::family = 0;
|
||||
template <>
|
||||
const char DeadObjectProxy<DeadProxyNotCallableIsConstructor>::family = 0;
|
||||
const char DeadObjectProxy<DeadProxyNotCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::family = 0;
|
||||
template <>
|
||||
const char DeadObjectProxy<DeadProxyIsCallableNotConstructor>::family = 0;
|
||||
const char DeadObjectProxy<DeadProxyNotCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::family = 0;
|
||||
template <>
|
||||
const char DeadObjectProxy<DeadProxyIsCallableIsConstructor>::family = 0;
|
||||
const char DeadObjectProxy<DeadProxyNotCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::family = 0;
|
||||
template <>
|
||||
const char DeadObjectProxy<DeadProxyIsCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::family = 0;
|
||||
template <>
|
||||
const char DeadObjectProxy<DeadProxyIsCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::family = 0;
|
||||
template <>
|
||||
const char DeadObjectProxy<DeadProxyIsCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::family = 0;
|
||||
template <>
|
||||
const char DeadObjectProxy<DeadProxyIsCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::family = 0;
|
||||
|
||||
bool
|
||||
js::IsDeadProxyObject(JSObject* obj)
|
||||
{
|
||||
return IsDerivedProxyObject(obj, DeadObjectProxy<DeadProxyNotCallableNotConstructor>::singleton()) ||
|
||||
IsDerivedProxyObject(obj, DeadObjectProxy<DeadProxyIsCallableIsConstructor>::singleton()) ||
|
||||
IsDerivedProxyObject(obj, DeadObjectProxy<DeadProxyIsCallableNotConstructor>::singleton()) ||
|
||||
IsDerivedProxyObject(obj, DeadObjectProxy<DeadProxyNotCallableIsConstructor>::singleton());
|
||||
return
|
||||
IsDerivedProxyObject(obj,
|
||||
DeadObjectProxy<DeadProxyNotCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::singleton()) ||
|
||||
IsDerivedProxyObject(obj,
|
||||
DeadObjectProxy<DeadProxyNotCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::singleton()) ||
|
||||
IsDerivedProxyObject(obj,
|
||||
DeadObjectProxy<DeadProxyIsCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::singleton()) ||
|
||||
IsDerivedProxyObject(obj,
|
||||
DeadObjectProxy<DeadProxyIsCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::singleton()) ||
|
||||
IsDerivedProxyObject(obj,
|
||||
DeadObjectProxy<DeadProxyIsCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::singleton()) ||
|
||||
IsDerivedProxyObject(obj,
|
||||
DeadObjectProxy<DeadProxyIsCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::singleton()) ||
|
||||
IsDerivedProxyObject(obj,
|
||||
DeadObjectProxy<DeadProxyNotCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::singleton()) ||
|
||||
IsDerivedProxyObject(obj,
|
||||
DeadObjectProxy<DeadProxyNotCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::singleton());
|
||||
}
|
||||
|
||||
|
||||
@ -190,19 +244,48 @@ const BaseProxyHandler*
|
||||
js::SelectDeadProxyHandler(ProxyObject* obj)
|
||||
{
|
||||
// When nuking scripted proxies, isCallable and isConstructor values for
|
||||
// the proxy needs to be preserved.
|
||||
// the proxy needs to be preserved. So does background-finalization status.
|
||||
uint32_t callable = obj->handler()->isCallable(obj);
|
||||
uint32_t constructor = obj->handler()->isConstructor(obj);
|
||||
bool finalizeInBackground = obj->handler()->finalizeInBackground(obj->private_());
|
||||
|
||||
if (callable) {
|
||||
if (constructor)
|
||||
return DeadObjectProxy<DeadProxyIsCallableIsConstructor>::singleton();
|
||||
return DeadObjectProxy<DeadProxyIsCallableNotConstructor>::singleton();
|
||||
if (constructor) {
|
||||
if (finalizeInBackground) {
|
||||
return DeadObjectProxy<DeadProxyIsCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::singleton();
|
||||
} else {
|
||||
return DeadObjectProxy<DeadProxyIsCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::singleton();
|
||||
}
|
||||
}
|
||||
|
||||
if (finalizeInBackground) {
|
||||
return DeadObjectProxy<DeadProxyIsCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::singleton();
|
||||
}
|
||||
|
||||
return DeadObjectProxy<DeadProxyIsCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::singleton();
|
||||
}
|
||||
|
||||
if (constructor)
|
||||
return DeadObjectProxy<DeadProxyNotCallableIsConstructor>::singleton();
|
||||
return DeadObjectProxy<DeadProxyNotCallableNotConstructor>::singleton();
|
||||
if (constructor) {
|
||||
if (finalizeInBackground) {
|
||||
return DeadObjectProxy<DeadProxyNotCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::singleton();
|
||||
}
|
||||
|
||||
return DeadObjectProxy<DeadProxyNotCallableIsConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::singleton();
|
||||
}
|
||||
|
||||
if (finalizeInBackground) {
|
||||
return DeadObjectProxy<DeadProxyNotCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::singleton();
|
||||
}
|
||||
|
||||
return DeadObjectProxy<DeadProxyNotCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::No>::singleton();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
@ -214,7 +297,8 @@ js::NewDeadProxyObject(JSContext* cx, JSObject* origObj)
|
||||
if (origObj && origObj->is<ProxyObject>())
|
||||
handler = SelectDeadProxyHandler(&origObj->as<ProxyObject>());
|
||||
else
|
||||
handler = DeadObjectProxy<DeadProxyNotCallableNotConstructor>::singleton();
|
||||
handler = DeadObjectProxy<DeadProxyNotCallableNotConstructor,
|
||||
DeadProxyBackgroundFinalized::Yes>::singleton();
|
||||
|
||||
return NewProxyObject(cx, handler, NullHandleValue, nullptr, ProxyOptions());
|
||||
}
|
||||
|
@ -21,7 +21,14 @@ enum DeadProxyIsCallableIsConstructorOption
|
||||
DeadProxyIsCallableIsConstructor
|
||||
};
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC>
|
||||
enum class DeadProxyBackgroundFinalized
|
||||
{
|
||||
Yes,
|
||||
No
|
||||
};
|
||||
|
||||
template <DeadProxyIsCallableIsConstructorOption CC,
|
||||
DeadProxyBackgroundFinalized BackgroundFinalized>
|
||||
class DeadObjectProxy : public BaseProxyHandler
|
||||
{
|
||||
public:
|
||||
@ -70,6 +77,10 @@ class DeadObjectProxy : public BaseProxyHandler
|
||||
return CC == DeadProxyIsCallableIsConstructor || CC == DeadProxyNotCallableIsConstructor;
|
||||
}
|
||||
|
||||
virtual bool finalizeInBackground(const JS::Value& priv) const override {
|
||||
return BackgroundFinalized == DeadProxyBackgroundFinalized::Yes;
|
||||
}
|
||||
|
||||
static const DeadObjectProxy* singleton() {
|
||||
static DeadObjectProxy singleton;
|
||||
return &singleton;
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "nsIContentIterator.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Event.h" // for Event::GetEventPopupControlState()
|
||||
#include "mozilla/dom/PointerEvent.h"
|
||||
#include "mozilla/dom/PointerEventHandler.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsAnimationManager.h"
|
||||
#include "nsNameSpaceManager.h" // for Pref-related rule management (bugs 22963,20760,31816)
|
||||
@ -215,17 +215,6 @@ CapturingContentInfo nsIPresShell::gCaptureInfo =
|
||||
false /* mPreventDrag */ };
|
||||
nsIContent* nsIPresShell::gKeyDownTarget;
|
||||
|
||||
// Keeps a map between pointerId and element that currently capturing pointer
|
||||
// with such pointerId. If pointerId is absent in this map then nobody is
|
||||
// capturing it. Additionally keep information about pending capturing content.
|
||||
static nsClassHashtable<nsUint32HashKey,
|
||||
nsIPresShell::PointerCaptureInfo>* sPointerCaptureList;
|
||||
|
||||
// Keeps information about pointers such as pointerId, activeState, pointerType,
|
||||
// primaryState
|
||||
static nsClassHashtable<nsUint32HashKey,
|
||||
nsIPresShell::PointerInfo>* sActivePointersIds;
|
||||
|
||||
// RangePaintInfo is used to paint ranges to offscreen buffers
|
||||
struct RangePaintInfo {
|
||||
RefPtr<nsRange> mRange;
|
||||
@ -712,8 +701,6 @@ nsIPresShell::FrameSelection()
|
||||
|
||||
static bool sSynthMouseMove = true;
|
||||
static uint32_t sNextPresShellId;
|
||||
static bool sPointerEventEnabled = true;
|
||||
static bool sPointerEventImplicitCapture = false;
|
||||
static bool sAccessibleCaretEnabled = false;
|
||||
static bool sAccessibleCaretOnTouch = false;
|
||||
|
||||
@ -842,19 +829,7 @@ PresShell::PresShell()
|
||||
"layout.reflow.synthMouseMove", true);
|
||||
addedSynthMouseMove = true;
|
||||
}
|
||||
static bool addedPointerEventEnabled = false;
|
||||
if (!addedPointerEventEnabled) {
|
||||
Preferences::AddBoolVarCache(&sPointerEventEnabled,
|
||||
"dom.w3c_pointer_events.enabled", true);
|
||||
addedPointerEventEnabled = true;
|
||||
}
|
||||
static bool addedPointerEventImplicitCapture = false;
|
||||
if (!addedPointerEventImplicitCapture) {
|
||||
Preferences::AddBoolVarCache(&sPointerEventImplicitCapture,
|
||||
"dom.w3c_pointer_events.implicit_capture",
|
||||
true);
|
||||
addedPointerEventImplicitCapture = true;
|
||||
}
|
||||
PointerEventHandler::Initialize();
|
||||
mPaintingIsFrozen = false;
|
||||
mHasCSSBackgroundColor = true;
|
||||
mIsLastChromeOnlyEscapeKeyConsumed = false;
|
||||
@ -4463,7 +4438,8 @@ PresShell::ContentRemoved(nsIDocument *aDocument,
|
||||
// precondition check that mDocument == aDocument ensures that
|
||||
// aDocument will not be null (since mDocument can't be null unless
|
||||
// we're still intializing).
|
||||
mPresContext->EventStateManager()->ContentRemoved(aDocument, aChild);
|
||||
mPresContext->EventStateManager()
|
||||
->ContentRemoved(aDocument, aMaybeContainer, aChild);
|
||||
|
||||
nsAutoCauseReflowNotifier crNotifier(this);
|
||||
|
||||
@ -4476,21 +4452,12 @@ PresShell::ContentRemoved(nsIDocument *aDocument,
|
||||
|
||||
// After removing aChild from tree we should save information about live ancestor
|
||||
if (mPointerEventTarget) {
|
||||
MOZ_ASSERT(PointerEventHandler::IsPointerEventEnabled());
|
||||
if (nsContentUtils::ContentIsDescendantOf(mPointerEventTarget, aChild)) {
|
||||
mPointerEventTarget = aMaybeContainer;
|
||||
}
|
||||
}
|
||||
|
||||
// We should check that aChild does not contain pointer capturing elements.
|
||||
// If it does we should release the pointer capture for the elements.
|
||||
for (auto iter = sPointerCaptureList->Iter(); !iter.Done(); iter.Next()) {
|
||||
nsIPresShell::PointerCaptureInfo* data = iter.UserData();
|
||||
if (data && data->mPendingContent &&
|
||||
nsContentUtils::ContentIsDescendantOf(data->mPendingContent, aChild)) {
|
||||
nsIPresShell::ReleasePointerCapturingContent(iter.Key());
|
||||
}
|
||||
}
|
||||
|
||||
mFrameConstructor->ContentRemoved(aMaybeContainer, aChild, oldNextSibling,
|
||||
nsCSSFrameConstructor::REMOVE_CONTENT);
|
||||
|
||||
@ -6499,158 +6466,6 @@ nsIPresShell::SetCapturingContent(nsIContent* aContent, uint8_t aFlags)
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsIPresShell::SetPointerCapturingContent(uint32_t aPointerId,
|
||||
nsIContent* aContent)
|
||||
{
|
||||
MOZ_ASSERT(aContent != nullptr);
|
||||
|
||||
if (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == GetPointerType(aPointerId)) {
|
||||
SetCapturingContent(aContent, CAPTURE_PREVENTDRAG);
|
||||
}
|
||||
|
||||
PointerCaptureInfo* pointerCaptureInfo = GetPointerCaptureInfo(aPointerId);
|
||||
if (pointerCaptureInfo) {
|
||||
pointerCaptureInfo->mPendingContent = aContent;
|
||||
} else {
|
||||
sPointerCaptureList->Put(aPointerId, new PointerCaptureInfo(aContent));
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ nsIPresShell::PointerCaptureInfo*
|
||||
nsIPresShell::GetPointerCaptureInfo(uint32_t aPointerId)
|
||||
{
|
||||
PointerCaptureInfo* pointerCaptureInfo = nullptr;
|
||||
sPointerCaptureList->Get(aPointerId, &pointerCaptureInfo);
|
||||
return pointerCaptureInfo;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsIPresShell::ReleasePointerCapturingContent(uint32_t aPointerId)
|
||||
{
|
||||
PointerCaptureInfo* pointerCaptureInfo = GetPointerCaptureInfo(aPointerId);
|
||||
if (pointerCaptureInfo && pointerCaptureInfo->mPendingContent) {
|
||||
if (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == GetPointerType(aPointerId)) {
|
||||
SetCapturingContent(nullptr, CAPTURE_PREVENTDRAG);
|
||||
}
|
||||
pointerCaptureInfo->mPendingContent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ nsIContent*
|
||||
nsIPresShell::GetPointerCapturingContent(uint32_t aPointerId)
|
||||
{
|
||||
PointerCaptureInfo* pointerCaptureInfo = GetPointerCaptureInfo(aPointerId);
|
||||
if (pointerCaptureInfo) {
|
||||
return pointerCaptureInfo->mOverrideContent;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsIPresShell::CheckPointerCaptureState(const WidgetPointerEvent* aPointerEvent)
|
||||
{
|
||||
PointerCaptureInfo* captureInfo =
|
||||
GetPointerCaptureInfo(aPointerEvent->pointerId);
|
||||
|
||||
if (captureInfo &&
|
||||
captureInfo->mPendingContent != captureInfo->mOverrideContent) {
|
||||
// cache captureInfo->mPendingContent since it may be changed in the pointer
|
||||
// event listener
|
||||
nsIContent* pendingContent = captureInfo->mPendingContent.get();
|
||||
if (captureInfo->mOverrideContent) {
|
||||
DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ false,
|
||||
aPointerEvent,
|
||||
captureInfo->mOverrideContent);
|
||||
}
|
||||
if (pendingContent) {
|
||||
DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ true,
|
||||
aPointerEvent, pendingContent);
|
||||
}
|
||||
|
||||
captureInfo->mOverrideContent = pendingContent;
|
||||
if (captureInfo->Empty()) {
|
||||
sPointerCaptureList->Remove(aPointerEvent->pointerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ uint16_t
|
||||
nsIPresShell::GetPointerType(uint32_t aPointerId)
|
||||
{
|
||||
PointerInfo* pointerInfo = nullptr;
|
||||
if (sActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
|
||||
return pointerInfo->mPointerType;
|
||||
}
|
||||
return nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsIPresShell::GetPointerPrimaryState(uint32_t aPointerId)
|
||||
{
|
||||
PointerInfo* pointerInfo = nullptr;
|
||||
if (sActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
|
||||
return pointerInfo->mPrimaryState;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsIPresShell::GetPointerInfo(uint32_t aPointerId, bool& aActiveState)
|
||||
{
|
||||
PointerInfo* pointerInfo = nullptr;
|
||||
if (sActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
|
||||
aActiveState = pointerInfo->mActiveState;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::UpdateActivePointerState(WidgetGUIEvent* aEvent)
|
||||
{
|
||||
switch (aEvent->mMessage) {
|
||||
case eMouseEnterIntoWidget:
|
||||
// In this case we have to know information about available mouse pointers
|
||||
if (WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) {
|
||||
sActivePointersIds->Put(mouseEvent->pointerId,
|
||||
new PointerInfo(false, mouseEvent->inputSource,
|
||||
true));
|
||||
}
|
||||
break;
|
||||
case ePointerDown:
|
||||
// In this case we switch pointer to active state
|
||||
if (WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent()) {
|
||||
sActivePointersIds->Put(pointerEvent->pointerId,
|
||||
new PointerInfo(true, pointerEvent->inputSource,
|
||||
pointerEvent->mIsPrimary));
|
||||
}
|
||||
break;
|
||||
case ePointerUp:
|
||||
// In this case we remove information about pointer or turn off active state
|
||||
if (WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent()) {
|
||||
if(pointerEvent->inputSource != nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
|
||||
sActivePointersIds->Put(pointerEvent->pointerId,
|
||||
new PointerInfo(false,
|
||||
pointerEvent->inputSource,
|
||||
pointerEvent->mIsPrimary));
|
||||
} else {
|
||||
sActivePointersIds->Remove(pointerEvent->pointerId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case eMouseExitFromWidget:
|
||||
// In this case we have to remove information about disappeared mouse
|
||||
// pointers
|
||||
if (WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) {
|
||||
sActivePointersIds->Remove(mouseEvent->pointerId);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
PresShell::GetCurrentEventContent()
|
||||
{
|
||||
@ -6924,190 +6739,6 @@ FlushThrottledStyles(nsIDocument *aDocument, void *aData)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the preventDefault behavior of pointerdown. When user
|
||||
* preventDefault on pointerdown, We have to mark the active pointer to prevent
|
||||
* sebsequent mouse events (except mouse transition events) and default
|
||||
* behaviors.
|
||||
*
|
||||
* We add mPreventMouseEventByContent flag in PointerInfo to represent the
|
||||
* active pointer won't firing compatible mouse events. It's set to true when
|
||||
* content preventDefault on pointerdown
|
||||
*/
|
||||
static void
|
||||
PostHandlePointerEventsPreventDefault(WidgetPointerEvent* aPointerEvent,
|
||||
WidgetGUIEvent* aMouseOrTouchEvent)
|
||||
{
|
||||
if (!aPointerEvent->mIsPrimary || aPointerEvent->mMessage != ePointerDown ||
|
||||
!aPointerEvent->DefaultPreventedByContent()) {
|
||||
return;
|
||||
}
|
||||
nsIPresShell::PointerInfo* pointerInfo = nullptr;
|
||||
if (!sActivePointersIds->Get(aPointerEvent->pointerId, &pointerInfo) ||
|
||||
!pointerInfo) {
|
||||
// We already added the PointerInfo for active pointer when
|
||||
// PresShell::HandleEvent handling pointerdown event.
|
||||
#ifdef DEBUG
|
||||
MOZ_CRASH("Got ePointerDown w/o active pointer info!!");
|
||||
#endif // #ifdef DEBUG
|
||||
return;
|
||||
}
|
||||
// PreventDefault only applied for active pointers.
|
||||
if (!pointerInfo->mActiveState) {
|
||||
return;
|
||||
}
|
||||
aMouseOrTouchEvent->PreventDefault(false);
|
||||
pointerInfo->mPreventMouseEventByContent = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the case when content had called preventDefault on the
|
||||
* active pointer. In that case we have to prevent firing subsequent mouse
|
||||
* to content. We check the flag PointerInfo::mPreventMouseEventByContent and
|
||||
* call PreventDefault(false) to stop default behaviors and stop firing mouse
|
||||
* events to content and chrome.
|
||||
*
|
||||
* note: mouse transition events are excluded
|
||||
* note: we have to clean mPreventMouseEventByContent on pointerup for those
|
||||
* devices support hover
|
||||
* note: we don't suppress firing mouse events to chrome and system group
|
||||
* handlers because they may implement default behaviors
|
||||
*/
|
||||
static void
|
||||
PreHandlePointerEventsPreventDefault(WidgetPointerEvent* aPointerEvent,
|
||||
WidgetGUIEvent* aMouseOrTouchEvent)
|
||||
{
|
||||
if (!aPointerEvent->mIsPrimary || aPointerEvent->mMessage == ePointerDown) {
|
||||
return;
|
||||
}
|
||||
nsIPresShell::PointerInfo* pointerInfo = nullptr;
|
||||
if (!sActivePointersIds->Get(aPointerEvent->pointerId, &pointerInfo) ||
|
||||
!pointerInfo) {
|
||||
// The PointerInfo for active pointer should be added for normal cases. But
|
||||
// in some cases, we may receive mouse events before adding PointerInfo in
|
||||
// sActivePointersIds. (e.g. receive mousemove before eMouseEnterIntoWidget
|
||||
// or change preference 'dom.w3c_pointer_events.enabled' from off to on).
|
||||
// In these cases, we could ignore them because they are not the events
|
||||
// between a DefaultPrevented pointerdown and the corresponding pointerup.
|
||||
return;
|
||||
}
|
||||
if (!pointerInfo->mPreventMouseEventByContent) {
|
||||
return;
|
||||
}
|
||||
aMouseOrTouchEvent->PreventDefault(false);
|
||||
if (aPointerEvent->mMessage == ePointerUp) {
|
||||
pointerInfo->mPreventMouseEventByContent = false;
|
||||
}
|
||||
}
|
||||
|
||||
static nsresult
|
||||
DispatchPointerFromMouseOrTouch(PresShell* aShell,
|
||||
nsIFrame* aFrame,
|
||||
WidgetGUIEvent* aEvent,
|
||||
bool aDontRetargetEvents,
|
||||
nsEventStatus* aStatus,
|
||||
nsIContent** aTargetContent)
|
||||
{
|
||||
EventMessage pointerMessage = eVoidEvent;
|
||||
if (aEvent->mClass == eMouseEventClass) {
|
||||
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
|
||||
// 1. If it is not mouse then it is likely will come as touch event
|
||||
// 2. We don't synthesize pointer events for those events that are not
|
||||
// dispatched to DOM.
|
||||
if (!mouseEvent->convertToPointer ||
|
||||
!aEvent->IsAllowedToDispatchDOMEvent()) {
|
||||
return NS_OK;
|
||||
}
|
||||
int16_t button = mouseEvent->button;
|
||||
switch (mouseEvent->mMessage) {
|
||||
case eMouseMove:
|
||||
button = WidgetMouseEvent::eNoButton;
|
||||
pointerMessage = ePointerMove;
|
||||
break;
|
||||
case eMouseUp:
|
||||
pointerMessage = mouseEvent->buttons ? ePointerMove : ePointerUp;
|
||||
break;
|
||||
case eMouseDown:
|
||||
pointerMessage =
|
||||
mouseEvent->buttons & ~nsContentUtils::GetButtonsFlagForButton(button) ?
|
||||
ePointerMove : ePointerDown;
|
||||
break;
|
||||
default:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
WidgetPointerEvent event(*mouseEvent);
|
||||
event.pointerId = mouseEvent->pointerId;
|
||||
event.inputSource = mouseEvent->inputSource;
|
||||
event.mMessage = pointerMessage;
|
||||
event.button = button;
|
||||
event.buttons = mouseEvent->buttons;
|
||||
event.pressure = event.buttons ?
|
||||
mouseEvent->pressure ? mouseEvent->pressure : 0.5f :
|
||||
0.0f;
|
||||
event.convertToPointer = mouseEvent->convertToPointer = false;
|
||||
PreHandlePointerEventsPreventDefault(&event, aEvent);
|
||||
aShell->HandleEvent(aFrame, &event, aDontRetargetEvents, aStatus,
|
||||
aTargetContent);
|
||||
PostHandlePointerEventsPreventDefault(&event, aEvent);
|
||||
} else if (aEvent->mClass == eTouchEventClass) {
|
||||
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
|
||||
int16_t button = WidgetMouseEvent::eLeftButton;
|
||||
int16_t buttons = WidgetMouseEvent::eLeftButtonFlag;
|
||||
// loop over all touches and dispatch pointer events on each touch
|
||||
// copy the event
|
||||
switch (touchEvent->mMessage) {
|
||||
case eTouchMove:
|
||||
pointerMessage = ePointerMove;
|
||||
button = WidgetMouseEvent::eNoButton;
|
||||
break;
|
||||
case eTouchEnd:
|
||||
pointerMessage = ePointerUp;
|
||||
buttons = WidgetMouseEvent::eNoButtonFlag;
|
||||
break;
|
||||
case eTouchStart:
|
||||
pointerMessage = ePointerDown;
|
||||
break;
|
||||
case eTouchCancel:
|
||||
case eTouchPointerCancel:
|
||||
pointerMessage = ePointerCancel;
|
||||
break;
|
||||
default:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < touchEvent->mTouches.Length(); ++i) {
|
||||
mozilla::dom::Touch* touch = touchEvent->mTouches[i];
|
||||
if (!TouchManager::ShouldConvertTouchToPointer(touch, touchEvent)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WidgetPointerEvent event(touchEvent->IsTrusted(), pointerMessage,
|
||||
touchEvent->mWidget);
|
||||
event.mIsPrimary = i == 0;
|
||||
event.pointerId = touch->Identifier();
|
||||
event.mRefPoint = touch->mRefPoint;
|
||||
event.mModifiers = touchEvent->mModifiers;
|
||||
event.mWidth = touch->RadiusX(CallerType::System);
|
||||
event.mHeight = touch->RadiusY(CallerType::System);
|
||||
event.tiltX = touch->tiltX;
|
||||
event.tiltY = touch->tiltY;
|
||||
event.mTime = touchEvent->mTime;
|
||||
event.mTimeStamp = touchEvent->mTimeStamp;
|
||||
event.mFlags = touchEvent->mFlags;
|
||||
event.button = button;
|
||||
event.buttons = buttons;
|
||||
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||
event.convertToPointer = touch->convertToPointer = false;
|
||||
PreHandlePointerEventsPreventDefault(&event, aEvent);
|
||||
aShell->HandleEvent(aFrame, &event, aDontRetargetEvents, aStatus,
|
||||
aTargetContent);
|
||||
PostHandlePointerEventsPreventDefault(&event, aEvent);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
PresShell::CanDispatchEvent(const WidgetGUIEvent* aEvent) const
|
||||
{
|
||||
@ -7154,12 +6785,12 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
||||
aFrame->SchedulePaint(nsIFrame::PAINT_COMPOSITE_ONLY);
|
||||
}
|
||||
|
||||
if (sPointerEventEnabled) {
|
||||
if (PointerEventHandler::IsPointerEventEnabled()) {
|
||||
AutoWeakFrame weakFrame(aFrame);
|
||||
nsCOMPtr<nsIContent> targetContent;
|
||||
DispatchPointerFromMouseOrTouch(this, aFrame, aEvent, aDontRetargetEvents,
|
||||
aEventStatus,
|
||||
getter_AddRefs(targetContent));
|
||||
PointerEventHandler::DispatchPointerFromMouseOrTouch(
|
||||
this, aFrame, aEvent, aDontRetargetEvents,
|
||||
aEventStatus, getter_AddRefs(targetContent));
|
||||
if (!weakFrame.IsAlive()) {
|
||||
if (targetContent) {
|
||||
aFrame = targetContent->GetPrimaryFrame();
|
||||
@ -7209,10 +6840,6 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
||||
}
|
||||
}
|
||||
|
||||
if (sPointerEventEnabled) {
|
||||
UpdateActivePointerState(aEvent);
|
||||
}
|
||||
|
||||
if (!nsContentUtils::IsSafeToRunScript() &&
|
||||
aEvent->IsAllowedToDispatchDOMEvent()) {
|
||||
if (aEvent->mClass == eCompositionEventClass) {
|
||||
@ -7551,51 +7178,18 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
||||
}
|
||||
}
|
||||
|
||||
if (aEvent->mClass == ePointerEventClass) {
|
||||
if (WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent()) {
|
||||
// Try to keep frame for following check, because
|
||||
// frame can be damaged during CheckPointerCaptureState.
|
||||
AutoWeakFrame frameKeeper(frame);
|
||||
// Handle pending pointer capture before any pointer events except
|
||||
// gotpointercapture / lostpointercapture.
|
||||
CheckPointerCaptureState(pointerEvent);
|
||||
// Prevent application crashes, in case damaged frame.
|
||||
if (!frameKeeper.IsAlive()) {
|
||||
frame = nullptr;
|
||||
}
|
||||
// Implicit pointer capture for touch
|
||||
if (frame && sPointerEventImplicitCapture &&
|
||||
pointerEvent->mMessage == ePointerDown &&
|
||||
pointerEvent->inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
|
||||
nsCOMPtr<nsIContent> targetContent;
|
||||
frame->GetContentForEvent(aEvent, getter_AddRefs(targetContent));
|
||||
while (targetContent && !targetContent->IsElement()) {
|
||||
targetContent = targetContent->GetParent();
|
||||
}
|
||||
if (targetContent) {
|
||||
SetPointerCapturingContent(pointerEvent->pointerId, targetContent);
|
||||
}
|
||||
}
|
||||
// Try to keep frame for following check, because frame can be damaged
|
||||
// during CheckPointerCaptureState.
|
||||
{
|
||||
AutoWeakFrame frameKeeper(frame);
|
||||
PointerEventHandler::CheckPointerCaptureState(aEvent->AsPointerEvent());
|
||||
// Prevent application crashes, in case damaged frame.
|
||||
if (!frameKeeper.IsAlive()) {
|
||||
frame = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse events should be fired to the same target as their mapped pointer
|
||||
// events
|
||||
if ((aEvent->mClass == ePointerEventClass ||
|
||||
aEvent->mClass == eMouseEventClass) &&
|
||||
aEvent->mMessage != ePointerDown && aEvent->mMessage != eMouseDown) {
|
||||
if (WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) {
|
||||
uint32_t pointerId = mouseEvent->pointerId;
|
||||
nsIContent* pointerCapturingContent =
|
||||
GetPointerCapturingContent(pointerId);
|
||||
|
||||
if (pointerCapturingContent) {
|
||||
if (nsIFrame* capturingFrame = pointerCapturingContent->GetPrimaryFrame()) {
|
||||
frame = capturingFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
frame = PointerEventHandler::GetPointerCapturingFrame(frame, aEvent);
|
||||
|
||||
// Suppress mouse event if it's being targeted at an element inside
|
||||
// a document which needs events suppressed
|
||||
@ -7690,8 +7284,8 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
||||
// Before HandlePositionedEvent we should save mPointerEventTarget in some
|
||||
// cases
|
||||
AutoWeakFrame weakFrame;
|
||||
if (sPointerEventEnabled && aTargetContent &&
|
||||
ePointerEventClass == aEvent->mClass) {
|
||||
if (aTargetContent && ePointerEventClass == aEvent->mClass) {
|
||||
MOZ_ASSERT(PointerEventHandler::IsPointerEventEnabled());
|
||||
weakFrame = frame;
|
||||
shell->mPointerEventTarget = frame->GetContent();
|
||||
MOZ_ASSERT(!frame->GetContent() ||
|
||||
@ -7715,8 +7309,8 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
||||
|
||||
// After HandlePositionedEvent we should reestablish
|
||||
// content (which still live in tree) in some cases
|
||||
if (sPointerEventEnabled && aTargetContent &&
|
||||
ePointerEventClass == aEvent->mClass) {
|
||||
if (aTargetContent && ePointerEventClass == aEvent->mClass) {
|
||||
MOZ_ASSERT(PointerEventHandler::IsPointerEventEnabled());
|
||||
if (!weakFrame.IsAlive()) {
|
||||
shell->mPointerEventTarget.swap(*aTargetContent);
|
||||
}
|
||||
@ -8162,8 +7756,8 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent,
|
||||
// ePointerCancel.
|
||||
WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent();
|
||||
MOZ_ASSERT(pointerEvent);
|
||||
nsIPresShell::ReleasePointerCapturingContent(pointerEvent->pointerId);
|
||||
nsIPresShell::CheckPointerCaptureState(pointerEvent);
|
||||
PointerEventHandler::ReleasePointerCaptureById(pointerEvent->pointerId);
|
||||
PointerEventHandler::CheckPointerCaptureState(pointerEvent);
|
||||
}
|
||||
|
||||
// 3. Give event to event manager for post event state changes and
|
||||
@ -8320,45 +7914,7 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent,
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsIPresShell::DispatchGotOrLostPointerCaptureEvent(
|
||||
bool aIsGotCapture,
|
||||
const WidgetPointerEvent* aPointerEvent,
|
||||
nsIContent* aCaptureTarget)
|
||||
{
|
||||
nsIDocument* targetDoc = aCaptureTarget->OwnerDoc();
|
||||
nsCOMPtr<nsIPresShell> shell = targetDoc->GetShell();
|
||||
NS_ENSURE_TRUE_VOID(shell);
|
||||
|
||||
if (!aIsGotCapture && !aCaptureTarget->IsInUncomposedDoc()) {
|
||||
// If the capturing element was removed from the DOM tree, fire
|
||||
// ePointerLostCapture at the document.
|
||||
PointerEventInit init;
|
||||
init.mPointerId = aPointerEvent->pointerId;
|
||||
init.mBubbles = true;
|
||||
init.mComposed = true;
|
||||
ConvertPointerTypeToString(aPointerEvent->inputSource, init.mPointerType);
|
||||
init.mIsPrimary = aPointerEvent->mIsPrimary;
|
||||
RefPtr<mozilla::dom::PointerEvent> event;
|
||||
event = PointerEvent::Constructor(aCaptureTarget,
|
||||
NS_LITERAL_STRING("lostpointercapture"),
|
||||
init);
|
||||
bool dummy;
|
||||
targetDoc->DispatchEvent(event->InternalDOMEvent(), &dummy);
|
||||
return;
|
||||
}
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
WidgetPointerEvent localEvent(aPointerEvent->IsTrusted(),
|
||||
aIsGotCapture ? ePointerGotCapture :
|
||||
ePointerLostCapture,
|
||||
aPointerEvent->mWidget);
|
||||
localEvent.AssignPointerEventData(*aPointerEvent, true);
|
||||
nsresult rv = shell->HandleEventWithTarget(
|
||||
&localEvent,
|
||||
aCaptureTarget->GetPrimaryFrame(),
|
||||
aCaptureTarget, &status);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PresShell::DispatchEventToDOM(WidgetEvent* aEvent,
|
||||
@ -10887,23 +10443,6 @@ nsIPresShell::AccService()
|
||||
}
|
||||
#endif
|
||||
|
||||
void nsIPresShell::InitializeStatics()
|
||||
{
|
||||
MOZ_ASSERT(!sPointerCaptureList, "InitializeStatics called multiple times!");
|
||||
sPointerCaptureList =
|
||||
new nsClassHashtable<nsUint32HashKey, PointerCaptureInfo>;
|
||||
sActivePointersIds = new nsClassHashtable<nsUint32HashKey, PointerInfo>;
|
||||
}
|
||||
|
||||
void nsIPresShell::ReleaseStatics()
|
||||
{
|
||||
MOZ_ASSERT(sPointerCaptureList, "ReleaseStatics called without Initialize!");
|
||||
delete sPointerCaptureList;
|
||||
sPointerCaptureList = nullptr;
|
||||
delete sActivePointersIds;
|
||||
sActivePointersIds = nullptr;
|
||||
}
|
||||
|
||||
// Asks our docshell whether we're active.
|
||||
void PresShell::QueryIsActive()
|
||||
{
|
||||
|
@ -734,9 +734,6 @@ protected:
|
||||
virtual void PausePainting() override;
|
||||
virtual void ResumePainting() override;
|
||||
|
||||
void UpdateActivePointerState(mozilla::WidgetGUIEvent* aEvent);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Approximate frame visibility tracking implementation.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1248,76 +1248,6 @@ public:
|
||||
// mouse capturing
|
||||
static CapturingContentInfo gCaptureInfo;
|
||||
|
||||
class PointerCaptureInfo final
|
||||
{
|
||||
public:
|
||||
nsCOMPtr<nsIContent> mPendingContent;
|
||||
nsCOMPtr<nsIContent> mOverrideContent;
|
||||
|
||||
explicit PointerCaptureInfo(nsIContent* aPendingContent)
|
||||
: mPendingContent(aPendingContent)
|
||||
{
|
||||
MOZ_COUNT_CTOR(PointerCaptureInfo);
|
||||
}
|
||||
|
||||
~PointerCaptureInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(PointerCaptureInfo);
|
||||
}
|
||||
|
||||
bool Empty()
|
||||
{
|
||||
return !(mPendingContent || mOverrideContent);
|
||||
}
|
||||
};
|
||||
|
||||
class PointerInfo final
|
||||
{
|
||||
public:
|
||||
uint16_t mPointerType;
|
||||
bool mActiveState;
|
||||
bool mPrimaryState;
|
||||
bool mPreventMouseEventByContent;
|
||||
explicit PointerInfo(bool aActiveState, uint16_t aPointerType,
|
||||
bool aPrimaryState)
|
||||
: mPointerType(aPointerType)
|
||||
, mActiveState(aActiveState)
|
||||
, mPrimaryState(aPrimaryState)
|
||||
, mPreventMouseEventByContent(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static void DispatchGotOrLostPointerCaptureEvent(
|
||||
bool aIsGotCapture,
|
||||
const mozilla::WidgetPointerEvent* aPointerEvent,
|
||||
nsIContent* aCaptureTarget);
|
||||
|
||||
static PointerCaptureInfo* GetPointerCaptureInfo(uint32_t aPointerId);
|
||||
static void SetPointerCapturingContent(uint32_t aPointerId,
|
||||
nsIContent* aContent);
|
||||
static void ReleasePointerCapturingContent(uint32_t aPointerId);
|
||||
static nsIContent* GetPointerCapturingContent(uint32_t aPointerId);
|
||||
|
||||
// CheckPointerCaptureState checks cases, when got/lostpointercapture events
|
||||
// should be fired.
|
||||
static void CheckPointerCaptureState(
|
||||
const mozilla::WidgetPointerEvent* aPointerEvent);
|
||||
|
||||
// GetPointerInfo returns true if pointer with aPointerId is situated in
|
||||
// device, false otherwise.
|
||||
// aActiveState is additional information, which shows state of pointer like
|
||||
// button state for mouse.
|
||||
static bool GetPointerInfo(uint32_t aPointerId, bool& aActiveState);
|
||||
|
||||
// GetPointerType returns pointer type like mouse, pen or touch for pointer
|
||||
// event with pointerId
|
||||
static uint16_t GetPointerType(uint32_t aPointerId);
|
||||
|
||||
// GetPointerPrimaryState returns state of attribute isPrimary for pointer
|
||||
// event with pointerId
|
||||
static bool GetPointerPrimaryState(uint32_t aPointerId);
|
||||
|
||||
/**
|
||||
* When capturing content is set, it traps all mouse events and retargets
|
||||
* them at this content node. If capturing is not allowed
|
||||
@ -1685,12 +1615,6 @@ public:
|
||||
virtual bool AddPostRefreshObserver(nsAPostRefreshObserver* aObserver);
|
||||
virtual bool RemovePostRefreshObserver(nsAPostRefreshObserver* aObserver);
|
||||
|
||||
/**
|
||||
* Initialize and shut down static variables.
|
||||
*/
|
||||
static void InitializeStatics();
|
||||
static void ReleaseStatics();
|
||||
|
||||
// If a frame in the subtree rooted at aFrame is capturing the mouse then
|
||||
// clears that capture.
|
||||
static void ClearMouseCapture(nsIFrame* aFrame);
|
||||
|
@ -124,6 +124,7 @@
|
||||
#include "mozilla/dom/WebIDLGlobalNameHash.h"
|
||||
#include "mozilla/dom/ipc/IPCBlobInputStreamStorage.h"
|
||||
#include "mozilla/dom/U2FTokenManager.h"
|
||||
#include "mozilla/dom/PointerEventHandler.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::net;
|
||||
@ -259,7 +260,7 @@ nsLayoutStatics::Initialize()
|
||||
nsHtml5Module::InitializeStatics();
|
||||
mozilla::dom::FallbackEncoding::Initialize();
|
||||
nsLayoutUtils::Initialize();
|
||||
nsIPresShell::InitializeStatics();
|
||||
PointerEventHandler::InitializeStatics();
|
||||
TouchManager::InitializeStatics();
|
||||
ContentPrincipal::InitializeStatics();
|
||||
|
||||
@ -400,7 +401,7 @@ nsLayoutStatics::Shutdown()
|
||||
|
||||
nsCORSListenerProxy::Shutdown();
|
||||
|
||||
nsIPresShell::ReleaseStatics();
|
||||
PointerEventHandler::ReleaseStatics();
|
||||
|
||||
TouchManager::ReleaseStatics();
|
||||
|
||||
|
5
layout/generic/crashtests/1401420-1.html
Normal file
5
layout/generic/crashtests/1401420-1.html
Normal file
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<style> rbc { display: ruby-base-container; } </style>
|
||||
<div style="-moz-column-width: 1px">
|
||||
x <ruby><rbc>aaaaaaaaaaaaaa</rbc><rbc><div style="float: left"></div></rbc></ruby>
|
||||
</div>
|
@ -658,5 +658,6 @@ load 1364361-1.html
|
||||
load 1367413-1.html
|
||||
load 1368617-1.html
|
||||
load 1373586.html
|
||||
load 1401420-1.html
|
||||
load 1401709.html
|
||||
load 1401807.html
|
||||
|
@ -1472,20 +1472,19 @@ nsContainerFrame::SetPropTableFrames(nsFrameList* aFrameList,
|
||||
SetProperty(aProperty, aFrameList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push aFromChild and its next siblings to the next-in-flow. Change the
|
||||
* geometric parent of each frame that's pushed. If there is no next-in-flow
|
||||
* the frames are placed on the overflow list (and the geometric parent is
|
||||
* left unchanged).
|
||||
*
|
||||
* Updates the next-in-flow's child count. Does <b>not</b> update the
|
||||
* pusher's child count.
|
||||
*
|
||||
* @param aFromChild the first child frame to push. It is disconnected from
|
||||
* aPrevSibling
|
||||
* @param aPrevSibling aFromChild's previous sibling. Must not be null. It's
|
||||
* an error to push a parent's first child frame
|
||||
*/
|
||||
void
|
||||
nsContainerFrame::PushChildrenToOverflow(nsIFrame* aFromChild,
|
||||
nsIFrame* aPrevSibling)
|
||||
{
|
||||
NS_PRECONDITION(aFromChild, "null pointer");
|
||||
NS_PRECONDITION(aPrevSibling, "pushing first child");
|
||||
NS_PRECONDITION(aPrevSibling->GetNextSibling() == aFromChild, "bad prev sibling");
|
||||
|
||||
// Add the frames to our overflow list (let our next in flow drain
|
||||
// our overflow list when it is ready)
|
||||
SetOverflowFrames(mFrames.RemoveFramesAfter(aPrevSibling));
|
||||
}
|
||||
|
||||
void
|
||||
nsContainerFrame::PushChildren(nsIFrame* aFromChild,
|
||||
nsIFrame* aPrevSibling)
|
||||
@ -1516,16 +1515,8 @@ nsContainerFrame::PushChildren(nsIFrame* aFromChild,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves any frames on the overflow lists (the prev-in-flow's overflow list and
|
||||
* the receiver's overflow list) to the child list.
|
||||
*
|
||||
* Updates this frame's child count and content mapping.
|
||||
*
|
||||
* @return true if any frames were moved and false otherwise
|
||||
*/
|
||||
bool
|
||||
nsContainerFrame::MoveOverflowToChildList()
|
||||
nsContainerFrame::MoveOverflowToChildList(nsIFrame* aLineContainer)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
@ -1535,9 +1526,23 @@ nsContainerFrame::MoveOverflowToChildList()
|
||||
AutoFrameListPtr prevOverflowFrames(PresContext(),
|
||||
prevInFlow->StealOverflowFrames());
|
||||
if (prevOverflowFrames) {
|
||||
// Tables are special; they can have repeated header/footer
|
||||
// frames on mFrames at this point.
|
||||
NS_ASSERTION(mFrames.IsEmpty() || IsTableFrame(), "bad overflow list");
|
||||
// Overflow frames from prev-in-flow should have been pushed to
|
||||
// this frame directly if we have already existed, so there should
|
||||
// be no frame in mFrames when we steal frames from overflow list
|
||||
// of prev-in-flow. However, there are two special cases:
|
||||
// * tables can have repeated header/footer frames at this point,
|
||||
// * inline frames always push frames into overflow list rather
|
||||
// than next-in-flow, so that floats reparenting can be handled
|
||||
// properly below.
|
||||
NS_ASSERTION(mFrames.IsEmpty() || IsTableFrame() || aLineContainer,
|
||||
"bad overflow list");
|
||||
// If we are on a frame which has line container, we may need to
|
||||
// reparent floats from prev-in-flow to our line container.
|
||||
if (aLineContainer && aLineContainer->GetPrevContinuation()) {
|
||||
ReparentFloatsForInlineChild(aLineContainer,
|
||||
prevOverflowFrames->FirstChild(),
|
||||
true);
|
||||
}
|
||||
// When pushing and pulling frames we need to check for whether any
|
||||
// views need to be reparented.
|
||||
nsContainerFrame::ReparentFrameViewList(*prevOverflowFrames,
|
||||
@ -1685,6 +1690,50 @@ nsContainerFrame::PullNextInFlowChild(ContinuationTraversingState& aState)
|
||||
return frame;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContainerFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer,
|
||||
nsIFrame* aFrame,
|
||||
bool aReparentSiblings)
|
||||
{
|
||||
// XXXbz this would be better if it took a nsFrameList or a frame
|
||||
// list slice....
|
||||
NS_ASSERTION(aOurLineContainer->GetNextContinuation() ||
|
||||
aOurLineContainer->GetPrevContinuation(),
|
||||
"Don't call this when we have no continuation, it's a waste");
|
||||
if (!aFrame) {
|
||||
NS_ASSERTION(aReparentSiblings, "Why did we get called?");
|
||||
return;
|
||||
}
|
||||
|
||||
nsBlockFrame* frameBlock = nsLayoutUtils::GetFloatContainingBlock(aFrame);
|
||||
if (!frameBlock || frameBlock == aOurLineContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsBlockFrame* ourBlock = nsLayoutUtils::GetAsBlock(aOurLineContainer);
|
||||
NS_ASSERTION(ourBlock, "Not a block, but broke vertically?");
|
||||
|
||||
while (true) {
|
||||
ourBlock->ReparentFloats(aFrame, frameBlock, false);
|
||||
|
||||
if (!aReparentSiblings)
|
||||
return;
|
||||
nsIFrame* next = aFrame->GetNextSibling();
|
||||
if (!next)
|
||||
return;
|
||||
if (next->GetParent() == aFrame->GetParent()) {
|
||||
aFrame = next;
|
||||
continue;
|
||||
}
|
||||
// This is paranoid and will hardly ever get hit ... but we can't actually
|
||||
// trust that the frames in the sibling chain all have the same parent,
|
||||
// because lazy reparenting may be going on. If we find a different
|
||||
// parent we need to redo our analysis.
|
||||
ReparentFloatsForInlineChild(aOurLineContainer, next, aReparentSiblings);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsContainerFrame::ResolvedOrientationIsVertical()
|
||||
{
|
||||
|
@ -629,26 +629,43 @@ protected:
|
||||
* Resets the overlist pointers to nullptr, and updates the receiver's child
|
||||
* count and content mapping.
|
||||
*
|
||||
* @param aLineContainer the line container of the current frame if it
|
||||
* has one. nullptr if unrelated.
|
||||
*
|
||||
* @return true if any frames were moved and false otherwise
|
||||
*/
|
||||
bool MoveOverflowToChildList();
|
||||
bool MoveOverflowToChildList(nsIFrame* aLineContainer = nullptr);
|
||||
|
||||
/**
|
||||
* Push aFromChild and its next siblings to the next-in-flow. Change
|
||||
* the geometric parent of each frame that's pushed. If there is no
|
||||
* next-in-flow the frames are placed on the overflow list (and the
|
||||
* geometric parent is left unchanged).
|
||||
* Push aFromChild and its next siblings to the overflow list.
|
||||
*
|
||||
* @param aFromChild the first child frame to push. It is disconnected
|
||||
* from aPrevSibling
|
||||
* @param aPrevSibling aFrameChild's previous sibling. Must not be null.
|
||||
* It's an error to push a parent's first child frame.
|
||||
*/
|
||||
void PushChildrenToOverflow(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
|
||||
|
||||
/**
|
||||
* Same as above, except that this pushes frames to the next-in-flow
|
||||
* frame and changes the geometric parent of the pushed frames when
|
||||
* there is a next-in-flow frame.
|
||||
*
|
||||
* Updates the next-in-flow's child count. Does <b>not</b> update the
|
||||
* pusher's child count.
|
||||
*
|
||||
* @param aFromChild the first child frame to push. It is disconnected from
|
||||
* aPrevSibling
|
||||
* @param aPrevSibling aFromChild's previous sibling. Must not be null.
|
||||
* It's an error to push a parent's first child frame
|
||||
*/
|
||||
void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
|
||||
|
||||
/**
|
||||
* Reparent floats whose placeholders are inline descendants of aFrame from
|
||||
* whatever block they're currently parented by to aOurBlock.
|
||||
* @param aReparentSiblings if this is true, we follow aFrame's
|
||||
* GetNextSibling chain reparenting them all
|
||||
*/
|
||||
static void ReparentFloatsForInlineChild(nsIFrame* aOurBlock,
|
||||
nsIFrame* aFrame,
|
||||
bool aReparentSiblings);
|
||||
|
||||
// ==========================================================================
|
||||
/*
|
||||
* Convenience methods for traversing continuations
|
||||
|
@ -294,50 +294,6 @@ nsInlineFrame::ComputeTightBounds(DrawTarget* aDrawTarget) const
|
||||
return ComputeSimpleTightBounds(aDrawTarget);
|
||||
}
|
||||
|
||||
void
|
||||
nsInlineFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer,
|
||||
nsIFrame* aFrame,
|
||||
bool aReparentSiblings)
|
||||
{
|
||||
// XXXbz this would be better if it took a nsFrameList or a frame
|
||||
// list slice....
|
||||
NS_ASSERTION(aOurLineContainer->GetNextContinuation() ||
|
||||
aOurLineContainer->GetPrevContinuation(),
|
||||
"Don't call this when we have no continuation, it's a waste");
|
||||
if (!aFrame) {
|
||||
NS_ASSERTION(aReparentSiblings, "Why did we get called?");
|
||||
return;
|
||||
}
|
||||
|
||||
nsBlockFrame* frameBlock = nsLayoutUtils::GetFloatContainingBlock(aFrame);
|
||||
if (!frameBlock || frameBlock == aOurLineContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsBlockFrame* ourBlock = nsLayoutUtils::GetAsBlock(aOurLineContainer);
|
||||
NS_ASSERTION(ourBlock, "Not a block, but broke vertically?");
|
||||
|
||||
while (true) {
|
||||
ourBlock->ReparentFloats(aFrame, frameBlock, false);
|
||||
|
||||
if (!aReparentSiblings)
|
||||
return;
|
||||
nsIFrame* next = aFrame->GetNextSibling();
|
||||
if (!next)
|
||||
return;
|
||||
if (next->GetParent() == aFrame->GetParent()) {
|
||||
aFrame = next;
|
||||
continue;
|
||||
}
|
||||
// This is paranoid and will hardly ever get hit ... but we can't actually
|
||||
// trust that the frames in the sibling chain all have the same parent,
|
||||
// because lazy reparenting may be going on. If we find a different
|
||||
// parent we need to redo our analysis.
|
||||
ReparentFloatsForInlineChild(aOurLineContainer, next, aReparentSiblings);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ReparentChildListStyle(nsPresContext* aPresContext,
|
||||
const nsFrameList::Slice& aFrames,
|
||||
@ -916,18 +872,12 @@ nsInlineFrame::PushFrames(nsPresContext* aPresContext,
|
||||
nsIFrame* aPrevSibling,
|
||||
InlineReflowInput& aState)
|
||||
{
|
||||
NS_PRECONDITION(aFromChild, "null pointer");
|
||||
NS_PRECONDITION(aPrevSibling, "pushing first child");
|
||||
NS_PRECONDITION(aPrevSibling->GetNextSibling() == aFromChild, "bad prev sibling");
|
||||
|
||||
#ifdef NOISY_PUSHING
|
||||
printf("%p pushing aFromChild %p, disconnecting from prev sib %p\n",
|
||||
this, aFromChild, aPrevSibling);
|
||||
#endif
|
||||
|
||||
// Add the frames to our overflow list (let our next in flow drain
|
||||
// our overflow list when it is ready)
|
||||
SetOverflowFrames(mFrames.RemoveFramesAfter(aPrevSibling));
|
||||
PushChildrenToOverflow(aFromChild, aPrevSibling);
|
||||
if (aState.mLineLayout) {
|
||||
aState.mLineLayout->SetDirtyNextLine();
|
||||
}
|
||||
|
@ -158,15 +158,6 @@ protected:
|
||||
nsIFrame* aFrame,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
/**
|
||||
* Reparent floats whose placeholders are inline descendants of aFrame from
|
||||
* whatever block they're currently parented by to aOurBlock.
|
||||
* @param aReparentSiblings if this is true, we follow aFrame's
|
||||
* GetNextSibling chain reparenting them all
|
||||
*/
|
||||
void ReparentFloatsForInlineChild(nsIFrame* aOurBlock, nsIFrame* aFrame,
|
||||
bool aReparentSiblings);
|
||||
|
||||
virtual nsIFrame* PullOneFrame(nsPresContext* aPresContext,
|
||||
InlineReflowInput& rs,
|
||||
bool* aIsComplete);
|
||||
|
@ -313,12 +313,13 @@ nsRubyBaseContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
mDescendantLeadings.Reset();
|
||||
|
||||
MoveOverflowToChildList();
|
||||
nsIFrame* lineContainer = aReflowInput.mLineLayout->LineContainerFrame();
|
||||
MoveOverflowToChildList(lineContainer);
|
||||
// Ask text containers to drain overflows
|
||||
AutoRubyTextContainerArray textContainers(this);
|
||||
const uint32_t rtcCount = textContainers.Length();
|
||||
for (uint32_t i = 0; i < rtcCount; i++) {
|
||||
textContainers[i]->MoveOverflowToChildList();
|
||||
textContainers[i]->MoveOverflowToChildList(lineContainer);
|
||||
}
|
||||
|
||||
WritingMode lineWM = aReflowInput.mLineLayout->GetWritingMode();
|
||||
@ -544,7 +545,7 @@ nsRubyBaseContainerFrame::ReflowColumns(const RubyReflowInput& aReflowInput,
|
||||
baseFrame = nextColumn->mBaseFrame;
|
||||
}
|
||||
if (baseFrame) {
|
||||
PushChildren(baseFrame, baseFrame->GetPrevSibling());
|
||||
PushChildrenToOverflow(baseFrame, baseFrame->GetPrevSibling());
|
||||
}
|
||||
for (uint32_t i = 0; i < rtcCount; i++) {
|
||||
nsRubyTextFrame* textFrame = column.mTextFrames[i];
|
||||
@ -552,8 +553,8 @@ nsRubyBaseContainerFrame::ReflowColumns(const RubyReflowInput& aReflowInput,
|
||||
textFrame = nextColumn->mTextFrames[i];
|
||||
}
|
||||
if (textFrame) {
|
||||
aReflowInput.mTextContainers[i]->PushChildren(
|
||||
textFrame, textFrame->GetPrevSibling());
|
||||
aReflowInput.mTextContainers[i]->
|
||||
PushChildrenToOverflow(textFrame, textFrame->GetPrevSibling());
|
||||
}
|
||||
}
|
||||
} else if (reflowStatus.IsInlineBreakAfter()) {
|
||||
|
@ -115,7 +115,7 @@ nsRubyFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
// Grab overflow frames from prev-in-flow and its own.
|
||||
MoveOverflowToChildList();
|
||||
MoveOverflowToChildList(aReflowInput.mLineLayout->LineContainerFrame());
|
||||
|
||||
// Clear leadings
|
||||
mLeadings.Reset();
|
||||
@ -228,7 +228,7 @@ nsRubyFrame::ReflowSegment(nsPresContext* aPresContext,
|
||||
aStatus.Reset();
|
||||
aStatus.SetInlineLineBreakAfter();
|
||||
aStatus.SetIncomplete();
|
||||
PushChildren(aBaseContainer, aBaseContainer->GetPrevSibling());
|
||||
PushChildrenToOverflow(aBaseContainer, aBaseContainer->GetPrevSibling());
|
||||
aReflowInput.mLineLayout->SetDirtyNextLine();
|
||||
}
|
||||
// This base container is not placed at all, we can skip all
|
||||
@ -274,7 +274,7 @@ nsRubyFrame::ReflowSegment(nsPresContext* aPresContext,
|
||||
// Always push the next frame after the last child in this segment.
|
||||
// It is possible that we pulled it back before our next-in-flow
|
||||
// drain our overflow.
|
||||
PushChildren(lastChild->GetNextSibling(), lastChild);
|
||||
PushChildrenToOverflow(lastChild->GetNextSibling(), lastChild);
|
||||
aReflowInput.mLineLayout->SetDirtyNextLine();
|
||||
}
|
||||
} else {
|
||||
|
@ -8063,15 +8063,13 @@ nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBu
|
||||
animationsId = 0;
|
||||
}
|
||||
|
||||
gfx::Matrix4x4Typed<LayerPixel, LayerPixel> boundTransform = ViewAs<gfx::Matrix4x4Typed<LayerPixel, LayerPixel>>(newTransformMatrix);
|
||||
|
||||
nsTArray<mozilla::wr::WrFilterOp> filters;
|
||||
StackingContextHelper sc(aSc,
|
||||
aBuilder,
|
||||
aDisplayListBuilder,
|
||||
this,
|
||||
mStoredList.GetChildren(),
|
||||
&boundTransform,
|
||||
&newTransformMatrix,
|
||||
animationsId,
|
||||
nullptr,
|
||||
transformForSC,
|
||||
|
@ -7,7 +7,7 @@
|
||||
# clipping on Windows. (Any other fix would have a significant perf cost.)
|
||||
fuzzy-if(winWidget,1,1) == multicolor-image-2.html multicolor-image-2-ref.html
|
||||
== multicolor-image-3.html multicolor-image-3-ref.html
|
||||
fails-if(webrender) == multicolor-image-4.html multicolor-image-4-ref.html
|
||||
== multicolor-image-4.html multicolor-image-4-ref.html
|
||||
== multicolor-image-5.html multicolor-image-5-ref.html
|
||||
== transparent-image-1.html transparent-image-1-ref.html
|
||||
!= repeat-image-1.html repeat-image-1-ref.html
|
||||
|
@ -1637,7 +1637,7 @@ HTTP(..) == 615121-1.html 615121-1-ref.html
|
||||
HTTP(..) != 615121-2.html 615121-2-notref.html
|
||||
== 617242-1.html 617242-1-ref.html
|
||||
!= 618071.html 618071-notref.html
|
||||
== 619117-1.html 619117-1-ref.html
|
||||
fails-if(webrender) == 619117-1.html 619117-1-ref.html
|
||||
HTTP(..) == 619511-1.html 619511-1-ref.html
|
||||
skip-if(Android) HTTP(..) == 621253-1-externalFilter.html 621253-1-ref.html
|
||||
skip-if(Android) == 621253-1-internalFilter.html 621253-1-ref.html
|
||||
@ -1807,7 +1807,7 @@ fuzzy-if(Android,1,1) fuzzy-if(skiaContent,1,160000) fails-if(webrender) == 9426
|
||||
fuzzy-if(skiaContent,1,5) == 956513-1.svg 956513-1-ref.svg
|
||||
== 944291-1.html 944291-1-ref.html
|
||||
== 950436-1.html 950436-1-ref.html
|
||||
fails-if(webrender) == 957770-1.svg 957770-1-ref.svg
|
||||
== 957770-1.svg 957770-1-ref.svg
|
||||
== 960277-1.html 960277-1-ref.html
|
||||
fuzzy-if(skiaContent,1,80) == 961887-1.html 961887-1-ref.html
|
||||
== 961887-2.html 961887-2-ref.html
|
||||
@ -1815,7 +1815,7 @@ fuzzy-if(skiaContent,1,80) == 961887-1.html 961887-1-ref.html
|
||||
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,145) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,3712) fails-if(webrender) == 966992-1.html 966992-1-ref.html
|
||||
skip-if(Android) == 966510-1.html 966510-1-ref.html # scrollable elements other than the root probably won't work well on android until bug 776030 is fixed
|
||||
skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above
|
||||
fuzzy-if(skiaContent,1,123) == 978911-1.svg 978911-1-ref.svg
|
||||
fuzzy-if(skiaContent,1,123) fails-if(webrender) == 978911-1.svg 978911-1-ref.svg
|
||||
== 983084-1.html 983084-1-ref.html
|
||||
== 983084-2.html 983084-2-ref.html
|
||||
== 983084-3.html 983084-1-ref.html
|
||||
|
@ -11,7 +11,7 @@ fails-if(azureSkia) fails-if(cocoaWidget) skip-if(styloVsGecko) == canvas-outsid
|
||||
== element-paint-repeated.html element-paint-repeated-ref.html
|
||||
== element-paint-recursion.html element-paint-recursion-ref.html
|
||||
HTTP(..) == element-paint-continuation.html element-paint-continuation-ref.html
|
||||
fails-if(webrender) == element-paint-transform-01.html element-paint-transform-01-ref.html
|
||||
== element-paint-transform-01.html element-paint-transform-01-ref.html
|
||||
random-if(d2d) == element-paint-transform-02.html element-paint-transform-02-ref.html # bug 587133
|
||||
fuzzy-if(d2d&&/^Windows\x20NT\x206\.1/.test(http.oscpu),16,90) == element-paint-background-size-01.html element-paint-background-size-01-ref.html
|
||||
== element-paint-background-size-02.html element-paint-background-size-02-ref.html
|
||||
@ -43,7 +43,7 @@ random-if(!cocoaWidget) fuzzy-if(cocoaWidget,2,42305) == gradient-html-07a.html
|
||||
fuzzy(1,16900) == gradient-html-07c.html gradient-html-07d.html
|
||||
HTTP == invalidate-1.html invalidate-1-ref.html
|
||||
== pattern-html-01.html pattern-html-01-ref.svg
|
||||
fails-if(webrender) == pattern-html-02.html pattern-html-02-ref.svg
|
||||
== pattern-html-02.html pattern-html-02-ref.svg
|
||||
== referenced-from-binding-01.html referenced-from-binding-01-ref.html
|
||||
|
||||
fuzzy-if(skiaContent,1,30000) == mask-image-element.html mask-image-element-ref.html
|
||||
|
@ -85,12 +85,12 @@ pref(layers.single-tile.enabled,false) != fast-scrolling.html about:blank
|
||||
== mask-invalidation-1a.html mask-invalidation-1-ref.html
|
||||
== mask-invalidation-1b.html mask-invalidation-1-ref.html
|
||||
|
||||
fails-if(webrender) == mask-invalidation-2a.html mask-invalidation-2-ref.html
|
||||
fails-if(webrender) == mask-invalidation-2b.html mask-invalidation-2-ref.html
|
||||
== mask-invalidation-2a.html mask-invalidation-2-ref.html
|
||||
== mask-invalidation-2b.html mask-invalidation-2-ref.html
|
||||
== mask-invalidation-2c.html mask-invalidation-2-ref.html
|
||||
== mask-invalidation-2d.html mask-invalidation-2-ref.html
|
||||
|
||||
fails-if(webrender) == clip-path-invalidation-1a.html mask-invalidation-2-ref.html
|
||||
fails-if(webrender) == clip-path-invalidation-1b.html mask-invalidation-2-ref.html
|
||||
== clip-path-invalidation-1a.html mask-invalidation-2-ref.html
|
||||
== clip-path-invalidation-1b.html mask-invalidation-2-ref.html
|
||||
== clip-path-invalidation-1c.html mask-invalidation-2-ref.html
|
||||
== clip-path-invalidation-1d.html mask-invalidation-2-ref.html
|
||||
|
@ -99,11 +99,11 @@ fuzzy-if(winWidget,1,10000) test-pref(svg.context-properties.content.enabled,tru
|
||||
# Simple <img> tests
|
||||
== img-simple-1.html lime100x100-ref.html
|
||||
== img-simple-2.html lime100x100-ref.html
|
||||
fuzzy-if(skiaContent,255,350) fails-if(webrender) == img-simple-3.html img-simple-3-ref.html
|
||||
fuzzy-if(skiaContent,255,350) == img-simple-3.html img-simple-3-ref.html
|
||||
== img-simple-4.html lime100x100-ref.html
|
||||
fuzzy-if(skiaContent,255,90) fails-if(webrender) == img-simple-5.html img-simple-5-ref.html
|
||||
fuzzy-if(skiaContent,255,90) == img-simple-5.html img-simple-5-ref.html
|
||||
== img-simple-6.html lime100x100-ref.html
|
||||
fuzzy-if(skiaContent,255,27) fails-if(webrender) == img-simple-7.html img-simple-7-ref.html
|
||||
fuzzy-if(skiaContent,255,27) == img-simple-7.html img-simple-7-ref.html
|
||||
|
||||
# Test with mix of <html:img> and <svg:image> referring to the same images,
|
||||
# with a variety of preserveAspectRatio values in play.
|
||||
@ -135,22 +135,22 @@ fails-if(webrender) == img-widthAndHeight-meet-2.html img-widthAndHeight-meet-2
|
||||
fails-if(webrender) == img-widthAndHeight-slice-1.html img-widthAndHeight-slice-1-ref.html
|
||||
fails-if(webrender) == img-widthAndHeight-slice-2.html img-widthAndHeight-slice-2-ref.html
|
||||
|
||||
fails-if(webrender) == img-height-meet-1.html img-height-meet-1-ref.html
|
||||
== img-height-meet-1.html img-height-meet-1-ref.html
|
||||
fails-if(webrender) == img-height-meet-2.html img-height-meet-2-ref.html
|
||||
fails-if(webrender) == img-height-slice-1.html img-height-slice-1-ref.html
|
||||
fails-if(webrender) == img-height-slice-2.html img-height-slice-2-ref.html
|
||||
|
||||
fails-if(webrender) == img-width-meet-1.html img-width-meet-1-ref.html
|
||||
== img-width-meet-1.html img-width-meet-1-ref.html
|
||||
fails-if(webrender) == img-width-meet-2.html img-width-meet-2-ref.html
|
||||
fails-if(webrender) == img-width-slice-1.html img-width-slice-1-ref.html
|
||||
fails-if(webrender) == img-width-slice-2.html img-width-slice-2-ref.html
|
||||
|
||||
# Alternate version of "width & height both non-%-valued" tests, but now
|
||||
# with no explicit viewBox, to trigger "synthesize-viewBox" behavior
|
||||
fails-if(webrender) == img-novb-widthAndHeight-meet-1-em.html img-novb-widthAndHeight-all-1-ref.html
|
||||
fails-if(webrender) == img-novb-widthAndHeight-meet-1-px.html img-novb-widthAndHeight-all-1-ref.html
|
||||
fails-if(webrender) == img-novb-widthAndHeight-slice-1-em.html img-novb-widthAndHeight-all-1-ref.html
|
||||
fails-if(webrender) == img-novb-widthAndHeight-slice-1-px.html img-novb-widthAndHeight-all-1-ref.html
|
||||
== img-novb-widthAndHeight-meet-1-em.html img-novb-widthAndHeight-all-1-ref.html
|
||||
== img-novb-widthAndHeight-meet-1-px.html img-novb-widthAndHeight-all-1-ref.html
|
||||
== img-novb-widthAndHeight-slice-1-em.html img-novb-widthAndHeight-all-1-ref.html
|
||||
== img-novb-widthAndHeight-slice-1-px.html img-novb-widthAndHeight-all-1-ref.html
|
||||
|
||||
# Alternate versions of "only one dimension is non-%-valued" tests, but now
|
||||
# with no explicit viewBox, to trigger "synthesize-viewBox" behavior
|
||||
|
@ -7,5 +7,5 @@ fuzzy-if(skiaContent,1,74) == img-zoomOut-1.html squaredCircle-50x50-ref.html
|
||||
# Ensure that scaled SVG images aren't fuzzy when tiled.
|
||||
== img-fuzzy-zoomOut-1.html img-fuzzy-zoomOut-1-ref.html
|
||||
== img-fuzzy-zoomIn-1.html img-fuzzy-zoomIn-1-ref.html
|
||||
fails-if(webrender) == img-fuzzy-transform-zoomOut-1.html img-fuzzy-zoomOut-1-ref.html
|
||||
fails-if(webrender) == img-fuzzy-transform-zoomIn-1.html img-fuzzy-zoomIn-1-ref.html
|
||||
== img-fuzzy-transform-zoomOut-1.html img-fuzzy-zoomOut-1-ref.html
|
||||
== img-fuzzy-transform-zoomIn-1.html img-fuzzy-zoomIn-1-ref.html
|
||||
|
@ -84,12 +84,12 @@ fails == filter-marked-line-01.svg pass.svg # bug 477704
|
||||
== filter-marked-line-08.svg pass.svg
|
||||
== filter-marked-line-09.svg pass.svg
|
||||
== filter-nested-filtering-01.svg pass.svg
|
||||
fails-if(webrender) == filter-nested-filtering-02.svg pass.svg
|
||||
== filter-nested-filtering-02.svg pass.svg
|
||||
== filter-patterned-rect-01.svg pass.svg
|
||||
== filter-patterned-rect-02.svg pass.svg
|
||||
== filter-region-01a.html pass.svg
|
||||
== filter-region-01b.html pass.svg
|
||||
fails-if(webrender) == filter-transform-01.svg pass.svg
|
||||
== filter-transform-01.svg pass.svg
|
||||
|
||||
== feColorMatrix-saturate-01.svg pass.svg
|
||||
|
||||
|
@ -19,4 +19,4 @@ random-if(d2d) == feImage-zoom-01b.svg feImage-zoom-01-ref.svg
|
||||
== foreignObject-zoom-01.svg pass.svg
|
||||
== zoom-invalidation-01.svg pass.svg
|
||||
== replaced-element-zoom-01.html pass.svg
|
||||
fuzzy-if(winWidget,12,7) fails-if(webrender) == zoomed-svg-with-viewBox-01.svg zoomed-svg-with-viewBox-01-ref.svg
|
||||
fuzzy-if(winWidget,12,7) == zoomed-svg-with-viewBox-01.svg zoomed-svg-with-viewBox-01-ref.svg
|
||||
|
@ -29,7 +29,7 @@ include svg-integration/reftest.list
|
||||
== background-svg-without-height-width.html background-ref.html
|
||||
== background-svg-without-width.html background-ref.html
|
||||
|
||||
fails-if(webrender) == baseline-middle-01.svg pass.svg
|
||||
== baseline-middle-01.svg pass.svg
|
||||
|
||||
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-color-burn.svg blend-color-burn-ref.svg
|
||||
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-color-dodge.svg blend-color-dodge-ref.svg
|
||||
@ -298,7 +298,7 @@ fuzzy-if(d2d||skiaContent,1,6400) == mask-type-04.svg mask-type-01-ref.svg
|
||||
fuzzy-if(skiaContent,3,448000) == nesting-invalid-01.svg nesting-invalid-01-ref.svg
|
||||
|
||||
fuzzy-if(d2d&&/^Windows\x20NT\x20(6\.1|10\.0)/.test(http.oscpu),63,168) fuzzy-if(cocoaWidget,1,122) fuzzy-if(skiaContent,2,1000) fails-if(webrender) == non-scaling-stroke-01.svg non-scaling-stroke-01-ref.svg # bug 1074161 for Win7 and OSX 10.8
|
||||
fuzzy-if(gtkWidget,1,99) fuzzy-if(!contentSameGfxBackendAsCanvas,9,99) fuzzy-if(Android,9,586) fails-if(webrender) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg
|
||||
fuzzy-if(gtkWidget,1,99) fuzzy-if(!contentSameGfxBackendAsCanvas,9,99) fuzzy-if(Android,9,586) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg
|
||||
fails-if(webrender) == non-scaling-stroke-03.svg non-scaling-stroke-03-ref.svg
|
||||
|
||||
== objectBoundingBox-and-clipPath.svg pass.svg
|
||||
@ -346,8 +346,8 @@ fuzzy-if(skiaContent,1,400) == path-06.svg path-06-ref.svg
|
||||
== path-07.svg path-07-ref.svg
|
||||
== path-08.svg pass.svg
|
||||
|
||||
fails-if(webrender) == pathLength-01.svg pass.svg
|
||||
fails-if(webrender) == pathLength-02.svg pass.svg
|
||||
== pathLength-01.svg pass.svg
|
||||
== pathLength-02.svg pass.svg
|
||||
|
||||
== pattern-basic-01.svg pass.svg
|
||||
fuzzy(1,5) skip-if(Android) fails-if(webrender) == pattern-big-image.html pattern-big-image-ref.html
|
||||
@ -356,7 +356,7 @@ fuzzy-if(skiaContent,1,5) == pattern-live-01a.svg pattern-live-01-ref.svg
|
||||
fuzzy-if(skiaContent,1,5) == pattern-live-01b.svg pattern-live-01-ref.svg
|
||||
fuzzy-if(skiaContent,1,5) == pattern-live-01c.svg pattern-live-01-ref.svg
|
||||
fuzzy-if(skiaContent,1,5) == pattern-scale-01a.svg pattern-scale-01-ref.svg
|
||||
fails-if(webrender) == pattern-scale-01b.svg pattern-scale-01-ref.svg
|
||||
== pattern-scale-01b.svg pattern-scale-01-ref.svg
|
||||
fuzzy-if(skiaContent,3,5) == pattern-scale-01c.svg pattern-scale-01-ref.svg
|
||||
fuzzy-if(webrender,0-2,0-227) == pattern-transform-presence-01.svg pattern-transform-presence-01-ref.svg
|
||||
== pattern-transformed-01.svg pattern-transformed-01-ref.svg
|
||||
@ -395,7 +395,7 @@ fuzzy-if(skiaContent,1,3600) == rect-01.svg pass.svg
|
||||
== stroke-dasharray-01.svg stroke-dasharray-01-ref.svg
|
||||
fuzzy-if(skiaContent,1,340) fails-if(webrender) == stroke-dasharray-02.svg pass.svg
|
||||
fuzzy-if(skiaContent,1,340) == stroke-dasharray-03.svg pass.svg
|
||||
fails-if(webrender) == stroke-dasharray-and-pathLength-01.svg pass.svg
|
||||
== stroke-dasharray-and-pathLength-01.svg pass.svg
|
||||
== stroke-dasharray-and-text-01.svg stroke-dasharray-and-text-01-ref.svg
|
||||
== stroke-dashoffset-01.svg pass.svg
|
||||
== stroke-dashoffset-and-pathLength-01.svg pass.svg
|
||||
@ -433,7 +433,7 @@ fuzzy-if(skiaContent,1,2600) == svg-in-foreignObject-02.xhtml svg-in-foreignObje
|
||||
== svg-transform-01.svg pass.svg
|
||||
== svg-transform-02.svg pass.svg
|
||||
|
||||
fails-if(webrender) == symbol-01.svg symbol-01-ref.svg
|
||||
== symbol-01.svg symbol-01-ref.svg
|
||||
|
||||
== text-font-size-01.svg pass.svg
|
||||
random-if(gtkWidget) == text-font-weight-01.svg text-font-weight-01-ref.svg # bug 386713
|
||||
@ -529,7 +529,7 @@ fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-re
|
||||
|
||||
== viewBox-and-pattern-01.svg pass.svg
|
||||
== viewBox-and-pattern-02.svg pass.svg
|
||||
fails-if(webrender) == viewBox-and-pattern-03.svg pass.svg
|
||||
== viewBox-and-pattern-03.svg pass.svg
|
||||
== viewBox-and-pattern-04.svg pass.svg
|
||||
== viewBox-invalid-01.svg pass.svg
|
||||
== viewBox-invalid-02.svg pass.svg
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
fuzzy(111,1802) fuzzy-if(skiaContent,130,1000) == additive-1.svg additive-1-ref.svg # bug 981344, bug 1239766
|
||||
== animate-width-1.svg lime.svg
|
||||
fuzzy-if(cocoaWidget,1,32) fuzzy-if(winWidget,15,30) fuzzy-if(gtkWidget,1,30) == paced-1.svg paced-1-ref.svg # bug 981640, Bug 1293550
|
||||
fuzzy-if(cocoaWidget,1,32) fuzzy-if(winWidget,15,30) fuzzy-if(gtkWidget,1,30) fails-if(webrender) == paced-1.svg paced-1-ref.svg # bug 981640, Bug 1293550
|
||||
fuzzy-if(skiaContent,7,90) == rotate-angle-1.svg rotate-angle-ref.svg
|
||||
fuzzy-if(skiaContent,7,90) == rotate-angle-2.svg rotate-angle-ref.svg
|
||||
fuzzy-if(skiaContent,7,130) == rotate-angle-3.svg rotate-angle-ref.svg
|
||||
|
@ -16,8 +16,8 @@ fuzzy-if(Android,255,30) == clipPath-html-06-extref.xhtml clipPath-html-06-ref.x
|
||||
== clipPath-html-07.xhtml clipPath-html-07-ref.svg
|
||||
== clipPath-html-08.xhtml clipPath-html-07-ref.svg # reuse 07-ref.svg
|
||||
== clipPath-html-zoomed-01.xhtml clipPath-html-01-ref.svg
|
||||
fails-if(webrender) == clipPath-transformed-html-01.xhtml ../pass.svg
|
||||
fails-if(webrender) == clipPath-transformed-html-02.xhtml ../pass.svg
|
||||
== clipPath-transformed-html-01.xhtml ../pass.svg
|
||||
== clipPath-transformed-html-02.xhtml ../pass.svg
|
||||
== conditions-outer-svg-01.xhtml ../pass.svg
|
||||
== conditions-outer-svg-02.xhtml ../pass.svg
|
||||
== dynamic-conditions-outer-svg-01.xhtml ../pass.svg
|
||||
@ -33,10 +33,10 @@ fuzzy-if(webrender,1,125414) == mask-html-01-extref-01.xhtml mask-html-01-ref.sv
|
||||
random == mask-html-01-extref-02.xhtml mask-html-01-ref.svg # random due to bug 877661
|
||||
fuzzy-if(webrender,1,125414) == mask-html-zoomed-01.xhtml mask-html-01-ref.svg
|
||||
fuzzy-if(webrender,1,125414) == mask-html-xbl-bound-01.html mask-html-01-ref.svg
|
||||
fails-if(webrender) == mask-transformed-html-01.xhtml ../pass.svg
|
||||
fails-if(webrender) == mask-transformed-html-02.xhtml ../pass.svg
|
||||
fuzzy-if(skiaContent,1,5) fails-if(webrender) == patterned-svg-under-transformed-html-01.xhtml ../pass.svg
|
||||
fails-if(webrender) == patterned-svg-under-transformed-html-02.xhtml ../pass.svg
|
||||
== mask-transformed-html-01.xhtml ../pass.svg
|
||||
== mask-transformed-html-02.xhtml ../pass.svg
|
||||
fuzzy-if(skiaContent,1,5) == patterned-svg-under-transformed-html-01.xhtml ../pass.svg
|
||||
== patterned-svg-under-transformed-html-02.xhtml ../pass.svg
|
||||
|
||||
fuzzy(1,5000) == mask-clipPath-opacity-01a.xhtml mask-clipPath-opacity-01-ref.xhtml
|
||||
fuzzy(1,5000) == mask-clipPath-opacity-01b.xhtml mask-clipPath-opacity-01-ref.xhtml
|
||||
|
@ -1,7 +1,7 @@
|
||||
== simple.svg simple-ref.html
|
||||
== simple-2.svg simple.svg
|
||||
== simple-underline.svg simple-underline-ref.html
|
||||
fails-if(webrender) == simple-underline-scaled.svg simple-underline-scaled-ref.svg
|
||||
== simple-underline-scaled.svg simple-underline-scaled-ref.svg
|
||||
== simple-anchor-end-bidi.svg simple-anchor-end-bidi-ref.html
|
||||
== simple-anchor-end-rtl.svg simple-anchor-end-rtl-ref.html
|
||||
== simple-anchor-end.svg simple-anchor-end-ref.html
|
||||
@ -123,7 +123,7 @@ fuzzy-if(skiaContent,1,15) == textpath.svg textpath-ref.svg
|
||||
fails-if(webrender) == textLength.svg textLength-ref.svg
|
||||
fuzzy-if(skiaContent,1,200) fails-if(webrender) == textLength-2.svg textLength-2-ref.svg
|
||||
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.[12]/.test(http.oscpu),4,17) fuzzy-if(skiaContent,4,100) fails-if(webrender) == textLength-3.svg textLength-3-ref.svg
|
||||
fails-if(webrender) == textLength-4.svg textLength-4-ref.svg
|
||||
== textLength-4.svg textLength-4-ref.svg
|
||||
== textLength-5.svg textLength-5-ref.svg
|
||||
== textLength-6.svg textLength-6-ref.svg
|
||||
|
||||
|
@ -11,7 +11,7 @@ fuzzy-if(webrender,0-1,0-6) == rotatey-1a.html rotatey-1-ref.html
|
||||
== rotatex-perspective-1c.html rotatex-1-ref.html
|
||||
== rotatex-perspective-3a.html rotatex-perspective-3-ref.html
|
||||
== scalez-1a.html scalez-1-ref.html
|
||||
fuzzy-if(gtkWidget||winWidget,8,376) fuzzy-if(Android,8,441) fuzzy-if(cocoaWidget,17,4) fuzzy-if(skiaContent,16,286) == preserve3d-1a.html preserve3d-1-ref.html
|
||||
fuzzy-if(gtkWidget||winWidget,8,376) fuzzy-if(Android,8,441) fuzzy-if(cocoaWidget,17,4) fuzzy-if(skiaContent,16,286) fails-if(webrender) == preserve3d-1a.html preserve3d-1-ref.html
|
||||
== preserve3d-1b.html about:blank
|
||||
== preserve3d-clipped.html about:blank
|
||||
== preserve3d-2a.html preserve3d-2-ref.html
|
||||
@ -41,7 +41,7 @@ fuzzy-if(winWidget&&!layersGPUAccelerated,1,251) == backface-visibility-2.html b
|
||||
fails-if(webrender) == perspective-clipping-1.html perspective-clipping-1-ref.html
|
||||
== perspective-clipping-2.html perspective-clipping-2-ref.html
|
||||
!= perspective-origin-1a.html rotatex-perspective-1a.html
|
||||
fuzzy-if(webrender,0-1,0-1) == perspective-origin-1b.html perspective-origin-1a.html
|
||||
fuzzy-if(webrender,0-1,0-3) == perspective-origin-1b.html perspective-origin-1a.html
|
||||
fuzzy(3,99) random-if(Android&&!browserIsRemote) == perspective-origin-2a.html perspective-origin-2-ref.html # subpixel AA, bug 732568
|
||||
fuzzy-if(winWidget&&!layersGPUAccelerated,1,61) == perspective-origin-3a.html perspective-origin-3-ref.html
|
||||
== perspective-origin-4a.html perspective-origin-4-ref.html
|
||||
|
@ -39,7 +39,7 @@ fuzzy-if(skiaContent,71,203) == mask-image-3i.html mask-image-3-ref.html
|
||||
|
||||
# mask-clip test cases
|
||||
== mask-clip-1.html mask-clip-1-ref.html
|
||||
fails-if(webrender) == mask-clip-2.html mask-clip-2-ref.html
|
||||
== mask-clip-2.html mask-clip-2-ref.html
|
||||
|
||||
# mask-position test cases
|
||||
== mask-position-1a.html mask-position-1-ref.html
|
||||
@ -65,7 +65,7 @@ fails-if(webrender) == mask-clip-2.html mask-clip-2-ref.html
|
||||
# mask-origin test cases
|
||||
== mask-origin-1.html mask-origin-1-ref.html
|
||||
fails == mask-origin-2.html mask-origin-2-ref.html # bug 1260094
|
||||
fails-if(webrender) == mask-origin-3.html mask-origin-3-ref.html
|
||||
== mask-origin-3.html mask-origin-3-ref.html
|
||||
|
||||
# mask-size test cases
|
||||
== mask-size-auto.html mask-size-auto-ref.html
|
||||
|
@ -46,6 +46,15 @@ DeclarationBlock::EnsureMutable()
|
||||
AsGecko()->AssertNotExpanded();
|
||||
}
|
||||
#endif
|
||||
if (IsServo() && !IsDirty()) {
|
||||
// In stylo, the old DeclarationBlock is stored in element's rule node tree
|
||||
// directly, to avoid new values replacing the DeclarationBlock in the tree
|
||||
// directly, we need to copy the old one here if we haven't yet copied.
|
||||
// As a result the new value does not replace rule node tree until traversal
|
||||
// happens.
|
||||
return Clone();
|
||||
}
|
||||
|
||||
if (!IsMutable()) {
|
||||
return Clone();
|
||||
}
|
||||
|
15
layout/style/crashtests/1402218-1.html
Normal file
15
layout/style/crashtests/1402218-1.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<style>
|
||||
#wrapper::first-line {}
|
||||
</style>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<div id="test"></div>
|
||||
</div>
|
||||
<script>
|
||||
document.querySelector('#test').style.position = 'absolute';
|
||||
document.body.offsetHeight;
|
||||
document.querySelector('#wrapper').style.color = 'green';
|
||||
document.querySelector('#test').style.position = '';
|
||||
</script>
|
||||
</body>
|
@ -233,6 +233,7 @@ load 1402366.html
|
||||
load 1402419.html
|
||||
load 1402472.html
|
||||
load 1403028.html
|
||||
load 1402218-1.html
|
||||
load 1403615.html
|
||||
load 1403592.html
|
||||
load 1403712.html
|
||||
|
@ -305,17 +305,7 @@ nsDOMCSSDeclaration::ModifyDeclaration(GeckoFunc aGeckoFunc,
|
||||
// between when we mutate the declaration and when we set the new
|
||||
// rule (see stack in bug 209575).
|
||||
mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
|
||||
RefPtr<DeclarationBlock> decl;
|
||||
if (olddecl->IsServo() && !olddecl->IsDirty()) {
|
||||
// In stylo, the old DeclarationBlock is stored in element's rule node tree
|
||||
// directly, to avoid new values replacing the DeclarationBlock in the tree
|
||||
// directly, we need to copy the old one here if we haven't yet copied.
|
||||
// As a result the new value does not replace rule node tree until traversal
|
||||
// happens.
|
||||
decl = olddecl->Clone();
|
||||
} else {
|
||||
decl = olddecl->EnsureMutable();
|
||||
}
|
||||
RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
|
||||
|
||||
bool changed;
|
||||
if (decl->IsGecko()) {
|
||||
|
@ -67,10 +67,28 @@
|
||||
of a table. */
|
||||
*|*::-moz-table-column {
|
||||
display: table-column !important;
|
||||
/* Make sure anonymous columns don't interfere with hit testing. Basically,
|
||||
* they should pretend as much as possible to not exist (since in the spec
|
||||
* they do not exist).
|
||||
*
|
||||
* Please make sure to not reintroduce
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1403293 if you change this
|
||||
* bit!
|
||||
*/
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
*|*::-moz-table-column-group {
|
||||
display: table-column-group !important;
|
||||
/* Make sure anonymous colgroups don't interfere with hit testing. Basically,
|
||||
* they should pretend as much as possible to not exist (since in the spec
|
||||
* they do not exist).
|
||||
*
|
||||
* Please make sure to not reintroduce
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1403293 if you change this
|
||||
* bit!
|
||||
*/
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
*|*::-moz-table-row-group {
|
||||
|
@ -3470,6 +3470,12 @@ nsBrowserAccess.prototype = {
|
||||
return this._getBrowser(aURI, null, aWhere, aFlags, null);
|
||||
},
|
||||
|
||||
createContentWindowInFrame: function browser_createContentWindowInFrame(
|
||||
aURI, aParams, aWhere, aFlags,
|
||||
aNextTabParentId, aName) {
|
||||
return this._getBrowser(null, null, aWhere, aFlags, null);
|
||||
},
|
||||
|
||||
isTabContentWindow: function(aWindow) {
|
||||
return BrowserApp.getBrowserForWindow(aWindow) != null;
|
||||
},
|
||||
|
@ -78,13 +78,13 @@ class GeckoViewNavigation extends GeckoViewModule {
|
||||
" aWhere=" + aWhere +
|
||||
" aFlags=" + aFlags);
|
||||
|
||||
if (!aUri || !this.isRegistered) {
|
||||
if (!this.isRegistered) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let message = {
|
||||
type: "GeckoView:OnLoadUri",
|
||||
uri: aUri.displaySpec,
|
||||
uri: aUri ? aUri.displaySpec : "",
|
||||
where: aWhere,
|
||||
flags: aFlags
|
||||
};
|
||||
@ -129,35 +129,45 @@ class GeckoViewNavigation extends GeckoViewModule {
|
||||
throw Cr.NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
// nsIBrowserDOMWindow::openURI implementation.
|
||||
openURI(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
|
||||
return this.createContentWindow(aUri, aOpener, aWhere, aFlags,
|
||||
aTriggeringPrincipal);
|
||||
}
|
||||
|
||||
// nsIBrowserDOMWindow::openURIInFrame implementation.
|
||||
openURIInFrame(aUri, aParams, aWhere, aFlags, aNextTabParentId, aName) {
|
||||
debug("openURIInFrame: aUri=" + (aUri && aUri.spec) +
|
||||
// nsIBrowserDOMWindow.
|
||||
createContentWindowInFrame(aUri, aParams, aWhere, aFlags, aNextTabParentId,
|
||||
aName) {
|
||||
debug("createContentWindowInFrame: aUri=" + (aUri && aUri.spec) +
|
||||
" aParams=" + aParams +
|
||||
" aWhere=" + aWhere +
|
||||
" aFlags=" + aFlags +
|
||||
" aNextTabParentId=" + aNextTabParentId +
|
||||
" aName=" + aName);
|
||||
|
||||
if (aWhere === Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW ||
|
||||
aWhere === Ci.nsIBrowserDOMWindow.OPEN_CURRENTWINDOW) {
|
||||
let handled = this.handleLoadUri(aUri, null, aWhere, aFlags, null);
|
||||
if (!handled &&
|
||||
(aWhere === Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW ||
|
||||
aWhere === Ci.nsIBrowserDOMWindow.OPEN_CURRENTWINDOW)) {
|
||||
return this.browser;
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
// nsIBrowserDOMWindow.
|
||||
openURI(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
|
||||
return this.createContentWindow(aUri, aOpener, aWhere, aFlags,
|
||||
aTriggeringPrincipal);
|
||||
}
|
||||
|
||||
// nsIBrowserDOMWindow.
|
||||
openURIInFrame(aUri, aParams, aWhere, aFlags, aNextTabParentId, aName) {
|
||||
return this.createContentWindowInFrame(aUri, aParams, aWhere, aFlags,
|
||||
aNextTabParentId, aName);
|
||||
}
|
||||
|
||||
// nsIBrowserDOMWindow.
|
||||
isTabContentWindow(aWindow) {
|
||||
debug("isTabContentWindow " + this.browser.contentWindow === aWindow);
|
||||
return this.browser.contentWindow === aWindow;
|
||||
}
|
||||
|
||||
// nsIBrowserDOMWindow::canClose implementation.
|
||||
// nsIBrowserDOMWindow.
|
||||
canClose() {
|
||||
debug("canClose");
|
||||
return false;
|
||||
|
@ -28,7 +28,7 @@ public class testEventDispatcher extends JavascriptBridgeTest implements BundleE
|
||||
private static final String JS_EVENT = "Robocop:TestJSEvent";
|
||||
private static final String JS_RESPONSE_EVENT = "Robocop:TestJSResponse";
|
||||
|
||||
private static final long WAIT_FOR_BUNDLE_EVENT_TIMEOUT_MILLIS = 20000; // 20 seconds
|
||||
private static final long WAIT_FOR_BUNDLE_EVENT_TIMEOUT_MILLIS = 40000; // 40 seconds
|
||||
|
||||
private boolean handledAsyncEvent;
|
||||
|
||||
@ -441,7 +441,7 @@ public class testEventDispatcher extends JavascriptBridgeTest implements BundleE
|
||||
continue;
|
||||
}
|
||||
|
||||
dispatchMessageForResponse(scope, responseEvent, "success", key, refBundle);
|
||||
dispatchMessageForResponse(scope, responseEvent, mode, key, refBundle);
|
||||
count++;
|
||||
|
||||
if (wait) {
|
||||
|
@ -363,8 +363,8 @@ SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel,
|
||||
accessTokenLevel = sandbox::USER_LOCKDOWN;
|
||||
initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
|
||||
delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_UNTRUSTED;
|
||||
} else if (aSandboxLevel >= 10) {
|
||||
jobLevel = sandbox::JOB_RESTRICTED;
|
||||
} else if (aSandboxLevel >= 4) {
|
||||
jobLevel = sandbox::JOB_LOCKDOWN;
|
||||
accessTokenLevel = sandbox::USER_LIMITED;
|
||||
initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
|
||||
delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import logging
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
@ -12,6 +13,7 @@ import sys
|
||||
from .. import GECKO
|
||||
from taskgraph.util.bbb_validation import valid_bbb_builders
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
base_path = os.path.join(GECKO, 'taskcluster', 'docs')
|
||||
|
||||
|
||||
@ -167,7 +169,7 @@ def verify_bbb_builders_valid(task, taskgraph, scratch_pad):
|
||||
if task.task.get('workerType') == 'buildbot-bridge':
|
||||
buildername = task.task['payload']['buildername']
|
||||
if buildername not in valid_builders:
|
||||
raise Exception(
|
||||
logger.warning(
|
||||
'{} uses an invalid buildbot buildername ("{}") '
|
||||
' - contact #releng for help'
|
||||
.format(task.label, buildername))
|
||||
|
Loading…
Reference in New Issue
Block a user