mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-05 08:35:26 +00:00
Merge mozilla-central into electrolysis.
This commit is contained in:
commit
20b787e19d
@ -55,11 +55,11 @@
|
|||||||
class nsIPresShell;
|
class nsIPresShell;
|
||||||
|
|
||||||
#define NS_ACCEVENT_IMPL_CID \
|
#define NS_ACCEVENT_IMPL_CID \
|
||||||
{ /* 55b89892-a83d-4252-ba78-cbdf53a86936 */ \
|
{ /* 39bde096-317e-4294-b23b-4af4a9b283f7 */ \
|
||||||
0x55b89892, \
|
0x39bde096, \
|
||||||
0xa83d, \
|
0x317e, \
|
||||||
0x4252, \
|
0x4294, \
|
||||||
{ 0xba, 0x78, 0xcb, 0xdf, 0x53, 0xa8, 0x69, 0x36 } \
|
{ 0xb2, 0x3b, 0x4a, 0xf4, 0xa9, 0xb2, 0x83, 0xf7 } \
|
||||||
}
|
}
|
||||||
|
|
||||||
class nsAccEvent: public nsIAccessibleEvent
|
class nsAccEvent: public nsIAccessibleEvent
|
||||||
@ -100,6 +100,12 @@ public:
|
|||||||
|
|
||||||
NS_DECL_NSIACCESSIBLEEVENT
|
NS_DECL_NSIACCESSIBLEEVENT
|
||||||
|
|
||||||
|
// nsAccEvent
|
||||||
|
PRUint32 GetEventType() const { return mEventType; }
|
||||||
|
EEventRule GetEventRule() const { return mEventRule; }
|
||||||
|
PRBool IsAsync() const { return mIsAsync; }
|
||||||
|
PRBool IsFromUserInput() const { return mIsFromUserInput; }
|
||||||
|
|
||||||
static void GetLastEventAttributes(nsIDOMNode *aNode,
|
static void GetLastEventAttributes(nsIDOMNode *aNode,
|
||||||
nsIPersistentProperties *aAttributes);
|
nsIPersistentProperties *aAttributes);
|
||||||
|
|
||||||
@ -121,27 +127,6 @@ private:
|
|||||||
static nsIDOMNode* gLastEventNodeWeak;
|
static nsIDOMNode* gLastEventNodeWeak;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static PRUint32 EventType(nsIAccessibleEvent *aAccEvent) {
|
|
||||||
PRUint32 eventType;
|
|
||||||
aAccEvent->GetEventType(&eventType);
|
|
||||||
return eventType;
|
|
||||||
}
|
|
||||||
static EEventRule EventRule(nsIAccessibleEvent *aAccEvent) {
|
|
||||||
nsRefPtr<nsAccEvent> accEvent =
|
|
||||||
nsAccUtils::QueryObject<nsAccEvent>(aAccEvent);
|
|
||||||
return accEvent->mEventRule;
|
|
||||||
}
|
|
||||||
static PRBool IsAsyncEvent(nsIAccessibleEvent *aAccEvent) {
|
|
||||||
nsRefPtr<nsAccEvent> accEvent =
|
|
||||||
nsAccUtils::QueryObject<nsAccEvent>(aAccEvent);
|
|
||||||
return accEvent->mIsAsync;
|
|
||||||
}
|
|
||||||
static PRBool IsFromUserInput(nsIAccessibleEvent *aAccEvent) {
|
|
||||||
PRBool isFromUserInput;
|
|
||||||
aAccEvent->GetIsFromUserInput(&isFromUserInput);
|
|
||||||
return isFromUserInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ResetLastInputState()
|
static void ResetLastInputState()
|
||||||
{gLastEventFromUserInput = PR_FALSE; gLastEventNodeWeak = nsnull; }
|
{gLastEventFromUserInput = PR_FALSE; gLastEventNodeWeak = nsnull; }
|
||||||
|
|
||||||
|
@ -1681,19 +1681,21 @@ nsDocAccessible::FlushPendingEvents()
|
|||||||
if (!mWeakShell)
|
if (!mWeakShell)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
nsCOMPtr<nsIAccessibleEvent> accessibleEvent(mEventsToFire[index]);
|
nsAccEvent *accEvent = mEventsToFire[index];
|
||||||
|
|
||||||
if (nsAccEvent::EventRule(accessibleEvent) == nsAccEvent::eDoNotEmit)
|
if (accEvent->GetEventRule() == nsAccEvent::eDoNotEmit)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
nsCOMPtr<nsIAccessible> accessible;
|
nsCOMPtr<nsIAccessible> accessible;
|
||||||
accessibleEvent->GetAccessible(getter_AddRefs(accessible));
|
accEvent->GetAccessible(getter_AddRefs(accessible));
|
||||||
nsCOMPtr<nsIDOMNode> domNode;
|
|
||||||
accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
|
nsCOMPtr<nsIDOMNode> domNode;
|
||||||
PRUint32 eventType = nsAccEvent::EventType(accessibleEvent);
|
accEvent->GetDOMNode(getter_AddRefs(domNode));
|
||||||
PRBool isFromUserInput = nsAccEvent::IsFromUserInput(accessibleEvent);
|
|
||||||
|
PRUint32 eventType = accEvent->GetEventType();
|
||||||
|
PRBool isFromUserInput = accEvent->IsFromUserInput();
|
||||||
|
PRBool isAsync = accEvent->IsAsync();
|
||||||
|
|
||||||
PRBool isAsync = nsAccEvent::IsAsyncEvent(accessibleEvent);
|
|
||||||
if (domNode == gLastFocusedNode && isAsync &&
|
if (domNode == gLastFocusedNode && isAsync &&
|
||||||
(eventType == nsIAccessibleEvent::EVENT_SHOW ||
|
(eventType == nsIAccessibleEvent::EVENT_SHOW ||
|
||||||
eventType == nsIAccessibleEvent::EVENT_HIDE)) {
|
eventType == nsIAccessibleEvent::EVENT_HIDE)) {
|
||||||
@ -1812,24 +1814,24 @@ nsDocAccessible::FlushPendingEvents()
|
|||||||
// Fire reorder event if it's unconditional (see InvalidateCacheSubtree
|
// Fire reorder event if it's unconditional (see InvalidateCacheSubtree
|
||||||
// method) or if changed node (that is the reason of this reorder event)
|
// method) or if changed node (that is the reason of this reorder event)
|
||||||
// is accessible or has accessible children.
|
// is accessible or has accessible children.
|
||||||
nsCOMPtr<nsAccReorderEvent> reorderEvent = do_QueryInterface(accessibleEvent);
|
nsCOMPtr<nsAccReorderEvent> reorderEvent = do_QueryInterface(accEvent);
|
||||||
if (reorderEvent->IsUnconditionalEvent() ||
|
if (reorderEvent->IsUnconditionalEvent() ||
|
||||||
reorderEvent->HasAccessibleInReasonSubtree()) {
|
reorderEvent->HasAccessibleInReasonSubtree()) {
|
||||||
nsAccEvent::PrepareForEvent(accessibleEvent);
|
nsAccEvent::PrepareForEvent(accEvent);
|
||||||
FireAccessibleEvent(accessibleEvent);
|
FireAccessibleEvent(accEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// The input state was previously stored with the nsIAccessibleEvent,
|
// The input state was previously stored with the nsIAccessibleEvent,
|
||||||
// so use that state now when firing the event
|
// so use that state now when firing the event
|
||||||
nsAccEvent::PrepareForEvent(accessibleEvent);
|
nsAccEvent::PrepareForEvent(accEvent);
|
||||||
FireAccessibleEvent(accessibleEvent);
|
FireAccessibleEvent(accEvent);
|
||||||
// Post event processing
|
// Post event processing
|
||||||
if (eventType == nsIAccessibleEvent::EVENT_HIDE) {
|
if (eventType == nsIAccessibleEvent::EVENT_HIDE) {
|
||||||
// Shutdown nsIAccessNode's or nsIAccessibles for any DOM nodes in
|
// Shutdown nsIAccessNode's or nsIAccessibles for any DOM nodes in
|
||||||
// this subtree.
|
// this subtree.
|
||||||
nsCOMPtr<nsIDOMNode> hidingNode;
|
nsCOMPtr<nsIDOMNode> hidingNode;
|
||||||
accessibleEvent->GetDOMNode(getter_AddRefs(hidingNode));
|
accEvent->GetDOMNode(getter_AddRefs(hidingNode));
|
||||||
if (hidingNode) {
|
if (hidingNode) {
|
||||||
RefreshNodes(hidingNode); // Will this bite us with asynch events
|
RefreshNodes(hidingNode); // Will this bite us with asynch events
|
||||||
}
|
}
|
||||||
|
@ -432,20 +432,8 @@ __try {
|
|||||||
groupLevel);
|
groupLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!description.IsEmpty()) {
|
if (description.IsEmpty())
|
||||||
*pszDescription = ::SysAllocStringLen(description.get(),
|
xpAccessible->GetDescription(description);
|
||||||
description.Length());
|
|
||||||
return *pszDescription ? S_OK : E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
xpAccessible->GetDescription(description);
|
|
||||||
if (!description.IsEmpty()) {
|
|
||||||
// Signal to screen readers that this description is speakable
|
|
||||||
// and is not a formatted positional information description
|
|
||||||
// Don't localize the "Description: " part of this string, it will be
|
|
||||||
// parsed out by assistive technologies.
|
|
||||||
description = NS_LITERAL_STRING("Description: ") + description;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pszDescription = ::SysAllocStringLen(description.get(),
|
*pszDescription = ::SysAllocStringLen(description.get(),
|
||||||
description.Length());
|
description.Length());
|
||||||
|
@ -78,6 +78,7 @@
|
|||||||
<menupopup id="menu_HelpPopup" onpopupshowing="buildHelpMenu();">
|
<menupopup id="menu_HelpPopup" onpopupshowing="buildHelpMenu();">
|
||||||
<menuitem id="menu_openHelp"
|
<menuitem id="menu_openHelp"
|
||||||
oncommand="openHelpLink('firefox-help')"
|
oncommand="openHelpLink('firefox-help')"
|
||||||
|
onclick="checkForMiddleClick(this, event);"
|
||||||
label="&productHelp.label;"
|
label="&productHelp.label;"
|
||||||
accesskey="&productHelp.accesskey;"
|
accesskey="&productHelp.accesskey;"
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
@ -89,7 +90,8 @@
|
|||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
<menuitem label="&helpForIEUsers.label;"
|
<menuitem label="&helpForIEUsers.label;"
|
||||||
accesskey="&helpForIEUsers.accesskey;"
|
accesskey="&helpForIEUsers.accesskey;"
|
||||||
oncommand="openHelpLink('ieusers');"/>
|
oncommand="openHelpLink('ieusers');"
|
||||||
|
onclick="checkForMiddleClick(this, event);"/>
|
||||||
#endif
|
#endif
|
||||||
<menuitem id="troubleShooting"
|
<menuitem id="troubleShooting"
|
||||||
accesskey="&helpTroubleshootingInfo.accesskey;"
|
accesskey="&helpTroubleshootingInfo.accesskey;"
|
||||||
|
@ -814,7 +814,7 @@ var allTabs = {
|
|||||||
|
|
||||||
while (this.container.hasChildNodes())
|
while (this.container.hasChildNodes())
|
||||||
this.container.removeChild(this.container.firstChild);
|
this.container.removeChild(this.container.firstChild);
|
||||||
for (let i = 0; i < rows; i++)
|
for (let i = rows || 1; i > 0; i--)
|
||||||
this.container.appendChild(document.createElement("hbox"));
|
this.container.appendChild(document.createElement("hbox"));
|
||||||
|
|
||||||
var row = this.container.firstChild;
|
var row = this.container.firstChild;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -46,18 +46,19 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
from getopt import getopt
|
from getopt import getopt
|
||||||
import automation
|
from automation import Automation
|
||||||
|
|
||||||
PORT = 8888
|
PORT = 8888
|
||||||
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
|
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
|
||||||
PROFILE_DIRECTORY = os.path.abspath(os.path.join(SCRIPT_DIR, "./leakprofile"))
|
PROFILE_DIRECTORY = os.path.abspath(os.path.join(SCRIPT_DIR, "./leakprofile"))
|
||||||
DIST_BIN = os.path.join(SCRIPT_DIR, automation.DIST_BIN)
|
|
||||||
os.chdir(SCRIPT_DIR)
|
os.chdir(SCRIPT_DIR)
|
||||||
|
|
||||||
class EasyServer(SocketServer.TCPServer):
|
class EasyServer(SocketServer.TCPServer):
|
||||||
allow_reuse_address = True
|
allow_reuse_address = True
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
automation = Automation()
|
||||||
|
DIST_BIN = os.path.join(SCRIPT_DIR, automation.DIST_BIN)
|
||||||
opts, extraArgs = getopt(sys.argv[1:], 'l:')
|
opts, extraArgs = getopt(sys.argv[1:], 'l:')
|
||||||
if len(opts) > 0:
|
if len(opts) > 0:
|
||||||
try:
|
try:
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
#
|
#
|
||||||
# ***** END LICENSE BLOCK *****
|
# ***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
import automation
|
from automation import Automation
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
@ -47,6 +47,8 @@ import sys
|
|||||||
#expand PROFILE_DIR = __PROFILE_DIR__
|
#expand PROFILE_DIR = __PROFILE_DIR__
|
||||||
#expand CERTS_SRC_DIR = __CERTS_SRC_DIR__
|
#expand CERTS_SRC_DIR = __CERTS_SRC_DIR__
|
||||||
|
|
||||||
|
automation = Automation()
|
||||||
|
|
||||||
dbFiles = [
|
dbFiles = [
|
||||||
re.compile("^cert[0-9]+\.db$"),
|
re.compile("^cert[0-9]+\.db$"),
|
||||||
re.compile("^key[0-9]+\.db$"),
|
re.compile("^key[0-9]+\.db$"),
|
||||||
|
@ -46,7 +46,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import automation
|
from automation import Automation
|
||||||
|
|
||||||
PORT = 8888
|
PORT = 8888
|
||||||
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
|
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
|
||||||
@ -57,6 +57,7 @@ class EasyServer(SocketServer.TCPServer):
|
|||||||
allow_reuse_address = True
|
allow_reuse_address = True
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
automation = Automation()
|
||||||
httpd = EasyServer(("", PORT), SimpleHTTPServer.SimpleHTTPRequestHandler)
|
httpd = EasyServer(("", PORT), SimpleHTTPServer.SimpleHTTPRequestHandler)
|
||||||
t = threading.Thread(target=httpd.serve_forever)
|
t = threading.Thread(target=httpd.serve_forever)
|
||||||
t.setDaemon(True) # don't hang on exit
|
t.setDaemon(True) # don't hang on exit
|
||||||
|
@ -258,10 +258,15 @@ copydir( char *from, char *to, mode_t mode, char *group, char *owner,
|
|||||||
sprintf(destdir, "%s%s%s", to, _DIRECTORY_SEPARATOR, base);
|
sprintf(destdir, "%s%s%s", to, _DIRECTORY_SEPARATOR, base);
|
||||||
if (mkdirs(destdir, mode) != 0) {
|
if (mkdirs(destdir, mode) != 0) {
|
||||||
fail("cannot make directory %s\n", destdir);
|
fail("cannot make directory %s\n", destdir);
|
||||||
|
free(destdir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = opendir(from);
|
if (!(dir = opendir(from))) {
|
||||||
|
fail("cannot open directory %s\n", from);
|
||||||
|
free(destdir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
direntry = xmalloc((unsigned int)PATH_MAX);
|
direntry = xmalloc((unsigned int)PATH_MAX);
|
||||||
destentry = xmalloc((unsigned int)PATH_MAX);
|
destentry = xmalloc((unsigned int)PATH_MAX);
|
||||||
@ -280,6 +285,7 @@ copydir( char *from, char *to, mode_t mode, char *group, char *owner,
|
|||||||
copyfile( direntry, destentry, mode, group, owner, dotimes, uid, gid );
|
copyfile( direntry, destentry, mode, group, owner, dotimes, uid, gid );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(destdir);
|
||||||
free(direntry);
|
free(direntry);
|
||||||
free(destentry);
|
free(destentry);
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
@ -233,7 +233,7 @@ nsTextNode::List(FILE* out, PRInt32 aIndent) const
|
|||||||
PRInt32 index;
|
PRInt32 index;
|
||||||
for (index = aIndent; --index >= 0; ) fputs(" ", out);
|
for (index = aIndent; --index >= 0; ) fputs(" ", out);
|
||||||
|
|
||||||
fprintf(out, "Text@%p", this);
|
fprintf(out, "Text@%p", static_cast<const void*>(this));
|
||||||
fprintf(out, " intrinsicstate=[%08x]", IntrinsicState());
|
fprintf(out, " intrinsicstate=[%08x]", IntrinsicState());
|
||||||
fprintf(out, " refcount=%d<", mRefCnt.get());
|
fprintf(out, " refcount=%d<", mRefCnt.get());
|
||||||
|
|
||||||
|
@ -151,7 +151,8 @@ NS_IMETHODIMP
|
|||||||
nsSVGStringProxyValue::SetValueString(const nsAString& aValue)
|
nsSVGStringProxyValue::SetValueString(const nsAString& aValue)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("nsSVGStringProxyValue(%p)::SetValueString(%s)\n", this, NS_ConvertUTF16toUTF8(aValue).get());
|
printf("nsSVGStringProxyValue(%p)::SetValueString(%s)\n",
|
||||||
|
static_cast<void*>(this), NS_ConvertUTF16toUTF8(aValue).get());
|
||||||
#endif
|
#endif
|
||||||
if (NS_FAILED(mProxiedValue->SetValueString(aValue))) {
|
if (NS_FAILED(mProxiedValue->SetValueString(aValue))) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -445,8 +445,6 @@
|
|||||||
// Drag and drop
|
// Drag and drop
|
||||||
#include "nsIDOMDataTransfer.h"
|
#include "nsIDOMDataTransfer.h"
|
||||||
|
|
||||||
// Offline includes
|
|
||||||
#include "nsIDOMLoadStatus.h"
|
|
||||||
// Geolocation
|
// Geolocation
|
||||||
#include "nsIDOMGeoGeolocation.h"
|
#include "nsIDOMGeoGeolocation.h"
|
||||||
#include "nsIDOMGeoPosition.h"
|
#include "nsIDOMGeoPosition.h"
|
||||||
@ -1140,8 +1138,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||||
NS_DEFINE_CLASSINFO_DATA(SVGTransformList, nsDOMGenericSH,
|
NS_DEFINE_CLASSINFO_DATA(SVGTransformList, nsDOMGenericSH,
|
||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||||
NS_DEFINE_CLASSINFO_DATA(SVGUnitTypes, nsDOMGenericSH,
|
|
||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
|
||||||
NS_DEFINE_CLASSINFO_DATA(SVGZoomEvent, nsDOMGenericSH,
|
NS_DEFINE_CLASSINFO_DATA(SVGZoomEvent, nsDOMGenericSH,
|
||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||||
#endif // MOZ_SVG
|
#endif // MOZ_SVG
|
||||||
@ -1208,12 +1204,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||||||
NS_DEFINE_CLASSINFO_DATA(StorageEvent, nsDOMGenericSH,
|
NS_DEFINE_CLASSINFO_DATA(StorageEvent, nsDOMGenericSH,
|
||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||||
|
|
||||||
// We just want this to have classinfo so it gets mark callbacks for marking
|
|
||||||
// event listeners.
|
|
||||||
// We really don't want any of the default flags!
|
|
||||||
NS_DEFINE_CLASSINFO_DATA(WindowRoot, nsEventReceiverSH,
|
|
||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
|
||||||
|
|
||||||
NS_DEFINE_CLASSINFO_DATA(DOMParser, nsDOMGenericSH,
|
NS_DEFINE_CLASSINFO_DATA(DOMParser, nsDOMGenericSH,
|
||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||||
NS_DEFINE_CLASSINFO_DATA(XMLSerializer, nsDOMGenericSH,
|
NS_DEFINE_CLASSINFO_DATA(XMLSerializer, nsDOMGenericSH,
|
||||||
@ -1242,9 +1232,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||||||
NS_DEFINE_CLASSINFO_DATA(OfflineResourceList, nsOfflineResourceListSH,
|
NS_DEFINE_CLASSINFO_DATA(OfflineResourceList, nsOfflineResourceListSH,
|
||||||
ARRAY_SCRIPTABLE_FLAGS)
|
ARRAY_SCRIPTABLE_FLAGS)
|
||||||
|
|
||||||
NS_DEFINE_CLASSINFO_DATA(LoadStatus, nsDOMGenericSH,
|
|
||||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
|
||||||
|
|
||||||
NS_DEFINE_CLASSINFO_DATA(FileList, nsFileListSH,
|
NS_DEFINE_CLASSINFO_DATA(FileList, nsFileListSH,
|
||||||
ARRAY_SCRIPTABLE_FLAGS)
|
ARRAY_SCRIPTABLE_FLAGS)
|
||||||
NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH,
|
NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH,
|
||||||
@ -3458,10 +3445,6 @@ nsDOMClassInfo::Init()
|
|||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTransformList)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTransformList)
|
||||||
DOM_CLASSINFO_MAP_END
|
DOM_CLASSINFO_MAP_END
|
||||||
|
|
||||||
DOM_CLASSINFO_MAP_BEGIN(SVGUnitTypes, nsIDOMSVGUnitTypes)
|
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUnitTypes)
|
|
||||||
DOM_CLASSINFO_MAP_END
|
|
||||||
|
|
||||||
DOM_CLASSINFO_MAP_BEGIN(SVGZoomEvent, nsIDOMSVGZoomEvent)
|
DOM_CLASSINFO_MAP_BEGIN(SVGZoomEvent, nsIDOMSVGZoomEvent)
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGZoomEvent)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGZoomEvent)
|
||||||
DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
|
DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
|
||||||
@ -3538,11 +3521,6 @@ nsDOMClassInfo::Init()
|
|||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageEvent)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageEvent)
|
||||||
DOM_CLASSINFO_MAP_END
|
DOM_CLASSINFO_MAP_END
|
||||||
|
|
||||||
// We just want this to have classinfo so it gets mark callbacks for marking
|
|
||||||
// event listeners.
|
|
||||||
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(WindowRoot, nsISupports)
|
|
||||||
DOM_CLASSINFO_MAP_END
|
|
||||||
|
|
||||||
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMParser, nsIDOMParser)
|
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMParser, nsIDOMParser)
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMParser)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMParser)
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMParserJS)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMParserJS)
|
||||||
@ -3590,10 +3568,6 @@ nsDOMClassInfo::Init()
|
|||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
|
||||||
DOM_CLASSINFO_MAP_END
|
DOM_CLASSINFO_MAP_END
|
||||||
|
|
||||||
DOM_CLASSINFO_MAP_BEGIN(LoadStatus, nsIDOMLoadStatus)
|
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMLoadStatus)
|
|
||||||
DOM_CLASSINFO_MAP_END
|
|
||||||
|
|
||||||
DOM_CLASSINFO_MAP_BEGIN(ClientRect, nsIDOMClientRect)
|
DOM_CLASSINFO_MAP_BEGIN(ClientRect, nsIDOMClientRect)
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMClientRect)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMClientRect)
|
||||||
DOM_CLASSINFO_MAP_END
|
DOM_CLASSINFO_MAP_END
|
||||||
|
@ -348,7 +348,6 @@ enum nsDOMClassInfoID {
|
|||||||
eDOMClassInfo_SVGRect_id,
|
eDOMClassInfo_SVGRect_id,
|
||||||
eDOMClassInfo_SVGTransform_id,
|
eDOMClassInfo_SVGTransform_id,
|
||||||
eDOMClassInfo_SVGTransformList_id,
|
eDOMClassInfo_SVGTransformList_id,
|
||||||
eDOMClassInfo_SVGUnitTypes_id,
|
|
||||||
eDOMClassInfo_SVGZoomEvent_id,
|
eDOMClassInfo_SVGZoomEvent_id,
|
||||||
#endif // MOZ_SVG
|
#endif // MOZ_SVG
|
||||||
|
|
||||||
@ -385,8 +384,6 @@ enum nsDOMClassInfoID {
|
|||||||
eDOMClassInfo_StorageItem_id,
|
eDOMClassInfo_StorageItem_id,
|
||||||
eDOMClassInfo_StorageEvent_id,
|
eDOMClassInfo_StorageEvent_id,
|
||||||
|
|
||||||
eDOMClassInfo_WindowRoot_id,
|
|
||||||
|
|
||||||
// DOMParser, XMLSerializer
|
// DOMParser, XMLSerializer
|
||||||
eDOMClassInfo_DOMParser_id,
|
eDOMClassInfo_DOMParser_id,
|
||||||
eDOMClassInfo_XMLSerializer_id,
|
eDOMClassInfo_XMLSerializer_id,
|
||||||
@ -410,7 +407,6 @@ enum nsDOMClassInfoID {
|
|||||||
eDOMClassInfo_XULCommandEvent_id,
|
eDOMClassInfo_XULCommandEvent_id,
|
||||||
eDOMClassInfo_CommandEvent_id,
|
eDOMClassInfo_CommandEvent_id,
|
||||||
eDOMClassInfo_OfflineResourceList_id,
|
eDOMClassInfo_OfflineResourceList_id,
|
||||||
eDOMClassInfo_LoadStatus_id,
|
|
||||||
|
|
||||||
eDOMClassInfo_FileList_id,
|
eDOMClassInfo_FileList_id,
|
||||||
eDOMClassInfo_File_id,
|
eDOMClassInfo_File_id,
|
||||||
|
@ -103,7 +103,7 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
|
|||||||
{
|
{
|
||||||
char* nodename = ToNewCString(mTag);
|
char* nodename = ToNewCString(mTag);
|
||||||
printf("Do Create Element parent = %p <%s>, offset = %d\n",
|
printf("Do Create Element parent = %p <%s>, offset = %d\n",
|
||||||
mParent.get(), nodename, mOffsetInParent);
|
static_cast<void*>(mParent.get()), nodename, mOffsetInParent);
|
||||||
nsMemory::Free(nodename);
|
nsMemory::Free(nodename);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -126,7 +126,10 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
|
|||||||
if (!mNewNode) return NS_ERROR_NULL_POINTER;
|
if (!mNewNode) return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf(" newNode = %p\n", mNewNode.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf(" newNode = %p\n", static_cast<void*>(mNewNode.get()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// insert the new node
|
// insert the new node
|
||||||
@ -180,8 +183,12 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
|
|||||||
NS_IMETHODIMP CreateElementTxn::UndoTransaction(void)
|
NS_IMETHODIMP CreateElementTxn::UndoTransaction(void)
|
||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("Undo Create Element, mParent = %p, node = %p\n",
|
if (gNoisy)
|
||||||
mParent.get(), mNewNode.get()); }
|
{
|
||||||
|
printf("Undo Create Element, mParent = %p, node = %p\n",
|
||||||
|
static_cast<void*>(mParent.get()),
|
||||||
|
static_cast<void*>(mNewNode.get()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_ASSERTION(mEditor && mParent, "bad state");
|
NS_ASSERTION(mEditor && mParent, "bad state");
|
||||||
|
@ -98,7 +98,12 @@ NS_IMETHODIMP DeleteElementTxn::Init(nsIEditor *aEditor,
|
|||||||
NS_IMETHODIMP DeleteElementTxn::DoTransaction(void)
|
NS_IMETHODIMP DeleteElementTxn::DoTransaction(void)
|
||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("%p Do Delete Element element = %p\n", this, mElement.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf("%p Do Delete Element element = %p\n",
|
||||||
|
static_cast<void*>(this),
|
||||||
|
static_cast<void*>(mElement.get()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!mElement) return NS_ERROR_NOT_INITIALIZED;
|
if (!mElement) return NS_ERROR_NOT_INITIALIZED;
|
||||||
@ -144,7 +149,13 @@ NS_IMETHODIMP DeleteElementTxn::DoTransaction(void)
|
|||||||
NS_IMETHODIMP DeleteElementTxn::UndoTransaction(void)
|
NS_IMETHODIMP DeleteElementTxn::UndoTransaction(void)
|
||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("%p Undo Delete Element element = %p, parent = %p\n", this, mElement.get(), mParent.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf("%p Undo Delete Element element = %p, parent = %p\n",
|
||||||
|
static_cast<void*>(this),
|
||||||
|
static_cast<void*>(mElement.get()),
|
||||||
|
static_cast<void*>(mParent.get()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!mParent) { return NS_OK; } // this is a legal state, the txn is a no-op
|
if (!mParent) { return NS_OK; } // this is a legal state, the txn is a no-op
|
||||||
@ -181,7 +192,13 @@ NS_IMETHODIMP DeleteElementTxn::UndoTransaction(void)
|
|||||||
NS_IMETHODIMP DeleteElementTxn::RedoTransaction(void)
|
NS_IMETHODIMP DeleteElementTxn::RedoTransaction(void)
|
||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("%p Redo Delete Element element = %p, parent = %p\n", this, mElement.get(), mParent.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf("%p Redo Delete Element element = %p, parent = %p\n",
|
||||||
|
static_cast<void*>(this),
|
||||||
|
static_cast<void*>(mElement.get()),
|
||||||
|
static_cast<void*>(mParent.get()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!mParent) { return NS_OK; } // this is a legal state, the txn is a no-op
|
if (!mParent) { return NS_OK; } // this is a legal state, the txn is a no-op
|
||||||
|
@ -96,8 +96,11 @@ NS_IMETHODIMP InsertElementTxn::DoTransaction(void)
|
|||||||
mNode->GetNodeName(namestr);
|
mNode->GetNodeName(namestr);
|
||||||
char* nodename = ToNewCString(namestr);
|
char* nodename = ToNewCString(namestr);
|
||||||
printf("%p Do Insert Element of %p <%s> into parent %p at offset %d\n",
|
printf("%p Do Insert Element of %p <%s> into parent %p at offset %d\n",
|
||||||
this, nodeAsContent.get(), nodename,
|
static_cast<void*>(this),
|
||||||
parentAsContent.get(), mOffset);
|
static_cast<void*>(nodeAsContent.get()),
|
||||||
|
nodename,
|
||||||
|
static_cast<void*>(parentAsContent.get()),
|
||||||
|
mOffset);
|
||||||
nsMemory::Free(nodename);
|
nsMemory::Free(nodename);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -149,8 +152,14 @@ NS_IMETHODIMP InsertElementTxn::DoTransaction(void)
|
|||||||
NS_IMETHODIMP InsertElementTxn::UndoTransaction(void)
|
NS_IMETHODIMP InsertElementTxn::UndoTransaction(void)
|
||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("%p Undo Insert Element of %p into parent %p at offset %d\n",
|
if (gNoisy)
|
||||||
this, mNode.get(), mParent.get(), mOffset); }
|
{
|
||||||
|
printf("%p Undo Insert Element of %p into parent %p at offset %d\n",
|
||||||
|
static_cast<void*>(this),
|
||||||
|
static_cast<void*>(mNode.get()),
|
||||||
|
static_cast<void*>(mParent.get()),
|
||||||
|
mOffset);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!mNode || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
if (!mNode || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||||
|
@ -93,7 +93,11 @@ NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
|||||||
NS_IMETHODIMP InsertTextTxn::DoTransaction(void)
|
NS_IMETHODIMP InsertTextTxn::DoTransaction(void)
|
||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("Do Insert Text element = %p\n", mElement.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf("Do Insert Text element = %p\n",
|
||||||
|
static_cast<void*>(mElement.get()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_ASSERTION(mElement && mEditor, "bad state");
|
NS_ASSERTION(mElement && mEditor, "bad state");
|
||||||
@ -125,7 +129,11 @@ NS_IMETHODIMP InsertTextTxn::DoTransaction(void)
|
|||||||
NS_IMETHODIMP InsertTextTxn::UndoTransaction(void)
|
NS_IMETHODIMP InsertTextTxn::UndoTransaction(void)
|
||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("Undo Insert Text element = %p\n", mElement.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf("Undo Insert Text element = %p\n",
|
||||||
|
static_cast<void*>(mElement.get()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_ASSERTION(mElement && mEditor, "bad state");
|
NS_ASSERTION(mElement && mEditor, "bad state");
|
||||||
@ -156,7 +164,11 @@ NS_IMETHODIMP InsertTextTxn::Merge(nsITransaction *aTransaction, PRBool *aDidMer
|
|||||||
mStringToInsert += otherData;
|
mStringToInsert += otherData;
|
||||||
*aDidMerge = PR_TRUE;
|
*aDidMerge = PR_TRUE;
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("InsertTextTxn assimilated %p\n", aTransaction); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf("InsertTextTxn assimilated %p\n",
|
||||||
|
static_cast<void*>(aTransaction));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
NS_RELEASE(otherInsTxn);
|
NS_RELEASE(otherInsTxn);
|
||||||
|
@ -89,7 +89,13 @@ NS_IMETHODIMP JoinElementTxn::Init(nsEditor *aEditor,
|
|||||||
NS_IMETHODIMP JoinElementTxn::DoTransaction(void)
|
NS_IMETHODIMP JoinElementTxn::DoTransaction(void)
|
||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("%p Do Join of %p and %p\n", this, mLeftNode.get(), mRightNode.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf("%p Do Join of %p and %p\n",
|
||||||
|
static_cast<void*>(this),
|
||||||
|
static_cast<void*>(mLeftNode.get()),
|
||||||
|
static_cast<void*>(mRightNode.get()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_PRECONDITION((mEditor && mLeftNode && mRightNode), "null arg");
|
NS_PRECONDITION((mEditor && mLeftNode && mRightNode), "null arg");
|
||||||
@ -130,7 +136,11 @@ NS_IMETHODIMP JoinElementTxn::DoTransaction(void)
|
|||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (NS_SUCCEEDED(result))
|
if (NS_SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf(" left node = %p removed\n",
|
||||||
|
static_cast<void*>(mLeftNode.get()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -147,7 +157,12 @@ NS_IMETHODIMP JoinElementTxn::DoTransaction(void)
|
|||||||
NS_IMETHODIMP JoinElementTxn::UndoTransaction(void)
|
NS_IMETHODIMP JoinElementTxn::UndoTransaction(void)
|
||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("%p Undo Join, right node = %p\n", this, mRightNode.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf("%p Undo Join, right node = %p\n",
|
||||||
|
static_cast<void*>(this),
|
||||||
|
static_cast<void*>(mRightNode.get()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_ASSERTION(mRightNode && mLeftNode && mParent, "bad state");
|
NS_ASSERTION(mRightNode && mLeftNode && mParent, "bad state");
|
||||||
|
@ -83,7 +83,13 @@ NS_IMETHODIMP SplitElementTxn::Init(nsEditor *aEditor,
|
|||||||
NS_IMETHODIMP SplitElementTxn::DoTransaction(void)
|
NS_IMETHODIMP SplitElementTxn::DoTransaction(void)
|
||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf("%p Do Split of node %p offset %d\n", this, mExistingRightNode.get(), mOffset); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf("%p Do Split of node %p offset %d\n",
|
||||||
|
static_cast<void*>(this),
|
||||||
|
static_cast<void*>(mExistingRightNode.get()),
|
||||||
|
mOffset);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_ASSERTION(mExistingRightNode && mEditor, "bad state");
|
NS_ASSERTION(mExistingRightNode && mEditor, "bad state");
|
||||||
@ -97,7 +103,11 @@ NS_IMETHODIMP SplitElementTxn::DoTransaction(void)
|
|||||||
mEditor->MarkNodeDirty(mExistingRightNode);
|
mEditor->MarkNodeDirty(mExistingRightNode);
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) { printf(" created left node = %p\n", mNewLeftNode.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf(" created left node = %p\n",
|
||||||
|
static_cast<void*>(mNewLeftNode.get()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// get the parent node
|
// get the parent node
|
||||||
@ -125,8 +135,11 @@ NS_IMETHODIMP SplitElementTxn::UndoTransaction(void)
|
|||||||
{
|
{
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) {
|
if (gNoisy) {
|
||||||
printf("%p Undo Split of existing node %p and new node %p offset %d\n",
|
printf("%p Undo Split of existing node %p and new node %p offset %d\n",
|
||||||
this, mExistingRightNode.get(), mNewLeftNode.get(), mOffset);
|
static_cast<void*>(this),
|
||||||
|
static_cast<void*>(mExistingRightNode.get()),
|
||||||
|
static_cast<void*>(mNewLeftNode.get()),
|
||||||
|
mOffset);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -140,12 +153,18 @@ NS_IMETHODIMP SplitElementTxn::UndoTransaction(void)
|
|||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy)
|
if (gNoisy)
|
||||||
{
|
{
|
||||||
printf("** after join left child node %p into right node %p\n", mNewLeftNode.get(), mExistingRightNode.get());
|
printf("** after join left child node %p into right node %p\n",
|
||||||
|
static_cast<void*>(mNewLeftNode.get()),
|
||||||
|
static_cast<void*>(mExistingRightNode.get()));
|
||||||
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
|
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
|
||||||
}
|
}
|
||||||
if (NS_SUCCEEDED(result))
|
if (NS_SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
if (gNoisy) { printf(" left node = %p removed\n", mNewLeftNode.get()); }
|
if (gNoisy)
|
||||||
|
{
|
||||||
|
printf(" left node = %p removed\n",
|
||||||
|
static_cast<void*>(mNewLeftNode.get()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -164,8 +183,11 @@ NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
|
|||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy) {
|
if (gNoisy) {
|
||||||
printf("%p Redo Split of existing node %p and new node %p offset %d\n",
|
printf("%p Redo Split of existing node %p and new node %p offset %d\n",
|
||||||
this, mExistingRightNode.get(), mNewLeftNode.get(), mOffset);
|
static_cast<void*>(this),
|
||||||
|
static_cast<void*>(mExistingRightNode.get()),
|
||||||
|
static_cast<void*>(mNewLeftNode.get()),
|
||||||
|
mOffset);
|
||||||
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
|
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -180,7 +202,9 @@ NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
|
|||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy)
|
if (gNoisy)
|
||||||
{
|
{
|
||||||
printf("** after delete of text in right text node %p offset %d\n", rightNodeAsText.get(), mOffset);
|
printf("** after delete of text in right text node %p offset %d\n",
|
||||||
|
static_cast<void*>(rightNodeAsText.get()),
|
||||||
|
mOffset);
|
||||||
mEditor->DebugDumpContent(); // DEBUG
|
mEditor->DebugDumpContent(); // DEBUG
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -203,7 +227,10 @@ NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
|
|||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy)
|
if (gNoisy)
|
||||||
{
|
{
|
||||||
printf("** move child node %p from right node %p to left node %p\n", child.get(), mExistingRightNode.get(), mNewLeftNode.get());
|
printf("** move child node %p from right node %p to left node %p\n",
|
||||||
|
static_cast<void*>(child.get()),
|
||||||
|
static_cast<void*>(mExistingRightNode.get()),
|
||||||
|
static_cast<void*>(mNewLeftNode.get()));
|
||||||
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
|
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -216,7 +243,9 @@ NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
|
|||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
if (gNoisy)
|
if (gNoisy)
|
||||||
{
|
{
|
||||||
printf("** reinsert left child node %p before right node %p\n", mNewLeftNode.get(), mExistingRightNode.get());
|
printf("** reinsert left child node %p before right node %p\n",
|
||||||
|
static_cast<void*>(mNewLeftNode.get()),
|
||||||
|
static_cast<void*>(mExistingRightNode.get()));
|
||||||
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
|
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -85,6 +85,7 @@ public:
|
|||||||
SurfaceTypeOS2,
|
SurfaceTypeOS2,
|
||||||
SurfaceTypeWin32Printing,
|
SurfaceTypeWin32Printing,
|
||||||
SurfaceTypeQuartzImage,
|
SurfaceTypeQuartzImage,
|
||||||
|
SurfaceTypeScript,
|
||||||
SurfaceTypeQPainter,
|
SurfaceTypeQPainter,
|
||||||
SurfaceTypeDDraw
|
SurfaceTypeDDraw
|
||||||
} gfxSurfaceType;
|
} gfxSurfaceType;
|
||||||
|
@ -258,10 +258,15 @@ copydir( char *from, char *to, mode_t mode, char *group, char *owner,
|
|||||||
sprintf(destdir, "%s%s%s", to, _DIRECTORY_SEPARATOR, base);
|
sprintf(destdir, "%s%s%s", to, _DIRECTORY_SEPARATOR, base);
|
||||||
if (mkdirs(destdir, mode) != 0) {
|
if (mkdirs(destdir, mode) != 0) {
|
||||||
fail("cannot make directory %s\n", destdir);
|
fail("cannot make directory %s\n", destdir);
|
||||||
|
free(destdir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = opendir(from);
|
if (!(dir = opendir(from))) {
|
||||||
|
fail("cannot open directory %s\n", from);
|
||||||
|
free(destdir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
direntry = xmalloc((unsigned int)PATH_MAX);
|
direntry = xmalloc((unsigned int)PATH_MAX);
|
||||||
destentry = xmalloc((unsigned int)PATH_MAX);
|
destentry = xmalloc((unsigned int)PATH_MAX);
|
||||||
@ -280,6 +285,7 @@ copydir( char *from, char *to, mode_t mode, char *group, char *owner,
|
|||||||
copyfile( direntry, destentry, mode, group, owner, dotimes, uid, gid );
|
copyfile( direntry, destentry, mode, group, owner, dotimes, uid, gid );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(destdir);
|
||||||
free(direntry);
|
free(direntry);
|
||||||
free(destentry);
|
free(destentry);
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
@ -4383,17 +4383,17 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
|
|||||||
NS_NewTableCaptionFrame) },
|
NS_NewTableCaptionFrame) },
|
||||||
{ NS_STYLE_DISPLAY_TABLE_ROW_GROUP,
|
{ NS_STYLE_DISPLAY_TABLE_ROW_GROUP,
|
||||||
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
|
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
|
||||||
FCDATA_MAY_NEED_SCROLLFRAME | FCDATA_SKIP_ABSPOS_PUSH |
|
FCDATA_SKIP_ABSPOS_PUSH |
|
||||||
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
|
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
|
||||||
NS_NewTableRowGroupFrame) },
|
NS_NewTableRowGroupFrame) },
|
||||||
{ NS_STYLE_DISPLAY_TABLE_HEADER_GROUP,
|
{ NS_STYLE_DISPLAY_TABLE_HEADER_GROUP,
|
||||||
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
|
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
|
||||||
FCDATA_MAY_NEED_SCROLLFRAME | FCDATA_SKIP_ABSPOS_PUSH |
|
FCDATA_SKIP_ABSPOS_PUSH |
|
||||||
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
|
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
|
||||||
NS_NewTableRowGroupFrame) },
|
NS_NewTableRowGroupFrame) },
|
||||||
{ NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP,
|
{ NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP,
|
||||||
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
|
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
|
||||||
FCDATA_MAY_NEED_SCROLLFRAME | FCDATA_SKIP_ABSPOS_PUSH |
|
FCDATA_SKIP_ABSPOS_PUSH |
|
||||||
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
|
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
|
||||||
NS_NewTableRowGroupFrame) },
|
NS_NewTableRowGroupFrame) },
|
||||||
{ NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP,
|
{ NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP,
|
||||||
@ -7888,40 +7888,36 @@ nsCSSFrameConstructor::CreateContinuingTableFrame(nsIPresShell* aPresShell,
|
|||||||
for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
|
for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
|
||||||
// See if it's a header/footer, possibly wrapped in a scroll frame.
|
// See if it's a header/footer, possibly wrapped in a scroll frame.
|
||||||
nsTableRowGroupFrame* rowGroupFrame =
|
nsTableRowGroupFrame* rowGroupFrame =
|
||||||
nsTableFrame::GetRowGroupFrame(childFrame);
|
static_cast<nsTableRowGroupFrame*>(childFrame);
|
||||||
if (rowGroupFrame) {
|
// If the row group was continued, then don't replicate it.
|
||||||
// If the row group was continued, then don't replicate it.
|
nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
|
||||||
nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
|
if (rgNextInFlow) {
|
||||||
if (rgNextInFlow) {
|
rowGroupFrame->SetRepeatable(PR_FALSE);
|
||||||
rowGroupFrame->SetRepeatable(PR_FALSE);
|
}
|
||||||
}
|
else if (rowGroupFrame->IsRepeatable()) {
|
||||||
else if (rowGroupFrame->IsRepeatable()) {
|
// Replicate the header/footer frame.
|
||||||
// Replicate the header/footer frame.
|
nsTableRowGroupFrame* headerFooterFrame;
|
||||||
nsTableRowGroupFrame* headerFooterFrame;
|
nsFrameItems childItems;
|
||||||
nsFrameItems childItems;
|
nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
|
||||||
nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
|
GetAbsoluteContainingBlock(newFrame),
|
||||||
GetAbsoluteContainingBlock(newFrame),
|
nsnull);
|
||||||
nsnull);
|
|
||||||
|
|
||||||
headerFooterFrame = static_cast<nsTableRowGroupFrame*>
|
headerFooterFrame = static_cast<nsTableRowGroupFrame*>
|
||||||
(NS_NewTableRowGroupFrame(aPresShell, rowGroupFrame->GetStyleContext()));
|
(NS_NewTableRowGroupFrame(aPresShell, rowGroupFrame->GetStyleContext()));
|
||||||
nsIContent* headerFooter = rowGroupFrame->GetContent();
|
nsIContent* headerFooter = rowGroupFrame->GetContent();
|
||||||
headerFooterFrame->Init(headerFooter, newFrame, nsnull);
|
headerFooterFrame->Init(headerFooter, newFrame, nsnull);
|
||||||
// No ancestor bindings to worry about ordering with, so null pending
|
ProcessChildren(state, headerFooter, rowGroupFrame->GetStyleContext(),
|
||||||
// binding is ok.
|
headerFooterFrame, PR_TRUE, childItems, PR_FALSE,
|
||||||
ProcessChildren(state, headerFooter, rowGroupFrame->GetStyleContext(),
|
nsnull);
|
||||||
headerFooterFrame, PR_TRUE, childItems, PR_FALSE,
|
NS_ASSERTION(state.mFloatedItems.IsEmpty(), "unexpected floated element");
|
||||||
nsnull);
|
headerFooterFrame->SetInitialChildList(nsnull, childItems);
|
||||||
NS_ASSERTION(state.mFloatedItems.IsEmpty(), "unexpected floated element");
|
headerFooterFrame->SetRepeatable(PR_TRUE);
|
||||||
headerFooterFrame->SetInitialChildList(nsnull, childItems);
|
|
||||||
headerFooterFrame->SetRepeatable(PR_TRUE);
|
|
||||||
|
|
||||||
// Table specific initialization
|
// Table specific initialization
|
||||||
headerFooterFrame->InitRepeatedFrame(aPresContext, rowGroupFrame);
|
headerFooterFrame->InitRepeatedFrame(aPresContext, rowGroupFrame);
|
||||||
|
|
||||||
// XXX Deal with absolute and fixed frames...
|
// XXX Deal with absolute and fixed frames...
|
||||||
childFrames.AddChild(headerFooterFrame);
|
childFrames.AddChild(headerFooterFrame);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -754,7 +754,13 @@ NS_IMETHODIMP
|
|||||||
nsPrintEngine::Print(nsIPrintSettings* aPrintSettings,
|
nsPrintEngine::Print(nsIPrintSettings* aPrintSettings,
|
||||||
nsIWebProgressListener* aWebProgressListener)
|
nsIWebProgressListener* aWebProgressListener)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(mDocument);
|
// If we have a print preview document, use that instead of the original
|
||||||
|
// mDocument. That way animated images etc. get printed using the same state
|
||||||
|
// as in print preview.
|
||||||
|
nsCOMPtr<nsIDOMDocument> doc =
|
||||||
|
do_QueryInterface(mPrtPreview && mPrtPreview->mPrintObject ?
|
||||||
|
mPrtPreview->mPrintObject->mDocument : mDocument);
|
||||||
|
|
||||||
return CommonPrint(PR_FALSE, aPrintSettings, aWebProgressListener, doc);
|
return CommonPrint(PR_FALSE, aPrintSettings, aWebProgressListener, doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
47
layout/reftests/bugs/167496-1-ref.html
Normal file
47
layout/reftests/bugs/167496-1-ref.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type"
|
||||||
|
content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>table border/css test</title>
|
||||||
|
<style type="text/css">
|
||||||
|
<!--
|
||||||
|
table {
|
||||||
|
border: 1px solid blue;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
border: 1px outset silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
border: 1px outset silver;
|
||||||
|
}
|
||||||
|
-->
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Table-header</th>
|
||||||
|
<th>Table-header</th>
|
||||||
|
<th>Table-header</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Table-data</td>
|
||||||
|
<td>Table-data</td>
|
||||||
|
<td>Table-data</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Table-data</td>
|
||||||
|
<td>Table-data</td>
|
||||||
|
<td>Table-data</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
46
layout/reftests/bugs/167496-1.html
Normal file
46
layout/reftests/bugs/167496-1.html
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type"
|
||||||
|
content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>table border/css test</title>
|
||||||
|
<style type="text/css">
|
||||||
|
<!--
|
||||||
|
table {
|
||||||
|
border: 1px solid blue;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
border: 1px outset silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
border: 1px outset silver;
|
||||||
|
}
|
||||||
|
-->
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<table border="1">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Table-header</th>
|
||||||
|
<th>Table-header</th>
|
||||||
|
<th>Table-header</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Table-data</td>
|
||||||
|
<td>Table-data</td>
|
||||||
|
<td>Table-data</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Table-data</td>
|
||||||
|
<td>Table-data</td>
|
||||||
|
<td>Table-data</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
14
layout/reftests/bugs/229591-1-ref.html
Normal file
14
layout/reftests/bugs/229591-1-ref.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||||
|
"http://www.w3.org/TR/html4/strict.dtd">
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
table {border-collapse:collapse}
|
||||||
|
td {border: thin solid lime}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<html >
|
||||||
|
<body style="color:lime">
|
||||||
|
<table><tr><td>cell1</td><td>cell2</td></tr>
|
||||||
|
<tr><td>cell3</td><td>cell4</td></tr></table>
|
||||||
|
</body>
|
||||||
|
</html>
|
8
layout/reftests/bugs/229591-1.html
Normal file
8
layout/reftests/bugs/229591-1.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||||
|
"http://www.w3.org/TR/html4/strict.dtd">
|
||||||
|
<html >
|
||||||
|
<body style="color:lime">
|
||||||
|
<table rules="all" frame="border" ><tr><td>cell1</td><td>cell2</td></tr>
|
||||||
|
<tr><td>cell3</td><td>cell4</td></tr></table>
|
||||||
|
</body>
|
||||||
|
</html>
|
21
layout/reftests/bugs/320979-1-ref.html
Normal file
21
layout/reftests/bugs/320979-1-ref.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||||
|
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||||
|
<title>Bug 320979</title>
|
||||||
|
<style type="text/css">
|
||||||
|
table {border:thin hidden;
|
||||||
|
border-collapse:collapse;}
|
||||||
|
td {background: green; color: white; border:thin solid white;}
|
||||||
|
</style>
|
||||||
|
<p>There should be no red.
|
||||||
|
<TABLE>
|
||||||
|
<TBODY>
|
||||||
|
<TR>
|
||||||
|
<td>test
|
||||||
|
<td>test
|
||||||
|
</TR>
|
||||||
|
<TR>
|
||||||
|
<td>test
|
||||||
|
<td>test
|
||||||
|
</TR>
|
||||||
|
</TBODY>
|
||||||
|
</TABLE>
|
20
layout/reftests/bugs/320979-1.html
Normal file
20
layout/reftests/bugs/320979-1.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||||
|
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||||
|
<title>Bug 320979</title>
|
||||||
|
<style type="text/css">
|
||||||
|
table {border-color: red}
|
||||||
|
td {background: green; color: white}
|
||||||
|
</style>
|
||||||
|
<p>There should be no red.
|
||||||
|
<TABLE rules=all border=0>
|
||||||
|
<TBODY>
|
||||||
|
<TR>
|
||||||
|
<td>test
|
||||||
|
<td>test
|
||||||
|
</TR>
|
||||||
|
<TR>
|
||||||
|
<td>test
|
||||||
|
<td>test
|
||||||
|
</TR>
|
||||||
|
</TBODY>
|
||||||
|
</TABLE>
|
@ -135,6 +135,7 @@ random == 99850-1b.html 99850-1-ref.html # bug 471629
|
|||||||
== 163504-1b.html 163504-1-ref.html
|
== 163504-1b.html 163504-1-ref.html
|
||||||
== 163504-2a.html 163504-2-ref.html
|
== 163504-2a.html 163504-2-ref.html
|
||||||
== 163504-2b.html 163504-2-ref.html
|
== 163504-2b.html 163504-2-ref.html
|
||||||
|
== 167496-1.html 167496-1-ref.html
|
||||||
== 169749-1.html 169749-1-ref.html
|
== 169749-1.html 169749-1-ref.html
|
||||||
== 172073-1.html 172073-1-ref.html
|
== 172073-1.html 172073-1-ref.html
|
||||||
== 179596-1a.html 179596-1a-ref.html
|
== 179596-1a.html 179596-1a-ref.html
|
||||||
@ -170,6 +171,7 @@ random == 99850-1b.html 99850-1-ref.html # bug 471629
|
|||||||
== 223809-1.html 223809-1-ref.html
|
== 223809-1.html 223809-1-ref.html
|
||||||
== 228856-1.html 228856-1-ref.html
|
== 228856-1.html 228856-1-ref.html
|
||||||
== 228856-2.html 228856-2-ref.html
|
== 228856-2.html 228856-2-ref.html
|
||||||
|
== 229591-1.html 229591-1-ref.html
|
||||||
# == 231823-1.html 231823-1-ref.html
|
# == 231823-1.html 231823-1-ref.html
|
||||||
== 232990-1a.xhtml 232990-1-ref.xhtml
|
== 232990-1a.xhtml 232990-1-ref.xhtml
|
||||||
== 232990-1b.xhtml 232990-1-ref.xhtml
|
== 232990-1b.xhtml 232990-1-ref.xhtml
|
||||||
@ -362,6 +364,7 @@ fails == 311366-unknown-block-3.html 311366-unknown-block-3-ref.html
|
|||||||
== 315920-29b.html 315920-29-ref.html
|
== 315920-29b.html 315920-29-ref.html
|
||||||
== 315920-30.html 315920-30-ref.html
|
== 315920-30.html 315920-30-ref.html
|
||||||
== 316057-1.html 316057-1-ref.html
|
== 316057-1.html 316057-1-ref.html
|
||||||
|
== 320979-1.html 320979-1-ref.html
|
||||||
!= 321402-1.html about:blank
|
!= 321402-1.html about:blank
|
||||||
!= 321402-2.html about:blank
|
!= 321402-2.html about:blank
|
||||||
== 321402-3.xul 321402-3-ref.xul
|
== 321402-3.xul 321402-3-ref.xul
|
||||||
@ -702,7 +705,7 @@ fails == 386147-1.html 386147-1-ref.html # bug 447460
|
|||||||
== 387201-3.html about:blank # Really an assertion test rather than a rendering test
|
== 387201-3.html about:blank # Really an assertion test rather than a rendering test
|
||||||
== 387227-1.html 387227-1-ref.html
|
== 387227-1.html 387227-1-ref.html
|
||||||
== 387227-2.html 387227-2-ref.html
|
== 387227-2.html 387227-2-ref.html
|
||||||
== 387344-1.html 387344-1-ref.html
|
fails == 387344-1.html 387344-1-ref.html # scrolling rowgroups removed bug 28800
|
||||||
== 387876-1.html 387876-1-ref.html
|
== 387876-1.html 387876-1-ref.html
|
||||||
random == 387876-2.html 387876-2-ref.html # bug 471630
|
random == 387876-2.html 387876-2-ref.html # bug 471630
|
||||||
== 387876-3a.html 387876-3-ref.html
|
== 387876-3a.html 387876-3-ref.html
|
||||||
@ -956,7 +959,7 @@ skip-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 413292-1.html 413292-1-ref.html # disabl
|
|||||||
== 423385-1.html 423385-1-ref.html
|
== 423385-1.html 423385-1-ref.html
|
||||||
== 423599-1.html 423599-1-ref.html
|
== 423599-1.html 423599-1-ref.html
|
||||||
== 423676-1.html 423676-1-ref.html
|
== 423676-1.html 423676-1-ref.html
|
||||||
== 423823-1.html 423823-1-ref.html
|
fails == 423823-1.html 423823-1-ref.html # scrolling rowgroups removed bug 28800
|
||||||
== 424074-1.xul 424074-1-ref.xul
|
== 424074-1.xul 424074-1-ref.xul
|
||||||
!= 424074-1.xul 424074-1-ref2.xul
|
!= 424074-1.xul 424074-1-ref2.xul
|
||||||
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") == 424074-1-ref2.xul 424074-1-ref3.xul
|
fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") == 424074-1-ref2.xul 424074-1-ref3.xul
|
||||||
|
@ -51,7 +51,7 @@ fails == border-separate-opacity-table-column.html border-separate-opacity-table
|
|||||||
== border-separate-opacity-table-row-group.html border-separate-opacity-table-row-group-ref.html
|
== border-separate-opacity-table-row-group.html border-separate-opacity-table-row-group-ref.html
|
||||||
== border-separate-opacity-table-row.html border-separate-opacity-table-row-ref.html
|
== border-separate-opacity-table-row.html border-separate-opacity-table-row-ref.html
|
||||||
== border-separate-opacity-table.html border-separate-opacity-table-ref.html
|
== border-separate-opacity-table.html border-separate-opacity-table-ref.html
|
||||||
!= scrollable-rowgroup-collapse-background.html scrollable-rowgroup-collapse-notref.html
|
!= scrollable-rowgroup-collapse-background.html scrollable-rowgroup-collapse-notref.html
|
||||||
!= scrollable-rowgroup-collapse-border.html scrollable-rowgroup-collapse-notref.html
|
!= scrollable-rowgroup-collapse-border.html scrollable-rowgroup-collapse-notref.html
|
||||||
!= scrollable-rowgroup-separate-background.html scrollable-rowgroup-separate-notref.html
|
!= scrollable-rowgroup-separate-background.html scrollable-rowgroup-separate-notref.html
|
||||||
!= scrollable-rowgroup-separate-border.html scrollable-rowgroup-separate-notref.html
|
== scrollable-rowgroup-separate-border.html scrollable-rowgroup-separate-notref.html # bug 28800
|
||||||
|
@ -879,7 +879,8 @@ CSSImportantRule::List(FILE* out, PRInt32 aIndent) const
|
|||||||
// Indent
|
// Indent
|
||||||
for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
|
for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
|
||||||
|
|
||||||
fprintf(out, "! Important rule block=%p\n", mImportantBlock.get());
|
fprintf(out, "! Important rule block=%p\n",
|
||||||
|
static_cast<void*>(mImportantBlock.get()));
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -82,7 +82,7 @@ nsTableCellMap::nsTableCellMap(nsTableFrame& aTableFrame,
|
|||||||
nsTableRowGroupFrame* prior = nsnull;
|
nsTableRowGroupFrame* prior = nsnull;
|
||||||
for (PRUint32 rgX = 0; rgX < orderedRowGroups.Length(); rgX++) {
|
for (PRUint32 rgX = 0; rgX < orderedRowGroups.Length(); rgX++) {
|
||||||
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgX];
|
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgX];
|
||||||
InsertGroupCellMap(*rgFrame, prior);
|
InsertGroupCellMap(rgFrame, prior);
|
||||||
prior = rgFrame;
|
prior = rgFrame;
|
||||||
}
|
}
|
||||||
if (aBorderCollapse) {
|
if (aBorderCollapse) {
|
||||||
@ -165,7 +165,7 @@ nsTableCellMap::InsertGroupCellMap(nsCellMap* aPrevMap,
|
|||||||
aNewMap.SetNextSibling(next);
|
aNewMap.SetNextSibling(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsTableCellMap::InsertGroupCellMap(nsTableRowGroupFrame& aNewGroup,
|
void nsTableCellMap::InsertGroupCellMap(nsTableRowGroupFrame* aNewGroup,
|
||||||
nsTableRowGroupFrame*& aPrevGroup)
|
nsTableRowGroupFrame*& aPrevGroup)
|
||||||
{
|
{
|
||||||
nsCellMap* newMap = new nsCellMap(aNewGroup, mBCInfo != nsnull);
|
nsCellMap* newMap = new nsCellMap(aNewGroup, mBCInfo != nsnull);
|
||||||
@ -471,7 +471,7 @@ nsTableCellMap::ClearCols()
|
|||||||
mBCInfo->mBottomBorders.Clear();
|
mBCInfo->mBottomBorders.Clear();
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
nsTableCellMap::InsertRows(nsTableRowGroupFrame& aParent,
|
nsTableCellMap::InsertRows(nsTableRowGroupFrame* aParent,
|
||||||
nsTArray<nsTableRowFrame*>& aRows,
|
nsTArray<nsTableRowFrame*>& aRows,
|
||||||
PRInt32 aFirstRowIndex,
|
PRInt32 aFirstRowIndex,
|
||||||
PRBool aConsiderSpans,
|
PRBool aConsiderSpans,
|
||||||
@ -484,7 +484,7 @@ nsTableCellMap::InsertRows(nsTableRowGroupFrame& aParent,
|
|||||||
nsCellMap* cellMap = mFirstMap;
|
nsCellMap* cellMap = mFirstMap;
|
||||||
while (cellMap) {
|
while (cellMap) {
|
||||||
nsTableRowGroupFrame* rg = cellMap->GetRowGroup();
|
nsTableRowGroupFrame* rg = cellMap->GetRowGroup();
|
||||||
if (rg == &aParent) {
|
if (rg == aParent) {
|
||||||
cellMap->InsertRows(*this, aRows, rowIndex, aConsiderSpans, aDamageArea);
|
cellMap->InsertRows(*this, aRows, rowIndex, aConsiderSpans, aDamageArea);
|
||||||
aDamageArea.y = NS_MIN(aFirstRowIndex, aDamageArea.y);
|
aDamageArea.y = NS_MIN(aFirstRowIndex, aDamageArea.y);
|
||||||
aDamageArea.height = NS_MAX(0, GetRowCount() - aDamageArea.y);
|
aDamageArea.height = NS_MAX(0, GetRowCount() - aDamageArea.y);
|
||||||
@ -1175,10 +1175,10 @@ nsTableCellMap::SetBCBorderCorner(Corner aCorner,
|
|||||||
else NS_ERROR("program error: Corner not found");
|
else NS_ERROR("program error: Corner not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCellMap::nsCellMap(nsTableRowGroupFrame& aRowGroup, PRBool aIsBC)
|
nsCellMap::nsCellMap(nsTableRowGroupFrame* aRowGroup, PRBool aIsBC)
|
||||||
: mRows(8), mContentRowCount(0), mRowGroupFrame(&aRowGroup),
|
: mRows(8), mContentRowCount(0), mRowGroupFrame(aRowGroup),
|
||||||
mNextSibling(nsnull), mIsBC(aIsBC),
|
mNextSibling(nsnull), mIsBC(aIsBC),
|
||||||
mPresContext(aRowGroup.PresContext())
|
mPresContext(aRowGroup->PresContext())
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsCellMap);
|
MOZ_COUNT_CTOR(nsCellMap);
|
||||||
NS_ASSERTION(mPresContext, "Must have prescontext");
|
NS_ASSERTION(mPresContext, "Must have prescontext");
|
||||||
|
@ -94,7 +94,7 @@ public:
|
|||||||
|
|
||||||
void RemoveGroupCellMap(nsTableRowGroupFrame* aRowGroup);
|
void RemoveGroupCellMap(nsTableRowGroupFrame* aRowGroup);
|
||||||
|
|
||||||
void InsertGroupCellMap(nsTableRowGroupFrame& aNewRowGroup,
|
void InsertGroupCellMap(nsTableRowGroupFrame* aNewRowGroup,
|
||||||
nsTableRowGroupFrame*& aPrevRowGroup);
|
nsTableRowGroupFrame*& aPrevRowGroup);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,7 +140,7 @@ public:
|
|||||||
nsRect& aDamageArea);
|
nsRect& aDamageArea);
|
||||||
/** Remove the previously gathered column information */
|
/** Remove the previously gathered column information */
|
||||||
void ClearCols();
|
void ClearCols();
|
||||||
void InsertRows(nsTableRowGroupFrame& aRowGroup,
|
void InsertRows(nsTableRowGroupFrame* aRowGroup,
|
||||||
nsTArray<nsTableRowFrame*>& aRows,
|
nsTArray<nsTableRowFrame*>& aRows,
|
||||||
PRInt32 aFirstRowIndex,
|
PRInt32 aFirstRowIndex,
|
||||||
PRBool aConsiderSpans,
|
PRBool aConsiderSpans,
|
||||||
@ -306,7 +306,7 @@ public:
|
|||||||
* @param aRowGroupFrame the row group frame this is a cellmap for
|
* @param aRowGroupFrame the row group frame this is a cellmap for
|
||||||
* @param aIsBC whether the table is doing border-collapse
|
* @param aIsBC whether the table is doing border-collapse
|
||||||
*/
|
*/
|
||||||
nsCellMap(nsTableRowGroupFrame& aRowGroupFrame, PRBool aIsBC);
|
nsCellMap(nsTableRowGroupFrame* aRowGroupFrame, PRBool aIsBC);
|
||||||
|
|
||||||
/** destructor
|
/** destructor
|
||||||
* NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
|
* NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
|
||||||
|
@ -65,7 +65,6 @@
|
|||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
#include "nsIDOMHTMLElement.h"
|
#include "nsIDOMHTMLElement.h"
|
||||||
#include "nsIDOMHTMLBodyElement.h"
|
#include "nsIDOMHTMLBodyElement.h"
|
||||||
#include "nsIScrollableFrame.h"
|
|
||||||
#include "nsFrameManager.h"
|
#include "nsFrameManager.h"
|
||||||
#include "nsCSSRendering.h"
|
#include "nsCSSRendering.h"
|
||||||
#include "nsLayoutErrors.h"
|
#include "nsLayoutErrors.h"
|
||||||
@ -522,30 +521,24 @@ void nsTableFrame::ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude
|
|||||||
{
|
{
|
||||||
// Iterate over the row groups and adjust the row indices of all rows
|
// Iterate over the row groups and adjust the row indices of all rows
|
||||||
// omit the rowgroups that will be inserted later
|
// omit the rowgroups that will be inserted later
|
||||||
// XXXbz this code seems to assume that the row groups handed out by
|
|
||||||
// aRowGroupsToExclude are already in OrderRowGroups() order.
|
|
||||||
// There's no reason that would be true!
|
|
||||||
RowGroupArray rowGroups;
|
RowGroupArray rowGroups;
|
||||||
OrderRowGroups(rowGroups);
|
OrderRowGroups(rowGroups);
|
||||||
|
|
||||||
PRInt32 rowIndex = 0;
|
PRInt32 rowIndex = 0;
|
||||||
nsTableRowGroupFrame* newRgFrame = nsnull;
|
nsTHashtable<nsPtrHashKey<nsTableRowGroupFrame> > excludeRowGroups;
|
||||||
|
if (!excludeRowGroups.Init()) {
|
||||||
|
NS_ERROR("Failed to initialize excludeRowGroups hash.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
nsFrameList::Enumerator excludeRowGroupsEnumerator(aRowGroupsToExclude);
|
nsFrameList::Enumerator excludeRowGroupsEnumerator(aRowGroupsToExclude);
|
||||||
if (!excludeRowGroupsEnumerator.AtEnd()) {
|
while (!excludeRowGroupsEnumerator.AtEnd()) {
|
||||||
newRgFrame = GetRowGroupFrame(excludeRowGroupsEnumerator.get());
|
excludeRowGroups.PutEntry(static_cast<nsTableRowGroupFrame*>(excludeRowGroupsEnumerator.get()));
|
||||||
excludeRowGroupsEnumerator.Next();
|
excludeRowGroupsEnumerator.Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
||||||
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
||||||
if (rgFrame == newRgFrame) {
|
if (!excludeRowGroups.GetEntry(rgFrame)) {
|
||||||
// omit the new rowgroup and move our iterator along
|
|
||||||
if (!excludeRowGroupsEnumerator.AtEnd()) {
|
|
||||||
newRgFrame = GetRowGroupFrame(excludeRowGroupsEnumerator.get());
|
|
||||||
excludeRowGroupsEnumerator.Next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const nsFrameList& rowFrames = rgFrame->GetChildList(nsnull);
|
const nsFrameList& rowFrames = rgFrame->GetChildList(nsnull);
|
||||||
for (nsFrameList::Enumerator rows(rowFrames); !rows.AtEnd(); rows.Next()) {
|
for (nsFrameList::Enumerator rows(rowFrames); !rows.AtEnd(); rows.Next()) {
|
||||||
if (NS_STYLE_DISPLAY_TABLE_ROW==rows.get()->GetStyleDisplay()->mDisplay) {
|
if (NS_STYLE_DISPLAY_TABLE_ROW==rows.get()->GetStyleDisplay()->mDisplay) {
|
||||||
@ -881,7 +874,7 @@ void nsTableFrame::RemoveCell(nsTableCellFrame* aCellFrame,
|
|||||||
}
|
}
|
||||||
|
|
||||||
PRInt32
|
PRInt32
|
||||||
nsTableFrame::GetStartRowIndex(nsTableRowGroupFrame& aRowGroupFrame)
|
nsTableFrame::GetStartRowIndex(nsTableRowGroupFrame* aRowGroupFrame)
|
||||||
{
|
{
|
||||||
RowGroupArray orderedRowGroups;
|
RowGroupArray orderedRowGroups;
|
||||||
OrderRowGroups(orderedRowGroups);
|
OrderRowGroups(orderedRowGroups);
|
||||||
@ -889,7 +882,7 @@ nsTableFrame::GetStartRowIndex(nsTableRowGroupFrame& aRowGroupFrame)
|
|||||||
PRInt32 rowIndex = 0;
|
PRInt32 rowIndex = 0;
|
||||||
for (PRUint32 rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
for (PRUint32 rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
||||||
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
|
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
|
||||||
if (rgFrame == &aRowGroupFrame) {
|
if (rgFrame == aRowGroupFrame) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
PRInt32 numRows = rgFrame->GetRowCount();
|
PRInt32 numRows = rgFrame->GetRowCount();
|
||||||
@ -899,7 +892,7 @@ nsTableFrame::GetStartRowIndex(nsTableRowGroupFrame& aRowGroupFrame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this cannot extend beyond a single row group
|
// this cannot extend beyond a single row group
|
||||||
void nsTableFrame::AppendRows(nsTableRowGroupFrame& aRowGroupFrame,
|
void nsTableFrame::AppendRows(nsTableRowGroupFrame* aRowGroupFrame,
|
||||||
PRInt32 aRowIndex,
|
PRInt32 aRowIndex,
|
||||||
nsTArray<nsTableRowFrame*>& aRowFrames)
|
nsTArray<nsTableRowFrame*>& aRowFrames)
|
||||||
{
|
{
|
||||||
@ -910,20 +903,9 @@ void nsTableFrame::AppendRows(nsTableRowGroupFrame& aRowGroupFrame,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt32
|
|
||||||
nsTableFrame::InsertRow(nsTableRowGroupFrame& aRowGroupFrame,
|
|
||||||
nsIFrame& aRowFrame,
|
|
||||||
PRInt32 aRowIndex,
|
|
||||||
PRBool aConsiderSpans)
|
|
||||||
{
|
|
||||||
nsAutoTArray<nsTableRowFrame*, 1> rows;
|
|
||||||
rows.AppendElement((nsTableRowFrame*)&aRowFrame);
|
|
||||||
return InsertRows(aRowGroupFrame, rows, aRowIndex, aConsiderSpans);
|
|
||||||
}
|
|
||||||
|
|
||||||
// this cannot extend beyond a single row group
|
// this cannot extend beyond a single row group
|
||||||
PRInt32
|
PRInt32
|
||||||
nsTableFrame::InsertRows(nsTableRowGroupFrame& aRowGroupFrame,
|
nsTableFrame::InsertRows(nsTableRowGroupFrame* aRowGroupFrame,
|
||||||
nsTArray<nsTableRowFrame*>& aRowFrames,
|
nsTArray<nsTableRowFrame*>& aRowFrames,
|
||||||
PRInt32 aRowIndex,
|
PRInt32 aRowIndex,
|
||||||
PRBool aConsiderSpans)
|
PRBool aConsiderSpans)
|
||||||
@ -1004,53 +986,18 @@ void nsTableFrame::RemoveRows(nsTableRowFrame& aFirstRowFrame,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTableRowGroupFrame*
|
|
||||||
nsTableFrame::GetRowGroupFrame(nsIFrame* aFrame,
|
|
||||||
nsIAtom* aFrameTypeIn)
|
|
||||||
{
|
|
||||||
nsIFrame* rgFrame = nsnull;
|
|
||||||
nsIAtom* frameType = aFrameTypeIn;
|
|
||||||
if (!aFrameTypeIn) {
|
|
||||||
frameType = aFrame->GetType();
|
|
||||||
}
|
|
||||||
if (nsGkAtoms::tableRowGroupFrame == frameType) {
|
|
||||||
rgFrame = aFrame;
|
|
||||||
}
|
|
||||||
else if (nsGkAtoms::scrollFrame == frameType) {
|
|
||||||
nsIScrollableFrame* scrollable = do_QueryFrame(aFrame);
|
|
||||||
if (scrollable) {
|
|
||||||
nsIFrame* scrolledFrame = scrollable->GetScrolledFrame();
|
|
||||||
if (scrolledFrame) {
|
|
||||||
if (nsGkAtoms::tableRowGroupFrame == scrolledFrame->GetType()) {
|
|
||||||
rgFrame = scrolledFrame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (nsTableRowGroupFrame*)rgFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
// collect the rows ancestors of aFrame
|
// collect the rows ancestors of aFrame
|
||||||
PRInt32
|
PRInt32
|
||||||
nsTableFrame::CollectRows(nsIFrame* aFrame,
|
nsTableFrame::CollectRows(nsIFrame* aFrame,
|
||||||
nsTArray<nsTableRowFrame*>& aCollection)
|
nsTArray<nsTableRowFrame*>& aCollection)
|
||||||
{
|
{
|
||||||
if (!aFrame) return 0;
|
NS_PRECONDITION(aFrame, "null frame");
|
||||||
PRInt32 numRows = 0;
|
PRInt32 numRows = 0;
|
||||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(aFrame);
|
nsIFrame* childFrame = aFrame->GetFirstChild(nsnull);
|
||||||
if (rgFrame) {
|
while (childFrame) {
|
||||||
nsIFrame* childFrame = rgFrame->GetFirstChild(nsnull);
|
aCollection.AppendElement(static_cast<nsTableRowFrame*>(childFrame));
|
||||||
while (childFrame) {
|
numRows++;
|
||||||
nsTableRowFrame *rowFrame = do_QueryFrame(childFrame);
|
childFrame = childFrame->GetNextSibling();
|
||||||
if (rowFrame) {
|
|
||||||
aCollection.AppendElement(rowFrame);
|
|
||||||
numRows++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
numRows += CollectRows(childFrame, aCollection);
|
|
||||||
}
|
|
||||||
childFrame = childFrame->GetNextSibling();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return numRows;
|
return numRows;
|
||||||
}
|
}
|
||||||
@ -1076,13 +1023,11 @@ nsTableFrame::InsertRowGroups(const nsFrameList::Slice& aRowGroups)
|
|||||||
for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
||||||
for (nsFrameList::Enumerator rowgroups(aRowGroups); !rowgroups.AtEnd();
|
for (nsFrameList::Enumerator rowgroups(aRowGroups); !rowgroups.AtEnd();
|
||||||
rowgroups.Next()) {
|
rowgroups.Next()) {
|
||||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(rowgroups.get());
|
if (orderedRowGroups[rgIndex] == rowgroups.get()) {
|
||||||
|
|
||||||
if (orderedRowGroups[rgIndex] == rgFrame) {
|
|
||||||
nsTableRowGroupFrame* priorRG =
|
nsTableRowGroupFrame* priorRG =
|
||||||
(0 == rgIndex) ? nsnull : orderedRowGroups[rgIndex - 1];
|
(0 == rgIndex) ? nsnull : orderedRowGroups[rgIndex - 1];
|
||||||
// create and add the cell map for the row group
|
// create and add the cell map for the row group
|
||||||
cellMap->InsertGroupCellMap(*rgFrame, priorRG);
|
cellMap->InsertGroupCellMap(orderedRowGroups[rgIndex], priorRG);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1095,9 +1040,7 @@ nsTableFrame::InsertRowGroups(const nsFrameList::Slice& aRowGroups)
|
|||||||
for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
||||||
for (nsFrameList::Enumerator rowgroups(aRowGroups); !rowgroups.AtEnd();
|
for (nsFrameList::Enumerator rowgroups(aRowGroups); !rowgroups.AtEnd();
|
||||||
rowgroups.Next()) {
|
rowgroups.Next()) {
|
||||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(rowgroups.get());
|
if (orderedRowGroups[rgIndex] == rowgroups.get()) {
|
||||||
|
|
||||||
if (orderedRowGroups[rgIndex] == rgFrame) {
|
|
||||||
nsTableRowGroupFrame* priorRG =
|
nsTableRowGroupFrame* priorRG =
|
||||||
(0 == rgIndex) ? nsnull : orderedRowGroups[rgIndex - 1];
|
(0 == rgIndex) ? nsnull : orderedRowGroups[rgIndex - 1];
|
||||||
// collect the new row frames in an array and add them to the table
|
// collect the new row frames in an array and add them to the table
|
||||||
@ -1108,7 +1051,7 @@ nsTableFrame::InsertRowGroups(const nsFrameList::Slice& aRowGroups)
|
|||||||
PRInt32 priorNumRows = priorRG->GetRowCount();
|
PRInt32 priorNumRows = priorRG->GetRowCount();
|
||||||
rowIndex = priorRG->GetStartRowIndex() + priorNumRows;
|
rowIndex = priorRG->GetStartRowIndex() + priorNumRows;
|
||||||
}
|
}
|
||||||
InsertRows(*rgFrame, rows, rowIndex, PR_TRUE);
|
InsertRows(orderedRowGroups[rgIndex], rows, rowIndex, PR_TRUE);
|
||||||
rows.Clear();
|
rows.Clear();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1697,7 +1640,6 @@ nsTableFrame::RequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState)
|
|||||||
NS_ASSERTION(IS_TABLE_CELL(frameType) ||
|
NS_ASSERTION(IS_TABLE_CELL(frameType) ||
|
||||||
nsGkAtoms::tableRowFrame == frameType ||
|
nsGkAtoms::tableRowFrame == frameType ||
|
||||||
nsGkAtoms::tableRowGroupFrame == frameType ||
|
nsGkAtoms::tableRowGroupFrame == frameType ||
|
||||||
nsGkAtoms::scrollFrame == frameType ||
|
|
||||||
nsGkAtoms::tableFrame == frameType,
|
nsGkAtoms::tableFrame == frameType,
|
||||||
"unexpected frame type");
|
"unexpected frame type");
|
||||||
|
|
||||||
@ -1993,7 +1935,7 @@ nsTableFrame::GetFirstBodyRowGroupFrame()
|
|||||||
// Table specific version that takes into account repeated header and footer
|
// Table specific version that takes into account repeated header and footer
|
||||||
// frames when continuing table frames
|
// frames when continuing table frames
|
||||||
void
|
void
|
||||||
nsTableFrame::PushChildren(const FrameArray& aFrames,
|
nsTableFrame::PushChildren(const RowGroupArray& aRowGroups,
|
||||||
PRInt32 aPushFrom)
|
PRInt32 aPushFrom)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(aPushFrom > 0, "pushing first child");
|
NS_PRECONDITION(aPushFrom > 0, "pushing first child");
|
||||||
@ -2001,17 +1943,11 @@ nsTableFrame::PushChildren(const FrameArray& aFrames,
|
|||||||
// extract the frames from the array into a sibling list
|
// extract the frames from the array into a sibling list
|
||||||
nsFrameList frames;
|
nsFrameList frames;
|
||||||
PRUint32 childX;
|
PRUint32 childX;
|
||||||
for (childX = aPushFrom; childX < aFrames.Length(); ++childX) {
|
for (childX = aPushFrom; childX < aRowGroups.Length(); ++childX) {
|
||||||
nsIFrame* f = aFrames[childX];
|
nsTableRowGroupFrame* rgFrame = aRowGroups[childX];
|
||||||
// Don't push repeatable frames, do push non-rowgroup frames.
|
|
||||||
// XXXbz Need to push the non-rowgroup frames, even though we don't reflow
|
|
||||||
// them, so that we don't lose them. Of course there shouldn't be any
|
|
||||||
// non-rowgroup frames here...
|
|
||||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(f);
|
|
||||||
NS_ASSERTION(rgFrame, "Unexpected non-row-group frame");
|
|
||||||
if (!rgFrame || !rgFrame->IsRepeatable()) {
|
if (!rgFrame || !rgFrame->IsRepeatable()) {
|
||||||
mFrames.RemoveFrame(f);
|
mFrames.RemoveFrame(rgFrame);
|
||||||
frames.AppendFrame(nsnull, f);
|
frames.AppendFrame(nsnull, rgFrame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2351,34 +2287,30 @@ nsTableFrame::RemoveFrame(nsIAtom* aListName,
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
NS_ASSERTION(!aListName, "unexpected child list");
|
NS_ASSERTION(!aListName, "unexpected child list");
|
||||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(aOldFrame);
|
nsTableRowGroupFrame* rgFrame =
|
||||||
if (rgFrame) {
|
static_cast<nsTableRowGroupFrame*>(aOldFrame);
|
||||||
// remove the row group from the cell map
|
// remove the row group from the cell map
|
||||||
nsTableCellMap* cellMap = GetCellMap();
|
nsTableCellMap* cellMap = GetCellMap();
|
||||||
if (cellMap) {
|
if (cellMap) {
|
||||||
cellMap->RemoveGroupCellMap(rgFrame);
|
cellMap->RemoveGroupCellMap(rgFrame);
|
||||||
}
|
|
||||||
|
|
||||||
// remove the row group frame from the sibling chain
|
|
||||||
mFrames.DestroyFrame(aOldFrame);
|
|
||||||
|
|
||||||
// XXXldb [reflow branch merging 20060830] do we still need this?
|
|
||||||
if (cellMap) {
|
|
||||||
cellMap->Synchronize(this);
|
|
||||||
// Create an empty slice
|
|
||||||
ResetRowIndices(nsFrameList::Slice(mFrames, nsnull, nsnull));
|
|
||||||
nsRect damageArea;
|
|
||||||
cellMap->RebuildConsideringCells(nsnull, nsnull, 0, 0, PR_FALSE, damageArea);
|
|
||||||
}
|
|
||||||
|
|
||||||
MatchCellMapToColCache(cellMap);
|
|
||||||
} else {
|
|
||||||
// Just remove the frame
|
|
||||||
mFrames.DestroyFrame(aOldFrame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove the row group frame from the sibling chain
|
||||||
|
mFrames.DestroyFrame(aOldFrame);
|
||||||
|
|
||||||
|
// the removal of a row group changes the cellmap, the columns might change
|
||||||
|
if (cellMap) {
|
||||||
|
cellMap->Synchronize(this);
|
||||||
|
// Create an empty slice
|
||||||
|
ResetRowIndices(nsFrameList::Slice(mFrames, nsnull, nsnull));
|
||||||
|
nsRect damageArea;
|
||||||
|
cellMap->RebuildConsideringCells(nsnull, nsnull, 0, 0, PR_FALSE, damageArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
MatchCellMapToColCache(cellMap);
|
||||||
}
|
}
|
||||||
// for now, just bail and recalc all of the collapsing borders
|
// for now, just bail and recalc all of the collapsing borders
|
||||||
// XXXldb [reflow branch merging 20060830] do we still need this?
|
// as the cellmap changes we need to recalc
|
||||||
if (IsBorderCollapse()) {
|
if (IsBorderCollapse()) {
|
||||||
nsRect damageArea(0, 0, NS_MAX(1, GetColCount()), NS_MAX(1, GetRowCount()));
|
nsRect damageArea(0, 0, NS_MAX(1, GetColCount()), NS_MAX(1, GetRowCount()));
|
||||||
SetBCDamageArea(damageArea);
|
SetBCDamageArea(damageArea);
|
||||||
@ -2502,10 +2434,9 @@ nsTableFrame::InitChildReflowState(nsHTMLReflowState& aReflowState)
|
|||||||
nsMargin* pCollapseBorder = nsnull;
|
nsMargin* pCollapseBorder = nsnull;
|
||||||
nsPresContext* presContext = PresContext();
|
nsPresContext* presContext = PresContext();
|
||||||
if (IsBorderCollapse()) {
|
if (IsBorderCollapse()) {
|
||||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(aReflowState.frame);
|
nsTableRowGroupFrame* rgFrame =
|
||||||
if (rgFrame) {
|
static_cast<nsTableRowGroupFrame*>(aReflowState.frame);
|
||||||
pCollapseBorder = rgFrame->GetBCBorderWidth(collapseBorder);
|
pCollapseBorder = rgFrame->GetBCBorderWidth(collapseBorder);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
aReflowState.Init(presContext, -1, -1, pCollapseBorder, &padding);
|
aReflowState.Init(presContext, -1, -1, pCollapseBorder, &padding);
|
||||||
|
|
||||||
@ -2545,7 +2476,9 @@ void nsTableFrame::PlaceChild(nsTableReflowState& aReflowState,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsTableFrame::OrderRowGroups(RowGroupArray& aChildren) const
|
nsTableFrame::OrderRowGroups(RowGroupArray& aChildren,
|
||||||
|
nsTableRowGroupFrame** aHead,
|
||||||
|
nsTableRowGroupFrame** aFoot) const
|
||||||
{
|
{
|
||||||
aChildren.Clear();
|
aChildren.Clear();
|
||||||
nsTableRowGroupFrame* head = nsnull;
|
nsTableRowGroupFrame* head = nsnull;
|
||||||
@ -2554,33 +2487,33 @@ nsTableFrame::OrderRowGroups(RowGroupArray& aChildren) const
|
|||||||
nsIFrame* kidFrame = mFrames.FirstChild();
|
nsIFrame* kidFrame = mFrames.FirstChild();
|
||||||
while (kidFrame) {
|
while (kidFrame) {
|
||||||
const nsStyleDisplay* kidDisplay = kidFrame->GetStyleDisplay();
|
const nsStyleDisplay* kidDisplay = kidFrame->GetStyleDisplay();
|
||||||
nsTableRowGroupFrame* rowGroup = GetRowGroupFrame(kidFrame);
|
nsTableRowGroupFrame* rowGroup =
|
||||||
if (NS_LIKELY(rowGroup)) {
|
static_cast<nsTableRowGroupFrame*>(kidFrame);
|
||||||
switch(kidDisplay->mDisplay) {
|
|
||||||
case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
|
switch (kidDisplay->mDisplay) {
|
||||||
if (head) { // treat additional thead like tbody
|
case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
|
||||||
aChildren.AppendElement(rowGroup);
|
if (head) { // treat additional thead like tbody
|
||||||
}
|
|
||||||
else {
|
|
||||||
head = rowGroup;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
|
|
||||||
if (foot) { // treat additional tfoot like tbody
|
|
||||||
aChildren.AppendElement(rowGroup);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
foot = rowGroup;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
|
|
||||||
aChildren.AppendElement(rowGroup);
|
aChildren.AppendElement(rowGroup);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NS_NOTREACHED("How did this produce an nsTableRowGroupFrame?");
|
|
||||||
// Just ignore it
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
head = rowGroup;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
|
||||||
|
if (foot) { // treat additional tfoot like tbody
|
||||||
|
aChildren.AppendElement(rowGroup);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foot = rowGroup;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
|
||||||
|
aChildren.AppendElement(rowGroup);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NS_NOTREACHED("How did this produce an nsTableRowGroupFrame?");
|
||||||
|
// Just ignore it
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// Get the next sibling but skip it if it's also the next-in-flow, since
|
// Get the next sibling but skip it if it's also the next-in-flow, since
|
||||||
// a next-in-flow will not be part of the current table.
|
// a next-in-flow will not be part of the current table.
|
||||||
@ -2596,88 +2529,14 @@ nsTableFrame::OrderRowGroups(RowGroupArray& aChildren) const
|
|||||||
if (head) {
|
if (head) {
|
||||||
aChildren.InsertElementAt(0, head);
|
aChildren.InsertElementAt(0, head);
|
||||||
}
|
}
|
||||||
|
if (aHead)
|
||||||
|
*aHead = head;
|
||||||
// put the tfoot after the last tbody
|
// put the tfoot after the last tbody
|
||||||
if (foot) {
|
if (foot) {
|
||||||
aChildren.AppendElement(foot);
|
aChildren.AppendElement(foot);
|
||||||
}
|
}
|
||||||
}
|
if (aFoot)
|
||||||
|
*aFoot = foot;
|
||||||
PRUint32
|
|
||||||
nsTableFrame::OrderRowGroups(FrameArray& aChildren,
|
|
||||||
nsTableRowGroupFrame** aHead,
|
|
||||||
nsTableRowGroupFrame** aFoot) const
|
|
||||||
{
|
|
||||||
aChildren.Clear();
|
|
||||||
// initialize out parameters
|
|
||||||
*aHead = nsnull;
|
|
||||||
*aFoot = nsnull;
|
|
||||||
|
|
||||||
FrameArray nonRowGroups;
|
|
||||||
|
|
||||||
nsIFrame* head = nsnull;
|
|
||||||
nsIFrame* foot = nsnull;
|
|
||||||
|
|
||||||
nsIFrame* kidFrame = mFrames.FirstChild();
|
|
||||||
while (kidFrame) {
|
|
||||||
const nsStyleDisplay* kidDisplay = kidFrame->GetStyleDisplay();
|
|
||||||
nsTableRowGroupFrame* rowGroup = GetRowGroupFrame(kidFrame);
|
|
||||||
if (NS_LIKELY(rowGroup)) {
|
|
||||||
switch(kidDisplay->mDisplay) {
|
|
||||||
case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
|
|
||||||
if (head) { // treat additional thead like tbody
|
|
||||||
aChildren.AppendElement(kidFrame);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
head = kidFrame;
|
|
||||||
*aHead = rowGroup;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
|
|
||||||
if (foot) { // treat additional tfoot like tbody
|
|
||||||
aChildren.AppendElement(kidFrame);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
foot = kidFrame;
|
|
||||||
*aFoot = rowGroup;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
|
|
||||||
aChildren.AppendElement(kidFrame);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
NS_NOTREACHED("Non-row-group primary frame list child of an "
|
|
||||||
"nsTableFrame? How come?");
|
|
||||||
nonRowGroups.AppendElement(kidFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the next sibling but skip it if it's also the next-in-flow, since
|
|
||||||
// a next-in-flow will not be part of the current table.
|
|
||||||
while (kidFrame) {
|
|
||||||
nsIFrame* nif = kidFrame->GetNextInFlow();
|
|
||||||
kidFrame = kidFrame->GetNextSibling();
|
|
||||||
if (kidFrame != nif)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// put the thead first
|
|
||||||
if (head) {
|
|
||||||
aChildren.InsertElementAt(0, head);
|
|
||||||
}
|
|
||||||
|
|
||||||
// put the tfoot after the last tbody
|
|
||||||
if (foot) {
|
|
||||||
aChildren.AppendElement(foot);
|
|
||||||
}
|
|
||||||
|
|
||||||
PRUint32 rowGroupCount = aChildren.Length();
|
|
||||||
aChildren.AppendElements(nonRowGroups);
|
|
||||||
|
|
||||||
return rowGroupCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTableRowGroupFrame*
|
nsTableRowGroupFrame*
|
||||||
@ -2687,10 +2546,7 @@ nsTableFrame::GetTHead() const
|
|||||||
while (kidFrame) {
|
while (kidFrame) {
|
||||||
if (kidFrame->GetStyleDisplay()->mDisplay ==
|
if (kidFrame->GetStyleDisplay()->mDisplay ==
|
||||||
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP) {
|
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP) {
|
||||||
nsTableRowGroupFrame* rg = GetRowGroupFrame(kidFrame);
|
return static_cast<nsTableRowGroupFrame*>(kidFrame);
|
||||||
if (rg) {
|
|
||||||
return rg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the next sibling but skip it if it's also the next-in-flow, since
|
// Get the next sibling but skip it if it's also the next-in-flow, since
|
||||||
@ -2713,10 +2569,7 @@ nsTableFrame::GetTFoot() const
|
|||||||
while (kidFrame) {
|
while (kidFrame) {
|
||||||
if (kidFrame->GetStyleDisplay()->mDisplay ==
|
if (kidFrame->GetStyleDisplay()->mDisplay ==
|
||||||
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP) {
|
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP) {
|
||||||
nsTableRowGroupFrame* rg = GetRowGroupFrame(kidFrame);
|
return static_cast<nsTableRowGroupFrame*>(kidFrame);
|
||||||
if (rg) {
|
|
||||||
return rg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the next sibling but skip it if it's also the next-in-flow, since
|
// Get the next sibling but skip it if it's also the next-in-flow, since
|
||||||
@ -2746,13 +2599,6 @@ nsTableFrame::SetupHeaderFooterChild(const nsTableReflowState& aReflowState,
|
|||||||
nsPresContext* presContext = PresContext();
|
nsPresContext* presContext = PresContext();
|
||||||
nscoord pageHeight = presContext->GetPageSize().height;
|
nscoord pageHeight = presContext->GetPageSize().height;
|
||||||
|
|
||||||
if (aFrame->GetParent() != this || pageHeight == NS_UNCONSTRAINEDSIZE) {
|
|
||||||
// Must be a scrollable head/footer (we don't allow those to repeat), or
|
|
||||||
// page has unconstrained height for some reason.
|
|
||||||
*aDesiredHeight = 0;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reflow the child with unconstrainted height
|
// Reflow the child with unconstrainted height
|
||||||
nsHTMLReflowState kidReflowState(presContext, aReflowState.reflowState,
|
nsHTMLReflowState kidReflowState(presContext, aReflowState.reflowState,
|
||||||
aFrame,
|
aFrame,
|
||||||
@ -2798,9 +2644,9 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||||||
mBits.mResizedColumns ||
|
mBits.mResizedColumns ||
|
||||||
IsGeometryDirty();
|
IsGeometryDirty();
|
||||||
|
|
||||||
FrameArray rowGroups;
|
RowGroupArray rowGroups;
|
||||||
nsTableRowGroupFrame *thead, *tfoot;
|
nsTableRowGroupFrame *thead, *tfoot;
|
||||||
PRUint32 numRowGroups = OrderRowGroups(rowGroups, &thead, &tfoot);
|
OrderRowGroups(rowGroups, &thead, &tfoot);
|
||||||
PRBool pageBreak = PR_FALSE;
|
PRBool pageBreak = PR_FALSE;
|
||||||
nscoord footerHeight = 0;
|
nscoord footerHeight = 0;
|
||||||
|
|
||||||
@ -2826,7 +2672,7 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PRUint32 childX = 0; childX < numRowGroups; childX++) {
|
for (PRUint32 childX = 0; childX < rowGroups.Length(); childX++) {
|
||||||
nsIFrame* kidFrame = rowGroups[childX];
|
nsIFrame* kidFrame = rowGroups[childX];
|
||||||
// Get the frame state bits
|
// Get the frame state bits
|
||||||
// See if we should only reflow the dirty child frames
|
// See if we should only reflow the dirty child frames
|
||||||
@ -2845,7 +2691,8 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||||||
// if the child is a tbody in paginated mode reduce the height by a repeated footer
|
// if the child is a tbody in paginated mode reduce the height by a repeated footer
|
||||||
PRBool allowRepeatedFooter = PR_FALSE;
|
PRBool allowRepeatedFooter = PR_FALSE;
|
||||||
if (isPaginated && (NS_UNCONSTRAINEDSIZE != kidAvailSize.height)) {
|
if (isPaginated && (NS_UNCONSTRAINEDSIZE != kidAvailSize.height)) {
|
||||||
nsTableRowGroupFrame* kidRG = GetRowGroupFrame(kidFrame);
|
nsTableRowGroupFrame* kidRG =
|
||||||
|
static_cast<nsTableRowGroupFrame*>(kidFrame);
|
||||||
if (kidRG != thead && kidRG != tfoot && tfoot && tfoot->IsRepeatable()) {
|
if (kidRG != thead && kidRG != tfoot && tfoot && tfoot->IsRepeatable()) {
|
||||||
// the child is a tbody and there is a repeatable footer
|
// the child is a tbody and there is a repeatable footer
|
||||||
NS_ASSERTION(tfoot == rowGroups[rowGroups.Length() - 1], "Missing footer!");
|
NS_ASSERTION(tfoot == rowGroups[rowGroups.Length() - 1], "Missing footer!");
|
||||||
@ -2894,11 +2741,11 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||||||
|
|
||||||
if (reorder) {
|
if (reorder) {
|
||||||
// reorder row groups the reflow may have changed the nextinflows
|
// reorder row groups the reflow may have changed the nextinflows
|
||||||
numRowGroups = OrderRowGroups(rowGroups, &thead, &tfoot);
|
OrderRowGroups(rowGroups, &thead, &tfoot);
|
||||||
childX = rowGroups.IndexOf(kidFrame);
|
childX = rowGroups.IndexOf(kidFrame);
|
||||||
if (childX == RowGroupArray::NoIndex) {
|
if (childX == RowGroupArray::NoIndex) {
|
||||||
// XXXbz can this happen?
|
// XXXbz can this happen?
|
||||||
childX = numRowGroups;
|
childX = rowGroups.Length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// see if the rowgroup did not fit on this page might be pushed on
|
// see if the rowgroup did not fit on this page might be pushed on
|
||||||
@ -2938,7 +2785,7 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||||||
if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated &&
|
if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated &&
|
||||||
(NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight)) {
|
(NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight)) {
|
||||||
nsIFrame* nextKid =
|
nsIFrame* nextKid =
|
||||||
(childX + 1 < numRowGroups) ? rowGroups[childX + 1] : nsnull;
|
(childX + 1 < rowGroups.Length()) ? rowGroups[childX + 1] : nsnull;
|
||||||
pageBreak = PageBreakAfter(*kidFrame, nextKid);
|
pageBreak = PageBreakAfter(*kidFrame, nextKid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2972,7 +2819,8 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Put the nextinflow so that it will get pushed
|
// Put the nextinflow so that it will get pushed
|
||||||
rowGroups.InsertElementAt(childX + 1, kidNextInFlow);
|
rowGroups.InsertElementAt(childX + 1,
|
||||||
|
static_cast <nsTableRowGroupFrame*>(kidNextInFlow));
|
||||||
|
|
||||||
// We've used up all of our available space so push the remaining
|
// We've used up all of our available space so push the remaining
|
||||||
// children to the next-in-flow
|
// children to the next-in-flow
|
||||||
@ -3066,15 +2914,10 @@ nsTableFrame::CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLRef
|
|||||||
nscoord cellSpacingY = GetCellSpacingY();
|
nscoord cellSpacingY = GetCellSpacingY();
|
||||||
nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
|
nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
|
||||||
|
|
||||||
// get the natural height based on the last child's (row group or scroll frame) rect
|
// get the natural height based on the last child's (row group) rect
|
||||||
FrameArray rowGroups;
|
RowGroupArray rowGroups;
|
||||||
PRUint32 numRowGroups;
|
OrderRowGroups(rowGroups);
|
||||||
{
|
if (rowGroups.IsEmpty()) {
|
||||||
// Scope for the dummies so we don't use them by accident
|
|
||||||
nsTableRowGroupFrame *dummy1, *dummy2;
|
|
||||||
numRowGroups = OrderRowGroups(rowGroups, &dummy1, &dummy2);
|
|
||||||
}
|
|
||||||
if (numRowGroups == 0) {
|
|
||||||
// tables can be used as rectangular items without content
|
// tables can be used as rectangular items without content
|
||||||
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
||||||
if ((NS_UNCONSTRAINEDSIZE != tableSpecifiedHeight) &&
|
if ((NS_UNCONSTRAINEDSIZE != tableSpecifiedHeight) &&
|
||||||
@ -3092,7 +2935,7 @@ nsTableFrame::CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLRef
|
|||||||
nscoord desiredHeight = borderPadding.top + borderPadding.bottom;
|
nscoord desiredHeight = borderPadding.top + borderPadding.bottom;
|
||||||
if (rowCount > 0 && colCount > 0) {
|
if (rowCount > 0 && colCount > 0) {
|
||||||
desiredHeight += cellSpacingY;
|
desiredHeight += cellSpacingY;
|
||||||
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
|
for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
||||||
desiredHeight += rowGroups[rgX]->GetSize().height + cellSpacingY;
|
desiredHeight += rowGroups[rgX]->GetSize().height + cellSpacingY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3388,7 +3231,6 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
|||||||
PR_FALSE);
|
PR_FALSE);
|
||||||
}
|
}
|
||||||
// Make sure child views are properly positioned
|
// Make sure child views are properly positioned
|
||||||
// XXX what happens if childFrame is a scroll frame and this gets skipped? see also below
|
|
||||||
}
|
}
|
||||||
else if (amountUsed > 0 && yOriginRG != rgRect.y) {
|
else if (amountUsed > 0 && yOriginRG != rgRect.y) {
|
||||||
rgFrame->InvalidateOverflowRect();
|
rgFrame->InvalidateOverflowRect();
|
||||||
@ -3478,8 +3320,6 @@ nsTableFrame::GetBaseline() const
|
|||||||
OrderRowGroups(orderedRowGroups);
|
OrderRowGroups(orderedRowGroups);
|
||||||
nsTableRowFrame* firstRow = nsnull;
|
nsTableRowFrame* firstRow = nsnull;
|
||||||
for (PRUint32 rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
for (PRUint32 rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
||||||
// XXXbz Do we really want to just let through the scrollable
|
|
||||||
// rowgroups and use their ascent?
|
|
||||||
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
|
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
|
||||||
if (rgFrame->GetRowCount()) {
|
if (rgFrame->GetRowCount()) {
|
||||||
firstRow = rgFrame->GetFirstRow();
|
firstRow = rgFrame->GetFirstRow();
|
||||||
@ -3625,30 +3465,31 @@ nsTableFrame::GetFrameAtOrBefore(nsIFrame* aParentFrame,
|
|||||||
void
|
void
|
||||||
nsTableFrame::DumpRowGroup(nsIFrame* aKidFrame)
|
nsTableFrame::DumpRowGroup(nsIFrame* aKidFrame)
|
||||||
{
|
{
|
||||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(aKidFrame);
|
if (!aKidFrame)
|
||||||
if (rgFrame) {
|
return;
|
||||||
nsIFrame* cFrame = rgFrame->GetFirstChild(nsnull);
|
|
||||||
while (cFrame) {
|
nsIFrame* cFrame = aKidFrame->GetFirstChild(nsnull);
|
||||||
nsTableRowFrame *rowFrame = do_QueryFrame(cFrame);
|
while (cFrame) {
|
||||||
if (rowFrame) {
|
nsTableRowFrame *rowFrame = do_QueryFrame(cFrame);
|
||||||
printf("row(%d)=%p ", rowFrame->GetRowIndex(), rowFrame);
|
if (rowFrame) {
|
||||||
nsIFrame* childFrame = cFrame->GetFirstChild(nsnull);
|
printf("row(%d)=%p ", rowFrame->GetRowIndex(),
|
||||||
while (childFrame) {
|
static_cast<void*>(rowFrame));
|
||||||
nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
|
nsIFrame* childFrame = cFrame->GetFirstChild(nsnull);
|
||||||
if (cellFrame) {
|
while (childFrame) {
|
||||||
PRInt32 colIndex;
|
nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
|
||||||
cellFrame->GetColIndex(colIndex);
|
if (cellFrame) {
|
||||||
printf("cell(%d)=%p ", colIndex, childFrame);
|
PRInt32 colIndex;
|
||||||
}
|
cellFrame->GetColIndex(colIndex);
|
||||||
childFrame = childFrame->GetNextSibling();
|
printf("cell(%d)=%p ", colIndex, childFrame);
|
||||||
}
|
}
|
||||||
printf("\n");
|
childFrame = childFrame->GetNextSibling();
|
||||||
}
|
}
|
||||||
else {
|
printf("\n");
|
||||||
DumpRowGroup(rowFrame);
|
|
||||||
}
|
|
||||||
cFrame = cFrame->GetNextSibling();
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
DumpRowGroup(rowFrame);
|
||||||
|
}
|
||||||
|
cFrame = cFrame->GetNextSibling();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3683,7 +3524,7 @@ nsTableFrame::Dump(PRBool aDumpRows,
|
|||||||
if (0 == (colX % 8)) {
|
if (0 == (colX % 8)) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
printf ("%d=%p ", colX, colFrame);
|
printf ("%d=%p ", colX, static_cast<void*>(colFrame));
|
||||||
nsTableColType colType = colFrame->GetColType();
|
nsTableColType colType = colFrame->GetColType();
|
||||||
switch (colType) {
|
switch (colType) {
|
||||||
case eColContent:
|
case eColContent:
|
||||||
@ -4327,7 +4168,7 @@ BCMapCellInfo::SetInfo(nsTableRowFrame* aNewRow,
|
|||||||
// possible
|
// possible
|
||||||
PRUint32 rgStart = aIter->mRowGroupStart;
|
PRUint32 rgStart = aIter->mRowGroupStart;
|
||||||
PRUint32 rgEnd = aIter->mRowGroupEnd;
|
PRUint32 rgEnd = aIter->mRowGroupEnd;
|
||||||
mRowGroup = mTableFrame->GetRowGroupFrame(mTopRow->GetParent());
|
mRowGroup = static_cast<nsTableRowGroupFrame*>(mTopRow->GetParent());
|
||||||
if (mRowGroup != aIter->GetCurrentRowGroup()) {
|
if (mRowGroup != aIter->GetCurrentRowGroup()) {
|
||||||
rgStart = mRowGroup->GetStartRowIndex();
|
rgStart = mRowGroup->GetStartRowIndex();
|
||||||
rgEnd = rgStart + mRowGroup->GetRowCount() - 1;
|
rgEnd = rgStart + mRowGroup->GetRowCount() - 1;
|
||||||
|
@ -480,16 +480,11 @@ public:
|
|||||||
virtual void RemoveCell(nsTableCellFrame* aCellFrame,
|
virtual void RemoveCell(nsTableCellFrame* aCellFrame,
|
||||||
PRInt32 aRowIndex);
|
PRInt32 aRowIndex);
|
||||||
|
|
||||||
void AppendRows(nsTableRowGroupFrame& aRowGroupFrame,
|
void AppendRows(nsTableRowGroupFrame* aRowGroupFrame,
|
||||||
PRInt32 aRowIndex,
|
PRInt32 aRowIndex,
|
||||||
nsTArray<nsTableRowFrame*>& aRowFrames);
|
nsTArray<nsTableRowFrame*>& aRowFrames);
|
||||||
|
|
||||||
PRInt32 InsertRow(nsTableRowGroupFrame& aRowGroupFrame,
|
PRInt32 InsertRows(nsTableRowGroupFrame* aRowGroupFrame,
|
||||||
nsIFrame& aFrame,
|
|
||||||
PRInt32 aRowIndex,
|
|
||||||
PRBool aConsiderSpans);
|
|
||||||
|
|
||||||
PRInt32 InsertRows(nsTableRowGroupFrame& aRowGroupFrame,
|
|
||||||
nsTArray<nsTableRowFrame*>& aFrames,
|
nsTArray<nsTableRowFrame*>& aFrames,
|
||||||
PRInt32 aRowIndex,
|
PRInt32 aRowIndex,
|
||||||
PRBool aConsiderSpans);
|
PRBool aConsiderSpans);
|
||||||
@ -629,13 +624,15 @@ protected:
|
|||||||
const nsRect& aOriginalKidOverflowRect);
|
const nsRect& aOriginalKidOverflowRect);
|
||||||
|
|
||||||
nsIFrame* GetFirstBodyRowGroupFrame();
|
nsIFrame* GetFirstBodyRowGroupFrame();
|
||||||
|
public:
|
||||||
|
typedef nsAutoTPtrArray<nsTableRowGroupFrame, 8> RowGroupArray;
|
||||||
/**
|
/**
|
||||||
* Push all our child frames from the aFrames array, in order, starting from the
|
* Push all our child frames from the aRowGroups array, in order, starting
|
||||||
* frame at aPushFrom to the end of the array. The frames are put on our overflow
|
* from the frame at aPushFrom to the end of the array. The frames are put on
|
||||||
* list or moved directly to our next-in-flow if one exists.
|
* our overflow list or moved directly to our next-in-flow if one exists.
|
||||||
*/
|
*/
|
||||||
typedef nsAutoTPtrArray<nsIFrame, 8> FrameArray;
|
protected:
|
||||||
void PushChildren(const FrameArray& aFrames, PRInt32 aPushFrom);
|
void PushChildren(const RowGroupArray& aRowGroups, PRInt32 aPushFrom);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// put the children frames in the display order (e.g. thead before tbodies
|
// put the children frames in the display order (e.g. thead before tbodies
|
||||||
@ -643,8 +640,10 @@ public:
|
|||||||
// children, and not append nulls, so the array is guaranteed to contain
|
// children, and not append nulls, so the array is guaranteed to contain
|
||||||
// nsTableRowGroupFrames. If there are multiple theads or tfoots, all but
|
// nsTableRowGroupFrames. If there are multiple theads or tfoots, all but
|
||||||
// the first one are treated as tbodies instead.
|
// the first one are treated as tbodies instead.
|
||||||
typedef nsAutoTPtrArray<nsTableRowGroupFrame, 8> RowGroupArray;
|
|
||||||
void OrderRowGroups(RowGroupArray& aChildren) const;
|
void OrderRowGroups(RowGroupArray& aChildren,
|
||||||
|
nsTableRowGroupFrame** aHead = nsnull,
|
||||||
|
nsTableRowGroupFrame** aFoot = nsnull) const;
|
||||||
|
|
||||||
// Return the thead, if any
|
// Return the thead, if any
|
||||||
nsTableRowGroupFrame* GetTHead() const;
|
nsTableRowGroupFrame* GetTHead() const;
|
||||||
@ -652,25 +651,6 @@ public:
|
|||||||
// Return the tfoot, if any
|
// Return the tfoot, if any
|
||||||
nsTableRowGroupFrame* GetTFoot() const;
|
nsTableRowGroupFrame* GetTFoot() const;
|
||||||
|
|
||||||
protected:
|
|
||||||
// As above, but does NOT actually call GetRowGroupFrame() on the kids, so
|
|
||||||
// returns an array of nsIFrames. This is to be used when you really want
|
|
||||||
// the flowable kids of the table, not the rowgroups. This outputs the thead
|
|
||||||
// and tfoot if they happen to be rowgroups. All the child nsIFrames of the
|
|
||||||
// table that return null if you call GetRowGroupFrame() on them will appear
|
|
||||||
// at the end of the array, after the tfoot, if any.
|
|
||||||
//
|
|
||||||
// aHead and aFoot must not be null.
|
|
||||||
//
|
|
||||||
// @return the number of frames in aChildren which return non-null if you
|
|
||||||
// call GetRowGroupFrame() on them.
|
|
||||||
//
|
|
||||||
// XXXbz why do we really care about the non-rowgroup kids?
|
|
||||||
PRUint32 OrderRowGroups(FrameArray& aChildren,
|
|
||||||
nsTableRowGroupFrame** aHead,
|
|
||||||
nsTableRowGroupFrame** aFoot) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Returns PR_TRUE if there are any cells above the row at
|
// Returns PR_TRUE if there are any cells above the row at
|
||||||
// aRowIndex and spanning into the row at aRowIndex, the number of
|
// aRowIndex and spanning into the row at aRowIndex, the number of
|
||||||
// effective columns limits the search up to that column
|
// effective columns limits the search up to that column
|
||||||
@ -742,11 +722,6 @@ public:
|
|||||||
|
|
||||||
nsTArray<nsTableColFrame*>& GetColCache();
|
nsTArray<nsTableColFrame*>& GetColCache();
|
||||||
|
|
||||||
/** Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
|
|
||||||
*/
|
|
||||||
static nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
|
|
||||||
nsIAtom* aFrameTypeIn = nsnull);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void SetBorderCollapse(PRBool aValue);
|
void SetBorderCollapse(PRBool aValue);
|
||||||
@ -763,7 +738,7 @@ protected:
|
|||||||
|
|
||||||
public: /* ----- Cell Map public methods ----- */
|
public: /* ----- Cell Map public methods ----- */
|
||||||
|
|
||||||
PRInt32 GetStartRowIndex(nsTableRowGroupFrame& aRowGroupFrame);
|
PRInt32 GetStartRowIndex(nsTableRowGroupFrame* aRowGroupFrame);
|
||||||
|
|
||||||
/** returns the number of rows in this table.
|
/** returns the number of rows in this table.
|
||||||
*/
|
*/
|
||||||
|
@ -454,8 +454,7 @@ TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
|
|||||||
// group may not be a child of the table.
|
// group may not be a child of the table.
|
||||||
mRowGroup.mRect.MoveTo(rg->GetOffsetTo(aTableFrame));
|
mRowGroup.mRect.MoveTo(rg->GetOffsetTo(aTableFrame));
|
||||||
if (mRowGroup.mRect.Intersects(mDirtyRect - mRenderPt)) {
|
if (mRowGroup.mRect.Intersects(mDirtyRect - mRenderPt)) {
|
||||||
nsresult rv = PaintRowGroup(rg,
|
nsresult rv = PaintRowGroup(rg, rg->IsPseudoStackingContextFromStyle());
|
||||||
rg->IsPseudoStackingContextFromStyle() || rg->IsScrolled());
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ PRInt32 nsTableRowGroupFrame::GetStartRowIndex()
|
|||||||
if (-1 == result) {
|
if (-1 == result) {
|
||||||
nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
|
nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
|
||||||
if (tableFrame) {
|
if (tableFrame) {
|
||||||
return tableFrame->GetStartRowIndex(*this);
|
return tableFrame->GetStartRowIndex(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
if (!IsVisibleInSelection(aBuilder))
|
if (!IsVisibleInSelection(aBuilder))
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
PRBool isRoot = aBuilder->IsAtRootOfPseudoStackingContext() || IsScrolled();
|
PRBool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
|
||||||
nsDisplayTableItem* item = nsnull;
|
nsDisplayTableItem* item = nsnull;
|
||||||
if (isRoot) {
|
if (isRoot) {
|
||||||
// This background is created regardless of whether this frame is
|
// This background is created regardless of whether this frame is
|
||||||
@ -1409,7 +1409,7 @@ nsTableRowGroupFrame::AppendFrames(nsIAtom* aListName,
|
|||||||
if (rows.Length() > 0) {
|
if (rows.Length() > 0) {
|
||||||
nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
|
nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
|
||||||
if (tableFrame) {
|
if (tableFrame) {
|
||||||
tableFrame->AppendRows(*this, rowIndex, rows);
|
tableFrame->AppendRows(this, rowIndex, rows);
|
||||||
PresContext()->PresShell()->
|
PresContext()->PresShell()->
|
||||||
FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
||||||
NS_FRAME_HAS_DIRTY_CHILDREN);
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
||||||
@ -1463,7 +1463,7 @@ nsTableRowGroupFrame::InsertFrames(nsIAtom* aListName,
|
|||||||
if (numRows > 0) {
|
if (numRows > 0) {
|
||||||
nsTableRowFrame* prevRow = (nsTableRowFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, nsGkAtoms::tableRowFrame);
|
nsTableRowFrame* prevRow = (nsTableRowFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, nsGkAtoms::tableRowFrame);
|
||||||
PRInt32 rowIndex = (prevRow) ? prevRow->GetRowIndex() + 1 : startRowIndex;
|
PRInt32 rowIndex = (prevRow) ? prevRow->GetRowIndex() + 1 : startRowIndex;
|
||||||
tableFrame->InsertRows(*this, rows, rowIndex, PR_TRUE);
|
tableFrame->InsertRows(this, rows, rowIndex, PR_TRUE);
|
||||||
|
|
||||||
PresContext()->PresShell()->
|
PresContext()->PresShell()->
|
||||||
FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
#include "nsILineIterator.h"
|
#include "nsILineIterator.h"
|
||||||
#include "nsTablePainter.h"
|
#include "nsTablePainter.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsCSSAnonBoxes.h"
|
|
||||||
|
|
||||||
class nsTableFrame;
|
class nsTableFrame;
|
||||||
class nsTableRowFrame;
|
class nsTableRowFrame;
|
||||||
@ -359,13 +358,6 @@ public:
|
|||||||
* decided not to use a cursor or we already have one set up.
|
* decided not to use a cursor or we already have one set up.
|
||||||
*/
|
*/
|
||||||
FrameCursorData* SetupRowCursor();
|
FrameCursorData* SetupRowCursor();
|
||||||
|
|
||||||
PRBool IsScrolled() {
|
|
||||||
// Note that if mOverflowY is CLIP, so is mOverflowX, and we need to clip the background
|
|
||||||
// as if the rowgroup is scrollable.
|
|
||||||
return GetStyleContext()->GetPseudo() == nsCSSAnonBoxes::scrolledContent ||
|
|
||||||
GetStyleDisplay()->mOverflowY == NS_STYLE_OVERFLOW_CLIP;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual nsILineIterator* GetLineIterator() { return this; }
|
virtual nsILineIterator* GetLineIterator() { return this; }
|
||||||
|
|
||||||
|
@ -44,54 +44,128 @@ Runs the reftest test harness.
|
|||||||
import sys, shutil, os, os.path
|
import sys, shutil, os, os.path
|
||||||
SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
|
SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
|
||||||
sys.path.append(SCRIPT_DIRECTORY)
|
sys.path.append(SCRIPT_DIRECTORY)
|
||||||
import automation
|
from automation import Automation
|
||||||
from automationutils import *
|
from automationutils import *
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
|
|
||||||
oldcwd = os.getcwd()
|
class RefTest(object):
|
||||||
os.chdir(SCRIPT_DIRECTORY)
|
|
||||||
|
|
||||||
def getFullPath(path):
|
oldcwd = os.getcwd()
|
||||||
"Get an absolute path relative to oldcwd."
|
|
||||||
return os.path.normpath(os.path.join(oldcwd, os.path.expanduser(path)))
|
|
||||||
|
|
||||||
def createReftestProfile(options, profileDir):
|
def __init__(self, automation):
|
||||||
"Sets up a profile for reftest."
|
self.automation = automation
|
||||||
|
os.chdir(SCRIPT_DIRECTORY)
|
||||||
|
|
||||||
# Set preferences.
|
def getFullPath(self, path):
|
||||||
prefsFile = open(os.path.join(profileDir, "user.js"), "w")
|
"Get an absolute path relative to self.oldcwd."
|
||||||
prefsFile.write("""user_pref("browser.dom.window.dump.enabled", true);
|
return os.path.normpath(os.path.join(self.oldcwd, os.path.expanduser(path)))
|
||||||
""")
|
|
||||||
prefsFile.write('user_pref("reftest.timeout", %d);\n' % (options.timeout * 1000))
|
|
||||||
prefsFile.write('user_pref("ui.caretBlinkTime", -1);\n')
|
|
||||||
|
|
||||||
for v in options.extraPrefs:
|
def createReftestProfile(self, options, profileDir):
|
||||||
thispref = v.split("=")
|
"Sets up a profile for reftest."
|
||||||
if len(thispref) < 2:
|
|
||||||
print "Error: syntax error in --setpref=" + v
|
# Set preferences.
|
||||||
sys.exit(1)
|
prefsFile = open(os.path.join(profileDir, "user.js"), "w")
|
||||||
part = 'user_pref("%s", %s);\n' % (thispref[0], thispref[1])
|
prefsFile.write("""user_pref("browser.dom.window.dump.enabled", true);
|
||||||
prefsFile.write(part)
|
""")
|
||||||
# no slow script dialogs
|
prefsFile.write('user_pref("reftest.timeout", %d);\n' % (options.timeout * 1000))
|
||||||
prefsFile.write('user_pref("dom.max_script_run_time", 0);')
|
prefsFile.write('user_pref("ui.caretBlinkTime", -1);\n')
|
||||||
prefsFile.write('user_pref("dom.max_chrome_script_run_time", 0);')
|
|
||||||
prefsFile.close()
|
for v in options.extraPrefs:
|
||||||
|
thispref = v.split("=")
|
||||||
|
if len(thispref) < 2:
|
||||||
|
print "Error: syntax error in --setpref=" + v
|
||||||
|
sys.exit(1)
|
||||||
|
part = 'user_pref("%s", %s);\n' % (thispref[0], thispref[1])
|
||||||
|
prefsFile.write(part)
|
||||||
|
# no slow script dialogs
|
||||||
|
prefsFile.write('user_pref("dom.max_script_run_time", 0);')
|
||||||
|
prefsFile.write('user_pref("dom.max_chrome_script_run_time", 0);')
|
||||||
|
prefsFile.close()
|
||||||
|
|
||||||
|
# install the reftest extension bits into the profile
|
||||||
|
profileExtensionsPath = os.path.join(profileDir, "extensions")
|
||||||
|
os.mkdir(profileExtensionsPath)
|
||||||
|
reftestExtensionPath = os.path.join(SCRIPT_DIRECTORY, "reftest")
|
||||||
|
extFile = open(os.path.join(profileExtensionsPath, "reftest@mozilla.org"), "w")
|
||||||
|
extFile.write(reftestExtensionPath)
|
||||||
|
extFile.close()
|
||||||
|
|
||||||
|
def runTests(self, manifest, options):
|
||||||
|
debuggerInfo = getDebuggerInfo(self.oldcwd, options.debugger, options.debuggerArgs,
|
||||||
|
options.debuggerInteractive);
|
||||||
|
|
||||||
|
profileDir = None
|
||||||
|
try:
|
||||||
|
profileDir = mkdtemp()
|
||||||
|
self.createReftestProfile(options, profileDir)
|
||||||
|
self.copyExtraFilesToProfile(options, profileDir)
|
||||||
|
|
||||||
|
# browser environment
|
||||||
|
browserEnv = self.automation.environment(xrePath = options.xrePath)
|
||||||
|
browserEnv["XPCOM_DEBUG_BREAK"] = "stack"
|
||||||
|
|
||||||
|
# Enable leaks detection to its own log file.
|
||||||
|
leakLogFile = os.path.join(profileDir, "runreftest_leaks.log")
|
||||||
|
browserEnv["XPCOM_MEM_BLOAT_LOG"] = leakLogFile
|
||||||
|
|
||||||
|
# run once with -silent to let the extension manager do its thing
|
||||||
|
# and then exit the app
|
||||||
|
self.automation.log.info("REFTEST INFO | runreftest.py | Performing extension manager registration: start.\n")
|
||||||
|
# Don't care about this |status|: |runApp()| reporting it should be enough.
|
||||||
|
status = self.automation.runApp(None, browserEnv, options.app, profileDir,
|
||||||
|
["-silent"],
|
||||||
|
utilityPath = options.utilityPath,
|
||||||
|
xrePath=options.xrePath,
|
||||||
|
symbolsPath=options.symbolsPath)
|
||||||
|
# We don't care to call |processLeakLog()| for this step.
|
||||||
|
self.automation.log.info("\nREFTEST INFO | runreftest.py | Performing extension manager registration: end.")
|
||||||
|
|
||||||
|
# Remove the leak detection file so it can't "leak" to the tests run.
|
||||||
|
# The file is not there if leak logging was not enabled in the application build.
|
||||||
|
if os.path.exists(leakLogFile):
|
||||||
|
os.remove(leakLogFile)
|
||||||
|
|
||||||
|
# then again to actually run reftest
|
||||||
|
self.automation.log.info("REFTEST INFO | runreftest.py | Running tests: start.\n")
|
||||||
|
reftestlist = self.getFullPath(manifest)
|
||||||
|
status = self.automation.runApp(None, browserEnv, options.app, profileDir,
|
||||||
|
["-reftest", reftestlist],
|
||||||
|
utilityPath = options.utilityPath,
|
||||||
|
xrePath=options.xrePath,
|
||||||
|
debuggerInfo=debuggerInfo,
|
||||||
|
symbolsPath=options.symbolsPath,
|
||||||
|
# give the JS harness 30 seconds to deal
|
||||||
|
# with its own timeouts
|
||||||
|
timeout=options.timeout + 30.0)
|
||||||
|
processLeakLog(leakLogFile, options.leakThreshold)
|
||||||
|
self.automation.log.info("\nREFTEST INFO | runreftest.py | Running tests: end.")
|
||||||
|
finally:
|
||||||
|
if profileDir:
|
||||||
|
shutil.rmtree(profileDir)
|
||||||
|
return status
|
||||||
|
|
||||||
|
def copyExtraFilesToProfile(self, options, profileDir):
|
||||||
|
"Copy extra files or dirs specified on the command line to the testing profile."
|
||||||
|
for f in options.extraProfileFiles:
|
||||||
|
abspath = self.getFullPath(f)
|
||||||
|
dest = os.path.join(profileDir, os.path.basename(abspath))
|
||||||
|
if os.path.isdir(abspath):
|
||||||
|
shutil.copytree(abspath, dest)
|
||||||
|
else:
|
||||||
|
shutil.copy(abspath, dest)
|
||||||
|
|
||||||
# install the reftest extension bits into the profile
|
|
||||||
profileExtensionsPath = os.path.join(profileDir, "extensions")
|
|
||||||
os.mkdir(profileExtensionsPath)
|
|
||||||
reftestExtensionPath = os.path.join(SCRIPT_DIRECTORY, "reftest")
|
|
||||||
extFile = open(os.path.join(profileExtensionsPath, "reftest@mozilla.org"), "w")
|
|
||||||
extFile.write(reftestExtensionPath)
|
|
||||||
extFile.close()
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
automation = Automation()
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
|
reftest = RefTest(automation)
|
||||||
|
|
||||||
# we want to pass down everything from automation.__all__
|
# we want to pass down everything from automation.__all__
|
||||||
addCommonOptions(parser, defaults=dict(zip(automation.__all__, [getattr(automation, x) for x in automation.__all__])))
|
addCommonOptions(parser,
|
||||||
automation.addExtraCommonOptions(parser)
|
defaults=dict(zip(automation.__all__,
|
||||||
|
[getattr(automation, x) for x in automation.__all__])))
|
||||||
|
automation.addCommonOptions(parser)
|
||||||
parser.add_option("--appname",
|
parser.add_option("--appname",
|
||||||
action = "store", type = "string", dest = "app",
|
action = "store", type = "string", dest = "app",
|
||||||
default = os.path.join(SCRIPT_DIRECTORY, automation.DEFAULT_APP),
|
default = os.path.join(SCRIPT_DIRECTORY, automation.DEFAULT_APP),
|
||||||
@ -118,90 +192,28 @@ def main():
|
|||||||
"programs (xpcshell, ssltunnel, certutil)")
|
"programs (xpcshell, ssltunnel, certutil)")
|
||||||
|
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
print >>sys.stderr, "No reftest.list specified."
|
print >>sys.stderr, "No reftest.list specified."
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
options.app = getFullPath(options.app)
|
options.app = reftest.getFullPath(options.app)
|
||||||
if not os.path.exists(options.app):
|
if not os.path.exists(options.app):
|
||||||
print """Error: Path %(app)s doesn't exist.
|
print """Error: Path %(app)s doesn't exist.
|
||||||
Are you executing $objdir/_tests/reftest/runreftest.py?""" \
|
Are you executing $objdir/_tests/reftest/runreftest.py?""" \
|
||||||
% {"app": options.app}
|
% {"app": options.app}
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if options.xrePath is None:
|
if options.xrePath is None:
|
||||||
options.xrePath = os.path.dirname(options.app)
|
options.xrePath = os.path.dirname(options.app)
|
||||||
else:
|
else:
|
||||||
# allow relative paths
|
# allow relative paths
|
||||||
options.xrePath = getFullPath(options.xrePath)
|
options.xrePath = reftest.getFullPath(options.xrePath)
|
||||||
|
|
||||||
if options.symbolsPath:
|
if options.symbolsPath:
|
||||||
options.symbolsPath = getFullPath(options.symbolsPath)
|
options.symbolsPath = reftest.getFullPath(options.symbolsPath)
|
||||||
options.utilityPath = getFullPath(options.utilityPath)
|
options.utilityPath = reftest.getFullPath(options.utilityPath)
|
||||||
|
|
||||||
debuggerInfo = getDebuggerInfo(oldcwd, options.debugger, options.debuggerArgs,
|
|
||||||
options.debuggerInteractive);
|
|
||||||
|
|
||||||
profileDir = None
|
|
||||||
try:
|
|
||||||
profileDir = mkdtemp()
|
|
||||||
createReftestProfile(options, profileDir)
|
|
||||||
copyExtraFilesToProfile(options, profileDir)
|
|
||||||
|
|
||||||
# browser environment
|
|
||||||
browserEnv = automation.environment(xrePath = options.xrePath)
|
|
||||||
browserEnv["XPCOM_DEBUG_BREAK"] = "stack"
|
|
||||||
|
|
||||||
# Enable leaks detection to its own log file.
|
|
||||||
leakLogFile = os.path.join(profileDir, "runreftest_leaks.log")
|
|
||||||
browserEnv["XPCOM_MEM_BLOAT_LOG"] = leakLogFile
|
|
||||||
|
|
||||||
# run once with -silent to let the extension manager do its thing
|
|
||||||
# and then exit the app
|
|
||||||
automation.log.info("REFTEST INFO | runreftest.py | Performing extension manager registration: start.\n")
|
|
||||||
# Don't care about this |status|: |runApp()| reporting it should be enough.
|
|
||||||
status = automation.runApp(None, browserEnv, options.app, profileDir,
|
|
||||||
["-silent"],
|
|
||||||
utilityPath = options.utilityPath,
|
|
||||||
xrePath=options.xrePath,
|
|
||||||
symbolsPath=options.symbolsPath)
|
|
||||||
# We don't care to call |processLeakLog()| for this step.
|
|
||||||
automation.log.info("\nREFTEST INFO | runreftest.py | Performing extension manager registration: end.")
|
|
||||||
|
|
||||||
# Remove the leak detection file so it can't "leak" to the tests run.
|
|
||||||
# The file is not there if leak logging was not enabled in the application build.
|
|
||||||
if os.path.exists(leakLogFile):
|
|
||||||
os.remove(leakLogFile)
|
|
||||||
|
|
||||||
# then again to actually run reftest
|
|
||||||
automation.log.info("REFTEST INFO | runreftest.py | Running tests: start.\n")
|
|
||||||
reftestlist = getFullPath(args[0])
|
|
||||||
status = automation.runApp(None, browserEnv, options.app, profileDir,
|
|
||||||
["-reftest", reftestlist],
|
|
||||||
utilityPath = options.utilityPath,
|
|
||||||
xrePath=options.xrePath,
|
|
||||||
debuggerInfo=debuggerInfo,
|
|
||||||
symbolsPath=options.symbolsPath,
|
|
||||||
# give the JS harness 30 seconds to deal
|
|
||||||
# with its own timeouts
|
|
||||||
timeout=options.timeout + 30.0)
|
|
||||||
processLeakLog(leakLogFile, options.leakThreshold)
|
|
||||||
automation.log.info("\nREFTEST INFO | runreftest.py | Running tests: end.")
|
|
||||||
finally:
|
|
||||||
if profileDir:
|
|
||||||
shutil.rmtree(profileDir)
|
|
||||||
sys.exit(status)
|
|
||||||
|
|
||||||
def copyExtraFilesToProfile(options, profileDir):
|
|
||||||
"Copy extra files or dirs specified on the command line to the testing profile."
|
|
||||||
for f in options.extraProfileFiles:
|
|
||||||
abspath = getFullPath(f)
|
|
||||||
dest = os.path.join(profileDir, os.path.basename(abspath))
|
|
||||||
if os.path.isdir(abspath):
|
|
||||||
shutil.copytree(abspath, dest)
|
|
||||||
else:
|
|
||||||
shutil.copy(abspath, dest)
|
|
||||||
|
|
||||||
|
sys.exit(reftest.runTests(args[0], options))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -52,40 +52,9 @@ import shutil
|
|||||||
from urllib import quote_plus as encodeURIComponent
|
from urllib import quote_plus as encodeURIComponent
|
||||||
import urllib2
|
import urllib2
|
||||||
import commands
|
import commands
|
||||||
import automation
|
from automation import Automation
|
||||||
from automationutils import *
|
from automationutils import *
|
||||||
|
|
||||||
# Path to the test script on the server
|
|
||||||
TEST_SERVER_HOST = "localhost:8888"
|
|
||||||
TEST_PATH = "/tests/"
|
|
||||||
CHROME_PATH = "/redirect.html";
|
|
||||||
A11Y_PATH = "/redirect-a11y.html"
|
|
||||||
TESTS_URL = "http://" + TEST_SERVER_HOST + TEST_PATH
|
|
||||||
CHROMETESTS_URL = "http://" + TEST_SERVER_HOST + CHROME_PATH
|
|
||||||
A11YTESTS_URL = "http://" + TEST_SERVER_HOST + A11Y_PATH
|
|
||||||
SERVER_SHUTDOWN_URL = "http://" + TEST_SERVER_HOST + "/server/shutdown"
|
|
||||||
# main browser chrome URL, same as browser.chromeURL pref
|
|
||||||
#ifdef MOZ_SUITE
|
|
||||||
BROWSER_CHROME_URL = "chrome://navigator/content/navigator.xul"
|
|
||||||
#else
|
|
||||||
BROWSER_CHROME_URL = "chrome://browser/content/browser.xul"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# Max time in seconds to wait for server startup before tests will fail -- if
|
|
||||||
# this seems big, it's mostly for debug machines where cold startup
|
|
||||||
# (particularly after a build) takes forever.
|
|
||||||
if automation.IS_DEBUG_BUILD:
|
|
||||||
SERVER_STARTUP_TIMEOUT = 180
|
|
||||||
else:
|
|
||||||
SERVER_STARTUP_TIMEOUT = 90
|
|
||||||
|
|
||||||
oldcwd = os.getcwd()
|
|
||||||
SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
|
|
||||||
os.chdir(SCRIPT_DIRECTORY)
|
|
||||||
|
|
||||||
PROFILE_DIRECTORY = os.path.abspath("./mochitesttestingprofile")
|
|
||||||
|
|
||||||
LEAK_REPORT_FILE = os.path.join(PROFILE_DIRECTORY, "runtests_leaks.log")
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# COMMANDLINE OPTIONS #
|
# COMMANDLINE OPTIONS #
|
||||||
@ -93,13 +62,15 @@ LEAK_REPORT_FILE = os.path.join(PROFILE_DIRECTORY, "runtests_leaks.log")
|
|||||||
|
|
||||||
class MochitestOptions(optparse.OptionParser):
|
class MochitestOptions(optparse.OptionParser):
|
||||||
"""Parses Mochitest commandline options."""
|
"""Parses Mochitest commandline options."""
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, automation, scriptdir, **kwargs):
|
||||||
|
self._automation = automation
|
||||||
optparse.OptionParser.__init__(self, **kwargs)
|
optparse.OptionParser.__init__(self, **kwargs)
|
||||||
defaults = {}
|
defaults = {}
|
||||||
|
|
||||||
# we want to pass down everything from automation.__all__
|
# we want to pass down everything from self._automation.__all__
|
||||||
addCommonOptions(self, defaults=dict(zip(automation.__all__, [getattr(automation, x) for x in automation.__all__])))
|
addCommonOptions(self, defaults=dict(zip(self._automation.__all__,
|
||||||
automation.addExtraCommonOptions(self)
|
[getattr(self._automation, x) for x in self._automation.__all__])))
|
||||||
|
self._automation.addCommonOptions(self)
|
||||||
|
|
||||||
self.add_option("--close-when-done",
|
self.add_option("--close-when-done",
|
||||||
action = "store_true", dest = "closeWhenDone",
|
action = "store_true", dest = "closeWhenDone",
|
||||||
@ -109,17 +80,17 @@ class MochitestOptions(optparse.OptionParser):
|
|||||||
self.add_option("--appname",
|
self.add_option("--appname",
|
||||||
action = "store", type = "string", dest = "app",
|
action = "store", type = "string", dest = "app",
|
||||||
help = "absolute path to application, overriding default")
|
help = "absolute path to application, overriding default")
|
||||||
defaults["app"] = os.path.join(SCRIPT_DIRECTORY, automation.DEFAULT_APP)
|
defaults["app"] = os.path.join(scriptdir, self._automation.DEFAULT_APP)
|
||||||
|
|
||||||
self.add_option("--utility-path",
|
self.add_option("--utility-path",
|
||||||
action = "store", type = "string", dest = "utilityPath",
|
action = "store", type = "string", dest = "utilityPath",
|
||||||
help = "absolute path to directory containing utility programs (xpcshell, ssltunnel, certutil)")
|
help = "absolute path to directory containing utility programs (xpcshell, ssltunnel, certutil)")
|
||||||
defaults["utilityPath"] = automation.DIST_BIN
|
defaults["utilityPath"] = self._automation.DIST_BIN
|
||||||
|
|
||||||
self.add_option("--certificate-path",
|
self.add_option("--certificate-path",
|
||||||
action = "store", type = "string", dest = "certPath",
|
action = "store", type = "string", dest = "certPath",
|
||||||
help = "absolute path to directory containing certificate store to use testing profile")
|
help = "absolute path to directory containing certificate store to use testing profile")
|
||||||
defaults["certPath"] = automation.CERTS_SRC_DIR
|
defaults["certPath"] = self._automation.CERTS_SRC_DIR
|
||||||
|
|
||||||
self.add_option("--log-file",
|
self.add_option("--log-file",
|
||||||
action = "store", type = "string",
|
action = "store", type = "string",
|
||||||
@ -249,17 +220,19 @@ See <http://mochikit.com/doc/html/MochiKit/Logging.html> for details on the logg
|
|||||||
class MochitestServer:
|
class MochitestServer:
|
||||||
"Web server used to serve Mochitests, for closer fidelity to the real web."
|
"Web server used to serve Mochitests, for closer fidelity to the real web."
|
||||||
|
|
||||||
def __init__(self, options):
|
def __init__(self, automation, options, profileDir):
|
||||||
|
self._automation = automation
|
||||||
self._closeWhenDone = options.closeWhenDone
|
self._closeWhenDone = options.closeWhenDone
|
||||||
self._utilityPath = options.utilityPath
|
self._utilityPath = options.utilityPath
|
||||||
self._xrePath = options.xrePath
|
self._xrePath = options.xrePath
|
||||||
|
self._profileDir = profileDir
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"Run the Mochitest server, returning the process ID of the server."
|
"Run the Mochitest server, returning the process ID of the server."
|
||||||
|
|
||||||
env = automation.environment(xrePath = self._xrePath)
|
env = self._automation.environment(xrePath = self._xrePath)
|
||||||
env["XPCOM_DEBUG_BREAK"] = "warn"
|
env["XPCOM_DEBUG_BREAK"] = "warn"
|
||||||
if automation.IS_WIN32:
|
if self._automation.IS_WIN32:
|
||||||
env["PATH"] = env["PATH"] + ";" + self._xrePath
|
env["PATH"] = env["PATH"] + ";" + self._xrePath
|
||||||
|
|
||||||
args = ["-g", self._xrePath,
|
args = ["-g", self._xrePath,
|
||||||
@ -268,19 +241,18 @@ class MochitestServer:
|
|||||||
"-f", "./" + "server.js"]
|
"-f", "./" + "server.js"]
|
||||||
|
|
||||||
xpcshell = os.path.join(self._utilityPath,
|
xpcshell = os.path.join(self._utilityPath,
|
||||||
"xpcshell" + automation.BIN_SUFFIX)
|
"xpcshell" + self._automation.BIN_SUFFIX)
|
||||||
self._process = automation.Process([xpcshell] + args, env = env)
|
self._process = self._automation.Process([xpcshell] + args, env = env)
|
||||||
pid = self._process.pid
|
pid = self._process.pid
|
||||||
if pid < 0:
|
if pid < 0:
|
||||||
print "Error starting server."
|
print "Error starting server."
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
automation.log.info("INFO | runtests.py | Server pid: %d", pid)
|
self._automation.log.info("INFO | runtests.py | Server pid: %d", pid)
|
||||||
|
|
||||||
|
|
||||||
def ensureReady(self, timeout):
|
def ensureReady(self, timeout):
|
||||||
assert timeout >= 0
|
assert timeout >= 0
|
||||||
|
|
||||||
aliveFile = os.path.join(PROFILE_DIRECTORY, "server_alive.txt")
|
aliveFile = os.path.join(self._profileDir, "server_alive.txt")
|
||||||
i = 0
|
i = 0
|
||||||
while i < timeout:
|
while i < timeout:
|
||||||
if os.path.exists(aliveFile):
|
if os.path.exists(aliveFile):
|
||||||
@ -301,16 +273,261 @@ class MochitestServer:
|
|||||||
except:
|
except:
|
||||||
self._process.kill()
|
self._process.kill()
|
||||||
|
|
||||||
def getFullPath(path):
|
|
||||||
"Get an absolute path relative to oldcwd."
|
|
||||||
return os.path.normpath(os.path.join(oldcwd, os.path.expanduser(path)))
|
|
||||||
|
|
||||||
#################
|
class Mochitest(object):
|
||||||
# MAIN FUNCTION #
|
# Path to the test script on the server
|
||||||
#################
|
TEST_SERVER_HOST = "localhost:8888"
|
||||||
|
TEST_PATH = "/tests/"
|
||||||
|
CHROME_PATH = "/redirect.html";
|
||||||
|
A11Y_PATH = "/redirect-a11y.html"
|
||||||
|
TESTS_URL = "http://" + TEST_SERVER_HOST + TEST_PATH
|
||||||
|
CHROMETESTS_URL = "http://" + TEST_SERVER_HOST + CHROME_PATH
|
||||||
|
A11YTESTS_URL = "http://" + TEST_SERVER_HOST + A11Y_PATH
|
||||||
|
SERVER_SHUTDOWN_URL = "http://" + TEST_SERVER_HOST + "/server/shutdown"
|
||||||
|
|
||||||
|
oldcwd = os.getcwd()
|
||||||
|
|
||||||
|
def __init__(self, automation):
|
||||||
|
self.automation = automation
|
||||||
|
|
||||||
|
# Max time in seconds to wait for server startup before tests will fail -- if
|
||||||
|
# this seems big, it's mostly for debug machines where cold startup
|
||||||
|
# (particularly after a build) takes forever.
|
||||||
|
if self.automation.IS_DEBUG_BUILD:
|
||||||
|
self.SERVER_STARTUP_TIMEOUT = 180
|
||||||
|
else:
|
||||||
|
self.SERVER_STARTUP_TIMEOUT = 90
|
||||||
|
|
||||||
|
self.SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
|
||||||
|
os.chdir(self.SCRIPT_DIRECTORY)
|
||||||
|
|
||||||
|
self.PROFILE_DIRECTORY = os.path.abspath("./mochitesttestingprofile")
|
||||||
|
|
||||||
|
self.LEAK_REPORT_FILE = os.path.join(self.PROFILE_DIRECTORY, "runtests_leaks.log")
|
||||||
|
|
||||||
|
def getFullPath(self, path):
|
||||||
|
"Get an absolute path relative to self.oldcwd."
|
||||||
|
return os.path.normpath(os.path.join(self.oldcwd, os.path.expanduser(path)))
|
||||||
|
|
||||||
|
def runTests(self, options):
|
||||||
|
debuggerInfo = getDebuggerInfo(self.oldcwd, options.debugger, options.debuggerArgs,
|
||||||
|
options.debuggerInteractive);
|
||||||
|
|
||||||
|
# browser environment
|
||||||
|
browserEnv = self.automation.environment(xrePath = options.xrePath)
|
||||||
|
|
||||||
|
# These variables are necessary for correct application startup; change
|
||||||
|
# via the commandline at your own risk.
|
||||||
|
browserEnv["XPCOM_DEBUG_BREAK"] = "stack"
|
||||||
|
|
||||||
|
for v in options.environment:
|
||||||
|
ix = v.find("=")
|
||||||
|
if ix <= 0:
|
||||||
|
print "Error: syntax error in --setenv=" + v
|
||||||
|
return 1
|
||||||
|
browserEnv[v[:ix]] = v[ix + 1:]
|
||||||
|
|
||||||
|
self.automation.initializeProfile(self.PROFILE_DIRECTORY, options.extraPrefs)
|
||||||
|
manifest = self.addChromeToProfile(options)
|
||||||
|
self.copyExtraFilesToProfile(options)
|
||||||
|
server = MochitestServer(self.automation, options, self.PROFILE_DIRECTORY)
|
||||||
|
server.start()
|
||||||
|
|
||||||
|
# If we're lucky, the server has fully started by now, and all paths are
|
||||||
|
# ready, etc. However, xpcshell cold start times suck, at least for debug
|
||||||
|
# builds. We'll try to connect to the server for awhile, and if we fail,
|
||||||
|
# we'll try to kill the server and exit with an error.
|
||||||
|
server.ensureReady(self.SERVER_STARTUP_TIMEOUT)
|
||||||
|
|
||||||
|
# URL parameters to test URL:
|
||||||
|
#
|
||||||
|
# autorun -- kick off tests automatically
|
||||||
|
# closeWhenDone -- runs quit.js after tests
|
||||||
|
# logFile -- logs test run to an absolute path
|
||||||
|
# totalChunks -- how many chunks to split tests into
|
||||||
|
# thisChunk -- which chunk to run
|
||||||
|
# timeout -- per-test timeout in seconds
|
||||||
|
#
|
||||||
|
|
||||||
|
# consoleLevel, fileLevel: set the logging level of the console and
|
||||||
|
# file logs, if activated.
|
||||||
|
# <http://mochikit.com/doc/html/MochiKit/Logging.html>
|
||||||
|
|
||||||
|
testURL = self.TESTS_URL + options.testPath
|
||||||
|
urlOpts = []
|
||||||
|
if options.chrome:
|
||||||
|
testURL = self.CHROMETESTS_URL
|
||||||
|
if options.testPath:
|
||||||
|
urlOpts.append("testPath=" + encodeURIComponent(options.testPath))
|
||||||
|
elif options.a11y:
|
||||||
|
testURL = self.A11YTESTS_URL
|
||||||
|
if options.testPath:
|
||||||
|
urlOpts.append("testPath=" + encodeURIComponent(options.testPath))
|
||||||
|
elif options.browserChrome:
|
||||||
|
testURL = "about:blank"
|
||||||
|
|
||||||
|
# allow relative paths for logFile
|
||||||
|
if options.logFile:
|
||||||
|
options.logFile = self.getFullPath(options.logFile)
|
||||||
|
if options.browserChrome:
|
||||||
|
self.makeTestConfig(options)
|
||||||
|
else:
|
||||||
|
if options.autorun:
|
||||||
|
urlOpts.append("autorun=1")
|
||||||
|
if options.timeout:
|
||||||
|
urlOpts.append("timeout=%d" % options.timeout)
|
||||||
|
if options.closeWhenDone:
|
||||||
|
urlOpts.append("closeWhenDone=1")
|
||||||
|
if options.logFile:
|
||||||
|
urlOpts.append("logFile=" + encodeURIComponent(options.logFile))
|
||||||
|
urlOpts.append("fileLevel=" + encodeURIComponent(options.fileLevel))
|
||||||
|
if options.consoleLevel:
|
||||||
|
urlOpts.append("consoleLevel=" + encodeURIComponent(options.consoleLevel))
|
||||||
|
if options.totalChunks:
|
||||||
|
urlOpts.append("totalChunks=%d" % options.totalChunks)
|
||||||
|
urlOpts.append("thisChunk=%d" % options.thisChunk)
|
||||||
|
if options.chunkByDir:
|
||||||
|
urlOpts.append("chunkByDir=%d" % options.chunkByDir)
|
||||||
|
if options.shuffle:
|
||||||
|
urlOpts.append("shuffle=1")
|
||||||
|
if len(urlOpts) > 0:
|
||||||
|
testURL += "?" + "&".join(urlOpts)
|
||||||
|
|
||||||
|
browserEnv["XPCOM_MEM_BLOAT_LOG"] = self.LEAK_REPORT_FILE
|
||||||
|
|
||||||
|
if options.fatalAssertions:
|
||||||
|
browserEnv["XPCOM_DEBUG_BREAK"] = "stack-and-abort"
|
||||||
|
|
||||||
|
# run once with -silent to let the extension manager do its thing
|
||||||
|
# and then exit the app
|
||||||
|
self.automation.log.info("INFO | runtests.py | Performing extension manager registration: start.\n")
|
||||||
|
# Don't care about this |status|: |runApp()| reporting it should be enough.
|
||||||
|
status = self.automation.runApp(None, browserEnv, options.app,
|
||||||
|
self.PROFILE_DIRECTORY, ["-silent"],
|
||||||
|
utilityPath = options.utilityPath,
|
||||||
|
xrePath = options.xrePath,
|
||||||
|
symbolsPath=options.symbolsPath)
|
||||||
|
# We don't care to call |processLeakLog()| for this step.
|
||||||
|
self.automation.log.info("\nINFO | runtests.py | Performing extension manager registration: end.")
|
||||||
|
|
||||||
|
# Remove the leak detection file so it can't "leak" to the tests run.
|
||||||
|
# The file is not there if leak logging was not enabled in the application build.
|
||||||
|
if os.path.exists(self.LEAK_REPORT_FILE):
|
||||||
|
os.remove(self.LEAK_REPORT_FILE)
|
||||||
|
|
||||||
|
# then again to actually run mochitest
|
||||||
|
if options.timeout:
|
||||||
|
timeout = options.timeout + 30
|
||||||
|
elif options.autorun:
|
||||||
|
timeout = None
|
||||||
|
else:
|
||||||
|
timeout = 330.0 # default JS harness timeout is 300 seconds
|
||||||
|
self.automation.log.info("INFO | runtests.py | Running tests: start.\n")
|
||||||
|
status = self.automation.runApp(testURL, browserEnv, options.app,
|
||||||
|
self.PROFILE_DIRECTORY, options.browserArgs,
|
||||||
|
runSSLTunnel = True,
|
||||||
|
utilityPath = options.utilityPath,
|
||||||
|
xrePath = options.xrePath,
|
||||||
|
certPath=options.certPath,
|
||||||
|
debuggerInfo=debuggerInfo,
|
||||||
|
symbolsPath=options.symbolsPath,
|
||||||
|
timeout = timeout)
|
||||||
|
|
||||||
|
# Server's no longer needed, and perhaps more importantly, anything it might
|
||||||
|
# spew to console shouldn't disrupt the leak information table we print next.
|
||||||
|
server.stop()
|
||||||
|
|
||||||
|
processLeakLog(self.LEAK_REPORT_FILE, options.leakThreshold)
|
||||||
|
self.automation.log.info("\nINFO | runtests.py | Running tests: end.")
|
||||||
|
|
||||||
|
# delete the profile and manifest
|
||||||
|
os.remove(manifest)
|
||||||
|
|
||||||
|
# hanging due to non-halting threads is no fun; assume we hit the errors we
|
||||||
|
# were going to hit already and exit.
|
||||||
|
return status
|
||||||
|
|
||||||
|
def makeTestConfig(self, options):
|
||||||
|
"Creates a test configuration file for customizing test execution."
|
||||||
|
def boolString(b):
|
||||||
|
if b:
|
||||||
|
return "true"
|
||||||
|
return "false"
|
||||||
|
|
||||||
|
logFile = options.logFile.replace("\\", "\\\\")
|
||||||
|
testPath = options.testPath.replace("\\", "\\\\")
|
||||||
|
content = """\
|
||||||
|
({
|
||||||
|
autoRun: %(autorun)s,
|
||||||
|
closeWhenDone: %(closeWhenDone)s,
|
||||||
|
logPath: "%(logPath)s",
|
||||||
|
testPath: "%(testPath)s"
|
||||||
|
})""" % {"autorun": boolString(options.autorun),
|
||||||
|
"closeWhenDone": boolString(options.closeWhenDone),
|
||||||
|
"logPath": logFile,
|
||||||
|
"testPath": testPath}
|
||||||
|
|
||||||
|
config = open(os.path.join(self.PROFILE_DIRECTORY, "testConfig.js"), "w")
|
||||||
|
config.write(content)
|
||||||
|
config.close()
|
||||||
|
|
||||||
|
|
||||||
|
def addChromeToProfile(self, options):
|
||||||
|
"Adds MochiKit chrome tests to the profile."
|
||||||
|
|
||||||
|
chromedir = os.path.join(self.PROFILE_DIRECTORY, "chrome")
|
||||||
|
os.mkdir(chromedir)
|
||||||
|
|
||||||
|
chrome = """
|
||||||
|
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
|
||||||
|
toolbar,
|
||||||
|
toolbarpalette {
|
||||||
|
background-color: rgb(235, 235, 235) !important;
|
||||||
|
}
|
||||||
|
toolbar#nav-bar {
|
||||||
|
background-image: none !important;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
# write userChrome.css
|
||||||
|
chromeFile = open(os.path.join(self.PROFILE_DIRECTORY, "userChrome.css"), "a")
|
||||||
|
chromeFile.write(chrome)
|
||||||
|
chromeFile.close()
|
||||||
|
|
||||||
|
|
||||||
|
# register our chrome dir
|
||||||
|
chrometestDir = os.path.abspath(".") + "/"
|
||||||
|
if self.automation.IS_WIN32:
|
||||||
|
chrometestDir = "file:///" + chrometestDir.replace("\\", "/")
|
||||||
|
|
||||||
|
|
||||||
|
(path, leaf) = os.path.split(options.app)
|
||||||
|
manifest = os.path.join(path, "chrome", "mochikit.manifest")
|
||||||
|
manifestFile = open(manifest, "w")
|
||||||
|
manifestFile.write("content mochikit " + chrometestDir + " contentaccessible=yes\n")
|
||||||
|
|
||||||
|
if options.browserChrome:
|
||||||
|
manifestFile.write("""overlay chrome://navigator/content/navigator.xul chrome://mochikit/content/browser-test-overlay.xul
|
||||||
|
overlay chrome://browser/content/browser.xul chrome://mochikit/content/browser-test-overlay.xul
|
||||||
|
""")
|
||||||
|
manifestFile.close()
|
||||||
|
|
||||||
|
return manifest
|
||||||
|
|
||||||
|
def copyExtraFilesToProfile(self, options):
|
||||||
|
"Copy extra files or dirs specified on the command line to the testing profile."
|
||||||
|
for f in options.extraProfileFiles:
|
||||||
|
abspath = self.getFullPath(f)
|
||||||
|
dest = os.path.join(self.PROFILE_DIRECTORY, os.path.basename(abspath))
|
||||||
|
if os.path.isdir(abspath):
|
||||||
|
shutil.copytree(abspath, dest)
|
||||||
|
else:
|
||||||
|
shutil.copy(abspath, dest)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = MochitestOptions()
|
automation = Automation()
|
||||||
|
mochitest = Mochitest(automation)
|
||||||
|
parser = MochitestOptions(automation, mochitest.SCRIPT_DIRECTORY)
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
if options.totalChunks is not None and options.thisChunk is None:
|
if options.totalChunks is not None and options.thisChunk is None:
|
||||||
@ -318,7 +535,7 @@ def main():
|
|||||||
|
|
||||||
if options.totalChunks:
|
if options.totalChunks:
|
||||||
if not 1 <= options.thisChunk <= options.totalChunks:
|
if not 1 <= options.thisChunk <= options.totalChunks:
|
||||||
parser.error("thisChunk must be between 1 and totalChunks")
|
parser.error("thisChunk must be between 1 and totalChunks")
|
||||||
|
|
||||||
if options.xrePath is None:
|
if options.xrePath is None:
|
||||||
# default xrePath to the app path if not provided
|
# default xrePath to the app path if not provided
|
||||||
@ -330,248 +547,22 @@ def main():
|
|||||||
options.xrePath = automation.DIST_BIN
|
options.xrePath = automation.DIST_BIN
|
||||||
|
|
||||||
# allow relative paths
|
# allow relative paths
|
||||||
options.xrePath = getFullPath(options.xrePath)
|
options.xrePath = mochitest.getFullPath(options.xrePath)
|
||||||
|
|
||||||
options.app = getFullPath(options.app)
|
options.app = mochitest.getFullPath(options.app)
|
||||||
if not os.path.exists(options.app):
|
if not os.path.exists(options.app):
|
||||||
msg = """\
|
msg = """\
|
||||||
Error: Path %(app)s doesn't exist.
|
Error: Path %(app)s doesn't exist.
|
||||||
Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
|
Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
|
||||||
print msg % {"app": options.app}
|
print msg % {"app": options.app}
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
options.utilityPath = getFullPath(options.utilityPath)
|
options.utilityPath = mochitest.getFullPath(options.utilityPath)
|
||||||
options.certPath = getFullPath(options.certPath)
|
options.certPath = mochitest.getFullPath(options.certPath)
|
||||||
if options.symbolsPath:
|
if options.symbolsPath:
|
||||||
options.symbolsPath = getFullPath(options.symbolsPath)
|
options.symbolsPath = mochitest.getFullPath(options.symbolsPath)
|
||||||
|
|
||||||
debuggerInfo = getDebuggerInfo(oldcwd, options.debugger, options.debuggerArgs,
|
sys.exit(mochitest.runTests(options))
|
||||||
options.debuggerInteractive);
|
|
||||||
|
|
||||||
# browser environment
|
|
||||||
browserEnv = automation.environment(xrePath = options.xrePath)
|
|
||||||
|
|
||||||
# These variables are necessary for correct application startup; change
|
|
||||||
# via the commandline at your own risk.
|
|
||||||
browserEnv["XPCOM_DEBUG_BREAK"] = "stack"
|
|
||||||
|
|
||||||
for v in options.environment:
|
|
||||||
ix = v.find("=")
|
|
||||||
if ix <= 0:
|
|
||||||
print "Error: syntax error in --setenv=" + v
|
|
||||||
sys.exit(1)
|
|
||||||
browserEnv[v[:ix]] = v[ix + 1:]
|
|
||||||
|
|
||||||
automation.initializeProfile(PROFILE_DIRECTORY, options.extraPrefs)
|
|
||||||
manifest = addChromeToProfile(options)
|
|
||||||
copyExtraFilesToProfile(options)
|
|
||||||
server = MochitestServer(options)
|
|
||||||
server.start()
|
|
||||||
|
|
||||||
# If we're lucky, the server has fully started by now, and all paths are
|
|
||||||
# ready, etc. However, xpcshell cold start times suck, at least for debug
|
|
||||||
# builds. We'll try to connect to the server for awhile, and if we fail,
|
|
||||||
# we'll try to kill the server and exit with an error.
|
|
||||||
server.ensureReady(SERVER_STARTUP_TIMEOUT)
|
|
||||||
|
|
||||||
# URL parameters to test URL:
|
|
||||||
#
|
|
||||||
# autorun -- kick off tests automatically
|
|
||||||
# closeWhenDone -- runs quit.js after tests
|
|
||||||
# logFile -- logs test run to an absolute path
|
|
||||||
# totalChunks -- how many chunks to split tests into
|
|
||||||
# thisChunk -- which chunk to run
|
|
||||||
# timeout -- per-test timeout in seconds
|
|
||||||
#
|
|
||||||
|
|
||||||
# consoleLevel, fileLevel: set the logging level of the console and
|
|
||||||
# file logs, if activated.
|
|
||||||
# <http://mochikit.com/doc/html/MochiKit/Logging.html>
|
|
||||||
|
|
||||||
testURL = TESTS_URL + options.testPath
|
|
||||||
urlOpts = []
|
|
||||||
if options.chrome:
|
|
||||||
testURL = CHROMETESTS_URL
|
|
||||||
if options.testPath:
|
|
||||||
urlOpts.append("testPath=" + encodeURIComponent(options.testPath))
|
|
||||||
elif options.a11y:
|
|
||||||
testURL = A11YTESTS_URL
|
|
||||||
if options.testPath:
|
|
||||||
urlOpts.append("testPath=" + encodeURIComponent(options.testPath))
|
|
||||||
elif options.browserChrome:
|
|
||||||
testURL = "about:blank"
|
|
||||||
|
|
||||||
# allow relative paths for logFile
|
|
||||||
if options.logFile:
|
|
||||||
options.logFile = getFullPath(options.logFile)
|
|
||||||
if options.browserChrome:
|
|
||||||
makeTestConfig(options)
|
|
||||||
else:
|
|
||||||
if options.autorun:
|
|
||||||
urlOpts.append("autorun=1")
|
|
||||||
if options.timeout:
|
|
||||||
urlOpts.append("timeout=%d" % options.timeout)
|
|
||||||
if options.closeWhenDone:
|
|
||||||
urlOpts.append("closeWhenDone=1")
|
|
||||||
if options.logFile:
|
|
||||||
urlOpts.append("logFile=" + encodeURIComponent(options.logFile))
|
|
||||||
urlOpts.append("fileLevel=" + encodeURIComponent(options.fileLevel))
|
|
||||||
if options.consoleLevel:
|
|
||||||
urlOpts.append("consoleLevel=" + encodeURIComponent(options.consoleLevel))
|
|
||||||
if options.totalChunks:
|
|
||||||
urlOpts.append("totalChunks=%d" % options.totalChunks)
|
|
||||||
urlOpts.append("thisChunk=%d" % options.thisChunk)
|
|
||||||
if options.chunkByDir:
|
|
||||||
urlOpts.append("chunkByDir=%d" % options.chunkByDir)
|
|
||||||
if options.shuffle:
|
|
||||||
urlOpts.append("shuffle=1")
|
|
||||||
if len(urlOpts) > 0:
|
|
||||||
testURL += "?" + "&".join(urlOpts)
|
|
||||||
|
|
||||||
browserEnv["XPCOM_MEM_BLOAT_LOG"] = LEAK_REPORT_FILE
|
|
||||||
|
|
||||||
if options.fatalAssertions:
|
|
||||||
browserEnv["XPCOM_DEBUG_BREAK"] = "stack-and-abort"
|
|
||||||
|
|
||||||
# run once with -silent to let the extension manager do its thing
|
|
||||||
# and then exit the app
|
|
||||||
automation.log.info("INFO | runtests.py | Performing extension manager registration: start.\n")
|
|
||||||
# Don't care about this |status|: |runApp()| reporting it should be enough.
|
|
||||||
status = automation.runApp(None, browserEnv, options.app,
|
|
||||||
PROFILE_DIRECTORY, ["-silent"],
|
|
||||||
utilityPath = options.utilityPath,
|
|
||||||
xrePath = options.xrePath,
|
|
||||||
symbolsPath=options.symbolsPath)
|
|
||||||
# We don't care to call |processLeakLog()| for this step.
|
|
||||||
automation.log.info("\nINFO | runtests.py | Performing extension manager registration: end.")
|
|
||||||
|
|
||||||
# Remove the leak detection file so it can't "leak" to the tests run.
|
|
||||||
# The file is not there if leak logging was not enabled in the application build.
|
|
||||||
if os.path.exists(LEAK_REPORT_FILE):
|
|
||||||
os.remove(LEAK_REPORT_FILE)
|
|
||||||
|
|
||||||
# then again to actually run mochitest
|
|
||||||
if options.timeout:
|
|
||||||
timeout = options.timeout + 30
|
|
||||||
elif options.autorun:
|
|
||||||
timeout = None
|
|
||||||
else:
|
|
||||||
timeout = 330.0 # default JS harness timeout is 300 seconds
|
|
||||||
automation.log.info("INFO | runtests.py | Running tests: start.\n")
|
|
||||||
status = automation.runApp(testURL, browserEnv, options.app,
|
|
||||||
PROFILE_DIRECTORY, options.browserArgs,
|
|
||||||
runSSLTunnel = True,
|
|
||||||
utilityPath = options.utilityPath,
|
|
||||||
xrePath = options.xrePath,
|
|
||||||
certPath=options.certPath,
|
|
||||||
debuggerInfo=debuggerInfo,
|
|
||||||
symbolsPath=options.symbolsPath,
|
|
||||||
timeout = timeout)
|
|
||||||
|
|
||||||
# Server's no longer needed, and perhaps more importantly, anything it might
|
|
||||||
# spew to console shouldn't disrupt the leak information table we print next.
|
|
||||||
server.stop()
|
|
||||||
|
|
||||||
processLeakLog(LEAK_REPORT_FILE, options.leakThreshold)
|
|
||||||
automation.log.info("\nINFO | runtests.py | Running tests: end.")
|
|
||||||
|
|
||||||
# delete the profile and manifest
|
|
||||||
os.remove(manifest)
|
|
||||||
|
|
||||||
# hanging due to non-halting threads is no fun; assume we hit the errors we
|
|
||||||
# were going to hit already and exit.
|
|
||||||
sys.exit(status)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#######################
|
|
||||||
# CONFIGURATION SETUP #
|
|
||||||
#######################
|
|
||||||
|
|
||||||
def makeTestConfig(options):
|
|
||||||
"Creates a test configuration file for customizing test execution."
|
|
||||||
def boolString(b):
|
|
||||||
if b:
|
|
||||||
return "true"
|
|
||||||
return "false"
|
|
||||||
|
|
||||||
logFile = options.logFile.replace("\\", "\\\\")
|
|
||||||
testPath = options.testPath.replace("\\", "\\\\")
|
|
||||||
content = """\
|
|
||||||
({
|
|
||||||
autoRun: %(autorun)s,
|
|
||||||
closeWhenDone: %(closeWhenDone)s,
|
|
||||||
logPath: "%(logPath)s",
|
|
||||||
testPath: "%(testPath)s"
|
|
||||||
})""" % {"autorun": boolString(options.autorun),
|
|
||||||
"closeWhenDone": boolString(options.closeWhenDone),
|
|
||||||
"logPath": logFile,
|
|
||||||
"testPath": testPath}
|
|
||||||
|
|
||||||
config = open(os.path.join(PROFILE_DIRECTORY, "testConfig.js"), "w")
|
|
||||||
config.write(content)
|
|
||||||
config.close()
|
|
||||||
|
|
||||||
|
|
||||||
def addChromeToProfile(options):
|
|
||||||
"Adds MochiKit chrome tests to the profile."
|
|
||||||
|
|
||||||
chromedir = os.path.join(PROFILE_DIRECTORY, "chrome")
|
|
||||||
os.mkdir(chromedir)
|
|
||||||
|
|
||||||
chrome = []
|
|
||||||
|
|
||||||
part = """
|
|
||||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
|
|
||||||
toolbar,
|
|
||||||
toolbarpalette {
|
|
||||||
background-color: rgb(235, 235, 235) !important;
|
|
||||||
}
|
|
||||||
toolbar#nav-bar {
|
|
||||||
background-image: none !important;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
chrome.append(part)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# write userChrome.css
|
|
||||||
chromeFile = open(os.path.join(PROFILE_DIRECTORY, "userChrome.css"), "a")
|
|
||||||
chromeFile.write("".join(chrome))
|
|
||||||
chromeFile.close()
|
|
||||||
|
|
||||||
|
|
||||||
# register our chrome dir
|
|
||||||
chrometestDir = os.path.abspath(".") + "/"
|
|
||||||
if automation.IS_WIN32:
|
|
||||||
chrometestDir = "file:///" + chrometestDir.replace("\\", "/")
|
|
||||||
|
|
||||||
|
|
||||||
(path, leaf) = os.path.split(options.app)
|
|
||||||
manifest = os.path.join(path, "chrome", "mochikit.manifest")
|
|
||||||
manifestFile = open(manifest, "w")
|
|
||||||
manifestFile.write("content mochikit " + chrometestDir + " contentaccessible=yes\n")
|
|
||||||
if options.browserChrome:
|
|
||||||
overlayLine = "overlay " + BROWSER_CHROME_URL + " " \
|
|
||||||
"chrome://mochikit/content/browser-test-overlay.xul\n"
|
|
||||||
manifestFile.write(overlayLine)
|
|
||||||
manifestFile.close()
|
|
||||||
|
|
||||||
return manifest
|
|
||||||
|
|
||||||
def copyExtraFilesToProfile(options):
|
|
||||||
"Copy extra files or dirs specified on the command line to the testing profile."
|
|
||||||
for f in options.extraProfileFiles:
|
|
||||||
abspath = getFullPath(f)
|
|
||||||
dest = os.path.join(PROFILE_DIRECTORY, os.path.basename(abspath))
|
|
||||||
if os.path.isdir(abspath):
|
|
||||||
shutil.copytree(abspath, dest)
|
|
||||||
else:
|
|
||||||
shutil.copy(abspath, dest)
|
|
||||||
|
|
||||||
#########
|
|
||||||
# DO IT #
|
|
||||||
#########
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -200,10 +200,18 @@ bool ReadConnectRequest(server_info_t* server_info,
|
|||||||
relayBuffer& buffer, PRInt32* result, string& certificate,
|
relayBuffer& buffer, PRInt32* result, string& certificate,
|
||||||
client_auth_option* clientauth, string& host)
|
client_auth_option* clientauth, string& host)
|
||||||
{
|
{
|
||||||
if (buffer.present() < 4)
|
if (buffer.present() < 4) {
|
||||||
|
printf(" !! only %d bytes present in the buffer", (int)buffer.present());
|
||||||
return false;
|
return false;
|
||||||
if (strncmp(buffer.buffertail-4, "\r\n\r\n", 4))
|
}
|
||||||
|
if (strncmp(buffer.buffertail-4, "\r\n\r\n", 4)) {
|
||||||
|
printf(" !! request is not tailed with CRLFCRLF but with %x %x %x %x",
|
||||||
|
*(buffer.buffertail-4),
|
||||||
|
*(buffer.buffertail-3),
|
||||||
|
*(buffer.buffertail-2),
|
||||||
|
*(buffer.buffertail-1));
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*result = 400;
|
*result = 400;
|
||||||
|
|
||||||
@ -293,6 +301,7 @@ bool AdjustRequestURI(relayBuffer& buffer, string *host)
|
|||||||
// Cannot use strnchr so add a null char at the end. There is always some space left
|
// Cannot use strnchr so add a null char at the end. There is always some space left
|
||||||
// because we preserve a margin.
|
// because we preserve a margin.
|
||||||
buffer.buffertail[1] = '\0';
|
buffer.buffertail[1] = '\0';
|
||||||
|
printf(" incoming request to adjust:\n%s\n", buffer.bufferhead);
|
||||||
|
|
||||||
char *token, *path;
|
char *token, *path;
|
||||||
path = strchr(buffer.bufferhead, ' ') + 1;
|
path = strchr(buffer.bufferhead, ' ') + 1;
|
||||||
@ -548,6 +557,9 @@ void HandleConnection(void* data)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf(", writen %d bytes", bytesWrite);
|
printf(", writen %d bytes", bytesWrite);
|
||||||
|
buffers[s2].buffertail[1] = '\0';
|
||||||
|
printf(" dump:\n%.*s\n", bytesWrite, buffers[s2].bufferhead);
|
||||||
|
|
||||||
buffers[s2].bufferhead += bytesWrite;
|
buffers[s2].bufferhead += bytesWrite;
|
||||||
if (buffers[s2].present())
|
if (buffers[s2].present())
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
# Contributor(s):
|
# Contributor(s):
|
||||||
# Serge Gautherie <sgautherie.bz@free.fr>
|
# Serge Gautherie <sgautherie.bz@free.fr>
|
||||||
# Ted Mielczarek <ted.mielczarek@gmail.com>
|
# Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||||
|
# Joel Maher <joel.maher@gmail.com>
|
||||||
#
|
#
|
||||||
# Alternatively, the contents of this file may be used under the terms of
|
# Alternatively, the contents of this file may be used under the terms of
|
||||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
@ -45,243 +46,246 @@ from tempfile import mkdtemp
|
|||||||
|
|
||||||
from automationutils import *
|
from automationutils import *
|
||||||
|
|
||||||
# Init logging
|
class XPCShellTests(object):
|
||||||
log = logging.getLogger()
|
|
||||||
handler = logging.StreamHandler(sys.stdout)
|
|
||||||
log.setLevel(logging.INFO)
|
|
||||||
log.addHandler(handler)
|
|
||||||
|
|
||||||
oldcwd = os.getcwd()
|
log = logging.getLogger()
|
||||||
|
oldcwd = os.getcwd()
|
||||||
|
|
||||||
def readManifest(manifest):
|
def __init__(self):
|
||||||
"""Given a manifest file containing a list of test directories,
|
# Init logging
|
||||||
return a list of absolute paths to the directories contained within."""
|
handler = logging.StreamHandler(sys.stdout)
|
||||||
manifestdir = os.path.dirname(manifest)
|
self.log.setLevel(logging.INFO)
|
||||||
testdirs = []
|
self.log.addHandler(handler)
|
||||||
try:
|
|
||||||
f = open(manifest, "r")
|
|
||||||
for line in f:
|
|
||||||
dir = line.rstrip()
|
|
||||||
path = os.path.join(manifestdir, dir)
|
|
||||||
if os.path.isdir(path):
|
|
||||||
testdirs.append(path)
|
|
||||||
f.close()
|
|
||||||
except:
|
|
||||||
pass # just eat exceptions
|
|
||||||
return testdirs
|
|
||||||
|
|
||||||
def runTests(xpcshell, xrePath=None, symbolsPath=None,
|
def readManifest(self, manifest):
|
||||||
manifest=None, testdirs=[], testPath=None,
|
"""Given a manifest file containing a list of test directories,
|
||||||
interactive=False, logfiles=True,
|
return a list of absolute paths to the directories contained within."""
|
||||||
debuggerInfo=None):
|
manifestdir = os.path.dirname(manifest)
|
||||||
"""Run xpcshell tests.
|
testdirs = []
|
||||||
|
try:
|
||||||
|
f = open(manifest, "r")
|
||||||
|
for line in f:
|
||||||
|
dir = line.rstrip()
|
||||||
|
path = os.path.join(manifestdir, dir)
|
||||||
|
if os.path.isdir(path):
|
||||||
|
testdirs.append(path)
|
||||||
|
f.close()
|
||||||
|
except:
|
||||||
|
pass # just eat exceptions
|
||||||
|
return testdirs
|
||||||
|
|
||||||
|xpcshell|, is the xpcshell executable to use to run the tests.
|
def runTests(self, xpcshell, xrePath=None, symbolsPath=None,
|
||||||
|xrePath|, if provided, is the path to the XRE to use.
|
manifest=None, testdirs=[], testPath=None,
|
||||||
|symbolsPath|, if provided is the path to a directory containing
|
interactive=False, logfiles=True,
|
||||||
breakpad symbols for processing crashes in tests.
|
debuggerInfo=None):
|
||||||
|manifest|, if provided, is a file containing a list of
|
"""Run xpcshell tests.
|
||||||
test directories to run.
|
|
||||||
|testdirs|, if provided, is a list of absolute paths of test directories.
|
|
||||||
No-manifest only option.
|
|
||||||
|testPath|, if provided, indicates a single path and/or test to run.
|
|
||||||
|interactive|, if set to True, indicates to provide an xpcshell prompt
|
|
||||||
instead of automatically executing the test.
|
|
||||||
|logfiles|, if set to False, indicates not to save output to log files.
|
|
||||||
Non-interactive only option.
|
|
||||||
|debuggerInfo|, if set, specifies the debugger and debugger arguments
|
|
||||||
that will be used to launch xpcshell.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not testdirs and not manifest:
|
|xpcshell|, is the xpcshell executable to use to run the tests.
|
||||||
# nothing to test!
|
|xrePath|, if provided, is the path to the XRE to use.
|
||||||
print >>sys.stderr, "Error: No test dirs or test manifest specified!"
|
|symbolsPath|, if provided is the path to a directory containing
|
||||||
return False
|
breakpad symbols for processing crashes in tests.
|
||||||
|
|manifest|, if provided, is a file containing a list of
|
||||||
|
test directories to run.
|
||||||
|
|testdirs|, if provided, is a list of absolute paths of test directories.
|
||||||
|
No-manifest only option.
|
||||||
|
|testPath|, if provided, indicates a single path and/or test to run.
|
||||||
|
|interactive|, if set to True, indicates to provide an xpcshell prompt
|
||||||
|
instead of automatically executing the test.
|
||||||
|
|logfiles|, if set to False, indicates not to save output to log files.
|
||||||
|
Non-interactive only option.
|
||||||
|
|debuggerInfo|, if set, specifies the debugger and debugger arguments
|
||||||
|
that will be used to launch xpcshell.
|
||||||
|
"""
|
||||||
|
|
||||||
passCount = 0
|
if not testdirs and not manifest:
|
||||||
failCount = 0
|
# nothing to test!
|
||||||
|
print >>sys.stderr, "Error: No test dirs or test manifest specified!"
|
||||||
|
return False
|
||||||
|
|
||||||
testharnessdir = os.path.dirname(os.path.abspath(__file__))
|
passCount = 0
|
||||||
xpcshell = os.path.abspath(xpcshell)
|
failCount = 0
|
||||||
# we assume that httpd.js lives in components/ relative to xpcshell
|
|
||||||
httpdJSPath = os.path.join(os.path.dirname(xpcshell), "components", "httpd.js").replace("\\", "/");
|
|
||||||
|
|
||||||
env = dict(os.environ)
|
testharnessdir = os.path.dirname(os.path.abspath(__file__))
|
||||||
# Make assertions fatal
|
xpcshell = os.path.abspath(xpcshell)
|
||||||
env["XPCOM_DEBUG_BREAK"] = "stack-and-abort"
|
# we assume that httpd.js lives in components/ relative to xpcshell
|
||||||
# Don't launch the crash reporter client
|
httpdJSPath = os.path.join(os.path.dirname(xpcshell), "components", "httpd.js").replace("\\", "/");
|
||||||
env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
|
|
||||||
|
|
||||||
if xrePath is None:
|
env = dict(os.environ)
|
||||||
xrePath = os.path.dirname(xpcshell)
|
# Make assertions fatal
|
||||||
else:
|
env["XPCOM_DEBUG_BREAK"] = "stack-and-abort"
|
||||||
xrePath = os.path.abspath(xrePath)
|
# Don't launch the crash reporter client
|
||||||
if sys.platform == 'win32':
|
env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
|
||||||
env["PATH"] = env["PATH"] + ";" + xrePath
|
|
||||||
elif sys.platform in ('os2emx', 'os2knix'):
|
|
||||||
os.environ["BEGINLIBPATH"] = xrePath + ";" + env["BEGINLIBPATH"]
|
|
||||||
os.environ["LIBPATHSTRICT"] = "T"
|
|
||||||
elif sys.platform == 'osx':
|
|
||||||
env["DYLD_LIBRARY_PATH"] = xrePath
|
|
||||||
else: # unix or linux?
|
|
||||||
env["LD_LIBRARY_PATH"] = xrePath
|
|
||||||
|
|
||||||
# xpcsRunArgs: <head.js> function to call to run the test.
|
if xrePath is None:
|
||||||
# pStdout, pStderr: Parameter values for later |Popen()| call.
|
xrePath = os.path.dirname(xpcshell)
|
||||||
if interactive:
|
else:
|
||||||
xpcsRunArgs = [
|
xrePath = os.path.abspath(xrePath)
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
env["PATH"] = env["PATH"] + ";" + xrePath
|
||||||
|
elif sys.platform in ('os2emx', 'os2knix'):
|
||||||
|
os.environ["BEGINLIBPATH"] = xrePath + ";" + env["BEGINLIBPATH"]
|
||||||
|
os.environ["LIBPATHSTRICT"] = "T"
|
||||||
|
elif sys.platform == 'osx':
|
||||||
|
env["DYLD_LIBRARY_PATH"] = xrePath
|
||||||
|
else: # unix or linux?
|
||||||
|
env["LD_LIBRARY_PATH"] = xrePath
|
||||||
|
|
||||||
|
# xpcsRunArgs: <head.js> function to call to run the test.
|
||||||
|
# pStdout, pStderr: Parameter values for later |Popen()| call.
|
||||||
|
if interactive:
|
||||||
|
xpcsRunArgs = [
|
||||||
'-e', 'print("To start the test, type |_execute_test();|.");',
|
'-e', 'print("To start the test, type |_execute_test();|.");',
|
||||||
'-i']
|
'-i']
|
||||||
pStdout = None
|
|
||||||
pStderr = None
|
|
||||||
else:
|
|
||||||
xpcsRunArgs = ['-e', '_execute_test();']
|
|
||||||
if (debuggerInfo and debuggerInfo["interactive"]):
|
|
||||||
pStdout = None
|
pStdout = None
|
||||||
pStderr = None
|
pStderr = None
|
||||||
else:
|
else:
|
||||||
if sys.platform == 'os2emx':
|
xpcsRunArgs = ['-e', '_execute_test();']
|
||||||
|
if (debuggerInfo and debuggerInfo["interactive"]):
|
||||||
pStdout = None
|
pStdout = None
|
||||||
|
pStderr = None
|
||||||
else:
|
else:
|
||||||
pStdout = PIPE
|
if sys.platform == 'os2emx':
|
||||||
pStderr = STDOUT
|
pStdout = None
|
||||||
|
else:
|
||||||
|
pStdout = PIPE
|
||||||
|
pStderr = STDOUT
|
||||||
|
|
||||||
# <head.js> has to be loaded by xpchell: it can't load itself.
|
# <head.js> has to be loaded by xpchell: it can't load itself.
|
||||||
xpcsCmd = [xpcshell, '-g', xrePath, '-j', '-s'] + \
|
xpcsCmd = [xpcshell, '-g', xrePath, '-j', '-s'] + \
|
||||||
['-e', 'const _HTTPD_JS_PATH = "%s";' % httpdJSPath,
|
['-e', 'const _HTTPD_JS_PATH = "%s";' % httpdJSPath,
|
||||||
'-f', os.path.join(testharnessdir, 'head.js')]
|
'-f', os.path.join(testharnessdir, 'head.js')]
|
||||||
|
|
||||||
if debuggerInfo:
|
if debuggerInfo:
|
||||||
xpcsCmd = [debuggerInfo["path"]] + debuggerInfo["args"] + xpcsCmd
|
xpcsCmd = [debuggerInfo["path"]] + debuggerInfo["args"] + xpcsCmd
|
||||||
|
|
||||||
# |testPath| will be the optional path only, or |None|.
|
# |testPath| will be the optional path only, or |None|.
|
||||||
# |singleFile| will be the optional test only, or |None|.
|
# |singleFile| will be the optional test only, or |None|.
|
||||||
singleFile = None
|
singleFile = None
|
||||||
if testPath:
|
if testPath:
|
||||||
if testPath.endswith('.js'):
|
if testPath.endswith('.js'):
|
||||||
# Split into path and file.
|
# Split into path and file.
|
||||||
if testPath.find('/') == -1:
|
if testPath.find('/') == -1:
|
||||||
# Test only.
|
# Test only.
|
||||||
singleFile = testPath
|
singleFile = testPath
|
||||||
testPath = None
|
testPath = None
|
||||||
|
else:
|
||||||
|
# Both path and test.
|
||||||
|
# Reuse |testPath| temporarily.
|
||||||
|
testPath = testPath.rsplit('/', 1)
|
||||||
|
singleFile = testPath[1]
|
||||||
|
testPath = testPath[0]
|
||||||
else:
|
else:
|
||||||
# Both path and test.
|
# Path only.
|
||||||
# Reuse |testPath| temporarily.
|
# Simply remove optional ending separator.
|
||||||
testPath = testPath.rsplit('/', 1)
|
testPath = testPath.rstrip("/")
|
||||||
singleFile = testPath[1]
|
|
||||||
testPath = testPath[0]
|
|
||||||
else:
|
|
||||||
# Path only.
|
|
||||||
# Simply remove optional ending separator.
|
|
||||||
testPath = testPath.rstrip("/")
|
|
||||||
|
|
||||||
# Override testdirs.
|
# Override testdirs.
|
||||||
if manifest is not None:
|
if manifest is not None:
|
||||||
testdirs = readManifest(os.path.abspath(manifest))
|
testdirs = self.readManifest(os.path.abspath(manifest))
|
||||||
|
|
||||||
# Process each test directory individually.
|
# Process each test directory individually.
|
||||||
for testdir in testdirs:
|
for testdir in testdirs:
|
||||||
if testPath and not testdir.endswith(testPath):
|
if testPath and not testdir.endswith(testPath):
|
||||||
continue
|
|
||||||
|
|
||||||
testdir = os.path.abspath(testdir)
|
|
||||||
|
|
||||||
# get the list of head and tail files from the directory
|
|
||||||
testHeadFiles = []
|
|
||||||
for f in sorted(glob(os.path.join(testdir, "head_*.js"))):
|
|
||||||
if os.path.isfile(f):
|
|
||||||
testHeadFiles += [f]
|
|
||||||
testTailFiles = []
|
|
||||||
# Tails are executed in the reverse order, to "match" heads order,
|
|
||||||
# as in "h1-h2-h3 then t3-t2-t1".
|
|
||||||
for f in reversed(sorted(glob(os.path.join(testdir, "tail_*.js")))):
|
|
||||||
if os.path.isfile(f):
|
|
||||||
testTailFiles += [f]
|
|
||||||
|
|
||||||
# if a single test file was specified, we only want to execute that test
|
|
||||||
testfiles = sorted(glob(os.path.join(testdir, "test_*.js")))
|
|
||||||
if singleFile:
|
|
||||||
if singleFile in [os.path.basename(x) for x in testfiles]:
|
|
||||||
testfiles = [os.path.join(testdir, singleFile)]
|
|
||||||
else: # not in this dir? skip it
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
cmdH = ", ".join(['"' + f.replace('\\', '/') + '"'
|
testdir = os.path.abspath(testdir)
|
||||||
for f in testHeadFiles])
|
|
||||||
cmdT = ", ".join(['"' + f.replace('\\', '/') + '"'
|
|
||||||
for f in testTailFiles])
|
|
||||||
cmdH = xpcsCmd + \
|
|
||||||
['-e', 'const _HEAD_FILES = [%s];' % cmdH] + \
|
|
||||||
['-e', 'const _TAIL_FILES = [%s];' % cmdT]
|
|
||||||
|
|
||||||
# Now execute each test individually.
|
# get the list of head and tail files from the directory
|
||||||
for test in testfiles:
|
testHeadFiles = []
|
||||||
# The test file will have to be loaded after the head files.
|
for f in sorted(glob(os.path.join(testdir, "head_*.js"))):
|
||||||
cmdT = ['-e', 'const _TEST_FILE = ["%s"];' %
|
if os.path.isfile(f):
|
||||||
os.path.join(testdir, test).replace('\\', '/')]
|
testHeadFiles += [f]
|
||||||
|
testTailFiles = []
|
||||||
|
# Tails are executed in the reverse order, to "match" heads order,
|
||||||
|
# as in "h1-h2-h3 then t3-t2-t1".
|
||||||
|
for f in reversed(sorted(glob(os.path.join(testdir, "tail_*.js")))):
|
||||||
|
if os.path.isfile(f):
|
||||||
|
testTailFiles += [f]
|
||||||
|
|
||||||
# create a temp dir that the JS harness can stick a profile in
|
# if a single test file was specified, we only want to execute that test
|
||||||
profileDir = None
|
testfiles = sorted(glob(os.path.join(testdir, "test_*.js")))
|
||||||
try:
|
if singleFile:
|
||||||
profileDir = mkdtemp()
|
if singleFile in [os.path.basename(x) for x in testfiles]:
|
||||||
env["XPCSHELL_TEST_PROFILE_DIR"] = profileDir
|
testfiles = [os.path.join(testdir, singleFile)]
|
||||||
|
else: # not in this dir? skip it
|
||||||
|
continue
|
||||||
|
|
||||||
# Enable leaks (only) detection to its own log file.
|
cmdH = ", ".join(['"' + f.replace('\\', '/') + '"'
|
||||||
leakLogFile = os.path.join(profileDir, "runxpcshelltests_leaks.log")
|
for f in testHeadFiles])
|
||||||
env["XPCOM_MEM_LEAK_LOG"] = leakLogFile
|
cmdT = ", ".join(['"' + f.replace('\\', '/') + '"'
|
||||||
|
for f in testTailFiles])
|
||||||
|
cmdH = xpcsCmd + \
|
||||||
|
['-e', 'const _HEAD_FILES = [%s];' % cmdH] + \
|
||||||
|
['-e', 'const _TAIL_FILES = [%s];' % cmdT]
|
||||||
|
|
||||||
proc = Popen(cmdH + cmdT + xpcsRunArgs,
|
# Now execute each test individually.
|
||||||
stdout=pStdout, stderr=pStderr, env=env, cwd=testdir)
|
for test in testfiles:
|
||||||
|
# The test file will have to be loaded after the head files.
|
||||||
|
cmdT = ['-e', 'const _TEST_FILE = ["%s"];' %
|
||||||
|
os.path.join(testdir, test).replace('\\', '/')]
|
||||||
|
|
||||||
# allow user to kill hung subprocess with SIGINT w/o killing this script
|
# create a temp dir that the JS harness can stick a profile in
|
||||||
# - don't move this line above Popen, or child will inherit the SIG_IGN
|
profileDir = None
|
||||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
try:
|
||||||
# |stderr == None| as |pStderr| was either |None| or redirected to |stdout|.
|
profileDir = mkdtemp()
|
||||||
stdout, stderr = proc.communicate()
|
env["XPCSHELL_TEST_PROFILE_DIR"] = profileDir
|
||||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
|
||||||
|
|
||||||
if interactive:
|
# Enable leaks (only) detection to its own log file.
|
||||||
# Not sure what else to do here...
|
leakLogFile = os.path.join(profileDir, "runxpcshelltests_leaks.log")
|
||||||
return True
|
env["XPCOM_MEM_LEAK_LOG"] = leakLogFile
|
||||||
|
|
||||||
if proc.returncode != 0 or (stdout and re.search("^TEST-UNEXPECTED-FAIL", stdout, re.MULTILINE)):
|
proc = Popen(cmdH + cmdT + xpcsRunArgs,
|
||||||
print """TEST-UNEXPECTED-FAIL | %s | test failed (with xpcshell return code: %d), see following log:
|
stdout=pStdout, stderr=pStderr, env=env, cwd=testdir)
|
||||||
|
|
||||||
|
# allow user to kill hung subprocess with SIGINT w/o killing this script
|
||||||
|
# - don't move this line above Popen, or child will inherit the SIG_IGN
|
||||||
|
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||||
|
# |stderr == None| as |pStderr| was either |None| or redirected to |stdout|.
|
||||||
|
stdout, stderr = proc.communicate()
|
||||||
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||||
|
|
||||||
|
if interactive:
|
||||||
|
# Not sure what else to do here...
|
||||||
|
return True
|
||||||
|
|
||||||
|
if proc.returncode != 0 or (stdout and re.search("^TEST-UNEXPECTED-FAIL", stdout, re.MULTILINE)):
|
||||||
|
print """TEST-UNEXPECTED-FAIL | %s | test failed (with xpcshell return code: %d), see following log:
|
||||||
>>>>>>>
|
>>>>>>>
|
||||||
%s
|
%s
|
||||||
<<<<<<<""" % (test, proc.returncode, stdout)
|
<<<<<<<""" % (test, proc.returncode, stdout)
|
||||||
failCount += 1
|
failCount += 1
|
||||||
else:
|
else:
|
||||||
print "TEST-PASS | %s | test passed" % test
|
print "TEST-PASS | %s | test passed" % test
|
||||||
passCount += 1
|
passCount += 1
|
||||||
|
|
||||||
checkForCrashes(testdir, symbolsPath, testName=test)
|
checkForCrashes(testdir, symbolsPath, testName=test)
|
||||||
dumpLeakLog(leakLogFile, True)
|
dumpLeakLog(leakLogFile, True)
|
||||||
|
|
||||||
if logfiles and stdout:
|
if logfiles and stdout:
|
||||||
try:
|
try:
|
||||||
f = open(test + ".log", "w")
|
f = open(test + ".log", "w")
|
||||||
f.write(stdout)
|
f.write(stdout)
|
||||||
|
|
||||||
if os.path.exists(leakLogFile):
|
if os.path.exists(leakLogFile):
|
||||||
leaks = open(leakLogFile, "r")
|
leaks = open(leakLogFile, "r")
|
||||||
f.write(leaks.read())
|
f.write(leaks.read())
|
||||||
leaks.close()
|
leaks.close()
|
||||||
finally:
|
finally:
|
||||||
if f:
|
if f:
|
||||||
f.close()
|
f.close()
|
||||||
finally:
|
finally:
|
||||||
if profileDir:
|
if profileDir:
|
||||||
shutil.rmtree(profileDir)
|
shutil.rmtree(profileDir)
|
||||||
|
|
||||||
if passCount == 0 and failCount == 0:
|
if passCount == 0 and failCount == 0:
|
||||||
print "TEST-UNEXPECTED-FAIL | runxpcshelltests.py | No tests run. Did you pass an invalid --test-path?"
|
print "TEST-UNEXPECTED-FAIL | runxpcshelltests.py | No tests run. Did you pass an invalid --test-path?"
|
||||||
failCount = 1
|
failCount = 1
|
||||||
|
|
||||||
print """INFO | Result summary:
|
print """INFO | Result summary:
|
||||||
INFO | Passed: %d
|
INFO | Passed: %d
|
||||||
INFO | Failed: %d""" % (passCount, failCount)
|
INFO | Failed: %d""" % (passCount, failCount)
|
||||||
|
|
||||||
return failCount == 0
|
return failCount == 0
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Process command line arguments and call runTests() to do the real work."""
|
"""Process command line arguments and call runTests() to do the real work."""
|
||||||
@ -307,27 +311,29 @@ def main():
|
|||||||
|
|
||||||
if len(args) < 2 and options.manifest is None or \
|
if len(args) < 2 and options.manifest is None or \
|
||||||
(len(args) < 1 and options.manifest is not None):
|
(len(args) < 1 and options.manifest is not None):
|
||||||
print >>sys.stderr, """Usage: %s <path to xpcshell> <test dirs>
|
print >>sys.stderr, """Usage: %s <path to xpcshell> <test dirs>
|
||||||
or: %s --manifest=test.manifest <path to xpcshell>""" % (sys.argv[0],
|
or: %s --manifest=test.manifest <path to xpcshell>""" % (sys.argv[0],
|
||||||
sys.argv[0])
|
sys.argv[0])
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
debuggerInfo = getDebuggerInfo(oldcwd, options.debugger, options.debuggerArgs,
|
xpcsh = XPCShellTests()
|
||||||
|
debuggerInfo = getDebuggerInfo(xpcsh.oldcwd, options.debugger, options.debuggerArgs,
|
||||||
options.debuggerInteractive);
|
options.debuggerInteractive);
|
||||||
|
|
||||||
if options.interactive and not options.testPath:
|
if options.interactive and not options.testPath:
|
||||||
print >>sys.stderr, "Error: You must specify a test filename in interactive mode!"
|
print >>sys.stderr, "Error: You must specify a test filename in interactive mode!"
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if not runTests(args[0],
|
|
||||||
xrePath=options.xrePath,
|
if not xpcsh.runTests(args[0],
|
||||||
symbolsPath=options.symbolsPath,
|
xrePath=options.xrePath,
|
||||||
manifest=options.manifest,
|
symbolsPath=options.symbolsPath,
|
||||||
testdirs=args[1:],
|
manifest=options.manifest,
|
||||||
testPath=options.testPath,
|
testdirs=args[1:],
|
||||||
interactive=options.interactive,
|
testPath=options.testPath,
|
||||||
logfiles=options.logfiles,
|
interactive=options.interactive,
|
||||||
debuggerInfo=debuggerInfo):
|
logfiles=options.logfiles,
|
||||||
|
debuggerInfo=debuggerInfo):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -286,12 +286,6 @@ var gUpdates = {
|
|||||||
*/
|
*/
|
||||||
sourceEvent: SRCEVT_FOREGROUND,
|
sourceEvent: SRCEVT_FOREGROUND,
|
||||||
|
|
||||||
/**
|
|
||||||
* The global error message - the reason the update failed. This is human
|
|
||||||
* readable text, used to initialize the error page.
|
|
||||||
*/
|
|
||||||
errorMessage: "",
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function for onLoad
|
* Helper function for onLoad
|
||||||
* Saves default button label & accesskey for use by _setButton
|
* Saves default button label & accesskey for use by _setButton
|
||||||
@ -364,26 +358,24 @@ var gUpdates = {
|
|||||||
var p = this.update.selectedPatch;
|
var p = this.update.selectedPatch;
|
||||||
if (p) {
|
if (p) {
|
||||||
var state = p.state;
|
var state = p.state;
|
||||||
if (state == STATE_DOWNLOADING) {
|
var patchFailed;
|
||||||
var patchFailed = false;
|
try {
|
||||||
try {
|
patchFailed = this.update.getProperty("patchingFailed");
|
||||||
patchFailed = this.update.getProperty("patchingFailed");
|
}
|
||||||
}
|
catch (e) {
|
||||||
catch (e) {
|
}
|
||||||
}
|
if (patchFailed == "partial") {
|
||||||
if (patchFailed == "partial") {
|
// If the system failed to apply the partial patch, show the
|
||||||
// If the system failed to apply the partial patch, show the
|
// screen which best describes this condition, which is triggered
|
||||||
// screen which best describes this condition, which is triggered
|
// by the |STATE_FAILED| state.
|
||||||
// by the |STATE_FAILED| state.
|
state = STATE_FAILED;
|
||||||
state = STATE_FAILED;
|
}
|
||||||
}
|
else if (patchFailed == "complete") {
|
||||||
else if (patchFailed == "complete") {
|
// Otherwise, if the complete patch failed, which is far less
|
||||||
// Otherwise, if the complete patch failed, which is far less
|
// likely, show the error text held by the update object in the
|
||||||
// likely, show the error text held by the update object in the
|
// generic errors page, triggered by the |STATE_DOWNLOAD_FAILED|
|
||||||
// generic errors page, triggered by the |STATE_DOWNLOAD_FAILED|
|
// state.
|
||||||
// state.
|
state = STATE_DOWNLOAD_FAILED;
|
||||||
state = STATE_DOWNLOAD_FAILED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now select the best page to start with, given the current state of
|
// Now select the best page to start with, given the current state of
|
||||||
@ -1165,6 +1157,12 @@ var gDownloadingPage = {
|
|||||||
gUpdates.wiz.getButton("extra1").focus();
|
gUpdates.wiz.getButton("extra1").focus();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showVerificationError: function() {
|
||||||
|
var verificationError = gUpdates.getAUSString("verificationError",
|
||||||
|
[gUpdates.brandName]);
|
||||||
|
gUpdates.advanceToErrorPage(verificationError);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the text status message
|
* Updates the text status message
|
||||||
*/
|
*/
|
||||||
|
@ -341,7 +341,6 @@ protected:
|
|||||||
void OnWindowPosChanged(WINDOWPOS *wp, PRBool& aResult);
|
void OnWindowPosChanged(WINDOWPOS *wp, PRBool& aResult);
|
||||||
#if defined(CAIRO_HAS_DDRAW_SURFACE)
|
#if defined(CAIRO_HAS_DDRAW_SURFACE)
|
||||||
PRBool OnPaintImageDDraw16();
|
PRBool OnPaintImageDDraw16();
|
||||||
HRESULT PaintRectImageDDraw16(RECT aRect, nsPaintEvent* aEvent);
|
|
||||||
#endif // defined(CAIRO_HAS_DDRAW_SURFACE)
|
#endif // defined(CAIRO_HAS_DDRAW_SURFACE)
|
||||||
PRBool OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam,
|
PRBool OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam,
|
||||||
PRBool& result, PRBool& getWheelInfo,
|
PRBool& result, PRBool& getWheelInfo,
|
||||||
|
@ -878,147 +878,31 @@ HBITMAP nsWindowGfx::DataToBitmap(PRUint8* aImageData,
|
|||||||
|
|
||||||
// Windows Mobile Special image/direct draw painting fun
|
// Windows Mobile Special image/direct draw painting fun
|
||||||
#if defined(CAIRO_HAS_DDRAW_SURFACE)
|
#if defined(CAIRO_HAS_DDRAW_SURFACE)
|
||||||
HRESULT nsWindow::PaintRectImageDDraw16(RECT rcPaint, nsPaintEvent* event){
|
PRBool nsWindow::OnPaintImageDDraw16()
|
||||||
HRESULT hr;
|
{
|
||||||
|
PRBool result = PR_FALSE;
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
|
||||||
gfxIntSize surfaceSize;
|
gfxIntSize surfaceSize;
|
||||||
nsRefPtr<gfxImageSurface> targetSurfaceImage;
|
nsRefPtr<gfxImageSurface> targetSurfaceImage;
|
||||||
nsRefPtr<gfxContext> thebesContext;
|
nsRefPtr<gfxContext> thebesContext;
|
||||||
nsCOMPtr<nsIRenderingContext> rc;
|
nsCOMPtr<nsIRenderingContext> rc;
|
||||||
nsEventStatus eventStatus = nsEventStatus_eIgnore;
|
nsEventStatus eventStatus = nsEventStatus_eIgnore;
|
||||||
RECT renderArea;
|
PRInt32 brx, bry, brw, brh;
|
||||||
|
|
||||||
surfaceSize = gfxIntSize(rcPaint.right - rcPaint.left,
|
|
||||||
rcPaint.bottom - rcPaint.top);
|
|
||||||
|
|
||||||
if (!EnsureSharedSurfaceSize(surfaceSize)) {
|
|
||||||
NS_ERROR("Couldn't allocate shared surface!");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
targetSurfaceImage = new gfxImageSurface(sSharedSurfaceData.get(),
|
|
||||||
surfaceSize,
|
|
||||||
surfaceSize.width * 4,
|
|
||||||
gfxASurface::ImageFormatRGB24);
|
|
||||||
|
|
||||||
if (!targetSurfaceImage || targetSurfaceImage->CairoStatus()) {
|
|
||||||
NS_ERROR("Invalid targetSurfaceImage!");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
targetSurfaceImage->SetDeviceOffset(gfxPoint(-rcPaint.left, -rcPaint.top));
|
|
||||||
|
|
||||||
thebesContext = new gfxContext(targetSurfaceImage);
|
|
||||||
thebesContext->SetFlag(gfxContext::FLAG_DESTINED_FOR_SCREEN);
|
|
||||||
thebesContext->SetFlag(gfxContext::FLAG_SIMPLIFY_OPERATORS);
|
|
||||||
|
|
||||||
nsresult rv = mContext->CreateRenderingContextInstance (*getter_AddRefs(rc));
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
NS_WARNING("CreateRenderingContextInstance failed");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = rc->Init(mContext, thebesContext);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
NS_WARNING("RC::Init failed");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
event->renderingContext = rc;
|
|
||||||
nsresult result = DispatchWindowEvent(event, eventStatus);
|
|
||||||
event->renderingContext = nsnull;
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
printf("result is null from dispatch\n");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
hr = glpDDSecondary->Lock(0, &gDDSDSecondary, DDLOCK_WAITNOTBUSY | DDLOCK_DISCARD, 0); /* should we wait here? */
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
DDError("Failed to lock renderer", hr);
|
|
||||||
#endif
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert RGB24 -> RGB565
|
|
||||||
pixman_image_t *srcPixmanImage = pixman_image_create_bits(PIXMAN_x8r8g8b8,
|
|
||||||
surfaceSize.width,
|
|
||||||
surfaceSize.height,
|
|
||||||
(uint32_t*) sSharedSurfaceData.get(),
|
|
||||||
surfaceSize.width * 4);
|
|
||||||
|
|
||||||
pixman_image_t *dstPixmanImage = pixman_image_create_bits(PIXMAN_r5g6b5,
|
|
||||||
gDDSDSecondary.dwWidth,
|
|
||||||
gDDSDSecondary.dwHeight,
|
|
||||||
(uint32_t*) gDDSDSecondary.lpSurface,
|
|
||||||
gDDSDSecondary.dwWidth * 2);
|
|
||||||
|
|
||||||
pixman_image_composite(PIXMAN_OP_SRC,
|
|
||||||
srcPixmanImage,
|
|
||||||
NULL,
|
|
||||||
dstPixmanImage,
|
|
||||||
0, 0,
|
|
||||||
0, 0,
|
|
||||||
0, 0,
|
|
||||||
surfaceSize.width,
|
|
||||||
surfaceSize.height);
|
|
||||||
|
|
||||||
pixman_image_unref(dstPixmanImage);
|
|
||||||
pixman_image_unref(srcPixmanImage);
|
|
||||||
|
|
||||||
hr = glpDDSecondary->Unlock(0);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
DDError("Failed to unlock renderer", hr);
|
|
||||||
#endif
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = glpDDClipper->SetHWnd(0, mWnd);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
DDError("SetHWnd", hr);
|
|
||||||
#endif
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// translate the paint region to screen coordinates
|
|
||||||
renderArea = rcPaint;
|
|
||||||
MapWindowPoints(mWnd, 0, (LPPOINT)&renderArea, 2);
|
|
||||||
|
|
||||||
// set the rect to be 0,0 based
|
|
||||||
rcPaint.right = surfaceSize.width;
|
|
||||||
rcPaint.bottom = surfaceSize.height;
|
|
||||||
rcPaint.left = rcPaint.top = 0;
|
|
||||||
|
|
||||||
return glpDDPrimary->Blt(&renderArea,
|
|
||||||
glpDDSecondary,
|
|
||||||
&rcPaint,
|
|
||||||
DDBLT_WAITNOTBUSY, /* should we really wait here? */
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PRBool nsWindow::OnPaintImageDDraw16()
|
|
||||||
{
|
|
||||||
PRBool result = PR_TRUE;
|
|
||||||
PAINTSTRUCT ps;
|
|
||||||
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
|
|
||||||
mPainting = PR_TRUE;
|
|
||||||
gfxIntSize newSize;
|
gfxIntSize newSize;
|
||||||
newSize.height = GetSystemMetrics(SM_CYSCREEN);
|
newSize.height = GetSystemMetrics(SM_CYSCREEN);
|
||||||
newSize.width = GetSystemMetrics(SM_CXSCREEN);
|
newSize.width = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
mPainting = PR_TRUE;
|
||||||
|
|
||||||
HDC hDC = ::BeginPaint(mWnd, &ps);
|
HDC hDC = ::BeginPaint(mWnd, &ps);
|
||||||
mPaintDC = hDC;
|
mPaintDC = hDC;
|
||||||
nsCOMPtr<nsIRegion> paintRgnWin = GetRegionToPaint(PR_FALSE, ps, hDC);
|
nsCOMPtr<nsIRegion> paintRgnWin = GetRegionToPaint(PR_FALSE, ps, hDC);
|
||||||
|
|
||||||
if (!paintRgnWin || paintRgnWin->IsEmpty() || !mEventCallback) {
|
if (!paintRgnWin || paintRgnWin->IsEmpty() || !mEventCallback) {
|
||||||
printf("nothing to paint\n");
|
result = PR_TRUE;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitEvent(event);
|
InitEvent(event);
|
||||||
|
|
||||||
event.region = paintRgnWin;
|
event.region = paintRgnWin;
|
||||||
@ -1058,22 +942,111 @@ PRBool nsWindow::OnPaintImageDDraw16()
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
paintRgnWin->GetBoundingBox(&brx, &bry, &brw, &brh);
|
||||||
|
surfaceSize = gfxIntSize(brw, brh);
|
||||||
|
|
||||||
|
if (!EnsureSharedSurfaceSize(surfaceSize))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
targetSurfaceImage = new gfxImageSurface(sSharedSurfaceData.get(),
|
||||||
|
surfaceSize,
|
||||||
|
surfaceSize.width * 4,
|
||||||
|
gfxASurface::ImageFormatRGB24);
|
||||||
|
|
||||||
|
if (!targetSurfaceImage || targetSurfaceImage->CairoStatus())
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
targetSurfaceImage->SetDeviceOffset(gfxPoint(-brx, -bry));
|
||||||
|
|
||||||
|
thebesContext = new gfxContext(targetSurfaceImage);
|
||||||
|
thebesContext->SetFlag(gfxContext::FLAG_DESTINED_FOR_SCREEN);
|
||||||
|
thebesContext->SetFlag(gfxContext::FLAG_SIMPLIFY_OPERATORS);
|
||||||
|
|
||||||
|
nsresult rv = mContext->CreateRenderingContextInstance (*getter_AddRefs(rc));
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
rv = rc->Init(mContext, thebesContext);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
event.renderingContext = rc;
|
||||||
|
PRBool res = DispatchWindowEvent(&event, eventStatus);
|
||||||
|
event.renderingContext = nsnull;
|
||||||
|
|
||||||
|
if (!res && eventStatus == nsEventStatus_eConsumeNoDefault)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
nsRegionRectSet *rects = nsnull;
|
nsRegionRectSet *rects = nsnull;
|
||||||
RECT r;
|
RECT r;
|
||||||
paintRgnWin->GetRects(&rects);
|
paintRgnWin->GetRects(&rects);
|
||||||
|
|
||||||
|
HRESULT hr = glpDDSecondary->Lock(0, &gDDSDSecondary, DDLOCK_WAITNOTBUSY | DDLOCK_DISCARD, 0);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
pixman_image_t *srcPixmanImage =
|
||||||
|
pixman_image_create_bits(PIXMAN_x8r8g8b8, surfaceSize.width,
|
||||||
|
surfaceSize.height,
|
||||||
|
(uint32_t*) sSharedSurfaceData.get(),
|
||||||
|
surfaceSize.width * 4);
|
||||||
|
|
||||||
|
pixman_image_t *dstPixmanImage =
|
||||||
|
pixman_image_create_bits(PIXMAN_r5g6b5, gDDSDSecondary.dwWidth,
|
||||||
|
gDDSDSecondary.dwHeight,
|
||||||
|
(uint32_t*) gDDSDSecondary.lpSurface,
|
||||||
|
gDDSDSecondary.dwWidth * 2);
|
||||||
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < rects->mNumRects; i++) {
|
for (unsigned int i = 0; i < rects->mNumRects; i++) {
|
||||||
|
pixman_image_composite(PIXMAN_OP_SRC, srcPixmanImage, NULL, dstPixmanImage,
|
||||||
|
rects->mRects[i].x - brx, rects->mRects[i].y - bry,
|
||||||
|
0, 0,
|
||||||
|
rects->mRects[i].x, rects->mRects[i].y,
|
||||||
|
rects->mRects[i].width, rects->mRects[i].height);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_image_unref(dstPixmanImage);
|
||||||
|
pixman_image_unref(srcPixmanImage);
|
||||||
|
|
||||||
|
hr = glpDDSecondary->Unlock(0);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
hr = glpDDClipper->SetHWnd(0, mWnd);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < rects->mNumRects; i++) {
|
||||||
r.left = rects->mRects[i].x;
|
r.left = rects->mRects[i].x;
|
||||||
r.top = rects->mRects[i].y;
|
r.top = rects->mRects[i].y;
|
||||||
r.right = rects->mRects[i].width + rects->mRects[i].x;
|
r.right = rects->mRects[i].width + rects->mRects[i].x;
|
||||||
r.bottom = rects->mRects[i].height + rects->mRects[i].y;
|
r.bottom = rects->mRects[i].height + rects->mRects[i].y;
|
||||||
PaintRectImageDDraw16(r, &event);
|
RECT renderRect = r;
|
||||||
|
SetLastError(0); // See http://msdn.microsoft.com/en-us/library/dd145046%28VS.85%29.aspx
|
||||||
|
if (MapWindowPoints(mWnd, 0, (LPPOINT)&renderRect, 2) || 0 == (hr = GetLastError()))
|
||||||
|
hr = glpDDPrimary->Blt(&renderRect, glpDDSecondary, &r, 0, NULL);
|
||||||
|
#ifdef WINCE_WINDOWS_MOBILE
|
||||||
|
if (FAILED(hr))
|
||||||
|
// add this rect back to the invalidated region so we'll attempt paint it next time around
|
||||||
|
mInvalidatedRegion->Union(rects->mRects[i].x, rects->mRects[i].y,
|
||||||
|
rects->mRects[i].width, rects->mRects[i].height);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
result = PR_TRUE;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
#ifdef WINCE_WINDOWS_MOBILE
|
||||||
|
// re-invalidate the region if we failed.
|
||||||
|
if (!result)
|
||||||
|
mInvalidatedRegion->Union(*paintRgnWin.get());
|
||||||
|
#endif
|
||||||
::EndPaint(mWnd, &ps);
|
::EndPaint(mWnd, &ps);
|
||||||
mPaintDC = nsnull;
|
mPaintDC = nsnull;
|
||||||
mPainting = PR_FALSE;
|
mPainting = PR_FALSE;
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif // defined(CAIRO_HAS_DDRAW_SURFACE)
|
#endif // defined(CAIRO_HAS_DDRAW_SURFACE)
|
||||||
|
Loading…
Reference in New Issue
Block a user