import changes from `dev' branch of rmottola/Arctic-Fox:- Bug 1258966 - Remove unnecessary null-checks of MediaDecoderStateMachine::mReader. r=bechen. (0513c82214)

- Bug 1258627 - always schedule next cycle so MDSM has a chance to leave buffering state. r=cpearce. (49fb876b9e)
- Bug 1258271 - Remove arguments from MediaDecoderStateMachine::HaveEnoughDecodedAudio(). r=bechen. (e8610f7f76)
- Bug 1252753. Part 1 - remove calls to PushFront(). r=kinetik. (7abe1bfb0f)
- Bug 1252753. Part 2 - remove MediaDecoderStateMachine::PushFront(). r=kinetik. (1a153a5b00)
- Bug 1230527: P1. Ensure seeked event is fired prior loadeddata. r=jwwang (aa9eef9fd3)
- Bug 1230527: P2. Add mochitest. r=jwwang (6e9f920781)
- Bug 1252767 - Remove MediaDecoderStateMachine::mPendingSeek. r=cpearce. (e5d69a191d)
- Bug 1255268 - Replace SeekJob::Steal() with move semantics. r=cpearce. (6294c01ba7)
- Bug 1253490 - fix the calculation of decodeTime. r=jya. (b8f3c8801a)
- Bug 1252343. Part 1 - make mReader const. r=bechen. (33a8b6a4ad)
- Bug 1252343. Part 2 - remove null checks for mReader which is const and never null. r=bechen. (5cd068aafc)
- Bug 1250054. Part 2 - employ MediaDecoderReaderWrapper for MDSM and remove code about adjusting start time. r=jya. (b5a954d8d8)
- Bug 1252341 - No need to reset mReader in ~MediaDecoderStateMachine() because the destructor will do that. r=bechen. (cd0639e366)
- Bug 1264784 - part 2 - remove unused virtual methods from nsIFrame; r=dholbert (5d52314a79)
- Bug 1264784 - part 3 - make nsIFrame::GetNearestWidget methods non-virtual; r=dholbert (67b0987de6)
- Bug 1053986 - Rename nsIFrame::IsBoxFrame to IsXULBoxFrame. r=dholbert (394613f49f)
- Bug 1256040 - Fix some nsGridContainerFrame.h/cpp compile errors in non-unified build. r=dholbert (b49241e3b1)
- Bug 1264607 - Treat track size <percentage> values as 'auto' when the grid container size is indefinite. r=dholbert (3895d4d922)
- Bug 1260614 - Cleanup grid item iterator Reset() calls. r=dholbert (e6760e1def)
- Bug 1256040 - Bustage fix. r=me (d67b9c0de5)
- Bug 1233191 part 1 - Implement sanity checks on the flex/grid container child frame list. Remove the anon grid item sanity checks that the frame constructor now does instead. r=dholbert (d9412bb043)
- Bug 1233191 part 2 - Remove anon flex item sanity checks that the frame constructor now does instead. r=dholbert (564184ea6d)
- Bug 1233191 part 3 - crashtest. (c6b6bb4fca)
- Bug 1187846 Stack layout doesn't honour min/max sizes for positioned elements r=Enn (8080e9db71)
- Bug 1053986 - Rename nsIFrame::GetMinSize to GetXULMinSize, and related methods. r=dholbert (fa1722982e)
- Bug 1000870 - Add some features in testing system. r=smaug (f7b4b8916f)
- Bug 1053986 - Rename nsIFrame::GetPrefSize to GetXULPrefSize, and related methods. r=dholbert (9f7e8de26e)
- Bug 1053986 - Rename nsIFrame::GetMaxSize to GetXULMaxSize, and related methods. r=dholbert (a632913886)
- Bug 1053986 - Rename nsIFrame::GetMinSizeForScrollArea to GetXULMinSizeForScrollArea. r=dholbert (ac520afe6f)
- Bug 1053986 - Rename nsIFrame::GetOrdinal to GetXULOrdinal. r=dholbert (e5f7342d03)
- Bug 1053986 - Rename nsIFrame::GetFlex to GetXULFlex. r=dholbert (aadf567a8c)
- Bug 1053986 - Rename nsIFrame::GetBoxAscent to GetXULBoxAscent. r=dholbert (4e729c60ea)
- Bug 1053986 - Rename nsFrame.cpp static method IsBoxWrapped to IsXULBoxWrapped. r=dholbert (009b251df0)
- Bug 1053986 - Rename nsIFrame::IsCollapsed to IsXULCollapsed, and related methods. r=dholbert (eec509e378)
- Bug 1168212 - Ensure popups have a minimum width of their preferred size r=Enn (657c8da6fa)
- Bug 1053986 - Rename nsIFrame::SetBounds to SetXULBounds. r=dholbert (304ff47c6c)
- Bug 1088637 - check we get the right transition event, r=Enn (b0da4a67f6)
- Bug 1053986 - Rename nsIFrame::Layout to XULLayout, and related methods with the same name. r=dholbert (66ef396b10)
- Bug 1053986 - Rename nsIFrame::GetBorderAndPadding to GetXULBorderAndPadding. r=dholbert (588f824000)
- Bug 1053986 - Rename nsIFrame::GetBorder to GetXULBorder. r=dholbert (f91ae3fc59)
- Bug 1053986 - Rename nsIFrame::GetPadding to GetXULPadding. r=dholbert (797e21e6af)
- Bug 1053986 - Rename nsIFrame::GetMargin to GetXULMargin. r=dholbert (05dc0235f2)
- Bug 1053986 - Rename nsIFrame::SetLayoutManager to SetXULLayoutManager. r=dholbert (0cb22c411d)
- Bug 1053986 - Rename nsIFrame::GetLayoutManager to GetXULLayoutManager. r=dholbert (6a03e1de2c)
- Bug 852754 - Part 1: Share the code for limiting scale factors to all image types. r=mstange (098a083d1a)
- Bug 852754 - Part 2: Share the implementation of GetContainer. r=mstange (063b7683dd)
- Bug 852754 - Part 3: Share the implementation of ConfigureLayer. r=mstange (ffd2d99802)
- Bug 1256999 - Pass the right context to new channels for image loads. r=bz r=seth (275cebb231)
- Bug 1194337 - Context menu positioned incorrectly on OSX. r=enn (1e429a9d3c)
- Bug 1216284 - Tooltips do not flip correctly on OSX. r=enndeakin (c08931768b)
- Bug 1053986 - Rename nsIFrame::GetClientRect to GetXULClientRect. r=dholbert (c06a121de6)
- Bug 1053986 - Rename nsIFrame::GetVAlign to GetXULVAlign. r=dholbert (a923d76c4b)
- Bug 1053986 - Rename nsBox::GetChildBox to GetChildXULBox. r=dholbert (ebe12c77f1)
- Bug 1053986 - Rename nsIFrame::GetHAlign to GetXULHAlign. r=dholbert (dbd501e2bd)
- Bug 1053986 - Rename nsBox::GetNextBox to GetNextXULBox. r=dholbert (1cd5fa1ce3)
- Bug 1053986 - Rename nsBox::GetParentBox to GetParentXULBox. r=dholbert (2beaeb6bdd)
- Bug 1171696 - Don't resize scrollbar thumb when updating its position. r=mstange (5b51241744)
- Bug 1053986 - Rename nsIFrame::IsHorizontal to IsXULHorizontal, and related methods. r=dholbert (7d8e4142e5)
- Bug 1053986 - Rename nsIFrame::IsNormalDirection to IsXULNormalDirection. r=dholbert (7d9686b089)
- Bug 1053986 - Rename nsIFrame::Redraw to XULRedraw. r=dholbert (20da19c2ce)
- Bug 1053986 - Rename nsIFrame::RelayoutChildAtOrdinal to XULRelayoutChildAtOrdinal. r=dholbert (e5c4eb2b9f)
- Bug 1053986 - Rename nsIFrame::SetDebug to SetXULDebug. r=dholbert (438c3a1109)
- Bug 1053986 - Rename nsIFrame::GetDebug to GetXULDebug. r=dholbert (00e0ca19e4)
- Bug 1053986 - Rename nsIFrame::DumpBox to XULDumpBox. r=dholbert (30edc21d8e)
- Bug 1053986 - Rename nsIFrame::AddCSSPrefSize, AddCSSMinSize, AddCSSMaxSize, and AddCSSFlex by replacing CSS with XUL. r=dholbert (4e79b90b1f)
- Bug 1053986 - Fix ordering of methods in nsIFrame.h r=dholbert (fb08aa035f)
- Bug 1053986 - Rename nsBox::BeginLayout to BeginXULLayout. r=dholbert (595cb70526)
- Bug 1053986 - Rename nsBox::EndLayout to EndXULLayout. r=dholbert (13f98a84a0)
- Bug 1213895: Part 1 - Correctly support crop="none" in XUL labels. r=neil (053e0c8414)
- Bug 1053986 - Rename nsBox::DoLayout to DoXULLayout. r=dholbert (40ef0ece53)
- Bug 1144619 - Variable 'nextX' is created in the wrong scope. r=dbaron (7893ccb301)
- Bug 1172011 - Remove unneeded 'spaceLeft' declaration from nsSplitterFrame.cpp. r=froydnj (7ef937e283)
- Bug 1192376: Make nsImageBoxFrame check whether image size is available before trying to paint an image. r=seth (2db203eb3b)
- Bug 1240533 - Parameters to ScreenForRect need to be passed as desktop pixels, not device pixels. r=emk (d49b532344)
- Bug 1212658 - Remove needless IsCallerChrome check in nsMenuPopupFrame. r=bz (bdf0d16a49)
- Bug 374471 Make the noautohide attribute live where supported r=enndeakin (f696b4d174)
- Bug 1200870, allow -1 as a value to popup.moveTo, r=tn (10e05d4240)
- Bug 1182856 - Part 1: Add StopTransitionsForElement. r=heycam (1c0ac374c4)
- Bug 1182856 - Part 2: Let AnimationsWithDestroyFrame destroy transitions. r=heycam (7820f7b1e5)
- Bug 1182856 - Part 3: Cancel transitions for destroy frames. r=heycam (439fb07545)
- Bug 1157936 - Put the correct ratio on the scrollbar layer. r=tn (a64f35b9ea)
- Bug 1238137 - Telemetry pings for main thread scrollbar-driven scroll input methods. r=kats (89e5187b88)
- Bug 1156106 - Make nsMenuBarFrame::mMenuBarListener an nsRefPtr; r=roc (838126cd16)
- Bug 1163304 Close all existing popups when menubar becomes active because it should have pseudo focus and other popups shouldn't handle key events r=enn+neil (933c9ae40e)
- Bug 1252693 - Assert that we do not tenure into an OMT Zone; r=sfink (0812fc81f2)
- Bug 1265679 - Always call the object moved hook in generational GC r=terrence (6d75efba2d)
- Bug 1265825 - Remove mSuppressionActive assert. r=kats (3b6b3ba030)
- Bug 1250226 - Only report compacting GC telemetry for compacting GCs r=terrence (4e0f511ccf)
- Bug 1258578: Improve documentation for js::RelocatablePtr. DONTBUILD r=terrence (3ed2a933e0)
- Bug 1252713 - Fix FILES_PER_UNIFIED_FILE=1 bustage in js/. r=terrence (8a97e6c7e2)
- Bug 1265741: Fix unified build for fuzzers; r=nbp (ad3b4a4543)
- Bug 1013219 - set the line number of the terminating retrval; r=jimb, r=ejpbruel, r=fitzgen (df810884a9)
- Bug 1013219 - set line number of return instruction; r=efaust, r=fitzgen, r=ejpbruel (503b1a2bf3)
- Bug 1260577 - Fix |obj[expr] += e2| erroneously calling expr.toString() twice. (r=till) (e2485baccb)
- Bug 1260577 - followup: Change confusing name SelfAssign to CompoundAssign. (rs=jorendorff) (51a7dee68e)
- Bug 1263881 - Check the the number of body level lexicals doesn't exceed that which we can store in Bindings r=shu (d610d7a1e9)
- Bug 1258097 - Check for redeclaration of imports by functions r=shu (78f06f273f)
- Bug 1264954 - Add missing OOM check in Parser::templateLiteral. r=jonco (2743a82e1e)
- Bug 1265313 - Fix Annex B.3.5 handling with body-level lexicals. (r=jorendorff) (6b4139d25b)
- Bug 1260620 - Ensure that possibleErrors are not null before attempting to check them; r=jorendorff (6b284c1107)
- Bug 1253275 - Remove const_casts from Runtime.cpp. r=sfink (40b6d68455)
- Bug 1262731 - Add JS_InitWithFailureDiagnostic(). r=sfink. (310579fcd3)
- Bug 1263886 - Don't call makeConstructorCode if the group has unknown properties. r=bhackett (e81c939928)
- Bug 1260891 - Acquire and release the lock when destorying an `ExclusiveData<T>`'s protected value; r=terrence a=kwierso (dc39af575e)
- Bug 1252034 - Value Numbering: Unconditionally generate fixup blocks. r=sunfish (3b46b2df51)
- Bug 1232229 - Ensure generator object prototype is a singleton and tenured. r=jonco (d0c4f17cb6)
This commit is contained in:
2024-04-25 21:58:07 +08:00
parent c6e1bfdcf2
commit 4696208ad8
171 changed files with 2369 additions and 2014 deletions
+2 -2
View File
@@ -432,9 +432,9 @@ Accessible::NativeState()
// XXX we should look at layout for non XUL box frames, but need to decide
// how that interacts with ARIA.
if (HasOwnContent() && mContent->IsXULElement() && frame->IsBoxFrame()) {
if (HasOwnContent() && mContent->IsXULElement() && frame->IsXULBoxFrame()) {
const nsStyleXUL* xulStyle = frame->StyleXUL();
if (xulStyle && frame->IsBoxFrame()) {
if (xulStyle && frame->IsXULBoxFrame()) {
// In XUL all boxes are either vertical or horizontal
if (xulStyle->mBoxOrient == NS_STYLE_BOX_ORIENT_VERTICAL)
state |= states::VERTICAL;
+1 -1
View File
@@ -1066,7 +1066,7 @@ HTMLTableAccessible::IsProbablyLayoutTable()
RETURN_LAYOUT_ANSWER(false, "table's first cell has no frame!");
nsMargin border;
cellFrame->GetBorder(border);
cellFrame->GetXULBorder(border);
if (border.top && border.bottom && border.left && border.right) {
RETURN_LAYOUT_ANSWER(false, "Has nonzero border-width on table cell");
}
+6 -1
View File
@@ -3142,7 +3142,8 @@ nsContentUtils::IsImageInCache(nsIURI* aURI, nsIDocument* aDocument)
// static
nsresult
nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
nsContentUtils::LoadImage(nsIURI* aURI, nsINode* aContext,
nsIDocument* aLoadingDocument,
nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer,
net::ReferrerPolicy aReferrerPolicy,
imgINotificationObserver* aObserver, int32_t aLoadFlags,
@@ -3151,6 +3152,7 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
uint32_t aContentPolicyType)
{
NS_PRECONDITION(aURI, "Must have a URI");
NS_PRECONDITION(aContext, "Must have a context");
NS_PRECONDITION(aLoadingDocument, "Must have a document");
NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
NS_PRECONDITION(aRequest, "Null out param");
@@ -3180,6 +3182,7 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
aLoadingPrincipal, /* loading principal */
loadGroup, /* loadgroup */
aObserver, /* imgINotificationObserver */
aContext, /* loading context */
aLoadingDocument, /* uniquification key */
aLoadFlags, /* load flags */
nullptr, /* cache key */
@@ -7636,6 +7639,8 @@ int16_t
nsContentUtils::GetButtonsFlagForButton(int32_t aButton)
{
switch (aButton) {
case -1:
return WidgetMouseEvent::eNoButtonFlag;
case WidgetMouseEvent::eLeftButton:
return WidgetMouseEvent::eLeftButtonFlag;
case WidgetMouseEvent::eMiddleButton:
+3
View File
@@ -662,6 +662,8 @@ public:
* keep a mutable version around should pass in a clone.
*
* @param aURI uri of the image to be loaded
* @param aContext element of document where the result of this request
* will be used.
* @param aLoadingDocument the document we belong to
* @param aLoadingPrincipal the principal doing the load
* @param aReferrer the referrer URI
@@ -674,6 +676,7 @@ public:
* @return the imgIRequest for the image load
*/
static nsresult LoadImage(nsIURI* aURI,
nsINode* aContext,
nsIDocument* aLoadingDocument,
nsIPrincipal* aLoadingPrincipal,
nsIURI* aReferrer,
+1
View File
@@ -9794,6 +9794,7 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
RefPtr<imgRequestProxy> request;
nsresult rv =
nsContentUtils::LoadImage(uri,
static_cast<nsINode*>(this),
this,
NodePrincipal(),
mDocumentURI, // uri of document used as referrer
+5 -1
View File
@@ -878,7 +878,11 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
// Not blocked. Do the load.
RefPtr<imgRequestProxy>& req = PrepareNextRequest(aImageLoadType);
nsIContent* content = AsContent();
nsresult rv = nsContentUtils::LoadImage(aNewURI, aDocument,
nsCOMPtr<nsINode> thisNode =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
nsresult rv = nsContentUtils::LoadImage(aNewURI,
thisNode,
aDocument,
aDocument->NodePrincipal(),
aDocument->GetDocumentURI(),
referrerPolicy,
+76 -150
View File
@@ -42,6 +42,7 @@
#include "ImageContainer.h"
#include "MediaDecoder.h"
#include "MediaDecoderReader.h"
#include "MediaDecoderReaderWrapper.h"
#include "MediaDecoderStateMachine.h"
#include "MediaShutdownManager.h"
#include "MediaTimer.h"
@@ -219,6 +220,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mObservedDuration(TimeUnit(), "MediaDecoderStateMachine::mObservedDuration"),
mFragmentEndTime(-1),
mReader(aReader),
mReaderWrapper(new MediaDecoderReaderWrapper(aRealTime, mTaskQueue, aReader)),
mDecodedAudioEndTime(0),
mDecodedVideoEndTime(0),
mPlaybackRate(1.0),
@@ -332,8 +334,6 @@ MediaDecoderStateMachine::~MediaDecoderStateMachine()
MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
MOZ_COUNT_DTOR(MediaDecoderStateMachine);
mReader = nullptr;
#ifdef XP_WIN
timeEndPeriod(1);
#endif
@@ -464,12 +464,13 @@ void MediaDecoderStateMachine::DiscardStreamData()
}
}
bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs)
bool MediaDecoderStateMachine::HaveEnoughDecodedAudio()
{
MOZ_ASSERT(OnTaskQueue());
int64_t ampleAudioUSecs = mAmpleAudioThresholdUsecs * mPlaybackRate;
if (AudioQueue().GetSize() == 0 ||
GetDecodedAudioDuration() < aAmpleAudioUSecs) {
GetDecodedAudioDuration() < ampleAudioUSecs) {
return false;
}
@@ -566,14 +567,12 @@ MediaDecoderStateMachine::NeedToDecodeAudio()
{
MOZ_ASSERT(OnTaskQueue());
SAMPLE_LOG("NeedToDecodeAudio() isDec=%d minPrl=%d enufAud=%d",
IsAudioDecoding(), mMinimizePreroll,
HaveEnoughDecodedAudio(mAmpleAudioThresholdUsecs * mPlaybackRate));
IsAudioDecoding(), mMinimizePreroll, HaveEnoughDecodedAudio());
return IsAudioDecoding() &&
mState != DECODER_STATE_SEEKING &&
((IsDecodingFirstFrame() && AudioQueue().GetSize() == 0) ||
(!mMinimizePreroll &&
!HaveEnoughDecodedAudio(mAmpleAudioThresholdUsecs * mPlaybackRate)));
(!mMinimizePreroll && !HaveEnoughDecodedAudio()));
}
bool
@@ -609,7 +608,6 @@ MediaDecoderStateMachine::OnAudioDecoded(MediaData* aAudioSample)
RefPtr<MediaData> audio(aAudioSample);
MOZ_ASSERT(audio);
mAudioDataRequest.Complete();
aAudioSample->AdjustForStartTime(StartTime());
// audio->GetEndTime() is not always mono-increasing in chained ogg.
mDecodedAudioEndTime = std::max(audio->GetEndTime(), mDecodedAudioEndTime);
@@ -707,22 +705,6 @@ MediaDecoderStateMachine::Push(MediaData* aSample, MediaData::Type aSampleType)
DispatchDecodeTasksIfNeeded();
}
void
MediaDecoderStateMachine::PushFront(MediaData* aSample, MediaData::Type aSampleType)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(aSample);
if (aSample->mType == MediaData::AUDIO_DATA) {
AudioQueue().PushFront(aSample);
} else if (aSample->mType == MediaData::VIDEO_DATA) {
aSample->As<VideoData>()->mFrameID = ++mCurrentFrameID;
VideoQueue().PushFront(aSample);
} else {
// TODO: Handle MediaRawData, determine which queue should be pushed.
}
UpdateNextFrameStatus();
}
void
MediaDecoderStateMachine::CheckIsAudible(const MediaData* aSample)
{
@@ -852,6 +834,11 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
return;
}
CheckIfDecodeComplete();
// Schedule next cycle to see if we can leave buffering state.
if (mState == DECODER_STATE_BUFFERING) {
ScheduleStateMachine();
}
return;
}
case DECODER_STATE_SEEKING: {
@@ -890,20 +877,19 @@ MediaDecoderStateMachine::MaybeFinishDecodeFirstFrame()
}
// We can now complete the pending seek.
mPendingSeek.Steal(mQueuedSeek);
SetState(DECODER_STATE_SEEKING);
ScheduleStateMachine();
InitiateSeek(Move(mQueuedSeek));
return true;
}
void
MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample)
MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample,
TimeStamp aDecodeStartTime)
{
MOZ_ASSERT(OnTaskQueue());
RefPtr<MediaData> video(aVideoSample);
MOZ_ASSERT(video);
mVideoDataRequest.Complete();
aVideoSample->AdjustForStartTime(StartTime());
// Handle abnormal or negative timestamps.
mDecodedVideoEndTime = std::max(mDecodedVideoEndTime, video->GetEndTime());
@@ -939,7 +925,7 @@ MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample)
if (mReader->IsAsync()) {
return;
}
TimeDuration decodeTime = TimeStamp::Now() - mVideoDecodeStartTime;
TimeDuration decodeTime = TimeStamp::Now() - aDecodeStartTime;
if (!IsDecodingFirstFrame() &&
THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs &&
!HasLowUndecodedData())
@@ -977,10 +963,8 @@ MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample)
// in this case, we'll just decode forward. Bug 1026330.
mCurrentSeek.mTarget.SetType(SeekTarget::Accurate);
}
if (mCurrentSeek.mTarget.IsFast() ||
mPendingSeek.Exists()) {
// Non-precise seek; or a pending seek exists ; we can stop the seek
// at the first sample.
if (mCurrentSeek.mTarget.IsFast()) {
// Non-precise seek. We can stop the seek at the first sample.
Push(video, MediaData::VIDEO_DATA);
} else {
// We're doing an accurate seek. We still need to discard
@@ -1274,10 +1258,6 @@ MediaDecoderStateMachine::SetDormant(bool aDormant)
return;
}
if (!mReader) {
return;
}
if (mMetadataRequest.Exists()) {
if (mPendingDormant && mPendingDormant.ref() != aDormant && !aDormant) {
// We already have a dormant request pending; the new request would have
@@ -1296,10 +1276,8 @@ MediaDecoderStateMachine::SetDormant(bool aDormant)
if (mState == DECODER_STATE_SEEKING) {
if (mQueuedSeek.Exists()) {
// Keep latest seek target
} else if (mPendingSeek.Exists()) {
mQueuedSeek.Steal(mPendingSeek);
} else if (mCurrentSeek.Exists()) {
mQueuedSeek.Steal(mCurrentSeek);
mQueuedSeek = Move(mCurrentSeek);
} else {
mQueuedSeek.mTarget = SeekTarget(mCurrentPosition,
SeekTarget::Accurate,
@@ -1316,7 +1294,6 @@ MediaDecoderStateMachine::SetDormant(bool aDormant)
// back to MediaDecoder when we come out of dormant?
RefPtr<MediaDecoder::SeekPromise> unused = mQueuedSeek.mPromise.Ensure(__func__);
}
mPendingSeek.RejectIfExists(__func__);
mCurrentSeek.RejectIfExists(__func__);
SetState(DECODER_STATE_DORMANT);
if (IsPlaying()) {
@@ -1354,7 +1331,6 @@ MediaDecoderStateMachine::Shutdown()
mBufferedUpdateRequest.DisconnectIfExists();
mQueuedSeek.RejectIfExists(__func__);
mPendingSeek.RejectIfExists(__func__);
mCurrentSeek.RejectIfExists(__func__);
#ifdef MOZ_EME
@@ -1368,11 +1344,7 @@ MediaDecoderStateMachine::Shutdown()
Reset();
mMediaSink->Shutdown();
// Shut down our start time rendezvous.
if (mStartTimeRendezvous) {
mStartTimeRendezvous->Destroy();
}
mReaderWrapper->Shutdown();
DECODER_LOG("Shutdown started");
@@ -1408,9 +1380,8 @@ void MediaDecoderStateMachine::StartDecoding()
"Return from dormant must have queued seek");
}
if (mQueuedSeek.Exists()) {
mPendingSeek.Steal(mQueuedSeek);
SetState(DECODER_STATE_SEEKING);
ScheduleStateMachine();
InitiateSeek(Move(mQueuedSeek));
return;
}
}
@@ -1510,8 +1481,7 @@ MediaDecoderStateMachine::ReadMetadata()
DECODER_LOG("Dispatching AsyncReadMetadata");
// Set mode to METADATA since we are about to read metadata.
mResource->SetReadMode(MediaCacheStream::MODE_METADATA);
mMetadataRequest.Begin(InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::AsyncReadMetadata)
mMetadataRequest.Begin(mReaderWrapper->ReadMetadata()
->Then(OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnMetadataRead,
&MediaDecoderStateMachine::OnMetadataNotRead));
@@ -1544,14 +1514,14 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget)
return mQueuedSeek.mPromise.Ensure(__func__);
}
mQueuedSeek.RejectIfExists(__func__);
mPendingSeek.RejectIfExists(__func__);
mPendingSeek.mTarget = aTarget;
DECODER_LOG("Changed state to SEEKING (to %lld)", mPendingSeek.mTarget.GetTime().ToMicroseconds());
DECODER_LOG("Changed state to SEEKING (to %lld)", aTarget.GetTime().ToMicroseconds());
SetState(DECODER_STATE_SEEKING);
ScheduleStateMachine();
return mPendingSeek.mPromise.Ensure(__func__);
SeekJob seekJob;
seekJob.mTarget = aTarget;
InitiateSeek(Move(seekJob));
return mCurrentSeek.mPromise.Ensure(__func__);
}
RefPtr<MediaDecoder::SeekPromise>
@@ -1631,12 +1601,12 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
}
void
MediaDecoderStateMachine::InitiateSeek()
MediaDecoderStateMachine::InitiateSeek(SeekJob aSeekJob)
{
MOZ_ASSERT(OnTaskQueue());
mCurrentSeek.RejectIfExists(__func__);
mCurrentSeek.Steal(mPendingSeek);
mCurrentSeek = Move(aSeekJob);
// Bound the seek time to be inside the media range.
int64_t end = Duration().ToMicroseconds();
@@ -1665,11 +1635,8 @@ MediaDecoderStateMachine::InitiateSeek()
// Do the seek.
RefPtr<MediaDecoderStateMachine> self = this;
SeekTarget seekTarget = mCurrentSeek.mTarget;
seekTarget.SetTime(seekTarget.GetTime() + media::TimeUnit::FromMicroseconds(StartTime()));
mSeekRequest.Begin(InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::Seek, seekTarget,
Duration().ToMicroseconds())
mSeekRequest.Begin(
mReaderWrapper->Seek(mCurrentSeek.mTarget, Duration())
->Then(OwnerThread(), __func__,
[self] (media::TimeUnit) -> void {
self->mSeekRequest.Complete();
@@ -1731,25 +1698,11 @@ MediaDecoderStateMachine::RequestAudioData()
SAMPLE_LOG("Queueing audio task - queued=%i, decoder-queued=%o",
AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
if (mSentFirstFrameLoadedEvent) {
mAudioDataRequest.Begin(InvokeAsync(DecodeTaskQueue(), mReader.get(),
__func__, &MediaDecoderReader::RequestAudioData)
->Then(OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded));
} else {
mAudioDataRequest.Begin(
InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::RequestAudioData)
->Then(OwnerThread(), __func__, mStartTimeRendezvous.get(),
&StartTimeRendezvous::ProcessFirstSample<AudioDataPromise, MediaData::AUDIO_DATA>,
&StartTimeRendezvous::FirstSampleRejected<MediaData::AUDIO_DATA>)
->CompletionPromise()
->Then(OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded)
);
}
mAudioDataRequest.Begin(
mReaderWrapper->RequestAudioData()
->Then(OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded));
}
nsresult
@@ -1799,40 +1752,28 @@ MediaDecoderStateMachine::RequestVideoData()
// Time the video decode, so that if it's slow, we can increase our low
// audio threshold to reduce the chance of an audio underrun while we're
// waiting for a video decode to complete.
mVideoDecodeStartTime = TimeStamp::Now();
TimeStamp videoDecodeStartTime = TimeStamp::Now();
bool skipToNextKeyFrame = mSentFirstFrameLoadedEvent &&
NeedToSkipToNextKeyframe();
int64_t currentTime =
mState == DECODER_STATE_SEEKING || !mSentFirstFrameLoadedEvent
? 0 : GetMediaTime() + StartTime();
media::TimeUnit currentTime = media::TimeUnit::FromMicroseconds(
mState == DECODER_STATE_SEEKING ? 0 : GetMediaTime());
SAMPLE_LOG("Queueing video task - queued=%i, decoder-queued=%o, skip=%i, time=%lld",
VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(), skipToNextKeyFrame,
currentTime);
currentTime.ToMicroseconds());
if (mSentFirstFrameLoadedEvent) {
mVideoDataRequest.Begin(
InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::RequestVideoData,
skipToNextKeyFrame, currentTime)
->Then(OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnVideoDecoded,
&MediaDecoderStateMachine::OnVideoNotDecoded));
} else {
mVideoDataRequest.Begin(
InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::RequestVideoData,
skipToNextKeyFrame, currentTime)
->Then(OwnerThread(), __func__, mStartTimeRendezvous.get(),
&StartTimeRendezvous::ProcessFirstSample<VideoDataPromise, MediaData::VIDEO_DATA>,
&StartTimeRendezvous::FirstSampleRejected<MediaData::VIDEO_DATA>)
->CompletionPromise()
->Then(OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnVideoDecoded,
&MediaDecoderStateMachine::OnVideoNotDecoded));
}
RefPtr<MediaDecoderStateMachine> self = this;
mVideoDataRequest.Begin(
mReaderWrapper->RequestVideoData(skipToNextKeyFrame, currentTime)
->Then(OwnerThread(), __func__,
[self, videoDecodeStartTime] (MediaData* aVideoSample) {
self->OnVideoDecoded(aVideoSample, videoDecodeStartTime);
},
[self] (MediaDecoderReader::NotDecodedReason aReason) {
self->OnVideoNotDecoded(aReason);
}));
}
void
@@ -1974,29 +1915,14 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
mMetadataTags = aMetadata->mTags.forget();
RefPtr<MediaDecoderStateMachine> self = this;
// Set up the start time rendezvous if it doesn't already exist (which is
// generally the case, unless we're coming out of dormant mode).
if (!mStartTimeRendezvous) {
mStartTimeRendezvous = new StartTimeRendezvous(OwnerThread(), HasAudio(), HasVideo(),
mReader->ForceZeroStartTime() || IsRealTime());
mStartTimeRendezvous->AwaitStartTime()->Then(OwnerThread(), __func__,
[self] () -> void {
NS_ENSURE_TRUE_VOID(!self->IsShutdown());
self->mReader->DispatchSetStartTime(self->StartTime());
},
[] () -> void { NS_WARNING("Setting start time on reader failed"); }
);
}
if (mInfo.mMetadataDuration.isSome()) {
RecomputeDuration();
} else if (mInfo.mUnadjustedMetadataEndTime.isSome()) {
mStartTimeRendezvous->AwaitStartTime()->Then(OwnerThread(), __func__,
mReaderWrapper->AwaitStartTime()->Then(OwnerThread(), __func__,
[self] () -> void {
NS_ENSURE_TRUE_VOID(!self->IsShutdown());
TimeUnit unadjusted = self->mInfo.mUnadjustedMetadataEndTime.ref();
TimeUnit adjustment = TimeUnit::FromMicroseconds(self->StartTime());
TimeUnit adjustment = self->mReaderWrapper->StartTime();
self->mInfo.mMetadataDuration.emplace(unadjusted - adjustment);
self->RecomputeDuration();
}, [] () -> void { NS_WARNING("Adjusting metadata end time failed"); }
@@ -2157,34 +2083,36 @@ MediaDecoderStateMachine::SeekCompleted()
newCurrentTime = video ? video->mTime : seekTime;
}
if (mDecodingFirstFrame) {
// We were resuming from dormant, or initiated a seek early.
// We can fire loadeddata now.
FinishDecodeFirstFrame();
}
// Change state to DECODING or COMPLETED now. SeekingStopped will
// call MediaDecoderStateMachine::Seek to reset our state to SEEKING
// if we need to seek again.
// Change state to DECODING or COMPLETED now.
bool isLiveStream = mResource->IsLiveStream();
if (mPendingSeek.Exists()) {
// A new seek target came in while we were processing the old one. No rest
// for the seeking.
DECODER_LOG("A new seek came along while we were finishing the old one - staying in SEEKING");
SetState(DECODER_STATE_SEEKING);
} else if (GetMediaTime() == Duration().ToMicroseconds() && !isLiveStream) {
State nextState;
if (GetMediaTime() == Duration().ToMicroseconds() && !isLiveStream) {
// Seeked to end of media, move to COMPLETED state. Note we don't do
// this when playing a live stream, since the end of media will advance
// once we download more data!
DECODER_LOG("Changed state from SEEKING (to %lld) to COMPLETED", seekTime);
// Explicitly set our state so we don't decode further, and so
// we report playback ended to the media element.
SetState(DECODER_STATE_COMPLETED);
DispatchDecodeTasksIfNeeded();
nextState = DECODER_STATE_COMPLETED;
} else {
DECODER_LOG("Changed state from SEEKING (to %lld) to DECODING", seekTime);
nextState = DECODER_STATE_DECODING;
}
// We want to resolve the seek request prior finishing the first frame
// to ensure that the seeked event is fired prior loadeded.
mCurrentSeek.Resolve(nextState == DECODER_STATE_COMPLETED, __func__);
if (mDecodingFirstFrame) {
// We were resuming from dormant, or initiated a seek early.
// We can fire loadeddata now.
FinishDecodeFirstFrame();
}
if (nextState == DECODER_STATE_DECODING) {
StartDecoding();
} else {
SetState(nextState);
}
// Ensure timestamps are up to date.
@@ -2198,7 +2126,6 @@ MediaDecoderStateMachine::SeekCompleted()
// if we need to buffer after the seek.
mQuickBuffering = false;
mCurrentSeek.Resolve(mState == DECODER_STATE_COMPLETED, __func__);
ScheduleStateMachine();
if (video) {
@@ -2347,9 +2274,6 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
}
case DECODER_STATE_SEEKING: {
if (mPendingSeek.Exists()) {
InitiateSeek();
}
return NS_OK;
}
@@ -2531,7 +2455,8 @@ MediaDecoderStateMachine::DropVideoUpToSeekTarget(MediaData* aSample)
DECODER_LOG("DropVideoUpToSeekTarget() found video frame [%lld, %lld] containing target=%lld",
video->mTime, video->GetEndTime(), target);
PushFront(video, MediaData::VIDEO_DATA);
MOZ_ASSERT(VideoQueue().GetSize() == 0, "Should be the 1st sample after seeking");
Push(video, MediaData::VIDEO_DATA);
}
return NS_OK;
@@ -2607,7 +2532,8 @@ MediaDecoderStateMachine::DropAudioUpToSeekTarget(MediaData* aSample)
Move(audioData),
channels,
audio->mRate));
PushFront(data, MediaData::AUDIO_DATA);
MOZ_ASSERT(AudioQueue().GetSize() == 0, "Should be the 1st sample after seeking");
Push(data, MediaData::AUDIO_DATA);
return NS_OK;
}
+59 -191
View File
@@ -104,6 +104,7 @@ class MediaSink;
class AudioSegment;
class DecodedStream;
class MediaDecoderReaderWrapper;
class OutputStreamManager;
class TaskQueue;
@@ -210,12 +211,10 @@ public:
OwnerThread()->Dispatch(r.forget());
}
// Drop reference to mReader and mResource. Only called during shutdown dance.
// Drop reference to mResource. Only called during shutdown dance.
void BreakCycles() {
MOZ_ASSERT(NS_IsMainThread());
if (mReader) {
mReader->BreakCycles();
}
mReader->BreakCycles();
mResource = nullptr;
}
@@ -246,17 +245,11 @@ public:
bool IsRealTime() const { return mRealTime; }
size_t SizeOfVideoQueue() {
if (mReader) {
return mReader->SizeOfVideoQueueInBytes();
}
return 0;
return mReader->SizeOfVideoQueueInBytes();
}
size_t SizeOfAudioQueue() {
if (mReader) {
return mReader->SizeOfAudioQueueInBytes();
}
return 0;
return mReader->SizeOfAudioQueueInBytes();
}
private:
@@ -348,7 +341,7 @@ private:
// Discard audio/video data that are already played by MSG.
void DiscardStreamData();
bool HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs);
bool HaveEnoughDecodedAudio();
bool HaveEnoughDecodedVideo();
// Returns true if the state machine has shutdown or is in the process of
@@ -362,7 +355,7 @@ private:
// TODO: Those callback function may receive demuxed-only data.
// Need to figure out a suitable API name for this case.
void OnAudioDecoded(MediaData* aAudioSample);
void OnVideoDecoded(MediaData* aVideoSample);
void OnVideoDecoded(MediaData* aVideoSample, TimeStamp aDecodeStartTime);
void OnNotDecoded(MediaData::Type aType, MediaDecoderReader::NotDecodedReason aReason);
void OnAudioNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
{
@@ -390,7 +383,6 @@ protected:
// aSample must not be null.
void Push(MediaData* aSample, MediaData::Type aSampleType);
void PushFront(MediaData* aSample, MediaData::Type aSampleType);
void OnAudioPopped(const RefPtr<MediaData>& aSample);
void OnVideoPopped(const RefPtr<MediaData>& aSample);
@@ -528,9 +520,56 @@ protected:
void EnqueueFirstFrameLoadedEvent();
struct SeekJob {
SeekJob() {}
SeekJob(SeekJob&& aOther) : mTarget(aOther.mTarget)
{
aOther.mTarget.Reset();
mPromise = Move(aOther.mPromise);
}
SeekJob& operator=(SeekJob&& aOther)
{
MOZ_DIAGNOSTIC_ASSERT(!Exists());
mTarget = aOther.mTarget;
aOther.mTarget.Reset();
mPromise = Move(aOther.mPromise);
return *this;
}
bool Exists()
{
MOZ_ASSERT(mTarget.IsValid() == !mPromise.IsEmpty());
return mTarget.IsValid();
}
void Resolve(bool aAtEnd, const char* aCallSite)
{
mTarget.Reset();
MediaDecoder::SeekResolveValue val(aAtEnd, mTarget.mEventVisibility);
mPromise.Resolve(val, aCallSite);
}
void RejectIfExists(const char* aCallSite)
{
mTarget.Reset();
mPromise.RejectIfExists(true, aCallSite);
}
~SeekJob()
{
MOZ_DIAGNOSTIC_ASSERT(!mTarget.IsValid());
MOZ_DIAGNOSTIC_ASSERT(mPromise.IsEmpty());
}
SeekTarget mTarget;
MozPromiseHolder<MediaDecoder::SeekPromise> mPromise;
};
// Clears any previous seeking state and initiates a new see on the decoder.
// The decoder monitor must be held.
void InitiateSeek();
void InitiateSeek(SeekJob aSeekJob);
nsresult DispatchAudioDecodeTaskIfNeeded();
@@ -662,138 +701,6 @@ private:
// Used to dispatch another round schedule with specific target time.
DelayedScheduler mDelayedScheduler;
// StartTimeRendezvous is a helper class that quarantines the first sample
// until it gets a sample from both channels, such that we can be guaranteed
// to know the start time by the time On{Audio,Video}Decoded is called.
class StartTimeRendezvous {
public:
typedef MediaDecoderReader::AudioDataPromise AudioDataPromise;
typedef MediaDecoderReader::VideoDataPromise VideoDataPromise;
typedef MozPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StartTimeRendezvous);
StartTimeRendezvous(AbstractThread* aOwnerThread, bool aHasAudio, bool aHasVideo,
bool aForceZeroStartTime)
: mOwnerThread(aOwnerThread)
{
if (aForceZeroStartTime) {
mAudioStartTime.emplace(0);
mVideoStartTime.emplace(0);
return;
}
if (!aHasAudio) {
mAudioStartTime.emplace(INT64_MAX);
}
if (!aHasVideo) {
mVideoStartTime.emplace(INT64_MAX);
}
}
void Destroy()
{
mAudioStartTime = Some(mAudioStartTime.refOr(INT64_MAX));
mVideoStartTime = Some(mVideoStartTime.refOr(INT64_MAX));
mHaveStartTimePromise.RejectIfExists(false, __func__);
}
RefPtr<HaveStartTimePromise> AwaitStartTime()
{
if (HaveStartTime()) {
return HaveStartTimePromise::CreateAndResolve(true, __func__);
}
return mHaveStartTimePromise.Ensure(__func__);
}
template<typename PromiseType>
struct PromiseSampleType {
typedef typename PromiseType::ResolveValueType::element_type Type;
};
template<typename PromiseType, MediaData::Type SampleType>
RefPtr<PromiseType> ProcessFirstSample(typename PromiseSampleType<PromiseType>::Type* aData)
{
typedef typename PromiseSampleType<PromiseType>::Type DataType;
typedef typename PromiseType::Private PromisePrivate;
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MaybeSetChannelStartTime<SampleType>(aData->mTime);
RefPtr<PromisePrivate> p = new PromisePrivate(__func__);
RefPtr<DataType> data = aData;
RefPtr<StartTimeRendezvous> self = this;
AwaitStartTime()->Then(mOwnerThread, __func__,
[p, data, self] () -> void {
MOZ_ASSERT(self->mOwnerThread->IsCurrentThreadIn());
p->Resolve(data, __func__);
},
[p] () -> void { p->Reject(MediaDecoderReader::CANCELED, __func__); });
return p.forget();
}
template<MediaData::Type SampleType>
void FirstSampleRejected(MediaDecoderReader::NotDecodedReason aReason)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
if (aReason == MediaDecoderReader::DECODE_ERROR) {
mHaveStartTimePromise.RejectIfExists(false, __func__);
} else if (aReason == MediaDecoderReader::END_OF_STREAM) {
MOZ_LOG(gMediaDecoderLog, LogLevel::Debug,
("StartTimeRendezvous=%p SampleType(%d) Has no samples.", this, SampleType));
MaybeSetChannelStartTime<SampleType>(INT64_MAX);
}
}
bool HaveStartTime() { return mAudioStartTime.isSome() && mVideoStartTime.isSome(); }
int64_t StartTime()
{
int64_t time = std::min(mAudioStartTime.ref(), mVideoStartTime.ref());
return time == INT64_MAX ? 0 : time;
}
private:
virtual ~StartTimeRendezvous() {}
template<MediaData::Type SampleType>
void MaybeSetChannelStartTime(int64_t aStartTime)
{
if (ChannelStartTime(SampleType).isSome()) {
// If we're initialized with aForceZeroStartTime=true, the channel start
// times are already set.
return;
}
MOZ_LOG(gMediaDecoderLog, LogLevel::Debug,
("StartTimeRendezvous=%p Setting SampleType(%d) start time to %lld",
this, SampleType, aStartTime));
ChannelStartTime(SampleType).emplace(aStartTime);
if (HaveStartTime()) {
mHaveStartTimePromise.ResolveIfExists(true, __func__);
}
}
Maybe<int64_t>& ChannelStartTime(MediaData::Type aType)
{
return aType == MediaData::AUDIO_DATA ? mAudioStartTime : mVideoStartTime;
}
MozPromiseHolder<HaveStartTimePromise> mHaveStartTimePromise;
RefPtr<AbstractThread> mOwnerThread;
Maybe<int64_t> mAudioStartTime;
Maybe<int64_t> mVideoStartTime;
};
RefPtr<StartTimeRendezvous> mStartTimeRendezvous;
bool HaveStartTime() { return mStartTimeRendezvous && mStartTimeRendezvous->HaveStartTime(); }
int64_t StartTime() { return mStartTimeRendezvous->StartTime(); }
// Time at which the last video sample was requested. If it takes too long
// before the sample arrives, we will increase the amount of audio we buffer.
// This is necessary for legacy synchronous decoders to prevent underruns.
TimeStamp mVideoDecodeStartTime;
// Queue of audio frames. This queue is threadsafe, and is accessed from
// the audio, decoder, state machine, and main threads.
MediaQueue<MediaData> mAudioQueue;
@@ -840,50 +747,9 @@ private:
mNextPlayState == MediaDecoder::PLAY_STATE_PLAYING;
}
struct SeekJob {
void Steal(SeekJob& aOther)
{
MOZ_DIAGNOSTIC_ASSERT(!Exists());
mTarget = aOther.mTarget;
aOther.mTarget.Reset();
mPromise = Move(aOther.mPromise);
}
bool Exists()
{
MOZ_ASSERT(mTarget.IsValid() == !mPromise.IsEmpty());
return mTarget.IsValid();
}
void Resolve(bool aAtEnd, const char* aCallSite)
{
mTarget.Reset();
MediaDecoder::SeekResolveValue val(aAtEnd, mTarget.mEventVisibility);
mPromise.Resolve(val, aCallSite);
}
void RejectIfExists(const char* aCallSite)
{
mTarget.Reset();
mPromise.RejectIfExists(true, aCallSite);
}
~SeekJob()
{
MOZ_DIAGNOSTIC_ASSERT(!mTarget.IsValid());
MOZ_DIAGNOSTIC_ASSERT(mPromise.IsEmpty());
}
SeekTarget mTarget;
MozPromiseHolder<MediaDecoder::SeekPromise> mPromise;
};
// Queued seek - moves to mPendingSeek when DecodeFirstFrame completes.
// Queued seek - moves to mCurrentSeek when DecodeFirstFrame completes.
SeekJob mQueuedSeek;
// Position to seek to in microseconds when the seek state transition occurs.
SeekJob mPendingSeek;
// The position that we're currently seeking to.
SeekJob mCurrentSeek;
@@ -895,7 +761,9 @@ private:
// The reader, don't call its methods with the decoder monitor held.
// This is created in the state machine's constructor.
RefPtr<MediaDecoderReader> mReader;
const RefPtr<MediaDecoderReader> mReader;
const RefPtr<MediaDecoderReaderWrapper> mReaderWrapper;
// The end time of the last audio frame that's been pushed onto the media sink
// in microseconds. This will approximately be the end time
+2
View File
@@ -78,6 +78,8 @@ skip-if = true # bug 1182946
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_SeekNoData_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_SeekedEvent_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_SeekTwice_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_SetModeThrows.html]
@@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<head>
<title>MSE: Check that seeked event is fired prior loadeddata</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mediasource.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
runWithMSE(function(ms, el) {
el.controls = true;
el._seeked = false;
el._loadeddata = false;
el._playing = false;
el.addEventListener("seeked", function() {
ok(true, "got seeked event");
is(el._loadeddata, false, "can't have received loadeddata prior seeked");
is(el._playing, false, "can't be playing prior seeked");
el._seeked = true;
});
el.addEventListener("loadeddata", function() {
ok(true, "got loadeddata event");
is(el._seeked, true, "must have received seeked prior loadeddata");
is(el._playing, false, "can't be playing prior playing");
el._loadeddata = true;
});
el.addEventListener("playing", function() {
ok(true, "got playing");
is(el._seeked, true, "must have received seeked prior playing");
is(el._loadeddata, true, "must have received loadeddata prior playing");
el._playing = true;
});
once(ms, 'sourceopen').then(function() {
ok(true, "Receive a sourceopen event");
var videosb = ms.addSourceBuffer("video/mp4");
is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4')
.then(once.bind(null, el, "loadedmetadata"))
.then(function() {
el.play();
videosb.timestampOffset = 2;
is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
// Load [2, 3.606).
var promises = [];
promises.push(once(el, "play"));
promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', ['1'], '.m4s'));
return Promise.all(promises);
})
.then(function() {
return fetchAndLoad(videosb, 'bipbop/bipbop_video', ['2'], '.m4s');
})
.then(function() {
is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
el.currentTime = 2;
var promises = [];
promises.push(once(el, "seeked"));
promises.push(once(el, "playing"));
return Promise.all(promises);
})
.then(function() {
ok(true, "completed seek");
SimpleTest.finish();
});
});
});
</script>
</pre>
</body>
</html>
+1 -1
View File
@@ -122,7 +122,7 @@ nsXBLResourceLoader::LoadResources(bool* aResult)
// Passing nullptr for pretty much everything -- cause we don't care!
// XXX: initialDocumentURI is nullptr!
RefPtr<imgRequestProxy> req;
nsContentUtils::LoadImage(url, doc, docPrincipal, docURL,
nsContentUtils::LoadImage(url, doc, doc, docPrincipal, docURL,
doc->GetReferrerPolicy(), nullptr,
nsIRequest::LOAD_BACKGROUND, EmptyString(),
getter_AddRefs(req));
+1 -1
View File
@@ -292,7 +292,7 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode* aDOMNode,
return il->LoadImage(bgUri, nullptr, nullptr,
doc->GetReferrerPolicy(), principal, nullptr,
nullptr, nullptr, nsIRequest::LOAD_NORMAL,
nullptr, nullptr, nullptr, nsIRequest::LOAD_NORMAL,
nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE,
EmptyString(), aRequest);
}
+11 -7
View File
@@ -2071,6 +2071,8 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI,
}
imgRequestProxy* proxy;
ReferrerPolicy refpol = ReferrerPolicyFromString(aReferrerPolicy);
nsCOMPtr<nsINode> node = do_QueryInterface(aCX);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
nsresult rv = LoadImage(aURI,
aInitialDocumentURI,
aReferrerURI,
@@ -2078,7 +2080,8 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI,
aLoadingPrincipal,
aLoadGroup,
aObserver,
aCX,
node,
doc,
aLoadFlags,
aCacheKey,
aContentPolicyType,
@@ -2096,7 +2099,8 @@ imgLoader::LoadImage(nsIURI* aURI,
nsIPrincipal* aLoadingPrincipal,
nsILoadGroup* aLoadGroup,
imgINotificationObserver* aObserver,
nsISupports* aCX,
nsINode *aContext,
nsIDocument* aLoadingDocument,
nsLoadFlags aLoadFlags,
nsISupports* aCacheKey,
nsContentPolicyType aContentPolicyType,
@@ -2175,13 +2179,13 @@ imgLoader::LoadImage(nsIURI* aURI,
// XXX For now ignore aCacheKey. We will need it in the future
// for correctly dealing with image load requests that are a result
// of post data.
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aCX);
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aLoadingDocument);
ImageCacheKey key(aURI, doc);
imgCacheTable& cache = GetCache(key);
if (cache.Get(key, getter_AddRefs(entry)) && entry) {
if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI,
aReferrerPolicy, aLoadGroup, aObserver, aCX,
aReferrerPolicy, aLoadGroup, aObserver, aLoadingDocument,
requestFlags, aContentPolicyType, true, _retval,
aLoadingPrincipal, corsmode)) {
request = entry->GetRequest();
@@ -2232,7 +2236,7 @@ imgLoader::LoadImage(nsIURI* aURI,
requestFlags,
aContentPolicyType,
aLoadingPrincipal,
aCX);
aContext);
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;
}
@@ -2250,7 +2254,7 @@ imgLoader::LoadImage(nsIURI* aURI,
nsCOMPtr<nsILoadGroup> channelLoadGroup;
newChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
request->Init(aURI, aURI, /* aHadInsecureRedirect = */ false,
channelLoadGroup, newChannel, entry, aCX,
channelLoadGroup, newChannel, entry, aLoadingDocument,
aLoadingPrincipal, corsmode, aReferrerPolicy);
// Add the initiator type for this image load
@@ -2322,7 +2326,7 @@ imgLoader::LoadImage(nsIURI* aURI,
// URL maps to the same image on a page) if we load the same image in a
// different tab (see bug 528003), because its load id will get re-set, and
// that'll cause us to validate over the network.
request->SetLoadId(aCX);
request->SetLoadId(aLoadingDocument);
LOG_MSG(gImgLog, "imgLoader::LoadImage", "creating proxy request.");
rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver,
+2 -1
View File
@@ -252,7 +252,8 @@ public:
nsIPrincipal* aLoadingPrincipal,
nsILoadGroup* aLoadGroup,
imgINotificationObserver* aObserver,
nsISupports* aCX,
nsINode* aContext,
nsIDocument* aLoadingDocument,
nsLoadFlags aLoadFlags,
nsISupports* aCacheKey,
nsContentPolicyType aContentPolicyType,
+8
View File
@@ -61,6 +61,14 @@ JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn,
extern JS_PUBLIC_API(bool)
JS_Init(void);
/**
* A variant of JS_Init. On success it returns nullptr. On failure it returns a
* pointer to a string literal that describes how initialization failed, which
* can be useful for debugging purposes.
*/
extern JS_PUBLIC_API(const char*)
JS_InitWithFailureDiagnostic(void);
/**
* Destroy free-standing resources allocated by SpiderMonkey, not associated
* with any runtime, context, or other structure.
+1
View File
@@ -32,6 +32,7 @@
#include "vm/Debugger-inl.h"
using namespace js;
using namespace js::jit;
using namespace js::wasm;
using mozilla::CheckedInt;
+1
View File
@@ -13,6 +13,7 @@
#include "gc/Tracer.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"
using namespace js;
using namespace js::frontend;
@@ -23,6 +23,9 @@ ion/bug787921.js
ion/bug977966.js
parallel/alloc-many-objs.js
parallel/alloc-too-many-objs.js
parser/bug-1263881-1.js
parser/bug-1263881-2.js
parser/bug-1263881-3.js
saved-stacks/bug-1006876-too-much-recursion.js
self-test/assertDeepEq.js
sunspider/check-string-unpack-code.js
+7 -3
View File
@@ -346,12 +346,16 @@ BytecodeCompiler::prepareAndEmitTree(ParseNode** ppn)
{
if (!FoldConstants(cx, ppn, parser.ptr()) ||
!NameFunctions(cx, *ppn) ||
!emitter->updateLocalsToFrameSlots() ||
!emitter->emitTree(*ppn))
!emitter->updateLocalsToFrameSlots())
{
return false;
}
emitter->setFunctionBodyEndPos((*ppn)->pn_pos);
if (!emitter->emitTree(*ppn))
return false;
return true;
}
@@ -846,7 +850,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
MOZ_ASSERT(!options.forEval);
BytecodeEmitter bce(/* parent = */ nullptr, &parser, pn->pn_funbox, script, lazy,
/* insideEval = */ false, /* evalCaller = */ nullptr,
/* insideNonGlobalEval = */ false, options.lineno,
/* insideNonGlobalEval = */ false, pn->pn_pos,
BytecodeEmitter::LazyFunction);
if (!bce.init())
return false;
+49 -18
View File
@@ -143,12 +143,27 @@ BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
insideEval(insideEval),
insideNonGlobalEval(insideNonGlobalEval),
insideModule(false),
emitterMode(emitterMode)
emitterMode(emitterMode),
functionBodyEndPosSet(false)
{
MOZ_ASSERT_IF(evalCaller, insideEval);
MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript);
}
BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
Parser<FullParseHandler>* parser, SharedContext* sc,
HandleScript script, Handle<LazyScript*> lazyScript,
bool insideEval, HandleScript evalCaller,
bool insideNonGlobalEval, TokenPos bodyPosition,
EmitterMode emitterMode)
: BytecodeEmitter(parent, parser, sc, script, lazyScript, insideEval,
evalCaller, insideNonGlobalEval,
parser->tokenStream.srcCoords.lineNum(bodyPosition.begin),
emitterMode)
{
setFunctionBodyEndPos(bodyPosition);
}
bool
BytecodeEmitter::init()
{
@@ -2820,8 +2835,13 @@ BytecodeEmitter::emitElemOperands(ParseNode* pn, EmitElemOption opts)
if (!emitTree(pn->pn_right))
return false;
if (opts == EmitElemOption::Set && !emit2(JSOP_PICK, 2))
return false;
if (opts == EmitElemOption::Set) {
if (!emit2(JSOP_PICK, 2))
return false;
} else if (opts == EmitElemOption::IncDec || opts == EmitElemOption::CompoundAssign) {
if (!emit1(JSOP_TOID))
return false;
}
return true;
}
@@ -2840,8 +2860,10 @@ BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, EmitElemOption opts)
// We need to convert the key to an object id first, so that we do not do
// it inside both the GETELEM and the SETELEM.
if (opts == EmitElemOption::IncDec && !emit1(JSOP_TOID))
return false;
if (opts == EmitElemOption::IncDec || opts == EmitElemOption::CompoundAssign) {
if (!emit1(JSOP_TOID))
return false;
}
if (!emitGetThisForSuperBase(pn->pn_left))
return false;
@@ -2913,6 +2935,9 @@ BytecodeEmitter::emitElemIncDec(ParseNode* pn)
bool isSuper = pn->pn_kid->as<PropertyByValue>().isSuper();
// We need to convert the key to an object id first, so that we do not do
// it inside both the GETELEM and the SETELEM. This is done by
// emit(Super)ElemOperands.
if (isSuper) {
if (!emitSuperElemOperands(pn->pn_kid, EmitElemOption::IncDec))
return false;
@@ -2936,12 +2961,7 @@ BytecodeEmitter::emitElemIncDec(ParseNode* pn)
return false;
getOp = JSOP_GETELEM_SUPER;
} else {
// We need to convert the key to an object id first, so that we do not do
// it inside both the GETELEM and the SETELEM. In the super case, this is
// done by emitSuperElemOperands.
// OBJ KEY*
if (!emit1(JSOP_TOID)) // OBJ KEY
return false;
// OBJ KEY
if (!emit1(JSOP_DUP2)) // OBJ KEY OBJ KEY
return false;
getOp = JSOP_GETELEM;
@@ -3598,9 +3618,13 @@ BytecodeEmitter::emitFunctionScript(ParseNode* body)
switchToMain();
}
setFunctionBodyEndPos(body->pn_pos);
if (!emitTree(body))
return false;
if (!updateSourceCoordNotes(body->pn_pos.end))
return false;
if (sc->isFunctionBox()) {
if (sc->asFunctionBox()->isGenerator()) {
// If we fall off the end of a generator, do a final yield.
@@ -3700,6 +3724,7 @@ BytecodeEmitter::emitModuleScript(ParseNode* body)
// may walk the scope chain of currently compiling scripts.
JSScript::linkToModuleFromEmitter(cx, script, modulebox);
setFunctionBodyEndPos(body->pn_pos);
if (!emitTree(body))
return false;
@@ -4601,20 +4626,20 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
return false;
break;
case PNK_ELEM:
case PNK_ELEM: {
MOZ_ASSERT(lhs->isArity(PN_BINARY));
EmitElemOption opt = op == JSOP_NOP ? EmitElemOption::Get : EmitElemOption::CompoundAssign;
if (lhs->as<PropertyByValue>().isSuper()) {
if (!emitSuperElemOperands(lhs))
if (!emitSuperElemOperands(lhs, opt))
return false;
offset += 3;
} else {
if (!emitTree(lhs->pn_left))
return false;
if (!emitTree(lhs->pn_right))
if (!emitElemOperands(lhs, opt))
return false;
offset += 2;
}
break;
}
case PNK_ARRAY:
case PNK_OBJECT:
break;
@@ -6425,10 +6450,9 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
script->bindings = funbox->bindings;
uint32_t lineNum = parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin);
BytecodeEmitter bce2(this, parser, funbox, script, /* lazyScript = */ nullptr,
insideEval, evalCaller,
insideNonGlobalEval, lineNum, emitterMode);
insideNonGlobalEval, pn->pn_pos, emitterMode);
if (!bce2.init())
return false;
@@ -6799,6 +6823,13 @@ BytecodeEmitter::emitReturn(ParseNode* pn)
return false;
}
// We know functionBodyEndPos is set because "return" is only
// valid in a function, and so we've passed through
// emitFunctionScript.
MOZ_ASSERT(functionBodyEndPosSet);
if (!updateSourceCoordNotes(functionBodyEndPos))
return false;
/*
* EmitNonLocalJumpFixup may add fixup bytecode to close open try
* blocks having finally clauses and to exit intermingled let blocks.
+19 -1
View File
@@ -232,6 +232,11 @@ struct BytecodeEmitter
const EmitterMode emitterMode;
// The end location of a function body that is being emitted.
uint32_t functionBodyEndPos;
// Whether functionBodyEndPos was set.
bool functionBodyEndPosSet;
/*
* Note that BytecodeEmitters are magic: they own the arena "top-of-stack"
* space above their tempMark points. This means that you cannot alloc from
@@ -242,6 +247,14 @@ struct BytecodeEmitter
HandleScript script, Handle<LazyScript*> lazyScript,
bool insideEval, HandleScript evalCaller,
bool insideNonGlobalEval, uint32_t lineNum, EmitterMode emitterMode = Normal);
// An alternate constructor that uses a TokenPos for the starting
// line and that sets functionBodyEndPos as well.
BytecodeEmitter(BytecodeEmitter* parent, Parser<FullParseHandler>* parser, SharedContext* sc,
HandleScript script, Handle<LazyScript*> lazyScript,
bool insideEval, HandleScript evalCaller,
bool insideNonGlobalEval, TokenPos bodyPosition, EmitterMode emitterMode = Normal);
bool init();
bool updateLocalsToFrameSlots();
@@ -302,6 +315,11 @@ struct BytecodeEmitter
unsigned currentLine() const { return current->currentLine; }
unsigned lastColumn() const { return current->lastColumn; }
void setFunctionBodyEndPos(TokenPos pos) {
functionBodyEndPos = pos.end;
functionBodyEndPosSet = true;
}
bool reportError(ParseNode* pn, unsigned errorNumber, ...);
bool reportStrictWarning(ParseNode* pn, unsigned errorNumber, ...);
bool reportStrictModeError(ParseNode* pn, unsigned errorNumber, ...);
@@ -519,7 +537,7 @@ struct BytecodeEmitter
// Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM
// opcode onto the stack in the right order. In the case of SETELEM, the
// value to be assigned must already be pushed.
enum class EmitElemOption { Get, Set, Call, IncDec };
enum class EmitElemOption { Get, Set, Call, IncDec, CompoundAssign };
bool emitElemOperands(ParseNode* pn, EmitElemOption opts);
bool emitElemOpBase(JSOp op);
+18 -7
View File
@@ -94,7 +94,9 @@ template <>
bool
ParseContext<FullParseHandler>::checkLocalsOverflow(TokenStream& ts)
{
if (vars_.length() + bodyLevelLexicals_.length() >= LOCALNO_LIMIT) {
if (vars_.length() + bodyLevelLexicals_.length() >= LOCALNO_LIMIT ||
bodyLevelLexicals_.length() >= Bindings::BODY_LEVEL_LEXICAL_LIMIT)
{
ts.reportError(JSMSG_TOO_MANY_LOCALS);
return false;
}
@@ -2331,8 +2333,9 @@ Parser<FullParseHandler>::bindBodyLevelFunctionName(HandlePropertyName funName,
MOZ_ASSERT(!dn->isUsed());
MOZ_ASSERT(dn->isDefn());
if (dn->kind() == Definition::CONSTANT || dn->kind() == Definition::LET)
return reportRedeclaration(nullptr, Definition::VAR, funName);
Definition::Kind kind = dn->kind();
if (kind == Definition::CONSTANT || kind == Definition::LET || kind == Definition::IMPORT)
return reportRedeclaration(nullptr, kind, funName);
/*
* Body-level function statements are effectively variable
@@ -2342,7 +2345,7 @@ Parser<FullParseHandler>::bindBodyLevelFunctionName(HandlePropertyName funName,
* the function's binding (which is mutable), so turn any existing
* declaration into a use.
*/
if (dn->kind() == Definition::ARG) {
if (kind == Definition::ARG) {
// The exception to the above comment is when the function
// has the same name as an argument. Then the argument node
// remains a definition. But change the function node pn so
@@ -2751,7 +2754,10 @@ Parser<ParseHandler>::templateLiteral(YieldHandling yieldHandling)
Node pn = noSubstitutionTemplate();
if (!pn)
return null();
Node nodeList = handler.newList(PNK_TEMPLATE_STRING_LIST, pn);
if (!nodeList)
return null();
TokenKind tt;
do {
@@ -3212,6 +3218,8 @@ Parser<ParseHandler>::functionArgsAndBodyGeneric(InHandling inHandling,
return false;
}
handler.setEndPosition(body, pos().begin);
return finishFunctionDefinition(pn, funbox, body);
}
@@ -4016,7 +4024,7 @@ HasOuterLexicalBinding(ParseContext<ParseHandler>* pc, StmtInfoPC* stmt, HandleA
while (stmt->enclosingScope) {
stmt = LexicalLookup(pc, atom, stmt->enclosingScope);
if (!stmt)
return false;
break;
if (stmt->type == StmtType::BLOCK)
return true;
}
@@ -7584,8 +7592,11 @@ Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
// We begin by checking for an outer pending error since it would
// have occurred first.
if (possibleError->checkForExprErrors())
possibleErrorInner.checkForExprErrors();
if (possibleError && !possibleError->checkForExprErrors())
return null();
// Go ahead and report the inner error.
possibleErrorInner.checkForExprErrors();
return null();
}
handler.addList(seq, pn);
+18 -4
View File
@@ -470,11 +470,25 @@ class HeapPtr : public WriteBarrieredBase<T>
};
/*
* A pre- and post-barriered heap pointer, for use inside the JS engine.
* A pre- and post-barriered heap pointer, for use inside the JS engine. These
* heap pointers can be stored in C++ containers like GCVector and GCHashMap.
*
* Unlike HeapPtr<T>, it can be used in memory that is not managed by the GC,
* i.e. in C++ containers. It is, however, somewhat slower, so should only be
* used in contexts where this ability is necessary.
* The GC sometimes keeps pointers to pointers to GC things --- for example, to
* track references into the nursery. However, C++ containers like GCVector and
* GCHashMap usually reserve the right to relocate their elements any time
* they're modified, invalidating all pointers to the elements. RelocatablePtr
* has a move constructor which knows how to keep the GC up to date if it is
* moved to a new location.
*
* However, because of this additional communication with the GC, RelocatablePtr
* is somewhat slower, so it should only be used in contexts where this ability
* is necessary.
*
* Obviously, JSObjects, JSStrings, and the like get tenured and compacted, so
* whatever pointers they contain get relocated, in the sense used here.
* However, since the GC itself is moving those values, it takes care of its
* internal pointers to those pointers itself. RelocatablePtr is only necessary
* when the relocation would otherwise occur without the GC's knowledge.
*/
template <class T>
class RelocatablePtr : public WriteBarrieredBase<T>
+13 -14
View File
@@ -2154,6 +2154,7 @@ JSObject*
js::TenuringTracer::moveToTenured(JSObject* src)
{
MOZ_ASSERT(IsInsideNursery(src));
MOZ_ASSERT(!src->zone()->usedByExclusiveThread);
AllocKind dstKind = src->allocKindForTenure(nursery());
Zone* zone = src->zone();
@@ -2286,20 +2287,18 @@ js::TenuringTracer::moveObjectToTenured(JSObject* dst, JSObject* src, AllocKind
}
}
if (src->getClass()->flags & JSCLASS_SKIP_NURSERY_FINALIZE) {
if (src->is<InlineTypedObject>()) {
InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
} else if (src->is<UnboxedArrayObject>()) {
tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
} else if (src->is<ArgumentsObject>()) {
tenuredSize += ArgumentsObject::objectMovedDuringMinorGC(this, dst, src);
} else if (JSObjectMovedOp op = dst->getClass()->extObjectMovedOp()) {
op(dst, src);
} else {
// Objects with JSCLASS_SKIP_NURSERY_FINALIZE need to be handled above
// to ensure any additional nursery buffers they hold are moved.
MOZ_CRASH("Unhandled JSCLASS_SKIP_NURSERY_FINALIZE Class");
}
if (src->is<InlineTypedObject>()) {
InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
} else if (src->is<UnboxedArrayObject>()) {
tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
} else if (src->is<ArgumentsObject>()) {
tenuredSize += ArgumentsObject::objectMovedDuringMinorGC(this, dst, src);
} else if (JSObjectMovedOp op = dst->getClass()->extObjectMovedOp()) {
op(dst, src);
} else if (src->getClass()->flags & JSCLASS_SKIP_NURSERY_FINALIZE) {
// Objects with JSCLASS_SKIP_NURSERY_FINALIZE need to be handled above
// to ensure any additional nursery buffers they hold are moved.
MOZ_CRASH("Unhandled JSCLASS_SKIP_NURSERY_FINALIZE Class");
}
return tenuredSize;
+3
View File
@@ -10,6 +10,8 @@
#define gc_Policy_h
#include "mozilla/TypeTraits.h"
#include "gc/Barrier.h"
#include "gc/Marking.h"
#include "js/GCPolicyAPI.h"
// Forward declare the types we're defining policies for. This file is
@@ -17,6 +19,7 @@
// will be available when we do template expansion, allowing for use of
// static members in the underlying types. We cannot, however, use
// static_assert to verify relations between types.
class JSLinearString;
namespace js {
class AccessorShape;
class ArgumentsObject;
@@ -0,0 +1,8 @@
if (!('oomTest' in this))
quit();
function f(x) {
oomTest(() => eval(x));
}
f("");
f("");
f(`eval([ "x = \`\${new Error.lineNumber}" ].join())`);
@@ -0,0 +1,34 @@
// Check that the line number reported at an onPop stop makes sense,
// even when it happens on an "artificial" instruction.
var g = newGlobal();
// This bit of code arranges for the line number of the "artificial"
// instruction to be something nonsensical -- the middle of a loop
// which cannot be entered.
g.eval(`function f() {
debugger; // +0
if(false) { // +1
for(var b=0; b<0; b++) { // +2
c = 2; // +3
} // +4
} // +5
} // +6
`);
var dbg = Debugger(g);
let debugLine;
let foundLine;
dbg.onDebuggerStatement = function(frame) {
debugLine = frame.script.getOffsetLocation(frame.offset).lineNumber;
frame.onPop = function(c) {
foundLine = this.script.getOffsetLocation(this.offset).lineNumber;
};
};
g.eval("f();\n");
// The stop should happen on the closing brace of the function.
assertEq(foundLine == debugLine + 6, true);
@@ -33,4 +33,4 @@ dbg.onDebuggerStatement = function(frame) {
g.f();
assertEq(foundLines, ",1,2,3,4,5,6,7,8,10");
assertEq(foundLines, ",1,2,3,4,5,6,7,8,10,11");
@@ -65,7 +65,7 @@ testOne("testTryFinally",
} finally { // +6
} // +7
nothing(); // +8
`, "168");
`, "1689");
// The same but without a finally clause.
testOne("testTryCatch",
@@ -74,7 +74,7 @@ testOne("testTryCatch",
} catch (e) { // +6
} // +7
nothing(); // +8
`, "18");
`, "189");
// Test the instructions at the end of a "catch".
testOne("testCatchFinally",
@@ -85,7 +85,7 @@ testOne("testCatchFinally",
} finally { // +6
} // +7
nothing(); // +8
`, "168");
`, "1689");
// The same but without a finally clause. This relies on a
// SpiderMonkey extension, because otherwise there's no way to see
@@ -98,7 +98,7 @@ testOne("testCatch",
} catch (e) { // +6
} // +7
nothing(); // +8
`, "18");
`, "189");
// Test the instruction at the end of a "finally" clause.
testOne("testFinally",
@@ -107,7 +107,7 @@ testOne("testFinally",
${bitOfCode}
} // +6
nothing(); // +7
`, "17");
`, "178");
// Test the instruction at the end of a "then" clause.
testOne("testThen",
@@ -116,7 +116,7 @@ testOne("testThen",
} else { // +6
} // +7
nothing(); // +8
`, "18");
`, "189");
// Test the instructions leaving a switch block.
testOne("testSwitch",
@@ -126,4 +126,4 @@ testOne("testSwitch",
${bitOfCode}
} // +6
nothing(); // +7
`, "17");
`, "178");
@@ -0,0 +1,29 @@
// Stepping over a not-taken "if" that is at the end of the function
// should move to the end of the function, not somewhere in the body
// of the "if".
var g = newGlobal();
g.eval(`function f() { // 1
var a,c; // 2
debugger; // 3
if(false) { // 4
for(var b=0; b<0; b++) { // 5
c = 2; // 6
} // 7
} // 8
} // 9
`);
var dbg = Debugger(g);
var badStep = false;
dbg.onDebuggerStatement = function(frame) {
let debugLine = frame.script.getOffsetLocation(frame.offset).lineNumber;
assertEq(debugLine, 3);
frame.onStep = function() {
let foundLine = this.script.getOffsetLocation(this.offset).lineNumber;
assertEq(foundLine <= 4 || foundLine >= 8, true);
};
};
g.eval("f();\n");
@@ -0,0 +1,34 @@
// Stepping through a function with a return statement should pause on
// the closing brace of the function.
var g = newGlobal();
var dbg = Debugger(g);
var log;
function test(fnStr) {
log = '';
g.eval(fnStr);
dbg.onDebuggerStatement = function(frame) {
frame.onStep = function() {
let {lineNumber, isEntryPoint} = frame.script.getOffsetLocation(frame.offset);
if (isEntryPoint) {
log += lineNumber + ' ';
}
};
};
g.eval("f(23);");
}
test("function f(x) {\n" + // 1
" debugger;\n" + // 2
" return 23 + x;\n" + // 3
"}\n"); // 4
assertEq(log, '3 4 ');
test("function f(x) {\n" + // 1
" debugger;\n" + // 2
" return;\n" + // 3
"}\n"); // 4
assertEq(log, '3 4 ');
@@ -48,7 +48,7 @@ assertEq(Object.keys(offsets).length, 2);
// have no effect on this one.
doSingleStep = false;
g.eval('t(0, 0, 0)');
assertEq(Object.keys(offsets).length, 6);
assertEq(Object.keys(offsets).length, 7);
doSingleStep = true;
// Single-step in an eval frame. This should reach every line but the
@@ -16,4 +16,4 @@ Debugger(global).onDebuggerStatement = function (frame) {
global.log = '';
global.eval("function f(n) { for (var i = 0; i < n; ++i) log += '. '; log += '! '; } debugger;");
global.f(3);
assertEq(global.log, "25 32 44 . 39 32 44 . 39 32 44 . 39 32 57 ! 69 ");
assertEq(global.log, "25 32 44 . 39 32 44 . 39 32 44 . 39 32 57 ! 70 ");
@@ -16,7 +16,7 @@ Debugger(global).onDebuggerStatement = function (frame) {
global.log = "";
global.eval("function ppppp() { return 1; }");
// 1 2 3 4
// 0123456789012345678901234567890123456789012345678
// 01234567890123456789012345678901234567890123456789
global.eval("function f(){ 1 && ppppp(ppppp()) && new Error() } debugger;");
global.f();
@@ -24,5 +24,5 @@ global.f();
// 25 - Inner print()
// 19 - Outer print()
// 37 - new Error()
// 48 - Exit the function body
assertEq(global.log, "14 25 19 37 48 ");
// 49 - Exit the function body
assertEq(global.log, "14 25 19 37 49 ");
@@ -55,7 +55,9 @@ g.eval("/* Any copyright is dedicated to the Public Domain.\n" +
" eval(\"42;\");\n" +
" function foo() {}\n" +
" if (true) {\n" +
" foo();\n" + // <- this is +6 and must be within the extent
" }\n" +
"}");
test(g.secondCall, 7);
" foo();\n" +
// The "missing" newline here is a trick to make a newline
// source note come at the end. A real newline between the two
// closing braces causes a setline note instead.
" } }");
test(g.secondCall, 8);
@@ -0,0 +1,14 @@
// |jit-test| --ion-pgo=on;
target = handler = {}
for (p of[new Proxy(target, handler)])
evaluate("foo()");
function foo() {
symbols = [Symbol]
values = [NaN]
for (comparator of[""])
for (b of values) assertEq;
for (comparator of[""])
for (a of symbols)
for (b of values) assertEq;
}
@@ -0,0 +1,3 @@
// |jit-test| module; error:SyntaxError
import x from 'y';
function x() {}
@@ -0,0 +1,11 @@
// |jit-test| error: SyntaxError
let moduleRepo = {};
setModuleResolveHook(function(module, specifier) {
return moduleRepo[specifier];
});
moduleRepo['a'] = parseModule("export let a = 1;");
let s = "";
let max = 65536;
for (let i = 0; i < max; i++)
s += "import * as ns" + i + " from 'a';\n";
parseModule(s);
@@ -0,0 +1,6 @@
// |jit-test| error: SyntaxError
let s = "";
let max = 65536;
for (let i = 0; i < max; i++)
s += "let ns" + i + " = "+ i +";\n";
eval(s);
@@ -0,0 +1,7 @@
// |jit-test| error: SyntaxError
let s = "function foo() {\n";
let max = 65536;
for (let i = 0; i < max; i++)
s += "let ns" + i + " = "+ i +";\n";
s += "};";
eval(s);
+13 -5
View File
@@ -1909,7 +1909,8 @@ jit::RenumberBlocks(MIRGraph& graph)
// A utility for code which deletes blocks. Renumber the remaining blocks,
// recompute dominators, and optionally recompute AliasAnalysis dependencies.
bool
jit::AccountForCFGChanges(MIRGenerator* mir, MIRGraph& graph, bool updateAliasAnalysis)
jit::AccountForCFGChanges(MIRGenerator* mir, MIRGraph& graph, bool updateAliasAnalysis,
bool underValueNumberer)
{
// Renumber the blocks and clear out the old dominator info.
size_t id = 0;
@@ -1928,7 +1929,7 @@ jit::AccountForCFGChanges(MIRGenerator* mir, MIRGraph& graph, bool updateAliasAn
return false;
}
AssertExtendedGraphCoherency(graph);
AssertExtendedGraphCoherency(graph, underValueNumberer);
return true;
}
@@ -2556,7 +2557,7 @@ AssertResumePointDominatedByOperands(MResumePoint* resume)
#endif // DEBUG
void
jit::AssertExtendedGraphCoherency(MIRGraph& graph)
jit::AssertExtendedGraphCoherency(MIRGraph& graph, bool underValueNumberer)
{
// Checks the basic GraphCoherency but also other conditions that
// do not hold immediately (such as the fact that critical edges
@@ -2580,8 +2581,15 @@ jit::AssertExtendedGraphCoherency(MIRGraph& graph)
MOZ_ASSERT(block->getSuccessor(i)->numPredecessors() == 1);
if (block->isLoopHeader()) {
MOZ_ASSERT(block->numPredecessors() == 2);
MBasicBlock* backedge = block->getPredecessor(1);
if (underValueNumberer && block->numPredecessors() == 3) {
// Fixup block.
MOZ_ASSERT(block->getPredecessor(1)->numPredecessors() == 0);
MOZ_ASSERT(graph.osrBlock(),
"Fixup blocks should only exists if we have an osr block.");
} else {
MOZ_ASSERT(block->numPredecessors() == 2);
}
MBasicBlock* backedge = block->backedge();
MOZ_ASSERT(backedge->id() >= block->id());
MOZ_ASSERT(backedge->numSuccessors() == 1);
MOZ_ASSERT(backedge->getSuccessor(0) == *block);
+3 -2
View File
@@ -60,7 +60,8 @@ bool
RenumberBlocks(MIRGraph& graph);
bool
AccountForCFGChanges(MIRGenerator* mir, MIRGraph& graph, bool updateAliasAnalysis);
AccountForCFGChanges(MIRGenerator* mir, MIRGraph& graph, bool updateAliasAnalysis,
bool underValueNumberer = false);
bool
RemoveUnmarkedBlocks(MIRGenerator* mir, MIRGraph& graph, uint32_t numMarkedBlocks);
@@ -81,7 +82,7 @@ void
AssertGraphCoherency(MIRGraph& graph);
void
AssertExtendedGraphCoherency(MIRGraph& graph);
AssertExtendedGraphCoherency(MIRGraph& graph, bool underValueNumberer = false);
bool
EliminateRedundantChecks(MIRGraph& graph);
+8 -1
View File
@@ -429,7 +429,11 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
bool hasUniqueBackedge() const {
MOZ_ASSERT(isLoopHeader());
MOZ_ASSERT(numPredecessors() >= 2);
return numPredecessors() == 2;
if (numPredecessors() == 2)
return true;
if (numPredecessors() == 3) // fixup block added by ValueNumbering phase.
return getPredecessor(1)->numPredecessors() == 0;
return false;
}
MBasicBlock* backedge() const {
MOZ_ASSERT(hasUniqueBackedge());
@@ -476,6 +480,9 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
}
void unmark() {
MOZ_ASSERT(mark_, "Unarking unmarked block");
unmarkUnchecked();
}
void unmarkUnchecked() {
mark_ = false;
}
+62 -18
View File
@@ -520,14 +520,12 @@ ValueNumberer::removePredecessorAndCleanUp(MBasicBlock* block, MBasicBlock* pred
// If this is a loop header, test whether it will become an unreachable
// loop, or whether it needs special OSR-related fixups.
bool isUnreachableLoop = false;
MBasicBlock* origBackedgeForOSRFixup = nullptr;
if (block->isLoopHeader()) {
if (block->loopPredecessor() == pred) {
if (MOZ_UNLIKELY(hasNonDominatingPredecessor(block, pred))) {
JitSpew(JitSpew_GVN, " "
"Loop with header block%u is now only reachable through an "
"OSR entry into the middle of the loop!!", block->id());
origBackedgeForOSRFixup = block->backedge();
} else {
// Deleting the entry into the loop makes the loop unreachable.
isUnreachableLoop = true;
@@ -606,11 +604,6 @@ ValueNumberer::removePredecessorAndCleanUp(MBasicBlock* block, MBasicBlock* pred
// Use the mark to note that we've already removed all its predecessors,
// and we know it's unreachable.
block->mark();
} else if (MOZ_UNLIKELY(origBackedgeForOSRFixup != nullptr)) {
// The loop is no only reachable through OSR into the middle. Fix it
// up so that the CFG can remain valid.
if (!fixupOSROnlyLoop(block, origBackedgeForOSRFixup))
return false;
}
return true;
@@ -1079,6 +1072,30 @@ ValueNumberer::visitGraph()
return true;
}
bool
ValueNumberer::insertOSRFixups()
{
ReversePostorderIterator end(graph_.end());
for (ReversePostorderIterator iter(graph_.begin()); iter != end; ) {
MBasicBlock* block = *iter++;
// Only add fixup block above for loops which can be reached from OSR.
if (!block->isLoopHeader())
continue;
// If the loop header is not self-dominated, then this loop does not
// have to deal with a second entry point, so there is no need to add a
// second entry point with a fixup block.
if (block->immediateDominator() != block)
continue;
if (!fixupOSROnlyLoop(block, block->backedge()))
return false;
}
return true;
}
// OSR fixups serve the purpose of representing the non-OSR entry into a loop
// when the only real entry is an OSR entry into the middle. However, if the
// entry into the middle is subsequently folded away, the loop may actually
@@ -1101,22 +1118,44 @@ bool ValueNumberer::cleanupOSRFixups()
succ->mark();
if (!worklist.append(succ))
return false;
} else if (succ->isLoopHeader() &&
succ->loopPredecessor() == block &&
succ->numPredecessors() == 3)
{
// Unmark fixup blocks if the loop predecessor is marked after
// the loop header.
succ->getPredecessor(1)->unmarkUnchecked();
}
}
// The one special thing we do during this mark pass is to mark
// loop predecessors of reachable blocks as reachable. These blocks are
// the OSR fixups blocks which need to remain if the loop remains,
// though they can be removed if the loop is removed.
// OSR fixup blocks are needed if and only if the loop header is
// reachable from its backedge (via the OSR block) and not from its
// original loop predecessor.
//
// Thus OSR fixup blocks are removed if the loop header is not
// reachable, or if the loop header is reachable from both its backedge
// and its original loop predecessor.
if (block->isLoopHeader()) {
MBasicBlock* pred = block->loopPredecessor();
if (!pred->isMarked() && pred->numPredecessors() == 0) {
MOZ_ASSERT(pred->numSuccessors() == 1,
MBasicBlock* maybeFixupBlock = nullptr;
if (block->numPredecessors() == 2) {
maybeFixupBlock = block->getPredecessor(0);
} else {
MOZ_ASSERT(block->numPredecessors() == 3);
if (!block->loopPredecessor()->isMarked())
maybeFixupBlock = block->getPredecessor(1);
}
if (maybeFixupBlock &&
!maybeFixupBlock->isMarked() &&
maybeFixupBlock->numPredecessors() == 0)
{
MOZ_ASSERT(maybeFixupBlock->numSuccessors() == 1,
"OSR fixup block should have exactly one successor");
MOZ_ASSERT(pred != graph_.entryBlock(),
MOZ_ASSERT(maybeFixupBlock != graph_.entryBlock(),
"OSR fixup block shouldn't be the entry block");
MOZ_ASSERT(pred != graph_.osrBlock(),
MOZ_ASSERT(maybeFixupBlock != graph_.osrBlock(),
"OSR fixup block shouldn't be the OSR entry block");
pred->mark();
maybeFixupBlock->mark();
}
}
}
@@ -1159,6 +1198,11 @@ ValueNumberer::run(UpdateAliasAnalysisFlag updateAliasAnalysis)
JitSpew(JitSpew_GVN, "Running GVN on graph (with %llu blocks)",
uint64_t(graph_.numBlocks()));
// Adding fixup blocks only make sense iff we have a second entry point into
// the graph which cannot be reached any more from the entry point.
if (graph_.osrBlock())
insertOSRFixups();
// Top level non-sparse iteration loop. If an iteration performs a
// significant change, such as discarding a block which changes the
// dominator tree and may enable more optimization, this loop takes another
@@ -1182,7 +1226,7 @@ ValueNumberer::run(UpdateAliasAnalysisFlag updateAliasAnalysis)
}
if (blocksRemoved_) {
if (!AccountForCFGChanges(mir_, graph_, dependenciesBroken_))
if (!AccountForCFGChanges(mir_, graph_, dependenciesBroken_, /* underValueNumberer = */ true))
return false;
blocksRemoved_ = false;
+2
View File
@@ -101,6 +101,8 @@ class ValueNumberer
bool visitBlock(MBasicBlock* block, const MBasicBlock* root);
bool visitDominatorTree(MBasicBlock* root);
bool visitGraph();
bool insertOSRFixups();
bool cleanupOSRFixups();
public:
@@ -13,24 +13,24 @@ BEGIN_TEST(testForceLexicalInitialization)
{
// Attach an uninitialized lexical to a scope and ensure that it's
// set to undefined
RootedGlobalObject g(cx, cx->global());
Rooted<ClonedBlockObject*> scope(cx, ClonedBlockObject::createGlobal(cx, g));
js::RootedGlobalObject g(cx, cx->global());
JS::Rooted<js::ClonedBlockObject*> scope(cx, js::ClonedBlockObject::createGlobal(cx, g));
RootedValue uninitialized(cx, MagicValue(JS_UNINITIALIZED_LEXICAL));
RootedPropertyName name(cx, Atomize(cx, "foopi", 4)->asPropertyName());
RootedId id(cx, NameToId(name));
JS::RootedValue uninitialized(cx, JS::MagicValue(JS_UNINITIALIZED_LEXICAL));
js::RootedPropertyName name(cx, Atomize(cx, "foopi", 4)->asPropertyName());
JS::RootedId id(cx, NameToId(name));
unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
NativeDefineProperty(cx, scope, id, uninitialized, nullptr, nullptr, attrs);
// Verify that "foopi" is uninitialized
const Value v = scope->getSlot(scope->lookup(cx, id)->slot());
const JS::Value v = scope->getSlot(scope->lookup(cx, id)->slot());
CHECK(v.isMagic(JS_UNINITIALIZED_LEXICAL));
ForceLexicalInitialization(cx, scope);
// Verify that "foopi" has been initialized to undefined
const Value v2 = scope->getSlot(scope->lookup(cx, id)->slot());
const JS::Value v2 = scope->getSlot(scope->lookup(cx, id)->slot());
CHECK(v2.isUndefined());
return true;
+4 -1
View File
@@ -8,7 +8,7 @@
#include "jsapi-tests/tests.h"
static bool WriteValidBytes(wasm::Encoder& encoder, bool* passed)
static bool WriteValidBytes(js::wasm::Encoder& encoder, bool* passed)
{
*passed = false;
if (!encoder.empty())
@@ -40,6 +40,7 @@ static bool WriteValidBytes(wasm::Encoder& encoder, bool* passed)
BEGIN_TEST(testWasmLEB128_encoding)
{
using namespace js;
using namespace wasm;
Bytes bytes;
@@ -69,6 +70,7 @@ END_TEST(testWasmLEB128_encoding)
BEGIN_TEST(testWasmLEB128_valid_decoding)
{
using namespace js;
using namespace wasm;
Bytes bytes;
@@ -119,6 +121,7 @@ END_TEST(testWasmLEB128_valid_decoding)
BEGIN_TEST(testWasmLEB128_invalid_decoding)
{
using namespace js;
using namespace wasm;
Bytes bytes;
+1 -1
View File
@@ -139,7 +139,7 @@ BEGIN_TEST(testXDR_sourceMap)
CHECK(script);
size_t len = strlen(*sm);
UniqueTwoByteChars expected_wrapper(js::InflateString(cx, *sm, &len));
JS::UniqueTwoByteChars expected_wrapper(js::InflateString(cx, *sm, &len));
char16_t *expected = expected_wrapper.get();
CHECK(expected);
+21 -7
View File
@@ -254,6 +254,7 @@ class Bindings
}
public:
static const uint32_t BODY_LEVEL_LEXICAL_LIMIT = UINT16_LIMIT;
static const uint32_t BLOCK_SCOPED_LIMIT = UINT16_LIMIT;
@@ -362,7 +363,6 @@ class Bindings
static_assert(sizeof(Bindings) % js::gc::CellSize == 0,
"Size of Bindings must be an integral multiple of js::gc::CellSize");
template <class Outer>
class BindingsOperations
{
@@ -437,12 +437,26 @@ class MutableBindingsOperations : public BindingsOperations<Outer>
void setBindingArray(const Binding* bindingArray, uintptr_t temporaryBit) {
bindings().bindingArrayAndFlag_ = uintptr_t(bindingArray) | temporaryBit;
}
void setNumArgs(uint16_t num) { bindings().numArgs_ = num; }
void setNumVars(uint32_t num) { bindings().numVars_ = num; }
void setNumBodyLevelLexicals(uint16_t num) { bindings().numBodyLevelLexicals_ = num; }
void setNumBlockScoped(uint16_t num) { bindings().numBlockScoped_ = num; }
void setNumUnaliasedVars(uint32_t num) { bindings().numUnaliasedVars_ = num; }
void setNumUnaliasedBodyLevelLexicals(uint16_t num) {
void setNumArgs(uint32_t num) {
MOZ_ASSERT(num <= UINT16_MAX);
bindings().numArgs_ = num;
}
void setNumVars(uint32_t num) {
bindings().numVars_ = num;
}
void setNumBodyLevelLexicals(uint32_t num) {
MOZ_ASSERT(num <= UINT16_MAX);
bindings().numBodyLevelLexicals_ = num;
}
void setNumBlockScoped(uint32_t num) {
MOZ_ASSERT(num <= UINT16_MAX);
bindings().numBlockScoped_ = num;
}
void setNumUnaliasedVars(uint32_t num) {
bindings().numUnaliasedVars_ = num;
}
void setNumUnaliasedBodyLevelLexicals(uint32_t num) {
MOZ_ASSERT(num <= UINT16_MAX);
bindings().numUnaliasedBodyLevelLexicals_ = num;
}
void setAliasedBodyLevelLexicalBegin(uint32_t offset) {
@@ -42,6 +42,17 @@ assertThrowsInstanceOf(function () {
`);
}, SyntaxError);
// Tests that redeclaring a var inside the catch is not allowed if there's a
// body-level lexical.
assertThrowsInstanceOf(function () {
eval(`
let x;
try {} catch (x) {
var x;
}
`);
}, SyntaxError);
var log = '';
var x = 'global-x';
@@ -38,6 +38,7 @@ const SYNTAX_ERROR_STMTS = [
"delete ({x=1})",
"delete {x=1} = {}",
"({x=1}.abc)",
"x > (0, {a = b} );",
// declarations
"var x = 0 + {a=1} = {}",
"let o = {x=1};",
@@ -0,0 +1,38 @@
var hits = 0;
var p = { toString() { hits++; return "prop" } };
var obj = { foo: 1 };
var ops = [["obj[p]++", 2],
["++obj[p]", 2],
["--obj[p]", 0],
["obj[p]--", 0],
["obj[p] += 2", 3],
["obj[p] -= 2", -1],
["obj[p] *= 2", 2],
["obj[p] /= 2", 0.5],
["obj[p] %= 2", 1],
["obj[p] >>>= 2", 0],
["obj[p] >>= 2", 0],
["obj[p] <<= 2", 4],
["obj[p] |= 2", 3],
["obj[p] ^= 2", 3],
["obj[p] &= 2", 0]];
var testHits = 0;
for (let op of ops) {
// Seed the value for each test.
obj.prop = 1;
// Do the operation.
eval(op[0]);
assertEq(obj.prop, op[1]);
// We should always call toString once, for each operation.
testHits++;
assertEq(hits, testHits);
}
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");
+13 -8
View File
@@ -7,6 +7,7 @@
#ifndef threading_ExclusiveData_h
#define threading_ExclusiveData_h
#include "mozilla/Alignment.h"
#include "mozilla/Maybe.h"
#include "mozilla/Move.h"
@@ -80,7 +81,7 @@ template <typename T>
class ExclusiveData
{
mutable Mutex lock_;
mutable T value_;
mutable mozilla::AlignedStorage2<T> value_;
ExclusiveData(const ExclusiveData&) = delete;
ExclusiveData& operator=(const ExclusiveData&) = delete;
@@ -94,15 +95,19 @@ class ExclusiveData
* value.
*/
template <typename U>
explicit ExclusiveData(U&& u)
: value_(mozilla::Forward<U>(u))
{
explicit ExclusiveData(U&& u) {
new (value_.addr()) T(mozilla::Forward<U>(u));
}
ExclusiveData(ExclusiveData&& rhs)
: value_(mozilla::Move(rhs.value_))
{
~ExclusiveData() {
acquire();
value_.addr()->~T();
release();
}
ExclusiveData(ExclusiveData&& rhs) {
MOZ_ASSERT(&rhs != this, "self-move disallowed!");
new (value_.addr()) T(mozilla::Move(*rhs.value_.addr()));
}
ExclusiveData& operator=(ExclusiveData&& rhs) {
@@ -148,7 +153,7 @@ class ExclusiveData
T& get() const {
MOZ_ASSERT(parent_);
return parent_->value_;
return *parent_->value_.addr();
}
operator T& () const { return get(); }
+1 -1
View File
@@ -119,7 +119,7 @@ class DateTimeInfo
}
};
friend bool ::JS_Init();
friend const char* ::JS_InitWithFailureDiagnostic();
// Initialize global date/time tracking state. This operation occurs
// during, and is restricted to, SpiderMonkey initialization.
+3 -1
View File
@@ -295,7 +295,9 @@ GlobalObject::initStarGenerators(JSContext* cx, Handle<GlobalObject*> global)
if (!iteratorProto)
return false;
RootedPlainObject genObjectProto(cx, NewObjectWithGivenProto<PlainObject>(cx, iteratorProto));
RootedObject genObjectProto(cx, global->createBlankPrototypeInheriting(cx,
&PlainObject::class_,
iteratorProto));
if (!genObjectProto)
return false;
if (!DefinePropertiesAndFunctions(cx, genObjectProto, nullptr, star_generator_methods))
+17 -10
View File
@@ -59,8 +59,8 @@ CheckMessageParameterCounts()
}
#endif /* DEBUG */
JS_PUBLIC_API(bool)
JS_Init(void)
JS_PUBLIC_API(const char*)
JS_InitWithFailureDiagnostic(void)
{
MOZ_ASSERT(libraryInitState == InitState::Uninitialized,
"must call JS_Init once before any JSAPI operation except "
@@ -76,18 +76,18 @@ JS_Init(void)
using js::TlsPerThreadData;
if (!TlsPerThreadData.init())
return false;
return "JS_InitWithFailureDiagnostic: TlsPerThreadData.init() failed";
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
if (!js::oom::InitThreadType())
return false;
return "JS_InitWithFailureDiagnostic: js::oom::InitThreadType() failed";
js::oom::SetThreadType(js::oom::THREAD_TYPE_MAIN);
#endif
js::jit::ExecutableAllocator::initStatic();
if (!js::jit::InitializeIon())
return false;
return "JS_InitWithFailureDiagnostic: js::jit::InitializeIon() failed";
js::DateTimeInfo::init();
@@ -95,20 +95,27 @@ JS_Init(void)
UErrorCode err = U_ZERO_ERROR;
u_init(&err);
if (U_FAILURE(err))
return false;
return "JS_InitWithFailureDiagnostic: u_init() failed";
#endif // EXPOSE_INTL_API
if (!js::CreateHelperThreadsState())
return false;
return "JS_InitWithFailureDiagnostic: js::CreateHelperThreadState() failed";
if (!FutexRuntime::initialize())
return false;
return "JS_InitWithFailureDiagnostic: FutexRuntime::initialize() failed";
if (!js::gcstats::Statistics::initialize())
return false;
return "JS_InitWithFailureDiagnostic: js::gcstats::Statistics::initialize() failed";
libraryInitState = InitState::Running;
return true;
return nullptr;
}
JS_PUBLIC_API(bool)
JS_Init(void)
{
const char* failure = JS_InitWithFailureDiagnostic();
return !failure;
}
JS_PUBLIC_API(void)
+7 -6
View File
@@ -205,7 +205,7 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
canUseSignalHandlers_(false),
defaultFreeOp_(thisFromCtor()),
debuggerMutations(0),
securityCallbacks(const_cast<JSSecurityCallbacks*>(&NullSecurityCallbacks)),
securityCallbacks(&NullSecurityCallbacks),
DOMcallbacks(nullptr),
destroyPrincipals(nullptr),
readPrincipals(nullptr),
@@ -698,9 +698,7 @@ JSRuntime::getDefaultLocale()
if (defaultLocale)
return defaultLocale;
char* locale;
char* lang;
char* p;
const char* locale;
#ifdef HAVE_SETLOCALE
locale = setlocale(LC_ALL, nullptr);
#else
@@ -708,10 +706,13 @@ JSRuntime::getDefaultLocale()
#endif
// convert to a well-formed BCP 47 language tag
if (!locale || !strcmp(locale, "C"))
locale = const_cast<char*>("und");
lang = JS_strdup(this, locale);
locale = "und";
char* lang = JS_strdup(this, locale);
if (!lang)
return nullptr;
char* p;
if ((p = strchr(lang, '.')))
*p = '\0';
while ((p = strchr(lang, '_')))
+1 -1
View File
@@ -895,7 +895,7 @@ IsSavedFrame(JSObject* obj)
if (!obj)
return false;
JSObject* unwrapped = CheckedUnwrap(obj);
JSObject* unwrapped = js::CheckedUnwrap(obj);
if (!unwrapped)
return false;
+4 -2
View File
@@ -141,8 +141,10 @@ class StaticBlockScope : public NestedStaticScope
/* Return the number of variables associated with this block. */
uint32_t numVariables() const {
// TODO: propertyCount() is O(n), use O(1) lastProperty()->slot() instead
return propertyCount();
uint32_t num = 0;
if (!lastProperty()->isEmptyShape())
num = lastProperty()->slot() + 1 - RESERVED_SLOTS;
return num;
}
private:
+2
View File
@@ -12,6 +12,8 @@
#include "gc/Barrier.h"
#include "gc/Zone.h"
#include "vm/Runtime-inl.h"
namespace js {
/* static */ void
+2
View File
@@ -10,6 +10,8 @@
#include "jscompartment.h"
#include "jsobjinlines.h"
#include "vm/NativeObject-inl.h"
using namespace js;
namespace JS {
+1
View File
@@ -698,6 +698,7 @@ UnboxedPlainObject::createWithProperties(ExclusiveContext* cx, HandleObjectGroup
#ifndef JS_CODEGEN_NONE
if (cx->isJSContext() &&
!group->unknownProperties() &&
!layout.constructorCode() &&
cx->asJSContext()->runtime()->jitSupportsFloatingPoint)
{
+4 -1
View File
@@ -570,7 +570,7 @@ static bool
HasBoxAncestor(nsIFrame* aFrame)
{
for (nsIFrame* f = aFrame; f; f = f->GetParent()) {
if (f->IsBoxFrame()) {
if (f->IsXULBoxFrame()) {
return true;
}
}
@@ -1117,6 +1117,8 @@ RestyleManager::AnimationsWithDestroyedFrame::StopAnimationsWithoutFrame(
{
nsAnimationManager* animationManager =
mRestyleManager->PresContext()->AnimationManager();
nsTransitionManager* transitionManager =
mRestyleManager->PresContext()->TransitionManager();
for (nsIContent* content : aArray) {
if (content->GetPrimaryFrame()) {
continue;
@@ -1124,6 +1126,7 @@ RestyleManager::AnimationsWithDestroyedFrame::StopAnimationsWithoutFrame(
dom::Element* element = content->AsElement();
animationManager->StopAnimationsForElement(element, aPseudoType);
transitionManager->StopTransitionsForElement(element, aPseudoType);
}
}
+5 -8
View File
@@ -250,8 +250,8 @@ public:
nsStyleContext* aOldStyleContext,
RefPtr<nsStyleContext>* aNewStyleContext /* inout */);
// AnimationsWithDestroyedFrame is used to stop animations on elements that
// have no frame at the end of the restyling process.
// AnimationsWithDestroyedFrame is used to stop animations and transitions
// on elements that have no frame at the end of the restyling process.
// It only lives during the restyling process.
class MOZ_STACK_CLASS AnimationsWithDestroyedFrame final {
public:
@@ -260,13 +260,10 @@ public:
// object. (This is generally easy since the caller is typically a
// method of RestyleManager.)
explicit AnimationsWithDestroyedFrame(RestyleManager* aRestyleManager);
~AnimationsWithDestroyedFrame()
{
}
// This method takes the content node for the generated content for
// animation on ::before and ::after, rather than the content node for
// the real element.
// animation/transition on ::before and ::after, rather than the
// content node for the real element.
void Put(nsIContent* aContent, nsStyleContext* aStyleContext) {
MOZ_ASSERT(aContent);
CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
@@ -291,7 +288,7 @@ public:
AutoRestore<AnimationsWithDestroyedFrame*> mRestorePointer;
// Below three arrays might include elements that have already had their
// animations stopped.
// animations or transitions stopped.
//
// mBeforeContents and mAfterContents hold the real element rather than
// the content node for the generated content (which might change during
+2 -2
View File
@@ -123,8 +123,8 @@ RestyleTracker::DoProcessRestyles()
bool isTimelineRecording = timelines && timelines->HasConsumer(docShell);
// Create a AnimationsWithDestroyedFrame during restyling process to
// stop animations on elements that have no frame at the end of the
// restyling process.
// stop animations and transitions on elements that have no frame at the end
// of the restyling process.
RestyleManager::AnimationsWithDestroyedFrame
animationsWithDestroyedFrame(mRestyleManager);
+52 -8
View File
@@ -425,7 +425,7 @@ static bool
ShouldSuppressFloatingOfDescendants(nsIFrame* aFrame)
{
return aFrame->IsFrameOfType(nsIFrame::eMathML) ||
aFrame->IsBoxFrame() ||
aFrame->IsXULBoxFrame() ||
::IsFlexOrGridContainer(aFrame);
}
@@ -8345,7 +8345,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
// (If we're in the XUL block-wrapping situation, parentFrame is the
// wrapper frame.)
nsIFrame* grandparentFrame = parentFrame->GetParent();
if (grandparentFrame && grandparentFrame->IsBoxFrame() &&
if (grandparentFrame && grandparentFrame->IsXULBoxFrame() &&
(grandparentFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
// check if this frame is the only one needing wrapping
aChild == AnyKidsNeedBlockParent(parentFrame->PrincipalChildList().FirstChild()) &&
@@ -10486,6 +10486,49 @@ void nsCSSFrameConstructor::CreateNeededPseudoSiblings(
iter.InsertItem(newItem);
}
#ifdef DEBUG
static bool
FrameWantsToBeInAnonymousItem(const nsIAtom* aParentType, const nsIFrame* aFrame)
{
// Note: This needs to match the logic in
// nsCSSFrameConstructor::FrameConstructionItem::NeedsAnonFlexOrGridItem()
if (aParentType == nsGkAtoms::gridContainerFrame) {
return aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
}
MOZ_ASSERT(aParentType == nsGkAtoms::flexContainerFrame);
return aFrame->IsFrameOfType(nsIFrame::eLineParticipant) ||
aFrame->GetType() == nsGkAtoms::placeholderFrame;
}
#endif
static void
VerifyGridFlexContainerChildren(nsIFrame* aParentFrame,
const nsFrameList& aChildren)
{
#ifdef DEBUG
auto parentType = aParentFrame->GetType();
if (parentType != nsGkAtoms::flexContainerFrame &&
parentType != nsGkAtoms::gridContainerFrame) {
return;
}
bool prevChildWasAnonItem = false;
for (const nsIFrame* child : aChildren) {
MOZ_ASSERT(!FrameWantsToBeInAnonymousItem(parentType, child),
"frame wants to be inside an anonymous item, but it isn't");
if (IsAnonymousFlexOrGridItem(child)) {
AssertAnonymousFlexOrGridItemParent(child, aParentFrame);
MOZ_ASSERT(!prevChildWasAnonItem, "two anon items in a row");
nsIFrame* firstWrappedChild = child->PrincipalChildList().FirstChild();
MOZ_ASSERT(firstWrappedChild, "anonymous item shouldn't be empty");
prevChildWasAnonItem = true;
} else {
prevChildWasAnonItem = false;
}
}
#endif
}
inline void
nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aState,
FrameConstructionItemList& aItems,
@@ -10504,6 +10547,7 @@ nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aSta
ConstructFramesFromItem(aState, iter, aParentFrame, aFrameItems);
}
VerifyGridFlexContainerChildren(aParentFrame, aFrameItems);
NS_ASSERTION(!aState.mHavePendingPopupgroup,
"Should have proccessed it by now");
}
@@ -10703,7 +10747,7 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
ConstructFramesFromItemList(aState, itemsToConstruct, aFrame, aFrameItems);
NS_ASSERTION(!aAllowBlockStyles || !aFrame->IsBoxFrame(),
NS_ASSERTION(!aAllowBlockStyles || !aFrame->IsXULBoxFrame(),
"can't be both block and box");
if (haveFirstLetterStyle) {
@@ -10716,15 +10760,15 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
// We might end up with first-line frames that change
// AnyKidsNeedBlockParent() without changing itemsToConstruct, but that
// should never happen for cases whan aFrame->IsBoxFrame().
NS_ASSERTION(!haveFirstLineStyle || !aFrame->IsBoxFrame(),
// should never happen for cases whan aFrame->IsXULBoxFrame().
NS_ASSERTION(!haveFirstLineStyle || !aFrame->IsXULBoxFrame(),
"Shouldn't have first-line style if we're a box");
NS_ASSERTION(!aFrame->IsBoxFrame() ||
NS_ASSERTION(!aFrame->IsXULBoxFrame() ||
itemsToConstruct.AnyItemsNeedBlockParent() ==
(AnyKidsNeedBlockParent(aFrameItems.FirstChild()) != nullptr),
"Something went awry in our block parent calculations");
if (aFrame->IsBoxFrame() && itemsToConstruct.AnyItemsNeedBlockParent()) {
if (aFrame->IsXULBoxFrame() && itemsToConstruct.AnyItemsNeedBlockParent()) {
// XXXbz we could do this on the FrameConstructionItemList level,
// no? And if we cared we could look through the item list
// instead of groveling through the framelist here..
@@ -12061,7 +12105,7 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
// Situation #1 is a XUL frame that contains frames that are required
// to be wrapped in blocks.
if (aFrame->IsBoxFrame() &&
if (aFrame->IsXULBoxFrame() &&
!(aFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
aItems.AnyItemsNeedBlockParent()) {
RecreateFramesForContent(aFrame->GetContent(), true,
-15
View File
@@ -5519,21 +5519,6 @@ nsImageRenderer::IsAnimatedImage()
return false;
}
bool
nsImageRenderer::IsContainerAvailable(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
if (mType != eStyleImageType_Image || !mImageContainer) {
return false;
}
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
return mImageContainer->IsImageContainerAvailable(aManager, flags);
}
already_AddRefed<imgIContainer>
nsImageRenderer::GetImage()
{
-10
View File
@@ -252,16 +252,6 @@ public:
bool IsRasterImage();
bool IsAnimatedImage();
/**
* @return true if this nsImageRenderer wraps an image which has an
* ImageContainer available.
*
* If IsContainerAvailable() returns true, GetImage() will return a non-null
* imgIContainer which callers can use to retrieve the ImageContainer.
*/
bool IsContainerAvailable(LayerManager* aManager,
nsDisplayListBuilder* aBuilder);
/// Retrieves the image associated with this nsImageRenderer, if there is one.
already_AddRefed<imgIContainer> GetImage();
+148 -125
View File
@@ -1941,7 +1941,7 @@ void nsDisplayList::DeleteAll() {
static bool
GetMouseThrough(const nsIFrame* aFrame)
{
if (!aFrame->IsBoxFrame())
if (!aFrame->IsXULBoxFrame())
return false;
const nsIFrame* frame = aFrame;
@@ -1951,7 +1951,7 @@ GetMouseThrough(const nsIFrame* aFrame)
} else if (frame->GetStateBits() & NS_FRAME_MOUSE_THROUGH_NEVER) {
return false;
}
frame = nsBox::GetParentBox(frame);
frame = nsBox::GetParentXULBox(frame);
}
return false;
}
@@ -2348,32 +2348,33 @@ nsDisplayBackgroundImage::nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilde
: nsDisplayImageContainer(aBuilder, aFrame)
, mBackgroundStyle(aBackgroundStyle)
, mLayer(aLayer)
, mIsRasterImage(false)
{
MOZ_COUNT_CTOR(nsDisplayBackgroundImage);
mBounds = GetBoundsInternal(aBuilder);
mDestArea = GetDestAreaInternal(aBuilder);
if (ShouldFixToViewport(aBuilder)) {
mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(this);
}
}
nsRect
nsDisplayBackgroundImage::GetDestAreaInternal(nsDisplayListBuilder* aBuilder)
{
if (!mBackgroundStyle) {
return nsRect();
}
nsPresContext* presContext = mFrame->PresContext();
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mImage.mLayers[mLayer];
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
nsBackgroundLayerState state =
nsCSSRendering::PrepareImageLayer(presContext, mFrame, flags,
borderArea, borderArea, layer);
return state.mDestArea;
mFillRect = state.mFillArea;
mDestRect = state.mDestArea;
nsImageRenderer* imageRenderer = &state.mImageRenderer;
// We only care about images here, not gradients.
if (imageRenderer->IsRasterImage()) {
mIsRasterImage = true;
mImage = imageRenderer->GetImage();
}
}
nsDisplayBackgroundImage::~nsDisplayBackgroundImage()
@@ -2606,24 +2607,16 @@ nsDisplayBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuil
if (mBackgroundStyle->mImage.mLayers.Length() != 1)
return false;
nsPresContext* presContext = mFrame->PresContext();
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
if (layer.mAttachment != NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED)
return false;
nsBackgroundLayerState state =
nsCSSRendering::PrepareImageLayer(presContext, mFrame, flags,
borderArea, aClipRect, layer);
nsImageRenderer* imageRenderer = &state.mImageRenderer;
// We only care about images here, not gradients.
if (!imageRenderer->IsRasterImage())
if (!mIsRasterImage)
return false;
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
*aDestRect = nsLayoutUtils::RectToGfxRect(state.mFillArea, appUnitsPerDevPixel);
int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
*aDestRect = nsLayoutUtils::RectToGfxRect(mFillRect, appUnitsPerDevPixel);
return true;
}
@@ -2658,75 +2651,35 @@ nsDisplayBackgroundImage::CanOptimizeToImageLayer(LayerManager* aManager,
return false;
}
nsPresContext* presContext = mFrame->PresContext();
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
nsBackgroundLayerState state =
nsCSSRendering::PrepareImageLayer(presContext, mFrame, flags,
borderArea, borderArea, layer);
nsImageRenderer* imageRenderer = &state.mImageRenderer;
// We only care about images here, not gradients.
if (!imageRenderer->IsRasterImage()) {
return false;
}
if (!imageRenderer->IsContainerAvailable(aManager, aBuilder)) {
// The image is not ready to be made into a layer yet.
return false;
}
// We currently can't handle tiled backgrounds.
if (!state.mDestArea.Contains(state.mFillArea)) {
if (!mDestRect.Contains(mFillRect)) {
return false;
}
// For 'contain' and 'cover', we allow any pixel of the image to be sampled
// because there isn't going to be any spriting/atlasing going on.
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
bool allowPartialImages =
(layer.mSize.mWidthType == nsStyleImageLayers::Size::eContain ||
layer.mSize.mWidthType == nsStyleImageLayers::Size::eCover);
if (!allowPartialImages && !state.mFillArea.Contains(state.mDestArea)) {
if (!allowPartialImages && !mFillRect.Contains(mDestRect)) {
return false;
}
// XXX Ignoring state.mAnchor. ImageLayer drawing snaps mDestArea edges to
// layer pixel boundaries. This should be OK for now.
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
mImageLayerDestRect =
LayoutDeviceRect::FromAppUnits(state.mDestArea, appUnitsPerDevPixel);
// Ok, we can turn this into a layer if needed.
mImage = imageRenderer->GetImage();
MOZ_ASSERT(mImage);
return true;
return nsDisplayImageContainer::CanOptimizeToImageLayer(aManager, aBuilder);
}
already_AddRefed<ImageContainer>
nsDisplayBackgroundImage::GetContainer(LayerManager* aManager,
nsDisplayListBuilder *aBuilder)
nsRect
nsDisplayBackgroundImage::GetDestRect()
{
if (!mImage) {
MOZ_ASSERT_UNREACHABLE("Must call CanOptimizeToImage() and get true "
"before calling GetContainer()");
return nullptr;
}
return mDestRect;
}
if (!mImageContainer) {
// We don't have an ImageContainer yet; get it from mImage.
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
mImageContainer = mImage->GetImageContainer(aManager, flags);
}
RefPtr<ImageContainer> container = mImageContainer;
return container.forget();
already_AddRefed<imgIContainer>
nsDisplayBackgroundImage::GetImage()
{
nsCOMPtr<imgIContainer> image = mImage;
return image.forget();
}
nsDisplayBackgroundImage::ImageLayerization
@@ -2787,8 +2740,11 @@ nsDisplayBackgroundImage::GetLayerState(nsDisplayListBuilder* aBuilder,
mImage->GetWidth(&imageWidth);
mImage->GetHeight(&imageHeight);
NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
LayoutDeviceRect destRect = LayoutDeviceRect::FromAppUnits(GetDestRect(), appUnitsPerDevPixel);
const LayerRect destLayerRect = mImageLayerDestRect * aParameters.Scale();
const LayerRect destLayerRect = destRect * aParameters.Scale();
// Calculate the scaling factor for the frame.
const gfxSize scale = gfxSize(destLayerRect.width / imageWidth,
@@ -2824,51 +2780,6 @@ nsDisplayBackgroundImage::BuildLayer(nsDisplayListBuilder* aBuilder,
return layer.forget();
}
void
nsDisplayBackgroundImage::ConfigureLayer(ImageLayer* aLayer,
const ContainerLayerParameters& aParameters)
{
aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
MOZ_ASSERT(mImage);
int32_t imageWidth;
int32_t imageHeight;
mImage->GetWidth(&imageWidth);
mImage->GetHeight(&imageHeight);
NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
if (imageWidth > 0 && imageHeight > 0) {
// We're actually using the ImageContainer. Let our frame know that it
// should consider itself to have painted successfully.
nsDisplayBackgroundGeometry::UpdateDrawResult(this,
image::DrawResult::SUCCESS);
}
// XXX(seth): Right now we ignore aParameters.Scale() and
// aParameters.Offset(), because FrameLayerBuilder already applies
// aParameters.Scale() via the layer's post-transform, and
// aParameters.Offset() is always zero.
MOZ_ASSERT(aParameters.Offset() == LayerIntPoint(0,0));
// It's possible (for example, due to downscale-during-decode) that the
// ImageContainer this ImageLayer is holding has a different size from the
// intrinsic size of the image. For this reason we compute the transform using
// the ImageContainer's size rather than the image's intrinsic size.
// XXX(seth): In reality, since the size of the ImageContainer may change
// asynchronously, this is not enough. Bug 1183378 will provide a more
// complete fix, but this solution is safe in more cases than simply relying
// on the intrinsic size.
IntSize containerSize = aLayer->GetContainer()
? aLayer->GetContainer()->GetCurrentSize()
: IntSize(imageWidth, imageHeight);
const LayoutDevicePoint p = mImageLayerDestRect.TopLeft();
Matrix transform = Matrix::Translation(p.x, p.y);
transform.PreScale(mImageLayerDestRect.width / containerSize.width,
mImageLayerDestRect.height / containerSize.height);
aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
}
void
nsDisplayBackgroundImage::HitTest(nsDisplayListBuilder* aBuilder,
const nsRect& aRect,
@@ -3079,7 +2990,7 @@ void nsDisplayBackgroundImage::ComputeInvalidationRegion(nsDisplayListBuilder* a
}
return;
}
if (!mDestArea.IsEqualInterior(geometry->mDestArea)) {
if (!mDestRect.IsEqualInterior(geometry->mDestRect)) {
// Dest area changed in a way that could cause everything to change,
// so invalidate everything (both old and new painting areas).
aInvalidRegion->Or(bounds, geometry->mBounds);
@@ -3305,6 +3216,118 @@ nsDisplayThemedBackground::GetBoundsInternal() {
return r + ToReferenceFrame();
}
void
nsDisplayImageContainer::ConfigureLayer(ImageLayer* aLayer,
const ContainerLayerParameters& aParameters)
{
aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
nsCOMPtr<imgIContainer> image = GetImage();
MOZ_ASSERT(image);
int32_t imageWidth;
int32_t imageHeight;
image->GetWidth(&imageWidth);
image->GetHeight(&imageHeight);
NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
if (imageWidth > 0 && imageHeight > 0) {
// We're actually using the ImageContainer. Let our frame know that it
// should consider itself to have painted successfully.
nsDisplayBackgroundGeometry::UpdateDrawResult(this,
image::DrawResult::SUCCESS);
}
// XXX(seth): Right now we ignore aParameters.Scale() and
// aParameters.Offset(), because FrameLayerBuilder already applies
// aParameters.Scale() via the layer's post-transform, and
// aParameters.Offset() is always zero.
MOZ_ASSERT(aParameters.Offset() == LayerIntPoint(0,0));
// It's possible (for example, due to downscale-during-decode) that the
// ImageContainer this ImageLayer is holding has a different size from the
// intrinsic size of the image. For this reason we compute the transform using
// the ImageContainer's size rather than the image's intrinsic size.
// XXX(seth): In reality, since the size of the ImageContainer may change
// asynchronously, this is not enough. Bug 1183378 will provide a more
// complete fix, but this solution is safe in more cases than simply relying
// on the intrinsic size.
IntSize containerSize = aLayer->GetContainer()
? aLayer->GetContainer()->GetCurrentSize()
: IntSize(imageWidth, imageHeight);
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
const LayoutDeviceRect destRect =
LayoutDeviceRect::FromAppUnits(GetDestRect(), factor);
const LayoutDevicePoint p = destRect.TopLeft();
Matrix transform = Matrix::Translation(p.x, p.y);
transform.PreScale(destRect.width / containerSize.width,
destRect.height / containerSize.height);
aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
}
already_AddRefed<ImageContainer>
nsDisplayImageContainer::GetContainer(LayerManager* aManager,
nsDisplayListBuilder *aBuilder)
{
nsCOMPtr<imgIContainer> image = GetImage();
if (!image) {
MOZ_ASSERT_UNREACHABLE("Must call CanOptimizeToImage() and get true "
"before calling GetContainer()");
return nullptr;
}
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
return image->GetImageContainer(aManager, flags);
}
bool
nsDisplayImageContainer::CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
nsCOMPtr<imgIContainer> image = GetImage();
if (!image) {
return false;
}
if (!image->IsImageContainerAvailable(aManager, flags)) {
return false;
}
int32_t imageWidth;
int32_t imageHeight;
image->GetWidth(&imageWidth);
image->GetHeight(&imageHeight);
if (imageWidth == 0 || imageHeight == 0) {
NS_ASSERTION(false, "invalid image size");
return false;
}
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
const LayoutDeviceRect destRect =
LayoutDeviceRect::FromAppUnits(GetDestRect(), factor);
// Calculate the scaling factor for the frame.
const gfxSize scale = gfxSize(destRect.width / imageWidth,
destRect.height / imageHeight);
if (scale.width < 0.2 || scale.height < 0.2) {
// This would look awful as long as we can't use high-quality downscaling
// for image layers (bug 803703), so don't turn this into an image layer.
return false;
}
return true;
}
void
nsDisplayBackgroundColor::ApplyOpacity(nsDisplayListBuilder* aBuilder,
float aOpacity,
+14 -18
View File
@@ -2330,12 +2330,16 @@ public:
* CanOptimizeToImageLayer() first and it returned true.
*/
virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) = 0;
nsDisplayListBuilder* aBuilder);
virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) = 0;
virtual void ConfigureLayer(ImageLayer* aLayer,
const ContainerLayerParameters& aParameters) = 0;
already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder);
void ConfigureLayer(ImageLayer* aLayer,
const ContainerLayerParameters& aParameters);
virtual already_AddRefed<imgIContainer> GetImage() = 0;
virtual nsRect GetDestRect() = 0;
virtual bool SupportsOptimizingToImage() override { return true; }
};
@@ -2705,11 +2709,6 @@ public:
*/
nsRect GetPositioningArea();
/**
* Return the destination area of one instance of the image.
*/
nsRect GetDestArea() const { return mDestArea; }
/**
* Returns true if existing rendered pixels of this display item may need
* to be redrawn if the positioning area size changes but its position does
@@ -2730,10 +2729,8 @@ public:
virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) override;
virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder *aBuilder) override;
virtual void ConfigureLayer(ImageLayer* aLayer,
const ContainerLayerParameters& aParameters) override;
virtual already_AddRefed<imgIContainer> GetImage() override;
virtual nsRect GetDestRect() override;
static nsRegion GetInsideClipRegion(nsDisplayItem* aItem, uint8_t aClip,
const nsRect& aRect);
@@ -2750,7 +2747,6 @@ protected:
gfxRect* aDestRect);
bool IsNonEmptyFixedImage() const;
nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder);
nsRect GetDestAreaInternal(nsDisplayListBuilder* aBuilder);
void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
const nsRect& aBounds, nsRect* aClipRect);
@@ -2769,12 +2765,12 @@ protected:
// mIsThemed is true or if FindBackground returned false.
const nsStyleBackground* mBackgroundStyle;
nsCOMPtr<imgIContainer> mImage;
RefPtr<ImageContainer> mImageContainer;
LayoutDeviceRect mImageLayerDestRect;
nsRect mFillRect;
nsRect mDestRect;
/* Bounds of this display item */
nsRect mBounds;
nsRect mDestArea;
uint32_t mLayer;
bool mIsRasterImage;
};
+2 -2
View File
@@ -63,7 +63,7 @@ nsDisplayBackgroundGeometry::nsDisplayBackgroundGeometry(nsDisplayBackgroundImag
: nsDisplayItemGeometry(aItem, aBuilder)
, nsImageGeometryMixin(aItem, aBuilder)
, mPositioningArea(aItem->GetPositioningArea())
, mDestArea(aItem->GetDestArea())
, mDestRect(aItem->GetDestRect())
{}
void
@@ -71,7 +71,7 @@ nsDisplayBackgroundGeometry::MoveBy(const nsPoint& aOffset)
{
nsDisplayItemGeometry::MoveBy(aOffset);
mPositioningArea.MoveBy(aOffset);
mDestArea.MoveBy(aOffset);
mDestRect.MoveBy(aOffset);
}
nsDisplayThemedBackgroundGeometry::nsDisplayThemedBackgroundGeometry(nsDisplayThemedBackground* aItem,
+1 -1
View File
@@ -194,7 +194,7 @@ public:
virtual void MoveBy(const nsPoint& aOffset) override;
nsRect mPositioningArea;
nsRect mDestArea;
nsRect mDestRect;
};
class nsDisplayThemedBackgroundGeometry : public nsDisplayItemGeometry
+4 -4
View File
@@ -477,7 +477,7 @@ nsTextControlFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
aCBSize, aAvailableISize,
aMargin, aBorder,
aPadding, aShrinkWrap);
// Disabled when there's inflation; see comment in GetPrefSize.
// Disabled when there's inflation; see comment in GetXULPrefSize.
MOZ_ASSERT(inflation != 1.0f ||
ancestorAutoSize.ISize(aWM) == autoSize.ISize(aWM),
"Incorrect size computed by ComputeAutoSize?");
@@ -586,14 +586,14 @@ nsTextControlFrame::ReflowTextControlChild(nsIFrame* aKid,
}
nsSize
nsTextControlFrame::GetMinSize(nsBoxLayoutState& aState)
nsTextControlFrame::GetXULMinSize(nsBoxLayoutState& aState)
{
// XXXbz why? Why not the nsBoxFrame sizes?
return nsBox::GetMinSize(aState);
return nsBox::GetXULMinSize(aState);
}
bool
nsTextControlFrame::IsCollapsed()
nsTextControlFrame::IsXULCollapsed()
{
// We're never collapsed in the box sense.
return false;
+2 -2
View File
@@ -62,8 +62,8 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus) override;
virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual bool IsCollapsed() override;
virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual bool IsXULCollapsed() override;
virtual bool IsLeaf() const override;
+9
View File
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<body>
<div style="width: 1px;"><fieldset style="display: grid;">y<legend></legend>x</fieldset></div>
<div style="width: 1px;"><fieldset style="display: grid; overflow:hidden">y<legend></legend>x</fieldset></div>
<div style="width: 1px;"><fieldset style="display: flex;">y<legend></legend>x</fieldset></div>
<div style="width: 1px;"><fieldset style="display: flex; overflow:hidden">y<legend></legend>x</fieldset></div>
</body>
</html>
@@ -611,3 +611,4 @@ load details-display-none-summary-3.html
load 1304441.html
pref(dom.details_element.enabled,true) load summary-position-out-of-flow.html
asserts(4) load 1225005.html # bug 682647 and bug 448083
load 1233191.html
+2 -2
View File
@@ -704,8 +704,8 @@ nsContainerFrame::SyncWindowProperties(nsPresContext* aPresContext,
}
nsBoxLayoutState aState(aPresContext, aRC);
nsSize minSize = rootFrame->GetMinSize(aState);
nsSize maxSize = rootFrame->GetMaxSize(aState);
nsSize minSize = rootFrame->GetXULMinSize(aState);
nsSize maxSize = rootFrame->GetXULMaxSize(aState);
SetSizeConstraints(aPresContext, windowWidget, minSize, maxSize);
#endif
-52
View File
@@ -2032,54 +2032,6 @@ nsFlexContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
}
#ifdef DEBUG
// helper for the debugging method below
bool
FrameWantsToBeInAnonymousFlexItem(nsIFrame* aFrame)
{
// Note: This needs to match the logic in
// nsCSSFrameConstructor::FrameConstructionItem::NeedsAnonFlexOrGridItem()
return (aFrame->IsFrameOfType(nsIFrame::eLineParticipant) ||
nsGkAtoms::placeholderFrame == aFrame->GetType());
}
// Debugging method, to let us assert that our anonymous flex items are
// set up correctly -- in particular, we assert:
// (1) we don't have any inline non-replaced children
// (2) we don't have any consecutive anonymous flex items
// (3) we don't have any empty anonymous flex items
//
// XXXdholbert This matches what nsCSSFrameConstructor currently does, and what
// the spec used to say. However, the spec has now changed regarding what
// types of content get wrapped in an anonymous flexbox item. The patch that
// implements those changes (in nsCSSFrameConstructor) will need to change
// this method as well.
void
nsFlexContainerFrame::SanityCheckAnonymousFlexItems() const
{
bool prevChildWasAnonFlexItem = false;
for (nsIFrame* child : mFrames) {
MOZ_ASSERT(!FrameWantsToBeInAnonymousFlexItem(child),
"frame wants to be inside an anonymous flex item, "
"but it isn't");
if (child->StyleContext()->GetPseudo() ==
nsCSSAnonBoxes::anonymousFlexItem) {
MOZ_ASSERT(!prevChildWasAnonFlexItem ||
HasAnyStateBits(NS_STATE_FLEX_CHILDREN_REORDERED),
"two anon flex items in a row (shouldn't happen, unless our "
"children have been reordered with the 'order' property)");
nsIFrame* firstWrappedChild = child->PrincipalChildList().FirstChild();
MOZ_ASSERT(firstWrappedChild,
"anonymous flex item is empty (shouldn't happen)");
prevChildWasAnonFlexItem = true;
} else {
prevChildWasAnonFlexItem = false;
}
}
}
#endif // DEBUG
void
FlexLine::FreezeItemsEarly(bool aIsUsingFlexGrow)
{
@@ -3677,10 +3629,6 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
}
#ifdef DEBUG
SanityCheckAnonymousFlexItems();
#endif // DEBUG
// If we've never reordered our children, then we can trust that they're
// already in DOM-order, and we only need to consider their "order" property
// when checking them for sortedness & sorting them.
+45 -66
View File
@@ -183,11 +183,11 @@ InitBoxMetrics(nsIFrame* aFrame, bool aClear)
}
static bool
IsBoxWrapped(const nsIFrame* aFrame)
IsXULBoxWrapped(const nsIFrame* aFrame)
{
return aFrame->GetParent() &&
aFrame->GetParent()->IsBoxFrame() &&
!aFrame->IsBoxFrame();
aFrame->GetParent()->IsXULBoxFrame() &&
!aFrame->IsXULBoxFrame();
}
// Formerly the nsIFrameDebug interface
@@ -497,7 +497,7 @@ IsFontSizeInflationContainer(nsIFrame* aFrame,
nsGkAtoms::optgroup,
nsGkAtoms::select) ||
content->IsInNativeAnonymousSubtree()))) &&
!(aFrame->IsBoxFrame() && aFrame->GetParent()->IsBoxFrame());
!(aFrame->IsXULBoxFrame() && aFrame->GetParent()->IsXULBoxFrame());
NS_ASSERTION(!aFrame->IsFrameOfType(nsIFrame::eLineParticipant) ||
isInline ||
// br frames and mathml frames report being line
@@ -611,7 +611,7 @@ nsFrame::Init(nsIContent* aContent,
DidSetStyleContext(nullptr);
if (::IsBoxWrapped(this))
if (::IsXULBoxWrapped(this))
::InitBoxMetrics(this, false);
}
@@ -710,9 +710,9 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
}
}
if (HasCSSAnimations()) {
if (HasCSSAnimations() || HasCSSTransitions()) {
// If no new frame for this element is created by the end of the
// restyling process, stop animations for this frame
// restyling process, stop animations and transitions for this frame
if (presContext->RestyleManager()->IsGecko()) {
RestyleManager::AnimationsWithDestroyedFrame* adf =
presContext->RestyleManager()->AsGecko()->GetAnimationsWithDestroyedFrame();
@@ -4252,7 +4252,7 @@ nsFrame::MarkIntrinsicISizesDirty()
{
// This version is meant only for what used to be box-to-block adaptors.
// It should not be called by other derived classes.
if (::IsBoxWrapped(this)) {
if (::IsXULBoxWrapped(this)) {
nsBoxLayoutMetrics *metrics = BoxMetrics();
SizeNeedsRecalc(metrics->mPrefSize);
@@ -5029,12 +5029,6 @@ nsIFrame::GetView() const
return value;
}
/* virtual */ nsView*
nsIFrame::GetViewExternal() const
{
return GetView();
}
nsresult
nsIFrame::SetView(nsView* aView)
{
@@ -5068,11 +5062,6 @@ nsIFrame::SetView(nsView* aView)
return NS_OK;
}
nsIFrame* nsIFrame::GetAncestorWithViewExternal() const
{
return GetAncestorWithView();
}
// Find the first geometric parent that has a view
nsIFrame* nsIFrame::GetAncestorWithView() const
{
@@ -5084,12 +5073,6 @@ nsIFrame* nsIFrame::GetAncestorWithView() const
return nullptr;
}
// virtual
nsPoint nsIFrame::GetOffsetToExternal(const nsIFrame* aOther) const
{
return GetOffsetTo(aOther);
}
nsPoint nsIFrame::GetOffsetTo(const nsIFrame* aOther) const
{
NS_PRECONDITION(aOther,
@@ -5179,23 +5162,11 @@ nsIFrame::GetOffsetToCrossDoc(const nsIFrame* aOther, const int32_t aAPD) const
return offset;
}
// virtual
nsIntRect nsIFrame::GetScreenRectExternal() const
{
return GetScreenRect();
}
nsIntRect nsIFrame::GetScreenRect() const
{
return GetScreenRectInAppUnits().ToNearestPixels(PresContext()->AppUnitsPerCSSPixel());
}
// virtual
nsRect nsIFrame::GetScreenRectInAppUnitsExternal() const
{
return GetScreenRectInAppUnits();
}
nsRect nsIFrame::GetScreenRectInAppUnits() const
{
nsPresContext* presContext = PresContext();
@@ -5920,7 +5891,7 @@ nsFrame::UpdateOverflow()
nsOverflowAreas overflowAreas(rect, rect);
if (!DoesClipChildren() &&
!(IsCollapsed() && (IsBoxFrame() || ::IsBoxWrapped(this)))) {
!(IsXULCollapsed() && (IsXULBoxFrame() || ::IsXULBoxWrapped(this)))) {
nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
}
@@ -8008,7 +7979,7 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
// Note that NS_STYLE_OVERFLOW_CLIP doesn't clip the frame background,
// so we add theme background overflow here so it's not clipped.
if (!::IsBoxWrapped(this) && IsThemed(disp)) {
if (!::IsXULBoxWrapped(this) && IsThemed(disp)) {
nsRect r(bounds);
nsPresContext *presContext = PresContext();
if (presContext->GetTheme()->
@@ -8655,7 +8626,7 @@ nsFrame::RefreshSizeCache(nsBoxLayoutState& aState)
nsRect rect = GetRect();
nsMargin bp(0,0,0,0);
GetBorderAndPadding(bp);
GetXULBorderAndPadding(bp);
{
// If we're a container for font size inflation, then shrink
@@ -8730,7 +8701,7 @@ nsFrame::GetLineIterator()
}
nsSize
nsFrame::GetPrefSize(nsBoxLayoutState& aState)
nsFrame::GetXULPrefSize(nsBoxLayoutState& aState)
{
nsSize size(0,0);
DISPLAY_PREF_SIZE(this, size);
@@ -8741,12 +8712,12 @@ nsFrame::GetPrefSize(nsBoxLayoutState& aState)
return metrics->mPrefSize;
}
if (IsCollapsed())
if (IsXULCollapsed())
return size;
// get our size in CSS.
bool widthSet, heightSet;
bool completelyRedefined = nsIFrame::AddCSSPrefSize(this, size, widthSet, heightSet);
bool completelyRedefined = nsIFrame::AddXULPrefSize(this, size, widthSet, heightSet);
// Refresh our caches with new sizes.
if (!completelyRedefined) {
@@ -8766,7 +8737,7 @@ nsFrame::GetPrefSize(nsBoxLayoutState& aState)
}
nsSize
nsFrame::GetMinSize(nsBoxLayoutState& aState)
nsFrame::GetXULMinSize(nsBoxLayoutState& aState)
{
nsSize size(0,0);
DISPLAY_MIN_SIZE(this, size);
@@ -8777,13 +8748,13 @@ nsFrame::GetMinSize(nsBoxLayoutState& aState)
return size;
}
if (IsCollapsed())
if (IsXULCollapsed())
return size;
// get our size in CSS.
bool widthSet, heightSet;
bool completelyRedefined =
nsIFrame::AddCSSMinSize(aState, this, size, widthSet, heightSet);
nsIFrame::AddXULMinSize(aState, this, size, widthSet, heightSet);
// Refresh our caches with new sizes.
if (!completelyRedefined) {
@@ -8801,7 +8772,7 @@ nsFrame::GetMinSize(nsBoxLayoutState& aState)
}
nsSize
nsFrame::GetMaxSize(nsBoxLayoutState& aState)
nsFrame::GetXULMaxSize(nsBoxLayoutState& aState)
{
nsSize size(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
DISPLAY_MAX_SIZE(this, size);
@@ -8812,35 +8783,35 @@ nsFrame::GetMaxSize(nsBoxLayoutState& aState)
return size;
}
if (IsCollapsed())
if (IsXULCollapsed())
return size;
size = nsBox::GetMaxSize(aState);
size = nsBox::GetXULMaxSize(aState);
metrics->mMaxSize = size;
return size;
}
nscoord
nsFrame::GetFlex()
nsFrame::GetXULFlex()
{
nsBoxLayoutMetrics *metrics = BoxMetrics();
if (!DoesNeedRecalc(metrics->mFlex))
return metrics->mFlex;
metrics->mFlex = nsBox::GetFlex();
metrics->mFlex = nsBox::GetXULFlex();
return metrics->mFlex;
}
nscoord
nsFrame::GetBoxAscent(nsBoxLayoutState& aState)
nsFrame::GetXULBoxAscent(nsBoxLayoutState& aState)
{
nsBoxLayoutMetrics *metrics = BoxMetrics();
if (!DoesNeedRecalc(metrics->mAscent))
return metrics->mAscent;
if (IsCollapsed()) {
if (IsXULCollapsed()) {
metrics->mAscent = 0;
} else {
// Refresh our caches with new sizes.
@@ -8852,7 +8823,7 @@ nsFrame::GetBoxAscent(nsBoxLayoutState& aState)
}
nsresult
nsFrame::DoLayout(nsBoxLayoutState& aState)
nsFrame::DoXULLayout(nsBoxLayoutState& aState)
{
nsRect ourRect(mRect);
@@ -8869,7 +8840,7 @@ nsFrame::DoLayout(nsBoxLayoutState& aState)
BoxReflow(aState, presContext, desiredSize, rendContext,
ourRect.x, ourRect.y, ourRect.width, ourRect.height);
if (IsCollapsed()) {
if (IsXULCollapsed()) {
SetSize(nsSize(0, 0));
} else {
@@ -8880,7 +8851,7 @@ nsFrame::DoLayout(nsBoxLayoutState& aState)
desiredSize.BSize(outerWM) > ourSize.BSize(outerWM)) {
#ifdef DEBUG_GROW
DumpBox(stdout);
XULDumpBox(stdout);
printf(" GREW from (%d,%d) -> (%d,%d)\n",
ourSize.ISize(outerWM), ourSize.BSize(outerWM),
desiredSize.ISize(outerWM), desiredSize.BSize(outerWM));
@@ -8901,7 +8872,7 @@ nsFrame::DoLayout(nsBoxLayoutState& aState)
}
}
// Should we do this if IsCollapsed() is true?
// Should we do this if IsXULCollapsed() is true?
LogicalSize size(GetLogicalSize(outerWM));
desiredSize.ISize(outerWM) = size.ISize(outerWM);
desiredSize.BSize(outerWM) = size.BSize(outerWM);
@@ -9001,7 +8972,7 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState,
// Construct a bogus parent reflow state so that there's a usable
// containing block reflow state.
nsMargin margin(0,0,0,0);
GetMargin(margin);
GetXULMargin(margin);
nsSize parentSize(aWidth, aHeight);
if (parentSize.height != NS_INTRINSICSIZE)
@@ -9026,8 +8997,8 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState,
parentReflowState.SetComputedHeight(std::max(parentSize.height, 0));
parentReflowState.ComputedPhysicalMargin().SizeTo(0, 0, 0, 0);
// XXX use box methods
parentFrame->GetPadding(parentReflowState.ComputedPhysicalPadding());
parentFrame->GetBorder(parentReflowState.ComputedPhysicalBorderPadding());
parentFrame->GetXULPadding(parentReflowState.ComputedPhysicalPadding());
parentFrame->GetXULBorder(parentReflowState.ComputedPhysicalBorderPadding());
parentReflowState.ComputedPhysicalBorderPadding() +=
parentReflowState.ComputedPhysicalPadding();
@@ -9097,7 +9068,7 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState,
}
}
// Box layout calls SetRect before Layout, whereas non-box layout
// Box layout calls SetRect before XULLayout, whereas non-box layout
// calls SetRect after Reflow.
// XXX Perhaps we should be doing this by twiddling the rect back to
// mLastSize before calling Reflow and then switching it back, but
@@ -9136,7 +9107,7 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState,
&reflowState, aX, aY, layoutFlags | NS_FRAME_NO_MOVE_FRAME);
// Save the ascent. (bug 103925)
if (IsCollapsed()) {
if (IsXULCollapsed()) {
metrics->mAscent = 0;
} else {
if (aDesiredSize.BlockStartAscent() ==
@@ -9245,12 +9216,12 @@ nsIFrame::SetParent(nsContainerFrame* aParent)
{
// Note that the current mParent may already be destroyed at this point.
mParent = aParent;
if (::IsBoxWrapped(this)) {
if (::IsXULBoxWrapped(this)) {
::InitBoxMetrics(this, true);
} else {
// We could call Properties().Delete(BoxMetricsProperty()); here but
// that's kind of slow and re-parenting in such a way that we were
// IsBoxWrapped() before but not now should be very rare, so we'll just
// IsXULBoxWrapped() before but not now should be very rare, so we'll just
// keep this unused frame property until this frame dies instead.
}
@@ -9382,6 +9353,14 @@ nsFrame::HasCSSAnimations()
return collection && collection->mAnimations.Length() > 0;
}
bool
nsFrame::HasCSSTransitions()
{
auto collection =
AnimationCollection<CSSTransition>::GetAnimationCollection(this);
return collection && collection->mAnimations.Length() > 0;
}
// Box layout debugging
#ifdef DEBUG_REFLOW
int32_t gIndent2 = 0;
@@ -10303,7 +10282,7 @@ void* nsFrame::DisplayLayoutEnter(nsIFrame* aFrame)
DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nullptr);
if (treeNode && treeNode->mDisplay) {
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
printf("Layout\n");
printf("XULLayout\n");
}
return treeNode;
}
@@ -10415,7 +10394,7 @@ void nsFrame::DisplayLayoutExit(nsIFrame* aFrame,
if (treeNode->mDisplay) {
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
nsRect rect = aFrame->GetRect();
printf("Layout=%d,%d,%d,%d\n", rect.x, rect.y, rect.width, rect.height);
printf("XULLayout=%d,%d,%d,%d\n", rect.x, rect.y, rect.width, rect.height);
}
DR_state->DeleteTreeNode(*treeNode);
}
+9 -6
View File
@@ -408,11 +408,11 @@ public:
virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint);
// Box layout methods
virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nscoord GetFlex() override;
virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nscoord GetXULFlex() override;
virtual nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) override;
// We compute and store the HTML content's overflow area. So don't
// try to compute it in the box code.
@@ -651,7 +651,7 @@ protected:
// Fills aCursor with the appropriate information from ui
static void FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
nsIFrame::Cursor& aCursor);
NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState) override;
NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
#ifdef DEBUG_LAYOUT
virtual void GetBoxName(nsAutoString& aName) override;
@@ -678,6 +678,9 @@ private:
// Returns true if this frame has any kind of CSS animations.
bool HasCSSAnimations();
// Returns true if this frame has any kind of CSS transitions.
bool HasCSSTransitions();
#ifdef DEBUG_FRAME_DUMP
public:
/**
+45 -45
View File
@@ -268,7 +268,7 @@ GetScrollbarMetrics(nsBoxLayoutState& aState, nsIFrame* aBox, nsSize* aMin,
"computations");
if (aMin) {
*aMin = aBox->GetMinSize(aState);
*aMin = aBox->GetXULMinSize(aState);
nsBox::AddMargin(aBox, *aMin);
if (aMin->width < 0) {
aMin->width = 0;
@@ -279,7 +279,7 @@ GetScrollbarMetrics(nsBoxLayoutState& aState, nsIFrame* aBox, nsSize* aMin,
}
if (aPref) {
*aPref = aBox->GetPrefSize(aState);
*aPref = aBox->GetXULPrefSize(aState);
nsBox::AddMargin(aBox, *aPref);
if (aPref->width < 0) {
aPref->width = 0;
@@ -794,18 +794,18 @@ nsHTMLScrollFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
}
nsresult
nsHTMLScrollFrame::GetPadding(nsMargin& aMargin)
nsHTMLScrollFrame::GetXULPadding(nsMargin& aMargin)
{
// Our padding hangs out on the inside of the scrollframe, but XUL doesn't
// reaize that. If we're stuck inside a XUL box, we need to claim no
// padding.
// @see also nsXULScrollFrame::GetPadding.
// @see also nsXULScrollFrame::GetXULPadding.
aMargin.SizeTo(0,0,0,0);
return NS_OK;
}
bool
nsHTMLScrollFrame::IsCollapsed()
nsHTMLScrollFrame::IsXULCollapsed()
{
// We're never collapsed in the box sense.
return false;
@@ -1009,7 +1009,7 @@ nsXULScrollFrame::nsXULScrollFrame(nsStyleContext* aContext,
: nsBoxFrame(aContext, aIsRoot),
mHelper(ALLOW_THIS_IN_INITIALIZER_LIST(this), aIsRoot)
{
SetLayoutManager(nullptr);
SetXULLayoutManager(nullptr);
mHelper.mClipAllDescendants = aClipAllDescendants;
}
@@ -1039,7 +1039,7 @@ ScrollFrameHelper::GetDesiredScrollbarSizes(nsBoxLayoutState* aState)
nsMargin result(0, 0, 0, 0);
if (mVScrollbarBox) {
nsSize size = mVScrollbarBox->GetPrefSize(*aState);
nsSize size = mVScrollbarBox->GetXULPrefSize(*aState);
nsBox::AddMargin(mVScrollbarBox, size);
if (IsScrollbarOnRight())
result.left = size.width;
@@ -1048,7 +1048,7 @@ ScrollFrameHelper::GetDesiredScrollbarSizes(nsBoxLayoutState* aState)
}
if (mHScrollbarBox) {
nsSize size = mHScrollbarBox->GetPrefSize(*aState);
nsSize size = mHScrollbarBox->GetXULPrefSize(*aState);
nsBox::AddMargin(mHScrollbarBox, size);
// We don't currently support any scripts that would require a scrollbar
// at the top. (Are there any?)
@@ -1207,7 +1207,7 @@ void
ScrollFrameHelper::ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection,
nsIScrollbarMediator::ScrollSnapMode aSnap)
{
bool isHorizontal = aScrollbar->IsHorizontal();
bool isHorizontal = aScrollbar->IsXULHorizontal();
nsIntPoint delta;
if (isHorizontal) {
const double kScrollMultiplier =
@@ -1253,7 +1253,7 @@ ScrollFrameHelper::ThumbMoved(nsScrollbarFrame* aScrollbar,
nscoord aNewPos)
{
MOZ_ASSERT(aScrollbar != nullptr);
bool isHorizontal = aScrollbar->IsHorizontal();
bool isHorizontal = aScrollbar->IsXULHorizontal();
nsPoint current = GetScrollPosition();
nsPoint dest = current;
if (isHorizontal) {
@@ -1293,7 +1293,7 @@ ScrollFrameHelper::ScrollByUnit(nsScrollbarFrame* aScrollbar,
nsIScrollbarMediator::ScrollSnapMode aSnap)
{
MOZ_ASSERT(aScrollbar != nullptr);
bool isHorizontal = aScrollbar->IsHorizontal();
bool isHorizontal = aScrollbar->IsXULHorizontal();
nsIntPoint delta;
if (isHorizontal) {
delta.x = aDirection;
@@ -1368,7 +1368,7 @@ nsXULScrollFrame::GetSplittableType() const
}
nsresult
nsXULScrollFrame::GetPadding(nsMargin& aMargin)
nsXULScrollFrame::GetXULPadding(nsMargin& aMargin)
{
aMargin.SizeTo(0,0,0,0);
return NS_OK;
@@ -1381,29 +1381,29 @@ nsXULScrollFrame::GetType() const
}
nscoord
nsXULScrollFrame::GetBoxAscent(nsBoxLayoutState& aState)
nsXULScrollFrame::GetXULBoxAscent(nsBoxLayoutState& aState)
{
if (!mHelper.mScrolledFrame)
return 0;
nscoord ascent = mHelper.mScrolledFrame->GetBoxAscent(aState);
nscoord ascent = mHelper.mScrolledFrame->GetXULBoxAscent(aState);
nsMargin m(0,0,0,0);
GetBorderAndPadding(m);
GetXULBorderAndPadding(m);
ascent += m.top;
GetMargin(m);
GetXULMargin(m);
ascent += m.top;
return ascent;
}
nsSize
nsXULScrollFrame::GetPrefSize(nsBoxLayoutState& aState)
nsXULScrollFrame::GetXULPrefSize(nsBoxLayoutState& aState)
{
#ifdef DEBUG_LAYOUT
PropagateDebug(aState);
#endif
nsSize pref = mHelper.mScrolledFrame->GetPrefSize(aState);
nsSize pref = mHelper.mScrolledFrame->GetXULPrefSize(aState);
ScrollbarStyles styles = GetScrollbarStyles();
@@ -1411,38 +1411,38 @@ nsXULScrollFrame::GetPrefSize(nsBoxLayoutState& aState)
if (mHelper.mVScrollbarBox &&
styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) {
nsSize vSize = mHelper.mVScrollbarBox->GetPrefSize(aState);
nsSize vSize = mHelper.mVScrollbarBox->GetXULPrefSize(aState);
nsBox::AddMargin(mHelper.mVScrollbarBox, vSize);
pref.width += vSize.width;
}
if (mHelper.mHScrollbarBox &&
styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL) {
nsSize hSize = mHelper.mHScrollbarBox->GetPrefSize(aState);
nsSize hSize = mHelper.mHScrollbarBox->GetXULPrefSize(aState);
nsBox::AddMargin(mHelper.mHScrollbarBox, hSize);
pref.height += hSize.height;
}
AddBorderAndPadding(pref);
bool widthSet, heightSet;
nsIFrame::AddCSSPrefSize(this, pref, widthSet, heightSet);
nsIFrame::AddXULPrefSize(this, pref, widthSet, heightSet);
return pref;
}
nsSize
nsXULScrollFrame::GetMinSize(nsBoxLayoutState& aState)
nsXULScrollFrame::GetXULMinSize(nsBoxLayoutState& aState)
{
#ifdef DEBUG_LAYOUT
PropagateDebug(aState);
#endif
nsSize min = mHelper.mScrolledFrame->GetMinSizeForScrollArea(aState);
nsSize min = mHelper.mScrolledFrame->GetXULMinSizeForScrollArea(aState);
ScrollbarStyles styles = GetScrollbarStyles();
if (mHelper.mVScrollbarBox &&
styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) {
nsSize vSize = mHelper.mVScrollbarBox->GetMinSize(aState);
nsSize vSize = mHelper.mVScrollbarBox->GetXULMinSize(aState);
AddMargin(mHelper.mVScrollbarBox, vSize);
min.width += vSize.width;
if (min.height < vSize.height)
@@ -1451,7 +1451,7 @@ nsXULScrollFrame::GetMinSize(nsBoxLayoutState& aState)
if (mHelper.mHScrollbarBox &&
styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL) {
nsSize hSize = mHelper.mHScrollbarBox->GetMinSize(aState);
nsSize hSize = mHelper.mHScrollbarBox->GetXULMinSize(aState);
AddMargin(mHelper.mHScrollbarBox, hSize);
min.height += hSize.height;
if (min.width < hSize.width)
@@ -1460,12 +1460,12 @@ nsXULScrollFrame::GetMinSize(nsBoxLayoutState& aState)
AddBorderAndPadding(min);
bool widthSet, heightSet;
nsIFrame::AddCSSMinSize(aState, this, min, widthSet, heightSet);
nsIFrame::AddXULMinSize(aState, this, min, widthSet, heightSet);
return min;
}
nsSize
nsXULScrollFrame::GetMaxSize(nsBoxLayoutState& aState)
nsXULScrollFrame::GetXULMaxSize(nsBoxLayoutState& aState)
{
#ifdef DEBUG_LAYOUT
PropagateDebug(aState);
@@ -1475,7 +1475,7 @@ nsXULScrollFrame::GetMaxSize(nsBoxLayoutState& aState)
AddBorderAndPadding(maxSize);
bool widthSet, heightSet;
nsIFrame::AddCSSMaxSize(this, maxSize, widthSet, heightSet);
nsIFrame::AddXULMaxSize(this, maxSize, widthSet, heightSet);
return maxSize;
}
@@ -1488,13 +1488,13 @@ nsXULScrollFrame::GetFrameName(nsAString& aResult) const
#endif
NS_IMETHODIMP
nsXULScrollFrame::DoLayout(nsBoxLayoutState& aState)
nsXULScrollFrame::DoXULLayout(nsBoxLayoutState& aState)
{
uint32_t flags = aState.LayoutFlags();
nsresult rv = Layout(aState);
nsresult rv = XULLayout(aState);
aState.SetLayoutFlags(flags);
nsBox::DoLayout(aState);
nsBox::DoXULLayout(aState);
return rv;
}
@@ -4590,7 +4590,7 @@ nsXULScrollFrame::AddRemoveScrollbar(nsBoxLayoutState& aState,
if (mHelper.mNeverHasHorizontalScrollbar || !mHelper.mHScrollbarBox)
return false;
nsSize hSize = mHelper.mHScrollbarBox->GetPrefSize(aState);
nsSize hSize = mHelper.mHScrollbarBox->GetXULPrefSize(aState);
nsBox::AddMargin(mHelper.mHScrollbarBox, hSize);
mHelper.SetScrollbarVisibility(mHelper.mHScrollbarBox, aAdd);
@@ -4609,7 +4609,7 @@ nsXULScrollFrame::AddRemoveScrollbar(nsBoxLayoutState& aState,
if (mHelper.mNeverHasVerticalScrollbar || !mHelper.mVScrollbarBox)
return false;
nsSize vSize = mHelper.mVScrollbarBox->GetPrefSize(aState);
nsSize vSize = mHelper.mVScrollbarBox->GetXULPrefSize(aState);
nsBox::AddMargin(mHelper.mVScrollbarBox, vSize);
mHelper.SetScrollbarVisibility(mHelper.mVScrollbarBox, aAdd);
@@ -4668,7 +4668,7 @@ nsXULScrollFrame::LayoutScrollArea(nsBoxLayoutState& aState,
mHelper.mScrollPort.Size());
int32_t flags = NS_FRAME_NO_MOVE_VIEW;
nsSize minSize = mHelper.mScrolledFrame->GetMinSize(aState);
nsSize minSize = mHelper.mScrolledFrame->GetXULMinSize(aState);
if (minSize.height > childRect.height)
childRect.height = minSize.height;
@@ -4678,7 +4678,7 @@ nsXULScrollFrame::LayoutScrollArea(nsBoxLayoutState& aState,
aState.SetLayoutFlags(flags);
ClampAndSetBounds(aState, childRect, aScrollPosition);
mHelper.mScrolledFrame->Layout(aState);
mHelper.mScrolledFrame->XULLayout(aState);
childRect = mHelper.mScrolledFrame->GetRect();
@@ -4813,14 +4813,14 @@ ScrollFrameHelper::IsScrollingActive(nsDisplayListBuilder* aBuilder) const
* cause any of the scrollbars to need to be reflowed.
*/
nsresult
nsXULScrollFrame::Layout(nsBoxLayoutState& aState)
nsXULScrollFrame::XULLayout(nsBoxLayoutState& aState)
{
bool scrollbarRight = IsScrollbarOnRight();
bool scrollbarBottom = true;
// get the content rect
nsRect clientRect(0,0,0,0);
GetClientRect(clientRect);
GetXULClientRect(clientRect);
nsRect oldScrollAreaBounds = mHelper.mScrollPort;
nsPoint oldScrollPosition = mHelper.GetLogicalScrollPosition();
@@ -5304,7 +5304,7 @@ ScrollFrameHelper::LayoutScrollbars(nsBoxLayoutState& aState,
// place the scrollcorner
if (mScrollCornerBox || mResizerBox) {
NS_PRECONDITION(!mScrollCornerBox || mScrollCornerBox->IsBoxFrame(), "Must be a box frame!");
NS_PRECONDITION(!mScrollCornerBox || mScrollCornerBox->IsXULBoxFrame(), "Must be a box frame!");
nsRect r(0, 0, 0, 0);
if (aContentArea.x != mScrollPort.x || scrollbarOnLeft) {
@@ -5334,17 +5334,17 @@ ScrollFrameHelper::LayoutScrollbars(nsBoxLayoutState& aState,
if (hasResizer) {
// if a resizer is present, get its size. Assume a default size of 15 pixels.
nscoord defaultSize = nsPresContext::CSSPixelsToAppUnits(15);
nsSize resizerMinSize = mResizerBox->GetMinSize(aState);
nsSize resizerMinSize = mResizerBox->GetXULMinSize(aState);
nscoord vScrollbarWidth = mVScrollbarBox ?
mVScrollbarBox->GetPrefSize(aState).width : defaultSize;
mVScrollbarBox->GetXULPrefSize(aState).width : defaultSize;
r.width = std::max(std::max(r.width, vScrollbarWidth), resizerMinSize.width);
if (aContentArea.x == mScrollPort.x && !scrollbarOnLeft) {
r.x = aContentArea.XMost() - r.width;
}
nscoord hScrollbarHeight = mHScrollbarBox ?
mHScrollbarBox->GetPrefSize(aState).height : defaultSize;
mHScrollbarBox->GetXULPrefSize(aState).height : defaultSize;
r.height = std::max(std::max(r.height, hScrollbarHeight), resizerMinSize.height);
if (aContentArea.y == mScrollPort.y) {
r.y = aContentArea.YMost() - r.height;
@@ -5361,7 +5361,7 @@ ScrollFrameHelper::LayoutScrollbars(nsBoxLayoutState& aState,
nsPresContext* presContext = mScrolledFrame->PresContext();
nsRect vRect;
if (mVScrollbarBox) {
NS_PRECONDITION(mVScrollbarBox->IsBoxFrame(), "Must be a box frame!");
NS_PRECONDITION(mVScrollbarBox->IsXULBoxFrame(), "Must be a box frame!");
vRect = mScrollPort;
if (overlayScrollBarsWithZoom) {
vRect.height = NSToCoordRound(res * scrollPortClampingSize.height);
@@ -5370,7 +5370,7 @@ ScrollFrameHelper::LayoutScrollbars(nsBoxLayoutState& aState,
vRect.x = scrollbarOnLeft ? aContentArea.x : mScrollPort.x + NSToCoordRound(res * scrollPortClampingSize.width);
if (mHasVerticalScrollbar) {
nsMargin margin;
mVScrollbarBox->GetMargin(margin);
mVScrollbarBox->GetXULMargin(margin);
vRect.Deflate(margin);
}
AdjustScrollbarRectForResizer(mOuter, presContext, vRect, hasResizer, true);
@@ -5378,7 +5378,7 @@ ScrollFrameHelper::LayoutScrollbars(nsBoxLayoutState& aState,
nsRect hRect;
if (mHScrollbarBox) {
NS_PRECONDITION(mHScrollbarBox->IsBoxFrame(), "Must be a box frame!");
NS_PRECONDITION(mHScrollbarBox->IsXULBoxFrame(), "Must be a box frame!");
hRect = mScrollPort;
if (overlayScrollBarsWithZoom) {
hRect.width = NSToCoordRound(res * scrollPortClampingSize.width);
@@ -5387,7 +5387,7 @@ ScrollFrameHelper::LayoutScrollbars(nsBoxLayoutState& aState,
hRect.y = mScrollPort.y + NSToCoordRound(res * scrollPortClampingSize.height);
if (mHasHorizontalScrollbar) {
nsMargin margin;
mHScrollbarBox->GetMargin(margin);
mHScrollbarBox->GetXULMargin(margin);
hRect.Deflate(margin);
}
AdjustScrollbarRectForResizer(mOuter, presContext, hRect, hasResizer, false);
+10 -10
View File
@@ -700,8 +700,8 @@ public:
virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
virtual nsresult GetPadding(nsMargin& aPadding) override;
virtual bool IsCollapsed() override;
virtual nsresult GetXULPadding(nsMargin& aPadding) override;
virtual bool IsXULCollapsed() override;
virtual void Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@@ -1128,20 +1128,20 @@ public:
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) override;
NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsresult GetPadding(nsMargin& aPadding) override;
NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsresult GetXULPadding(nsMargin& aPadding) override;
virtual bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
Sides aSkipSides, nscoord aRadii[8]) const override {
return mHelper.GetBorderRadii(aFrameSize, aBorderArea, aSkipSides, aRadii);
}
nsresult Layout(nsBoxLayoutState& aState);
nsresult XULLayout(nsBoxLayoutState& aState);
void LayoutScrollArea(nsBoxLayoutState& aState, const nsPoint& aScrollPosition);
static bool AddRemoveScrollbar(bool& aHasScrollbar,
@@ -1452,7 +1452,7 @@ protected:
if (!mHelper.IsLTR()) {
aRect.x = mHelper.mScrollPort.XMost() - aScrollPosition.x - aRect.width;
}
mHelper.mScrolledFrame->SetBounds(aState, aRect, aRemoveOverflowAreas);
mHelper.mScrolledFrame->SetXULBounds(aState, aRect, aRemoveOverflowAreas);
}
private:
+19 -44
View File
@@ -16,6 +16,7 @@
#include "nsAlgorithm.h" // for clamped()
#include "nsAutoPtr.h"
#include "nsCSSAnonBoxes.h"
#include "nsCSSFrameConstructor.h"
#include "nsDataHashtable.h"
#include "nsDisplayList.h"
#include "nsHashKeys.h"
@@ -151,8 +152,21 @@ nsGridContainerFrame::TrackSize::Initialize(nscoord aPercentageBasis,
{
MOZ_ASSERT(mBase == 0 && mLimit == 0 && mState == 0,
"track size data is expected to be initialized to zero");
auto minSizeUnit = aMinCoord.GetUnit();
auto maxSizeUnit = aMaxCoord.GetUnit();
if (aPercentageBasis == NS_UNCONSTRAINEDSIZE) {
// https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-percentage
// "If the inline or block size of the grid container is indefinite,
// <percentage> values relative to that size are treated as 'auto'."
if (aMinCoord.HasPercent()) {
minSizeUnit = eStyleUnit_Auto;
}
if (aMaxCoord.HasPercent()) {
maxSizeUnit = eStyleUnit_Auto;
}
}
// http://dev.w3.org/csswg/css-grid/#algo-init
switch (aMinCoord.GetUnit()) {
switch (minSizeUnit) {
case eStyleUnit_Auto:
mState = eAutoMinSizing;
break;
@@ -166,7 +180,7 @@ nsGridContainerFrame::TrackSize::Initialize(nscoord aPercentageBasis,
default:
mBase = nsRuleNode::ComputeCoordPercentCalc(aMinCoord, aPercentageBasis);
}
switch (aMaxCoord.GetUnit()) {
switch (maxSizeUnit) {
case eStyleUnit_Auto:
mState |= eAutoMaxSizing;
mLimit = NS_UNCONSTRAINEDSIZE;
@@ -2038,12 +2052,10 @@ nsGridContainerFrame::GridReflowState::CalculateTrackSizes(
mRows.Initialize(mRowFunctions, mGridStyle->mGridRowGap,
aGrid.mGridRowEnd, aContentBox.BSize(mWM));
mIter.Reset(); // XXX cleanup this Reset mess!
mCols.CalculateSizes(*this, mGridItems, mColFunctions,
aContentBox.ISize(mWM), &GridArea::mCols,
aConstraint);
mIter.Reset(); // XXX cleanup this Reset mess!
mRows.CalculateSizes(*this, mGridItems, mRowFunctions,
aContentBox.BSize(mWM), &GridArea::mRows,
aConstraint);
@@ -2937,6 +2949,7 @@ nsGridContainerFrame::Grid::PlaceGridItems(GridReflowState& aState,
int32_t minCol = 1;
int32_t minRow = 1;
aState.mGridItems.ClearAndRetainStorage();
aState.mIter.Reset();
for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
nsIFrame* child = *aState.mIter;
GridItemInfo* info =
@@ -3208,12 +3221,8 @@ nsGridContainerFrame::Tracks::Initialize(
aFunctions.NumExplicitTracks());
mSizes.SetLength(aNumTracks);
PodZero(mSizes.Elements(), mSizes.Length());
nscoord percentageBasis = aContentBoxSize;
if (percentageBasis == NS_UNCONSTRAINEDSIZE) {
percentageBasis = 0;
}
for (uint32_t i = 0, len = mSizes.Length(); i < len; ++i) {
mSizes[i].Initialize(percentageBasis,
mSizes[i].Initialize(aContentBoxSize,
aFunctions.MinSizingFor(i),
aFunctions.MaxSizingFor(i));
}
@@ -3485,6 +3494,7 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSize(
const TrackSize::StateBits flexMin =
aConstraint == nsLayoutUtils::MIN_ISIZE ? TrackSize::eFlexMinSizing
: TrackSize::StateBits(0);
iter.Reset();
for (; !iter.AtEnd(); iter.Next()) {
nsIFrame* child = *iter;
const GridArea& area = aGridItems[iter.GridItemIndex()].mArea;
@@ -5005,7 +5015,6 @@ nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
grid.PlaceGridItems(gridReflowState, computedMinSize, computedSize,
aReflowState.ComputedMaxSize());
gridReflowState.mIter.Reset();
gridReflowState.CalculateTrackSizes(grid, computedSize,
nsLayoutUtils::PREF_ISIZE);
@@ -5149,7 +5158,6 @@ nsGridContainerFrame::IntrinsicISize(nsRenderingContext* aRenderingContext,
}
state.mCols.Initialize(state.mColFunctions, state.mGridStyle->mGridColumnGap,
grid.mGridColEnd, NS_UNCONSTRAINEDSIZE);
state.mIter.Reset();
state.mCols.CalculateSizes(state, state.mGridItems, state.mColFunctions,
NS_UNCONSTRAINEDSIZE, &GridArea::mCols,
aConstraint);
@@ -5342,20 +5350,6 @@ nsGridContainerFrame::MergeSortedExcessOverflowContainers(nsFrameList& aList)
}
#ifdef DEBUG
static bool
FrameWantsToBeInAnonymousGridItem(nsIFrame* aFrame)
{
// Note: This needs to match the logic in
// nsCSSFrameConstructor::FrameConstructionItem::NeedsAnonFlexOrGridItem()
return aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
}
// Debug-only override, to let us assert that our anonymous grid items are
// set up correctly by the frame constructor -- in particular, we assert:
// (1) we don't have any inline non-replaced children
// (2) we don't have any consecutive anonymous grid items
// (3) we don't have any empty anonymous grid items
// (4) all children are on the expected child lists
void
nsGridContainerFrame::SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList)
@@ -5363,25 +5357,6 @@ nsGridContainerFrame::SetInitialChildList(ChildListID aListID,
ChildListIDs supportedLists = kAbsoluteList | kFixedList | kPrincipalList;
MOZ_ASSERT(supportedLists.Contains(aListID), "unexpected child list");
if (aListID == kPrincipalList) {
bool prevChildWasAnonGridItem = false;
for (nsFrameList::Enumerator e(aChildList); !e.AtEnd(); e.Next()) {
nsIFrame* child = e.get();
MOZ_ASSERT(!FrameWantsToBeInAnonymousGridItem(child),
"frame wants to be inside an anonymous grid item, but it isn't");
if (child->StyleContext()->GetPseudo() ==
nsCSSAnonBoxes::anonymousGridItem) {
MOZ_ASSERT(!prevChildWasAnonGridItem, "two anon grid items in a row");
nsIFrame* firstWrappedChild = child->PrincipalChildList().FirstChild();
MOZ_ASSERT(firstWrappedChild,
"anonymous grid item is empty (shouldn't happen)");
prevChildWasAnonGridItem = true;
} else {
prevChildWasAnonGridItem = false;
}
}
}
return nsContainerFrame::SetInitialChildList(aListID, aChildList);
}
+3 -1
View File
@@ -9,6 +9,7 @@
#ifndef nsGridContainerFrame_h___
#define nsGridContainerFrame_h___
#include "mozilla/Maybe.h"
#include "mozilla/TypeTraits.h"
#include "nsContainerFrame.h"
#include "nsHashKeys.h"
@@ -46,6 +47,7 @@ public:
NS_DECL_FRAMEARENA_HELPERS
NS_DECL_QUERYFRAME_TARGET(nsGridContainerFrame)
NS_DECL_QUERYFRAME
typedef mozilla::ComputedGridTrackInfo ComputedGridTrackInfo;
// nsIFrame overrides
void Reflow(nsPresContext* aPresContext,
@@ -202,7 +204,7 @@ private:
bool mIsAutoBSize;
};
Maybe<nsGridContainerFrame::Fragmentainer>
mozilla::Maybe<nsGridContainerFrame::Fragmentainer>
GetNearestFragmentainer(const GridReflowState& aState) const;
// @return the consumed size of all continuations so far including this frame
+1 -1
View File
@@ -665,7 +665,7 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameT
mStylePosition->MaxBSizeDependsOnContainer(wm) ||
mStylePosition->OffsetHasPercent(wm.PhysicalSide(eLogicalSideBStart)) ||
mStylePosition->mOffset.GetBEndUnit(wm) != eStyleUnit_Auto ||
frame->IsBoxFrame();
frame->IsXULBoxFrame();
if (mStyleText->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
NS_ASSERTION(mStyleText->mLineHeight.GetIntValue() ==
+41 -49
View File
@@ -2107,7 +2107,6 @@ public:
*/
bool HasView() const { return !!(mState & NS_FRAME_HAS_VIEW); }
nsView* GetView() const;
virtual nsView* GetViewExternal() const;
nsresult SetView(nsView* aView);
/**
@@ -2121,7 +2120,6 @@ public:
* Find the closest ancestor (excluding |this| !) that has a view
*/
nsIFrame* GetAncestorWithView() const;
virtual nsIFrame* GetAncestorWithViewExternal() const;
/**
* Get the offset between the coordinate systems of |this| and aOther.
@@ -2140,7 +2138,6 @@ public:
* aOther.
*/
nsPoint GetOffsetTo(const nsIFrame* aOther) const;
virtual nsPoint GetOffsetToExternal(const nsIFrame* aOther) const;
/**
* Get the offset between the coordinate systems of |this| and aOther
@@ -2175,14 +2172,12 @@ public:
* @return the pixel rect of the frame in screen coordinates.
*/
nsIntRect GetScreenRect() const;
virtual nsIntRect GetScreenRectExternal() const;
/**
* Get the screen rect of the frame in app units.
* @return the app unit rect of the frame in screen coordinates.
*/
nsRect GetScreenRectInAppUnits() const;
virtual nsRect GetScreenRectInAppUnitsExternal() const;
/**
* Returns the offset from this frame to the closest geometric parent that
@@ -2195,16 +2190,15 @@ public:
* view and the view has a widget, then this frame's widget is
* returned, otherwise this frame's geometric parent is checked
* recursively upwards.
* XXX virtual because gfx callers use it! (themes)
*/
virtual nsIWidget* GetNearestWidget() const;
nsIWidget* GetNearestWidget() const;
/**
* Same as GetNearestWidget() above but uses an outparam to return the offset
* of this frame to the returned widget expressed in appunits of |this| (the
* widget might be in a different document with a different zoom).
*/
virtual nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
/**
* Get the "type" of the frame. May return nullptr.
@@ -2868,7 +2862,7 @@ public:
// BOX LAYOUT METHODS
// These methods have been migrated from nsIBox and are in the process of
// being refactored. DO NOT USE OUTSIDE OF XUL.
bool IsBoxFrame() const
bool IsXULBoxFrame() const
{
return IsFrameOfType(nsIFrame::eXULBox);
}
@@ -2891,87 +2885,85 @@ public:
* @param[in] aBoxLayoutState The desired state to calculate for
* @return The minimum size
*/
virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) = 0;
virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) = 0;
/**
* This calculates the preferred size of a box based on its state
* @param[in] aBoxLayoutState The desired state to calculate for
* @return The preferred size
*/
virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) = 0;
virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) = 0;
/**
* This calculates the maximum size for a box based on its state
* @param[in] aBoxLayoutState The desired state to calculate for
* @return The maximum size
*/
virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) = 0;
virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) = 0;
/**
* This returns the minimum size for the scroll area if this frame is
* being scrolled. Usually it's (0,0).
*/
virtual nsSize GetMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) = 0;
virtual nsSize GetXULMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) = 0;
// Implemented in nsBox, used in nsBoxFrame
uint32_t GetOrdinal();
uint32_t GetXULOrdinal();
virtual nscoord GetFlex() = 0;
virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) = 0;
virtual bool IsCollapsed() = 0;
virtual nscoord GetXULFlex() = 0;
virtual nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) = 0;
virtual bool IsXULCollapsed() = 0;
// This does not alter the overflow area. If the caller is changing
// the box size, the caller is responsible for updating the overflow
// area. It's enough to just call Layout or SyncLayout on the
// area. It's enough to just call XULLayout or SyncLayout on the
// box. You can pass true to aRemoveOverflowArea as a
// convenience.
virtual void SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
bool aRemoveOverflowAreas = false) = 0;
nsresult Layout(nsBoxLayoutState& aBoxLayoutState);
virtual void SetXULBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
bool aRemoveOverflowAreas = false) = 0;
nsresult XULLayout(nsBoxLayoutState& aBoxLayoutState);
// Box methods. Note that these do NOT just get the CSS border, padding,
// etc. They also talk to nsITheme.
virtual nsresult GetBorderAndPadding(nsMargin& aBorderAndPadding);
virtual nsresult GetBorder(nsMargin& aBorder)=0;
virtual nsresult GetPadding(nsMargin& aBorderAndPadding)=0;
virtual nsresult GetMargin(nsMargin& aMargin)=0;
virtual void SetLayoutManager(nsBoxLayout* aLayout) { }
virtual nsBoxLayout* GetLayoutManager() { return nullptr; }
nsresult GetClientRect(nsRect& aContentRect);
virtual nsresult GetXULBorderAndPadding(nsMargin& aBorderAndPadding);
virtual nsresult GetXULBorder(nsMargin& aBorder)=0;
virtual nsresult GetXULPadding(nsMargin& aBorderAndPadding)=0;
virtual nsresult GetXULMargin(nsMargin& aMargin)=0;
virtual void SetXULLayoutManager(nsBoxLayout* aLayout) { }
virtual nsBoxLayout* GetXULLayoutManager() { return nullptr; }
nsresult GetXULClientRect(nsRect& aContentRect);
// For nsSprocketLayout
virtual Valignment GetVAlign() const = 0;
virtual Halignment GetHAlign() const = 0;
virtual Valignment GetXULVAlign() const = 0;
virtual Halignment GetXULHAlign() const = 0;
bool IsHorizontal() const { return (mState & NS_STATE_IS_HORIZONTAL) != 0; }
bool IsNormalDirection() const { return (mState & NS_STATE_IS_DIRECTION_NORMAL) != 0; }
bool IsXULHorizontal() const { return (mState & NS_STATE_IS_HORIZONTAL) != 0; }
bool IsXULNormalDirection() const { return (mState & NS_STATE_IS_DIRECTION_NORMAL) != 0; }
nsresult Redraw(nsBoxLayoutState& aState);
virtual nsresult RelayoutChildAtOrdinal(nsIFrame* aChild)=0;
// XXX take this out after we've branched
virtual bool GetMouseThrough() const { return false; }
nsresult XULRedraw(nsBoxLayoutState& aState);
virtual nsresult XULRelayoutChildAtOrdinal(nsIFrame* aChild)=0;
#ifdef DEBUG_LAYOUT
virtual nsresult SetDebug(nsBoxLayoutState& aState, bool aDebug)=0;
virtual nsresult GetDebug(bool& aDebug)=0;
virtual nsresult SetXULDebug(nsBoxLayoutState& aState, bool aDebug)=0;
virtual nsresult GetXULDebug(bool& aDebug)=0;
virtual nsresult DumpBox(FILE* out)=0;
virtual nsresult XULDumpBox(FILE* out)=0;
#endif
static bool AddXULPrefSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
static bool AddXULMinSize(nsBoxLayoutState& aState, nsIFrame* aBox,
nsSize& aSize, bool& aWidth, bool& aHeightSet);
static bool AddXULMaxSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
static bool AddXULFlex(nsIFrame* aBox, nscoord& aFlex);
// END OF BOX LAYOUT METHODS
// The above methods have been migrated from nsIBox and are in the process of
// being refactored. DO NOT USE OUTSIDE OF XUL.
/**
* @return true if this text frame ends with a newline character. It
* should return false if this is not a text frame.
*/
virtual bool HasSignificantTerminalNewline() const;
static bool AddCSSPrefSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
static bool AddCSSMinSize(nsBoxLayoutState& aState, nsIFrame* aBox,
nsSize& aSize, bool& aWidth, bool& aHeightSet);
static bool AddCSSMaxSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
static bool AddCSSFlex(nsIFrame* aBox, nscoord& aFlex);
// END OF BOX LAYOUT METHODS
// The above methods have been migrated from nsIBox and are in the process of
// being refactored. DO NOT USE OUTSIDE OF XUL.
struct CaretPosition {
CaretPosition();
~CaretPosition();
+6 -99
View File
@@ -1524,64 +1524,18 @@ nsDisplayImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
nsDisplayImageContainer::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
bool
nsDisplayImage::CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
already_AddRefed<imgIContainer>
nsDisplayImage::GetImage()
{
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
if (!mImage->IsImageContainerAvailable(aManager, flags)) {
return false;
}
int32_t imageWidth;
int32_t imageHeight;
mImage->GetWidth(&imageWidth);
mImage->GetHeight(&imageHeight);
if (imageWidth == 0 || imageHeight == 0) {
NS_ASSERTION(false, "invalid image size");
return false;
}
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
const LayoutDeviceRect destRect =
LayoutDeviceRect::FromAppUnits(GetDestRect(), factor);
// Calculate the scaling factor for the frame.
const gfxSize scale = gfxSize(destRect.width / imageWidth,
destRect.height / imageHeight);
if (scale.width < 0.2 || scale.height < 0.2) {
// This would look awful as long as we can't use high-quality downscaling
// for image layers (bug 803703), so don't turn this into an image layer.
return false;
}
return true;
}
already_AddRefed<ImageContainer>
nsDisplayImage::GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
return mImage->GetImageContainer(aManager, flags);
nsCOMPtr<imgIContainer> image = mImage;
return image.forget();
}
nsRect
nsDisplayImage::GetDestRect(bool* aSnap)
nsDisplayImage::GetDestRect()
{
bool snap = true;
const nsRect frameContentBox = GetBounds(&snap);
if (aSnap) {
*aSnap = snap;
}
nsImageFrame* imageFrame = static_cast<nsImageFrame*>(mFrame);
return imageFrame->PredictedDestRect(frameContentBox);
@@ -1682,54 +1636,6 @@ nsDisplayImage::BuildLayer(nsDisplayListBuilder* aBuilder,
return layer.forget();
}
void
nsDisplayImage::ConfigureLayer(ImageLayer* aLayer,
const ContainerLayerParameters& aParameters)
{
aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
int32_t imageWidth;
int32_t imageHeight;
mImage->GetWidth(&imageWidth);
mImage->GetHeight(&imageHeight);
NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
if (imageWidth > 0 && imageHeight > 0) {
// We're actually using the ImageContainer. Let our frame know that it
// should consider itself to have painted successfully.
nsDisplayItemGenericImageGeometry::UpdateDrawResult(this,
DrawResult::SUCCESS);
}
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
const LayoutDeviceRect destRect =
LayoutDeviceRect::FromAppUnits(GetDestRect(), factor);
// XXX(seth): Right now we ignore aParameters.Scale() and
// aParameters.Offset(), because FrameLayerBuilder already applies
// aParameters.Scale() via the layer's post-transform, and
// aParameters.Offset() is always zero.
MOZ_ASSERT(aParameters.Offset() == LayerIntPoint(0,0));
// It's possible (for example, due to downscale-during-decode) that the
// ImageContainer this ImageLayer is holding has a different size from the
// intrinsic size of the image. For this reason we compute the transform using
// the ImageContainer's size rather than the image's intrinsic size.
// XXX(seth): In reality, since the size of the ImageContainer may change
// asynchronously, this is not enough. Bug 1183378 will provide a more
// complete fix, but this solution is safe in more cases than simply relying
// on the intrinsic size.
IntSize containerSize = aLayer->GetContainer()
? aLayer->GetContainer()->GetCurrentSize()
: IntSize(imageWidth, imageHeight);
const LayoutDevicePoint p = destRect.TopLeft();
Matrix transform = Matrix::Translation(p.x, p.y);
transform.PreScale(destRect.Width() / containerSize.width,
destRect.Height() / containerSize.height);
aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
}
DrawResult
nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
const nsRect& aDirtyRect, imgIContainer* aImage,
@@ -2265,6 +2171,7 @@ nsImageFrame::LoadIcon(const nsAString& aSpec,
nullptr, /* principal (not relevant for icons) */
loadGroup,
gIconLoad,
nullptr, /* No context */
nullptr, /* Not associated with any particular document */
loadFlags,
nullptr,
+2 -17
View File
@@ -428,21 +428,13 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) override;
virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) override;
/**
* Returns an ImageContainer for this image if the image type
* supports it (TYPE_RASTER only).
*/
virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) override;
virtual already_AddRefed<imgIContainer> GetImage() override;
/**
* @return The dest rect we'll use when drawing this image, in app units.
* Not necessarily contained in this item's bounds.
*/
nsRect GetDestRect(bool* aSnap = nullptr);
virtual nsRect GetDestRect() override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
@@ -468,13 +460,6 @@ public:
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
/**
* Configure an ImageLayer for this display item.
* Set the required filter and scaling transform.
*/
virtual void ConfigureLayer(ImageLayer* aLayer,
const ContainerLayerParameters& aParameters) override;
NS_DISPLAY_DECL_NAME("Image", TYPE_IMAGE)
private:
nsCOMPtr<imgIContainer> mImage;
+3 -3
View File
@@ -38,7 +38,7 @@ NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
#endif
/* virtual */ nsSize
nsPlaceholderFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
nsPlaceholderFrame::GetXULMinSize(nsBoxLayoutState& aBoxLayoutState)
{
nsSize size(0, 0);
DISPLAY_MIN_SIZE(this, size);
@@ -46,7 +46,7 @@ nsPlaceholderFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
}
/* virtual */ nsSize
nsPlaceholderFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState)
nsPlaceholderFrame::GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState)
{
nsSize size(0, 0);
DISPLAY_PREF_SIZE(this, size);
@@ -54,7 +54,7 @@ nsPlaceholderFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState)
}
/* virtual */ nsSize
nsPlaceholderFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState)
nsPlaceholderFrame::GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState)
{
nsSize size(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
DISPLAY_MAX_SIZE(this, size);
+4 -4
View File
@@ -88,15 +88,15 @@ public:
}
// nsIFrame overrides
// We need to override GetMinSize and GetPrefSize because XUL uses
// We need to override GetXULMinSize and GetXULPrefSize because XUL uses
// placeholders not within lines.
virtual void AddInlineMinISize(nsRenderingContext* aRenderingContext,
InlineMinISizeData* aData) override;
virtual void AddInlinePrefISize(nsRenderingContext* aRenderingContext,
InlinePrefISizeData* aData) override;
virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual void Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
+1 -1
View File
@@ -610,7 +610,7 @@ nsVideoFrame::GetVideoIntrinsicSize(nsRenderingContext *aRenderingContext)
// Ask the controls frame what its preferred height is
nsBoxLayoutState boxState(PresContext(), aRenderingContext, 0);
nscoord prefHeight = mFrames.LastChild()->GetPrefSize(boxState).height;
nscoord prefHeight = mFrames.LastChild()->GetXULPrefSize(boxState).height;
return nsSize(nsPresContext::CSSPixelsToAppUnits(size.width), prefHeight);
}
+2 -1
View File
@@ -263,7 +263,8 @@ ImageLoader::LoadImage(nsIURI* aURI, nsIPrincipal* aOriginPrincipal,
}
RefPtr<imgRequestProxy> request;
nsContentUtils::LoadImage(aURI, mDocument, aOriginPrincipal, aReferrer,
nsContentUtils::LoadImage(aURI, mDocument, mDocument,
aOriginPrincipal, aReferrer,
mDocument->GetReferrerPolicy(),
nullptr, nsIRequest::LOAD_NORMAL,
NS_LITERAL_STRING("css"),
+16
View File
@@ -800,3 +800,19 @@ nsTransitionManager::PruneCompletedTransitions(mozilla::dom::Element* aElement,
collection = nullptr;
}
}
void
nsTransitionManager::StopTransitionsForElement(
mozilla::dom::Element* aElement,
mozilla::CSSPseudoElementType aPseudoType)
{
MOZ_ASSERT(aElement);
CSSTransitionCollection* collection =
CSSTransitionCollection::GetAnimationCollection(aElement, aPseudoType);
if (!collection) {
return;
}
nsAutoAnimationMutationBatch mb(aElement->OwnerDoc());
collection->Destroy();
}
+6
View File
@@ -339,6 +339,12 @@ public:
void SortEvents() { mEventDispatcher.SortEvents(); }
void ClearEventQueue() { mEventDispatcher.ClearEventQueue(); }
// Stop transitions on the element. This method takes the real element
// rather than the element for the generated content for transitions on
// ::before and ::after.
void StopTransitionsForElement(mozilla::dom::Element* aElement,
mozilla::CSSPseudoElementType aPseudoType);
protected:
virtual ~nsTransitionManager() {}
+8 -8
View File
@@ -92,7 +92,7 @@ static nsIFrame* GetScrolledBox(BoxObject* aScrollBox) {
nsIFrame* scrolledFrame = scrollFrame->GetScrolledFrame();
if (!scrolledFrame)
return nullptr;
return nsBox::GetChildBox(scrolledFrame);
return nsBox::GetChildXULBox(scrolledFrame);
}
void ScrollBoxObject::ScrollByIndex(int32_t dindexes, ErrorResult& aRv)
@@ -112,13 +112,13 @@ void ScrollBoxObject::ScrollByIndex(int32_t dindexes, ErrorResult& aRv)
nsRect rect;
// now get the scrolled boxes first child.
nsIFrame* child = nsBox::GetChildBox(scrolledBox);
nsIFrame* child = nsBox::GetChildXULBox(scrolledBox);
bool horiz = scrolledBox->IsHorizontal();
bool horiz = scrolledBox->IsXULHorizontal();
nsPoint cp = sf->GetScrollPosition();
nscoord diff = 0;
int32_t curIndex = 0;
bool isLTR = scrolledBox->IsNormalDirection();
bool isLTR = scrolledBox->IsXULNormalDirection();
int32_t frameWidth = 0;
if (!isLTR && horiz) {
@@ -152,7 +152,7 @@ void ScrollBoxObject::ScrollByIndex(int32_t dindexes, ErrorResult& aRv)
break;
}
}
child = nsBox::GetNextBox(child);
child = nsBox::GetNextXULBox(child);
curIndex++;
}
@@ -163,7 +163,7 @@ void ScrollBoxObject::ScrollByIndex(int32_t dindexes, ErrorResult& aRv)
if (dindexes > 0) {
while(child) {
child = nsBox::GetNextBox(child);
child = nsBox::GetNextXULBox(child);
if (child) {
rect = child->GetRect();
}
@@ -174,7 +174,7 @@ void ScrollBoxObject::ScrollByIndex(int32_t dindexes, ErrorResult& aRv)
}
} else if (dindexes < 0) {
child = nsBox::GetChildBox(scrolledBox);
child = nsBox::GetChildXULBox(scrolledBox);
while(child) {
rect = child->GetRect();
if (count >= curIndex + dindexes) {
@@ -182,7 +182,7 @@ void ScrollBoxObject::ScrollByIndex(int32_t dindexes, ErrorResult& aRv)
}
count++;
child = nsBox::GetNextBox(child);
child = nsBox::GetNextXULBox(child);
}
}
+40 -40
View File
@@ -245,7 +245,7 @@ nsGrid::FindRowsAndColumns(nsIFrame** aRows, nsIFrame** aColumns)
nsIFrame* child = nullptr;
// if we have <grid></grid> then mBox will be null (bug 125689)
if (mBox)
child = nsBox::GetChildBox(mBox);
child = nsBox::GetChildXULBox(mBox);
while(child)
{
@@ -262,7 +262,7 @@ nsGrid::FindRowsAndColumns(nsIFrame** aRows, nsIFrame** aColumns)
{
nsGridRowGroupLayout* rowGroup = monument->CastToRowGroupLayout();
if (rowGroup) {
bool isHorizontal = !nsSprocketLayout::IsHorizontal(child);
bool isHorizontal = !nsSprocketLayout::IsXULHorizontal(child);
if (isHorizontal)
*aRows = child;
else
@@ -277,7 +277,7 @@ nsGrid::FindRowsAndColumns(nsIFrame** aRows, nsIFrame** aColumns)
child = oldBox;
}
child = nsBox::GetNextBox(child);
child = nsBox::GetNextXULBox(child);
}
}
@@ -397,7 +397,7 @@ nsGrid::PopulateCellMap(nsGridRow* aRows, nsGridRow* aColumns, int32_t aRowCount
child = row->mBox;
if (child) {
child = nsBox::GetChildBox(child);
child = nsBox::GetChildXULBox(child);
j = 0;
@@ -416,7 +416,7 @@ nsGrid::PopulateCellMap(nsGridRow* aRows, nsGridRow* aColumns, int32_t aRowCount
else
GetCellAt(i,j)->SetBoxInColumn(child);
child = nsBox::GetNextBox(child);
child = nsBox::GetNextXULBox(child);
j++;
}
@@ -543,7 +543,7 @@ nsGrid::GetPartFromBox(nsIFrame* aBox)
if (!aBox)
return nullptr;
nsBoxLayout* layout = aBox->GetLayoutManager();
nsBoxLayout* layout = aBox->GetXULLayoutManager();
return layout ? layout->AsGridPart() : nullptr;
}
@@ -598,7 +598,7 @@ nsGrid::GetFirstAndLastRow(int32_t& aFirstIndex,
for (i=0; i < count; i++)
{
nsGridRow* row = GetRowAt(i,aIsHorizontal);
if (!row->IsCollapsed()) {
if (!row->IsXULCollapsed()) {
aFirstIndex = i;
aFirstRow = row;
break;
@@ -609,7 +609,7 @@ nsGrid::GetFirstAndLastRow(int32_t& aFirstIndex,
for (i=count-1; i >= 0; i--)
{
nsGridRow* row = GetRowAt(i,aIsHorizontal);
if (!row->IsCollapsed()) {
if (!row->IsXULCollapsed()) {
aLastIndex = i;
aLastRow = row;
break;
@@ -652,13 +652,13 @@ nsGrid::GetRowOffsets(int32_t aIndex, nscoord& aTop, nscoord& aBottom, bool aIsH
// borders padding into account
if (box && !row->mIsBogus)
{
if (!box->IsCollapsed())
if (!box->IsXULCollapsed())
{
// get real border and padding. GetBorderAndPadding
// get real border and padding. GetXULBorderAndPadding
// is redefined on nsGridRowLeafFrame. If we called it here
// we would be in finite recurson.
box->GetBorder(border);
box->GetPadding(padding);
box->GetXULBorder(border);
box->GetXULPadding(padding);
totalBorderPadding += border;
totalBorderPadding += padding;
@@ -717,17 +717,17 @@ nsGrid::GetRowOffsets(int32_t aIndex, nscoord& aTop, nscoord& aBottom, bool aIsH
if (box)
{
// ignore collapsed children
if (!box->IsCollapsed())
if (!box->IsXULCollapsed())
{
// include the margin of the columns. To the row
// at this point border/padding and margins all added
// up to more needed space.
margin = GetBoxTotalMargin(box, !aIsHorizontal);
// get real border and padding. GetBorderAndPadding
// get real border and padding. GetXULBorderAndPadding
// is redefined on nsGridRowLeafFrame. If we called it here
// we would be in finite recurson.
box->GetBorder(border);
box->GetPadding(padding);
box->GetXULBorder(border);
box->GetXULPadding(padding);
totalChildBorderPadding += border;
totalChildBorderPadding += padding;
totalChildBorderPadding += margin;
@@ -792,7 +792,7 @@ nsGrid::GetPrefRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHoriz
nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
if (row->IsCollapsed())
if (row->IsXULCollapsed())
return 0;
if (row->IsPrefSet())
@@ -805,7 +805,7 @@ nsGrid::GetPrefRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHoriz
{
bool widthSet, heightSet;
nsSize cssSize(-1, -1);
nsIFrame::AddCSSPrefSize(box, cssSize, widthSet, heightSet);
nsIFrame::AddXULPrefSize(box, cssSize, widthSet, heightSet);
row->mPref = GET_HEIGHT(cssSize, aIsHorizontal);
@@ -826,7 +826,7 @@ nsGrid::GetPrefRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHoriz
nsSize size(0,0);
if (box)
{
size = box->GetPrefSize(aState);
size = box->GetXULPrefSize(aState);
nsBox::AddMargin(box, size);
nsGridLayout2::AddOffset(box, size);
}
@@ -849,9 +849,9 @@ nsGrid::GetPrefRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHoriz
child = GetCellAt(aIndex,i);
// ignore collapsed children
if (!child->IsCollapsed())
if (!child->IsXULCollapsed())
{
nsSize childSize = child->GetPrefSize(aState);
nsSize childSize = child->GetXULPrefSize(aState);
nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal);
}
@@ -869,7 +869,7 @@ nsGrid::GetMinRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizo
nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
if (row->IsCollapsed())
if (row->IsXULCollapsed())
return 0;
if (row->IsMinSet())
@@ -881,7 +881,7 @@ nsGrid::GetMinRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizo
if (box) {
bool widthSet, heightSet;
nsSize cssSize(-1, -1);
nsIFrame::AddCSSMinSize(aState, box, cssSize, widthSet, heightSet);
nsIFrame::AddXULMinSize(aState, box, cssSize, widthSet, heightSet);
row->mMin = GET_HEIGHT(cssSize, aIsHorizontal);
@@ -901,7 +901,7 @@ nsGrid::GetMinRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizo
{
nsSize size(0,0);
if (box) {
size = box->GetPrefSize(aState);
size = box->GetXULPrefSize(aState);
nsBox::AddMargin(box, size);
nsGridLayout2::AddOffset(box, size);
}
@@ -924,9 +924,9 @@ nsGrid::GetMinRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizo
child = GetCellAt(aIndex,i);
// ignore collapsed children
if (!child->IsCollapsed())
if (!child->IsXULCollapsed())
{
nsSize childSize = child->GetMinSize(aState);
nsSize childSize = child->GetXULMinSize(aState);
nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal);
}
@@ -944,7 +944,7 @@ nsGrid::GetMaxRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizo
nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
if (row->IsCollapsed())
if (row->IsXULCollapsed())
return 0;
if (row->IsMaxSet())
@@ -956,7 +956,7 @@ nsGrid::GetMaxRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizo
if (box) {
bool widthSet, heightSet;
nsSize cssSize(-1, -1);
nsIFrame::AddCSSMaxSize(box, cssSize, widthSet, heightSet);
nsIFrame::AddXULMaxSize(box, cssSize, widthSet, heightSet);
row->mMax = GET_HEIGHT(cssSize, aIsHorizontal);
@@ -976,7 +976,7 @@ nsGrid::GetMaxRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizo
{
nsSize size(NS_INTRINSICSIZE,NS_INTRINSICSIZE);
if (box) {
size = box->GetPrefSize(aState);
size = box->GetXULPrefSize(aState);
nsBox::AddMargin(box, size);
nsGridLayout2::AddOffset(box, size);
}
@@ -999,10 +999,10 @@ nsGrid::GetMaxRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizo
child = GetCellAt(aIndex,i);
// ignore collapsed children
if (!child->IsCollapsed())
if (!child->IsXULCollapsed())
{
nsSize min = child->GetMinSize(aState);
nsSize childSize = nsBox::BoundsCheckMinMax(min, child->GetMaxSize(aState));
nsSize min = child->GetXULMinSize(aState);
nsSize childSize = nsBox::BoundsCheckMinMax(min, child->GetXULMaxSize(aState));
nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal);
}
}
@@ -1092,21 +1092,21 @@ nsGrid::GetRowFlex(int32_t aIndex, bool aIsHorizontal)
// the grid. 3) Then we are not flexible
box = GetScrollBox(box);
nsIFrame* parent = nsBox::GetParentBox(box);
nsIFrame* parent = nsBox::GetParentXULBox(box);
nsIFrame* parentsParent=nullptr;
while(parent)
{
parent = GetScrollBox(parent);
parentsParent = nsBox::GetParentBox(parent);
parentsParent = nsBox::GetParentXULBox(parent);
// if our parents parent is not a grid
// the get its flex. If its 0 then we are
// not flexible.
if (parentsParent) {
if (!IsGrid(parentsParent)) {
nscoord flex = parent->GetFlex();
nsIFrame::AddCSSFlex(parent, flex);
nscoord flex = parent->GetXULFlex();
nsIFrame::AddXULFlex(parent, flex);
if (flex == 0) {
row->mFlex = 0;
return row->mFlex;
@@ -1119,8 +1119,8 @@ nsGrid::GetRowFlex(int32_t aIndex, bool aIsHorizontal)
}
// get the row flex.
row->mFlex = box->GetFlex();
nsIFrame::AddCSSFlex(box, row->mFlex);
row->mFlex = box->GetXULFlex();
nsIFrame::AddXULFlex(box, row->mFlex);
}
return row->mFlex;
@@ -1225,7 +1225,7 @@ nsGrid::GetScrollBox(nsIFrame* aChild)
return nullptr;
// get parent
nsIFrame* parent = nsBox::GetParentBox(aChild);
nsIFrame* parent = nsBox::GetParentXULBox(aChild);
// walk up until we find a scrollframe or a part
// if it's a scrollframe return it.
@@ -1242,7 +1242,7 @@ nsGrid::GetScrollBox(nsIFrame* aChild)
if (parentGridRow)
break;
parent = nsBox::GetParentBox(parent);
parent = nsBox::GetParentXULBox(parent);
}
return aChild;
+12 -12
View File
@@ -27,7 +27,7 @@ nsGridCell::~nsGridCell()
}
nsSize
nsGridCell::GetPrefSize(nsBoxLayoutState& aState)
nsGridCell::GetXULPrefSize(nsBoxLayoutState& aState)
{
nsSize sum(0,0);
@@ -36,7 +36,7 @@ nsGridCell::GetPrefSize(nsBoxLayoutState& aState)
// we are tall as the tallest child plus its top offset
if (mBoxInColumn) {
nsSize pref = mBoxInColumn->GetPrefSize(aState);
nsSize pref = mBoxInColumn->GetXULPrefSize(aState);
nsBox::AddMargin(mBoxInColumn, pref);
nsGridLayout2::AddOffset(mBoxInColumn, pref);
@@ -45,7 +45,7 @@ nsGridCell::GetPrefSize(nsBoxLayoutState& aState)
}
if (mBoxInRow) {
nsSize pref = mBoxInRow->GetPrefSize(aState);
nsSize pref = mBoxInRow->GetXULPrefSize(aState);
nsBox::AddMargin(mBoxInRow, pref);
nsGridLayout2::AddOffset(mBoxInRow, pref);
@@ -57,7 +57,7 @@ nsGridCell::GetPrefSize(nsBoxLayoutState& aState)
}
nsSize
nsGridCell::GetMinSize(nsBoxLayoutState& aState)
nsGridCell::GetXULMinSize(nsBoxLayoutState& aState)
{
nsSize sum(0, 0);
@@ -66,7 +66,7 @@ nsGridCell::GetMinSize(nsBoxLayoutState& aState)
// we are tall as the tallest child plus its top offset
if (mBoxInColumn) {
nsSize min = mBoxInColumn->GetMinSize(aState);
nsSize min = mBoxInColumn->GetXULMinSize(aState);
nsBox::AddMargin(mBoxInColumn, min);
nsGridLayout2::AddOffset(mBoxInColumn, min);
@@ -75,7 +75,7 @@ nsGridCell::GetMinSize(nsBoxLayoutState& aState)
}
if (mBoxInRow) {
nsSize min = mBoxInRow->GetMinSize(aState);
nsSize min = mBoxInRow->GetXULMinSize(aState);
nsBox::AddMargin(mBoxInRow, min);
nsGridLayout2::AddOffset(mBoxInRow, min);
@@ -87,7 +87,7 @@ nsGridCell::GetMinSize(nsBoxLayoutState& aState)
}
nsSize
nsGridCell::GetMaxSize(nsBoxLayoutState& aState)
nsGridCell::GetXULMaxSize(nsBoxLayoutState& aState)
{
nsSize sum(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
@@ -96,7 +96,7 @@ nsGridCell::GetMaxSize(nsBoxLayoutState& aState)
// we are tall as the shortest child plus its top offset
if (mBoxInColumn) {
nsSize max = mBoxInColumn->GetMaxSize(aState);
nsSize max = mBoxInColumn->GetXULMaxSize(aState);
nsBox::AddMargin(mBoxInColumn, max);
nsGridLayout2::AddOffset(mBoxInColumn, max);
@@ -105,7 +105,7 @@ nsGridCell::GetMaxSize(nsBoxLayoutState& aState)
}
if (mBoxInRow) {
nsSize max = mBoxInRow->GetMaxSize(aState);
nsSize max = mBoxInRow->GetXULMaxSize(aState);
nsBox::AddMargin(mBoxInRow, max);
nsGridLayout2::AddOffset(mBoxInRow, max);
@@ -118,10 +118,10 @@ nsGridCell::GetMaxSize(nsBoxLayoutState& aState)
bool
nsGridCell::IsCollapsed()
nsGridCell::IsXULCollapsed()
{
return ((mBoxInColumn && mBoxInColumn->IsCollapsed()) ||
(mBoxInRow && mBoxInRow->IsCollapsed()));
return ((mBoxInColumn && mBoxInColumn->IsXULCollapsed()) ||
(mBoxInRow && mBoxInRow->IsXULCollapsed()));
}
+4 -4
View File
@@ -33,10 +33,10 @@ public:
nsGridCell();
~nsGridCell();
nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState);
nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState);
nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState);
bool IsCollapsed();
nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState);
nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState);
nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState);
bool IsXULCollapsed();
// accessors
nsIFrame* GetBoxInColumn() { return mBoxInColumn; }
+10 -10
View File
@@ -47,13 +47,13 @@ nsGridLayout2::AddOffset(nsIFrame* aChild, nsSize& aSize)
}
NS_IMETHODIMP
nsGridLayout2::Layout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
nsGridLayout2::XULLayout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
{
// XXX This should be set a better way!
mGrid.SetBox(aBox);
NS_ASSERTION(aBox->GetLayoutManager() == this, "setting incorrect box");
NS_ASSERTION(aBox->GetXULLayoutManager() == this, "setting incorrect box");
nsresult rv = nsStackLayout::Layout(aBox, aBoxLayoutState);
nsresult rv = nsStackLayout::XULLayout(aBox, aBoxLayoutState);
#ifdef DEBUG_grid
mGrid.PrintCellMap();
#endif
@@ -75,7 +75,7 @@ nsGridLayout2::GetGrid(nsIFrame* aBox, int32_t* aIndex, nsGridRowLayout* aReques
{
// XXX This should be set a better way!
mGrid.SetBox(aBox);
NS_ASSERTION(aBox->GetLayoutManager() == this, "setting incorrect box");
NS_ASSERTION(aBox->GetXULLayoutManager() == this, "setting incorrect box");
return &mGrid;
}
@@ -93,9 +93,9 @@ nsGridLayout2::AddWidth(nsSize& aSize, nscoord aSize2, bool aIsHorizontal)
}
nsSize
nsGridLayout2::GetMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
nsGridLayout2::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
{
nsSize minSize = nsStackLayout::GetMinSize(aBox, aState);
nsSize minSize = nsStackLayout::GetXULMinSize(aBox, aState);
// if there are no <rows> tags that will sum up our columns,
// sum up our columns here.
@@ -132,9 +132,9 @@ nsGridLayout2::GetMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
}
nsSize
nsGridLayout2::GetPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
nsGridLayout2::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
{
nsSize pref = nsStackLayout::GetPrefSize(aBox, aState);
nsSize pref = nsStackLayout::GetXULPrefSize(aBox, aState);
// if there are no <rows> tags that will sum up our columns,
// sum up our columns here.
@@ -171,9 +171,9 @@ nsGridLayout2::GetPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
}
nsSize
nsGridLayout2::GetMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState)
nsGridLayout2::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState)
{
nsSize maxSize = nsStackLayout::GetMaxSize(aBox, aState);
nsSize maxSize = nsStackLayout::GetXULMaxSize(aBox, aState);
// if there are no <rows> tags that will sum up our columns,
// sum up our columns here.
+4 -4
View File
@@ -30,7 +30,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED
NS_IMETHOD Layout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
NS_IMETHOD XULLayout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
virtual void IntrinsicISizesDirty(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
virtual nsGridRowGroupLayout* CastToRowGroupLayout() override { return nullptr; }
@@ -39,9 +39,9 @@ public:
virtual nsIGridPart* GetParentGridPart(nsIFrame* aBox, nsIFrame** aParentBox) override {
NS_NOTREACHED("Should not be called"); return nullptr;
}
virtual nsSize GetMinSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetMaxSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetPrefSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
virtual void CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount) override { aRowCount++; }
virtual void DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState) override { }
virtual int32_t BuildRows(nsIFrame* aBox, nsGridRow* aRows) override;

Some files were not shown because too many files have changed in this diff Show More