зеркало из 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 {
|
#main-window {
|
||||||
--urlbar-border-color: ThreeDShadow;
|
--urlbar-border-color: ThreeDShadow;
|
||||||
--urlbar-border-color-hover: var(--urlbar-border-color);
|
--urlbar-border-color-hover: var(--urlbar-border-color);
|
||||||
--urlbar-background-color: -moz-field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#navigator-toolbox:-moz-lwtheme {
|
#navigator-toolbox:-moz-lwtheme {
|
||||||
--urlbar-border-color: rgba(0,0,0,.3);
|
--urlbar-border-color: rgba(0,0,0,.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#urlbar {
|
||||||
|
/* override textbox[enablehistory="true"] styling: */
|
||||||
|
background-color: -moz-field;
|
||||||
|
}
|
||||||
|
|
||||||
%include ../shared/urlbar-searchbar.inc.css
|
%include ../shared/urlbar-searchbar.inc.css
|
||||||
|
|
||||||
%ifdef MOZ_PHOTON_THEME
|
%ifdef MOZ_PHOTON_THEME
|
||||||
|
@ -301,10 +305,6 @@ menuitem.bookmark-item {
|
||||||
border-color: Highlight;
|
border-color: Highlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
#urlbar {
|
|
||||||
background-color: -moz-field;
|
|
||||||
}
|
|
||||||
|
|
||||||
#urlbar:-moz-lwtheme,
|
#urlbar:-moz-lwtheme,
|
||||||
.searchbar-textbox:-moz-lwtheme {
|
.searchbar-textbox:-moz-lwtheme {
|
||||||
background-color: rgba(255,255,255,.8);
|
background-color: rgba(255,255,255,.8);
|
||||||
|
|
|
@ -527,7 +527,6 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
|
||||||
#main-window {
|
#main-window {
|
||||||
--urlbar-border-color: hsla(240, 5%, 5%, .25);
|
--urlbar-border-color: hsla(240, 5%, 5%, .25);
|
||||||
--urlbar-border-color-hover: hsla(240, 5%, 5%, .35);
|
--urlbar-border-color-hover: hsla(240, 5%, 5%, .35);
|
||||||
--urlbar-background-color: -moz-field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#urlbar[focused="true"],
|
#urlbar[focused="true"],
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
.searchbar-textbox {
|
.searchbar-textbox {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
background-clip: content-box;
|
background-clip: content-box;
|
||||||
background-color: var(--urlbar-background-color);
|
|
||||||
border: 1px solid var(--urlbar-border-color);
|
border: 1px solid var(--urlbar-border-color);
|
||||||
border-radius: var(--toolbarbutton-border-radius);
|
border-radius: var(--toolbarbutton-border-radius);
|
||||||
box-shadow: 0 1px 4px hsla(0, 0%, 0%, .05);
|
box-shadow: 0 1px 4px hsla(0, 0%, 0%, .05);
|
||||||
|
|
|
@ -670,7 +670,6 @@ toolbar[brighttext] #close-button {
|
||||||
#main-window:not(:-moz-lwtheme) {
|
#main-window:not(:-moz-lwtheme) {
|
||||||
--urlbar-border-color: hsla(240, 5%, 5%, .25);
|
--urlbar-border-color: hsla(240, 5%, 5%, .25);
|
||||||
--urlbar-border-color-hover: hsla(240, 5%, 5%, .35);
|
--urlbar-border-color-hover: hsla(240, 5%, 5%, .35);
|
||||||
--urlbar-background-color: -moz-field;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,7 @@ TimeoutManager::TimeoutManager(nsGlobalWindow& aWindow)
|
||||||
|
|
||||||
TimeoutManager::~TimeoutManager()
|
TimeoutManager::~TimeoutManager()
|
||||||
{
|
{
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mWindow.AsInner()->InnerObjectsFreed());
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!mThrottleTrackingTimeoutsTimer);
|
MOZ_DIAGNOSTIC_ASSERT(!mThrottleTrackingTimeoutsTimer);
|
||||||
|
|
||||||
MOZ_LOG(gLog, LogLevel::Debug,
|
MOZ_LOG(gLog, LogLevel::Debug,
|
||||||
|
@ -1472,7 +1473,8 @@ TimeoutManager::OnDocumentLoaded()
|
||||||
void
|
void
|
||||||
TimeoutManager::MaybeStartThrottleTrackingTimout()
|
TimeoutManager::MaybeStartThrottleTrackingTimout()
|
||||||
{
|
{
|
||||||
if (gTrackingTimeoutThrottlingDelay <= 0) {
|
if (gTrackingTimeoutThrottlingDelay <= 0 ||
|
||||||
|
mWindow.AsInner()->InnerObjectsFreed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -424,6 +424,10 @@ def DOMClass(descriptor):
|
||||||
hooks=NativePropertyHooks(descriptor))
|
hooks=NativePropertyHooks(descriptor))
|
||||||
|
|
||||||
|
|
||||||
|
def InstanceReservedSlots(descriptor):
|
||||||
|
return INSTANCE_RESERVED_SLOTS + descriptor.interface.totalMembersInSlots
|
||||||
|
|
||||||
|
|
||||||
class CGDOMJSClass(CGThing):
|
class CGDOMJSClass(CGThing):
|
||||||
"""
|
"""
|
||||||
Generate a DOMJSClass for a given descriptor
|
Generate a DOMJSClass for a given descriptor
|
||||||
|
@ -438,7 +442,7 @@ class CGDOMJSClass(CGThing):
|
||||||
def define(self):
|
def define(self):
|
||||||
callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
|
callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
|
||||||
objectMovedHook = OBJECT_MOVED_HOOK_NAME if self.descriptor.wrapperCache 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 | "
|
classFlags = "JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | "
|
||||||
if self.descriptor.isGlobal():
|
if self.descriptor.isGlobal():
|
||||||
classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS)"
|
classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS)"
|
||||||
|
@ -528,9 +532,10 @@ class CGDOMProxyJSClass(CGThing):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def define(self):
|
def define(self):
|
||||||
|
slotCount = InstanceReservedSlots(self.descriptor)
|
||||||
# We need one reserved slot (DOM_OBJECT_SLOT).
|
# We need one reserved slot (DOM_OBJECT_SLOT).
|
||||||
flags = ["JSCLASS_IS_DOMJSCLASS",
|
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 use an IDL annotation for JSCLASS_EMULATES_UNDEFINED because
|
||||||
# we don't want people ever adding that to any interface other than
|
# we don't want people ever adding that to any interface other than
|
||||||
# HTMLAllCollection. So just hardcode it here.
|
# HTMLAllCollection. So just hardcode it here.
|
||||||
|
@ -12717,10 +12722,6 @@ class CGDescriptor(CGThing):
|
||||||
|
|
||||||
if descriptor.concrete:
|
if descriptor.concrete:
|
||||||
if descriptor.proxy:
|
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(
|
cgThings.append(CGGeneric(fill(
|
||||||
"""
|
"""
|
||||||
static_assert(IsBaseOf<nsISupports, ${nativeType} >::value,
|
static_assert(IsBaseOf<nsISupports, ${nativeType} >::value,
|
||||||
|
@ -12741,6 +12742,7 @@ class CGDescriptor(CGThing):
|
||||||
else:
|
else:
|
||||||
cgThings.append(CGDOMJSClass(descriptor))
|
cgThings.append(CGDOMJSClass(descriptor))
|
||||||
cgThings.append(CGGetJSClassMethod(descriptor))
|
cgThings.append(CGGetJSClassMethod(descriptor))
|
||||||
|
|
||||||
if descriptor.interface.hasMembersInSlots():
|
if descriptor.interface.hasMembersInSlots():
|
||||||
cgThings.append(CGUpdateMemberSlotsMethod(descriptor))
|
cgThings.append(CGUpdateMemberSlotsMethod(descriptor))
|
||||||
|
|
||||||
|
|
|
@ -1217,6 +1217,8 @@ public:
|
||||||
uint32_t Item(uint32_t, bool&) = delete;
|
uint32_t Item(uint32_t, bool&) = delete;
|
||||||
uint32_t Length();
|
uint32_t Length();
|
||||||
void LegacyCall(JS::Handle<JS::Value>);
|
void LegacyCall(JS::Handle<JS::Value>);
|
||||||
|
int32_t CachedAttr();
|
||||||
|
int32_t StoreInSlotAttr();
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestNamedGetterInterface : public nsISupports,
|
class TestNamedGetterInterface : public nsISupports,
|
||||||
|
|
|
@ -1188,6 +1188,8 @@ interface TestIndexedGetterInterface {
|
||||||
getter long item(unsigned long idx);
|
getter long item(unsigned long idx);
|
||||||
readonly attribute unsigned long length;
|
readonly attribute unsigned long length;
|
||||||
legacycaller void();
|
legacycaller void();
|
||||||
|
[Cached, Pure] readonly attribute long cachedAttr;
|
||||||
|
[StoreInSlot, Pure] readonly attribute long storeInSlotAttr;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface TestNamedGetterInterface {
|
interface TestNamedGetterInterface {
|
||||||
|
|
|
@ -192,6 +192,10 @@ IPCBlobInputStream::Clone(nsIInputStream** aResult)
|
||||||
MOZ_ASSERT(mActor);
|
MOZ_ASSERT(mActor);
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> stream = mActor->CreateStream();
|
nsCOMPtr<nsIInputStream> stream = mActor->CreateStream();
|
||||||
|
if (!stream) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
stream.forget(aResult);
|
stream.forget(aResult);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,19 +13,17 @@ namespace {
|
||||||
|
|
||||||
// This runnable is used in case the last stream is forgotten on the 'wrong'
|
// This runnable is used in case the last stream is forgotten on the 'wrong'
|
||||||
// thread.
|
// thread.
|
||||||
class DeleteRunnable final : public Runnable
|
class ShutdownRunnable final : public Runnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit DeleteRunnable(IPCBlobInputStreamChild* aActor)
|
explicit ShutdownRunnable(IPCBlobInputStreamChild* aActor)
|
||||||
: mActor(aActor)
|
: mActor(aActor)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
NS_IMETHOD
|
NS_IMETHOD
|
||||||
Run() override
|
Run() override
|
||||||
{
|
{
|
||||||
if (mActor->IsAlive()) {
|
mActor->Shutdown();
|
||||||
mActor->Send__delete__(mActor);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,13 +93,32 @@ IPCBlobInputStreamChild::IPCBlobInputStreamChild(const nsID& aID,
|
||||||
IPCBlobInputStreamChild::~IPCBlobInputStreamChild()
|
IPCBlobInputStreamChild::~IPCBlobInputStreamChild()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void
|
||||||
|
IPCBlobInputStreamChild::Shutdown()
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
|
||||||
|
RefPtr<IPCBlobInputStreamChild> kungFuDeathGrip = this;
|
||||||
|
|
||||||
|
mPendingOperations.Clear();
|
||||||
|
|
||||||
|
if (mActorAlive) {
|
||||||
|
SendClose();
|
||||||
|
mActorAlive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason)
|
IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason)
|
||||||
|
{
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
mActorAlive = false;
|
mActorAlive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IPCBlobInputStreamChild::IsAlive()
|
IPCBlobInputStreamChild::IsAlive()
|
||||||
{
|
{
|
||||||
|
@ -114,6 +131,10 @@ IPCBlobInputStreamChild::CreateStream()
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
|
|
||||||
|
if (!mActorAlive) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<IPCBlobInputStream> stream = new IPCBlobInputStream(this);
|
RefPtr<IPCBlobInputStream> stream = new IPCBlobInputStream(this);
|
||||||
mStreams.AppendElement(stream);
|
mStreams.AppendElement(stream);
|
||||||
return stream.forget();
|
return stream.forget();
|
||||||
|
@ -124,7 +145,7 @@ IPCBlobInputStreamChild::ForgetStream(IPCBlobInputStream* aStream)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aStream);
|
MOZ_ASSERT(aStream);
|
||||||
|
|
||||||
RefPtr<IPCBlobInputStreamChild> kungFoDeathGrip = this;
|
RefPtr<IPCBlobInputStreamChild> kungFuDeathGrip = this;
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
|
@ -136,11 +157,11 @@ IPCBlobInputStreamChild::ForgetStream(IPCBlobInputStream* aStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mOwningThread == NS_GetCurrentThread()) {
|
if (mOwningThread == NS_GetCurrentThread()) {
|
||||||
Send__delete__(this);
|
Shutdown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<DeleteRunnable> runnable = new DeleteRunnable(this);
|
RefPtr<ShutdownRunnable> runnable = new ShutdownRunnable(this);
|
||||||
mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +170,11 @@ IPCBlobInputStreamChild::StreamNeeded(IPCBlobInputStream* aStream,
|
||||||
nsIEventTarget* aEventTarget)
|
nsIEventTarget* aEventTarget)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
|
|
||||||
|
if (!mActorAlive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(mStreams.Contains(aStream));
|
MOZ_ASSERT(mStreams.Contains(aStream));
|
||||||
|
|
||||||
PendingOperation* opt = mPendingOperations.AppendElement();
|
PendingOperation* opt = mPendingOperations.AppendElement();
|
||||||
|
@ -175,6 +201,7 @@ IPCBlobInputStreamChild::RecvStreamReady(const OptionalIPCStream& aStream)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
MOZ_ASSERT(!mPendingOperations.IsEmpty());
|
MOZ_ASSERT(!mPendingOperations.IsEmpty());
|
||||||
|
MOZ_ASSERT(mActorAlive);
|
||||||
|
|
||||||
pendingStream = mPendingOperations[0].mStream;
|
pendingStream = mPendingOperations[0].mStream;
|
||||||
eventTarget = mPendingOperations[0].mEventTarget;
|
eventTarget = mPendingOperations[0].mEventTarget;
|
||||||
|
|
|
@ -56,6 +56,9 @@ public:
|
||||||
mozilla::ipc::IPCResult
|
mozilla::ipc::IPCResult
|
||||||
RecvStreamReady(const OptionalIPCStream& aStream) override;
|
RecvStreamReady(const OptionalIPCStream& aStream) override;
|
||||||
|
|
||||||
|
void
|
||||||
|
Shutdown();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~IPCBlobInputStreamChild();
|
~IPCBlobInputStreamChild();
|
||||||
|
|
||||||
|
|
|
@ -96,5 +96,14 @@ IPCBlobInputStreamParent::RecvStreamNeeded()
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult
|
||||||
|
IPCBlobInputStreamParent::RecvClose()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mContentManager || mPBackgroundManager);
|
||||||
|
|
||||||
|
Unused << Send__delete__(this);
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -44,6 +44,9 @@ public:
|
||||||
mozilla::ipc::IPCResult
|
mozilla::ipc::IPCResult
|
||||||
RecvStreamNeeded() override;
|
RecvStreamNeeded() override;
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult
|
||||||
|
RecvClose() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IPCBlobInputStreamParent(const nsID& aID, uint64_t aSize,
|
IPCBlobInputStreamParent(const nsID& aID, uint64_t aSize,
|
||||||
nsIContentParent* aManager);
|
nsIContentParent* aManager);
|
||||||
|
|
|
@ -20,11 +20,11 @@ protocol PIPCBlobInputStream
|
||||||
|
|
||||||
parent:
|
parent:
|
||||||
async StreamNeeded();
|
async StreamNeeded();
|
||||||
|
async Close();
|
||||||
async __delete__();
|
|
||||||
|
|
||||||
child:
|
child:
|
||||||
async StreamReady(OptionalIPCStream aStream);
|
async StreamReady(OptionalIPCStream aStream);
|
||||||
|
async __delete__();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
@ -44,6 +44,11 @@ public:
|
||||||
bool Selected() const;
|
bool Selected() const;
|
||||||
bool DefaultSelected() const;
|
bool DefaultSelected() const;
|
||||||
|
|
||||||
|
void SetSelectedChanged(bool aValue)
|
||||||
|
{
|
||||||
|
mSelectedChanged = aValue;
|
||||||
|
}
|
||||||
|
|
||||||
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
|
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
|
||||||
int32_t aModType) const override;
|
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)
|
// Make sure something is selected unless we were set to -1 (none)
|
||||||
if (optionsDeselected && aStartIndex != -1) {
|
if (optionsDeselected && aStartIndex != -1 && !(aOptionsMask & NO_RESELECT)) {
|
||||||
optionsSelected =
|
optionsSelected =
|
||||||
CheckSelectSomething(aOptionsMask & NOTIFY) || optionsSelected;
|
CheckSelectSomething(aOptionsMask & NOTIFY) || optionsSelected;
|
||||||
}
|
}
|
||||||
|
@ -1648,13 +1648,14 @@ HTMLSelectElement::Reset()
|
||||||
// Reset the option to its default value
|
// Reset the option to its default value
|
||||||
//
|
//
|
||||||
|
|
||||||
uint32_t mask = SET_DISABLED | NOTIFY;
|
uint32_t mask = SET_DISABLED | NOTIFY | NO_RESELECT;
|
||||||
if (option->DefaultSelected()) {
|
if (option->DefaultSelected()) {
|
||||||
mask |= IS_SELECTED;
|
mask |= IS_SELECTED;
|
||||||
numSelected++;
|
numSelected++;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetOptionsSelectedByIndex(i, i, mask);
|
SetOptionsSelectedByIndex(i, i, mask);
|
||||||
|
option->SetSelectedChanged(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,12 +134,16 @@ public:
|
||||||
* (for JavaScript)
|
* (for JavaScript)
|
||||||
*
|
*
|
||||||
* NOTIFY whether to notify frames and such
|
* NOTIFY whether to notify frames and such
|
||||||
|
*
|
||||||
|
* NO_RESELECT no need to select something after an option is deselected
|
||||||
|
* (for reset)
|
||||||
*/
|
*/
|
||||||
enum OptionType {
|
enum OptionType {
|
||||||
IS_SELECTED = 1 << 0,
|
IS_SELECTED = 1 << 0,
|
||||||
CLEAR_ALL = 1 << 1,
|
CLEAR_ALL = 1 << 1,
|
||||||
SET_DISABLED = 1 << 2,
|
SET_DISABLED = 1 << 2,
|
||||||
NOTIFY = 1 << 3
|
NOTIFY = 1 << 3,
|
||||||
|
NO_RESELECT = 1 << 4
|
||||||
};
|
};
|
||||||
|
|
||||||
using nsIConstraintValidation::GetValidationMessage;
|
using nsIConstraintValidation::GetValidationMessage;
|
||||||
|
|
|
@ -89,7 +89,7 @@ SessionStorageManager::GetStorage(mozIDOMWindow* aWindow,
|
||||||
nsAutoCString originKey;
|
nsAutoCString originKey;
|
||||||
nsAutoCString originAttributes;
|
nsAutoCString originAttributes;
|
||||||
nsresult rv = GenerateOriginKey(aPrincipal, originAttributes, originKey);
|
nsresult rv = GenerateOriginKey(aPrincipal, originAttributes, originKey);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ SessionStorageManager::CloneStorage(nsIDOMStorage* aStorage)
|
||||||
nsAutoCString originAttributes;
|
nsAutoCString originAttributes;
|
||||||
nsresult rv = GenerateOriginKey(storage->Principal(), originAttributes,
|
nsresult rv = GenerateOriginKey(storage->Principal(), originAttributes,
|
||||||
originKey);
|
originKey);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ AndroidDynamicToolbarAnimator::AndroidDynamicToolbarAnimator()
|
||||||
, mCompositorReceivedFirstPaint(false)
|
, mCompositorReceivedFirstPaint(false)
|
||||||
, mCompositorWaitForPageResize(false)
|
, mCompositorWaitForPageResize(false)
|
||||||
, mCompositorToolbarShowRequested(false)
|
, mCompositorToolbarShowRequested(false)
|
||||||
|
, mCompositorSendResponseForSnapshotUpdate(false)
|
||||||
, mCompositorAnimationStyle(eAnimate)
|
, mCompositorAnimationStyle(eAnimate)
|
||||||
, mCompositorMaxToolbarHeight(0)
|
, mCompositorMaxToolbarHeight(0)
|
||||||
, mCompositorToolbarHeight(0)
|
, mCompositorToolbarHeight(0)
|
||||||
|
@ -270,30 +271,6 @@ AndroidDynamicToolbarAnimator::GetCompositionHeight() const
|
||||||
return mCompositorCompositionSize.height;
|
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
|
void
|
||||||
AndroidDynamicToolbarAnimator::SetScrollingRootContent()
|
AndroidDynamicToolbarAnimator::SetScrollingRootContent()
|
||||||
{
|
{
|
||||||
|
@ -318,8 +295,8 @@ AndroidDynamicToolbarAnimator::ToolbarAnimatorMessageFromUI(int32_t aMessage)
|
||||||
StartCompositorAnimation(mCompositorAnimationDirection, mCompositorAnimationStyle, mCompositorToolbarHeight, mCompositorWaitForPageResize);
|
StartCompositorAnimation(mCompositorAnimationDirection, mCompositorAnimationStyle, mCompositorToolbarHeight, mCompositorWaitForPageResize);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The compositor is already animating the toolbar so no need to defer.
|
// Animation already running so just make sure it is going the right direction.
|
||||||
mCompositorAnimationDeferred = false;
|
StartCompositorAnimation(MOVE_TOOLBAR_UP, mCompositorAnimationStyle, mCompositorToolbarHeight, mCompositorWaitForPageResize);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOOLBAR_VISIBLE:
|
case TOOLBAR_VISIBLE:
|
||||||
|
@ -470,6 +447,35 @@ AndroidDynamicToolbarAnimator::UpdateRootFrameMetrics(const FrameMetrics& aMetri
|
||||||
UpdateFrameMetrics(scrollOffset, scale, cssPageRect);
|
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
|
// Layers updates are need by Robocop test which enables them
|
||||||
void
|
void
|
||||||
AndroidDynamicToolbarAnimator::EnableLayersUpdateNotifications(bool aEnable)
|
AndroidDynamicToolbarAnimator::EnableLayersUpdateNotifications(bool aEnable)
|
||||||
|
@ -525,7 +531,8 @@ AndroidDynamicToolbarAnimator::GetToolbarEffect(CompositorOGL* gl)
|
||||||
uiController->DeallocShmem(mCompositorToolbarPixels.ref());
|
uiController->DeallocShmem(mCompositorToolbarPixels.ref());
|
||||||
mCompositorToolbarPixels.reset();
|
mCompositorToolbarPixels.reset();
|
||||||
// Send notification that texture is ready after the current composition has completed.
|
// 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));
|
CompositorThreadHolder::Loop()->PostTask(NewRunnableMethod(this, &AndroidDynamicToolbarAnimator::PostToolbarReady));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -574,6 +581,7 @@ AndroidDynamicToolbarAnimator::ProcessTouchDelta(StaticToolbarState aCurrentTool
|
||||||
|
|
||||||
if (aCurrentToolbarState == eToolbarVisible) {
|
if (aCurrentToolbarState == eToolbarVisible) {
|
||||||
if (tryingToHideToolbar && (mControllerState != eUnlockPending)) {
|
if (tryingToHideToolbar && (mControllerState != eUnlockPending)) {
|
||||||
|
mCompositorSendResponseForSnapshotUpdate = true;
|
||||||
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
|
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
|
||||||
mControllerState = eUnlockPending;
|
mControllerState = eUnlockPending;
|
||||||
}
|
}
|
||||||
|
@ -796,7 +804,7 @@ AndroidDynamicToolbarAnimator::UpdateFixedLayerMargins()
|
||||||
}
|
}
|
||||||
AsyncCompositionManager* manager = parent->GetCompositionManager(nullptr);
|
AsyncCompositionManager* manager = parent->GetCompositionManager(nullptr);
|
||||||
if (manager) {
|
if (manager) {
|
||||||
if (mToolbarState == eToolbarAnimating) {
|
if ((mToolbarState == eToolbarAnimating) && mCompositorAnimationStarted) {
|
||||||
manager->SetFixedLayerMargins(mCompositorToolbarHeight, 0);
|
manager->SetFixedLayerMargins(mCompositorToolbarHeight, 0);
|
||||||
} else {
|
} else {
|
||||||
manager->SetFixedLayerMargins(0, GetFixedLayerMarginsBottom());
|
manager->SetFixedLayerMargins(0, GetFixedLayerMarginsBottom());
|
||||||
|
@ -851,6 +859,7 @@ AndroidDynamicToolbarAnimator::StartCompositorAnimation(int32_t aDirection, Anim
|
||||||
// and defer animation until it has been unlocked
|
// and defer animation until it has been unlocked
|
||||||
if ((initialToolbarState != eToolbarUnlocked) && (initialToolbarState != eToolbarAnimating)) {
|
if ((initialToolbarState != eToolbarUnlocked) && (initialToolbarState != eToolbarAnimating)) {
|
||||||
mCompositorAnimationDeferred = true;
|
mCompositorAnimationDeferred = true;
|
||||||
|
mCompositorSendResponseForSnapshotUpdate = true;
|
||||||
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
|
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
|
||||||
} else {
|
} else {
|
||||||
// Toolbar is either unlocked or already animating so animation may begin immediately
|
// 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) {
|
if (initialToolbarState != eToolbarAnimating) {
|
||||||
mCompositorAnimationStarted = false;
|
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();
|
NotifyControllerAnimationStarted();
|
||||||
|
// Only reset the time stamp and start compositor animation if not already animating.
|
||||||
|
if (initialToolbarState != eToolbarAnimating) {
|
||||||
CompositorBridgeParent* parent = CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(mRootLayerTreeId);
|
CompositorBridgeParent* parent = CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(mRootLayerTreeId);
|
||||||
if (parent) {
|
if (parent) {
|
||||||
mCompositorAnimationStartTimeStamp = parent->GetAPZCTreeManager()->GetFrameTime();
|
mCompositorAnimationStartTimeStamp = parent->GetAPZCTreeManager()->GetFrameTime();
|
||||||
}
|
}
|
||||||
if (initialToolbarState != eToolbarAnimating) {
|
|
||||||
// Kick the compositor to start the animation if we aren't already animating.
|
// Kick the compositor to start the animation if we aren't already animating.
|
||||||
RequestComposite();
|
RequestComposite();
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,8 +81,6 @@ public:
|
||||||
// shown, the content may extend beyond the bottom of the surface until the toolbar is completely
|
// shown, the content may extend beyond the bottom of the surface until the toolbar is completely
|
||||||
// visible or hidden.
|
// visible or hidden.
|
||||||
ScreenIntCoord GetCompositionHeight() const;
|
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
|
// 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
|
// 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
|
// show the toolbar while scrolling up will only hide the toolbar if it is the root content
|
||||||
|
@ -95,6 +93,8 @@ public:
|
||||||
void FirstPaint();
|
void FirstPaint();
|
||||||
// Called whenever the root document's FrameMetrics have reached a steady state.
|
// Called whenever the root document's FrameMetrics have reached a steady state.
|
||||||
void UpdateRootFrameMetrics(const FrameMetrics& aMetrics);
|
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
|
// 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.
|
// be notified when the layer tree has been updated. Enabled currently by robocop tests.
|
||||||
void EnableLayersUpdateNotifications(bool aEnable);
|
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 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 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
|
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 mCompositorMaxToolbarHeight; // Should contain the same value as mControllerMaxToolbarHeight
|
||||||
ScreenIntCoord mCompositorToolbarHeight; // This value is only updated by the compositor thread when the mToolbarState == ToolbarAnimating
|
ScreenIntCoord mCompositorToolbarHeight; // This value is only updated by the compositor thread when the mToolbarState == ToolbarAnimating
|
||||||
ScreenIntCoord mCompositorSurfaceHeight; // Current height of the render surface
|
ScreenIntCoord mCompositorSurfaceHeight; // Current height of the render surface
|
||||||
|
|
|
@ -3477,12 +3477,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
||||||
if (APZCTreeManager* manager = GetApzcTreeManager()) {
|
if (APZCTreeManager* manager = GetApzcTreeManager()) {
|
||||||
AndroidDynamicToolbarAnimator* animator = manager->GetAndroidDynamicToolbarAnimator();
|
AndroidDynamicToolbarAnimator* animator = manager->GetAndroidDynamicToolbarAnimator();
|
||||||
MOZ_ASSERT(animator);
|
MOZ_ASSERT(animator);
|
||||||
CSSToScreenScale scale = ViewTargetAs<ScreenPixel>(aLayerMetrics.GetZoom().ToScaleFactor(),
|
animator->MaybeUpdateCompositionSizeAndRootFrameMetrics(aLayerMetrics);
|
||||||
PixelCastJustification::ScreenIsParentLayerForRoot);
|
|
||||||
ScreenIntSize size = ScreenIntSize::Round(aLayerMetrics.GetRootCompositionSize() * scale);
|
|
||||||
if (animator->SetCompositionSize(size)) {
|
|
||||||
animator->UpdateRootFrameMetrics(aLayerMetrics);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -945,23 +945,24 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
|
||||||
if (*aOutFoundRoot) {
|
if (*aOutFoundRoot) {
|
||||||
mRootScrollableId = metrics.GetScrollId();
|
mRootScrollableId = metrics.GetScrollId();
|
||||||
Compositor* compositor = mLayerManager->GetCompositor();
|
Compositor* compositor = mLayerManager->GetCompositor();
|
||||||
if (mIsFirstPaint) {
|
|
||||||
if (CompositorBridgeParent* bridge = compositor->GetCompositorBridgeParent()) {
|
if (CompositorBridgeParent* bridge = compositor->GetCompositorBridgeParent()) {
|
||||||
AndroidDynamicToolbarAnimator* animator = bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator();
|
AndroidDynamicToolbarAnimator* animator = bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator();
|
||||||
MOZ_ASSERT(animator);
|
MOZ_ASSERT(animator);
|
||||||
|
if (mIsFirstPaint) {
|
||||||
animator->UpdateRootFrameMetrics(metrics);
|
animator->UpdateRootFrameMetrics(metrics);
|
||||||
animator->FirstPaint();
|
animator->FirstPaint();
|
||||||
}
|
mIsFirstPaint = false;
|
||||||
}
|
}
|
||||||
if (mLayersUpdated) {
|
if (mLayersUpdated) {
|
||||||
if (CompositorBridgeParent* bridge = compositor->GetCompositorBridgeParent()) {
|
|
||||||
AndroidDynamicToolbarAnimator* animator = bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator();
|
|
||||||
MOZ_ASSERT(animator);
|
|
||||||
animator->NotifyLayersUpdated();
|
animator->NotifyLayersUpdated();
|
||||||
}
|
|
||||||
mLayersUpdated = false;
|
mLayersUpdated = false;
|
||||||
}
|
}
|
||||||
mIsFirstPaint = 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
fixedLayerMargins = mFixedLayerMargins;
|
fixedLayerMargins = mFixedLayerMargins;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,9 +81,9 @@ public:
|
||||||
|
|
||||||
class Record {
|
class Record {
|
||||||
public:
|
public:
|
||||||
Record() {
|
explicit Record(TimeStamp aStart = TimeStamp()) {
|
||||||
if (gfxPrefs::LayersDrawFPS()) {
|
if (gfxPrefs::LayersDrawFPS()) {
|
||||||
mStart = TimeStamp::Now();
|
mStart = aStart.IsNull() ? TimeStamp::Now() : aStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool Recording() const {
|
bool Recording() const {
|
||||||
|
|
|
@ -919,7 +919,7 @@ LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion, const nsIntRegi
|
||||||
|
|
||||||
// Render our layers.
|
// Render our layers.
|
||||||
{
|
{
|
||||||
Diagnostics::Record record;
|
Diagnostics::Record record(mRenderStartTime);
|
||||||
RootLayer()->Prepare(ViewAs<RenderTargetPixel>(clipRect, PixelCastJustification::RenderTargetIsParentLayerForRoot));
|
RootLayer()->Prepare(ViewAs<RenderTargetPixel>(clipRect, PixelCastJustification::RenderTargetIsParentLayerForRoot));
|
||||||
if (record.Recording()) {
|
if (record.Recording()) {
|
||||||
mDiagnostics->RecordPrepareTime(record.Duration());
|
mDiagnostics->RecordPrepareTime(record.Duration());
|
||||||
|
|
|
@ -569,11 +569,14 @@ BackgroundChildImpl::DeallocPGamepadTestChannelChild(PGamepadTestChannelChild* a
|
||||||
void
|
void
|
||||||
BackgroundChildImpl::OnChannelReceivedMessage(const Message& aMsg)
|
BackgroundChildImpl::OnChannelReceivedMessage(const Message& aMsg)
|
||||||
{
|
{
|
||||||
|
// Telemetry collection temporarily disabled in bug 1366156.
|
||||||
|
#if 0
|
||||||
if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) {
|
if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) {
|
||||||
// Not really necessary to look at the message payload, it will be
|
// Not really necessary to look at the message payload, it will be
|
||||||
// <0.5ms away from TimeStamp::Now()
|
// <0.5ms away from TimeStamp::Now()
|
||||||
SchedulerGroup::MarkVsyncReceived();
|
SchedulerGroup::MarkVsyncReceived();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "builtin/TestingFunctions.h"
|
#include "builtin/TestingFunctions.h"
|
||||||
|
|
||||||
|
#include "mozilla/Atomics.h"
|
||||||
#include "mozilla/FloatingPoint.h"
|
#include "mozilla/FloatingPoint.h"
|
||||||
#include "mozilla/Move.h"
|
#include "mozilla/Move.h"
|
||||||
#include "mozilla/Sprintf.h"
|
#include "mozilla/Sprintf.h"
|
||||||
|
@ -67,11 +68,11 @@ using mozilla::Move;
|
||||||
|
|
||||||
// If fuzzingSafe is set, remove functionality that could cause problems with
|
// If fuzzingSafe is set, remove functionality that could cause problems with
|
||||||
// fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE.
|
// 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
|
// If disableOOMFunctions is set, disable functionality that causes artificial
|
||||||
// OOM conditions.
|
// OOM conditions.
|
||||||
static bool disableOOMFunctions = false;
|
static mozilla::Atomic<bool> disableOOMFunctions(false);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EnvVarIsDefined(const char* name)
|
EnvVarIsDefined(const char* name)
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
# | E | | E'|
|
# | E | | E'|
|
||||||
# +---+ +---+
|
# +---+ +---+
|
||||||
|
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
|
@ -174,52 +175,56 @@ AllPhaseKinds = findAllPhaseKinds()
|
||||||
# one parent.
|
# one parent.
|
||||||
|
|
||||||
class Phase:
|
class Phase:
|
||||||
def __init__(self, phaseKind, parent, depth):
|
def __init__(self, phaseKind, parent):
|
||||||
self.phaseKind = phaseKind
|
self.phaseKind = phaseKind
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.depth = depth
|
self.depth = parent.depth + 1 if parent else 0
|
||||||
self.children = []
|
self.children = []
|
||||||
self.nextSibling = None
|
self.nextSibling = None
|
||||||
self.nextInPhaseKind = 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():
|
def expandPhases():
|
||||||
phases = []
|
phases = []
|
||||||
phasesForPhase = collections.defaultdict(list)
|
phasesForKind = collections.defaultdict(list)
|
||||||
|
|
||||||
def traverse(phaseKind, parent, depth):
|
def traverse(phaseKind, parent):
|
||||||
ep = Phase(phaseKind, parent, depth)
|
ep = Phase(phaseKind, parent)
|
||||||
phases.append(ep)
|
phases.append(ep)
|
||||||
|
|
||||||
# Update list of expanded phases for this phase kind.
|
# Update list of expanded phases for this phase kind.
|
||||||
if phasesForPhase[phaseKind]:
|
if phasesForKind[phaseKind]:
|
||||||
phasesForPhase[phaseKind][-1].nextInPhaseKind = ep
|
phasesForKind[phaseKind][-1].nextInPhaseKind = ep
|
||||||
phasesForPhase[phaseKind].append(ep)
|
phasesForKind[phaseKind].append(ep)
|
||||||
|
|
||||||
# Recurse over children.
|
# Recurse over children.
|
||||||
for child in phaseKind.children:
|
for child in phaseKind.children:
|
||||||
child_ep = traverse(child, ep, depth + 1)
|
child_ep = traverse(child, ep)
|
||||||
if ep.children:
|
if ep.children:
|
||||||
ep.children[-1].nextSibling = child_ep
|
ep.children[-1].nextSibling = child_ep
|
||||||
ep.children.append(child_ep)
|
ep.children.append(child_ep)
|
||||||
return ep
|
return ep
|
||||||
|
|
||||||
for phaseKind in PhaseKindGraphRoots:
|
for phaseKind in PhaseKindGraphRoots:
|
||||||
traverse(phaseKind, None, 0)
|
traverse(phaseKind, None)
|
||||||
|
|
||||||
return phases, phasesForPhase
|
return phases, phasesForKind
|
||||||
|
|
||||||
AllPhases, PhasesForPhaseKind = expandPhases()
|
AllPhases, PhasesForPhaseKind = expandPhases()
|
||||||
|
|
||||||
# Name expanded phases based on phase kind name and index if there are
|
# Name phases based on phase kind name and index if there are multiple phases
|
||||||
# multiple expanded phases corresponding to a single phase kind.
|
# corresponding to a single phase kind.
|
||||||
|
|
||||||
for phaseKind in AllPhaseKinds:
|
for phaseKind in AllPhaseKinds:
|
||||||
phases = PhasesForPhaseKind[phaseKind]
|
phases = PhasesForPhaseKind[phaseKind]
|
||||||
if len(phases) == 1:
|
if len(phases) == 1:
|
||||||
phases[0].name = "%s" % phaseKind.name
|
phases[0].name = "%s" % phaseKind.name
|
||||||
else:
|
else:
|
||||||
for index, xphase in enumerate(phases):
|
for index, phase in enumerate(phases):
|
||||||
xphase.name = "%s_%d" % (phaseKind.name, index + 1)
|
phase.name = "%s_%d" % (phaseKind.name, index + 1)
|
||||||
|
|
||||||
# Generate code.
|
# Generate code.
|
||||||
|
|
||||||
|
@ -250,13 +255,13 @@ def generateHeader(out):
|
||||||
#
|
#
|
||||||
# Generate Phase enum.
|
# Generate Phase enum.
|
||||||
#
|
#
|
||||||
expandedPhaseNames = map(lambda xphase: xphase.name, AllPhases)
|
phaseNames = map(lambda phase: phase.name, AllPhases)
|
||||||
extraPhases = [
|
extraPhases = [
|
||||||
"NONE = LIMIT",
|
"NONE = LIMIT",
|
||||||
"EXPLICIT_SUSPENSION = LIMIT",
|
"EXPLICIT_SUSPENSION = LIMIT",
|
||||||
"IMPLICIT_SUSPENSION"
|
"IMPLICIT_SUSPENSION"
|
||||||
]
|
]
|
||||||
writeEnumClass(out, "Phase", "uint8_t", expandedPhaseNames, extraPhases)
|
writeEnumClass(out, "Phase", "uint8_t", phaseNames, extraPhases)
|
||||||
|
|
||||||
def generateCpp(out):
|
def generateCpp(out):
|
||||||
#
|
#
|
||||||
|
@ -264,29 +269,30 @@ def generateCpp(out):
|
||||||
#
|
#
|
||||||
out.write("static const PhaseKindTable phaseKinds = {\n")
|
out.write("static const PhaseKindTable phaseKinds = {\n")
|
||||||
for phaseKind in AllPhaseKinds:
|
for phaseKind in AllPhaseKinds:
|
||||||
xPhase = PhasesForPhaseKind[phaseKind][0]
|
phase = PhasesForPhaseKind[phaseKind][0]
|
||||||
out.write(" /* PhaseKind::%s */ PhaseKindInfo { Phase::%s, %d },\n" %
|
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")
|
||||||
out.write("\n")
|
out.write("\n")
|
||||||
|
|
||||||
#
|
#
|
||||||
# Generate the PhaseInfo tree.
|
# Generate the PhaseInfo tree.
|
||||||
#
|
#
|
||||||
def name(xphase):
|
def name(phase):
|
||||||
return "Phase::" + xphase.name if xphase else "Phase::NONE"
|
return "Phase::" + phase.name if phase else "Phase::NONE"
|
||||||
|
|
||||||
out.write("static const PhaseTable phases = {\n")
|
out.write("static const PhaseTable phases = {\n")
|
||||||
for xphase in AllPhases:
|
for phase in AllPhases:
|
||||||
firstChild = xphase.children[0] if xphase.children else None
|
firstChild = phase.children[0] if phase.children else None
|
||||||
phaseKind = xphase.phaseKind
|
phaseKind = phase.phaseKind
|
||||||
out.write(" /* %s */ PhaseInfo { %s, %s, %s, %s, PhaseKind::%s, %d, \"%s\" },\n" %
|
out.write(" /* %s */ PhaseInfo { %s, %s, %s, %s, PhaseKind::%s, %d, \"%s\", \"%s\" },\n" %
|
||||||
(name(xphase),
|
(name(phase),
|
||||||
name(xphase.parent),
|
name(phase.parent),
|
||||||
name(firstChild),
|
name(firstChild),
|
||||||
name(xphase.nextSibling),
|
name(phase.nextSibling),
|
||||||
name(xphase.nextInPhaseKind),
|
name(phase.nextInPhaseKind),
|
||||||
phaseKind.name,
|
phaseKind.name,
|
||||||
xphase.depth,
|
phase.depth,
|
||||||
phaseKind.descr))
|
phaseKind.descr,
|
||||||
|
phase.path))
|
||||||
out.write("};\n")
|
out.write("};\n")
|
||||||
|
|
|
@ -107,12 +107,13 @@ struct PhaseInfo
|
||||||
PhaseKind phaseKind;
|
PhaseKind phaseKind;
|
||||||
uint8_t depth;
|
uint8_t depth;
|
||||||
const char* name;
|
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>;
|
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>;
|
using PhaseKindTable = EnumeratedArray<PhaseKind, PhaseKind::LIMIT, PhaseKindInfo>;
|
||||||
|
|
||||||
#include "gc/StatsPhasesGenerated.cpp"
|
#include "gc/StatsPhasesGenerated.cpp"
|
||||||
|
@ -132,8 +133,8 @@ Statistics::currentPhase() const
|
||||||
PhaseKind
|
PhaseKind
|
||||||
Statistics::currentPhaseKind() const
|
Statistics::currentPhaseKind() const
|
||||||
{
|
{
|
||||||
// Public API to get the current phase. Return the current phase,
|
// Public API to get the current phase kind, suppressing the synthetic
|
||||||
// suppressing the synthetic PhaseKind::MUTATOR phase.
|
// PhaseKind::MUTATOR phase.
|
||||||
|
|
||||||
Phase phase = currentPhase();
|
Phase phase = currentPhase();
|
||||||
MOZ_ASSERT_IF(phase == Phase::MUTATOR, phaseNestingDepth == 1);
|
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);
|
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
|
void
|
||||||
Statistics::formatJsonPhaseTimes(const PhaseTimeTable& phaseTimes, JSONPrinter& json) const
|
Statistics::formatJsonPhaseTimes(const PhaseTimeTable& phaseTimes, JSONPrinter& json) const
|
||||||
{
|
{
|
||||||
for (auto phase : AllPhases()) {
|
for (auto phase : AllPhases()) {
|
||||||
UniqueChars name = SanitizeJsonKey(phases[phase].name);
|
|
||||||
if (!name)
|
|
||||||
json.outOfMemory();
|
|
||||||
TimeDuration ownTime = phaseTimes[phase];
|
TimeDuration ownTime = phaseTimes[phase];
|
||||||
if (!ownTime.IsZero())
|
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
|
// 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
|
// LSlots and a few other things like that, but I'm not sure there's a
|
||||||
// way to reuse those here.
|
// 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) {
|
if (slot < NativeObject::MAX_FIXED_SLOTS) {
|
||||||
masm.loadValue(Address(ObjectReg, NativeObject::getFixedSlotOffset(slot)),
|
masm.loadValue(Address(ObjectReg, NativeObject::getFixedSlotOffset(slot)),
|
||||||
JSReturnOperand);
|
JSReturnOperand);
|
||||||
|
@ -11509,6 +11514,11 @@ CodeGenerator::visitGetDOMMemberV(LGetDOMMemberV* ins)
|
||||||
// require us to have MGetDOMMember inherit from MLoadFixedSlot, and then
|
// 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
|
// we'd have to duplicate a bunch of stuff we now get for free from
|
||||||
// MGetDOMProperty.
|
// 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());
|
Register object = ToRegister(ins->object());
|
||||||
size_t slot = ins->mir()->domMemberSlotIndex();
|
size_t slot = ins->mir()->domMemberSlotIndex();
|
||||||
ValueOperand result = GetValueOutput(ins);
|
ValueOperand result = GetValueOutput(ins);
|
||||||
|
@ -11524,6 +11534,11 @@ CodeGenerator::visitGetDOMMemberT(LGetDOMMemberT* ins)
|
||||||
// require us to have MGetDOMMember inherit from MLoadFixedSlot, and then
|
// 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
|
// we'd have to duplicate a bunch of stuff we now get for free from
|
||||||
// MGetDOMProperty.
|
// 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());
|
Register object = ToRegister(ins->object());
|
||||||
size_t slot = ins->mir()->domMemberSlotIndex();
|
size_t slot = ins->mir()->domMemberSlotIndex();
|
||||||
AnyRegister result = ToAnyRegister(ins->getDef(0));
|
AnyRegister result = ToAnyRegister(ins->getDef(0));
|
||||||
|
|
|
@ -10881,11 +10881,18 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
|
||||||
|
|
||||||
if (isDOM) {
|
if (isDOM) {
|
||||||
const JSJitInfo* jitinfo = commonGetter->jitInfo();
|
const JSJitInfo* jitinfo = commonGetter->jitInfo();
|
||||||
|
// 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;
|
MInstruction* get;
|
||||||
if (jitinfo->isAlwaysInSlot) {
|
if (jitinfo->isAlwaysInSlot) {
|
||||||
// If our object is a singleton and we know the property is
|
// 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
|
// 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.
|
// anything), we can just read the slot here and use that
|
||||||
|
// constant.
|
||||||
JSObject* singleton = objTypes->maybeSingleton();
|
JSObject* singleton = objTypes->maybeSingleton();
|
||||||
if (singleton && jitinfo->aliasSet() == JSJitInfo::AliasNone) {
|
if (singleton && jitinfo->aliasSet() == JSJitInfo::AliasNone) {
|
||||||
size_t slot = jitinfo->slotIndex;
|
size_t slot = jitinfo->slotIndex;
|
||||||
|
@ -10894,8 +10901,9 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can't use MLoadFixedSlot here because it might not have the
|
// We can't use MLoadFixedSlot here because it might not have
|
||||||
// right aliasing behavior; we want to alias DOM setters as needed.
|
// the right aliasing behavior; we want to alias DOM setters as
|
||||||
|
// needed.
|
||||||
get = MGetDOMMember::New(alloc(), jitinfo, obj, guard, globalGuard);
|
get = MGetDOMMember::New(alloc(), jitinfo, obj, guard, globalGuard);
|
||||||
} else {
|
} else {
|
||||||
get = MGetDOMProperty::New(alloc(), jitinfo, obj, guard, globalGuard);
|
get = MGetDOMProperty::New(alloc(), jitinfo, obj, guard, globalGuard);
|
||||||
|
@ -10914,6 +10922,7 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
|
||||||
*emitted = true;
|
*emitted = true;
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Don't call the getter with a primitive value.
|
// Don't call the getter with a primitive value.
|
||||||
if (obj->type() != MIRType::Object) {
|
if (obj->type() != MIRType::Object) {
|
||||||
|
|
|
@ -45,9 +45,6 @@
|
||||||
|
|
||||||
using js::shell::RCFile;
|
using js::shell::RCFile;
|
||||||
|
|
||||||
static RCFile** gErrFilePtr = nullptr;
|
|
||||||
static RCFile** gOutFilePtr = nullptr;
|
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace shell {
|
namespace shell {
|
||||||
|
|
||||||
|
@ -555,13 +552,15 @@ Redirect(JSContext* cx, const CallArgs& args, RCFile** outFile)
|
||||||
static bool
|
static bool
|
||||||
osfile_redirectOutput(JSContext* cx, unsigned argc, Value* vp) {
|
osfile_redirectOutput(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
return Redirect(cx, args, gOutFilePtr);
|
ShellContext* scx = GetShellContext(cx);
|
||||||
|
return Redirect(cx, args, scx->outFilePtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
osfile_redirectError(JSContext* cx, unsigned argc, Value* vp) {
|
osfile_redirectError(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
return Redirect(cx, args, gErrFilePtr);
|
ShellContext* scx = GetShellContext(cx);
|
||||||
|
return Redirect(cx, args, scx->errFilePtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -1010,8 +1009,9 @@ DefineOS(JSContext* cx, HandleObject global,
|
||||||
if (!GenerateInterfaceHelp(cx, obj, "os"))
|
if (!GenerateInterfaceHelp(cx, obj, "os"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
gOutFilePtr = shellOut;
|
ShellContext* scx = GetShellContext(cx);
|
||||||
gErrFilePtr = shellErr;
|
scx->outFilePtr = shellOut;
|
||||||
|
scx->errFilePtr = shellErr;
|
||||||
|
|
||||||
// For backwards compatibility, expose various os.file.* functions as
|
// For backwards compatibility, expose various os.file.* functions as
|
||||||
// direct methods on the global.
|
// direct methods on the global.
|
||||||
|
|
|
@ -113,6 +113,8 @@ using namespace js;
|
||||||
using namespace js::cli;
|
using namespace js::cli;
|
||||||
using namespace js::shell;
|
using namespace js::shell;
|
||||||
|
|
||||||
|
using js::shell::RCFile;
|
||||||
|
|
||||||
using mozilla::ArrayLength;
|
using mozilla::ArrayLength;
|
||||||
using mozilla::Atomic;
|
using mozilla::Atomic;
|
||||||
using mozilla::MakeScopeExit;
|
using mozilla::MakeScopeExit;
|
||||||
|
@ -152,35 +154,8 @@ static const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(1800.
|
||||||
// SharedArrayBuffer and Atomics are enabled by default (tracking Firefox).
|
// SharedArrayBuffer and Atomics are enabled by default (tracking Firefox).
|
||||||
#define SHARED_MEMORY_DEFAULT 1
|
#define SHARED_MEMORY_DEFAULT 1
|
||||||
|
|
||||||
// Some platform hooks must be implemented for single-step profiling.
|
bool
|
||||||
#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS64)
|
OffThreadState::startIfIdle(JSContext* cx, ScriptKind kind, ScopedJSFreePtr<char16_t>& newSource)
|
||||||
# define SINGLESTEP_PROFILING
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
AutoLockMonitor alm(monitor);
|
AutoLockMonitor alm(monitor);
|
||||||
if (state != IDLE)
|
if (state != IDLE)
|
||||||
|
@ -195,8 +170,8 @@ class OffThreadState {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool startIfIdle(JSContext* cx, ScriptKind kind,
|
bool
|
||||||
JS::TranscodeBuffer&& newXdr)
|
OffThreadState::startIfIdle(JSContext* cx, ScriptKind kind, JS::TranscodeBuffer&& newXdr)
|
||||||
{
|
{
|
||||||
AutoLockMonitor alm(monitor);
|
AutoLockMonitor alm(monitor);
|
||||||
if (state != IDLE)
|
if (state != IDLE)
|
||||||
|
@ -211,7 +186,9 @@ class OffThreadState {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void abandon(JSContext* cx) {
|
void
|
||||||
|
OffThreadState::abandon(JSContext* cx)
|
||||||
|
{
|
||||||
AutoLockMonitor alm(monitor);
|
AutoLockMonitor alm(monitor);
|
||||||
MOZ_ASSERT(state == COMPILING);
|
MOZ_ASSERT(state == COMPILING);
|
||||||
MOZ_ASSERT(!token);
|
MOZ_ASSERT(!token);
|
||||||
|
@ -225,7 +202,9 @@ class OffThreadState {
|
||||||
state = IDLE;
|
state = IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void markDone(void* newToken) {
|
void
|
||||||
|
OffThreadState::markDone(void* newToken)
|
||||||
|
{
|
||||||
AutoLockMonitor alm(monitor);
|
AutoLockMonitor alm(monitor);
|
||||||
MOZ_ASSERT(state == COMPILING);
|
MOZ_ASSERT(state == COMPILING);
|
||||||
MOZ_ASSERT(!token);
|
MOZ_ASSERT(!token);
|
||||||
|
@ -237,7 +216,9 @@ class OffThreadState {
|
||||||
alm.notify();
|
alm.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* waitUntilDone(JSContext* cx, ScriptKind kind) {
|
void*
|
||||||
|
OffThreadState::waitUntilDone(JSContext* cx, ScriptKind kind)
|
||||||
|
{
|
||||||
AutoLockMonitor alm(monitor);
|
AutoLockMonitor alm(monitor);
|
||||||
if (state == IDLE || scriptKind != kind)
|
if (state == IDLE || scriptKind != kind)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -260,81 +241,10 @@ class OffThreadState {
|
||||||
return holdToken;
|
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>
|
|
||||||
{
|
|
||||||
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>;
|
|
||||||
|
|
||||||
struct ShellCompartmentPrivate {
|
struct ShellCompartmentPrivate {
|
||||||
JS::Heap<JSObject*> grayRoot;
|
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 {
|
struct MOZ_STACK_CLASS EnvironmentPreparer : public js::ScriptEnvironmentPreparer {
|
||||||
JSContext* cx;
|
JSContext* cx;
|
||||||
explicit EnvironmentPreparer(JSContext* cx)
|
explicit EnvironmentPreparer(JSContext* cx)
|
||||||
|
@ -476,11 +386,13 @@ ShellContext::ShellContext(JSContext* cx)
|
||||||
exitCode(0),
|
exitCode(0),
|
||||||
quitting(false),
|
quitting(false),
|
||||||
readLineBufPos(0),
|
readLineBufPos(0),
|
||||||
|
errFilePtr(nullptr),
|
||||||
|
outFilePtr(nullptr),
|
||||||
geckoProfilingStackSize(0)
|
geckoProfilingStackSize(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
static ShellContext*
|
ShellContext*
|
||||||
GetShellContext(JSContext* cx)
|
js::shell::GetShellContext(JSContext* cx)
|
||||||
{
|
{
|
||||||
ShellContext* sc = static_cast<ShellContext*>(JS_GetContextPrivate(cx));
|
ShellContext* sc = static_cast<ShellContext*>(JS_GetContextPrivate(cx));
|
||||||
MOZ_ASSERT(sc);
|
MOZ_ASSERT(sc);
|
||||||
|
|
|
@ -7,8 +7,25 @@
|
||||||
#ifndef jsshell_js_h
|
#ifndef jsshell_js_h
|
||||||
#define jsshell_js_h
|
#define jsshell_js_h
|
||||||
|
|
||||||
|
#include "mozilla/Atomics.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "mozilla/TimeStamp.h"
|
||||||
|
|
||||||
#include "jsapi.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 js {
|
||||||
namespace shell {
|
namespace shell {
|
||||||
|
|
||||||
|
@ -90,6 +107,115 @@ struct RCFile {
|
||||||
bool
|
bool
|
||||||
CreateAlias(JSContext* cx, const char* dstName, JS::HandleObject namespaceObj, const char* srcName);
|
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 shell */
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
|
|
|
@ -2409,6 +2409,27 @@ TemporaryTypeSet::maybeCallable(CompilerConstraintList* constraints)
|
||||||
return false;
|
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
|
bool
|
||||||
TemporaryTypeSet::maybeEmulatesUndefined(CompilerConstraintList* constraints)
|
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. */
|
/* Whether clasp->isCallable() is true for one or more objects in this set. */
|
||||||
bool maybeCallable(CompilerConstraintList* constraints);
|
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. */
|
/* Whether clasp->emulatesUndefined() is true for one or more objects in this set. */
|
||||||
bool maybeEmulatesUndefined(CompilerConstraintList* constraints);
|
bool maybeEmulatesUndefined(CompilerConstraintList* constraints);
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#define DOC_ELEM_INSERTED_TOPIC "document-element-inserted"
|
#define DOC_ELEM_INSERTED_TOPIC "document-element-inserted"
|
||||||
#define CLEANUP_TOPIC "xpcom-shutdown"
|
#define CLEANUP_TOPIC "xpcom-shutdown"
|
||||||
#define SHUTDOWN_TOPIC "quit-application-granted"
|
#define SHUTDOWN_TOPIC "quit-application-granted"
|
||||||
#define CACHE_FLUSH_TOPIC "startupcache-invalidate"
|
#define CACHE_INVALIDATE_TOPIC "startupcache-invalidate"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -163,7 +163,9 @@ ScriptPreloader::InitContentChild(ContentParent& parent)
|
||||||
cache.mInitializedProcesses += processType;
|
cache.mInitializedProcesses += processType;
|
||||||
|
|
||||||
auto fd = cache.mCacheData.cloneFileDescriptor();
|
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);
|
Unused << parent.SendPScriptCacheConstructor(fd, wantScriptData);
|
||||||
} else {
|
} else {
|
||||||
Unused << parent.SendPScriptCacheConstructor(NS_ERROR_FILE_NOT_FOUND, wantScriptData);
|
Unused << parent.SendPScriptCacheConstructor(NS_ERROR_FILE_NOT_FOUND, wantScriptData);
|
||||||
|
@ -227,7 +229,7 @@ ScriptPreloader::ScriptPreloader()
|
||||||
}
|
}
|
||||||
obs->AddObserver(this, SHUTDOWN_TOPIC, false);
|
obs->AddObserver(this, SHUTDOWN_TOPIC, false);
|
||||||
obs->AddObserver(this, CLEANUP_TOPIC, false);
|
obs->AddObserver(this, CLEANUP_TOPIC, false);
|
||||||
obs->AddObserver(this, CACHE_FLUSH_TOPIC, false);
|
obs->AddObserver(this, CACHE_INVALIDATE_TOPIC, false);
|
||||||
|
|
||||||
AutoSafeJSAPI jsapi;
|
AutoSafeJSAPI jsapi;
|
||||||
JS_AddExtraGCRootsTracer(jsapi.cx(), TraceOp, this);
|
JS_AddExtraGCRootsTracer(jsapi.cx(), TraceOp, this);
|
||||||
|
@ -265,10 +267,12 @@ ScriptPreloader::Cleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ScriptPreloader::FlushCache()
|
ScriptPreloader::InvalidateCache()
|
||||||
{
|
{
|
||||||
MonitorAutoLock mal(mMonitor);
|
MonitorAutoLock mal(mMonitor);
|
||||||
|
|
||||||
|
mCacheInvalidated = true;
|
||||||
|
|
||||||
for (auto& script : IterHash(mScripts)) {
|
for (auto& script : IterHash(mScripts)) {
|
||||||
// We can only purge finished scripts here. Async scripts that are
|
// We can only purge finished scripts here. Async scripts that are
|
||||||
// still being parsed off-thread have a non-refcounted reference to
|
// 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();
|
ForceWriteCacheFile();
|
||||||
} else if (!strcmp(topic, CLEANUP_TOPIC)) {
|
} else if (!strcmp(topic, CLEANUP_TOPIC)) {
|
||||||
Cleanup();
|
Cleanup();
|
||||||
} else if (!strcmp(topic, CACHE_FLUSH_TOPIC)) {
|
} else if (!strcmp(topic, CACHE_INVALIDATE_TOPIC)) {
|
||||||
FlushCache();
|
InvalidateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
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->UpdateLoadTime(loadTime);
|
||||||
script->mProcessTypes += processType;
|
script->mProcessTypes += processType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,7 +350,7 @@ private:
|
||||||
void ForceWriteCacheFile();
|
void ForceWriteCacheFile();
|
||||||
void Cleanup();
|
void Cleanup();
|
||||||
|
|
||||||
void FlushCache();
|
void InvalidateCache();
|
||||||
|
|
||||||
// Opens the cache file for reading.
|
// Opens the cache file for reading.
|
||||||
Result<Ok, nsresult> OpenCache();
|
Result<Ok, nsresult> OpenCache();
|
||||||
|
@ -404,6 +404,7 @@ private:
|
||||||
bool mCacheInitialized = false;
|
bool mCacheInitialized = false;
|
||||||
bool mSaveComplete = false;
|
bool mSaveComplete = false;
|
||||||
bool mDataPrepared = false;
|
bool mDataPrepared = false;
|
||||||
|
bool mCacheInvalidated = false;
|
||||||
|
|
||||||
// The process type of the current process.
|
// The process type of the current process.
|
||||||
static ProcessType sProcessType;
|
static ProcessType sProcessType;
|
||||||
|
|
|
@ -1708,7 +1708,15 @@ public class BrowserApp extends GeckoApp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toggleToolbarChrome(final boolean aShow) {
|
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() {
|
public void refreshToolbarHeight() {
|
||||||
|
@ -1730,22 +1738,17 @@ public class BrowserApp extends GeckoApp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void toggleChrome(final boolean aShow) {
|
void toggleChrome(final boolean aShow) {
|
||||||
if (aShow) {
|
if (mDynamicToolbar != null) {
|
||||||
mBrowserChrome.setVisibility(View.VISIBLE);
|
mDynamicToolbar.setVisible(aShow, VisibilityTransition.IMMEDIATE);
|
||||||
} 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.toggleChrome(aShow);
|
super.toggleChrome(aShow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void focusChrome() {
|
void focusChrome() {
|
||||||
mBrowserChrome.setVisibility(View.VISIBLE);
|
if (mDynamicToolbar != null) {
|
||||||
|
mDynamicToolbar.setVisible(true, VisibilityTransition.IMMEDIATE);
|
||||||
|
}
|
||||||
mActionBarFlipper.requestFocusFromTouch();
|
mActionBarFlipper.requestFocusFromTouch();
|
||||||
|
|
||||||
super.focusChrome();
|
super.focusChrome();
|
||||||
|
|
|
@ -481,6 +481,11 @@ nsHttpHandler::Init()
|
||||||
"net:current-toplevel-outer-content-windowid",
|
"net:current-toplevel-outer-content-windowid",
|
||||||
true);
|
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
|
// disabled as its a nop right now
|
||||||
// obsService->AddObserver(this, "net:failed-to-process-uri-content", true);
|
// obsService->AddObserver(this, "net:failed-to-process-uri-content", true);
|
||||||
}
|
}
|
||||||
|
@ -648,7 +653,6 @@ nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter()
|
||||||
if (mFastOpenConsecutiveFailureCounter == mFastOpenConsecutiveFailureLimit) {
|
if (mFastOpenConsecutiveFailureCounter == mFastOpenConsecutiveFailureLimit) {
|
||||||
LOG(("nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter - "
|
LOG(("nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter - "
|
||||||
"Fast open failed too many times"));
|
"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;
|
return NS_OK;
|
||||||
|
|
|
@ -164,7 +164,11 @@ public:
|
||||||
return mTCPKeepaliveLongLivedIdleTimeS;
|
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
|
// 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
|
// fast open, it means that Fast Open is turned off so we will not try again
|
||||||
// until a restart. This is only on Linux.
|
// 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
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
import sys
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from firefox_puppeteer import PuppeteerMixin
|
from firefox_puppeteer import PuppeteerMixin
|
||||||
from marionette_driver import Wait
|
from marionette_driver import Wait
|
||||||
from marionette_harness import MarionetteTestCase
|
from marionette_harness import MarionetteTestCase
|
||||||
|
@ -57,25 +54,3 @@ class TestBrowserWindowShortcuts(PuppeteerMixin, MarionetteTestCase):
|
||||||
return selection_name == "input"
|
return selection_name == "input"
|
||||||
|
|
||||||
Wait(self.marionette).until(has_input_selected)
|
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:
|
if kwargs[modifier] is True:
|
||||||
keys.append(keymap[modifier])
|
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()
|
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);';
|
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.addMessageListener("chromeEvent", messageHandler);
|
||||||
|
messageManager.loadFrameScript(listener, true);
|
||||||
}
|
}
|
||||||
if (gConfig.e10s) {
|
if (gConfig.e10s) {
|
||||||
e10s_init();
|
e10s_init();
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
// added until then.
|
// added until then.
|
||||||
window.addEventListener("MozAfterPaint", function() {
|
window.addEventListener("MozAfterPaint", function() {
|
||||||
setTimeout(redirectToHarness, 0);
|
setTimeout(redirectToHarness, 0);
|
||||||
|
// In case the listener was not ready, try again after a few seconds.
|
||||||
|
setTimeout(redirectToHarness, 5000);
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12914,7 +12914,7 @@
|
||||||
},
|
},
|
||||||
"DISPLAY_ITEM_USAGE_COUNT": {
|
"DISPLAY_ITEM_USAGE_COUNT": {
|
||||||
"record_in_processes": ["main", "content"],
|
"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],
|
"bug_numbers": [1353521],
|
||||||
"expires_in_version": "56",
|
"expires_in_version": "56",
|
||||||
"kind": "enumerated",
|
"kind": "enumerated",
|
||||||
|
|
|
@ -61,17 +61,23 @@ public:
|
||||||
: mIsBackground(aRunnable->IsBackground())
|
: mIsBackground(aRunnable->IsBackground())
|
||||||
{
|
{
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
|
// Telemetry collection temporarily disabled in bug 1366156.
|
||||||
|
#if 0
|
||||||
#ifdef EARLY_BETA_OR_EARLIER
|
#ifdef EARLY_BETA_OR_EARLIER
|
||||||
aRunnable->GetName(mKey);
|
aRunnable->GetName(mKey);
|
||||||
mStart = TimeStamp::Now();
|
mStart = TimeStamp::Now();
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
~AutoCollectVsyncTelemetry()
|
~AutoCollectVsyncTelemetry()
|
||||||
{
|
{
|
||||||
|
// Telemetry collection temporarily disabled in bug 1366156.
|
||||||
|
#if 0
|
||||||
#ifdef EARLY_BETA_OR_EARLIER
|
#ifdef EARLY_BETA_OR_EARLIER
|
||||||
if (Telemetry::CanRecordBase()) {
|
if (Telemetry::CanRecordBase()) {
|
||||||
CollectTelemetry();
|
CollectTelemetry();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче