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
// to use it here. Similar for comboboxes.
if (frame->GetType() != nsGkAtoms::menuFrame &&
frame->GetType() != nsGkAtoms::comboboxControlFrame) {
nsIAtom* type = frame->GetType();
if (type != nsGkAtoms::menuFrame && type != nsGkAtoms::comboboxControlFrame) {
nsIScrollableFrame *scrollFrame = frame->GetScrollTargetFrame();
if (scrollFrame)
return scrollFrame;

View File

@ -532,9 +532,9 @@ public:
}
}
void RemoveTextTrack(TextTrack* aTextTrack) {
void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly = false) {
if (mTextTrackManager) {
mTextTrackManager->RemoveTextTrack(aTextTrack);
mTextTrackManager->RemoveTextTrack(aTextTrack, aPendingListOnly);
}
}
@ -862,6 +862,11 @@ protected:
// Update the audio channel playing state
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.
// At most one of mDecoder and mSrcStream can be non-null.
nsRefPtr<MediaDecoder> mDecoder;

View File

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

View File

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

View File

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

View File

@ -7,11 +7,12 @@
#include "mozilla/dom/TextTrackManager.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/dom/HTMLTrackElement.h"
namespace mozilla {
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_UNROOT_NATIVE(TextTrackManager, Release)
@ -20,6 +21,8 @@ TextTrackManager::TextTrackManager(HTMLMediaElement *aMediaElement)
{
MOZ_COUNT_CTOR(TextTrackManager);
mTextTracks = new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject());
mPendingTextTracks =
new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject());
}
TextTrackManager::~TextTrackManager()
@ -37,7 +40,10 @@ already_AddRefed<TextTrack>
TextTrackManager::AddTextTrack(TextTrackKind aKind, const nsAString& aLabel,
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
@ -47,8 +53,13 @@ TextTrackManager::AddTextTrack(TextTrack* aTextTrack)
}
void
TextTrackManager::RemoveTextTrack(TextTrack* aTextTrack)
TextTrackManager::RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly)
{
mPendingTextTracks->RemoveTextTrack(aTextTrack);
if (aPendingListOnly) {
return;
}
mTextTracks->RemoveTextTrack(aTextTrack);
}
@ -64,5 +75,19 @@ TextTrackManager::Update(double 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 mozilla

View File

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

View File

@ -11,6 +11,7 @@
#include "mozilla/dom/TextTrackRegion.h"
#include "mozilla/dom/TextTrackRegionList.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/dom/HTMLTrackElement.h"
namespace mozilla {
namespace dom {
@ -68,6 +69,7 @@ TextTrack::SetDefaultSettings()
mRegionList = new TextTrackRegionList(mParent);
mCuePos = 0;
mDirty = false;
mReadyState = HTMLTrackElement::NONE;
}
void
@ -170,5 +172,21 @@ TextTrack::GetActiveCues()
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 mozilla

View File

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

View File

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

View File

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

View File

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

View File

@ -765,7 +765,7 @@ public:
mozilla::dom::SpeechSynthesis* GetSpeechSynthesisInternal();
#endif
mozilla::dom::BarProp* Scrollbars();
mozilla::dom::BarProp* GetScrollbars();
protected:
// 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:
// Slot 2: Argumentsobject.
// Note: when updating this, please also update the assert in SnapshotWriter::startFrame
return 2 + (script->argumentsHasVarBinding() ? 1 : 0);
}
@ -34,6 +35,8 @@ CountArgSlots(JSScript *script, JSFunction *fun)
// Slot x + 1: Argument 1.
// ...
// 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);
}

View File

@ -1656,12 +1656,6 @@ IonCompile(JSContext *cx, JSScript *script,
return success ? AbortReason_NoAbort : AbortReason_Disable;
}
static bool
TooManyArguments(unsigned nargs)
{
return (nargs >= SNAPSHOT_MAX_NARGS || nargs > js_IonOptions.maxStackArgs);
}
static bool
CheckFrame(BaselineFrame *frame)
{
@ -1902,6 +1896,12 @@ jit::CanEnter(JSContext *cx, RunState &state)
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()) {
RootedScript scriptRoot(cx, script);
RootedObject callee(cx, &invoke.args().callee());

View File

@ -384,6 +384,12 @@ IsIonInlinablePC(jsbytecode *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, ExecutionMode mode);
uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc);

View File

@ -266,7 +266,7 @@ IonBuilder::canEnterInlinedFunction(JSFunction *target)
}
bool
IonBuilder::canInlineTarget(JSFunction *target, bool constructing)
IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo)
{
if (!target->isInterpreted()) {
IonSpew(IonSpew_Inlining, "Cannot inline due to non-interpreted");
@ -297,7 +297,7 @@ IonBuilder::canInlineTarget(JSFunction *target, bool constructing)
return false;
}
if (constructing && !target->isInterpretedConstructor()) {
if (callInfo.constructing() && !target->isInterpretedConstructor()) {
IonSpew(IonSpew_Inlining, "Cannot inline because callee is not a constructor");
return false;
}
@ -317,6 +317,18 @@ IonBuilder::canInlineTarget(JSFunction *target, bool constructing)
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.
IonBuilder *builder = callerBuilder_;
while (builder) {
@ -3947,7 +3959,7 @@ IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo)
return true;
// Determine whether inlining is possible at callee site
if (!canInlineTarget(target, callInfo.constructing()))
if (!canInlineTarget(target, callInfo))
return false;
// Heuristics!

View File

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

View File

@ -83,15 +83,19 @@ jit::IonSpewNewFunction(MIRGraph *graph, HandleScript func)
{
if (!OffThreadIonCompilationEnabled(GetIonContext()->runtime)) {
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 {
if (func) {
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.)");
}
IonSpew(IonSpew_Logs, "Can't log asm.js compilation. (Compiled on background thread.)");
}
}
@ -342,9 +346,6 @@ jit::CheckLogging()
EnableChannel(IonSpew_BaselineBailouts);
}
if (LoggingBits != 0)
EnableIonDebugLogging();
IonSpewFile = stderr;
}

View File

@ -301,7 +301,10 @@ SnapshotWriter::startSnapshot(uint32_t frameCount, BailoutKind kind, bool resume
void
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 formalArgs = CountArgSlots(script, fun);

View File

@ -3050,39 +3050,50 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
nsIContent* const content = aItem.mContent;
nsStyleContext* const styleContext = aItem.mStyleContext;
nsIFrame* newFrame = NS_NewFieldSetFrame(mPresShell, styleContext);
nsIFrame* fieldsetFrame = NS_NewFieldSetFrame(mPresShell, styleContext);
// Initialize it
InitAndRestoreFrame(aState, content,
aState.GetGeometricParent(aStyleDisplay, aParentFrame),
newFrame);
fieldsetFrame);
// Resolve style and initialize the frame
nsRefPtr<nsStyleContext> fieldsetContentStyle;
fieldsetContentStyle = mPresShell->StyleSet()->
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,
NS_BLOCK_FLOAT_MGR |
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
nsFrameConstructorSaveState absoluteSaveState;
nsFrameItems childItems;
newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
if (newFrame->IsPositioned()) {
aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
blockFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
if (fieldsetFrame->IsPositioned()) {
aState.PushAbsoluteContainingBlock(blockFrame, fieldsetFrame, absoluteSaveState);
}
ProcessChildren(aState, content, styleContext, blockFrame, true,
childItems, true, aItem.mPendingBinding);
nsFrameItems fieldsetKids;
fieldsetKids.AddChild(blockFrame);
fieldsetKids.AddChild(scrollFrame ? scrollFrame : blockFrame);
for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) {
nsIFrame* child = e.get();
@ -3094,21 +3105,25 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
// GetAdjustedParentFrame() below depends on this frame order.
childItems.RemoveFrame(child);
// 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;
}
}
if (isScrollable) {
FinishBuildingScrollFrame(scrollFrame, blockFrame);
}
// Set the inner frame's initial child lists
blockFrame->SetInitialChildList(kPrincipalList, childItems);
// 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.
return newFrame;
return fieldsetFrame;
}
static nsIFrame*
@ -3262,6 +3277,17 @@ nsCSSFrameConstructor::FindDataByTag(nsIAtom* aTag,
#define COMPLEX_TAG_CREATE(_tag, _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 */
const nsCSSFrameConstructor::FrameConstructionData*
nsCSSFrameConstructor::FindHTMLData(Element* aElement,
@ -3284,9 +3310,7 @@ nsCSSFrameConstructor::FindHTMLData(Element* aElement,
"Unexpected parent for fieldset content anon box");
if (aTag == nsGkAtoms::legend &&
(!aParentFrame ||
(aParentFrame->GetType() != nsGkAtoms::fieldSetFrame &&
aParentFrame->StyleContext()->GetPseudo() !=
nsCSSAnonBoxes::fieldsetContent) ||
!IsFrameForFieldSet(aParentFrame, aParentFrame->GetType()) ||
!aElement->GetParent() ||
!aElement->GetParent()->IsHTML(nsGkAtoms::fieldset) ||
aStyleContext->StyleDisplay()->IsFloatingStyle() ||
@ -5919,13 +5943,8 @@ nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
{
nsIFrame* parentFrame = aSibling->GetParent();
nsIAtom* parentType = nullptr;
nsIAtom* grandparentType = nullptr;
if (parentFrame) {
parentType = parentFrame->GetType();
nsIFrame* grandparentFrame = parentFrame->GetParent();
if (grandparentFrame) {
grandparentType = grandparentFrame->GetType();
}
}
uint8_t siblingDisplay = aSibling->GetDisplay();
@ -5984,9 +6003,7 @@ nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
return true;
}
else if (nsGkAtoms::fieldSetFrame == parentType ||
(nsGkAtoms::fieldSetFrame == grandparentType &&
nsGkAtoms::blockFrame == parentType)) {
else if (IsFrameForFieldSet(parentFrame, parentType)) {
// Legends can be sibling of legends but not of other content in the fieldset
nsIAtom* sibType = aSibling->GetContentInsertionFrame()->GetType();
bool legendContent = aContent->IsHTML(nsGkAtoms::legend);
@ -7083,7 +7100,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
// fieldsets have multiple insertion points.
NS_ASSERTION(isSingleInsert || frameType != nsGkAtoms::fieldSetFrame,
"Unexpected parent");
if (frameType == nsGkAtoms::fieldSetFrame &&
if (IsFrameForFieldSet(parentFrame, frameType) &&
aStartChild->Tag() == nsGkAtoms::legend) {
// Just reframe the parent, since figuring out whether this
// 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!
*/
const nsStyleDisplay* display = aFrame->StyleDisplay();
nsRect boundingRect = (aBoundsOverride ? *aBoundsOverride :
nsDisplayTransform::GetFrameBoundsForTransform(aFrame));
nsRect boundingRect;
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. */
float coords[2];

View File

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

View File

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

View File

@ -15,6 +15,7 @@
#include "nsStyleConsts.h"
#include "nsDisplayList.h"
#include "nsRenderingContext.h"
#include "nsIScrollableFrame.h"
#include "mozilla/Likely.h"
using namespace mozilla;
@ -78,6 +79,10 @@ public:
return nsContainerFrame::IsFrameOfType(aFlags &
~nsIFrame::eCanContainOverflowContainers);
}
virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE
{
return do_QueryFrame(GetInner());
}
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
@ -356,10 +361,14 @@ nsFieldSetFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext,
}
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 =
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner, aType);
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner, aType,
nsLayoutUtils::IGNORE_PADDING);
}
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
// 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 ||
nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext,
inner,
@ -459,8 +471,7 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
"Bogus availSize.width; should be bigger");
// get our border and padding
const nsMargin &borderPadding = aReflowState.mComputedBorderPadding;
nsMargin border = borderPadding - aReflowState.mComputedPadding;
nsMargin border = aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding;
// Figure out how big the legend is if there is one.
// get the legend's margin
@ -481,7 +492,7 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
legendMargin = legend->GetUsedMargin();
mLegendRect.width = legendDesiredSize.width + legendMargin.left + legendMargin.right;
mLegendRect.height = legendDesiredSize.height + legendMargin.top + legendMargin.bottom;
mLegendRect.x = borderPadding.left;
mLegendRect.x = 0;
mLegendRect.y = 0;
nscoord oldSpace = mLegendSpace;
@ -513,16 +524,22 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
// reflow the content frame only if needed
if (reflowInner) {
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
// 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).
if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) {
kidReflowState.SetComputedHeight(std::max(0, aReflowState.ComputedHeight() - mLegendSpace));
kidReflowState.SetComputedHeight(
std::max(0, aReflowState.ComputedHeight() - mLegendSpace));
}
kidReflowState.mComputedMinHeight =
std::max(0, aReflowState.mComputedMinHeight - mLegendSpace);
if (aReflowState.mComputedMinHeight > 0) {
kidReflowState.mComputedMinHeight =
std::max(0, aReflowState.mComputedMinHeight - mLegendSpace);
}
if (aReflowState.mComputedMaxHeight != NS_UNCONSTRAINEDSIZE) {
kidReflowState.mComputedMaxHeight =
@ -533,7 +550,7 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
// Reflow the frame
NS_ASSERTION(kidReflowState.mComputedMargin == nsMargin(0,0,0,0),
"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,
pt.x, pt.y, 0, aStatus);
@ -542,37 +559,45 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus);
}
nsRect contentRect(0,0,0,0);
nsRect contentRect;
if (inner) {
// We don't support margins on inner, so our "content rect" is just
// its rect.
// We don't support margins on inner, so our content rect is just the
// inner's border-box.
contentRect = inner->GetRect();
}
// use the computed width if the inner content does not fill it
if (aReflowState.ComputedWidth() > contentRect.width) {
contentRect.width = aReflowState.ComputedWidth();
// Our content rect must fill up the available width
if (availSize.width > contentRect.width) {
contentRect.width = availSize.width;
}
if (legend) {
// if the content rect is larger then the legend we can align the legend
if (contentRect.width > mLegendRect.width) {
// the legend is postioned horizontally within the inner's content rect
// (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*>
(legend->GetContentInsertionFrame())->GetAlign();
switch(align) {
switch (align) {
case NS_STYLE_TEXT_ALIGN_RIGHT:
mLegendRect.x = contentRect.width - mLegendRect.width + borderPadding.left;
mLegendRect.x = innerContentRect.XMost() - mLegendRect.width;
break;
case NS_STYLE_TEXT_ALIGN_CENTER:
// 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;
}
} else {
// 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
nsRect actualLegendRect(mLegendRect);
@ -594,16 +619,16 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
// Return our size and our result
if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
aDesiredSize.height = mLegendSpace +
borderPadding.TopBottom() +
contentRect.height;
border.TopBottom() +
(inner ? inner->GetRect().height : 0);
} else {
nscoord min = borderPadding.TopBottom() + mLegendRect.height;
nscoord min = border.TopBottom() + mLegendRect.height;
aDesiredSize.height =
aReflowState.ComputedHeight() + borderPadding.TopBottom();
aReflowState.ComputedHeight() + aReflowState.mComputedBorderPadding.TopBottom();
if (aDesiredSize.height < min)
aDesiredSize.height = min;
}
aDesiredSize.width = contentRect.width + borderPadding.LeftRight();
aDesiredSize.width = contentRect.width + border.LeftRight();
aDesiredSize.SetOverflowAreasToDesiredBounds();
if (legend)
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend);
@ -681,9 +706,6 @@ nsFieldSetFrame::ReparentFrameList(const nsFrameList& aFrameList)
nscoord
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();
NS_ASSERTION(nsLayoutUtils::GetAsBlock(inner), "Unexpected inner");
return inner->GetPosition().y + inner->GetBaseline();
}

View File

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

View File

@ -36,3 +36,26 @@ sfnt2woff svg.ttf
[1] https://github.com/edf825/SVG-OpenType-Utils
[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;
unicode-bidi: inherit;
text-overflow: inherit;
overflow: inherit;
padding: inherit;
position: inherit;
height: 100%; /* Need this so percentage heights of kids work right */
}

View File

@ -1862,7 +1862,15 @@ nsSVGUtils::GetSVGGlyphExtents(Element* aElement,
if (!svgFrame) {
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::eBBoxIncludeStroke | nsSVGUtils::eBBoxIncludeStrokeGeometry |
nsSVGUtils::eBBoxIncludeMarkers);

View File

@ -62,6 +62,7 @@ div.non-verbose pre.entries {
h1 {
padding: 0;
margin: 0;
display: inline; /* allow subsequent text to the right of the heading */
}
h2 {
@ -69,6 +70,16 @@ h2 {
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 {
color: #d22;
}

View File

@ -885,7 +885,7 @@ function appendAboutMemoryMain(aProcessReports, aHasMozMallocUsableSize)
let process = processes[i];
let section = appendElement(gMain, 'div', 'section');
appendProcessAboutMemoryElements(section, process,
appendProcessAboutMemoryElements(section, i, process,
pcollsByProcess[process]._trees,
pcollsByProcess[process]._degenerates,
pcollsByProcess[process]._heapTotal,
@ -1308,6 +1308,8 @@ function appendWarningElements(aP, aHasKnownHeapAllocated,
*
* @param aP
* The parent DOM node.
* @param aN
* The number of the process, starting at 0.
* @param aProcess
* The name of the process.
* @param aTrees
@ -1318,10 +1320,34 @@ function appendWarningElements(aP, aHasKnownHeapAllocated,
* Boolean indicating if moz_malloc_usable_size works.
* @return The generated text.
*/
function appendProcessAboutMemoryElements(aP, aProcess, aTrees, aDegenerates,
aHeapTotal, aHasMozMallocUsableSize)
function appendProcessAboutMemoryElements(aP, aN, aProcess, aTrees,
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.
let warningsDiv = appendElement(aP, "div", "accuracyWarning");
@ -1347,7 +1373,7 @@ function appendProcessAboutMemoryElements(aP, aProcess, aTrees, aDegenerates,
appendTreeElements(pre, t, aProcess, "");
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.
@ -1388,13 +1414,16 @@ function appendProcessAboutMemoryElements(aP, aProcess, aTrees, aDegenerates,
let padText = pad("", maxStringLength - t.toString().length, ' ');
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.
// 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,
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
// 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.
const kHorizontal = "\u2500",
kVertical = "\u2502",

View File

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

View File

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

View File

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

View File

@ -99,6 +99,7 @@ Explicit Allocations\n\
\n\
Other Measurements\n\
\n\
End of Explicit-only process\n\
Main Process (pid NNN)\n\
Explicit Allocations\n\
\n\
@ -132,6 +133,7 @@ Other Measurements\n\
\n\
250.00 MB ── heap-allocated\n\
\n\
End of Main Process (pid NNN)\n\
Other-only process\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\
@ -145,6 +147,7 @@ Other Measurements\n\
\n\
0.48 MB ── heap-allocated\n\
\n\
End of Other-only process\n\
";
// 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));
if (contentWin) {
nsRefPtr<nsGlobalWindow> window = static_cast<nsGlobalWindow*>(contentWin.get());
nsRefPtr<mozilla::dom::BarProp> scrollbars = window->Scrollbars();
nsRefPtr<mozilla::dom::BarProp> scrollbars = window->GetScrollbars();
if (scrollbars) {
mozilla::ErrorResult rv;
scrollbars->SetVisible(aVisible, rv);