Merge latest green b2g-inbound changeset and mozilla-central

This commit is contained in:
Ed Morley 2013-10-25 17:27:25 +01:00
commit 6cdb8fe911
60 changed files with 887 additions and 146 deletions

View File

@ -502,8 +502,8 @@ Element::GetScrollFrame(nsIFrame **aStyledFrame, bool aFlushLayout)
// menu frames implement GetScrollTargetFrame but we don't want // menu frames implement GetScrollTargetFrame but we don't want
// to use it here. Similar for comboboxes. // to use it here. Similar for comboboxes.
if (frame->GetType() != nsGkAtoms::menuFrame && nsIAtom* type = frame->GetType();
frame->GetType() != nsGkAtoms::comboboxControlFrame) { if (type != nsGkAtoms::menuFrame && type != nsGkAtoms::comboboxControlFrame) {
nsIScrollableFrame *scrollFrame = frame->GetScrollTargetFrame(); nsIScrollableFrame *scrollFrame = frame->GetScrollTargetFrame();
if (scrollFrame) if (scrollFrame)
return scrollFrame; return scrollFrame;

View File

@ -532,9 +532,9 @@ public:
} }
} }
void RemoveTextTrack(TextTrack* aTextTrack) { void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly = false) {
if (mTextTrackManager) { if (mTextTrackManager) {
mTextTrackManager->RemoveTextTrack(aTextTrack); mTextTrackManager->RemoveTextTrack(aTextTrack, aPendingListOnly);
} }
} }
@ -862,6 +862,11 @@ protected:
// Update the audio channel playing state // Update the audio channel playing state
virtual void UpdateAudioChannelPlayingState(); virtual void UpdateAudioChannelPlayingState();
// Adds to the element's list of pending text tracks each text track
// in the element's list of text tracks whose text track mode is not disabled
// and whose text track readiness state is loading.
void PopulatePendingTextTrackList();
// The current decoder. Load() has been called on this decoder. // The current decoder. Load() has been called on this decoder.
// At most one of mDecoder and mSrcStream can be non-null. // At most one of mDecoder and mSrcStream can be non-null.
nsRefPtr<MediaDecoder> mDecoder; nsRefPtr<MediaDecoder> mDecoder;

View File

@ -3920,5 +3920,13 @@ HTMLMediaElement::AddTextTrack(TextTrackKind aKind,
: nullptr; : nullptr;
} }
void
HTMLMediaElement::PopulatePendingTextTrackList()
{
if (mTextTrackManager) {
mTextTrackManager->PopulatePendingList();
}
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -67,7 +67,6 @@ static const char* kKindTableDefaultString = kKindTable->tag;
/** HTMLTrackElement */ /** HTMLTrackElement */
HTMLTrackElement::HTMLTrackElement(already_AddRefed<nsINodeInfo> aNodeInfo) HTMLTrackElement::HTMLTrackElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo) : nsGenericHTMLElement(aNodeInfo)
, mReadyState(NONE)
{ {
#ifdef PR_LOGGING #ifdef PR_LOGGING
if (!gTrackElementLog) { if (!gTrackElementLog) {
@ -305,5 +304,15 @@ HTMLTrackElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
} }
uint16_t
HTMLTrackElement::ReadyState() const
{
if (!mTrack) {
return NONE;
}
return mTrack->ReadyState();
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -102,10 +102,7 @@ public:
LOADED = 2U, LOADED = 2U,
ERROR = 3U ERROR = 3U
}; };
uint16_t ReadyState() const uint16_t ReadyState() const;
{
return mReadyState;
}
TextTrack* Track(); TextTrack* Track();
@ -157,7 +154,6 @@ protected:
nsCOMPtr<nsIChannel> mChannel; nsCOMPtr<nsIChannel> mChannel;
nsRefPtr<HTMLMediaElement> mMediaParent; nsRefPtr<HTMLMediaElement> mMediaParent;
nsRefPtr<WebVTTListener> mListener; nsRefPtr<WebVTTListener> mListener;
uint16_t mReadyState;
void CreateTextTrack(); void CreateTextTrack();
}; };

View File

@ -7,11 +7,12 @@
#include "mozilla/dom/TextTrackManager.h" #include "mozilla/dom/TextTrackManager.h"
#include "mozilla/dom/HTMLMediaElement.h" #include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/dom/HTMLTrackElement.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
NS_IMPL_CYCLE_COLLECTION_1(TextTrackManager, mTextTracks) NS_IMPL_CYCLE_COLLECTION_2(TextTrackManager, mTextTracks, mPendingTextTracks)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(TextTrackManager, AddRef) NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(TextTrackManager, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(TextTrackManager, Release) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(TextTrackManager, Release)
@ -20,6 +21,8 @@ TextTrackManager::TextTrackManager(HTMLMediaElement *aMediaElement)
{ {
MOZ_COUNT_CTOR(TextTrackManager); MOZ_COUNT_CTOR(TextTrackManager);
mTextTracks = new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject()); mTextTracks = new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject());
mPendingTextTracks =
new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject());
} }
TextTrackManager::~TextTrackManager() TextTrackManager::~TextTrackManager()
@ -37,7 +40,10 @@ already_AddRefed<TextTrack>
TextTrackManager::AddTextTrack(TextTrackKind aKind, const nsAString& aLabel, TextTrackManager::AddTextTrack(TextTrackKind aKind, const nsAString& aLabel,
const nsAString& aLanguage) const nsAString& aLanguage)
{ {
return mTextTracks->AddTextTrack(mMediaElement, aKind, aLabel, aLanguage); nsRefPtr<TextTrack> ttrack =
mTextTracks->AddTextTrack(mMediaElement, aKind, aLabel, aLanguage);
ttrack->SetReadyState(HTMLTrackElement::LOADED);
return ttrack.forget();
} }
void void
@ -47,8 +53,13 @@ TextTrackManager::AddTextTrack(TextTrack* aTextTrack)
} }
void void
TextTrackManager::RemoveTextTrack(TextTrack* aTextTrack) TextTrackManager::RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly)
{ {
mPendingTextTracks->RemoveTextTrack(aTextTrack);
if (aPendingListOnly) {
return;
}
mTextTracks->RemoveTextTrack(aTextTrack); mTextTracks->RemoveTextTrack(aTextTrack);
} }
@ -64,5 +75,19 @@ TextTrackManager::Update(double aTime)
mTextTracks->Update(aTime); mTextTracks->Update(aTime);
} }
void
TextTrackManager::PopulatePendingList()
{
uint32_t len = mTextTracks->Length();
bool dummy;
for (uint32_t index = 0; index < len; ++index) {
TextTrack* ttrack = mTextTracks->IndexedGetter(index, dummy);
if (ttrack && ttrack->Mode() != TextTrackMode::Disabled &&
ttrack->ReadyState() == HTMLTrackElement::LOADING) {
mPendingTextTracks->AddTextTrack(ttrack);
}
}
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -30,13 +30,15 @@ public:
const nsAString& aLabel, const nsAString& aLabel,
const nsAString& aLanguage); const nsAString& aLanguage);
void AddTextTrack(TextTrack* aTextTrack); void AddTextTrack(TextTrack* aTextTrack);
void RemoveTextTrack(TextTrack* aTextTrack); void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly);
void DidSeek(); void DidSeek();
// Update the display of cues on the video as per the current play back time // Update the display of cues on the video as per the current play back time
// of aTime. // of aTime.
void Update(double aTime); void Update(double aTime);
void PopulatePendingList();
private: private:
// The HTMLMediaElement that this TextTrackManager manages the TextTracks of. // The HTMLMediaElement that this TextTrackManager manages the TextTracks of.
// This is a weak reference as the life time of TextTrackManager is dependent // This is a weak reference as the life time of TextTrackManager is dependent
@ -45,6 +47,8 @@ private:
HTMLMediaElement* mMediaElement; HTMLMediaElement* mMediaElement;
// List of the TextTrackManager's owning HTMLMediaElement's TextTracks. // List of the TextTrackManager's owning HTMLMediaElement's TextTracks.
nsRefPtr<TextTrackList> mTextTracks; nsRefPtr<TextTrackList> mTextTracks;
// List of text track objects awaiting loading.
nsRefPtr<TextTrackList> mPendingTextTracks;
}; };
} // namespace dom } // namespace dom

View File

@ -11,6 +11,7 @@
#include "mozilla/dom/TextTrackRegion.h" #include "mozilla/dom/TextTrackRegion.h"
#include "mozilla/dom/TextTrackRegionList.h" #include "mozilla/dom/TextTrackRegionList.h"
#include "mozilla/dom/HTMLMediaElement.h" #include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/dom/HTMLTrackElement.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -68,6 +69,7 @@ TextTrack::SetDefaultSettings()
mRegionList = new TextTrackRegionList(mParent); mRegionList = new TextTrackRegionList(mParent);
mCuePos = 0; mCuePos = 0;
mDirty = false; mDirty = false;
mReadyState = HTMLTrackElement::NONE;
} }
void void
@ -170,5 +172,21 @@ TextTrack::GetActiveCues()
return mActiveCueList; return mActiveCueList;
} }
uint16_t
TextTrack::ReadyState() const
{
return mReadyState;
}
void
TextTrack::SetReadyState(uint16_t aState)
{
mReadyState = aState;
if (mReadyState == HTMLTrackElement::LOADED ||
mReadyState == HTMLTrackElement::ERROR) {
mMediaElement->RemoveTextTrack(this, true);
}
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -92,6 +92,9 @@ public:
return nullptr; return nullptr;
} }
uint16_t ReadyState() const;
void SetReadyState(uint16_t aState);
void AddRegion(TextTrackRegion& aRegion); void AddRegion(TextTrackRegion& aRegion);
void RemoveRegion(const TextTrackRegion& aRegion, ErrorResult& aRv); void RemoveRegion(const TextTrackRegion& aRegion, ErrorResult& aRv);
@ -121,6 +124,7 @@ private:
nsRefPtr<TextTrackRegionList> mRegionList; nsRefPtr<TextTrackRegionList> mRegionList;
uint32_t mCuePos; uint32_t mCuePos;
uint16_t mReadyState;
bool mDirty; bool mDirty;
}; };

View File

@ -78,7 +78,7 @@ WebVTTListener::LoadResource()
rv = mParserWrapper->Watch(this); rv = mParserWrapper->Watch(this);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mElement->mReadyState = HTMLTrackElement::LOADING; mElement->mTrack->SetReadyState(HTMLTrackElement::LOADING);
return NS_OK; return NS_OK;
} }
@ -106,8 +106,8 @@ WebVTTListener::OnStopRequest(nsIRequest* aRequest,
nsISupports* aContext, nsISupports* aContext,
nsresult aStatus) nsresult aStatus)
{ {
if (mElement->mReadyState != HTMLTrackElement::ERROR) { if (mElement->ReadyState() != HTMLTrackElement::ERROR) {
mElement->mReadyState = HTMLTrackElement::LOADED; mElement->mTrack->SetReadyState(HTMLTrackElement::LOADED);
} }
// Attempt to parse any final data the parser might still have. // Attempt to parse any final data the parser might still have.
mParserWrapper->Flush(); mParserWrapper->Flush();

View File

@ -17,9 +17,10 @@ namespace dom {
// //
// Basic (virtual) BarProp class implementation // Basic (virtual) BarProp class implementation
// //
BarProp::BarProp(nsGlobalWindow *aWindow) BarProp::BarProp(nsGlobalWindow* aWindow)
: mDOMWindow(aWindow) : mDOMWindow(aWindow)
{ {
MOZ_ASSERT(aWindow->IsInnerWindow());
SetIsDOMBinding(); SetIsDOMBinding();
} }

View File

@ -3665,7 +3665,7 @@ nsGlobalWindow::GetPrompter(nsIPrompt** aPrompt)
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalWindow::GetMenubar(nsISupports** aMenubar) nsGlobalWindow::GetMenubar(nsISupports** aMenubar)
{ {
FORWARD_TO_OUTER(GetMenubar, (aMenubar), NS_ERROR_NOT_INITIALIZED); FORWARD_TO_INNER(GetMenubar, (aMenubar), NS_ERROR_NOT_INITIALIZED);
*aMenubar = nullptr; *aMenubar = nullptr;
@ -3684,7 +3684,7 @@ nsGlobalWindow::GetMenubar(nsISupports** aMenubar)
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalWindow::GetToolbar(nsISupports** aToolbar) nsGlobalWindow::GetToolbar(nsISupports** aToolbar)
{ {
FORWARD_TO_OUTER(GetToolbar, (aToolbar), NS_ERROR_NOT_INITIALIZED); FORWARD_TO_INNER(GetToolbar, (aToolbar), NS_ERROR_NOT_INITIALIZED);
*aToolbar = nullptr; *aToolbar = nullptr;
@ -3703,7 +3703,7 @@ nsGlobalWindow::GetToolbar(nsISupports** aToolbar)
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalWindow::GetLocationbar(nsISupports** aLocationbar) nsGlobalWindow::GetLocationbar(nsISupports** aLocationbar)
{ {
FORWARD_TO_OUTER(GetLocationbar, (aLocationbar), NS_ERROR_NOT_INITIALIZED); FORWARD_TO_INNER(GetLocationbar, (aLocationbar), NS_ERROR_NOT_INITIALIZED);
*aLocationbar = nullptr; *aLocationbar = nullptr;
@ -3722,7 +3722,7 @@ nsGlobalWindow::GetLocationbar(nsISupports** aLocationbar)
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalWindow::GetPersonalbar(nsISupports** aPersonalbar) nsGlobalWindow::GetPersonalbar(nsISupports** aPersonalbar)
{ {
FORWARD_TO_OUTER(GetPersonalbar, (aPersonalbar), NS_ERROR_NOT_INITIALIZED); FORWARD_TO_INNER(GetPersonalbar, (aPersonalbar), NS_ERROR_NOT_INITIALIZED);
*aPersonalbar = nullptr; *aPersonalbar = nullptr;
@ -3741,7 +3741,7 @@ nsGlobalWindow::GetPersonalbar(nsISupports** aPersonalbar)
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalWindow::GetStatusbar(nsISupports** aStatusbar) nsGlobalWindow::GetStatusbar(nsISupports** aStatusbar)
{ {
FORWARD_TO_OUTER(GetStatusbar, (aStatusbar), NS_ERROR_NOT_INITIALIZED); FORWARD_TO_INNER(GetStatusbar, (aStatusbar), NS_ERROR_NOT_INITIALIZED);
*aStatusbar = nullptr; *aStatusbar = nullptr;
@ -3758,8 +3758,9 @@ nsGlobalWindow::GetStatusbar(nsISupports** aStatusbar)
} }
mozilla::dom::BarProp* mozilla::dom::BarProp*
nsGlobalWindow::Scrollbars() nsGlobalWindow::GetScrollbars()
{ {
FORWARD_TO_INNER(GetScrollbars, (), nullptr);
if (!mScrollbars) { if (!mScrollbars) {
mScrollbars = new ScrollbarsProp(this); mScrollbars = new ScrollbarsProp(this);
} }
@ -3770,9 +3771,7 @@ nsGlobalWindow::Scrollbars()
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalWindow::GetScrollbars(nsISupports** aScrollbars) nsGlobalWindow::GetScrollbars(nsISupports** aScrollbars)
{ {
FORWARD_TO_OUTER(GetScrollbars, (aScrollbars), NS_ERROR_NOT_INITIALIZED); NS_IF_ADDREF(*aScrollbars = GetScrollbars());
NS_ADDREF(*aScrollbars = Scrollbars());
return NS_OK; return NS_OK;
} }

View File

@ -765,7 +765,7 @@ public:
mozilla::dom::SpeechSynthesis* GetSpeechSynthesisInternal(); mozilla::dom::SpeechSynthesis* GetSpeechSynthesisInternal();
#endif #endif
mozilla::dom::BarProp* Scrollbars(); mozilla::dom::BarProp* GetScrollbars();
protected: protected:
// Array of idle observers that are notified of idle events. // Array of idle observers that are notified of idle events.

View File

@ -0,0 +1,5 @@
rex = RegExp("()()()()()()()()()()(z)?(y)");
a = ["sub"];
a[230] = '' + "a"
f = Function.apply(null, a);
"xyz".replace(rex, f);

View File

@ -0,0 +1,44 @@
try{} catch(e){}
function test(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a) {
return 0;
}
test();
test();
/////////////////////
function test2() {
return 0;
}
var a = 1;
test2(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a);
test2(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a);
/////////////////////
function test4() {
test3()
}
function test3(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a) {
return 0;
}
test4();
/////////////////////
function test6() {
test5.apply({}, [])
}
function test5() {
return 0;
}
test6();
test6();

View File

@ -24,6 +24,7 @@ StartArgSlot(JSScript *script, JSFunction *fun)
// When needed: // When needed:
// Slot 2: Argumentsobject. // Slot 2: Argumentsobject.
// Note: when updating this, please also update the assert in SnapshotWriter::startFrame
return 2 + (script->argumentsHasVarBinding() ? 1 : 0); return 2 + (script->argumentsHasVarBinding() ? 1 : 0);
} }
@ -34,6 +35,8 @@ CountArgSlots(JSScript *script, JSFunction *fun)
// Slot x + 1: Argument 1. // Slot x + 1: Argument 1.
// ... // ...
// Slot x + n: Argument n. // Slot x + n: Argument n.
// Note: when updating this, please also update the assert in SnapshotWriter::startFrame
return StartArgSlot(script, fun) + (fun ? fun->nargs + 1 : 0); return StartArgSlot(script, fun) + (fun ? fun->nargs + 1 : 0);
} }

View File

@ -1656,12 +1656,6 @@ IonCompile(JSContext *cx, JSScript *script,
return success ? AbortReason_NoAbort : AbortReason_Disable; return success ? AbortReason_NoAbort : AbortReason_Disable;
} }
static bool
TooManyArguments(unsigned nargs)
{
return (nargs >= SNAPSHOT_MAX_NARGS || nargs > js_IonOptions.maxStackArgs);
}
static bool static bool
CheckFrame(BaselineFrame *frame) CheckFrame(BaselineFrame *frame)
{ {
@ -1902,6 +1896,12 @@ jit::CanEnter(JSContext *cx, RunState &state)
return Method_CantCompile; return Method_CantCompile;
} }
if (TooManyArguments(invoke.args().callee().as<JSFunction>().nargs)) {
IonSpew(IonSpew_Abort, "too many args");
ForbidCompilation(cx, script);
return Method_CantCompile;
}
if (invoke.constructing() && invoke.args().thisv().isPrimitive()) { if (invoke.constructing() && invoke.args().thisv().isPrimitive()) {
RootedScript scriptRoot(cx, script); RootedScript scriptRoot(cx, script);
RootedObject callee(cx, &invoke.args().callee()); RootedObject callee(cx, &invoke.args().callee());

View File

@ -384,6 +384,12 @@ IsIonInlinablePC(jsbytecode *pc) {
return IsCallPC(pc) || IsGetPropPC(pc) || IsSetPropPC(pc); return IsCallPC(pc) || IsGetPropPC(pc) || IsSetPropPC(pc);
} }
inline bool
TooManyArguments(unsigned nargs)
{
return (nargs >= SNAPSHOT_MAX_NARGS || nargs > js_IonOptions.maxStackArgs);
}
void ForbidCompilation(JSContext *cx, JSScript *script); void ForbidCompilation(JSContext *cx, JSScript *script);
void ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode); void ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode);
uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc); uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc);

View File

@ -266,7 +266,7 @@ IonBuilder::canEnterInlinedFunction(JSFunction *target)
} }
bool bool
IonBuilder::canInlineTarget(JSFunction *target, bool constructing) IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo)
{ {
if (!target->isInterpreted()) { if (!target->isInterpreted()) {
IonSpew(IonSpew_Inlining, "Cannot inline due to non-interpreted"); IonSpew(IonSpew_Inlining, "Cannot inline due to non-interpreted");
@ -297,7 +297,7 @@ IonBuilder::canInlineTarget(JSFunction *target, bool constructing)
return false; return false;
} }
if (constructing && !target->isInterpretedConstructor()) { if (callInfo.constructing() && !target->isInterpretedConstructor()) {
IonSpew(IonSpew_Inlining, "Cannot inline because callee is not a constructor"); IonSpew(IonSpew_Inlining, "Cannot inline because callee is not a constructor");
return false; return false;
} }
@ -317,6 +317,18 @@ IonBuilder::canInlineTarget(JSFunction *target, bool constructing)
return false; return false;
} }
if (TooManyArguments(target->nargs)) {
IonSpew(IonSpew_Inlining, "%s:%d Cannot inline too many args",
inlineScript->filename(), inlineScript->lineno);
return false;
}
if (TooManyArguments(callInfo.argc())) {
IonSpew(IonSpew_Inlining, "%s:%d Cannot inline too many args",
inlineScript->filename(), inlineScript->lineno);
return false;
}
// Allow inlining of recursive calls, but only one level deep. // Allow inlining of recursive calls, but only one level deep.
IonBuilder *builder = callerBuilder_; IonBuilder *builder = callerBuilder_;
while (builder) { while (builder) {
@ -3947,7 +3959,7 @@ IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo)
return true; return true;
// Determine whether inlining is possible at callee site // Determine whether inlining is possible at callee site
if (!canInlineTarget(target, callInfo.constructing())) if (!canInlineTarget(target, callInfo))
return false; return false;
// Heuristics! // Heuristics!

View File

@ -231,7 +231,7 @@ class IonBuilder : public MIRGenerator
JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes); JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes);
bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing, bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing,
ObjectVector &targets, uint32_t maxTargets, bool *gotLambda); ObjectVector &targets, uint32_t maxTargets, bool *gotLambda);
bool canInlineTarget(JSFunction *target, bool constructing); bool canInlineTarget(JSFunction *target, CallInfo &callInfo);
void popCfgStack(); void popCfgStack();
DeferredEdge *filterDeadDeferredEdges(DeferredEdge *edge); DeferredEdge *filterDeadDeferredEdges(DeferredEdge *edge);

View File

@ -83,15 +83,19 @@ jit::IonSpewNewFunction(MIRGraph *graph, HandleScript func)
{ {
if (!OffThreadIonCompilationEnabled(GetIonContext()->runtime)) { if (!OffThreadIonCompilationEnabled(GetIonContext()->runtime)) {
ionspewer.beginFunction(graph, func); ionspewer.beginFunction(graph, func);
return;
}
if (!IonSpewEnabled(IonSpew_Logs))
return;
// Ionspewer isn't threads-safe. Therefore logging is disabled for
// off-thread spewing. Throw informative message when trying.
if (func) {
IonSpew(IonSpew_Logs, "Can't log script %s:%d. (Compiled on background thread.)",
func->filename(), func->lineno);
} else { } else {
if (func) { IonSpew(IonSpew_Logs, "Can't log asm.js compilation. (Compiled on background thread.)");
IonSpew(IonSpew_Logs,
"Can't log script %s:%d. (Compiled on background thread.)",
func->filename(), func->lineno);
} else {
IonSpew(IonSpew_Logs,
"Can't log asm.js compilation. (Compiled on background thread.)");
}
} }
} }
@ -342,9 +346,6 @@ jit::CheckLogging()
EnableChannel(IonSpew_BaselineBailouts); EnableChannel(IonSpew_BaselineBailouts);
} }
if (LoggingBits != 0)
EnableIonDebugLogging();
IonSpewFile = stderr; IonSpewFile = stderr;
} }

View File

@ -301,7 +301,10 @@ SnapshotWriter::startSnapshot(uint32_t frameCount, BailoutKind kind, bool resume
void void
SnapshotWriter::startFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, uint32_t exprStack) SnapshotWriter::startFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, uint32_t exprStack)
{ {
JS_ASSERT(CountArgSlots(script, fun) < SNAPSHOT_MAX_NARGS); // Test if we honor the maximum of arguments at all times.
// This is a sanity check and not an algorithm limit. So check might be a bit too loose.
// +4 to account for scope chain, return value, this value and maybe arguments_object.
JS_ASSERT(CountArgSlots(script, fun) < SNAPSHOT_MAX_NARGS + 4);
uint32_t implicit = StartArgSlot(script, fun); uint32_t implicit = StartArgSlot(script, fun);
uint32_t formalArgs = CountArgSlots(script, fun); uint32_t formalArgs = CountArgSlots(script, fun);

View File

@ -3050,39 +3050,50 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
nsIContent* const content = aItem.mContent; nsIContent* const content = aItem.mContent;
nsStyleContext* const styleContext = aItem.mStyleContext; nsStyleContext* const styleContext = aItem.mStyleContext;
nsIFrame* newFrame = NS_NewFieldSetFrame(mPresShell, styleContext); nsIFrame* fieldsetFrame = NS_NewFieldSetFrame(mPresShell, styleContext);
// Initialize it // Initialize it
InitAndRestoreFrame(aState, content, InitAndRestoreFrame(aState, content,
aState.GetGeometricParent(aStyleDisplay, aParentFrame), aState.GetGeometricParent(aStyleDisplay, aParentFrame),
newFrame); fieldsetFrame);
// Resolve style and initialize the frame // Resolve style and initialize the frame
nsRefPtr<nsStyleContext> fieldsetContentStyle; nsRefPtr<nsStyleContext> fieldsetContentStyle;
fieldsetContentStyle = mPresShell->StyleSet()-> fieldsetContentStyle = mPresShell->StyleSet()->
ResolveAnonymousBoxStyle(nsCSSAnonBoxes::fieldsetContent, styleContext); ResolveAnonymousBoxStyle(nsCSSAnonBoxes::fieldsetContent, styleContext);
const nsStyleDisplay* fieldsetContentDisplay = fieldsetContentStyle->StyleDisplay();
bool isScrollable = fieldsetContentDisplay->IsScrollableOverflow();
nsIFrame* scrollFrame = nullptr;
if (isScrollable) {
fieldsetContentStyle =
BeginBuildingScrollFrame(aState, content, fieldsetContentStyle,
fieldsetFrame, nsCSSAnonBoxes::scrolledContent,
false, scrollFrame);
}
nsIFrame* blockFrame = NS_NewBlockFrame(mPresShell, fieldsetContentStyle, nsIFrame* blockFrame = NS_NewBlockFrame(mPresShell, fieldsetContentStyle,
NS_BLOCK_FLOAT_MGR | NS_BLOCK_FLOAT_MGR |
NS_BLOCK_MARGIN_ROOT); NS_BLOCK_MARGIN_ROOT);
InitAndRestoreFrame(aState, content, newFrame, blockFrame); InitAndRestoreFrame(aState, content,
scrollFrame ? scrollFrame : fieldsetFrame, blockFrame);
aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame); aState.AddChild(fieldsetFrame, aFrameItems, content, styleContext, aParentFrame);
// Process children // Process children
nsFrameConstructorSaveState absoluteSaveState; nsFrameConstructorSaveState absoluteSaveState;
nsFrameItems childItems; nsFrameItems childItems;
newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN); blockFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
if (newFrame->IsPositioned()) { if (fieldsetFrame->IsPositioned()) {
aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState); aState.PushAbsoluteContainingBlock(blockFrame, fieldsetFrame, absoluteSaveState);
} }
ProcessChildren(aState, content, styleContext, blockFrame, true, ProcessChildren(aState, content, styleContext, blockFrame, true,
childItems, true, aItem.mPendingBinding); childItems, true, aItem.mPendingBinding);
nsFrameItems fieldsetKids; nsFrameItems fieldsetKids;
fieldsetKids.AddChild(blockFrame); fieldsetKids.AddChild(scrollFrame ? scrollFrame : blockFrame);
for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) { for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) {
nsIFrame* child = e.get(); nsIFrame* child = e.get();
@ -3094,21 +3105,25 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
// GetAdjustedParentFrame() below depends on this frame order. // GetAdjustedParentFrame() below depends on this frame order.
childItems.RemoveFrame(child); childItems.RemoveFrame(child);
// Make sure to reparent the legend so it has the fieldset as the parent. // Make sure to reparent the legend so it has the fieldset as the parent.
fieldsetKids.InsertFrame(newFrame, nullptr, child); fieldsetKids.InsertFrame(fieldsetFrame, nullptr, child);
break; break;
} }
} }
if (isScrollable) {
FinishBuildingScrollFrame(scrollFrame, blockFrame);
}
// Set the inner frame's initial child lists // Set the inner frame's initial child lists
blockFrame->SetInitialChildList(kPrincipalList, childItems); blockFrame->SetInitialChildList(kPrincipalList, childItems);
// Set the outer frame's initial child list // Set the outer frame's initial child list
newFrame->SetInitialChildList(kPrincipalList, fieldsetKids); fieldsetFrame->SetInitialChildList(kPrincipalList, fieldsetKids);
newFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT); fieldsetFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
// Our new frame returned is the outer frame, which is the fieldset frame. // Our new frame returned is the outer frame, which is the fieldset frame.
return newFrame; return fieldsetFrame;
} }
static nsIFrame* static nsIFrame*
@ -3262,6 +3277,17 @@ nsCSSFrameConstructor::FindDataByTag(nsIAtom* aTag,
#define COMPLEX_TAG_CREATE(_tag, _func) \ #define COMPLEX_TAG_CREATE(_tag, _func) \
{ &nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) } { &nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) }
static bool
IsFrameForFieldSet(nsIFrame* aFrame, nsIAtom* aFrameType)
{
nsIAtom* pseudo = aFrame->StyleContext()->GetPseudo();
if (pseudo == nsCSSAnonBoxes::fieldsetContent ||
pseudo == nsCSSAnonBoxes::scrolledContent) {
return IsFrameForFieldSet(aFrame->GetParent(), aFrame->GetParent()->GetType());
}
return aFrameType == nsGkAtoms::fieldSetFrame;
}
/* static */ /* static */
const nsCSSFrameConstructor::FrameConstructionData* const nsCSSFrameConstructor::FrameConstructionData*
nsCSSFrameConstructor::FindHTMLData(Element* aElement, nsCSSFrameConstructor::FindHTMLData(Element* aElement,
@ -3284,9 +3310,7 @@ nsCSSFrameConstructor::FindHTMLData(Element* aElement,
"Unexpected parent for fieldset content anon box"); "Unexpected parent for fieldset content anon box");
if (aTag == nsGkAtoms::legend && if (aTag == nsGkAtoms::legend &&
(!aParentFrame || (!aParentFrame ||
(aParentFrame->GetType() != nsGkAtoms::fieldSetFrame && !IsFrameForFieldSet(aParentFrame, aParentFrame->GetType()) ||
aParentFrame->StyleContext()->GetPseudo() !=
nsCSSAnonBoxes::fieldsetContent) ||
!aElement->GetParent() || !aElement->GetParent() ||
!aElement->GetParent()->IsHTML(nsGkAtoms::fieldset) || !aElement->GetParent()->IsHTML(nsGkAtoms::fieldset) ||
aStyleContext->StyleDisplay()->IsFloatingStyle() || aStyleContext->StyleDisplay()->IsFloatingStyle() ||
@ -5919,13 +5943,8 @@ nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
{ {
nsIFrame* parentFrame = aSibling->GetParent(); nsIFrame* parentFrame = aSibling->GetParent();
nsIAtom* parentType = nullptr; nsIAtom* parentType = nullptr;
nsIAtom* grandparentType = nullptr;
if (parentFrame) { if (parentFrame) {
parentType = parentFrame->GetType(); parentType = parentFrame->GetType();
nsIFrame* grandparentFrame = parentFrame->GetParent();
if (grandparentFrame) {
grandparentType = grandparentFrame->GetType();
}
} }
uint8_t siblingDisplay = aSibling->GetDisplay(); uint8_t siblingDisplay = aSibling->GetDisplay();
@ -5984,9 +6003,7 @@ nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
return true; return true;
} }
else if (nsGkAtoms::fieldSetFrame == parentType || else if (IsFrameForFieldSet(parentFrame, parentType)) {
(nsGkAtoms::fieldSetFrame == grandparentType &&
nsGkAtoms::blockFrame == parentType)) {
// Legends can be sibling of legends but not of other content in the fieldset // Legends can be sibling of legends but not of other content in the fieldset
nsIAtom* sibType = aSibling->GetContentInsertionFrame()->GetType(); nsIAtom* sibType = aSibling->GetContentInsertionFrame()->GetType();
bool legendContent = aContent->IsHTML(nsGkAtoms::legend); bool legendContent = aContent->IsHTML(nsGkAtoms::legend);
@ -7083,7 +7100,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
// fieldsets have multiple insertion points. // fieldsets have multiple insertion points.
NS_ASSERTION(isSingleInsert || frameType != nsGkAtoms::fieldSetFrame, NS_ASSERTION(isSingleInsert || frameType != nsGkAtoms::fieldSetFrame,
"Unexpected parent"); "Unexpected parent");
if (frameType == nsGkAtoms::fieldSetFrame && if (IsFrameForFieldSet(parentFrame, frameType) &&
aStartChild->Tag() == nsGkAtoms::legend) { aStartChild->Tag() == nsGkAtoms::legend) {
// Just reframe the parent, since figuring out whether this // Just reframe the parent, since figuring out whether this
// should be the new legend and then handling it is too complex. // should be the new legend and then handling it is too complex.

View File

@ -3922,8 +3922,15 @@ nsDisplayTransform::GetDeltaToTransformOrigin(const nsIFrame* aFrame,
* a distance, it's already computed for us! * a distance, it's already computed for us!
*/ */
const nsStyleDisplay* display = aFrame->StyleDisplay(); const nsStyleDisplay* display = aFrame->StyleDisplay();
nsRect boundingRect = (aBoundsOverride ? *aBoundsOverride : nsRect boundingRect;
nsDisplayTransform::GetFrameBoundsForTransform(aFrame)); if (aBoundsOverride) {
boundingRect = *aBoundsOverride;
} else if (display->mTransformOrigin[0].GetUnit() != eStyleUnit_Coord ||
display->mTransformOrigin[1].GetUnit() != eStyleUnit_Coord) {
// GetFrameBoundsForTransform is expensive for SVG frames and we don't need
// it if the origin is coords (which it is by default for SVG).
boundingRect = nsDisplayTransform::GetFrameBoundsForTransform(aFrame);
}
/* Allows us to access named variables by index. */ /* Allows us to access named variables by index. */
float coords[2]; float coords[2];

View File

@ -2825,7 +2825,8 @@ static int32_t gNoiseIndent = 0;
/* static */ nscoord /* static */ nscoord
nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext, nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
nsIFrame *aFrame, nsIFrame *aFrame,
IntrinsicWidthType aType) IntrinsicWidthType aType,
uint32_t aFlags)
{ {
NS_PRECONDITION(aFrame, "null frame"); NS_PRECONDITION(aFrame, "null frame");
NS_PRECONDITION(aType == MIN_WIDTH || aType == PREF_WIDTH, "bad type"); NS_PRECONDITION(aType == MIN_WIDTH || aType == PREF_WIDTH, "bad type");
@ -2919,15 +2920,17 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
// fall through // fall through
} }
case NS_STYLE_BOX_SIZING_PADDING: { case NS_STYLE_BOX_SIZING_PADDING: {
const nsStylePadding* stylePadding = aFrame->StylePadding(); if (!(aFlags & IGNORE_PADDING)) {
nscoord pad; const nsStylePadding* stylePadding = aFrame->StylePadding();
if (GetAbsoluteCoord(stylePadding->mPadding.GetTop(), pad) || nscoord pad;
GetPercentHeight(stylePadding->mPadding.GetTop(), aFrame, pad)) { if (GetAbsoluteCoord(stylePadding->mPadding.GetTop(), pad) ||
heightTakenByBoxSizing += pad; GetPercentHeight(stylePadding->mPadding.GetTop(), aFrame, pad)) {
} heightTakenByBoxSizing += pad;
if (GetAbsoluteCoord(stylePadding->mPadding.GetBottom(), pad) || }
GetPercentHeight(stylePadding->mPadding.GetBottom(), aFrame, pad)) { if (GetAbsoluteCoord(stylePadding->mPadding.GetBottom(), pad) ||
heightTakenByBoxSizing += pad; GetPercentHeight(stylePadding->mPadding.GetBottom(), aFrame, pad)) {
heightTakenByBoxSizing += pad;
}
} }
// fall through // fall through
} }
@ -2978,18 +2981,22 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
// percentages do not operate linearly. // percentages do not operate linearly.
// Doing this is ok because although percentages aren't handled // Doing this is ok because although percentages aren't handled
// linearly, they are handled monotonically. // linearly, they are handled monotonically.
nscoord coordOutsideWidth = offsets.hPadding; nscoord coordOutsideWidth = 0;
float pctOutsideWidth = offsets.hPctPadding; float pctOutsideWidth = 0;
float pctTotal = 0.0f; float pctTotal = 0.0f;
if (boxSizing == NS_STYLE_BOX_SIZING_PADDING) { if (!(aFlags & IGNORE_PADDING)) {
min += coordOutsideWidth; coordOutsideWidth += offsets.hPadding;
result = NSCoordSaturatingAdd(result, coordOutsideWidth); pctOutsideWidth += offsets.hPctPadding;
pctTotal += pctOutsideWidth;
coordOutsideWidth = 0; if (boxSizing == NS_STYLE_BOX_SIZING_PADDING) {
pctOutsideWidth = 0.0f; min += coordOutsideWidth;
result = NSCoordSaturatingAdd(result, coordOutsideWidth);
pctTotal += pctOutsideWidth;
coordOutsideWidth = 0;
pctOutsideWidth = 0.0f;
}
} }
coordOutsideWidth += offsets.hBorder; coordOutsideWidth += offsets.hBorder;

View File

@ -988,9 +988,13 @@ public:
* and margin. * and margin.
*/ */
enum IntrinsicWidthType { MIN_WIDTH, PREF_WIDTH }; enum IntrinsicWidthType { MIN_WIDTH, PREF_WIDTH };
enum {
IGNORE_PADDING = 0x01
};
static nscoord IntrinsicForContainer(nsRenderingContext* aRenderingContext, static nscoord IntrinsicForContainer(nsRenderingContext* aRenderingContext,
nsIFrame* aFrame, nsIFrame* aFrame,
IntrinsicWidthType aType); IntrinsicWidthType aType,
uint32_t aFlags = 0);
/* /*
* Convert nsStyleCoord to nscoord when percentages depend on the * Convert nsStyleCoord to nscoord when percentages depend on the

View File

@ -15,6 +15,7 @@
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsDisplayList.h" #include "nsDisplayList.h"
#include "nsRenderingContext.h" #include "nsRenderingContext.h"
#include "nsIScrollableFrame.h"
#include "mozilla/Likely.h" #include "mozilla/Likely.h"
using namespace mozilla; using namespace mozilla;
@ -78,6 +79,10 @@ public:
return nsContainerFrame::IsFrameOfType(aFlags & return nsContainerFrame::IsFrameOfType(aFlags &
~nsIFrame::eCanContainOverflowContainers); ~nsIFrame::eCanContainOverflowContainers);
} }
virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE
{
return do_QueryFrame(GetInner());
}
#ifdef ACCESSIBILITY #ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
@ -356,10 +361,14 @@ nsFieldSetFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext,
} }
if (nsIFrame* inner = GetInner()) { if (nsIFrame* inner = GetInner()) {
// Ignore padding on the inner, since the padding will be applied to the
// outer instead, and the padding computed for the inner is wrong
// for percentage padding.
contentWidth = contentWidth =
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner, aType); nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner, aType,
nsLayoutUtils::IGNORE_PADDING);
} }
return std::max(legendWidth, contentWidth); return std::max(legendWidth, contentWidth);
} }
@ -444,7 +453,10 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
// We don't allow fieldsets to break vertically. If we did, we'd // We don't allow fieldsets to break vertically. If we did, we'd
// need logic here to push and pull overflow frames. // need logic here to push and pull overflow frames.
nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE); // Since we're not applying our padding in this frame, we need to add it here
// to compute the available width for our children.
nsSize availSize(aReflowState.ComputedWidth() + aReflowState.mComputedPadding.LeftRight(),
NS_UNCONSTRAINEDSIZE);
NS_ASSERTION(!inner || NS_ASSERTION(!inner ||
nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext, nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext,
inner, inner,
@ -459,8 +471,7 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
"Bogus availSize.width; should be bigger"); "Bogus availSize.width; should be bigger");
// get our border and padding // get our border and padding
const nsMargin &borderPadding = aReflowState.mComputedBorderPadding; nsMargin border = aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding;
nsMargin border = borderPadding - aReflowState.mComputedPadding;
// Figure out how big the legend is if there is one. // Figure out how big the legend is if there is one.
// get the legend's margin // get the legend's margin
@ -481,7 +492,7 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
legendMargin = legend->GetUsedMargin(); legendMargin = legend->GetUsedMargin();
mLegendRect.width = legendDesiredSize.width + legendMargin.left + legendMargin.right; mLegendRect.width = legendDesiredSize.width + legendMargin.left + legendMargin.right;
mLegendRect.height = legendDesiredSize.height + legendMargin.top + legendMargin.bottom; mLegendRect.height = legendDesiredSize.height + legendMargin.top + legendMargin.bottom;
mLegendRect.x = borderPadding.left; mLegendRect.x = 0;
mLegendRect.y = 0; mLegendRect.y = 0;
nscoord oldSpace = mLegendSpace; nscoord oldSpace = mLegendSpace;
@ -513,16 +524,22 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
// reflow the content frame only if needed // reflow the content frame only if needed
if (reflowInner) { if (reflowInner) {
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, inner, nsHTMLReflowState kidReflowState(aPresContext, aReflowState, inner,
availSize); availSize, -1, -1, nsHTMLReflowState::CALLER_WILL_INIT);
// Override computed padding, in case it's percentage padding
kidReflowState.Init(aPresContext, -1, -1, nullptr,
&aReflowState.mComputedPadding);
// Our child is "height:100%" but we actually want its height to be reduced // Our child is "height:100%" but we actually want its height to be reduced
// by the amount of content-height the legend is eating up, unless our // by the amount of content-height the legend is eating up, unless our
// height is unconstrained (in which case the child's will be too). // height is unconstrained (in which case the child's will be too).
if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) { if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) {
kidReflowState.SetComputedHeight(std::max(0, aReflowState.ComputedHeight() - mLegendSpace)); kidReflowState.SetComputedHeight(
std::max(0, aReflowState.ComputedHeight() - mLegendSpace));
} }
kidReflowState.mComputedMinHeight = if (aReflowState.mComputedMinHeight > 0) {
std::max(0, aReflowState.mComputedMinHeight - mLegendSpace); kidReflowState.mComputedMinHeight =
std::max(0, aReflowState.mComputedMinHeight - mLegendSpace);
}
if (aReflowState.mComputedMaxHeight != NS_UNCONSTRAINEDSIZE) { if (aReflowState.mComputedMaxHeight != NS_UNCONSTRAINEDSIZE) {
kidReflowState.mComputedMaxHeight = kidReflowState.mComputedMaxHeight =
@ -533,7 +550,7 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
// Reflow the frame // Reflow the frame
NS_ASSERTION(kidReflowState.mComputedMargin == nsMargin(0,0,0,0), NS_ASSERTION(kidReflowState.mComputedMargin == nsMargin(0,0,0,0),
"Margins on anonymous fieldset child not supported!"); "Margins on anonymous fieldset child not supported!");
nsPoint pt(borderPadding.left, borderPadding.top + mLegendSpace); nsPoint pt(border.left, border.top + mLegendSpace);
ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowState, ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowState,
pt.x, pt.y, 0, aStatus); pt.x, pt.y, 0, aStatus);
@ -542,37 +559,45 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus); NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus);
} }
nsRect contentRect(0,0,0,0); nsRect contentRect;
if (inner) { if (inner) {
// We don't support margins on inner, so our "content rect" is just // We don't support margins on inner, so our content rect is just the
// its rect. // inner's border-box.
contentRect = inner->GetRect(); contentRect = inner->GetRect();
} }
// use the computed width if the inner content does not fill it // Our content rect must fill up the available width
if (aReflowState.ComputedWidth() > contentRect.width) { if (availSize.width > contentRect.width) {
contentRect.width = aReflowState.ComputedWidth(); contentRect.width = availSize.width;
} }
if (legend) { if (legend) {
// if the content rect is larger then the legend we can align the legend // the legend is postioned horizontally within the inner's content rect
if (contentRect.width > mLegendRect.width) { // (so that padding on the fieldset affects the legend position).
nsRect innerContentRect = contentRect;
innerContentRect.Deflate(aReflowState.mComputedPadding);
// if the inner content rect is larger than the legend, we can align the legend
if (innerContentRect.width > mLegendRect.width) {
int32_t align = static_cast<nsLegendFrame*> int32_t align = static_cast<nsLegendFrame*>
(legend->GetContentInsertionFrame())->GetAlign(); (legend->GetContentInsertionFrame())->GetAlign();
switch(align) { switch (align) {
case NS_STYLE_TEXT_ALIGN_RIGHT: case NS_STYLE_TEXT_ALIGN_RIGHT:
mLegendRect.x = contentRect.width - mLegendRect.width + borderPadding.left; mLegendRect.x = innerContentRect.XMost() - mLegendRect.width;
break; break;
case NS_STYLE_TEXT_ALIGN_CENTER: case NS_STYLE_TEXT_ALIGN_CENTER:
// Note: rounding removed; there doesn't seem to be any need // Note: rounding removed; there doesn't seem to be any need
mLegendRect.x = contentRect.width / 2 - mLegendRect.width / 2 + borderPadding.left; mLegendRect.x = innerContentRect.width / 2 - mLegendRect.width / 2 + innerContentRect.x;
break;
default:
mLegendRect.x = innerContentRect.x;
break; break;
} }
} else { } else {
// otherwise make place for the legend // otherwise make place for the legend
contentRect.width = mLegendRect.width; mLegendRect.x = innerContentRect.x;
innerContentRect.width = mLegendRect.width;
contentRect.width = mLegendRect.width + aReflowState.mComputedPadding.LeftRight();
} }
// place the legend // place the legend
nsRect actualLegendRect(mLegendRect); nsRect actualLegendRect(mLegendRect);
@ -594,16 +619,16 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
// Return our size and our result // Return our size and our result
if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) { if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
aDesiredSize.height = mLegendSpace + aDesiredSize.height = mLegendSpace +
borderPadding.TopBottom() + border.TopBottom() +
contentRect.height; (inner ? inner->GetRect().height : 0);
} else { } else {
nscoord min = borderPadding.TopBottom() + mLegendRect.height; nscoord min = border.TopBottom() + mLegendRect.height;
aDesiredSize.height = aDesiredSize.height =
aReflowState.ComputedHeight() + borderPadding.TopBottom(); aReflowState.ComputedHeight() + aReflowState.mComputedBorderPadding.TopBottom();
if (aDesiredSize.height < min) if (aDesiredSize.height < min)
aDesiredSize.height = min; aDesiredSize.height = min;
} }
aDesiredSize.width = contentRect.width + borderPadding.LeftRight(); aDesiredSize.width = contentRect.width + border.LeftRight();
aDesiredSize.SetOverflowAreasToDesiredBounds(); aDesiredSize.SetOverflowAreasToDesiredBounds();
if (legend) if (legend)
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend); ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend);
@ -681,9 +706,6 @@ nsFieldSetFrame::ReparentFrameList(const nsFrameList& aFrameList)
nscoord nscoord
nsFieldSetFrame::GetBaseline() const nsFieldSetFrame::GetBaseline() const
{ {
// We know inner is a block, so calling GetBaseline() on it will do
// the right thing (that being to return the baseline of the last line).
nsIFrame* inner = GetInner(); nsIFrame* inner = GetInner();
NS_ASSERTION(nsLayoutUtils::GetAsBlock(inner), "Unexpected inner");
return inner->GetPosition().y + inner->GetBaseline(); return inner->GetPosition().y + inner->GetBaseline();
} }

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html style="height: 100%"> <html class="reftest-wait" style="height: 100%">
<head> <head>
<script> <script>
function doIt() { function doIt() {
@ -8,10 +8,12 @@
"position: absolute; left: 0; right: 0; top: 0; " + "position: absolute; left: 0; right: 0; top: 0; " +
"bottom: 0; background: green"); "bottom: 0; background: green");
document.getElementById("x").appendChild(d); document.getElementById("x").appendChild(d);
document.documentElement.removeAttribute("class");
} }
window.addEventListener("MozReftestInvalidate", doIt);
</script> </script>
</head> </head>
<body style="height: 100%" onload="doIt()"> <body style="height: 100%">
<fieldset id="x" style="position: relative; display: table; width: 50%; <fieldset id="x" style="position: relative; display: table; width: 50%;
height: 50%; top: 25%; left: 25%"> height: 50%; top: 25%; left: 25%">
</fieldset> </fieldset>

View File

@ -0,0 +1,24 @@
<!DOCTYPE HTML>
<html>
<head>
<style>
fieldset {
background:pink;
overflow:hidden;
height:100px;
}
legend::after { content:"legend"; }
p {
background:lime;
height:20px;
}
</style>
</head>
<body>
<fieldset id="f1"><legend></legend><p></p></fieldset>
<br>
<fieldset id="f2"><legend></legend><p></p></fieldset>
<br>
<fieldset id="f3"><legend></legend></fieldset>
</body>
</html>

View File

@ -0,0 +1,33 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<head>
<style>
fieldset {
background:pink;
overflow:hidden;
height:100px;
}
legend::after { content:"legend"; }
p {
background:lime;
height:20px;
}
</style>
</head>
<body>
<fieldset id="f1"><p></p></fieldset>
<br>
<fieldset id="f2"><p></p></fieldset>
<br>
<fieldset id="f3"></fieldset>
<script>
function doTest() {
f1.appendChild(document.createElement('legend'));
f2.insertBefore(document.createElement('legend'), f2.firstChild);
f3.appendChild(document.createElement('legend'));
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", doTest);
</script>
</body>
</html>

View File

@ -0,0 +1,21 @@
<!DOCTYPE HTML>
<html>
<body>
<fieldset style="width:200px; height:200px; padding:0">
<legend>Legend</legend>
<div style="overflow:hidden; height:100%;">
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
</div>
</fieldset>
</body>
</html>

View File

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<body>
<fieldset style="overflow:hidden; width:200px; height:200px; padding:0">
<legend>Legend</legend>
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
</fieldset>
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE HTML>
<html>
<body>
<fieldset style="width:0; padding:0;">
<div style="width:400px; height:200px;"></div>
</fieldset>
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE HTML>
<html>
<body>
<fieldset style="padding:50px; float:left;">
<div style="width:300px; height:100px;"></div>
</fieldset>
</body>
</html>

View File

@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<html><head>
<meta charset="utf-8">
<title>Testcase for bug 261037</title>
<style type="text/css">
fieldset, div {
background:pink;
overflow:auto;
height:100px;
margin:0; padding:0; border:0;
}
p {
background:blue;
height:100px;
margin:0; padding:0;
}
.overflow {
height:110px;
}
.abs {
position:absolute;
width:100px;
top:250px;
}
p.abs {
top:0;left:0;
}
.b { border:10px solid black; }
.p { padding: 7px 0; }
.p p { height:114px; }
</style>
</head>
<body>
<div><p></p></div>
<br>
<div><p class="overflow"></p></div>
<br>
<div class="abs"><p class="abs"></p></div>
<br>
<div class="abs" style="left:120px"><p class="abs overflow"></p></div>
<br>
<div class="abs b" style="left:240px"><p class="abs"></p></div>
<br>
<div class="abs b" style="left:370px"><p class="abs overflow"></p></div>
<br>
<div class="abs b p" style="left:510px"><p class="abs"></p></div>
<br>
<div class="abs b p" style="left:640px"><p class="abs overflow"></p></div>
</body>
</html>

View File

@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<html><head>
<meta charset="utf-8">
<title>Testcase for bug 261037</title>
<style type="text/css">
fieldset, div {
background:pink;
overflow:auto;
height:100px;
margin:0; padding:0; border:0;
}
p {
background:blue;
height:100px;
margin:0; padding:0;
}
.overflow {
height:110px;
}
.abs {
position:absolute;
width:100px;
top:250px;
}
p.abs {
top:0;left:0;
}
.b { border:10px solid black; }
.p { padding: 7px 0; }
.p p { height:114px; }
</style>
</head>
<body>
<fieldset><p></p></fieldset>
<br>
<fieldset><p class="overflow"></p></fieldset>
<br>
<fieldset class="abs"><p class="abs"></p></fieldset>
<br>
<fieldset class="abs" style="left:120px"><p class="abs overflow"></p></fieldset>
<br>
<fieldset class="abs b" style="left:240px"><p class="abs"></p></fieldset>
<br>
<fieldset class="abs b" style="left:370px"><p class="abs overflow"></p></fieldset>
<br>
<fieldset class="abs b p" style="left:510px"><p class="abs"></p></fieldset>
<br>
<fieldset class="abs b p" style="left:640px"><p class="abs overflow"></p></fieldset>
</body>
</html>

View File

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<body>
<div style="width:700px; border:2px solid green; overflow:hidden">
<fieldset style="padding:140px; width:400px;">
<legend>Legend</legend>
TextTextTextTextTextText
</fieldset>
<fieldset style="padding:140px; display:inline;">
<legend>Legend</legend>
TextTextTextTextTextText
</fieldset>
<fieldset style="padding:140px; float:left;">
<legend>Legend</legend>
TextTextTextTextTextText
</fieldset>
</div>
</body>
</html>

View File

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<body>
<div style="width:700px; border:2px solid green; overflow:hidden">
<fieldset style="padding:20%; width:400px;">
<legend>Legend</legend>
TextTextTextTextTextText
</fieldset>
<fieldset style="padding:20%; display:inline;">
<legend>Legend</legend>
TextTextTextTextTextText
</fieldset>
<fieldset style="padding:20%; float:left;">
<legend>Legend</legend>
TextTextTextTextTextText
</fieldset>
</div>
</body>
</html>

View File

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<html>
<body>
<fieldset style="width:200px; height:200px; padding:0">
<legend>Legend</legend>
<div style="overflow:scroll; height:100%">
</fieldset>
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE HTML>
<html>
<body>
<fieldset style="overflow:scroll; width:200px; height:200px; padding:0">
<legend>Legend</legend>
</fieldset>
</body>
</html>

View File

@ -0,0 +1,24 @@
<!DOCTYPE HTML>
<html>
<body>
<fieldset style="width:200px; height:200px; padding:0">
<legend style="overflow:hidden">Legend</legend>
<div id="d" style="overflow:hidden; height:100%;">
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
</div>
</fieldset>
<script>
d.scrollTop = 20;
</script>
</body>
</html>

View File

@ -0,0 +1,27 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<body>
<fieldset id="f" style="overflow:hidden; width:200px; height:200px; padding:0">
<legend style="overflow:hidden">Legend</legend>
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
<p>Hello Kitty
</fieldset>
<script>
f.scrollTop = 0;
function doTest() {
f.scrollTop = 20;
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", doTest);
</script>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<body>
<fieldset style="position:relative; overflow:hidden; width:500px; height:500px;">
<legend>Legend</legend>
<div style="height:1000px;">
<div style="position:absolute; left:20px; top:20px; background:yellow;">Abs-pos</div>
</div>
</fieldset>
</body>
</html>

View File

@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<html>
<body>
<fieldset id="f" style="position:relative; overflow:hidden; width:500px; height:500px;">
<legend>Legend</legend>
<div style="height:1000px;">
<div style="position:absolute; left:20px; top:50px; background:yellow;">Abs-pos</div>
</div>
</fieldset>
<script>
f.scrollTop = 30;
</script>
</body>
</html>

View File

@ -0,0 +1,8 @@
== dynamic-legend-scroll-1.html dynamic-legend-scroll-1-ref.html
== fieldset-hidden-1.html fieldset-hidden-1-ref.html
== fieldset-intrinsic-width-1.html fieldset-intrinsic-width-1-ref.html
== fieldset-percentage-padding-1.html fieldset-percentage-padding-1-ref.html
== fieldset-scroll-1.html fieldset-scroll-1-ref.html
== fieldset-scrolled-1.html fieldset-scrolled-1-ref.html
== fieldset-overflow-auto-1.html fieldset-overflow-auto-1-ref.html
== positioned-container-1.html positioned-container-1-ref.html

View File

@ -6,6 +6,9 @@ include button/reftest.list
# legend element # legend element
include legend/reftest.list include legend/reftest.list
# fieldset element
include fieldset/reftest.list
# placeholder # placeholder
include placeholder/reftest.list include placeholder/reftest.list

View File

@ -20,3 +20,4 @@ pref(gfx.font_rendering.opentype_svg.enabled,true) fuzzy-if(cocoaWidget,255,1
pref(gfx.font_rendering.opentype_svg.enabled,true) fails == svg-glyph-mask.svg svg-glyph-mask-ref.svg # bug 872483 pref(gfx.font_rendering.opentype_svg.enabled,true) fails == svg-glyph-mask.svg svg-glyph-mask-ref.svg # bug 872483
pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-paint-server.svg svg-glyph-paint-server-ref.svg pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-paint-server.svg svg-glyph-paint-server-ref.svg
pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-transform.svg svg-glyph-transform-ref.svg pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-transform.svg svg-glyph-transform-ref.svg
pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-extents.html svg-glyph-extents-ref.html

View File

@ -36,3 +36,26 @@ sfnt2woff svg.ttf
[1] https://github.com/edf825/SVG-OpenType-Utils [1] https://github.com/edf825/SVG-OpenType-Utils
[2] http://people.mozilla.com/~jkew/woff/ [2] http://people.mozilla.com/~jkew/woff/
Additional test fonts:
======================
svg-glyph-extents.otf
---------------------
This is a copy of Fira Sans with a simple SVG table added using the tool from
https://github.com/rocallahan/svg-opentype-workshop. The SVG table defines four
glyphs, corresponding to 'A' through 'D':
<svg xmlns='http://www.w3.org/2000/svg'>
<rect id='glyph36' x='0' y='-1000' width='1000' height='1500' fill='red'/>
<rect id='glyph37' x='0' y='-1000' width='1000' height='1500' fill='green' transform='scale(2)'/>
<g id='glyph38'>
<rect x='0' y='-1000' width='1000' height='1500' fill='red'/>
</g>
<g id='glyph39'>
<rect x='0' y='-1000' width='1000' height='1500' fill='green' transform='scale(2)'/>
</g>
</svg>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<style type="text/css">
@font-face {
font-family: foo;
src: url(resources/svg-glyph-extents.otf);
}
body {
font-family: foo;
font-size: 10px;
}
div {
display: inline-block;
height: 100px;
width: 100px;
}
</style>
</head>
<body>
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</body>
</html>

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html class="reftest-wait">
<meta charset="utf-8">
<head>
<style type="text/css">
@font-face {
font-family: foo;
src: url(resources/svg-glyph-extents.otf);
}
body {
font-family: foo;
font-size: 10px;
}
@keyframes test {
from {
font-size: 100px;
}
to {
font-size: 10px;
}
}
div {
display: inline-block;
height: 100px;
width: 100px;
animation-duration: 3s;
animation-name: test;
}
</style>
<script type="text/javascript">
function setup() {
var e = document.getElementById("watchme");
e.addEventListener("animationend", listener, false);
}
function listener() {
document.documentElement.className = "";
}
</script>
</head>
<body onload="setup()">
<div>A</div>
<div id="watchme">B</div>
<div>C</div>
<div>D</div>
</body>
</html>

View File

@ -14,6 +14,9 @@
display: block; display: block;
unicode-bidi: inherit; unicode-bidi: inherit;
text-overflow: inherit; text-overflow: inherit;
overflow: inherit;
padding: inherit;
position: inherit;
height: 100%; /* Need this so percentage heights of kids work right */ height: 100%; /* Need this so percentage heights of kids work right */
} }

View File

@ -1862,7 +1862,15 @@ nsSVGUtils::GetSVGGlyphExtents(Element* aElement,
if (!svgFrame) { if (!svgFrame) {
return false; return false;
} }
*aResult = svgFrame->GetBBoxContribution(aSVGToAppSpace,
gfxMatrix transform(aSVGToAppSpace);
nsIContent* content = frame->GetContent();
if (content->IsSVG()) {
transform = static_cast<nsSVGElement*>(content)->
PrependLocalTransformsTo(aSVGToAppSpace);
}
*aResult = svgFrame->GetBBoxContribution(transform,
nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIncludeFillGeometry | nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIncludeFillGeometry |
nsSVGUtils::eBBoxIncludeStroke | nsSVGUtils::eBBoxIncludeStrokeGeometry | nsSVGUtils::eBBoxIncludeStroke | nsSVGUtils::eBBoxIncludeStrokeGeometry |
nsSVGUtils::eBBoxIncludeMarkers); nsSVGUtils::eBBoxIncludeMarkers);

View File

@ -62,6 +62,7 @@ div.non-verbose pre.entries {
h1 { h1 {
padding: 0; padding: 0;
margin: 0; margin: 0;
display: inline; /* allow subsequent text to the right of the heading */
} }
h2 { h2 {
@ -69,6 +70,16 @@ h2 {
padding-left: .1em; padding-left: .1em;
} }
h3 {
display: inline; /* allow subsequent text to the right of the heading */
}
a.upDownArrow {
font-size: 130%;
text-decoration: none;
-moz-user-select: none; /* no need to include this when cutting+pasting */
}
.accuracyWarning { .accuracyWarning {
color: #d22; color: #d22;
} }

View File

@ -885,7 +885,7 @@ function appendAboutMemoryMain(aProcessReports, aHasMozMallocUsableSize)
let process = processes[i]; let process = processes[i];
let section = appendElement(gMain, 'div', 'section'); let section = appendElement(gMain, 'div', 'section');
appendProcessAboutMemoryElements(section, process, appendProcessAboutMemoryElements(section, i, process,
pcollsByProcess[process]._trees, pcollsByProcess[process]._trees,
pcollsByProcess[process]._degenerates, pcollsByProcess[process]._degenerates,
pcollsByProcess[process]._heapTotal, pcollsByProcess[process]._heapTotal,
@ -1308,6 +1308,8 @@ function appendWarningElements(aP, aHasKnownHeapAllocated,
* *
* @param aP * @param aP
* The parent DOM node. * The parent DOM node.
* @param aN
* The number of the process, starting at 0.
* @param aProcess * @param aProcess
* The name of the process. * The name of the process.
* @param aTrees * @param aTrees
@ -1318,10 +1320,34 @@ function appendWarningElements(aP, aHasKnownHeapAllocated,
* Boolean indicating if moz_malloc_usable_size works. * Boolean indicating if moz_malloc_usable_size works.
* @return The generated text. * @return The generated text.
*/ */
function appendProcessAboutMemoryElements(aP, aProcess, aTrees, aDegenerates, function appendProcessAboutMemoryElements(aP, aN, aProcess, aTrees,
aHeapTotal, aHasMozMallocUsableSize) aDegenerates, aHeapTotal,
aHasMozMallocUsableSize)
{ {
appendElementWithText(aP, "h1", "", aProcess + "\n\n"); const kUpwardsArrow = "\u2191",
kDownwardsArrow = "\u2193";
let appendLink = function(aHere, aThere, aArrow) {
let link = appendElementWithText(aP, "a", "upDownArrow", aArrow);
link.href = "#" + aThere + aN;
link.id = aHere + aN;
link.title = "Go to the " + aThere + " of " + aProcess;
link.style = "text-decoration: none";
// This jumps to the anchor without the page location getting the anchor
// name tacked onto its end, which is what happens with a vanilla link.
link.addEventListener("click", function(event) {
document.documentElement.scrollTop =
document.querySelector(event.target.href).offsetTop;
event.preventDefault();
}, false);
// This gives nice spacing when we copy and paste.
appendElementWithText(aP, "span", "", "\n");
}
appendElementWithText(aP, "h1", "", aProcess);
appendLink("start", "end", kDownwardsArrow);
// We'll fill this in later. // We'll fill this in later.
let warningsDiv = appendElement(aP, "div", "accuracyWarning"); let warningsDiv = appendElement(aP, "div", "accuracyWarning");
@ -1347,7 +1373,7 @@ function appendProcessAboutMemoryElements(aP, aProcess, aTrees, aDegenerates,
appendTreeElements(pre, t, aProcess, ""); appendTreeElements(pre, t, aProcess, "");
delete aTrees[treeName]; delete aTrees[treeName];
} }
appendTextNode(aP, "\n"); // gives nice spacing when we cut and paste appendTextNode(aP, "\n"); // gives nice spacing when we copy and paste
} }
// Fill in and sort all the non-degenerate other trees. // Fill in and sort all the non-degenerate other trees.
@ -1388,13 +1414,16 @@ function appendProcessAboutMemoryElements(aP, aProcess, aTrees, aDegenerates,
let padText = pad("", maxStringLength - t.toString().length, ' '); let padText = pad("", maxStringLength - t.toString().length, ' ');
appendTreeElements(pre, t, aProcess, padText); appendTreeElements(pre, t, aProcess, padText);
} }
appendTextNode(aP, "\n"); // gives nice spacing when we cut and paste appendTextNode(aP, "\n"); // gives nice spacing when we copy and paste
// Add any warnings about inaccuracies due to platform limitations. // Add any warnings about inaccuracies due to platform limitations.
// These must be computed after generating all the text. The newlines give // These must be computed after generating all the text. The newlines give
// nice spacing if we cut+paste into a text buffer. // nice spacing if we copy+paste into a text buffer.
appendWarningElements(warningsDiv, hasKnownHeapAllocated, appendWarningElements(warningsDiv, hasKnownHeapAllocated,
aHasMozMallocUsableSize); aHasMozMallocUsableSize);
appendElementWithText(aP, "h3", "", "End of " + aProcess);
appendLink("end", "start", kUpwardsArrow);
} }
/** /**
@ -1517,7 +1546,7 @@ function pad(aS, aN, aC)
// There's a subset of the Unicode "light" box-drawing chars that is widely // There's a subset of the Unicode "light" box-drawing chars that is widely
// implemented in terminals, and this code sticks to that subset to maximize // implemented in terminals, and this code sticks to that subset to maximize
// the chance that cutting and pasting about:memory output to a terminal will // the chance that copying and pasting about:memory output to a terminal will
// work correctly. // work correctly.
const kHorizontal = "\u2500", const kHorizontal = "\u2500",
kVertical = "\u2502", kVertical = "\u2502",

View File

@ -279,6 +279,7 @@ Other Measurements\n\
45.67% ── perc1\n\ 45.67% ── perc1\n\
100.00% ── perc2\n\ 100.00% ── perc2\n\
\n\ \n\
End of Main Process\n\
4th\n\ 4th\n\
\n\ \n\
WARNING: the following values are negative or unreasonably large.\n\ WARNING: the following values are negative or unreasonably large.\n\
@ -314,6 +315,7 @@ Other Measurements\n\
666.66% ── other6\n\ 666.66% ── other6\n\
200.00 MB ── resident\n\ 200.00 MB ── resident\n\
\n\ \n\
End of 4th\n\
3rd\n\ 3rd\n\
\n\ \n\
WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\ WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\
@ -329,6 +331,7 @@ Other Measurements\n\
1.00 MB ── other1\n\ 1.00 MB ── other1\n\
100.00 MB ── resident\n\ 100.00 MB ── resident\n\
\n\ \n\
End of 3rd\n\
2nd\n\ 2nd\n\
Explicit Allocations\n\ Explicit Allocations\n\
\n\ \n\
@ -345,6 +348,7 @@ Other Measurements\n\
666.00 MB ── other0\n\ 666.00 MB ── other0\n\
111.00 MB ── other1\n\ 111.00 MB ── other1\n\
\n\ \n\
End of 2nd\n\
5th\n\ 5th\n\
\n\ \n\
WARNING: the following values are negative or unreasonably large.\n\ WARNING: the following values are negative or unreasonably large.\n\
@ -377,6 +381,7 @@ Other Measurements\n\
\n\ \n\
100.00 MB ── heap-allocated\n\ 100.00 MB ── heap-allocated\n\
\n\ \n\
End of 5th\n\
"; ";
let amvExpectedText = let amvExpectedText =
@ -446,6 +451,7 @@ Other Measurements\n\
45.67% ── perc1\n\ 45.67% ── perc1\n\
100.00% ── perc2\n\ 100.00% ── perc2\n\
\n\ \n\
End of Main Process\n\
4th\n\ 4th\n\
\n\ \n\
WARNING: the following values are negative or unreasonably large.\n\ WARNING: the following values are negative or unreasonably large.\n\
@ -479,6 +485,7 @@ Other Measurements\n\
666.66% ── other6\n\ 666.66% ── other6\n\
209,715,200 B ── resident\n\ 209,715,200 B ── resident\n\
\n\ \n\
End of 4th\n\
3rd\n\ 3rd\n\
\n\ \n\
WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\ WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\
@ -494,6 +501,7 @@ Other Measurements\n\
1,048,576 B ── other1\n\ 1,048,576 B ── other1\n\
104,857,600 B ── resident\n\ 104,857,600 B ── resident\n\
\n\ \n\
End of 3rd\n\
2nd\n\ 2nd\n\
Explicit Allocations\n\ Explicit Allocations\n\
\n\ \n\
@ -510,6 +518,7 @@ Other Measurements\n\
698,351,616 B ── other0\n\ 698,351,616 B ── other0\n\
116,391,936 B ── other1\n\ 116,391,936 B ── other1\n\
\n\ \n\
End of 2nd\n\
5th\n\ 5th\n\
\n\ \n\
WARNING: the following values are negative or unreasonably large.\n\ WARNING: the following values are negative or unreasonably large.\n\
@ -541,7 +550,8 @@ Other Measurements\n\
\n\ \n\
104,857,600 B ── heap-allocated\n\ 104,857,600 B ── heap-allocated\n\
\n\ \n\
" End of 5th\n\
";
function finish() function finish()
{ {
@ -567,7 +577,7 @@ Other Measurements\n\
let mostRecentActual; let mostRecentActual;
let frame = document.getElementById(aFrameId); let frame = document.getElementById(aFrameId);
frame.focus(); frame.focus();
// Set the verbose checkbox value and click the go button. // Set the verbose checkbox value and click the go button.
let doc = frame.contentWindow.document; let doc = frame.contentWindow.document;
let measureButton = doc.getElementById("measureButton"); let measureButton = doc.getElementById("measureButton");
@ -588,9 +598,9 @@ Other Measurements\n\
function() { function() {
ok(false, "pasted text doesn't match for " + aFrameId); ok(false, "pasted text doesn't match for " + aFrameId);
dump("******EXPECTED******\n"); dump("******EXPECTED******\n");
dump(aExpected); dump("<<<" + aExpected + ">>>\n");
dump("*******ACTUAL*******\n"); dump("*******ACTUAL*******\n");
dump(mostRecentActual); dump("<<<" + mostRecentActual + ">>>\n");
dump("********************\n"); dump("********************\n");
finish(); finish();
} }

View File

@ -177,6 +177,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process\n\
"; ";
let acCollapsedExpected = let acCollapsedExpected =
@ -201,6 +202,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process\n\
"; ";
let alExpandedExpected = let alExpandedExpected =
@ -227,6 +229,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process\n\
"; ";
let aCollapsedExpected = let aCollapsedExpected =
@ -247,6 +250,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process\n\
"; ";
let hCollapsedExpected = let hCollapsedExpected =
@ -265,6 +269,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process\n\
"; ";
let jExpandedExpected = let jExpandedExpected =
@ -285,6 +290,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process\n\
"; ";
// The important thing here is that two values have been swapped. // The important thing here is that two values have been swapped.
@ -308,6 +314,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process\n\
"; ";
let aExpandedExpected = let aExpandedExpected =
@ -334,6 +341,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process\n\
"; ";
let acExpandedExpected = let acExpandedExpected =
@ -362,6 +370,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process\n\
"; ";
let alCollapsedExpected = let alCollapsedExpected =
@ -388,6 +397,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process\n\
"; ";
// Test the following cases: // Test the following cases:

View File

@ -159,7 +159,7 @@
synthesizeKey("A", {accelKey: true}); synthesizeKey("A", {accelKey: true});
synthesizeKey("C", {accelKey: true}); synthesizeKey("C", {accelKey: true});
let actual = SpecialPowers.getClipboardData("text/unicode"); let actual = SpecialPowers.getClipboardData("text/unicode");
actual = actual.replace(/\(pid \d+\)/, "(pid NNN)"); actual = actual.replace(/\(pid \d+\)/g, "(pid NNN)");
if (actual === aExpected) { if (actual === aExpected) {
SimpleTest.ok(true, "Clipboard has the expected contents"); SimpleTest.ok(true, "Clipboard has the expected contents");
@ -204,6 +204,7 @@ Explicit Allocations\n\
\n\ \n\
Other Measurements\n\ Other Measurements\n\
\n\ \n\
End of Explicit-only process\n\
Main Process (pid NNN)\n\ Main Process (pid NNN)\n\
Explicit Allocations\n\ Explicit Allocations\n\
\n\ \n\
@ -237,6 +238,7 @@ Other Measurements\n\
\n\ \n\
262,144,000 B ── heap-allocated\n\ 262,144,000 B ── heap-allocated\n\
\n\ \n\
End of Main Process (pid NNN)\n\
Other-only process\n\ Other-only process\n\
\n\ \n\
WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\ WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\
@ -250,6 +252,7 @@ Other Measurements\n\
\n\ \n\
500,000 B ── heap-allocated\n\ 500,000 B ── heap-allocated\n\
\n\ \n\
End of Other-only process\n\
"; ";
let expectedGood2 = let expectedGood2 =
@ -269,12 +272,14 @@ Other Measurements\n\
\n\ \n\
262,144,000 B ── heap-allocated\n\ 262,144,000 B ── heap-allocated\n\
\n\ \n\
End of Main Process (pid NNN)\n\
"; ";
// This is the output for a malformed data file. // This is the output for a malformed data file.
let expectedBad = let expectedBad =
"\ "\
Invalid memory report(s): missing 'hasMozMallocUsableSize' property"; Invalid memory report(s): missing 'hasMozMallocUsableSize' property\
";
// This is the output for a diff. // This is the output for a diff.
let expectedDiff = let expectedDiff =
@ -294,6 +299,7 @@ Other Measurements\n\
3,000 B ── canvas-2d-pixel-bytes [2] [+]\n\ 3,000 B ── canvas-2d-pixel-bytes [2] [+]\n\
-100 B ── foobar [-]\n\ -100 B ── foobar [-]\n\
\n\ \n\
End of P\n\
P2 (pid NNN)\n\ P2 (pid NNN)\n\
\n\ \n\
WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\ WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\
@ -303,6 +309,7 @@ Other Measurements\n\
\n\ \n\
11 B ── z 0xNNN\n\ 11 B ── z 0xNNN\n\
\n\ \n\
End of P2 (pid NNN)\n\
P3\n\ P3\n\
\n\ \n\
WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\ WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\
@ -312,6 +319,7 @@ Other Measurements\n\
\n\ \n\
-55 B ── p3 [-]\n\ -55 B ── p3 [-]\n\
\n\ \n\
End of P3\n\
P4\n\ P4\n\
\n\ \n\
WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\ WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\
@ -321,6 +329,7 @@ Other Measurements\n\
\n\ \n\
66 B ── p4 [+]\n\ 66 B ── p4 [+]\n\
\n\ \n\
End of P4\n\
"; ";
let frames = [ let frames = [

View File

@ -99,6 +99,7 @@ Explicit Allocations\n\
\n\ \n\
Other Measurements\n\ Other Measurements\n\
\n\ \n\
End of Explicit-only process\n\
Main Process (pid NNN)\n\ Main Process (pid NNN)\n\
Explicit Allocations\n\ Explicit Allocations\n\
\n\ \n\
@ -132,6 +133,7 @@ Other Measurements\n\
\n\ \n\
250.00 MB ── heap-allocated\n\ 250.00 MB ── heap-allocated\n\
\n\ \n\
End of Main Process (pid NNN)\n\
Other-only process\n\ Other-only process\n\
\n\ \n\
WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\ WARNING: the 'heap-allocated' memory reporter does not work for this platform and/or configuration. This means that 'heap-unclassified' is not shown and the 'explicit' tree shows less memory than it should.\n\
@ -145,6 +147,7 @@ Other Measurements\n\
\n\ \n\
0.48 MB ── heap-allocated\n\ 0.48 MB ── heap-allocated\n\
\n\ \n\
End of Other-only process\n\
"; ";
// This is the output for a malformed data file. // This is the output for a malformed data file.

View File

@ -1963,7 +1963,7 @@ void nsXULWindow::SetContentScrollbarVisibility(bool aVisible)
nsCOMPtr<nsPIDOMWindow> contentWin(do_GetInterface(mPrimaryContentShell)); nsCOMPtr<nsPIDOMWindow> contentWin(do_GetInterface(mPrimaryContentShell));
if (contentWin) { if (contentWin) {
nsRefPtr<nsGlobalWindow> window = static_cast<nsGlobalWindow*>(contentWin.get()); nsRefPtr<nsGlobalWindow> window = static_cast<nsGlobalWindow*>(contentWin.get());
nsRefPtr<mozilla::dom::BarProp> scrollbars = window->Scrollbars(); nsRefPtr<mozilla::dom::BarProp> scrollbars = window->GetScrollbars();
if (scrollbars) { if (scrollbars) {
mozilla::ErrorResult rv; mozilla::ErrorResult rv;
scrollbars->SetVisible(aVisible, rv); scrollbars->SetVisible(aVisible, rv);