Merge inbound to central, a=merge

MozReview-Commit-ID: EI67EKp8ykS
This commit is contained in:
Wes Kocher 2017-05-19 15:14:19 -07:00
Родитель b3e139291b c0fe8b0e0e
Коммит 15edcfd962
46 изменённых файлов: 570 добавлений и 407 удалений

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

@ -268,13 +268,17 @@ menuitem.bookmark-item {
#main-window {
--urlbar-border-color: ThreeDShadow;
--urlbar-border-color-hover: var(--urlbar-border-color);
--urlbar-background-color: -moz-field;
}
#navigator-toolbox:-moz-lwtheme {
--urlbar-border-color: rgba(0,0,0,.3);
}
#urlbar {
/* override textbox[enablehistory="true"] styling: */
background-color: -moz-field;
}
%include ../shared/urlbar-searchbar.inc.css
%ifdef MOZ_PHOTON_THEME
@ -301,10 +305,6 @@ menuitem.bookmark-item {
border-color: Highlight;
}
#urlbar {
background-color: -moz-field;
}
#urlbar:-moz-lwtheme,
.searchbar-textbox:-moz-lwtheme {
background-color: rgba(255,255,255,.8);

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

@ -527,7 +527,6 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
#main-window {
--urlbar-border-color: hsla(240, 5%, 5%, .25);
--urlbar-border-color-hover: hsla(240, 5%, 5%, .35);
--urlbar-background-color: -moz-field;
}
#urlbar[focused="true"],

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

@ -8,7 +8,6 @@
.searchbar-textbox {
-moz-appearance: none;
background-clip: content-box;
background-color: var(--urlbar-background-color);
border: 1px solid var(--urlbar-border-color);
border-radius: var(--toolbarbutton-border-radius);
box-shadow: 0 1px 4px hsla(0, 0%, 0%, .05);

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

@ -670,7 +670,6 @@ toolbar[brighttext] #close-button {
#main-window:not(:-moz-lwtheme) {
--urlbar-border-color: hsla(240, 5%, 5%, .25);
--urlbar-border-color-hover: hsla(240, 5%, 5%, .35);
--urlbar-background-color: -moz-field;
}
}

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

@ -256,6 +256,7 @@ TimeoutManager::TimeoutManager(nsGlobalWindow& aWindow)
TimeoutManager::~TimeoutManager()
{
MOZ_DIAGNOSTIC_ASSERT(mWindow.AsInner()->InnerObjectsFreed());
MOZ_DIAGNOSTIC_ASSERT(!mThrottleTrackingTimeoutsTimer);
MOZ_LOG(gLog, LogLevel::Debug,
@ -1472,7 +1473,8 @@ TimeoutManager::OnDocumentLoaded()
void
TimeoutManager::MaybeStartThrottleTrackingTimout()
{
if (gTrackingTimeoutThrottlingDelay <= 0) {
if (gTrackingTimeoutThrottlingDelay <= 0 ||
mWindow.AsInner()->InnerObjectsFreed()) {
return;
}

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

@ -424,6 +424,10 @@ def DOMClass(descriptor):
hooks=NativePropertyHooks(descriptor))
def InstanceReservedSlots(descriptor):
return INSTANCE_RESERVED_SLOTS + descriptor.interface.totalMembersInSlots
class CGDOMJSClass(CGThing):
"""
Generate a DOMJSClass for a given descriptor
@ -438,7 +442,7 @@ class CGDOMJSClass(CGThing):
def define(self):
callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
objectMovedHook = OBJECT_MOVED_HOOK_NAME if self.descriptor.wrapperCache else 'nullptr'
slotCount = INSTANCE_RESERVED_SLOTS + self.descriptor.interface.totalMembersInSlots
slotCount = InstanceReservedSlots(self.descriptor)
classFlags = "JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | "
if self.descriptor.isGlobal():
classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS)"
@ -528,9 +532,10 @@ class CGDOMProxyJSClass(CGThing):
return ""
def define(self):
slotCount = InstanceReservedSlots(self.descriptor)
# We need one reserved slot (DOM_OBJECT_SLOT).
flags = ["JSCLASS_IS_DOMJSCLASS",
"JSCLASS_HAS_RESERVED_SLOTS(1)"]
"JSCLASS_HAS_RESERVED_SLOTS(%d)" % slotCount]
# We don't use an IDL annotation for JSCLASS_EMULATES_UNDEFINED because
# we don't want people ever adding that to any interface other than
# HTMLAllCollection. So just hardcode it here.
@ -12717,10 +12722,6 @@ class CGDescriptor(CGThing):
if descriptor.concrete:
if descriptor.proxy:
if descriptor.interface.totalMembersInSlots != 0:
raise TypeError("We can't have extra reserved slots for "
"proxy interface %s" %
descriptor.interface.identifier.name)
cgThings.append(CGGeneric(fill(
"""
static_assert(IsBaseOf<nsISupports, ${nativeType} >::value,
@ -12741,8 +12742,9 @@ class CGDescriptor(CGThing):
else:
cgThings.append(CGDOMJSClass(descriptor))
cgThings.append(CGGetJSClassMethod(descriptor))
if descriptor.interface.hasMembersInSlots():
cgThings.append(CGUpdateMemberSlotsMethod(descriptor))
if descriptor.interface.hasMembersInSlots():
cgThings.append(CGUpdateMemberSlotsMethod(descriptor))
if descriptor.isGlobal():
assert descriptor.wrapperCache

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

@ -1217,6 +1217,8 @@ public:
uint32_t Item(uint32_t, bool&) = delete;
uint32_t Length();
void LegacyCall(JS::Handle<JS::Value>);
int32_t CachedAttr();
int32_t StoreInSlotAttr();
};
class TestNamedGetterInterface : public nsISupports,

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

@ -1188,6 +1188,8 @@ interface TestIndexedGetterInterface {
getter long item(unsigned long idx);
readonly attribute unsigned long length;
legacycaller void();
[Cached, Pure] readonly attribute long cachedAttr;
[StoreInSlot, Pure] readonly attribute long storeInSlotAttr;
};
interface TestNamedGetterInterface {

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

@ -192,6 +192,10 @@ IPCBlobInputStream::Clone(nsIInputStream** aResult)
MOZ_ASSERT(mActor);
nsCOMPtr<nsIInputStream> stream = mActor->CreateStream();
if (!stream) {
return NS_ERROR_FAILURE;
}
stream.forget(aResult);
return NS_OK;
}

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

@ -13,19 +13,17 @@ namespace {
// This runnable is used in case the last stream is forgotten on the 'wrong'
// thread.
class DeleteRunnable final : public Runnable
class ShutdownRunnable final : public Runnable
{
public:
explicit DeleteRunnable(IPCBlobInputStreamChild* aActor)
explicit ShutdownRunnable(IPCBlobInputStreamChild* aActor)
: mActor(aActor)
{}
NS_IMETHOD
Run() override
{
if (mActor->IsAlive()) {
mActor->Send__delete__(mActor);
}
mActor->Shutdown();
return NS_OK;
}
@ -96,10 +94,29 @@ IPCBlobInputStreamChild::~IPCBlobInputStreamChild()
{}
void
IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason)
IPCBlobInputStreamChild::Shutdown()
{
MutexAutoLock lock(mMutex);
mActorAlive = false;
RefPtr<IPCBlobInputStreamChild> kungFuDeathGrip = this;
mPendingOperations.Clear();
if (mActorAlive) {
SendClose();
mActorAlive = false;
}
}
void
IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason)
{
{
MutexAutoLock lock(mMutex);
mActorAlive = false;
}
Shutdown();
}
bool
@ -114,6 +131,10 @@ IPCBlobInputStreamChild::CreateStream()
{
MutexAutoLock lock(mMutex);
if (!mActorAlive) {
return nullptr;
}
RefPtr<IPCBlobInputStream> stream = new IPCBlobInputStream(this);
mStreams.AppendElement(stream);
return stream.forget();
@ -124,7 +145,7 @@ IPCBlobInputStreamChild::ForgetStream(IPCBlobInputStream* aStream)
{
MOZ_ASSERT(aStream);
RefPtr<IPCBlobInputStreamChild> kungFoDeathGrip = this;
RefPtr<IPCBlobInputStreamChild> kungFuDeathGrip = this;
{
MutexAutoLock lock(mMutex);
@ -136,11 +157,11 @@ IPCBlobInputStreamChild::ForgetStream(IPCBlobInputStream* aStream)
}
if (mOwningThread == NS_GetCurrentThread()) {
Send__delete__(this);
Shutdown();
return;
}
RefPtr<DeleteRunnable> runnable = new DeleteRunnable(this);
RefPtr<ShutdownRunnable> runnable = new ShutdownRunnable(this);
mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
}
@ -149,6 +170,11 @@ IPCBlobInputStreamChild::StreamNeeded(IPCBlobInputStream* aStream,
nsIEventTarget* aEventTarget)
{
MutexAutoLock lock(mMutex);
if (!mActorAlive) {
return;
}
MOZ_ASSERT(mStreams.Contains(aStream));
PendingOperation* opt = mPendingOperations.AppendElement();
@ -175,6 +201,7 @@ IPCBlobInputStreamChild::RecvStreamReady(const OptionalIPCStream& aStream)
{
MutexAutoLock lock(mMutex);
MOZ_ASSERT(!mPendingOperations.IsEmpty());
MOZ_ASSERT(mActorAlive);
pendingStream = mPendingOperations[0].mStream;
eventTarget = mPendingOperations[0].mEventTarget;

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

@ -56,6 +56,9 @@ public:
mozilla::ipc::IPCResult
RecvStreamReady(const OptionalIPCStream& aStream) override;
void
Shutdown();
private:
~IPCBlobInputStreamChild();

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

@ -96,5 +96,14 @@ IPCBlobInputStreamParent::RecvStreamNeeded()
return IPC_OK();
}
mozilla::ipc::IPCResult
IPCBlobInputStreamParent::RecvClose()
{
MOZ_ASSERT(mContentManager || mPBackgroundManager);
Unused << Send__delete__(this);
return IPC_OK();
}
} // namespace dom
} // namespace mozilla

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

@ -44,6 +44,9 @@ public:
mozilla::ipc::IPCResult
RecvStreamNeeded() override;
mozilla::ipc::IPCResult
RecvClose() override;
private:
IPCBlobInputStreamParent(const nsID& aID, uint64_t aSize,
nsIContentParent* aManager);

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

@ -20,11 +20,11 @@ protocol PIPCBlobInputStream
parent:
async StreamNeeded();
async __delete__();
async Close();
child:
async StreamReady(OptionalIPCStream aStream);
async __delete__();
};
} // namespace dom

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

@ -44,6 +44,11 @@ public:
bool Selected() const;
bool DefaultSelected() const;
void SetSelectedChanged(bool aValue)
{
mSelectedChanged = aValue;
}
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
int32_t aModType) const override;

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

@ -1072,7 +1072,7 @@ HTMLSelectElement::SetOptionsSelectedByIndex(int32_t aStartIndex,
}
// Make sure something is selected unless we were set to -1 (none)
if (optionsDeselected && aStartIndex != -1) {
if (optionsDeselected && aStartIndex != -1 && !(aOptionsMask & NO_RESELECT)) {
optionsSelected =
CheckSelectSomething(aOptionsMask & NOTIFY) || optionsSelected;
}
@ -1648,13 +1648,14 @@ HTMLSelectElement::Reset()
// Reset the option to its default value
//
uint32_t mask = SET_DISABLED | NOTIFY;
uint32_t mask = SET_DISABLED | NOTIFY | NO_RESELECT;
if (option->DefaultSelected()) {
mask |= IS_SELECTED;
numSelected++;
}
SetOptionsSelectedByIndex(i, i, mask);
option->SetSelectedChanged(false);
}
}

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

@ -134,12 +134,16 @@ public:
* (for JavaScript)
*
* NOTIFY whether to notify frames and such
*
* NO_RESELECT no need to select something after an option is deselected
* (for reset)
*/
enum OptionType {
IS_SELECTED = 1 << 0,
CLEAR_ALL = 1 << 1,
SET_DISABLED = 1 << 2,
NOTIFY = 1 << 3
NOTIFY = 1 << 3,
NO_RESELECT = 1 << 4
};
using nsIConstraintValidation::GetValidationMessage;

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

@ -89,7 +89,7 @@ SessionStorageManager::GetStorage(mozIDOMWindow* aWindow,
nsAutoCString originKey;
nsAutoCString originAttributes;
nsresult rv = GenerateOriginKey(aPrincipal, originAttributes, originKey);
if (NS_WARN_IF(NS_FAILED(rv))) {
if (NS_FAILED(rv)) {
return rv;
}
@ -128,7 +128,7 @@ SessionStorageManager::CloneStorage(nsIDOMStorage* aStorage)
nsAutoCString originAttributes;
nsresult rv = GenerateOriginKey(storage->Principal(), originAttributes,
originKey);
if (NS_WARN_IF(NS_FAILED(rv))) {
if (NS_FAILED(rv)) {
return rv;
}

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

@ -67,6 +67,7 @@ AndroidDynamicToolbarAnimator::AndroidDynamicToolbarAnimator()
, mCompositorReceivedFirstPaint(false)
, mCompositorWaitForPageResize(false)
, mCompositorToolbarShowRequested(false)
, mCompositorSendResponseForSnapshotUpdate(false)
, mCompositorAnimationStyle(eAnimate)
, mCompositorMaxToolbarHeight(0)
, mCompositorToolbarHeight(0)
@ -270,30 +271,6 @@ AndroidDynamicToolbarAnimator::GetCompositionHeight() const
return mCompositorCompositionSize.height;
}
bool
AndroidDynamicToolbarAnimator::SetCompositionSize(ScreenIntSize aSize)
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (mCompositorCompositionSize == aSize) {
return false;
}
ScreenIntSize prevSize = mCompositorCompositionSize;
mCompositorCompositionSize = aSize;
// The width has changed so the static snapshot needs to be updated
if ((prevSize.width != aSize.width) && (mToolbarState != eToolbarVisible)) {
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
}
if (prevSize.height != aSize.height) {
UpdateControllerCompositionHeight(aSize.height);
UpdateFixedLayerMargins();
}
return true;
}
void
AndroidDynamicToolbarAnimator::SetScrollingRootContent()
{
@ -318,8 +295,8 @@ AndroidDynamicToolbarAnimator::ToolbarAnimatorMessageFromUI(int32_t aMessage)
StartCompositorAnimation(mCompositorAnimationDirection, mCompositorAnimationStyle, mCompositorToolbarHeight, mCompositorWaitForPageResize);
}
} else {
// The compositor is already animating the toolbar so no need to defer.
mCompositorAnimationDeferred = false;
// Animation already running so just make sure it is going the right direction.
StartCompositorAnimation(MOVE_TOOLBAR_UP, mCompositorAnimationStyle, mCompositorToolbarHeight, mCompositorWaitForPageResize);
}
break;
case TOOLBAR_VISIBLE:
@ -470,6 +447,35 @@ AndroidDynamicToolbarAnimator::UpdateRootFrameMetrics(const FrameMetrics& aMetri
UpdateFrameMetrics(scrollOffset, scale, cssPageRect);
}
void
AndroidDynamicToolbarAnimator::MaybeUpdateCompositionSizeAndRootFrameMetrics(const FrameMetrics& aMetrics)
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
CSSToScreenScale scale = ViewTargetAs<ScreenPixel>(aMetrics.GetZoom().ToScaleFactor(),
PixelCastJustification::ScreenIsParentLayerForRoot);
ScreenIntSize size = ScreenIntSize::Round(aMetrics.GetRootCompositionSize() * scale);
if (mCompositorCompositionSize == size) {
return;
}
ScreenIntSize prevSize = mCompositorCompositionSize;
mCompositorCompositionSize = size;
// The width has changed so the static snapshot needs to be updated
if ((prevSize.width != size.width) && (mToolbarState == eToolbarUnlocked)) {
// No need to set mCompositorSendResponseForSnapshotUpdate. If it is already true we don't want to change it.
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
}
if (prevSize.height != size.height) {
UpdateControllerCompositionHeight(size.height);
UpdateFixedLayerMargins();
}
UpdateRootFrameMetrics(aMetrics);
}
// Layers updates are need by Robocop test which enables them
void
AndroidDynamicToolbarAnimator::EnableLayersUpdateNotifications(bool aEnable)
@ -525,7 +531,8 @@ AndroidDynamicToolbarAnimator::GetToolbarEffect(CompositorOGL* gl)
uiController->DeallocShmem(mCompositorToolbarPixels.ref());
mCompositorToolbarPixels.reset();
// Send notification that texture is ready after the current composition has completed.
if (mCompositorToolbarTexture) {
if (mCompositorToolbarTexture && mCompositorSendResponseForSnapshotUpdate) {
mCompositorSendResponseForSnapshotUpdate = false;
CompositorThreadHolder::Loop()->PostTask(NewRunnableMethod(this, &AndroidDynamicToolbarAnimator::PostToolbarReady));
}
}
@ -574,6 +581,7 @@ AndroidDynamicToolbarAnimator::ProcessTouchDelta(StaticToolbarState aCurrentTool
if (aCurrentToolbarState == eToolbarVisible) {
if (tryingToHideToolbar && (mControllerState != eUnlockPending)) {
mCompositorSendResponseForSnapshotUpdate = true;
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
mControllerState = eUnlockPending;
}
@ -796,7 +804,7 @@ AndroidDynamicToolbarAnimator::UpdateFixedLayerMargins()
}
AsyncCompositionManager* manager = parent->GetCompositionManager(nullptr);
if (manager) {
if (mToolbarState == eToolbarAnimating) {
if ((mToolbarState == eToolbarAnimating) && mCompositorAnimationStarted) {
manager->SetFixedLayerMargins(mCompositorToolbarHeight, 0);
} else {
manager->SetFixedLayerMargins(0, GetFixedLayerMarginsBottom());
@ -851,6 +859,7 @@ AndroidDynamicToolbarAnimator::StartCompositorAnimation(int32_t aDirection, Anim
// and defer animation until it has been unlocked
if ((initialToolbarState != eToolbarUnlocked) && (initialToolbarState != eToolbarAnimating)) {
mCompositorAnimationDeferred = true;
mCompositorSendResponseForSnapshotUpdate = true;
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
} else {
// Toolbar is either unlocked or already animating so animation may begin immediately
@ -859,13 +868,14 @@ AndroidDynamicToolbarAnimator::StartCompositorAnimation(int32_t aDirection, Anim
if (initialToolbarState != eToolbarAnimating) {
mCompositorAnimationStarted = false;
}
// Let the controller know we starting an animation so it may clear the AnimationStartPending flag.
// Let the controller know we are starting an animation so it may clear the AnimationStartPending flag.
NotifyControllerAnimationStarted();
CompositorBridgeParent* parent = CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(mRootLayerTreeId);
if (parent) {
mCompositorAnimationStartTimeStamp = parent->GetAPZCTreeManager()->GetFrameTime();
}
// Only reset the time stamp and start compositor animation if not already animating.
if (initialToolbarState != eToolbarAnimating) {
CompositorBridgeParent* parent = CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(mRootLayerTreeId);
if (parent) {
mCompositorAnimationStartTimeStamp = parent->GetAPZCTreeManager()->GetFrameTime();
}
// Kick the compositor to start the animation if we aren't already animating.
RequestComposite();
}

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

@ -81,8 +81,6 @@ public:
// shown, the content may extend beyond the bottom of the surface until the toolbar is completely
// visible or hidden.
ScreenIntCoord GetCompositionHeight() const;
// Returns true if the composition size has changed from the last time it was set.
bool SetCompositionSize(ScreenIntSize aSize);
// Called to signal that root content is being scrolled. This prevents sub scroll frames from
// affecting the toolbar when being scrolled up. The idea is a scrolling down will always
// show the toolbar while scrolling up will only hide the toolbar if it is the root content
@ -95,6 +93,8 @@ public:
void FirstPaint();
// Called whenever the root document's FrameMetrics have reached a steady state.
void UpdateRootFrameMetrics(const FrameMetrics& aMetrics);
// Only update the frame metrics if the root composition size has changed
void MaybeUpdateCompositionSizeAndRootFrameMetrics(const FrameMetrics& aMetrics);
// When aEnable is set to true, it informs the animator that the UI thread expects to
// be notified when the layer tree has been updated. Enabled currently by robocop tests.
void EnableLayersUpdateNotifications(bool aEnable);
@ -225,7 +225,8 @@ protected:
bool mCompositorReceivedFirstPaint; // Set to true when a first paint occurs. Used by toolbar animator to detect a new page load.
bool mCompositorWaitForPageResize; // Set to true if the bottom of the page has been reached and the toolbar animator should wait for the page to resize before ending animation.
bool mCompositorToolbarShowRequested; // Set to true if the animator has already requested the real toolbar chrome be shown
AnimationStyle mCompositorAnimationStyle; // Set to true when the snap should be immediately hidden or shown in the animation update
bool mCompositorSendResponseForSnapshotUpdate; // Set to true when a message should be sent after a static toolbar snapshot update
AnimationStyle mCompositorAnimationStyle; // Set to true when the snapshot should be immediately hidden or shown in the animation update
ScreenIntCoord mCompositorMaxToolbarHeight; // Should contain the same value as mControllerMaxToolbarHeight
ScreenIntCoord mCompositorToolbarHeight; // This value is only updated by the compositor thread when the mToolbarState == ToolbarAnimating
ScreenIntCoord mCompositorSurfaceHeight; // Current height of the render surface

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

@ -3477,12 +3477,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
if (APZCTreeManager* manager = GetApzcTreeManager()) {
AndroidDynamicToolbarAnimator* animator = manager->GetAndroidDynamicToolbarAnimator();
MOZ_ASSERT(animator);
CSSToScreenScale scale = ViewTargetAs<ScreenPixel>(aLayerMetrics.GetZoom().ToScaleFactor(),
PixelCastJustification::ScreenIsParentLayerForRoot);
ScreenIntSize size = ScreenIntSize::Round(aLayerMetrics.GetRootCompositionSize() * scale);
if (animator->SetCompositionSize(size)) {
animator->UpdateRootFrameMetrics(aLayerMetrics);
}
animator->MaybeUpdateCompositionSizeAndRootFrameMetrics(aLayerMetrics);
}
}
#endif

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

@ -945,23 +945,24 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
if (*aOutFoundRoot) {
mRootScrollableId = metrics.GetScrollId();
Compositor* compositor = mLayerManager->GetCompositor();
if (mIsFirstPaint) {
if (CompositorBridgeParent* bridge = compositor->GetCompositorBridgeParent()) {
AndroidDynamicToolbarAnimator* animator = bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator();
MOZ_ASSERT(animator);
if (CompositorBridgeParent* bridge = compositor->GetCompositorBridgeParent()) {
AndroidDynamicToolbarAnimator* animator = bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator();
MOZ_ASSERT(animator);
if (mIsFirstPaint) {
animator->UpdateRootFrameMetrics(metrics);
animator->FirstPaint();
mIsFirstPaint = false;
}
}
if (mLayersUpdated) {
if (CompositorBridgeParent* bridge = compositor->GetCompositorBridgeParent()) {
AndroidDynamicToolbarAnimator* animator = bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator();
MOZ_ASSERT(animator);
if (mLayersUpdated) {
animator->NotifyLayersUpdated();
mLayersUpdated = false;
}
// If this is not actually the root content then the animator is not getting updated in AsyncPanZoomController::NotifyLayersUpdated
// because the root content document is not scrollable. So update it here so it knows if the root composition size has changed.
if (!metrics.IsRootContent()) {
animator->MaybeUpdateCompositionSizeAndRootFrameMetrics(metrics);
}
mLayersUpdated = false;
}
mIsFirstPaint = false;
fixedLayerMargins = mFixedLayerMargins;
}
}

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

@ -81,9 +81,9 @@ public:
class Record {
public:
Record() {
explicit Record(TimeStamp aStart = TimeStamp()) {
if (gfxPrefs::LayersDrawFPS()) {
mStart = TimeStamp::Now();
mStart = aStart.IsNull() ? TimeStamp::Now() : aStart;
}
}
bool Recording() const {

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

@ -919,7 +919,7 @@ LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion, const nsIntRegi
// Render our layers.
{
Diagnostics::Record record;
Diagnostics::Record record(mRenderStartTime);
RootLayer()->Prepare(ViewAs<RenderTargetPixel>(clipRect, PixelCastJustification::RenderTargetIsParentLayerForRoot));
if (record.Recording()) {
mDiagnostics->RecordPrepareTime(record.Duration());

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

@ -569,11 +569,14 @@ BackgroundChildImpl::DeallocPGamepadTestChannelChild(PGamepadTestChannelChild* a
void
BackgroundChildImpl::OnChannelReceivedMessage(const Message& aMsg)
{
// Telemetry collection temporarily disabled in bug 1366156.
#if 0
if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) {
// Not really necessary to look at the message payload, it will be
// <0.5ms away from TimeStamp::Now()
SchedulerGroup::MarkVsyncReceived();
}
#endif
}
#endif

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

@ -6,6 +6,7 @@
#include "builtin/TestingFunctions.h"
#include "mozilla/Atomics.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/Move.h"
#include "mozilla/Sprintf.h"
@ -67,11 +68,11 @@ using mozilla::Move;
// If fuzzingSafe is set, remove functionality that could cause problems with
// fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE.
static bool fuzzingSafe = false;
static mozilla::Atomic<bool> fuzzingSafe(false);
// If disableOOMFunctions is set, disable functionality that causes artificial
// OOM conditions.
static bool disableOOMFunctions = false;
static mozilla::Atomic<bool> disableOOMFunctions(false);
static bool
EnvVarIsDefined(const char* name)

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

@ -49,6 +49,7 @@
# | E | | E'|
# +---+ +---+
import re
import sys
import collections
@ -174,52 +175,56 @@ AllPhaseKinds = findAllPhaseKinds()
# one parent.
class Phase:
def __init__(self, phaseKind, parent, depth):
def __init__(self, phaseKind, parent):
self.phaseKind = phaseKind
self.parent = parent
self.depth = depth
self.depth = parent.depth + 1 if parent else 0
self.children = []
self.nextSibling = None
self.nextInPhaseKind = None
self.path = re.sub(r'\W+', '_', phaseKind.name.lower())
if parent is not None:
self.path = parent.path + '.' + self.path
def expandPhases():
phases = []
phasesForPhase = collections.defaultdict(list)
phasesForKind = collections.defaultdict(list)
def traverse(phaseKind, parent, depth):
ep = Phase(phaseKind, parent, depth)
def traverse(phaseKind, parent):
ep = Phase(phaseKind, parent)
phases.append(ep)
# Update list of expanded phases for this phase kind.
if phasesForPhase[phaseKind]:
phasesForPhase[phaseKind][-1].nextInPhaseKind = ep
phasesForPhase[phaseKind].append(ep)
if phasesForKind[phaseKind]:
phasesForKind[phaseKind][-1].nextInPhaseKind = ep
phasesForKind[phaseKind].append(ep)
# Recurse over children.
for child in phaseKind.children:
child_ep = traverse(child, ep, depth + 1)
child_ep = traverse(child, ep)
if ep.children:
ep.children[-1].nextSibling = child_ep
ep.children.append(child_ep)
return ep
for phaseKind in PhaseKindGraphRoots:
traverse(phaseKind, None, 0)
traverse(phaseKind, None)
return phases, phasesForPhase
return phases, phasesForKind
AllPhases, PhasesForPhaseKind = expandPhases()
# Name expanded phases based on phase kind name and index if there are
# multiple expanded phases corresponding to a single phase kind.
# Name phases based on phase kind name and index if there are multiple phases
# corresponding to a single phase kind.
for phaseKind in AllPhaseKinds:
phases = PhasesForPhaseKind[phaseKind]
if len(phases) == 1:
phases[0].name = "%s" % phaseKind.name
else:
for index, xphase in enumerate(phases):
xphase.name = "%s_%d" % (phaseKind.name, index + 1)
for index, phase in enumerate(phases):
phase.name = "%s_%d" % (phaseKind.name, index + 1)
# Generate code.
@ -250,13 +255,13 @@ def generateHeader(out):
#
# Generate Phase enum.
#
expandedPhaseNames = map(lambda xphase: xphase.name, AllPhases)
phaseNames = map(lambda phase: phase.name, AllPhases)
extraPhases = [
"NONE = LIMIT",
"EXPLICIT_SUSPENSION = LIMIT",
"IMPLICIT_SUSPENSION"
]
writeEnumClass(out, "Phase", "uint8_t", expandedPhaseNames, extraPhases)
writeEnumClass(out, "Phase", "uint8_t", phaseNames, extraPhases)
def generateCpp(out):
#
@ -264,29 +269,30 @@ def generateCpp(out):
#
out.write("static const PhaseKindTable phaseKinds = {\n")
for phaseKind in AllPhaseKinds:
xPhase = PhasesForPhaseKind[phaseKind][0]
phase = PhasesForPhaseKind[phaseKind][0]
out.write(" /* PhaseKind::%s */ PhaseKindInfo { Phase::%s, %d },\n" %
(phaseKind.name, xPhase.name, phaseKind.bucket))
(phaseKind.name, phase.name, phaseKind.bucket))
out.write("};\n")
out.write("\n")
#
# Generate the PhaseInfo tree.
#
def name(xphase):
return "Phase::" + xphase.name if xphase else "Phase::NONE"
def name(phase):
return "Phase::" + phase.name if phase else "Phase::NONE"
out.write("static const PhaseTable phases = {\n")
for xphase in AllPhases:
firstChild = xphase.children[0] if xphase.children else None
phaseKind = xphase.phaseKind
out.write(" /* %s */ PhaseInfo { %s, %s, %s, %s, PhaseKind::%s, %d, \"%s\" },\n" %
(name(xphase),
name(xphase.parent),
for phase in AllPhases:
firstChild = phase.children[0] if phase.children else None
phaseKind = phase.phaseKind
out.write(" /* %s */ PhaseInfo { %s, %s, %s, %s, PhaseKind::%s, %d, \"%s\", \"%s\" },\n" %
(name(phase),
name(phase.parent),
name(firstChild),
name(xphase.nextSibling),
name(xphase.nextInPhaseKind),
name(phase.nextSibling),
name(phase.nextInPhaseKind),
phaseKind.name,
xphase.depth,
phaseKind.descr))
phase.depth,
phaseKind.descr,
phase.path))
out.write("};\n")

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

@ -107,12 +107,13 @@ struct PhaseInfo
PhaseKind phaseKind;
uint8_t depth;
const char* name;
const char* path;
};
// A table of ExpandePhaseInfo indexed by Phase.
// A table of PhaseInfo indexed by Phase.
using PhaseTable = EnumeratedArray<Phase, Phase::LIMIT, PhaseInfo>;
// A table of PhaseKindInfo indexed by Phase.
// A table of PhaseKindInfo indexed by PhaseKind.
using PhaseKindTable = EnumeratedArray<PhaseKind, PhaseKind::LIMIT, PhaseKindInfo>;
#include "gc/StatsPhasesGenerated.cpp"
@ -132,8 +133,8 @@ Statistics::currentPhase() const
PhaseKind
Statistics::currentPhaseKind() const
{
// Public API to get the current phase. Return the current phase,
// suppressing the synthetic PhaseKind::MUTATOR phase.
// Public API to get the current phase kind, suppressing the synthetic
// PhaseKind::MUTATOR phase.
Phase phase = currentPhase();
MOZ_ASSERT_IF(phase == Phase::MUTATOR, phaseNestingDepth == 1);
@ -621,35 +622,13 @@ Statistics::formatJsonSliceDescription(unsigned i, const SliceData& slice, JSONP
json.property("end_timestamp", slice.end - originTime, JSONPrinter::SECONDS);
}
static UniqueChars
SanitizeJsonKey(const char* const buffer)
{
char* mut = strdup(buffer);
if (!mut)
return UniqueChars(nullptr);
char* c = mut;
while (*c) {
if (!isalpha(*c))
*c = '_';
else if (isupper(*c))
*c = tolower(*c);
++c;
}
return UniqueChars(mut);
}
void
Statistics::formatJsonPhaseTimes(const PhaseTimeTable& phaseTimes, JSONPrinter& json) const
{
for (auto phase : AllPhases()) {
UniqueChars name = SanitizeJsonKey(phases[phase].name);
if (!name)
json.outOfMemory();
TimeDuration ownTime = phaseTimes[phase];
if (!ownTime.IsZero())
json.property(name.get(), ownTime, JSONPrinter::MILLISECONDS);
json.property(phases[phase].path, ownTime, JSONPrinter::MILLISECONDS);
}
}

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

@ -11437,6 +11437,11 @@ CodeGenerator::visitGetDOMProperty(LGetDOMProperty* ins)
// It's a bit annoying to redo these slot calculations, which duplcate
// LSlots and a few other things like that, but I'm not sure there's a
// way to reuse those here.
//
// If this ever gets fixed to work with proxies (by not assuming that
// reserved slot indices, which is what domMemberSlotIndex() returns,
// match fixed slot indices), we can reenable MGetDOMProperty for
// proxies in IonBuilder.
if (slot < NativeObject::MAX_FIXED_SLOTS) {
masm.loadValue(Address(ObjectReg, NativeObject::getFixedSlotOffset(slot)),
JSReturnOperand);
@ -11509,6 +11514,11 @@ CodeGenerator::visitGetDOMMemberV(LGetDOMMemberV* ins)
// require us to have MGetDOMMember inherit from MLoadFixedSlot, and then
// we'd have to duplicate a bunch of stuff we now get for free from
// MGetDOMProperty.
//
// If this ever gets fixed to work with proxies (by not assuming that
// reserved slot indices, which is what domMemberSlotIndex() returns,
// match fixed slot indices), we can reenable MGetDOMMember for
// proxies in IonBuilder.
Register object = ToRegister(ins->object());
size_t slot = ins->mir()->domMemberSlotIndex();
ValueOperand result = GetValueOutput(ins);
@ -11524,6 +11534,11 @@ CodeGenerator::visitGetDOMMemberT(LGetDOMMemberT* ins)
// require us to have MGetDOMMember inherit from MLoadFixedSlot, and then
// we'd have to duplicate a bunch of stuff we now get for free from
// MGetDOMProperty.
//
// If this ever gets fixed to work with proxies (by not assuming that
// reserved slot indices, which is what domMemberSlotIndex() returns,
// match fixed slot indices), we can reenable MGetDOMMember for
// proxies in IonBuilder.
Register object = ToRegister(ins->object());
size_t slot = ins->mir()->domMemberSlotIndex();
AnyRegister result = ToAnyRegister(ins->getDef(0));

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

@ -10881,38 +10881,47 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
if (isDOM) {
const JSJitInfo* jitinfo = commonGetter->jitInfo();
MInstruction* get;
if (jitinfo->isAlwaysInSlot) {
// If our object is a singleton and we know the property is
// constant (which is true if and only if the get doesn't alias
// anything), we can just read the slot here and use that constant.
JSObject* singleton = objTypes->maybeSingleton();
if (singleton && jitinfo->aliasSet() == JSJitInfo::AliasNone) {
size_t slot = jitinfo->slotIndex;
*emitted = true;
pushConstant(GetReservedSlot(singleton, slot));
return Ok();
// We don't support MGetDOMProperty/MGetDOMMember on things that might
// be proxies when the value might be in a slot, because the
// CodeGenerator code for LGetDOMProperty/LGetDOMMember doesn't handle
// that case correctly.
if ((!jitinfo->isAlwaysInSlot && !jitinfo->isLazilyCachedInSlot) ||
!objTypes->maybeProxy(constraints())) {
MInstruction* get;
if (jitinfo->isAlwaysInSlot) {
// If our object is a singleton and we know the property is
// constant (which is true if and only if the get doesn't alias
// anything), we can just read the slot here and use that
// constant.
JSObject* singleton = objTypes->maybeSingleton();
if (singleton && jitinfo->aliasSet() == JSJitInfo::AliasNone) {
size_t slot = jitinfo->slotIndex;
*emitted = true;
pushConstant(GetReservedSlot(singleton, slot));
return Ok();
}
// We can't use MLoadFixedSlot here because it might not have
// the right aliasing behavior; we want to alias DOM setters as
// needed.
get = MGetDOMMember::New(alloc(), jitinfo, obj, guard, globalGuard);
} else {
get = MGetDOMProperty::New(alloc(), jitinfo, obj, guard, globalGuard);
}
if (!get)
return abort(AbortReason::Alloc);
current->add(get);
current->push(get);
// We can't use MLoadFixedSlot here because it might not have the
// right aliasing behavior; we want to alias DOM setters as needed.
get = MGetDOMMember::New(alloc(), jitinfo, obj, guard, globalGuard);
} else {
get = MGetDOMProperty::New(alloc(), jitinfo, obj, guard, globalGuard);
if (get->isEffectful())
MOZ_TRY(resumeAfter(get));
MOZ_TRY(pushDOMTypeBarrier(get, types, commonGetter));
trackOptimizationOutcome(TrackedOutcome::DOM);
*emitted = true;
return Ok();
}
if (!get)
return abort(AbortReason::Alloc);
current->add(get);
current->push(get);
if (get->isEffectful())
MOZ_TRY(resumeAfter(get));
MOZ_TRY(pushDOMTypeBarrier(get, types, commonGetter));
trackOptimizationOutcome(TrackedOutcome::DOM);
*emitted = true;
return Ok();
}
// Don't call the getter with a primitive value.

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

@ -45,9 +45,6 @@
using js::shell::RCFile;
static RCFile** gErrFilePtr = nullptr;
static RCFile** gOutFilePtr = nullptr;
namespace js {
namespace shell {
@ -555,13 +552,15 @@ Redirect(JSContext* cx, const CallArgs& args, RCFile** outFile)
static bool
osfile_redirectOutput(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
return Redirect(cx, args, gOutFilePtr);
ShellContext* scx = GetShellContext(cx);
return Redirect(cx, args, scx->outFilePtr);
}
static bool
osfile_redirectError(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
return Redirect(cx, args, gErrFilePtr);
ShellContext* scx = GetShellContext(cx);
return Redirect(cx, args, scx->errFilePtr);
}
static bool
@ -1010,8 +1009,9 @@ DefineOS(JSContext* cx, HandleObject global,
if (!GenerateInterfaceHelp(cx, obj, "os"))
return false;
gOutFilePtr = shellOut;
gErrFilePtr = shellErr;
ShellContext* scx = GetShellContext(cx);
scx->outFilePtr = shellOut;
scx->errFilePtr = shellErr;
// For backwards compatibility, expose various os.file.* functions as
// direct methods on the global.

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

@ -113,6 +113,8 @@ using namespace js;
using namespace js::cli;
using namespace js::shell;
using js::shell::RCFile;
using mozilla::ArrayLength;
using mozilla::Atomic;
using mozilla::MakeScopeExit;
@ -152,189 +154,97 @@ static const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(1800.
// SharedArrayBuffer and Atomics are enabled by default (tracking Firefox).
#define SHARED_MEMORY_DEFAULT 1
// Some platform hooks must be implemented for single-step profiling.
#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS64)
# define SINGLESTEP_PROFILING
#endif
enum class ScriptKind
bool
OffThreadState::startIfIdle(JSContext* cx, ScriptKind kind, ScopedJSFreePtr<char16_t>& newSource)
{
Script,
DecodeScript,
Module
};
AutoLockMonitor alm(monitor);
if (state != IDLE)
return false;
class OffThreadState {
enum State {
IDLE, /* ready to work; no token, no source */
COMPILING, /* working; no token, have source */
DONE /* compilation done: have token and source */
};
MOZ_ASSERT(!token);
public:
OffThreadState()
: monitor(mutexid::ShellOffThreadState),
state(IDLE),
token(),
source(nullptr)
{ }
source = newSource.forget();
bool startIfIdle(JSContext* cx, ScriptKind kind,
ScopedJSFreePtr<char16_t>& newSource)
{
AutoLockMonitor alm(monitor);
if (state != IDLE)
return false;
scriptKind = kind;
state = COMPILING;
return true;
}
MOZ_ASSERT(!token);
source = newSource.forget();
scriptKind = kind;
state = COMPILING;
return true;
}
bool startIfIdle(JSContext* cx, ScriptKind kind,
JS::TranscodeBuffer&& newXdr)
{
AutoLockMonitor alm(monitor);
if (state != IDLE)
return false;
MOZ_ASSERT(!token);
xdr = mozilla::Move(newXdr);
scriptKind = kind;
state = COMPILING;
return true;
}
void abandon(JSContext* cx) {
AutoLockMonitor alm(monitor);
MOZ_ASSERT(state == COMPILING);
MOZ_ASSERT(!token);
MOZ_ASSERT(source || !xdr.empty());
if (source)
js_free(source);
source = nullptr;
xdr.clearAndFree();
state = IDLE;
}
void markDone(void* newToken) {
AutoLockMonitor alm(monitor);
MOZ_ASSERT(state == COMPILING);
MOZ_ASSERT(!token);
MOZ_ASSERT(source || !xdr.empty());
MOZ_ASSERT(newToken);
token = newToken;
state = DONE;
alm.notify();
}
void* waitUntilDone(JSContext* cx, ScriptKind kind) {
AutoLockMonitor alm(monitor);
if (state == IDLE || scriptKind != kind)
return nullptr;
if (state == COMPILING) {
while (state != DONE)
alm.wait();
}
MOZ_ASSERT(source || !xdr.empty());
if (source)
js_free(source);
source = nullptr;
xdr.clearAndFree();
MOZ_ASSERT(token);
void* holdToken = token;
token = nullptr;
state = IDLE;
return holdToken;
}
JS::TranscodeBuffer& xdrBuffer() { return xdr; }
private:
Monitor monitor;
ScriptKind scriptKind;
State state;
void* token;
char16_t* source;
JS::TranscodeBuffer xdr;
};
#ifdef SINGLESTEP_PROFILING
typedef Vector<char16_t, 0, SystemAllocPolicy> StackChars;
#endif
class NonshrinkingGCObjectVector : public GCVector<JSObject*, 0, SystemAllocPolicy>
bool
OffThreadState::startIfIdle(JSContext* cx, ScriptKind kind, JS::TranscodeBuffer&& newXdr)
{
public:
void sweep() {
for (uint32_t i = 0; i < this->length(); i++) {
if (JS::GCPolicy<JSObject*>::needsSweep(&(*this)[i]))
(*this)[i] = nullptr;
}
}
};
AutoLockMonitor alm(monitor);
if (state != IDLE)
return false;
using MarkBitObservers = JS::WeakCache<NonshrinkingGCObjectVector>;
MOZ_ASSERT(!token);
xdr = mozilla::Move(newXdr);
scriptKind = kind;
state = COMPILING;
return true;
}
void
OffThreadState::abandon(JSContext* cx)
{
AutoLockMonitor alm(monitor);
MOZ_ASSERT(state == COMPILING);
MOZ_ASSERT(!token);
MOZ_ASSERT(source || !xdr.empty());
if (source)
js_free(source);
source = nullptr;
xdr.clearAndFree();
state = IDLE;
}
void
OffThreadState::markDone(void* newToken)
{
AutoLockMonitor alm(monitor);
MOZ_ASSERT(state == COMPILING);
MOZ_ASSERT(!token);
MOZ_ASSERT(source || !xdr.empty());
MOZ_ASSERT(newToken);
token = newToken;
state = DONE;
alm.notify();
}
void*
OffThreadState::waitUntilDone(JSContext* cx, ScriptKind kind)
{
AutoLockMonitor alm(monitor);
if (state == IDLE || scriptKind != kind)
return nullptr;
if (state == COMPILING) {
while (state != DONE)
alm.wait();
}
MOZ_ASSERT(source || !xdr.empty());
if (source)
js_free(source);
source = nullptr;
xdr.clearAndFree();
MOZ_ASSERT(token);
void* holdToken = token;
token = nullptr;
state = IDLE;
return holdToken;
}
struct ShellCompartmentPrivate {
JS::Heap<JSObject*> grayRoot;
};
// Per-context shell state.
struct ShellContext
{
explicit ShellContext(JSContext* cx);
bool isWorker;
double timeoutInterval;
double startTime;
Atomic<bool> serviceInterrupt;
Atomic<bool> haveInterruptFunc;
JS::PersistentRootedValue interruptFunc;
bool lastWarningEnabled;
JS::PersistentRootedValue lastWarning;
JS::PersistentRootedValue promiseRejectionTrackerCallback;
#ifdef SINGLESTEP_PROFILING
Vector<StackChars, 0, SystemAllocPolicy> stacks;
#endif
/*
* Watchdog thread state.
*/
Mutex watchdogLock;
ConditionVariable watchdogWakeup;
Maybe<Thread> watchdogThread;
Maybe<TimeStamp> watchdogTimeout;
ConditionVariable sleepWakeup;
int exitCode;
bool quitting;
UniqueChars readLineBuf;
size_t readLineBufPos;
static const uint32_t GeckoProfilingMaxStackSize = 1000;
ProfileEntry geckoProfilingStack[GeckoProfilingMaxStackSize];
mozilla::Atomic<uint32_t> geckoProfilingStackSize;
OffThreadState offThreadState;
UniqueChars moduleLoadPath;
UniquePtr<MarkBitObservers> markObservers;
};
struct MOZ_STACK_CLASS EnvironmentPreparer : public js::ScriptEnvironmentPreparer {
JSContext* cx;
explicit EnvironmentPreparer(JSContext* cx)
@ -476,11 +386,13 @@ ShellContext::ShellContext(JSContext* cx)
exitCode(0),
quitting(false),
readLineBufPos(0),
errFilePtr(nullptr),
outFilePtr(nullptr),
geckoProfilingStackSize(0)
{}
static ShellContext*
GetShellContext(JSContext* cx)
ShellContext*
js::shell::GetShellContext(JSContext* cx)
{
ShellContext* sc = static_cast<ShellContext*>(JS_GetContextPrivate(cx));
MOZ_ASSERT(sc);

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

@ -7,8 +7,25 @@
#ifndef jsshell_js_h
#define jsshell_js_h
#include "mozilla/Atomics.h"
#include "mozilla/Maybe.h"
#include "mozilla/TimeStamp.h"
#include "jsapi.h"
#include "js/GCVector.h"
#include "threading/ConditionVariable.h"
#include "threading/LockGuard.h"
#include "threading/Mutex.h"
#include "threading/Thread.h"
#include "vm/GeckoProfiler.h"
#include "vm/Monitor.h"
// Some platform hooks must be implemented for single-step profiling.
#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS64)
# define SINGLESTEP_PROFILING
#endif
namespace js {
namespace shell {
@ -90,6 +107,115 @@ struct RCFile {
bool
CreateAlias(JSContext* cx, const char* dstName, JS::HandleObject namespaceObj, const char* srcName);
enum class ScriptKind
{
Script,
DecodeScript,
Module
};
class OffThreadState {
enum State {
IDLE, /* ready to work; no token, no source */
COMPILING, /* working; no token, have source */
DONE /* compilation done: have token and source */
};
public:
OffThreadState()
: monitor(mutexid::ShellOffThreadState),
state(IDLE),
token(),
source(nullptr)
{ }
bool startIfIdle(JSContext* cx, ScriptKind kind, ScopedJSFreePtr<char16_t>& newSource);
bool startIfIdle(JSContext* cx, ScriptKind kind, JS::TranscodeBuffer&& newXdr);
void abandon(JSContext* cx);
void markDone(void* newToken);
void* waitUntilDone(JSContext* cx, ScriptKind kind);
JS::TranscodeBuffer& xdrBuffer() { return xdr; }
private:
js::Monitor monitor;
ScriptKind scriptKind;
State state;
void* token;
char16_t* source;
JS::TranscodeBuffer xdr;
};
class NonshrinkingGCObjectVector : public GCVector<JSObject*, 0, SystemAllocPolicy>
{
public:
void sweep() {
for (uint32_t i = 0; i < this->length(); i++) {
if (JS::GCPolicy<JSObject*>::needsSweep(&(*this)[i]))
(*this)[i] = nullptr;
}
}
};
using MarkBitObservers = JS::WeakCache<NonshrinkingGCObjectVector>;
#ifdef SINGLESTEP_PROFILING
using StackChars = Vector<char16_t, 0, SystemAllocPolicy>;
#endif
// Per-context shell state.
struct ShellContext
{
explicit ShellContext(JSContext* cx);
bool isWorker;
double timeoutInterval;
double startTime;
mozilla::Atomic<bool> serviceInterrupt;
mozilla::Atomic<bool> haveInterruptFunc;
JS::PersistentRootedValue interruptFunc;
bool lastWarningEnabled;
JS::PersistentRootedValue lastWarning;
JS::PersistentRootedValue promiseRejectionTrackerCallback;
#ifdef SINGLESTEP_PROFILING
Vector<StackChars, 0, SystemAllocPolicy> stacks;
#endif
/*
* Watchdog thread state.
*/
js::Mutex watchdogLock;
js::ConditionVariable watchdogWakeup;
mozilla::Maybe<js::Thread> watchdogThread;
mozilla::Maybe<mozilla::TimeStamp> watchdogTimeout;
js::ConditionVariable sleepWakeup;
int exitCode;
bool quitting;
JS::UniqueChars readLineBuf;
size_t readLineBufPos;
js::shell::RCFile** errFilePtr;
js::shell::RCFile** outFilePtr;
static const uint32_t GeckoProfilingMaxStackSize = 1000;
js::ProfileEntry geckoProfilingStack[GeckoProfilingMaxStackSize];
mozilla::Atomic<uint32_t> geckoProfilingStackSize;
OffThreadState offThreadState;
JS::UniqueChars moduleLoadPath;
UniquePtr<MarkBitObservers> markObservers;
};
extern ShellContext*
GetShellContext(JSContext* cx);
} /* namespace shell */
} /* namespace js */

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

@ -2409,6 +2409,27 @@ TemporaryTypeSet::maybeCallable(CompilerConstraintList* constraints)
return false;
}
bool
TemporaryTypeSet::maybeProxy(CompilerConstraintList* constraints)
{
if (!maybeObject())
return false;
if (unknownObject())
return true;
unsigned count = getObjectCount();
for (unsigned i = 0; i < count; i++) {
const Class* clasp = getObjectClass(i);
if (!clasp)
continue;
if (clasp->isProxy() || !getObject(i)->hasStableClassAndProto(constraints))
return true;
}
return false;
}
bool
TemporaryTypeSet::maybeEmulatesUndefined(CompilerConstraintList* constraints)
{

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

@ -829,6 +829,9 @@ class TemporaryTypeSet : public TypeSet
/* Whether clasp->isCallable() is true for one or more objects in this set. */
bool maybeCallable(CompilerConstraintList* constraints);
/* Whether clasp->isProxy() might be true for one or more objects in this set. */
bool maybeProxy(CompilerConstraintList* constraints);
/* Whether clasp->emulatesUndefined() is true for one or more objects in this set. */
bool maybeEmulatesUndefined(CompilerConstraintList* constraints);

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

@ -33,7 +33,7 @@
#define DOC_ELEM_INSERTED_TOPIC "document-element-inserted"
#define CLEANUP_TOPIC "xpcom-shutdown"
#define SHUTDOWN_TOPIC "quit-application-granted"
#define CACHE_FLUSH_TOPIC "startupcache-invalidate"
#define CACHE_INVALIDATE_TOPIC "startupcache-invalidate"
namespace mozilla {
namespace {
@ -163,7 +163,9 @@ ScriptPreloader::InitContentChild(ContentParent& parent)
cache.mInitializedProcesses += processType;
auto fd = cache.mCacheData.cloneFileDescriptor();
if (fd.IsValid()) {
// Don't send original cache data to new processes if the cache has been
// invalidated.
if (fd.IsValid() && !cache.mCacheInvalidated) {
Unused << parent.SendPScriptCacheConstructor(fd, wantScriptData);
} else {
Unused << parent.SendPScriptCacheConstructor(NS_ERROR_FILE_NOT_FOUND, wantScriptData);
@ -227,7 +229,7 @@ ScriptPreloader::ScriptPreloader()
}
obs->AddObserver(this, SHUTDOWN_TOPIC, false);
obs->AddObserver(this, CLEANUP_TOPIC, false);
obs->AddObserver(this, CACHE_FLUSH_TOPIC, false);
obs->AddObserver(this, CACHE_INVALIDATE_TOPIC, false);
AutoSafeJSAPI jsapi;
JS_AddExtraGCRootsTracer(jsapi.cx(), TraceOp, this);
@ -265,10 +267,12 @@ ScriptPreloader::Cleanup()
}
void
ScriptPreloader::FlushCache()
ScriptPreloader::InvalidateCache()
{
MonitorAutoLock mal(mMonitor);
mCacheInvalidated = true;
for (auto& script : IterHash(mScripts)) {
// We can only purge finished scripts here. Async scripts that are
// still being parsed off-thread have a non-refcounted reference to
@ -321,8 +325,8 @@ ScriptPreloader::Observe(nsISupports* subject, const char* topic, const char16_t
ForceWriteCacheFile();
} else if (!strcmp(topic, CLEANUP_TOPIC)) {
Cleanup();
} else if (!strcmp(topic, CACHE_FLUSH_TOPIC)) {
FlushCache();
} else if (!strcmp(topic, CACHE_INVALIDATE_TOPIC)) {
InvalidateCache();
}
return NS_OK;
@ -724,6 +728,21 @@ ScriptPreloader::NoteScript(const nsCString& url, const nsCString& cachePath,
}
}
if (!script->mSize && !script->mScript) {
// If the content process is sending us a script entry for a script
// which was in the cache at startup, it expects us to already have this
// script data, so it doesn't send it.
//
// However, the cache may have been invalidated at this point (usually
// due to the add-on manager installing or uninstalling a legacy
// extension during very early startup), which means we may no longer
// have an entry for this script. Since that means we have no data to
// write to the new cache, and no JSScript to generate it from, we need
// to discard this entry.
mScripts.Remove(cachePath);
return;
}
script->UpdateLoadTime(loadTime);
script->mProcessTypes += processType;
}

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

@ -350,7 +350,7 @@ private:
void ForceWriteCacheFile();
void Cleanup();
void FlushCache();
void InvalidateCache();
// Opens the cache file for reading.
Result<Ok, nsresult> OpenCache();
@ -404,6 +404,7 @@ private:
bool mCacheInitialized = false;
bool mSaveComplete = false;
bool mDataPrepared = false;
bool mCacheInvalidated = false;
// The process type of the current process.
static ProcessType sProcessType;

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

@ -1708,7 +1708,15 @@ public class BrowserApp extends GeckoApp
@Override
public void toggleToolbarChrome(final boolean aShow) {
toggleChrome(aShow);
if (aShow) {
mBrowserChrome.setVisibility(View.VISIBLE);
} else {
// The chrome needs to be INVISIBLE instead of GONE so that
// it will continue update when the layout changes. This
// ensures the bitmap generated for the static toolbar
// snapshot is the correct size.
mBrowserChrome.setVisibility(View.INVISIBLE);
}
}
public void refreshToolbarHeight() {
@ -1730,22 +1738,17 @@ public class BrowserApp extends GeckoApp
@Override
void toggleChrome(final boolean aShow) {
if (aShow) {
mBrowserChrome.setVisibility(View.VISIBLE);
} else {
// The chrome needs to be INVISIBLE instead of GONE so that
// it will continue update when the layout changes. This
// ensures the bitmap generated for the static toolbar
// snapshot is the correct size.
mBrowserChrome.setVisibility(View.INVISIBLE);
if (mDynamicToolbar != null) {
mDynamicToolbar.setVisible(aShow, VisibilityTransition.IMMEDIATE);
}
super.toggleChrome(aShow);
}
@Override
void focusChrome() {
mBrowserChrome.setVisibility(View.VISIBLE);
if (mDynamicToolbar != null) {
mDynamicToolbar.setVisible(true, VisibilityTransition.IMMEDIATE);
}
mActionBarFlipper.requestFocusFromTouch();
super.focusChrome();

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

@ -481,6 +481,11 @@ nsHttpHandler::Init()
"net:current-toplevel-outer-content-windowid",
true);
if (mFastOpenSupported) {
obsService->AddObserver(this, "captive-portal-login", true);
obsService->AddObserver(this, "captive-portal-login-success", true);
}
// disabled as its a nop right now
// obsService->AddObserver(this, "net:failed-to-process-uri-content", true);
}
@ -648,7 +653,6 @@ nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter()
if (mFastOpenConsecutiveFailureCounter == mFastOpenConsecutiveFailureLimit) {
LOG(("nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter - "
"Fast open failed too many times"));
SetFastOpenNotSupported();
}
}
}
@ -2315,6 +2319,11 @@ nsHttpHandler::Observe(nsISupports *subject,
}
}
}
} else if (!strcmp(topic, "captive-portal-login") ||
!strcmp(topic, "captive-portal-login-success")) {
// We have detected a captive portal and we will reset the Fast Open
// failure counter.
ResetFastOpenConsecutiveFailureCounter();
}
return NS_OK;

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

@ -164,7 +164,11 @@ public:
return mTCPKeepaliveLongLivedIdleTimeS;
}
bool UseFastOpen() { return mUseFastOpen && mFastOpenSupported; }
bool UseFastOpen()
{
return mUseFastOpen && mFastOpenSupported &&
mFastOpenConsecutiveFailureCounter < mFastOpenConsecutiveFailureLimit;
}
// If one of tcp connections return PR_NOT_TCP_SOCKET_ERROR while trying
// fast open, it means that Fast Open is turned off so we will not try again
// until a restart. This is only on Linux.

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

@ -2,9 +2,6 @@
# 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/.
import sys
import unittest
from firefox_puppeteer import PuppeteerMixin
from marionette_driver import Wait
from marionette_harness import MarionetteTestCase
@ -57,25 +54,3 @@ class TestBrowserWindowShortcuts(PuppeteerMixin, MarionetteTestCase):
return selection_name == "input"
Wait(self.marionette).until(has_input_selected)
@unittest.skipIf(sys.platform == 'darwin',
'Quit Shotcut not supported due to native menu of Mac OS')
class TestBrowserQuitShortcut(PuppeteerMixin, MarionetteTestCase):
def test_quit_firefox_shortcut(self):
def quit_via_shortcut_callback():
if self.puppeteer.platform == 'win':
key = 'quitApplicationCmdWin2.accesskey'
else:
key = 'quitApplicationCmdUnix.key'
self.browser.send_shortcut(self.browser.localize_entity(key),
accel=True)
self.marionette.quit(in_app=True, callback=quit_via_shortcut_callback)
self.assertIsNone(self.marionette.session)
def tearDown(self):
self.marionette.start_session()
super(TestBrowserQuitShortcut, self).tearDown()

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

@ -409,7 +409,8 @@ class BaseWindow(BaseLib):
if kwargs[modifier] is True:
keys.append(keymap[modifier])
keys.append(command_key)
# Bug 1125209 - Only lower-case command keys should be sent
keys.append(command_key.lower())
self.switch_to()

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

@ -94,8 +94,8 @@ function testInit() {
};
var listener = 'data:,function doLoad(e) { var data=e.detail&&e.detail.data;removeEventListener("contentEvent", function (e) { doLoad(e); }, false, true);sendAsyncMessage("chromeEvent", {"data":data}); };addEventListener("contentEvent", function (e) { doLoad(e); }, false, true);';
messageManager.loadFrameScript(listener, true);
messageManager.addMessageListener("chromeEvent", messageHandler);
messageManager.loadFrameScript(listener, true);
}
if (gConfig.e10s) {
e10s_init();

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

@ -27,6 +27,8 @@
// added until then.
window.addEventListener("MozAfterPaint", function() {
setTimeout(redirectToHarness, 0);
// In case the listener was not ready, try again after a few seconds.
setTimeout(redirectToHarness, 5000);
}, {once: true});
}

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

@ -12914,7 +12914,7 @@
},
"DISPLAY_ITEM_USAGE_COUNT": {
"record_in_processes": ["main", "content"],
"alert_emails": ["mchang@mozilla.com", "gfx-telemetry@mozilla.com"],
"alert_emails": ["mchang@mozilla.com", "gfx-telemetry-alerts@mozilla.com"],
"bug_numbers": [1353521],
"expires_in_version": "56",
"kind": "enumerated",

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

@ -61,17 +61,23 @@ public:
: mIsBackground(aRunnable->IsBackground())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
// Telemetry collection temporarily disabled in bug 1366156.
#if 0
#ifdef EARLY_BETA_OR_EARLIER
aRunnable->GetName(mKey);
mStart = TimeStamp::Now();
#endif
#endif
}
~AutoCollectVsyncTelemetry()
{
// Telemetry collection temporarily disabled in bug 1366156.
#if 0
#ifdef EARLY_BETA_OR_EARLIER
if (Telemetry::CanRecordBase()) {
CollectTelemetry();
}
#endif
#endif
}