mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to s-c
This commit is contained in:
commit
ba6209b00e
@ -1601,6 +1601,20 @@ public:
|
||||
|
||||
virtual void PostVisibilityUpdateEvent() = 0;
|
||||
|
||||
void SetNeedLayoutFlush() {
|
||||
mNeedLayoutFlush = true;
|
||||
if (mDisplayDocument) {
|
||||
mDisplayDocument->SetNeedLayoutFlush();
|
||||
}
|
||||
}
|
||||
|
||||
void SetNeedStyleFlush() {
|
||||
mNeedStyleFlush = true;
|
||||
if (mDisplayDocument) {
|
||||
mDisplayDocument->SetNeedStyleFlush();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
PRUint64 mWarnedAbout;
|
||||
|
||||
@ -1765,6 +1779,12 @@ protected:
|
||||
// True if this document has links whose state needs updating
|
||||
bool mHasLinksToUpdate;
|
||||
|
||||
// True if a layout flush might not be a no-op
|
||||
bool mNeedLayoutFlush;
|
||||
|
||||
// True if a style flush might not be a no-op
|
||||
bool mNeedStyleFlush;
|
||||
|
||||
// The document's script global object, the object from which the
|
||||
// document can get its script context and scope. This is the
|
||||
// *inner* window object.
|
||||
|
@ -6226,7 +6226,15 @@ nsDocument::CreateEvent(const nsAString& aEventType, nsIDOMEvent** aReturn)
|
||||
void
|
||||
nsDocument::FlushPendingNotifications(mozFlushType aType)
|
||||
{
|
||||
if ((!IsHTML() || aType > Flush_ContentAndNotify) &&
|
||||
// We need to flush the sink for non-HTML documents (because the XML
|
||||
// parser still does insertion with deferred notifications). We
|
||||
// also need to flush the sink if this is a layout-related flush, to
|
||||
// make sure that layout is started as needed. But we can skip that
|
||||
// part if we have no presshell or if it's already done an initial
|
||||
// reflow.
|
||||
if ((!IsHTML() ||
|
||||
(aType > Flush_ContentAndNotify && mPresShell &&
|
||||
!mPresShell->DidInitialReflow())) &&
|
||||
(mParser || mWeakSink)) {
|
||||
nsCOMPtr<nsIContentSink> sink;
|
||||
if (mParser) {
|
||||
@ -6267,9 +6275,28 @@ nsDocument::FlushPendingNotifications(mozFlushType aType)
|
||||
mParentDocument->FlushPendingNotifications(parentType);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell = GetShell();
|
||||
if (shell) {
|
||||
shell->FlushPendingNotifications(aType);
|
||||
// We can optimize away getting our presshell and calling
|
||||
// FlushPendingNotifications on it if we don't need a flush of the sort we're
|
||||
// looking at. The one exception is if mInFlush is true, because in that
|
||||
// case we might have set mNeedStyleFlush and mNeedLayoutFlush to false
|
||||
// already but the presshell hasn't actually done the corresponding work yet.
|
||||
// So if mInFlush and reentering this code, we need to flush the presshell.
|
||||
if (mNeedStyleFlush ||
|
||||
(mNeedLayoutFlush && aType >= Flush_InterruptibleLayout) ||
|
||||
aType >= Flush_Display ||
|
||||
mInFlush) {
|
||||
nsCOMPtr<nsIPresShell> shell = GetShell();
|
||||
if (shell) {
|
||||
mNeedStyleFlush = false;
|
||||
mNeedLayoutFlush = mNeedLayoutFlush && (aType < Flush_InterruptibleLayout);
|
||||
// mInFlush is a bitfield, so can't us AutoRestore here. But we
|
||||
// need to keep track of multi-level reentry correctly, so need
|
||||
// to restore the old mInFlush value.
|
||||
bool oldInFlush = mInFlush;
|
||||
mInFlush = true;
|
||||
shell->FlushPendingNotifications(aType);
|
||||
mInFlush = oldInFlush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6759,7 +6786,7 @@ nsDocument::CreateElem(const nsAString& aName, nsIAtom *aPrefix, PRInt32 aNamesp
|
||||
bool
|
||||
nsDocument::IsSafeToFlush() const
|
||||
{
|
||||
nsCOMPtr<nsIPresShell> shell = GetShell();
|
||||
nsIPresShell* shell = GetShell();
|
||||
if (!shell)
|
||||
return true;
|
||||
|
||||
|
@ -1187,6 +1187,10 @@ protected:
|
||||
// Whether we are currently in full-screen mode, as per the DOM API.
|
||||
bool mIsFullScreen:1;
|
||||
|
||||
// Whether we're currently under a FlushPendingNotifications call to
|
||||
// our presshell. This is used to handle flush reentry correctly.
|
||||
bool mInFlush:1;
|
||||
|
||||
PRUint8 mXMLDeclarationBits;
|
||||
|
||||
nsInterfaceHashtable<nsVoidPtrHashKey, nsPIBoxObject> *mBoxObjectTable;
|
||||
|
@ -537,6 +537,7 @@ _TEST_FILES2 = \
|
||||
file_bug707142_baseline.json \
|
||||
file_bug707142_bom.json \
|
||||
file_bug707142_utf-16.json \
|
||||
test_reentrant_flush.html \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_FILES = \
|
||||
|
58
content/base/test/test_reentrant_flush.html
Normal file
58
content/base/test/test_reentrant_flush.html
Normal file
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=709256
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 709256</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=709256">Mozilla Bug 709256</a>
|
||||
<p id="display">
|
||||
<iframe id="test"
|
||||
style="width: 100px" src="data:text/html,<body style='width: 100%'>">
|
||||
</iframe>
|
||||
</p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 709256 **/
|
||||
addLoadEvent(function() {
|
||||
var ifr = $("test");
|
||||
var bod = ifr.contentDocument.body;
|
||||
|
||||
is(bod.getBoundingClientRect().width, 100,
|
||||
"Width of body should be 100px to start with");
|
||||
|
||||
var resizeHandlerRan = false;
|
||||
|
||||
function handleResize() {
|
||||
resizeHandlerRan = true;
|
||||
is(bod.getBoundingClientRect().width, 50,
|
||||
"Width of body should now be 50px");
|
||||
}
|
||||
|
||||
var win = ifr.contentWindow;
|
||||
|
||||
win.addEventListener("resize", handleResize, false);
|
||||
SpecialPowers.setFullZoom(win, 2);
|
||||
|
||||
is(resizeHandlerRan, false,
|
||||
"Resize handler should not have run yet for this test to be valid");
|
||||
|
||||
// Now flush out layout on the subdocument, to trigger the resize handler
|
||||
is(bod.getBoundingClientRect().width, 50, "Width of body should still be 50px");
|
||||
|
||||
is(resizeHandlerRan, true, "Resize handler should have run");
|
||||
|
||||
win.removeEventListener("resize", handleResize, false);
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -852,3 +852,9 @@ nsSMILAnimationController::GetRefreshDriver()
|
||||
nsPresContext* context = shell->GetPresContext();
|
||||
return context ? context->RefreshDriver() : nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILAnimationController::FlagDocumentNeedsFlush()
|
||||
{
|
||||
mDocument->SetNeedStyleFlush();
|
||||
}
|
||||
|
@ -96,9 +96,13 @@ public:
|
||||
// (A resample performs the same operations as a sample but doesn't advance
|
||||
// the current time and doesn't check if the container is paused)
|
||||
void Resample() { DoSample(false); }
|
||||
|
||||
void SetResampleNeeded()
|
||||
{
|
||||
if (!mRunningSample) {
|
||||
if (!mResampleNeeded) {
|
||||
FlagDocumentNeedsFlush();
|
||||
}
|
||||
mResampleNeeded = true;
|
||||
}
|
||||
}
|
||||
@ -198,6 +202,8 @@ protected:
|
||||
virtual nsresult AddChild(nsSMILTimeContainer& aChild);
|
||||
virtual void RemoveChild(nsSMILTimeContainer& aChild);
|
||||
|
||||
void FlagDocumentNeedsFlush();
|
||||
|
||||
// Members
|
||||
nsAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
@ -989,6 +989,9 @@ nsBindingManager::AddToAttachedQueue(nsXBLBinding* aBinding)
|
||||
PostProcessAttachedQueueEvent();
|
||||
}
|
||||
|
||||
// Make sure that flushes will flush out the new items as needed.
|
||||
mDocument->SetNeedStyleFlush();
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
@ -2224,8 +2224,10 @@ nsDOMClassInfo::RegisterExternalClasses()
|
||||
/* number of interfaces due to the terminating null */ \
|
||||
for (size_t i = 0; i < count - 1; ++i) { \
|
||||
if (!interface_list[i]) { \
|
||||
/* We are moving the element at index i+1 and successors, */ \
|
||||
/* so we must move only count - (i+1) elements total. */ \
|
||||
memmove(&interface_list[i], &interface_list[i+1], \
|
||||
sizeof(nsIID*) * (count - i)); \
|
||||
sizeof(nsIID*) * (count - (i+1))); \
|
||||
/* Make sure to examine the new pointer we ended up with at this */ \
|
||||
/* slot, since it may be null too */ \
|
||||
--i; \
|
||||
|
@ -59,6 +59,7 @@ PEGroupRuleNestedAtRule=%1$S rule not allowed within @media or @-moz-document ru
|
||||
PEMozDocRuleBadFunc=Expected url(), url-prefix(), or domain() in @-moz-document rule but found '%1$S'.
|
||||
PEMozDocRuleNotURI=Expected URI in @-moz-document rule but found '%1$S'.
|
||||
PEMozDocRuleNotString=Expected string in @-moz-document rule regexp() function but found '%1$S'.
|
||||
PEMozDocRuleEOF=next URI in @-moz-document rule
|
||||
PEAtNSPrefixEOF=namespace prefix in @namespace rule
|
||||
PEAtNSURIEOF=namespace URI in @namespace rule
|
||||
PEAtNSUnexpected=Unexpected token within @namespace: '%1$S'.
|
||||
|
@ -1490,36 +1490,18 @@ JS_DefineProfilingFunctions(JSContext *cx, JSObject *obj)
|
||||
|
||||
#include <valgrind/callgrind.h>
|
||||
|
||||
/*
|
||||
* Wrapper for callgrind macros to stop warnings coming from their expansions.
|
||||
*/
|
||||
#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
# define WRAP_CALLGRIND(call) \
|
||||
JS_BEGIN_MACRO \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"") \
|
||||
call; \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
JS_END_MACRO
|
||||
#else
|
||||
# define WRAP_CALLGRIND(call) \
|
||||
JS_BEGIN_MACRO \
|
||||
call; \
|
||||
JS_END_MACRO
|
||||
#endif
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_StartCallgrind()
|
||||
{
|
||||
WRAP_CALLGRIND(CALLGRIND_START_INSTRUMENTATION);
|
||||
WRAP_CALLGRIND(CALLGRIND_ZERO_STATS);
|
||||
JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_START_INSTRUMENTATION);
|
||||
JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_ZERO_STATS);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_StopCallgrind()
|
||||
{
|
||||
WRAP_CALLGRIND(CALLGRIND_STOP_INSTRUMENTATION);
|
||||
JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_STOP_INSTRUMENTATION);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1527,9 +1509,9 @@ JS_FRIEND_API(JSBool)
|
||||
js_DumpCallgrind(const char *outfile)
|
||||
{
|
||||
if (outfile) {
|
||||
WRAP_CALLGRIND(CALLGRIND_DUMP_STATS_AT(outfile));
|
||||
JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_DUMP_STATS_AT(outfile));
|
||||
} else {
|
||||
WRAP_CALLGRIND(CALLGRIND_DUMP_STATS);
|
||||
JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_DUMP_STATS);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1010,7 +1010,7 @@ MarkWordConservatively(JSTracer *trc, jsuword w)
|
||||
* original word. See bug 572678.
|
||||
*/
|
||||
#ifdef JS_VALGRIND
|
||||
VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(w));
|
||||
JS_SILENCE_UNUSED_VALUE_IN_EXPR(VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(w)));
|
||||
#endif
|
||||
|
||||
MarkIfGCThingWord(trc, w);
|
||||
|
@ -440,4 +440,28 @@ typedef size_t jsbitmap;
|
||||
#define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &= \
|
||||
~((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
|
||||
|
||||
/* Wrapper for various macros to stop warnings coming from their expansions. */
|
||||
#if defined(__clang__)
|
||||
# define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
|
||||
JS_BEGIN_MACRO \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wunused-value\"") \
|
||||
expr; \
|
||||
_Pragma("clang diagnostic pop") \
|
||||
JS_END_MACRO
|
||||
#elif (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
# define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
|
||||
JS_BEGIN_MACRO \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"") \
|
||||
expr; \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
JS_END_MACRO
|
||||
#else
|
||||
# define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
|
||||
JS_BEGIN_MACRO \
|
||||
expr; \
|
||||
JS_END_MACRO
|
||||
#endif
|
||||
|
||||
#endif /* jsutil_h___ */
|
||||
|
@ -166,7 +166,7 @@ RestyleTracker::ProcessOneRestyle(Element* aElement,
|
||||
}
|
||||
|
||||
void
|
||||
RestyleTracker::ProcessRestyles()
|
||||
RestyleTracker::DoProcessRestyles()
|
||||
{
|
||||
SAMPLE_LABEL("CSS", "ProcessRestyles");
|
||||
// Make sure to not rebuild quote or counter lists while we're
|
||||
|
@ -94,7 +94,13 @@ public:
|
||||
/**
|
||||
* Process the restyles we've been tracking.
|
||||
*/
|
||||
void ProcessRestyles();
|
||||
void ProcessRestyles() {
|
||||
// Fast-path the common case (esp. for the animation restyle
|
||||
// tracker) of not having anything to do.
|
||||
if (mPendingRestyles.Count()) {
|
||||
DoProcessRestyles();
|
||||
}
|
||||
}
|
||||
|
||||
// Return our ELEMENT_HAS_PENDING_(ANIMATION_)RESTYLE bit
|
||||
PRUint32 RestyleBit() const {
|
||||
@ -143,6 +149,11 @@ private:
|
||||
nsRestyleHint aRestyleHint,
|
||||
nsChangeHint aChangeHint);
|
||||
|
||||
/**
|
||||
* The guts of our restyle processing.
|
||||
*/
|
||||
void DoProcessRestyles();
|
||||
|
||||
typedef nsDataHashtable<nsISupportsHashKey, RestyleData> PendingRestyleTable;
|
||||
typedef nsAutoTArray< nsRefPtr<Element>, 32> RestyleRootArray;
|
||||
// Our restyle bits. These will be a subset of ELEMENT_ALL_RESTYLE_FLAGS, and
|
||||
|
@ -11703,6 +11703,11 @@ nsCSSFrameConstructor::PostRestyleEventInternal(bool aForLazyConstruction)
|
||||
mObservingRefreshDriver = mPresShell->GetPresContext()->RefreshDriver()->
|
||||
AddStyleFlushObserver(mPresShell);
|
||||
}
|
||||
|
||||
// Unconditionally flag our document as needing a flush. The other
|
||||
// option here would be a dedicated boolean to track whether we need
|
||||
// to do so (set here and unset in ProcessPendingRestyles).
|
||||
mPresShell->GetDocument()->SetNeedStyleFlush();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1774,11 +1774,13 @@ private:
|
||||
void QuotesDirty() {
|
||||
NS_PRECONDITION(mUpdateCount != 0, "Instant quote updates are bad news");
|
||||
mQuotesDirty = true;
|
||||
mDocument->SetNeedLayoutFlush();
|
||||
}
|
||||
|
||||
void CountersDirty() {
|
||||
NS_PRECONDITION(mUpdateCount != 0, "Instant counter updates are bad news");
|
||||
mCountersDirty = true;
|
||||
mDocument->SetNeedLayoutFlush();
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -1677,6 +1677,7 @@ nsPresContext::PostMediaFeatureValuesChangedEvent()
|
||||
NS_NewRunnableMethod(this, &nsPresContext::HandleMediaFeatureValuesChangedEvent);
|
||||
if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev))) {
|
||||
mPendingMediaFeatureValuesChanged = true;
|
||||
mDocument->SetNeedStyleFlush();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1886,6 +1887,7 @@ nsPresContext::RebuildUserFontSet()
|
||||
}
|
||||
|
||||
mUserFontSetDirty = true;
|
||||
mDocument->SetNeedStyleFlush();
|
||||
|
||||
// Somebody has already asked for the user font set, so we need to
|
||||
// post an event to rebuild it. Setting the user font set to be dirty
|
||||
|
@ -2183,6 +2183,7 @@ PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight)
|
||||
NS_NewRunnableMethod(this, &PresShell::FireResizeEvent);
|
||||
if (NS_SUCCEEDED(NS_DispatchToCurrentThread(resizeEvent))) {
|
||||
mResizeEvent = resizeEvent;
|
||||
mDocument->SetNeedStyleFlush();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2864,6 +2865,7 @@ PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
|
||||
// we've hit a reflow root or the root frame
|
||||
if (!wasDirty) {
|
||||
mDirtyRoots.AppendElement(f);
|
||||
mDocument->SetNeedLayoutFlush();
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
@ -3444,6 +3446,7 @@ PresShell::ScrollContentIntoView(nsIContent* aContent,
|
||||
mContentToScrollToFlags = aFlags;
|
||||
|
||||
// Flush layout and attempt to scroll in the process.
|
||||
currentDoc->SetNeedLayoutFlush();
|
||||
currentDoc->FlushPendingNotifications(Flush_InterruptibleLayout);
|
||||
|
||||
// If mContentToScrollTo is non-null, that means we interrupted the reflow
|
||||
@ -3835,7 +3838,7 @@ PresShell::UnsuppressPainting()
|
||||
// the reflows and get all the frames where we want them
|
||||
// before actually unlocking the painting. Otherwise
|
||||
// go ahead and unlock now.
|
||||
if (mDirtyRoots.Length() > 0)
|
||||
if (!mDirtyRoots.IsEmpty())
|
||||
mShouldUnsuppressPainting = true;
|
||||
else
|
||||
UnsuppressAndInvalidate();
|
||||
@ -3966,6 +3969,12 @@ PresShell::IsSafeToFlush() const
|
||||
void
|
||||
PresShell::FlushPendingNotifications(mozFlushType aType)
|
||||
{
|
||||
/**
|
||||
* VERY IMPORTANT: If you add some sort of new flushing to this
|
||||
* method, make sure to add the relevant SetNeedLayoutFlush or
|
||||
* SetNeedStyleFlush calls on the document.
|
||||
*/
|
||||
|
||||
#ifdef NS_FUNCTION_TIMER
|
||||
NS_TIME_FUNCTION_DECLARE_DOCURL;
|
||||
static const char *flushTypeNames[] = {
|
||||
@ -4100,6 +4109,11 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
|
||||
mContentToScrollToFlags);
|
||||
mContentToScrollTo = nsnull;
|
||||
}
|
||||
} else if (!mIsDestroying && mSuppressInterruptibleReflows &&
|
||||
aType == Flush_InterruptibleLayout) {
|
||||
// We suppressed this flush, but the document thinks it doesn't
|
||||
// need to flush anymore. Let it know what's really going on.
|
||||
mDocument->SetNeedLayoutFlush();
|
||||
}
|
||||
|
||||
if (aType >= Flush_Layout) {
|
||||
@ -7343,6 +7357,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
|
||||
mFramesToDirty.EnumerateEntries(&MarkFramesDirtyToRoot, target);
|
||||
NS_ASSERTION(NS_SUBTREE_DIRTY(target), "Why is the target not dirty?");
|
||||
mDirtyRoots.AppendElement(target);
|
||||
mDocument->SetNeedLayoutFlush();
|
||||
|
||||
// Clear mFramesToDirty after we've done the NS_SUBTREE_DIRTY(target)
|
||||
// assertion so that if it fails it's easier to see what's going on.
|
||||
@ -7385,7 +7400,7 @@ PresShell::DoVerifyReflow()
|
||||
ok ? "ok" : "failed");
|
||||
}
|
||||
|
||||
if (0 != mDirtyRoots.Length()) {
|
||||
if (!mDirtyRoots.IsEmpty()) {
|
||||
printf("XXX yikes! reflow commands queued during verify-reflow\n");
|
||||
}
|
||||
}
|
||||
@ -7395,10 +7410,15 @@ PresShell::DoVerifyReflow()
|
||||
bool
|
||||
PresShell::ProcessReflowCommands(bool aInterruptible)
|
||||
{
|
||||
if (mDirtyRoots.IsEmpty() && !mShouldUnsuppressPainting) {
|
||||
// Nothing to do; bail out
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_TIME_FUNCTION_WITH_DOCURL;
|
||||
mozilla::TimeStamp timerStart = mozilla::TimeStamp::Now();
|
||||
bool interrupted = false;
|
||||
if (0 != mDirtyRoots.Length()) {
|
||||
if (!mDirtyRoots.IsEmpty()) {
|
||||
|
||||
#ifdef DEBUG
|
||||
if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
|
||||
@ -7434,10 +7454,10 @@ PresShell::ProcessReflowCommands(bool aInterruptible)
|
||||
|
||||
// Keep going until we're out of reflow commands, or we've run
|
||||
// past our deadline, or we're interrupted.
|
||||
} while (!interrupted && mDirtyRoots.Length() &&
|
||||
} while (!interrupted && !mDirtyRoots.IsEmpty() &&
|
||||
(!aInterruptible || PR_IntervalNow() < deadline));
|
||||
|
||||
interrupted = mDirtyRoots.Length() != 0;
|
||||
interrupted = !mDirtyRoots.IsEmpty();
|
||||
}
|
||||
|
||||
// Exiting the scriptblocker might have killed us
|
||||
@ -7460,13 +7480,16 @@ PresShell::ProcessReflowCommands(bool aInterruptible)
|
||||
// after DidDoReflow(), since that method can change whether there are
|
||||
// dirty roots around by flushing, and there's no point in posting a
|
||||
// reflow event just to have the flush revoke it.
|
||||
if (mDirtyRoots.Length())
|
||||
if (!mDirtyRoots.IsEmpty()) {
|
||||
MaybeScheduleReflow();
|
||||
// And tell our document that we might need flushing
|
||||
mDocument->SetNeedLayoutFlush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mIsDestroying && mShouldUnsuppressPainting &&
|
||||
mDirtyRoots.Length() == 0) {
|
||||
mDirtyRoots.IsEmpty()) {
|
||||
// We only unlock if we're out of reflows. It's pointless
|
||||
// to unlock if reflows are still pending, since reflows
|
||||
// are just going to thrash the frames around some more. By
|
||||
|
@ -546,6 +546,9 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
|
||||
// dispatch them the next time we get a refresh driver notification
|
||||
// or the next time somebody calls
|
||||
// nsPresShell::FlushPendingNotifications.
|
||||
if (!mPendingEvents.IsEmpty()) {
|
||||
mPresContext->Document()->SetNeedStyleFlush();
|
||||
}
|
||||
}
|
||||
|
||||
return GetAnimationRule(aElement, aStyleContext->GetPseudoType());
|
||||
@ -901,7 +904,7 @@ nsAnimationManager::WillRefresh(mozilla::TimeStamp aTime)
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationManager::DispatchEvents()
|
||||
nsAnimationManager::DoDispatchEvents()
|
||||
{
|
||||
EventArray events;
|
||||
mPendingEvents.SwapElements(events);
|
||||
|
@ -131,7 +131,12 @@ public:
|
||||
* accumulate animationstart events at other points when style
|
||||
* contexts are created.
|
||||
*/
|
||||
void DispatchEvents();
|
||||
void DispatchEvents() {
|
||||
// Fast-path the common case: no events
|
||||
if (!mPendingEvents.IsEmpty()) {
|
||||
DoDispatchEvents();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ElementAnimations* GetElementAnimations(mozilla::dom::Element *aElement,
|
||||
@ -149,6 +154,9 @@ private:
|
||||
|
||||
nsCSSKeyframesRule* KeyframesRuleFor(const nsSubstring& aName);
|
||||
|
||||
// The guts of DispatchEvents
|
||||
void DoDispatchEvents();
|
||||
|
||||
bool mKeyframesListIsDirty;
|
||||
nsDataHashtable<nsStringHashKey, nsCSSKeyframesRule*> mKeyframesRules;
|
||||
|
||||
|
@ -335,22 +335,23 @@ protected:
|
||||
void PopGroup();
|
||||
|
||||
bool ParseRuleSet(RuleAppendFunc aAppendFunc, void* aProcessData,
|
||||
bool aInsideBraces = false);
|
||||
bool ParseAtRule(RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
bool aInsideBraces = false);
|
||||
bool ParseAtRule(RuleAppendFunc aAppendFunc, void* aProcessData,
|
||||
bool aInAtRule);
|
||||
bool ParseCharsetRule(RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
bool ParseImportRule(RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
bool ParseURLOrString(nsString& aURL);
|
||||
bool GatherMedia(nsMediaList* aMedia,
|
||||
bool aInAtRule);
|
||||
bool aInAtRule);
|
||||
bool ParseMediaQuery(bool aInAtRule, nsMediaQuery **aQuery,
|
||||
bool *aHitStop);
|
||||
bool *aHitStop);
|
||||
bool ParseMediaQueryExpression(nsMediaQuery* aQuery);
|
||||
void ProcessImport(const nsString& aURLSpec,
|
||||
nsMediaList* aMedia,
|
||||
RuleAppendFunc aAppendFunc,
|
||||
void* aProcessData);
|
||||
bool ParseGroupRule(css::GroupRule* aRule, RuleAppendFunc aAppendFunc,
|
||||
void* aProcessData);
|
||||
void* aProcessData);
|
||||
bool ParseMediaRule(RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
bool ParseMozDocumentRule(RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
bool ParseNameSpaceRule(RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
@ -361,7 +362,7 @@ protected:
|
||||
bool ParseFontFaceRule(RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
bool ParseFontDescriptor(nsCSSFontFaceRule* aRule);
|
||||
bool ParseFontDescriptorValue(nsCSSFontDesc aDescID,
|
||||
nsCSSValue& aValue);
|
||||
nsCSSValue& aValue);
|
||||
|
||||
bool ParsePageRule(RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
bool ParseKeyframesRule(RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
@ -919,7 +920,7 @@ CSSParserImpl::ParseSheet(const nsAString& aInput,
|
||||
continue; // legal here only
|
||||
}
|
||||
if (eCSSToken_AtKeyword == tk->mType) {
|
||||
ParseAtRule(AppendRuleToSheet, this);
|
||||
ParseAtRule(AppendRuleToSheet, this, false);
|
||||
continue;
|
||||
}
|
||||
UngetToken();
|
||||
@ -1050,7 +1051,7 @@ CSSParserImpl::ParseRule(const nsAString& aRule,
|
||||
REPORT_UNEXPECTED(PEParseRuleWSOnly);
|
||||
OUTPUT_ERROR();
|
||||
} else if (eCSSToken_AtKeyword == tk->mType) {
|
||||
ParseAtRule(AppendRuleToArray, &aResult);
|
||||
ParseAtRule(AppendRuleToArray, &aResult, false);
|
||||
}
|
||||
else {
|
||||
UngetToken();
|
||||
@ -1508,14 +1509,10 @@ CSSParserImpl::SkipAtRule(bool aInsideBlock)
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseAtRule(RuleAppendFunc aAppendFunc,
|
||||
void* aData)
|
||||
void* aData,
|
||||
bool aInAtRule)
|
||||
{
|
||||
// If we ever allow nested at-rules, we need to be very careful about
|
||||
// the error handling rules in the CSS spec. In particular, we need
|
||||
// to pass in to ParseAtRule whether we're inside a block, we need to
|
||||
// ensure that all the individual at-rule parsing functions terminate
|
||||
// immediately when they hit a '}', and then we need to pass whether
|
||||
// we're inside a block to SkipAtRule below.
|
||||
|
||||
nsCSSSection newSection;
|
||||
bool (CSSParserImpl::*parseFunc)(RuleAppendFunc, void*);
|
||||
|
||||
@ -1560,16 +1557,27 @@ CSSParserImpl::ParseAtRule(RuleAppendFunc aAppendFunc,
|
||||
OUTPUT_ERROR();
|
||||
}
|
||||
// Skip over unsupported at rule, don't advance section
|
||||
return SkipAtRule(false);
|
||||
return SkipAtRule(aInAtRule);
|
||||
}
|
||||
|
||||
if (!(this->*parseFunc)(aAppendFunc, aData)) {
|
||||
// Inside of @-rules, only the rules that can occur anywhere
|
||||
// are allowed.
|
||||
bool unnestable = aInAtRule && newSection != eCSSSection_General;
|
||||
if (unnestable) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEGroupRuleNestedAtRule);
|
||||
}
|
||||
|
||||
if (unnestable || !(this->*parseFunc)(aAppendFunc, aData)) {
|
||||
// Skip over invalid at rule, don't advance section
|
||||
OUTPUT_ERROR();
|
||||
return SkipAtRule(false);
|
||||
return SkipAtRule(aInAtRule);
|
||||
}
|
||||
|
||||
mSection = newSection;
|
||||
// Nested @-rules don't affect the top-level rule chain requirement
|
||||
if (!aInAtRule) {
|
||||
mSection = newSection;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1637,7 +1645,7 @@ CSSParserImpl::ParseMediaQuery(bool aInAtRule,
|
||||
}
|
||||
|
||||
if (eCSSToken_Symbol == mToken.mType && aInAtRule &&
|
||||
(mToken.mSymbol == ';' || mToken.mSymbol == '{')) {
|
||||
(mToken.mSymbol == ';' || mToken.mSymbol == '{' || mToken.mSymbol == '}' )) {
|
||||
*aHitStop = true;
|
||||
UngetToken();
|
||||
return true;
|
||||
@ -1701,7 +1709,7 @@ CSSParserImpl::ParseMediaQuery(bool aInAtRule,
|
||||
}
|
||||
|
||||
if (eCSSToken_Symbol == mToken.mType && aInAtRule &&
|
||||
(mToken.mSymbol == ';' || mToken.mSymbol == '{')) {
|
||||
(mToken.mSymbol == ';' || mToken.mSymbol == '{' || mToken.mSymbol == '}')) {
|
||||
*aHitStop = true;
|
||||
UngetToken();
|
||||
break;
|
||||
@ -1742,14 +1750,14 @@ CSSParserImpl::GatherMedia(nsMediaList* aMedia,
|
||||
}
|
||||
if (aInAtRule) {
|
||||
const PRUnichar stopChars[] =
|
||||
{ PRUnichar(','), PRUnichar('{'), PRUnichar(';'), PRUnichar(0) };
|
||||
{ PRUnichar(','), PRUnichar('{'), PRUnichar(';'), PRUnichar('}'), PRUnichar(0) };
|
||||
SkipUntilOneOf(stopChars);
|
||||
} else {
|
||||
SkipUntil(',');
|
||||
}
|
||||
// Rely on SkipUntilOneOf leaving mToken around as the last token read.
|
||||
if (mToken.mType == eCSSToken_Symbol && aInAtRule &&
|
||||
(mToken.mSymbol == '{' || mToken.mSymbol == ';')) {
|
||||
(mToken.mSymbol == '{' || mToken.mSymbol == ';' || mToken.mSymbol == '}')) {
|
||||
UngetToken();
|
||||
hitStop = true;
|
||||
}
|
||||
@ -1993,9 +2001,8 @@ CSSParserImpl::ParseGroupRule(css::GroupRule* aRule,
|
||||
break;
|
||||
}
|
||||
if (eCSSToken_AtKeyword == mToken.mType) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEGroupRuleNestedAtRule);
|
||||
OUTPUT_ERROR();
|
||||
SkipAtRule(true); // group rules cannot contain @rules
|
||||
// Parse for nested rules
|
||||
ParseAtRule(aAppendFunc, aData, true);
|
||||
continue;
|
||||
}
|
||||
UngetToken();
|
||||
@ -2040,13 +2047,19 @@ CSSParserImpl::ParseMozDocumentRule(RuleAppendFunc aAppendFunc, void* aData)
|
||||
css::DocumentRule::URL *urls = nsnull;
|
||||
css::DocumentRule::URL **next = &urls;
|
||||
do {
|
||||
if (!GetToken(true) ||
|
||||
!(eCSSToken_URL == mToken.mType ||
|
||||
if (!GetToken(true)) {
|
||||
REPORT_UNEXPECTED_EOF(PEMozDocRuleEOF);
|
||||
delete urls;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(eCSSToken_URL == mToken.mType ||
|
||||
(eCSSToken_Function == mToken.mType &&
|
||||
(mToken.mIdent.LowerCaseEqualsLiteral("url-prefix") ||
|
||||
mToken.mIdent.LowerCaseEqualsLiteral("domain") ||
|
||||
mToken.mIdent.LowerCaseEqualsLiteral("regexp"))))) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEMozDocRuleBadFunc);
|
||||
UngetToken();
|
||||
delete urls;
|
||||
return false;
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ _TEST_FILES = test_acid3_test46.html \
|
||||
test_bug470769.html \
|
||||
test_bug499655.html \
|
||||
test_bug499655.xhtml \
|
||||
test_bug511909.html \
|
||||
test_bug517224.html \
|
||||
test_bug524175.html \
|
||||
test_bug534804.html \
|
||||
|
205
layout/style/test/test_bug511909.html
Normal file
205
layout/style/test/test_bug511909.html
Normal file
@ -0,0 +1,205 @@
|
||||
<html><!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=511909
|
||||
--><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>@media and @-moz-document testcases</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
|
||||
|
||||
<style type="text/css">
|
||||
a {
|
||||
font-weight: bold;
|
||||
}
|
||||
#pink {
|
||||
color: pink;
|
||||
}
|
||||
|
||||
#green {
|
||||
color: green;
|
||||
}
|
||||
|
||||
#blue {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
|
||||
pre {
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style type="text/css">
|
||||
@-moz-document regexp(".*test_bug511909.*"){
|
||||
#d {
|
||||
color: pink;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
@media screen {
|
||||
#m {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
@-moz-document regexp(".*test_bug511909.*"){
|
||||
@media screen {
|
||||
#dm {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<!-- should parse -->
|
||||
<style type="text/css">
|
||||
|
||||
@media print {
|
||||
@-moz-document regexp("not_this_url"),}
|
||||
#mx {
|
||||
color: pink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<!-- should parse -->
|
||||
<style type="text/css">
|
||||
|
||||
@-moz-document regexp("not_this_url"){
|
||||
@media print ,}
|
||||
#mxx {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
@media screen {
|
||||
@-moz-document regexp(".*test_bug511909.*"){
|
||||
#md {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
@media screen {
|
||||
@-moz-document regexp(".*test_bug511909.*"){
|
||||
@media screen {
|
||||
@-moz-document regexp(".*test_bug511909.*"){
|
||||
@media screen {
|
||||
#me {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=511909">Mozilla Bug 511909</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(function() {
|
||||
var pink = getComputedStyle(document.getElementById("pink"), "");
|
||||
var green = getComputedStyle(document.getElementById("green"), "");
|
||||
var blue = getComputedStyle(document.getElementById("blue"), "");
|
||||
|
||||
var cs1 = getComputedStyle(document.getElementById("d"), "");
|
||||
var cs2 = getComputedStyle(document.getElementById("m"), "");
|
||||
var cs3 = getComputedStyle(document.getElementById("dm"), "");
|
||||
var cs4 = getComputedStyle(document.getElementById("md"), "");
|
||||
var cs5 = getComputedStyle(document.getElementById("mx"), "");
|
||||
var cs6 = getComputedStyle(document.getElementById("mxx"), "");
|
||||
var cs7 = getComputedStyle(document.getElementById("me"), "");
|
||||
|
||||
is(cs1.color, pink.color, "@-moz-document applies");
|
||||
is(cs2.color, green.color, "@media applies");
|
||||
is(cs3.color, blue.color, "@media nested in @-moz-document applies");
|
||||
is(cs4.color, green.color, "@-moz-document nested in @media applies");
|
||||
is(cs5.color, pink.color, "broken @media nested in @-moz-document correctly handled");
|
||||
is(cs6.color, blue.color, "broken @-moz-document nested in @media correctly handled");
|
||||
is(cs7.color, blue.color, "@media nested in @-moz-document nested in @media applies");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
<div>
|
||||
<pre>default style
|
||||
</pre>
|
||||
<a id="pink">This line should be pink</a><br>
|
||||
|
||||
<a id="green">This line should be green</a><br>
|
||||
|
||||
<a id="blue">This line should be blue</a><br>
|
||||
|
||||
<pre>@-moz-document {...}
|
||||
</pre>
|
||||
<a id="d">This line should be pink</a><br>
|
||||
<pre>@media screen {...}
|
||||
</pre>
|
||||
<a id="m">This line should be green</a><br>
|
||||
<pre>@-moz-document {
|
||||
@media screen {...}
|
||||
}
|
||||
</pre>
|
||||
<a id="dm">This line should be blue</a><br>
|
||||
<pre>@media print {
|
||||
@-moz-document regexp("not_this_url"),}
|
||||
#mx {
|
||||
color: pink;
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<a id="mx">This line should be pink</a><br></div>
|
||||
<pre>@-moz-document regexp("not_this_url"){
|
||||
@media print ,}
|
||||
#mxx {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<a id="mxx">This line should be blue</a><br>
|
||||
<pre>@media screen {
|
||||
@-moz-documen {...}
|
||||
}
|
||||
</pre>
|
||||
<a id="md">This line should be green</a><br>
|
||||
<pre>@media screen {
|
||||
@-moz-document {
|
||||
@media screen {...}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<a id="me">This line should be blue</a><br>
|
||||
|
||||
|
||||
</body></html>
|
@ -55,7 +55,7 @@ _BROWSER_FILES = \
|
||||
remote_forms.js \
|
||||
remote_formsZoom.js \
|
||||
remote_vkb.js \
|
||||
browser_addons.js \
|
||||
$(warning browser_addons.js disabled due to failures - bug 710956) \
|
||||
browser_addons_locales.js \
|
||||
browser_appmenu.js \
|
||||
browser_autocompletesearch.js \
|
||||
|
@ -281,6 +281,9 @@ NS_IMETHODIMP nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight
|
||||
DoSetWindowDimensions(aWidth, aHeight);
|
||||
} else {
|
||||
mDelayedResize.SizeTo(aWidth, aHeight);
|
||||
if (mPresShell && mPresShell->GetDocument()) {
|
||||
mPresShell->GetDocument()->SetNeedStyleFlush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user