зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to central, a=merge
MozReview-Commit-ID: EI67EKp8ykS
This commit is contained in:
Коммит
15edcfd962
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче