merge mozilla-central to autoland. r=merge a=merge

This commit is contained in:
Sebastian Hengst 2017-09-29 11:49:46 +02:00
commit 5a95ac34b4
68 changed files with 1386 additions and 900 deletions

View File

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

View File

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

View File

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

View File

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

View 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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -990,6 +990,7 @@ parent:
bool aCalledFromJS,
bool aPositionSpecified,
bool aSizeSpecified,
OptionalURIParams aURIToLoad,
nsCString aFeatures,
nsCString aBaseURI,
float aFullZoom,

View File

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

View File

@ -317,6 +317,8 @@ private:
StreamState mState;
DataSource& mDataSource;
bool mPrefillQuirk;
};
} // namespace mozilla

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -734,9 +734,6 @@ protected:
virtual void PausePainting() override;
virtual void ResumePainting() override;
void UpdateActivePointerState(mozilla::WidgetGUIEvent* aEvent);
//////////////////////////////////////////////////////////////////////////////
// Approximate frame visibility tracking implementation.
//////////////////////////////////////////////////////////////////////////////

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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