Merge the last green PGO changeset from mozilla-inbound to mozilla-central

This commit is contained in:
Ehsan Akhgari 2012-07-06 10:45:06 -04:00
Родитель d712821491 b1f0381abe
Коммит 1aabf0598f
163 изменённых файлов: 1441 добавлений и 2681 удалений

Просмотреть файл

@ -62,8 +62,8 @@ interface nsIAccessibleProvider : nsISupports
const long XULTab = 0x00001017;
/** Used for XUL tabs element, a container for tab elements */
const long XULTabs = 0x00001018;
/** Used for XUL tabpanels container element */
const long XULTabpanels = 0x00001019;
/** Used for XUL deck frame */
const long XULDeck = 0x00001019;
const long XULText = 0x0000101A;
const long XULTextBox = 0x0000101B;

Просмотреть файл

@ -1153,11 +1153,14 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
}
if (!newAcc) {
// Create generic accessibles for SVG and MathML nodes.
if (content->IsSVG(nsGkAtoms::svg)) {
// xul:deck does not have XBL and nsIFrame::CreateAccessible() is only called
// on HTML elements
nsIAtom* tag = content->Tag();
if ((tag == nsGkAtoms::deck) || (tag == nsGkAtoms::tabpanels)) {
newAcc = new XULDeckAccessible(content, docAcc);
} else if (content->IsSVG(nsGkAtoms::svg)) {
newAcc = new EnumRoleAccessible(content, docAcc, roles::DIAGRAM);
}
else if (content->IsMathML(nsGkAtoms::math)) {
} else if (content->IsMathML(nsGkAtoms::math)) {
newAcc = new EnumRoleAccessible(content, docAcc, roles::EQUATION);
}
}
@ -1326,6 +1329,10 @@ nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
accessible = new XULComboboxAccessible(aContent, aDoc);
break;
case nsIAccessibleProvider::XULDeck:
accessible = new XULDeckAccessible(aContent, aDoc);
break;
case nsIAccessibleProvider::XULDropmarker:
accessible = new XULDropmarkerAccessible(aContent, aDoc);
break;
@ -1430,10 +1437,6 @@ nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
accessible = new XULTabsAccessible(aContent, aDoc);
break;
case nsIAccessibleProvider::XULTabpanels:
accessible = new XULTabpanelsAccessible(aContent, aDoc);
break;
case nsIAccessibleProvider::XULText:
accessible = new XULLabelAccessible(aContent, aDoc);
break;

Просмотреть файл

@ -508,6 +508,8 @@ public:
inline bool IsXULTree() const { return mFlags & eXULTreeAccessible; }
mozilla::a11y::XULTreeAccessible* AsXULTree();
inline bool IsXULDeck() const { return mFlags & eXULDeckAccessible; }
inline bool IsListControl() const { return mFlags & eListControlAccessible; }
inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
@ -766,7 +768,8 @@ protected:
eMenuPopupAccessible = 1 << 16,
eRootAccessible = 1 << 17,
eTextLeafAccessible = 1 << 18,
eXULTreeAccessible = 1 << 19
eXULDeckAccessible = 1 << 19,
eXULTreeAccessible = 1 << 20
};
//////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -59,6 +59,9 @@ AccessibleWrap::GetNativeType ()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (IsXULDeck())
return [mozPaneAccessible class];
roles::Role role = Role();
switch (role) {
case roles::PUSHBUTTON:
@ -81,15 +84,17 @@ AccessibleWrap::GetNativeType ()
case roles::PAGETABLIST:
return [mozTabsAccessible class];
case roles::ENTRY:
case roles::STATICTEXT:
case roles::CAPTION:
case roles::ACCEL_LABEL:
case roles::TEXT_LEAF:
case roles::PASSWORD_TEXT:
// normal textfield (static or editable)
return [mozTextAccessible class];
return [mozTextAccessible class];
case roles::TEXT_LEAF:
return [mozTextLeafAccessible class];
case roles::LINK:
return [mozLinkAccessible class];

Просмотреть файл

@ -48,5 +48,7 @@ LOCAL_INCLUDES += \
-I$(srcdir)/../xul \
-I$(topsrcdir)/widget/cocoa \
-I$(topsrcdir)/widget/xpwidgets \
-I$(topsrcdir)/layout/xul/base/src \
-I$(topsrcdir)/layout/generic \
$(NULL)

Просмотреть файл

@ -23,6 +23,14 @@ GetObjectOrRepresentedView(id <mozAccessible> aObject)
return [aObject hasRepresentedView] ? [aObject representedView] : aObject;
}
inline mozAccessible*
GetNativeFromGeckoAccessible(nsIAccessible* aAccessible)
{
mozAccessible* native = nil;
aAccessible->GetNativeInterface((void**)&native);
return native;
}
@interface mozAccessible : NSObject <mozAccessible>
{
/**
@ -39,15 +47,7 @@ GetObjectOrRepresentedView(id <mozAccessible> aObject)
* Weak reference to the parent
*/
mozAccessible* mParent;
/**
* We can be marked as 'expired' if Shutdown() is called on our geckoAccessible.
* since we might still be retained by some third-party, we need to do cleanup
* in |expire|, and prevent any potential harm that could come from someone using us
* after this point.
*/
BOOL mIsExpired;
/**
* The nsIAccessible role of our gecko accessible.
*/

Просмотреть файл

@ -9,6 +9,7 @@
#import "mozView.h"
#include "Accessible-inl.h"
#include "nsAccUtils.h"
#include "nsIAccessibleRelation.h"
#include "nsIAccessibleText.h"
#include "nsIAccessibleEditableText.h"
@ -21,6 +22,7 @@
#include "nsCocoaUtils.h"
#include "nsCoord.h"
#include "nsObjCExceptions.h"
#include "nsWhitespaceTokenizer.h"
using namespace mozilla;
using namespace mozilla::a11y;
@ -63,18 +65,6 @@ GetClosestInterestingAccessible(id anObject)
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
static inline mozAccessible*
GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL;
mozAccessible *native = nil;
anAccessible->GetNativeInterface ((void**)&native);
return native;
NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL;
}
#pragma mark -
@implementation mozAccessible
@ -85,7 +75,6 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
if ((self = [super init])) {
mGeckoAccessible = geckoAccessible;
mIsExpired = NO;
mRole = geckoAccessible->Role();
}
@ -112,7 +101,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
// unknown (either unimplemented, or irrelevant) elements are marked as ignored
// as well as expired elements.
return mIsExpired || [[self role] isEqualToString:NSAccessibilityUnknownRole];
return !mGeckoAccessible || [[self role] isEqualToString:NSAccessibilityUnknownRole];
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
}
@ -122,7 +111,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
// if we're expired, we don't support any attributes.
if (mIsExpired)
if (!mGeckoAccessible)
return [NSArray array];
static NSArray *generalAttributes = nil;
@ -160,7 +149,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (mIsExpired)
if (!mGeckoAccessible)
return nil;
#if DEBUG
@ -246,7 +235,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
- (id)accessibilityHitTest:(NSPoint)point
{
if (mIsExpired)
if (!mGeckoAccessible)
return nil;
// Convert from cocoa's coordinate system to gecko's. According to the docs
@ -288,7 +277,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
- (id)accessibilityFocusedUIElement
{
if (mIsExpired)
if (!mGeckoAccessible)
return nil;
Accessible* focusedGeckoChild = mGeckoAccessible->FocusedChild();
@ -420,7 +409,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
- (NSString*)role
{
if (mIsExpired)
if (!mGeckoAccessible)
return nil;
#ifdef DEBUG
@ -444,6 +433,42 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
- (NSString*)subrole
{
if (!mGeckoAccessible)
return nil;
// XXX maybe we should cache the subrole.
nsAutoString xmlRoles;
nsCOMPtr<nsIPersistentProperties> attributes;
// XXX we don't need all the attributes (see bug 771113)
nsresult rv = mGeckoAccessible->GetAttributes(getter_AddRefs(attributes));
if (NS_SUCCEEDED(rv) && attributes)
nsAccUtils::GetAccAttr(attributes, nsGkAtoms::xmlroles, xmlRoles);
nsWhitespaceTokenizer tokenizer(xmlRoles);
while (tokenizer.hasMoreTokens()) {
const nsDependentSubstring token(tokenizer.nextToken());
if (token.EqualsLiteral("banner"))
return @"AXLandmarkBanner";
if (token.EqualsLiteral("complementary"))
return @"AXLandmarkComplementary";
if (token.EqualsLiteral("contentinfo"))
return @"AXLandmarkContentInfo";
if (token.EqualsLiteral("main"))
return @"AXLandmarkMain";
if (token.EqualsLiteral("navigation"))
return @"AXLandmarkNavigation";
if (token.EqualsLiteral("search"))
return @"AXLandmarkSearch";
}
switch (mRole) {
case roles::LIST:
return @"AXContentList"; // 10.6+ NSAccessibilityContentListSubrole;
@ -468,15 +493,33 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
{
if (mRole == roles::DOCUMENT)
return utils::LocalizedString(NS_LITERAL_STRING("htmlContent"));
NSString* subrole = [self subrole];
if ((mRole == roles::LISTITEM) && [subrole isEqualToString:@"AXTerm"])
return utils::LocalizedString(NS_LITERAL_STRING("term"));
if ((mRole == roles::PARAGRAPH) && [subrole isEqualToString:@"AXDefinition"])
return utils::LocalizedString(NS_LITERAL_STRING("definition"));
return NSAccessibilityRoleDescription([self role], subrole);
NSString* role = [self role];
// the WAI-ARIA Landmarks
if ([role isEqualToString:NSAccessibilityGroupRole]) {
if ([subrole isEqualToString:@"AXLandmarkBanner"])
return utils::LocalizedString(NS_LITERAL_STRING("banner"));
if ([subrole isEqualToString:@"AXLandmarkComplementary"])
return utils::LocalizedString(NS_LITERAL_STRING("complementary"));
if ([subrole isEqualToString:@"AXLandmarkContentInfo"])
return utils::LocalizedString(NS_LITERAL_STRING("content"));
if ([subrole isEqualToString:@"AXLandmarkMain"])
return utils::LocalizedString(NS_LITERAL_STRING("main"));
if ([subrole isEqualToString:@"AXLandmarkNavigation"])
return utils::LocalizedString(NS_LITERAL_STRING("navigation"));
if ([subrole isEqualToString:@"AXLandmarkSearch"])
return utils::LocalizedString(NS_LITERAL_STRING("search"));
}
return NSAccessibilityRoleDescription(role, subrole);
}
- (NSString*)title
@ -485,7 +528,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
nsAutoString title;
mGeckoAccessible->Name(title);
return title.IsEmpty() ? nil : [NSString stringWithCharacters:title.BeginReading() length:title.Length()];
return nsCocoaUtils::ToNSString(title);
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
@ -528,7 +571,8 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
nsAutoString desc;
mGeckoAccessible->Description(desc);
return desc.IsEmpty() ? nil : [NSString stringWithCharacters:desc.BeginReading() length:desc.Length()];
return nsCocoaUtils::ToNSString(desc);
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
@ -561,18 +605,21 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
- (BOOL)canBeFocused
{
return mGeckoAccessible->InteractiveState() & states::FOCUSABLE;
return mGeckoAccessible && (mGeckoAccessible->InteractiveState() & states::FOCUSABLE);
}
- (BOOL)focus
{
if (!mGeckoAccessible)
return NO;
nsresult rv = mGeckoAccessible->TakeFocus();
return NS_SUCCEEDED(rv);
}
- (BOOL)isEnabled
{
return (mGeckoAccessible->InteractiveState() & states::UNAVAILABLE) == 0;
return mGeckoAccessible && ((mGeckoAccessible->InteractiveState() & states::UNAVAILABLE) == 0);
}
// The root accessible calls this when the focused node was
@ -637,7 +684,6 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
[self invalidateChildren];
mIsExpired = YES;
mGeckoAccessible = nsnull;
NS_OBJC_END_TRY_ABORT_BLOCK;
@ -645,7 +691,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
- (BOOL)isExpired
{
return mIsExpired;
return !mGeckoAccessible;
}
#pragma mark -

Просмотреть файл

@ -29,3 +29,10 @@
}
-(id)tabs;
@end
/**
* Accessible for a PANE
*/
@interface mozPaneAccessible : mozAccessible
@end

Просмотреть файл

@ -7,8 +7,10 @@
#import "MacUtils.h"
#include "Accessible-inl.h"
#include "DocAccessible.h"
#include "XULTabAccessible.h"
#include "nsDeckFrame.h"
#include "nsObjCExceptions.h"
using namespace mozilla::a11y;
@ -71,7 +73,7 @@ enum CheckboxValue {
- (BOOL)accessibilityIsIgnored
{
return mIsExpired;
return !mGeckoAccessible;
}
- (NSArray*)accessibilityActionNames
@ -333,3 +335,30 @@ enum CheckboxValue {
}
@end
@implementation mozPaneAccessible
- (NSArray*)children
{
if (!mGeckoAccessible)
return nil;
nsDeckFrame* deckFrame = do_QueryFrame(mGeckoAccessible->GetFrame());
nsIFrame* selectedFrame = deckFrame ? deckFrame->GetSelectedBox() : nsnull;
Accessible* selectedAcc = nsnull;
if (selectedFrame) {
nsINode* node = selectedFrame->GetContent();
selectedAcc = mGeckoAccessible->Document()->GetAccessible(node);
}
if (selectedAcc) {
mozAccessible *curNative = GetNativeFromGeckoAccessible(selectedAcc);
if (curNative)
return [NSArray arrayWithObjects:GetObjectOrRepresentedView(curNative), nil];
}
return nil;
}
@end

Просмотреть файл

@ -31,7 +31,7 @@ getNativeViewFromRootAccessible(Accessible* aAccessible)
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
// if we're expired, we don't support any attributes.
if (mIsExpired)
if (!mGeckoAccessible)
return [NSArray array];
// standard attributes that are shared and supported by root accessible (AXMain) elements.

Просмотреть файл

@ -13,6 +13,17 @@
@implementation mozHeadingAccessible
- (NSString*)title
{
nsAutoString title;
// XXX use the flattening API when there are available
// see bug 768298
nsresult rv = mGeckoAccessible->GetContent()->GetTextContent(title);
NS_ENSURE_SUCCESS(rv, nil);
return nsCocoaUtils::ToNSString(title);
}
- (id)value
{
if (!mGeckoAccessible || !mGeckoAccessible->IsHyperText())
@ -33,7 +44,7 @@
- (NSArray*)accessibilityAttributeNames
{
// if we're expired, we don't support any attributes.
if (mIsExpired)
if (!mGeckoAccessible)
return [NSArray array];
static NSMutableArray* attributes = nil;
@ -57,7 +68,7 @@
- (NSArray*)accessibilityActionNames
{
// if we're expired, we don't support any attributes.
if (mIsExpired)
if (!mGeckoAccessible)
return [NSArray array];
static NSArray* actionNames = nil;

Просмотреть файл

@ -14,3 +14,8 @@
nsIAccessibleEditableText *mGeckoEditableTextAccessible; // strong
}
@end
@interface mozTextLeafAccessible : mozAccessible
{
}
@end

Просмотреть файл

@ -5,6 +5,7 @@
#include "AccessibleWrap.h"
#include "TextLeafAccessible.h"
#include "nsCocoaUtils.h"
#include "nsObjCExceptions.h"
@ -67,7 +68,7 @@ ToNSString(id aValue)
- (BOOL)accessibilityIsIgnored
{
return mIsExpired;
return !mGeckoAccessible;
}
- (NSArray*)accessibilityAttributeNames
@ -110,13 +111,18 @@ ToNSString(id aValue)
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute])
return [self selectedText];
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
return @"";
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
// Apple's SpeechSynthesisServer expects AXValue to return an AXStaticText
// object's AXSelectedText attribute. See bug 674612 for details.
// Also if there is no selected text, we return the full text.
// See bug 369710 for details.
if ([[self role] isEqualToString:NSAccessibilityStaticTextRole])
return [self selectedText] ? : [self text];
if ([[self role] isEqualToString:NSAccessibilityStaticTextRole]) {
NSString* selectedText = [self selectedText];
return (selectedText && [selectedText length]) ? selectedText : [self text];
}
return [self text];
}
@ -226,7 +232,7 @@ ToNSString(id aValue)
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
return [self isReadOnly];
return ![self isReadOnly];
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute] ||
[attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute] ||
@ -359,7 +365,7 @@ ToNSString(id aValue)
- (NSString*)text
{
if (!mGeckoTextAccessible)
if (!mGeckoAccessible || !mGeckoTextAccessible)
return nil;
// A password text field returns an empty value
@ -378,6 +384,9 @@ ToNSString(id aValue)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
if (!mGeckoAccessible || !mGeckoTextAccessible)
return 0;
return mGeckoTextAccessible ? mGeckoTextAccessible->CharacterCount() : 0;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
@ -484,3 +493,45 @@ ToNSString(id aValue)
}
@end
@implementation mozTextLeafAccessible
- (NSArray*)accessibilityAttributeNames
{
static NSMutableArray* supportedAttributes = nil;
if (!supportedAttributes) {
supportedAttributes = [[super accessibilityAttributeNames] mutableCopy];
[supportedAttributes removeObject:NSAccessibilityChildrenAttribute];
}
return supportedAttributes;
}
- (id)accessibilityAttributeValue:(NSString*)attribute
{
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
return @"";
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
return [self text];
return [super accessibilityAttributeValue:attribute];
}
- (NSString*)text
{
if (!mGeckoAccessible)
return nil;
return nsCocoaUtils::ToNSString(mGeckoAccessible->AsTextLeaf()->Text());
}
- (long)textLength
{
if (!mGeckoAccessible)
return 0;
return mGeckoAccessible->AsTextLeaf()->Text().Length();
}
@end

Просмотреть файл

@ -164,22 +164,15 @@ XULTabsAccessible::GetNameInternal(nsAString& aName)
////////////////////////////////////////////////////////////////////////////////
// XULTabpanelsAccessible
// XULDeckAccessible
////////////////////////////////////////////////////////////////////////////////
XULTabpanelsAccessible::
XULTabpanelsAccessible(nsIContent* aContent, DocAccessible* aDoc) :
AccessibleWrap(aContent, aDoc)
{
}
role
XULTabpanelsAccessible::NativeRole()
XULDeckAccessible::NativeRole()
{
return roles::PANE;
}
////////////////////////////////////////////////////////////////////////////////
// XULTabpanelAccessible
////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -56,13 +56,15 @@ public:
};
/**
/**
* A container of tab panels, xul:tabpanels element.
*/
class XULTabpanelsAccessible : public AccessibleWrap
class XULDeckAccessible : public AccessibleWrap
{
public:
XULTabpanelsAccessible(nsIContent* aContent, DocAccessible* aDoc);
XULDeckAccessible(nsIContent* aContent, DocAccessible* aDoc) :
AccessibleWrap(aContent, aDoc)
{ mFlags |= eXULDeckAccessible; }
// Accessible
virtual a11y::role NativeRole();

Просмотреть файл

@ -161,7 +161,7 @@ DeviceTabActor.prototype = {
'tab should have an actorID.');
return {
'actor': this.actorID,
'title': this.browser.contentTitle,
'title': this.browser.title,
'url': this.browser.document.documentURI
}
},
@ -222,7 +222,7 @@ DeviceTabActor.prototype = {
this.conn.addActorPool(this._contextPool);
this.threadActor = new ThreadActor(this);
this._addDebuggees(this.browser.content.wrappedJSObject);
this._addDebuggees(this.browser.wrappedJSObject);
this._contextPool.addActor(this.threadActor);
},
@ -293,7 +293,7 @@ DeviceTabActor.prototype = {
* Prepare to enter a nested event loop by disabling debuggee events.
*/
preNest: function DTA_preNest() {
let windowUtils = this.browser.content
let windowUtils = this.browser
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
windowUtils.suppressEventHandling(true);
@ -304,7 +304,7 @@ DeviceTabActor.prototype = {
* Prepare to exit a nested event loop by enabling debuggee events.
*/
postNest: function DTA_postNest(aNestData) {
let windowUtils = this.browser.content
let windowUtils = this.browser
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
windowUtils.resumeTimeouts();

Просмотреть файл

@ -2610,13 +2610,16 @@ function BrowserOnClick(event) {
if (previousNotification)
notificationBox.removeNotification(previousNotification);
notificationBox.appendNotification(
let notification = notificationBox.appendNotification(
title,
value,
"chrome://global/skin/icons/blacklist_favicon.png",
notificationBox.PRIORITY_CRITICAL_HIGH,
buttons
);
// Persist the notification until the user removes so it
// doesn't get removed on redirects.
notification.persistence = -1;
}
}
else if (/^about:home$/i.test(ownerDoc.documentURI)) {

Просмотреть файл

@ -7,6 +7,7 @@ let EXPORTED_SYMBOLS = ["WebappsInstaller"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");

Просмотреть файл

@ -3616,7 +3616,7 @@ PrintPropertyPolicy(PLDHashTable *table, PLDHashEntryHdr *entry,
JSContext* cx = (JSContext*)arg;
prop.AppendInt((PRUint32)pp->key);
prop += ' ';
prop.AppendWithConversion((PRUnichar*)JS_GetStringChars(pp->key));
LossyAppendUTF16toASCII((PRUnichar*)JS_GetStringChars(pp->key), prop);
prop += ": Get=";
if (SECURITY_ACCESS_LEVEL_FLAG(pp->mGet))
prop.AppendInt(pp->mGet.level);

Просмотреть файл

@ -8859,10 +8859,10 @@ mkdir -p _virtualenv
MACOSX_DEPLOYMENT_TARGET= PYTHONDONTWRITEBYTECODE= $PYTHON $_topsrcdir/other-licenses/virtualenv/virtualenv.py --system-site-packages ./_virtualenv
case "$host_os" in
mingw*)
PYTHON=`pwd`/_virtualenv/Scripts/python.exe
PYTHON=$MOZ_BUILD_ROOT/_virtualenv/Scripts/python.exe
;;
*)
PYTHON=`pwd`/_virtualenv/bin/python
PYTHON=$MOZ_BUILD_ROOT/_virtualenv/bin/python
;;
esac

Просмотреть файл

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var j = 0;
var a = document.getElementById("a");
var r = document.createRange();
r.setStart(a.childNodes[0], 0);
r.setEnd(a.childNodes[1], 0);
function f()
{
if (++j >= 2) {
document.removeEventListener("DOMNodeRemoved", f, false);
}
r.extractContents();
}
document.addEventListener("DOMNodeRemoved", f, false);
r.extractContents();
}
</script>
</head>
<body onload="boom();">
<div id="a"><span><span></span></span>X</div>
</body>
</html>

Просмотреть файл

@ -108,6 +108,7 @@ load 713417.html
load 713417-2.html
load 715056.html
load 741163-1.html
load 766426.html
asserts(0-1) load 752226-1.html
asserts(0-1) load 752226-2.html
HTTP(..) load xhr_abortinprogress.html

Просмотреть файл

@ -1446,6 +1446,21 @@ PrependChild(nsIDOMNode* aParent, nsIDOMNode* aChild)
return aParent->InsertBefore(aChild, first, getter_AddRefs(tmpNode));
}
// Helper function for CutContents, making sure that the current node wasn't
// removed by mutation events (bug 766426)
static bool
ValidateCurrentNode(nsRange* aRange, RangeSubtreeIterator& aIter)
{
bool before, after;
nsCOMPtr<nsIDOMNode> domNode = aIter.GetCurrentNode();
nsCOMPtr<nsINode> node = do_QueryInterface(domNode);
MOZ_ASSERT(node);
nsresult res = nsRange::CompareNodeToRange(node, aRange, &before, &after);
return NS_SUCCEEDED(res) && !before && !after;
}
nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
{
if (aFragment) {
@ -1573,8 +1588,11 @@ nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
nodeToResult = clone;
}
nsMutationGuard guard;
rv = charData->DeleteData(startOffset, endOffset - startOffset);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(!guard.Mutated(0) ||
ValidateCurrentNode(this, iter));
}
handled = true;
@ -1588,9 +1606,12 @@ nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
if (dataLength >= (PRUint32)startOffset)
{
nsMutationGuard guard;
nsCOMPtr<nsIDOMCharacterData> cutNode;
rv = SplitDataNode(charData, startOffset, getter_AddRefs(cutNode));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(!guard.Mutated(1) ||
ValidateCurrentNode(this, iter));
nodeToResult = cutNode;
}
@ -1603,6 +1624,7 @@ nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
if (endOffset >= 0)
{
nsMutationGuard guard;
nsCOMPtr<nsIDOMCharacterData> cutNode;
/* The Range spec clearly states clones get cut and original nodes
remain behind, so use false as the last parameter.
@ -1610,6 +1632,8 @@ nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
rv = SplitDataNode(charData, endOffset, getter_AddRefs(cutNode),
false);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(!guard.Mutated(1) ||
ValidateCurrentNode(this, iter));
nodeToResult = cutNode;
}
@ -1681,12 +1705,20 @@ nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
NS_ENSURE_SUCCESS(rv, rv);
}
nsMutationGuard guard;
nsCOMPtr<nsIDOMNode> parent;
nodeToResult->GetParentNode(getter_AddRefs(parent));
rv = closestAncestor ? PrependChild(closestAncestor, nodeToResult)
: PrependChild(commonCloneAncestor, nodeToResult);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(!guard.Mutated(parent ? 2 : 1) ||
ValidateCurrentNode(this, iter));
} else if (nodeToResult) {
nsMutationGuard guard;
rv = RemoveNode(nodeToResult);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(!guard.Mutated(1) ||
ValidateCurrentNode(this, iter));
}
if (!iter.IsDone() && retval) {

Просмотреть файл

@ -4954,11 +4954,16 @@ WebGLContext::CompileShader(WebGLShader *shader)
compileOptions |= SH_OBJECT_CODE
| SH_MAP_LONG_VARIABLE_NAMES;
#ifdef XP_MACOSX
// work around bug 665578 and bug 769810
if (gl->WorkAroundDriverBugs() &&
gl->Vendor() == gl::GLContext::VendorATI)
{
compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
if (gl->WorkAroundDriverBugs()) {
// Work around bug 665578 and bug 769810
if (gl->Vendor() == gl::GLContext::VendorATI) {
compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
}
// Work around bug 735560
if (gl->Vendor() == gl::GLContext::VendorIntel) {
compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
}
}
#endif
}

Просмотреть файл

@ -424,10 +424,10 @@ static const nsModifierPair kPairs[] = {
{ widget::MODIFIER_FN, NS_DOM_KEYNAME_FN },
{ widget::MODIFIER_META, NS_DOM_KEYNAME_META },
{ widget::MODIFIER_NUMLOCK, NS_DOM_KEYNAME_NUMLOCK },
{ widget::MODIFIER_SCROLL, NS_DOM_KEYNAME_SCROLL },
{ widget::MODIFIER_SCROLLLOCK, NS_DOM_KEYNAME_SCROLLLOCK },
{ widget::MODIFIER_SHIFT, NS_DOM_KEYNAME_SHIFT },
{ widget::MODIFIER_SYMBOLLOCK, NS_DOM_KEYNAME_SYMBOLLOCK },
{ widget::MODIFIER_WIN, NS_DOM_KEYNAME_WIN }
{ widget::MODIFIER_OS, NS_DOM_KEYNAME_OS }
};
/* static */
@ -484,8 +484,8 @@ nsDOMUIEvent::GetModifierStateInternal(const nsAString& aKey)
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_ALTGRAPH)) {
return inputEvent->IsAltGraph();
}
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_WIN)) {
return inputEvent->IsWin();
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_OS)) {
return inputEvent->IsOS();
}
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_CAPSLOCK)) {
@ -498,7 +498,7 @@ nsDOMUIEvent::GetModifierStateInternal(const nsAString& aKey)
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_FN)) {
return inputEvent->IsFn();
}
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SCROLL)) {
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SCROLLLOCK)) {
return inputEvent->IsScrollLocked();
}
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SYMBOLLOCK)) {

Просмотреть файл

@ -72,12 +72,13 @@ function testInitializingUntrustedEvent()
];
const kOtherModifierName = [
"CapsLock", "NumLock", "Scroll", "SymbolLock", "Fn", "Win", "AltGraph"
"CapsLock", "NumLock", "ScrollLock", "SymbolLock", "Fn", "OS", "AltGraph"
];
const kInvalidModifierName = [
"shift", "control", "alt", "meta", "capslock", "numlock", "scroll",
"symbollock", "fn", "win", "altgraph", "Invalid", "Shift Control"
"shift", "control", "alt", "meta", "capslock", "numlock", "scrolllock",
"symbollock", "fn", "os", "altgraph", "Invalid", "Shift Control",
"Win", "Scroll"
];
for (var i = 0; i < kTests.length; i++) {

Просмотреть файл

@ -81,12 +81,13 @@ function testInitializingUntrustedEvent()
];
const kOtherModifierName = [
"CapsLock", "NumLock", "Scroll", "SymbolLock", "Fn", "Win", "AltGraph"
"CapsLock", "NumLock", "ScrollLock", "SymbolLock", "Fn", "OS", "AltGraph"
];
const kInvalidModifierName = [
"shift", "control", "alt", "meta", "capslock", "numlock", "scroll",
"symbollock", "fn", "win", "altgraph", "Invalid", "Shift Control"
"shift", "control", "alt", "meta", "capslock", "numlock", "scrolllock",
"symbollock", "fn", "os", "altgraph", "Invalid", "Shift Control",
"Win", "Scroll"
];
for (var i = 0; i < kTests.length; i++) {

Просмотреть файл

@ -121,6 +121,7 @@ INCLUDES += \
-I$(srcdir)/../../../../dom/base \
-I$(srcdir)/../../../../editor/libeditor/base \
-I$(srcdir)/../../../../editor/libeditor/text \
-I$(srcdir)/../../../../editor/txmgr/src \
-I$(srcdir) \
-I$(topsrcdir)/xpcom/ds \
$(NULL)

Просмотреть файл

@ -459,14 +459,14 @@ nsDOMWindowUtils::GetWidgetModifiers(PRInt32 aModifiers)
if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) {
result |= widget::MODIFIER_NUMLOCK;
}
if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLL) {
result |= widget::MODIFIER_SCROLL;
if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) {
result |= widget::MODIFIER_SCROLLLOCK;
}
if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) {
result |= widget::MODIFIER_SYMBOLLOCK;
}
if (aModifiers & nsIDOMWindowUtils::MODIFIER_WIN) {
result |= widget::MODIFIER_WIN;
if (aModifiers & nsIDOMWindowUtils::MODIFIER_OS) {
result |= widget::MODIFIER_OS;
}
return result;
}

Просмотреть файл

@ -8545,8 +8545,8 @@ nsGlobalWindow::ScheduleNextIdleObserverCallback()
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 callbackTimeMS = 0;
if (idleObserver.mTimeInS * 1000 > userIdleTimeMS) {
callbackTimeMS = idleObserver.mTimeInS * 1000 - userIdleTimeMS;
if (idleObserver.mTimeInS * 1000 + mIdleFuzzFactor > userIdleTimeMS) {
callbackTimeMS = idleObserver.mTimeInS * 1000 - userIdleTimeMS + mIdleFuzzFactor;
}
mIdleTimer->Cancel();
@ -8568,7 +8568,7 @@ nsGlobalWindow::GetFuzzTimeMS()
return 0;
}
PRUint32 randNum = 0;
PRUint32 randNum = MAX_IDLE_FUZZ_TIME_MS;
PRSize nbytes = PR_GetRandomNoise(&randNum, sizeof(randNum));
if (nbytes != sizeof(randNum)) {
NS_WARNING("PR_GetRandomNoise(...) Not implemented or no available noise!");
@ -8605,23 +8605,6 @@ nsGlobalWindow::ScheduleActiveTimerCallback()
return NS_OK;
}
nsresult
nsGlobalWindow::ScheduleIdleTimerCallback()
{
MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
MOZ_ASSERT(mIdleTimer);
nsRefPtr<nsGlobalWindow> kungFuDeathGrip(this);
mIdleTimer->Cancel();
mIdleFuzzFactor = GetFuzzTimeMS();
nsresult rv = mIdleTimer->InitWithFuncCallback(IdleActiveTimerCallback,
this,
mIdleFuzzFactor,
nsITimer::TYPE_ONE_SHOT);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
nsGlobalWindow::NotifyIdleObserversOfIdleActiveEvent()
{
@ -8629,12 +8612,15 @@ nsGlobalWindow::NotifyIdleObserversOfIdleActiveEvent()
if (mCurrentlyIdle) {
mIdleCallbackIndex = 0;
mIdleFuzzFactor = GetFuzzTimeMS();
nsresult rv = ScheduleNextIdleObserverCallback();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
mIdleCallbackIndex = -1;
MOZ_ASSERT(mIdleTimer);
mIdleTimer->Cancel();
nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
while (iter.HasMore()) {
IdleObserverHolder& idleObserver = iter.GetNext();
@ -8682,8 +8668,6 @@ nsGlobalWindow::RegisterIdleObserver(nsIIdleObserver* aIdleObserver)
} else {
mIdleTimer->Cancel();
}
mIdleFuzzFactor = GetFuzzTimeMS();
}
MOZ_ASSERT(mIdleService);
@ -8730,20 +8714,7 @@ nsGlobalWindow::RegisterIdleObserver(nsIIdleObserver* aIdleObserver)
}
if (static_cast<PRInt32>(insertAtIndex) == mIdleCallbackIndex) {
PRUint32 userIdleTimeMS;
rv = mIdleService->GetIdleTime(&userIdleTimeMS);
NS_ENSURE_SUCCESS(rv, rv);
if (tmpIdleObserver.mTimeInS*1000 <= userIdleTimeMS) {
NotifyIdleObserver(tmpIdleObserver.mIdleObserver,
tmpIdleObserver.mTimeInS,
true);
mIdleCallbackIndex++;
return NS_OK;
}
mIdleTimer->Cancel();
rv = ScheduleNextIdleObserverCallback();
NS_ENSURE_SUCCESS(rv, rv);
}
@ -8860,7 +8831,7 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
mNotifyIdleObserversIdleOnThaw = true;
mNotifyIdleObserversActiveOnThaw = false;
} else if (mOuterWindow && mOuterWindow->GetCurrentInnerWindow() == this) {
ScheduleIdleTimerCallback();
NotifyIdleObserversOfIdleActiveEvent();
}
return NS_OK;
}
@ -9046,7 +9017,7 @@ nsGlobalWindow::FireDelayedDOMEvents()
if (mNotifyIdleObserversIdleOnThaw) {
mNotifyIdleObserversIdleOnThaw = false;
ScheduleIdleTimerCallback();
NotifyIdleObserversOfIdleActiveEvent();
}
if (mNotifyIdleObserversActiveOnThaw) {

Просмотреть файл

@ -769,7 +769,6 @@ protected:
nsresult ScheduleNextIdleObserverCallback();
PRUint32 GetFuzzTimeMS();
nsresult ScheduleActiveTimerCallback();
nsresult ScheduleIdleTimerCallback();
PRUint32 FindInsertionIndex(IdleObserverHolder* aIdleObserver);
virtual nsresult RegisterIdleObserver(nsIIdleObserver* aIdleObserverPtr);
nsresult FindIndexOfElementToRemove(nsIIdleObserver* aIdleObserver,

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/Preferences.h"
#include "nsNetCID.h"
#include "nsPrintfCString.h"
#include "XPCJSMemoryReporter.h"
using namespace mozilla;
@ -101,10 +102,14 @@ AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr)
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows")
// The key is the window ID.
typedef nsDataHashtable<nsUint64HashKey, nsCString> WindowPaths;
static nsresult
CollectWindowReports(nsGlobalWindow *aWindow,
nsWindowSizes *aWindowTotalSizes,
nsTHashtable<nsUint64HashKey> *aGhostWindowIDs,
WindowPaths *aWindowPaths,
nsIMemoryMultiReporterCallback *aCb,
nsISupports *aClosure)
{
@ -140,6 +145,9 @@ CollectWindowReports(nsGlobalWindow *aWindow,
AppendWindowURI(aWindow, windowPath);
windowPath += NS_LITERAL_CSTRING(")");
// Remember the path for later.
aWindowPaths->Put(aWindow->WindowID(), windowPath);
#define REPORT(_pathTail, _amount, _desc) \
do { \
if (_amount > 0) { \
@ -294,14 +302,23 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
NS_EFFECTIVETLDSERVICE_CONTRACTID);
NS_ENSURE_STATE(tldService);
WindowPaths windowPaths;
windowPaths.Init();
// Collect window memory usage.
nsWindowSizes windowTotalSizes(NULL);
for (PRUint32 i = 0; i < windows.Length(); i++) {
nsresult rv = CollectWindowReports(windows[i], &windowTotalSizes,
&ghostWindows, aCb, aClosure);
&ghostWindows, &windowPaths,
aCb, aClosure);
NS_ENSURE_SUCCESS(rv, rv);
}
// Report JS memory usage. We do this from here because the JS memory
// multi-reporter needs to be passed |windowPaths|.
nsresult rv = xpc::JSMemoryMultiReporter::CollectReports(&windowPaths, aCb, aClosure);
NS_ENSURE_SUCCESS(rv, rv);
#define REPORT(_path, _amount, _desc) \
do { \
nsresult rv; \
@ -392,9 +409,9 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
NS_IMETHODIMP
nsWindowMemoryReporter::GetExplicitNonHeap(PRInt64* aAmount)
{
// This reporter only measures heap memory.
*aAmount = 0;
return NS_OK;
// This reporter only measures heap memory, so we don't need to report any
// bytes for it. However, the JS multi-reporter needs to be invoked.
return xpc::JSMemoryMultiReporter::GetExplicitNonHeap(aAmount);
}
PRUint32

Просмотреть файл

@ -182,9 +182,9 @@ interface nsIDOMWindowUtils : nsISupports {
const long MODIFIER_CAPSLOCK = 0x0020;
const long MODIFIER_FN = 0x0040;
const long MODIFIER_NUMLOCK = 0x0080;
const long MODIFIER_SCROLL = 0x0100;
const long MODIFIER_SCROLLLOCK = 0x0100;
const long MODIFIER_SYMBOLLOCK = 0x0200;
const long MODIFIER_WIN = 0x0400;
const long MODIFIER_OS = 0x0400;
/** Synthesize a mouse event. The event types supported are:
* mousedown, mouseup, mousemove, mouseover, mouseout, contextmenu

Просмотреть файл

@ -25,3 +25,10 @@ tab = tab
# The Role Description for definition list dl, dt and dd
term = term
definition = definition
# The Role Description for WAI-ARIA Landmarks
search = search
banner = banner
navigation = navigation
complementary = complementary
content = content
main = main

Просмотреть файл

@ -1274,12 +1274,7 @@ PluginModuleParent::OnCrash(DWORD processID, const nsAString& aDumpID)
NS_ERROR("Got minidump for Flash process neither broker nor sandbox.");
}
CrashReporter::AppendExtraData(aDumpID, notes);
MessageLoop::current()->PostTask(
FROM_HERE,
mTaskFactory.NewRunnableMethod(
&PluginModuleParent::CleanupFromTimeout));
GetIPCChannel()->CloseWithError();
KillProcess(OtherProcess(), 1, false);
}

Просмотреть файл

@ -46,23 +46,26 @@ function test() {
worker = new ChromeWorker("worker_constants.js");
SimpleTest.waitForExplicitFinish();
ok(true, "test_constants.xul: Chrome worker created");
worker.onerror = function(error) {
worker.onerror = function onerror(error) {
error.preventDefault();
ok(false, "error "+error);
ok(false, "error " + error);
}
worker.onmessage = function(msg) {
worker.onmessage = function onmessage(msg) {
switch (msg.data.kind) {
case "is":
return SimpleTest.is(msg.data.a, msg.data.b, msg.data.description);
SimpleTest.is(msg.data.a, msg.data.b, msg.data.description);
return;
case "isnot":
return SimpleTest.isnot(msg.data.a, msg.data.b, msg.data.description);
SimpleTest.isnot(msg.data.a, msg.data.b, msg.data.description);
return;
case "ok":
return SimpleTest.ok(msg.data.condition, msg.data.description);
SimpleTest.ok(msg.data.condition, msg.data.description);
return;
case "finish":
SimpleTest.finish();
return;
default:
SimpleTest.ok(false, "test_constants.xul: wrong message "+JSON.stringify(msg.data));
SimpleTest.ok(false, "test_constants.xul: wrong message " + JSON.stringify(msg.data));
return;
}
};

Просмотреть файл

@ -133,11 +133,19 @@ struct WorkerJSRuntimeStats : public JS::RuntimeStats
virtual void initExtraCompartmentStats(JSCompartment *c,
JS::CompartmentStats *cstats) MOZ_OVERRIDE
{
MOZ_ASSERT(!cstats->extra);
MOZ_ASSERT(!cstats->extra1);
MOZ_ASSERT(!cstats->extra2);
// ReportJSRuntimeExplicitTreeStats expects that cstats->extra is a char pointer
const char *name = js::IsAtomsCompartment(c) ? "Web Worker Atoms" : "Web Worker";
cstats->extra = const_cast<char *>(name);
// ReportJSRuntimeExplicitTreeStats expects that cstats->{extra1,extra2}
// are char pointers.
// This is the |cPathPrefix|. Using NULL here means that we'll end up
// using WorkerMemoryReporter::mRtPath as the path prefix for each
// compartment. See xpc::ReportJSRuntimeExplicitTreeStats().
cstats->extra1 = NULL;
// This is the |cName|.
cstats->extra2 = (void *)(js::IsAtomsCompartment(c) ? "Web Worker Atoms" : "Web Worker");
}
};
@ -145,7 +153,7 @@ class WorkerMemoryReporter MOZ_FINAL : public nsIMemoryMultiReporter
{
WorkerPrivate* mWorkerPrivate;
nsCString mAddressString;
nsCString mPathPrefix;
nsCString mRtPath;
public:
NS_DECL_ISUPPORTS
@ -175,10 +183,10 @@ public:
}
}
mPathPrefix = NS_LITERAL_CSTRING("explicit/dom/workers(") +
escapedDomain + NS_LITERAL_CSTRING(")/worker(") +
escapedURL + NS_LITERAL_CSTRING(", ") + mAddressString +
NS_LITERAL_CSTRING(")/");
mRtPath = NS_LITERAL_CSTRING("explicit/workers/workers(") +
escapedDomain + NS_LITERAL_CSTRING(")/worker(") +
escapedURL + NS_LITERAL_CSTRING(", ") + mAddressString +
NS_LITERAL_CSTRING(")/");
}
nsresult
@ -232,7 +240,7 @@ public:
// Always report, even if we're disabled, so that we at least get an entry
// in about::memory.
return xpc::ReportJSRuntimeExplicitTreeStats(rtStats, mPathPrefix,
return xpc::ReportJSRuntimeExplicitTreeStats(rtStats, mRtPath,
aCallback, aClosure);
}

Просмотреть файл

@ -40,7 +40,7 @@ DeleteTextTxn::Init(nsEditor* aEditor,
PRUint32 aNumCharsToDelete,
nsRangeUpdater* aRangeUpdater)
{
MOZ_ASSERT(aEditor && aCharData && aNumCharsToDelete);
MOZ_ASSERT(aEditor && aCharData);
mEditor = aEditor;
mCharData = aCharData;

Просмотреть файл

@ -58,6 +58,7 @@ include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(topsrcdir)/editor/libeditor/text \
-I$(topsrcdir)/editor/txmgr/src \
-I$(topsrcdir)/content/base/src \
-I$(topsrcdir)/content/events/src \
-I$(topsrcdir)/layout/style \

Просмотреть файл

@ -165,7 +165,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEditor)
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRootElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInlineSpellChecker)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTxnMgr)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTxnMgr, nsITransactionManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mIMETextRangeList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mIMETextNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mActionListeners)
@ -613,61 +613,52 @@ nsEditor::GetSelection()
return frameSel->GetSelection(nsISelectionController::SELECTION_NORMAL);
}
NS_IMETHODIMP
nsEditor::DoTransaction(nsITransaction *aTxn)
NS_IMETHODIMP
nsEditor::DoTransaction(nsITransaction* aTxn)
{
#ifdef NS_DEBUG_EDITOR
if (gNoisy) { printf("Editor::DoTransaction ----------\n"); }
#endif
if (mPlaceHolderBatch && !mPlaceHolderTxn) {
// it's pretty darn amazing how many different types of pointers this
// transaction goes through here. I bet this is a record.
nsresult result = NS_OK;
if (mPlaceHolderBatch && !mPlaceHolderTxn)
{
// it's pretty darn amazing how many different types of pointers
// this transaction goes through here. I bet this is a record.
// We start off with an EditTxn since that's what the factory returns.
nsRefPtr<EditTxn> editTxn = new PlaceholderTxn();
if (!editTxn) { return NS_ERROR_OUT_OF_MEMORY; }
// Then we QI to an nsIAbsorbingTransaction to get at placeholder functionality
// Then we QI to an nsIAbsorbingTransaction to get at placeholder
// functionality
nsCOMPtr<nsIAbsorbingTransaction> plcTxn;
editTxn->QueryInterface(NS_GET_IID(nsIAbsorbingTransaction), getter_AddRefs(plcTxn));
editTxn->QueryInterface(NS_GET_IID(nsIAbsorbingTransaction),
getter_AddRefs(plcTxn));
// have to use line above instead of "plcTxn = do_QueryInterface(editTxn);"
// due to our broken interface model for transactions.
// save off weak reference to placeholder txn
mPlaceHolderTxn = do_GetWeakReference(plcTxn);
plcTxn->Init(mPlaceHolderName, mSelState, this);
mSelState = nsnull; // placeholder txn took ownership of this pointer
// placeholder txn took ownership of this pointer
mSelState = nsnull;
// finally we QI to an nsITransaction since that's what DoTransaction() expects
// finally we QI to an nsITransaction since that's what DoTransaction()
// expects
nsCOMPtr<nsITransaction> theTxn = do_QueryInterface(plcTxn);
DoTransaction(theTxn); // we will recurse, but will not hit this case in the nested call
// we will recurse, but will not hit this case in the nested call
DoTransaction(theTxn);
if (mTxnMgr)
{
nsCOMPtr<nsITransaction> topTxn;
result = mTxnMgr->PeekUndoStack(getter_AddRefs(topTxn));
NS_ENSURE_SUCCESS(result, result);
if (topTxn)
{
if (mTxnMgr) {
nsCOMPtr<nsITransaction> topTxn = mTxnMgr->PeekUndoStack();
if (topTxn) {
plcTxn = do_QueryInterface(topTxn);
if (plcTxn)
{
// there is a palceholder transaction on top of the undo stack. It is
// either the one we just created, or an earlier one that we are now merging
// into. From here on out remember this placeholder instead of the one
// we just created.
if (plcTxn) {
// there is a placeholder transaction on top of the undo stack. It
// is either the one we just created, or an earlier one that we are
// now merging into. From here on out remember this placeholder
// instead of the one we just created.
mPlaceHolderTxn = do_GetWeakReference(plcTxn);
}
}
}
}
if (aTxn)
{
if (aTxn) {
// XXX: Why are we doing selection specific batching stuff here?
// XXX: Most entry points into the editor have auto variables that
// XXX: should trigger Begin/EndUpdateViewBatch() calls that will make
@ -688,56 +679,42 @@ nsEditor::DoTransaction(nsITransaction *aTxn)
// XXX: re-entry during initial reflow. - kin
// get the selection and start a batch change
nsCOMPtr<nsISelection>selection;
result = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(result, result);
nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsISelectionPrivate>selPrivate(do_QueryInterface(selection));
selPrivate->StartBatchChanges();
selection->StartBatchChanges();
nsresult res;
if (mTxnMgr) {
result = mTxnMgr->DoTransaction(aTxn);
res = mTxnMgr->DoTransaction(aTxn);
} else {
res = aTxn->DoTransaction();
}
else {
result = aTxn->DoTransaction();
}
if (NS_SUCCEEDED(result)) {
result = DoAfterDoTransaction(aTxn);
if (NS_SUCCEEDED(res)) {
DoAfterDoTransaction(aTxn);
}
selPrivate->EndBatchChanges(); // no need to check result here, don't lose result of operation
// no need to check res here, don't lose result of operation
selection->EndBatchChanges();
NS_ENSURE_SUCCESS(res, res);
}
NS_ENSURE_SUCCESS(result, result);
return result;
return NS_OK;
}
NS_IMETHODIMP
nsEditor::EnableUndo(bool aEnable)
{
nsresult result=NS_OK;
if (true==aEnable)
{
if (!mTxnMgr)
{
mTxnMgr = do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
if (NS_FAILED(result) || !mTxnMgr) {
return NS_ERROR_NOT_AVAILABLE;
}
}
mTxnMgr->SetMaxTransactionCount(-1);
}
else
{ // disable the transaction manager if it is enabled
if (mTxnMgr)
{
mTxnMgr->Clear();
mTxnMgr->SetMaxTransactionCount(0);
if (aEnable) {
if (!mTxnMgr) {
mTxnMgr = new nsTransactionManager();
}
} else if (mTxnMgr) {
// disable the transaction manager if it is enabled
mTxnMgr->Clear();
mTxnMgr->SetMaxTransactionCount(0);
}
return NS_OK;
@ -774,7 +751,8 @@ nsEditor::SetTransactionManager(nsITransactionManager *aTxnManager)
{
NS_ENSURE_TRUE(aTxnManager, NS_ERROR_FAILURE);
mTxnMgr = aTxnManager;
// nsITransactionManager is builtinclass, so this is safe
mTxnMgr = static_cast<nsTransactionManager*>(aTxnManager);
return NS_OK;
}
@ -801,8 +779,7 @@ nsEditor::Undo(PRUint32 aCount)
nsresult rv = mTxnMgr->UndoTransaction();
NS_ENSURE_SUCCESS(rv, rv);
rv = DoAfterUndoTransaction();
NS_ENSURE_SUCCESS(rv, rv);
DoAfterUndoTransaction();
}
return NS_OK;
@ -845,8 +822,7 @@ nsEditor::Redo(PRUint32 aCount)
nsresult rv = mTxnMgr->RedoTransaction();
NS_ENSURE_SUCCESS(rv, rv);
rv = DoAfterRedoTransaction();
NS_ENSURE_SUCCESS(rv, rv);
DoAfterRedoTransaction();
}
return NS_OK;
@ -2019,22 +1995,18 @@ nsEditor::BeginIMEComposition()
return NS_OK;
}
nsresult
void
nsEditor::EndIMEComposition()
{
NS_ENSURE_TRUE(mInIMEMode, NS_OK); // nothing to do
nsresult rv = NS_OK;
NS_ENSURE_TRUE(mInIMEMode, ); // nothing to do
// commit the IME transaction..we can get at it via the transaction mgr.
// Note that this means IME won't work without an undo stack!
if (mTxnMgr) {
nsCOMPtr<nsITransaction> txn;
rv = mTxnMgr->PeekUndoStack(getter_AddRefs(txn));
NS_ASSERTION(NS_SUCCEEDED(rv), "PeekUndoStack() failed");
nsCOMPtr<nsITransaction> txn = mTxnMgr->PeekUndoStack();
nsCOMPtr<nsIAbsorbingTransaction> plcTxn = do_QueryInterface(txn);
if (plcTxn) {
rv = plcTxn->Commit();
DebugOnly<nsresult> rv = plcTxn->Commit();
NS_ASSERTION(NS_SUCCEEDED(rv),
"nsIAbsorbingTransaction::Commit() failed");
}
@ -2049,8 +2021,6 @@ nsEditor::EndIMEComposition()
// notify editor observers of action
NotifyEditorObservers();
return rv;
}
@ -4479,14 +4449,12 @@ nsEditor::DeleteSelectionAndPrepareToCreateNode()
NS_IMETHODIMP
void
nsEditor::DoAfterDoTransaction(nsITransaction *aTxn)
{
nsresult rv = NS_OK;
bool isTransientTransaction;
rv = aTxn->GetIsTransient(&isTransientTransaction);
NS_ENSURE_SUCCESS(rv, rv);
bool isTransientTransaction;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
aTxn->GetIsTransient(&isTransientTransaction)));
if (!isTransientTransaction)
{
@ -4499,27 +4467,27 @@ nsEditor::DoAfterDoTransaction(nsITransaction *aTxn)
if (modCount < 0)
modCount = -modCount;
rv = IncrementModificationCount(1); // don't count transient transactions
// don't count transient transactions
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
IncrementModificationCount(1)));
}
return rv;
}
NS_IMETHODIMP
void
nsEditor::DoAfterUndoTransaction()
{
nsresult rv = NS_OK;
rv = IncrementModificationCount(-1); // all undoable transactions are non-transient
return rv;
// all undoable transactions are non-transient
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
IncrementModificationCount(-1)));
}
NS_IMETHODIMP
void
nsEditor::DoAfterRedoTransaction()
{
return IncrementModificationCount(1); // all redoable transactions are non-transient
// all redoable transactions are non-transient
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
IncrementModificationCount(1)));
}
NS_IMETHODIMP

Просмотреть файл

@ -19,7 +19,7 @@
#include "mozilla/Selection.h"
#include "nsIDOMCharacterData.h"
#include "nsIPrivateTextRange.h"
#include "nsITransactionManager.h"
#include "nsTransactionManager.h"
#include "nsIComponentManager.h"
#include "nsCOMArray.h"
#include "nsIEditActionListener.h"
@ -218,7 +218,7 @@ public:
virtual nsresult BeginIMEComposition();
virtual nsresult UpdateIMEComposition(const nsAString &aCompositionString,
nsIPrivateTextRangeList *aTextRange)=0;
nsresult EndIMEComposition();
void EndIMEComposition();
void SwitchTextDirectionTo(PRUint32 aDirection);
@ -325,11 +325,11 @@ protected:
// called after a transaction is done successfully
NS_IMETHOD DoAfterDoTransaction(nsITransaction *aTxn);
void DoAfterDoTransaction(nsITransaction *aTxn);
// called after a transaction is undone successfully
NS_IMETHOD DoAfterUndoTransaction();
void DoAfterUndoTransaction();
// called after a transaction is redone successfully
NS_IMETHOD DoAfterRedoTransaction();
void DoAfterRedoTransaction();
typedef enum {
eDocumentCreated,
@ -821,7 +821,7 @@ protected:
nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker;
nsCOMPtr<nsITransactionManager> mTxnMgr;
nsRefPtr<nsTransactionManager> mTxnMgr;
nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
nsCOMPtr<nsIPrivateTextRangeList> mIMETextRangeList; // IME special selection ranges
nsCOMPtr<nsIDOMCharacterData> mIMETextNode; // current IME text node

Просмотреть файл

@ -307,8 +307,10 @@ nsEditorEventListener::HandleEvent(nsIDOMEvent* aEvent)
return HandleText(aEvent);
if (eventType.EqualsLiteral("compositionstart"))
return HandleStartComposition(aEvent);
if (eventType.EqualsLiteral("compositionend"))
return HandleEndComposition(aEvent);
if (eventType.EqualsLiteral("compositionend")) {
HandleEndComposition(aEvent);
return NS_OK;
}
return NS_OK;
}
@ -822,19 +824,19 @@ nsEditorEventListener::HandleStartComposition(nsIDOMEvent* aCompositionEvent)
return mEditor->BeginIMEComposition();
}
NS_IMETHODIMP
void
nsEditorEventListener::HandleEndComposition(nsIDOMEvent* aCompositionEvent)
{
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
MOZ_ASSERT(mEditor);
if (!mEditor->IsAcceptableInputEvent(aCompositionEvent)) {
return NS_OK;
return;
}
// Transfer the event's trusted-ness to our editor
nsCOMPtr<nsIDOMNSEvent> NSEvent = do_QueryInterface(aCompositionEvent);
nsEditor::HandlingTrustedAction operation(mEditor, NSEvent);
return mEditor->EndIMEComposition();
mEditor->EndIMEComposition();
}
NS_IMETHODIMP

Просмотреть файл

@ -46,7 +46,7 @@ public:
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
NS_IMETHOD HandleText(nsIDOMEvent* aTextEvent);
NS_IMETHOD HandleStartComposition(nsIDOMEvent* aCompositionEvent);
NS_IMETHOD HandleEndComposition(nsIDOMEvent* aCompositionEvent);
void HandleEndComposition(nsIDOMEvent* aCompositionEvent);
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; }
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);

Просмотреть файл

@ -55,5 +55,6 @@ include $(topsrcdir)/config/rules.mk
INCLUDES += -I$(topsrcdir)/editor/libeditor/base \
-I$(topsrcdir)/editor/libeditor/text \
-I$(topsrcdir)/editor/txmgr/src \
-I$(topsrcdir)/content/base/src \
$(NULL)

Просмотреть файл

@ -0,0 +1,16 @@
<html xmlns="http://www.w3.org/1999/xhtml" contenteditable="true" style="-moz-user-select: all;"><sub>x</sub><script>
function boom()
{
window.getSelection().removeAllRanges();
var r = document.createRange();
r.setStart(document.documentElement, 0);
r.setEnd(document.documentElement, 0);
window.getSelection().addRange(r);
document.execCommand("subscript", false, null);
document.execCommand("insertText", false, "y");
}
window.addEventListener("load", boom, false);
</script></html>

Просмотреть файл

@ -33,4 +33,5 @@ load 766305.html
load 766387.html
load 766795.html
load 767169.html
load 769967.xhtml
load 768748.html

Просмотреть файл

@ -3223,12 +3223,6 @@ nsHTMLEditor::DeleteNode(nsIDOMNode* aNode)
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMNode> selectAllNode = FindUserSelectAllNode(aNode);
if (selectAllNode)
{
return nsEditor::DeleteNode(selectAllNode);
}
return nsEditor::DeleteNode(aNode);
}
@ -3241,12 +3235,6 @@ NS_IMETHODIMP nsHTMLEditor::DeleteText(nsIDOMCharacterData *aTextNode,
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMNode> selectAllNode = FindUserSelectAllNode(aTextNode);
if (selectAllNode)
{
return nsEditor::DeleteNode(selectAllNode);
}
return nsEditor::DeleteText(aTextNode, aOffset, aLength);
}
@ -3324,42 +3312,6 @@ nsHTMLEditor::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
}
}
/* This routine examines aNode and its ancestors looking for any node which has the
-moz-user-select: all style lit. Return the highest such ancestor. */
already_AddRefed<nsIDOMNode>
nsHTMLEditor::FindUserSelectAllNode(nsIDOMNode* aNode)
{
nsCOMPtr<nsIDOMNode> node = aNode;
nsCOMPtr<nsIDOMElement> root = do_QueryInterface(GetRoot());
if (!nsEditorUtils::IsDescendantOf(aNode, root))
return nsnull;
nsCOMPtr<nsIDOMNode> resultNode; // starts out empty
nsAutoString mozUserSelectValue;
while (node)
{
// retrieve the computed style of -moz-user-select for node
mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssMozUserSelect, mozUserSelectValue);
if (mozUserSelectValue.EqualsLiteral("all"))
{
resultNode = node;
}
if (node != root)
{
nsCOMPtr<nsIDOMNode> tmp;
node->GetParentNode(getter_AddRefs(tmp));
node = tmp;
}
else
{
node = nsnull;
}
}
return resultNode.forget();
}
NS_IMETHODIMP_(bool)
nsHTMLEditor::IsModifiableNode(nsIDOMNode *aNode)
{

Просмотреть файл

@ -331,7 +331,6 @@ public:
nsCOMPtr<nsIDOMNode> *ioParent,
PRInt32 *ioOffset,
bool aNoEmptyNodes);
virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode);
// Use this to assure that selection is set after attribute nodes when
// trying to collapse selection at begining of a block node

Просмотреть файл

@ -34,5 +34,6 @@ include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(topsrcdir)/editor/libeditor/base \
-I$(topsrcdir)/editor/txmgr/src \
-I$(topsrcdir)/content/base/src \
$(NULL)

Просмотреть файл

@ -1183,7 +1183,7 @@ nsPlaintextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,
nsresult rv = NS_OK;
nsCAutoString formatType(NS_DOC_ENCODER_CONTRACTID_BASE);
formatType.AppendWithConversion(aFormatType);
LossyAppendUTF16toASCII(aFormatType, formatType);
nsCOMPtr<nsIDocumentEncoder> docEncoder (do_CreateInstance(formatType.get(), &rv));
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -20,7 +20,7 @@
* This interface is implemented by an object that wants to
* manage/track transactions.
*/
[scriptable, uuid(58e330c2-7b48-11d2-98b9-00805f297d89)]
[scriptable, builtinclass, uuid(58e330c2-7b48-11d2-98b9-00805f297d89)]
interface nsITransactionManager : nsISupports
{
/**

Просмотреть файл

@ -82,14 +82,11 @@ nsTransactionItem::AddChild(nsTransactionItem *aTransactionItem)
return NS_OK;
}
nsresult
nsTransactionItem::GetTransaction(nsITransaction **aTransaction)
already_AddRefed<nsITransaction>
nsTransactionItem::GetTransaction()
{
NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
NS_IF_ADDREF(*aTransaction = mTransaction);
return NS_OK;
nsCOMPtr<nsITransaction> txn = mTransaction;
return txn.forget();
}
nsresult
@ -227,13 +224,7 @@ nsTransactionItem::UndoChildren(nsTransactionManager *aTxMgr)
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsITransaction> t;
result = item->GetTransaction(getter_AddRefs(t));
if (NS_FAILED(result)) {
return result;
}
nsCOMPtr<nsITransaction> t = item->GetTransaction();
bool doInterrupt = false;
@ -306,13 +297,7 @@ nsTransactionItem::RedoChildren(nsTransactionManager *aTxMgr)
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsITransaction> t;
result = item->GetTransaction(getter_AddRefs(t));
if (NS_FAILED(result)) {
return result;
}
nsCOMPtr<nsITransaction> t = item->GetTransaction();
bool doInterrupt = false;

Просмотреть файл

@ -30,7 +30,7 @@ public:
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsTransactionItem)
virtual nsresult AddChild(nsTransactionItem *aTransactionItem);
virtual nsresult GetTransaction(nsITransaction **aTransaction);
already_AddRefed<nsITransaction> GetTransaction();
virtual nsresult GetIsBatch(bool *aIsBatch);
virtual nsresult GetNumberOfChildren(PRInt32 *aNumChildren);
virtual nsresult GetChild(PRInt32 aIndex, nsTransactionItem **aChild);

Просмотреть файл

@ -104,7 +104,9 @@ NS_IMETHODIMP nsTransactionList::GetItem(PRInt32 aIndex, nsITransaction **aItem)
NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
return item->GetTransaction(aItem);
*aItem = item->GetTransaction().get();
return NS_OK;
}
/* long getNumChildrenForItem (in long aIndex); */

Просмотреть файл

@ -13,6 +13,7 @@
#include "nsTransactionList.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "mozilla/Assertions.h"
nsTransactionManager::nsTransactionManager(PRInt32 aMaxTransactionCount)
: mMaxTransactionCount(aMaxTransactionCount)
@ -111,13 +112,7 @@ nsTransactionManager::UndoTransaction()
return NS_OK;
}
nsCOMPtr<nsITransaction> t;
result = tx->GetTransaction(getter_AddRefs(t));
if (NS_FAILED(result)) {
return result;
}
nsCOMPtr<nsITransaction> t = tx->GetTransaction();
bool doInterrupt = false;
@ -170,13 +165,7 @@ nsTransactionManager::RedoTransaction()
return NS_OK;
}
nsCOMPtr<nsITransaction> t;
result = tx->GetTransaction(getter_AddRefs(t));
if (NS_FAILED(result)) {
return result;
}
nsCOMPtr<nsITransaction> t = tx->GetTransaction();
bool doInterrupt = false;
@ -272,8 +261,9 @@ nsTransactionManager::EndBatch()
nsRefPtr<nsTransactionItem> tx = mDoStack.Peek();
if (tx)
tx->GetTransaction(getter_AddRefs(ti));
if (tx) {
ti = tx->GetTransaction();
}
if (!tx || ti) {
return NS_ERROR_FAILURE;
@ -399,41 +389,41 @@ nsTransactionManager::SetMaxTransactionCount(PRInt32 aMaxCount)
NS_IMETHODIMP
nsTransactionManager::PeekUndoStack(nsITransaction **aTransaction)
{
nsresult result;
NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
*aTransaction = 0;
MOZ_ASSERT(aTransaction);
*aTransaction = PeekUndoStack().get();
return NS_OK;
}
already_AddRefed<nsITransaction>
nsTransactionManager::PeekUndoStack()
{
nsRefPtr<nsTransactionItem> tx = mUndoStack.Peek();
if (!tx) {
return NS_OK;
return nsnull;
}
result = tx->GetTransaction(aTransaction);
return result;
return tx->GetTransaction();
}
NS_IMETHODIMP
nsTransactionManager::PeekRedoStack(nsITransaction **aTransaction)
nsTransactionManager::PeekRedoStack(nsITransaction** aTransaction)
{
nsresult result;
NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
*aTransaction = 0;
MOZ_ASSERT(aTransaction);
*aTransaction = PeekRedoStack().get();
return NS_OK;
}
already_AddRefed<nsITransaction>
nsTransactionManager::PeekRedoStack()
{
nsRefPtr<nsTransactionItem> tx = mRedoStack.Peek();
if (!tx) {
return NS_OK;
return nsnull;
}
result = tx->GetTransaction(aTransaction);
return result;
return tx->GetTransaction();
}
NS_IMETHODIMP
@ -749,7 +739,6 @@ nsTransactionManager::BeginTransaction(nsITransaction *aTransaction)
nsresult
nsTransactionManager::EndTransaction()
{
nsCOMPtr<nsITransaction> tint;
nsresult result = NS_OK;
nsRefPtr<nsTransactionItem> tx = mDoStack.Pop();
@ -757,12 +746,7 @@ nsTransactionManager::EndTransaction()
if (!tx)
return NS_ERROR_FAILURE;
result = tx->GetTransaction(getter_AddRefs(tint));
if (NS_FAILED(result)) {
// XXX: What do we do with the transaction item at this point?
return result;
}
nsCOMPtr<nsITransaction> tint = tx->GetTransaction();
if (!tint) {
PRInt32 nc = 0;
@ -819,9 +803,7 @@ nsTransactionManager::EndTransaction()
if (tint && top) {
bool didMerge = false;
nsCOMPtr<nsITransaction> topTransaction;
result = top->GetTransaction(getter_AddRefs(topTransaction));
nsCOMPtr<nsITransaction> topTransaction = top->GetTransaction();
if (topTransaction) {

Просмотреть файл

@ -11,11 +11,11 @@
#include "nsCOMArray.h"
#include "nsITransactionListener.h"
#include "nsCycleCollectionParticipant.h"
#include "nsTransactionStack.h"
class nsITransaction;
class nsITransactionListener;
class nsTransactionItem;
class nsTransactionStack;
/** implementation of a transaction manager object.
*
@ -52,6 +52,8 @@ public:
/* nsTransactionManager specific methods. */
virtual nsresult ClearUndoStack(void);
virtual nsresult ClearRedoStack(void);
already_AddRefed<nsITransaction> PeekUndoStack();
already_AddRefed<nsITransaction> PeekRedoStack();
virtual nsresult WillDoNotify(nsITransaction *aTransaction, bool *aInterrupt);
virtual nsresult DidDoNotify(nsITransaction *aTransaction, nsresult aExecuteResult);

Просмотреть файл

@ -5,7 +5,8 @@
#include "mozilla/Hal.h"
#include "mozilla/HalWakeLock.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Services.h"
#include "nsObserverService.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
@ -42,14 +43,40 @@ struct LockCount {
static int sActiveChildren = 0;
static nsAutoPtr<nsDataHashtable<nsStringHashKey, LockCount> > sLockTable;
static bool sInitialized = false;
static bool sIsShuttingDown = false;
namespace {
class ClearHashtableOnShutdown : public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
};
NS_IMPL_ISUPPORTS1(ClearHashtableOnShutdown, nsIObserver)
NS_IMETHODIMP
ClearHashtableOnShutdown::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* data)
{
MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"));
sIsShuttingDown = true;
sLockTable = nsnull;
return NS_OK;
}
} // anonymous namespace
static void
Init()
{
sLockTable = new nsDataHashtable<nsStringHashKey, LockCount>();
sLockTable->Init();
ClearOnShutdown(&sLockTable);
sInitialized = true;
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->AddObserver(new ClearHashtableOnShutdown(), "xpcom-shutdown", false);
}
}
void
@ -69,6 +96,9 @@ ModifyWakeLock(const nsAString &aTopic,
hal::WakeLockControl aLockAdjust,
hal::WakeLockControl aHiddenAdjust)
{
if (sIsShuttingDown) {
return;
}
if (!sInitialized) {
Init();
}
@ -107,6 +137,10 @@ ModifyWakeLock(const nsAString &aTopic,
void
GetWakeLockInfo(const nsAString &aTopic, WakeLockInformation *aWakeLockInfo)
{
if (sIsShuttingDown) {
NS_WARNING("You don't want to get wake lock information during xpcom-shutdown!");
return;
}
if (!sInitialized) {
Init();
}

Просмотреть файл

@ -482,6 +482,8 @@ AsyncChannel::OnNotifyMaybeChannelError()
AssertWorkerThread();
mMonitor->AssertNotCurrentThreadOwns();
mChannelErrorTask = NULL;
// OnChannelError holds mMonitor when it posts this task and this
// task cannot be allowed to run until OnChannelError has
// exited. We enforce that order by grabbing the mutex here which
@ -743,13 +745,27 @@ AsyncChannel::OnChannelErrorFromLink()
PostErrorNotifyTask();
}
void
AsyncChannel::CloseWithError()
{
AssertWorkerThread();
MonitorAutoLock lock(*mMonitor);
if (ChannelConnected != mChannelState) {
return;
}
SynchronouslyClose();
mChannelState = ChannelError;
PostErrorNotifyTask();
}
void
AsyncChannel::PostErrorNotifyTask()
{
AssertLinkThread();
mMonitor->AssertCurrentThreadOwns();
NS_ASSERTION(!mChannelErrorTask, "OnChannelError called twice?");
if (mChannelErrorTask)
return;
// This must be the last code that runs on this thread!
mChannelErrorTask =

Просмотреть файл

@ -103,6 +103,10 @@ public:
// Close the underlying transport channel.
void Close();
// Force the channel to behave as if a channel error occurred. Valid
// for process links only, not thread links.
void CloseWithError();
// Asynchronously send a message to the other side of the channel
virtual bool Send(Message* msg);

Просмотреть файл

@ -85,7 +85,9 @@ struct CompartmentStats
memset(this, 0, sizeof(*this));
}
void *extra;
// These fields can be used by embedders.
void *extra1;
void *extra2;
// If you add a new number, remember to update add() and maybe
// gcHeapThingsSize()!

Просмотреть файл

@ -196,7 +196,7 @@ CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats)
IterateCompartmentsArenasCells(rt, rtStats, StatsCompartmentCallback,
StatsArenaCallback, StatsCellCallback);
// Take the "explcit/js/runtime/" measurements.
// Take the "explicit/js/runtime/" measurements.
rt->sizeOfIncludingThis(rtStats->mallocSizeOf, &rtStats->runtime);
rtStats->gcHeapGcThings = 0;

Просмотреть файл

@ -235,6 +235,8 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *call
if (!script->fullyInitFromEmitter(cx, &bce))
return NULL;
bce.tellDebuggerAboutCompiledScript(cx);
if (!MarkInnerAndOuterFunctions(cx, script))
return NULL;

Просмотреть файл

@ -36,6 +36,7 @@
#include "frontend/BytecodeEmitter.h"
#include "frontend/Parser.h"
#include "frontend/TokenStream.h"
#include "vm/Debugger.h"
#include "vm/RegExpObject.h"
#include "jsatominlines.h"
@ -1587,6 +1588,21 @@ BytecodeEmitter::needsImplicitThis()
return false;
}
void
BytecodeEmitter::tellDebuggerAboutCompiledScript(JSContext *cx)
{
js_CallNewScriptHook(cx, script, script->function());
if (!parent) {
GlobalObject *compileAndGoGlobal = NULL;
if (script->compileAndGo) {
compileAndGoGlobal = script->globalObject;
if (!compileAndGoGlobal)
compileAndGoGlobal = &sc->scopeChain()->global();
}
Debugger::onNewScript(cx, script, compileAndGoGlobal);
}
}
bool
BytecodeEmitter::reportError(ParseNode *pn, unsigned errorNumber, ...)
{
@ -2553,6 +2569,25 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
if (!bce->script->fullyInitFromEmitter(cx, bce))
return false;
// Initialize fun->script() so that the debugger has a valid fun->script().
RootedFunction fun(cx, bce->script->function());
JS_ASSERT(fun->isInterpreted());
if (bce->sc->funIsHeavyweight())
fun->flags |= JSFUN_HEAVYWEIGHT;
/* Mark functions which will only be executed once as singletons. */
bool singleton =
cx->typeInferenceEnabled() &&
bce->parent &&
bce->parent->checkSingletonContext();
JS_ASSERT(!fun->script());
fun->setScript(bce->script);
if (!fun->setTypeForScriptedFunction(cx, singleton))
return false;
bce->tellDebuggerAboutCompiledScript(cx);
return true;
}

Просмотреть файл

@ -176,6 +176,8 @@ struct BytecodeEmitter
bool needsImplicitThis();
void tellDebuggerAboutCompiledScript(JSContext *cx);
TokenStream *tokenStream() { return &parser->tokenStream; }
jsbytecode *base() const { return current->base; }

Просмотреть файл

@ -126,7 +126,7 @@ class ContextFlags {
};
struct SharedContext {
JSContext *context;
JSContext *const context;
private:
const RootedFunction fun_; /* function to store argument and variable

Просмотреть файл

@ -634,8 +634,11 @@ ScanBaseShape(GCMarker *gcmarker, BaseShape *base)
if (base->hasSetterObject())
PushMarkStack(gcmarker, base->setterObject());
if (JSObject *parent = base->getObjectParent())
if (JSObject *parent = base->getObjectParent()) {
PushMarkStack(gcmarker, parent);
} else if (GlobalObject *global = base->compartment()->maybeGlobal()) {
PushMarkStack(gcmarker, global);
}
/*
* All children of the owned base shape are consistent with its

Просмотреть файл

@ -52,7 +52,9 @@ The general format in EBNF is:
cookie ::= "|jit-test|"
item ::= flag | attribute
flag ::= "slow" | "allow-oom" | "valgrind" | "mjitalways" | "debug"
flag ::= "slow" | "allow-oom" | "valgrind" | "tz-pacific" |
"mjitalways" | "debug" |
attribute ::= name ":" value
name ::= "error" | "exitstatus"
@ -66,6 +68,7 @@ The meaning of the items:
slow Test runs slowly. Do not run if the --no-slow option is given.
allow-oom If the test runs out of memory, it counts as passing.
valgrind Run test under valgrind.
tz-pacific Always run test with the Pacific time zone (TZ=PST8PDT).
mjitalways Run js with -a, whether --jitflags says to or not
debug Run js with -d, whether --jitflags says to or not

Просмотреть файл

@ -54,6 +54,7 @@ class Test:
self.slow = False # True means the test is slow-running
self.allow_oom = False # True means that OOM is not considered a failure
self.valgrind = False # True means run under valgrind
self.tz_pacific = False # True means force Pacific time for the test
self.expect_error = '' # Errors to expect and consider passing
self.expect_status = 0 # Exit status to expect from shell
@ -63,6 +64,7 @@ class Test:
t.slow = self.slow
t.allow_oom = self.allow_oom
t.valgrind = self.valgrind
t.tz_pacific = self.tz_pacific
t.expect_error = self.expect_error
t.expect_status = self.expect_status
return t
@ -101,6 +103,8 @@ class Test:
test.allow_oom = True
elif name == 'valgrind':
test.valgrind = options.valgrind
elif name == 'tz-pacific':
test.tz_pacific = True
elif name == 'mjitalways':
test.jitflags.append('-a')
elif name == 'debug':
@ -222,7 +226,12 @@ def run_test(test, lib_dir, shell_args):
run = run_cmd_avoid_stdio
else:
run = run_cmd
out, err, code, timed_out = run(cmd, os.environ, OPTIONS.timeout)
env = os.environ.copy()
if test.tz_pacific:
env['TZ'] = 'PST8PDT'
out, err, code, timed_out = run(cmd, env, OPTIONS.timeout)
if OPTIONS.show_output:
sys.stdout.write(out)

Просмотреть файл

@ -0,0 +1,11 @@
var callStack = new Array();
function exitFunc (funcName) {
var lastFunc = callStack.pop();
}
gczeal(4);
var sb = evalcx('');
sb.parent = this;
this.f = function name(outer) {
return (exitFunc ('test'));
}
evalcx('this.f = parent.f; var s = ""; for (i = 0; i < 10; ++i) s += f(true); s', sb);

Просмотреть файл

@ -0,0 +1,14 @@
a = function() {
b = newGlobal()
};
c = [0, 0]
c.sort(a)
function d() {
yield arguments[4]
}
b.iterate = d
f = Proxy.create(b)
e = Iterator(f, true)
for (p in f) {
e.next()
}

Просмотреть файл

@ -1,3 +1,5 @@
// |jit-test| tz-pacific
function arrayExists(array, x) {
for (var i = 0; i < array.length; i++) {
if (array[i] == x) return true;

Просмотреть файл

@ -1951,11 +1951,12 @@ ScriptAnalysis::needsArgsObj(JSContext *cx)
/*
* Since let variables and dynamic name access are not tracked, we cannot
* soundly perform this analysis in their presence. Also, debuggers may
* want to see 'arguments', so assume every arguments object escapes.
* soundly perform this analysis in their presence. Debuggers may want to
* see 'arguments', so assume every arguments object escapes. Generators
* can be suspended when the speculation fails, so disallow it also.
*/
if (script->bindingsAccessedDynamically || script->numClosedArgs() > 0 ||
localsAliasStack() || cx->compartment->debugMode())
localsAliasStack() || cx->compartment->debugMode() || script->isGenerator)
{
return true;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -3053,6 +3053,13 @@ JS_GetObjectPrototype(JSContext *cx, JSObject *forObj);
extern JS_PUBLIC_API(JSObject *)
JS_GetGlobalForObject(JSContext *cx, JSObject *obj);
/*
* May return NULL, if |c| never had a global (e.g. the atoms compartment), or
* if |c|'s global has been collected.
*/
extern JS_PUBLIC_API(JSObject *)
JS_GetGlobalForCompartmentOrNull(JSContext *cx, JSCompartment *c);
extern JS_PUBLIC_API(JSObject *)
JS_GetGlobalForScopeChain(JSContext *cx);

Просмотреть файл

@ -291,7 +291,7 @@ js::DestroyContext(JSContext *cx, DestroyContextMode mode)
JS_REMOVE_LINK(&cx->link);
bool last = !rt->hasContexts();
if (last) {
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
/*
* Dump remaining type inference results first. This printing
@ -311,7 +311,7 @@ js::DestroyContext(JSContext *cx, DestroyContextMode mode)
PrepareForFullGC(rt);
GC(rt, GC_NORMAL, gcreason::LAST_CONTEXT);
} else if (mode == DCM_FORCE_GC) {
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
PrepareForFullGC(rt);
GC(rt, GC_NORMAL, gcreason::DESTROY_CONTEXT);
}
@ -1166,7 +1166,7 @@ JSRuntime::onTooMuchMalloc()
JS_FRIEND_API(void *)
JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
{
if (gcRunning)
if (isHeapBusy())
return NULL;
/*
@ -1313,7 +1313,7 @@ namespace JS {
AutoCheckRequestDepth::AutoCheckRequestDepth(JSContext *cx)
: cx(cx)
{
JS_ASSERT(cx->runtime->requestDepth || cx->runtime->gcRunning);
JS_ASSERT(cx->runtime->requestDepth || cx->runtime->isHeapBusy());
JS_ASSERT(cx->runtime->onOwnerThread());
cx->runtime->checkRequestDepth++;
}

Просмотреть файл

@ -578,7 +578,16 @@ struct JSRuntime : js::RuntimeFriendFields
#endif
bool gcPoke;
bool gcRunning;
enum HeapState {
Idle, // doing nothing with the GC heap
Tracing, // tracing the GC heap without collecting, e.g. IterateCompartments()
Collecting // doing a GC of the heap
};
HeapState heapState;
bool isHeapBusy() { return heapState != Idle; }
/*
* These options control the zealousness of the GC. The fundamental values

Просмотреть файл

@ -229,7 +229,7 @@ class CompartmentChecker
{
if (cx->compartment) {
GlobalObject *global = GetGlobalForScopeChain(cx);
JS_ASSERT(cx->compartment->global() == *global);
JS_ASSERT(cx->compartment->maybeGlobal() == global);
}
}
@ -328,7 +328,7 @@ class CompartmentChecker
* depends on other objects not having been swept yet.
*/
#define START_ASSERT_SAME_COMPARTMENT() \
if (cx->runtime->gcRunning) \
if (cx->runtime->isHeapBusy()) \
return; \
CompartmentChecker c(cx)

Просмотреть файл

@ -491,6 +491,9 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
discardJitCode(fop);
}
if (global_ && !IsObjectMarked(&global_))
global_ = NULL;
/* JIT code can hold references on RegExpShared, so sweep regexps after clearing code. */
regExps.sweep(rt);
@ -680,7 +683,7 @@ JSCompartment::updateForDebugMode(FreeOp *fop, AutoDebugModeGC &dmgc)
// dmgc makes sure we can't forget to GC, but it is also important not
// to run any scripts in this compartment until the dmgc is destroyed.
// That is the caller's responsibility.
if (!rt->gcRunning)
if (!rt->isHeapBusy())
dmgc.scheduleGC(this);
#endif
}

Просмотреть файл

@ -119,12 +119,23 @@ struct JSCompartment
private:
js::GlobalObject *global_;
public:
js::GlobalObject &global() const {
JS_ASSERT(global_->compartment() == this);
return *global_;
// Nb: global_ might be NULL, if (a) it's the atoms compartment, or (b) the
// compartment's global has been collected. The latter can happen if e.g.
// a string in a compartment is rooted but no object is, and thus the
// global isn't rooted, and thus the global can be finalized while the
// compartment lives on.
//
// In contrast, JSObject::global() is infallible because marking a JSObject
// always marks its global as well.
// TODO: add infallible JSScript::global() and JSContext::global()
//
js::GlobalObject *maybeGlobal() const {
JS_ASSERT_IF(global_, global_->compartment() == this);
return global_;
}
void initGlobal(js::GlobalObject &global) {
JS_ASSERT(global.compartment() == this);
JS_ASSERT(!global_);
global_ = &global;
}
@ -160,7 +171,7 @@ struct JSCompartment
public:
bool isCollecting() const {
/* Allow this if we're in the middle of an incremental GC. */
if (rt->gcRunning) {
if (rt->isHeapBusy()) {
return gcState == GCRunning;
} else {
JS_ASSERT(gcState != GCRunning);
@ -181,7 +192,7 @@ struct JSCompartment
}
void setCollecting(bool collecting) {
JS_ASSERT(rt->gcRunning);
JS_ASSERT(rt->isHeapBusy());
if (collecting)
gcState = GCRunning;
else
@ -189,13 +200,13 @@ struct JSCompartment
}
void scheduleGC() {
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
JS_ASSERT(gcState != GCRunning);
gcState = GCScheduled;
}
void unscheduleGC() {
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
JS_ASSERT(gcState != GCRunning);
gcState = NoGCScheduled;
}
@ -414,7 +425,7 @@ class js::AutoDebugModeGC
}
void scheduleGC(JSCompartment *compartment) {
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
PrepareCompartmentForGC(compartment);
needGC = true;
}

Просмотреть файл

@ -798,7 +798,7 @@ DisableIncrementalGC(JSRuntime *rt)
JS_FRIEND_API(bool)
IsIncrementalBarrierNeeded(JSRuntime *rt)
{
return (rt->gcIncrementalState == gc::MARK && !rt->gcRunning);
return (rt->gcIncrementalState == gc::MARK && !rt->isHeapBusy());
}
JS_FRIEND_API(bool)
@ -824,7 +824,7 @@ IncrementalReferenceBarrier(void *ptr)
{
if (!ptr)
return;
JS_ASSERT(!static_cast<gc::Cell *>(ptr)->compartment()->rt->gcRunning);
JS_ASSERT(!static_cast<gc::Cell *>(ptr)->compartment()->rt->isHeapBusy());
uint32_t kind = gc::GetGCThingTraceKind(ptr);
if (kind == JSTRACE_OBJECT)
JSObject::writeBarrierPre((JSObject *) ptr);

Просмотреть файл

@ -392,7 +392,8 @@ js::XDRInterpretedFunction(XDRState<mode> *xdr, JSObject **objp, JSScript *paren
fun->flags = uint16_t(flagsword);
fun->atom.init(atom);
fun->initScript(script);
if (!script->typeSetFunction(cx, fun))
script->setFunction(fun);
if (!fun->setTypeForScriptedFunction(cx))
return false;
JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs());
js_CallNewScriptHook(cx, fun->script(), fun);
@ -431,7 +432,8 @@ js::CloneInterpretedFunction(JSContext *cx, JSFunction *srcFun)
clone->flags = srcFun->flags;
clone->atom.init(srcFun->atom);
clone->initScript(clonedScript);
if (!clonedScript->typeSetFunction(cx, clone))
clonedScript->setFunction(clone);
if (!clone->setTypeForScriptedFunction(cx))
return NULL;
js_CallNewScriptHook(cx, clone->script(), clone);
@ -1301,7 +1303,8 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
cscript->globalObject = &clone->global();
clone->setScript(cscript);
if (!cscript->typeSetFunction(cx, clone))
cscript->setFunction(clone);
if (!clone->setTypeForScriptedFunction(cx))
return NULL;
js_CallNewScriptHook(cx, clone->script(), clone);

Просмотреть файл

@ -178,6 +178,9 @@ struct JSFunction : public JSObject
inline void setExtendedSlot(size_t which, const js::Value &val);
inline const js::Value &getExtendedSlot(size_t which) const;
/* Constructs a new type for the function if necessary. */
bool setTypeForScriptedFunction(JSContext *cx, bool singleton = false);
private:
/*
* These member functions are inherited from JSObject, but should never be applied to

Просмотреть файл

@ -214,7 +214,7 @@ ArenaHeader::checkSynchronizedWithFreeList() const
* list in the compartment can mutate at any moment. We cannot do any
* checks in this case.
*/
if (!compartment->rt->gcRunning)
if (!compartment->rt->isHeapBusy())
return;
FreeSpan firstSpan = FreeSpan::decodeOffsets(arenaAddress(), firstFreeSpanOffsets);
@ -1633,7 +1633,7 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
JSCompartment *comp = cx->compartment;
JSRuntime *rt = comp->rt;
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
bool runGC = rt->gcIncrementalState != NO_INCREMENTAL && comp->gcBytes > comp->gcTriggerBytes;
for (;;) {
@ -2027,7 +2027,7 @@ GCMarker::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const
void
SetMarkStackLimit(JSRuntime *rt, size_t limit)
{
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
rt->gcMarker.setSizeLimit(limit);
}
@ -2431,7 +2431,7 @@ TriggerGC(JSRuntime *rt, gcreason::Reason reason)
{
JS_ASSERT(rt->onOwnerThread());
if (rt->gcRunning)
if (rt->isHeapBusy())
return;
PrepareForFullGC(rt);
@ -2444,7 +2444,7 @@ TriggerCompartmentGC(JSCompartment *comp, gcreason::Reason reason)
JSRuntime *rt = comp->rt;
JS_ASSERT(rt->onOwnerThread());
if (rt->gcRunning)
if (rt->isHeapBusy())
return;
if (rt->gcZeal() == ZealAllocValue) {
@ -2568,7 +2568,7 @@ DecommitArenasFromAvailableList(JSRuntime *rt, Chunk **availableListHeadp)
* lock.
*/
Maybe<AutoUnlockGC> maybeUnlock;
if (!rt->gcRunning)
if (!rt->isHeapBusy())
maybeUnlock.construct(rt);
ok = MarkPagesUnused(aheader->getArena(), ArenaSize);
}
@ -3285,9 +3285,9 @@ SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep)
/*
* Sweep phase.
*
* Finalize as we sweep, outside of rt->gcLock but with rt->gcRunning set
* so that any attempt to allocate a GC-thing from a finalizer will fail,
* rather than nest badly and leave the unmarked newborn to be swept.
* Finalize as we sweep, outside of rt->gcLock but with rt->isHeapBusy()
* true so that any attempt to allocate a GC-thing from a finalizer will
* fail, rather than nest badly and leave the unmarked newborn to be swept.
*
* We first sweep atom state so we can use IsAboutToBeFinalized on
* JSString held in a hashtable to check if the hashtable entry can be
@ -3420,43 +3420,44 @@ SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep)
* This class should be used by any code that needs to exclusive access to the
* heap in order to trace through it...
*/
class AutoHeapSession {
class AutoTraceSession {
public:
explicit AutoHeapSession(JSRuntime *rt);
~AutoHeapSession();
AutoTraceSession(JSRuntime *rt, JSRuntime::HeapState state = JSRuntime::Tracing);
~AutoTraceSession();
protected:
JSRuntime *runtime;
private:
AutoHeapSession(const AutoHeapSession&) MOZ_DELETE;
void operator=(const AutoHeapSession&) MOZ_DELETE;
AutoTraceSession(const AutoTraceSession&) MOZ_DELETE;
void operator=(const AutoTraceSession&) MOZ_DELETE;
};
/* ...while this class is to be used only for garbage collection. */
class AutoGCSession : AutoHeapSession {
class AutoGCSession : AutoTraceSession {
public:
explicit AutoGCSession(JSRuntime *rt);
~AutoGCSession();
};
/* Start a new heap session. */
AutoHeapSession::AutoHeapSession(JSRuntime *rt)
AutoTraceSession::AutoTraceSession(JSRuntime *rt, JSRuntime::HeapState heapState)
: runtime(rt)
{
JS_ASSERT(!rt->noGCOrAllocationCheck);
JS_ASSERT(!rt->gcRunning);
rt->gcRunning = true;
JS_ASSERT(!rt->isHeapBusy());
JS_ASSERT(heapState == JSRuntime::Collecting || heapState == JSRuntime::Tracing);
rt->heapState = heapState;
}
AutoHeapSession::~AutoHeapSession()
AutoTraceSession::~AutoTraceSession()
{
JS_ASSERT(runtime->gcRunning);
runtime->gcRunning = false;
JS_ASSERT(runtime->isHeapBusy());
runtime->heapState = JSRuntime::Idle;
}
AutoGCSession::AutoGCSession(JSRuntime *rt)
: AutoHeapSession(rt)
: AutoTraceSession(rt, JSRuntime::Collecting)
{
DebugOnly<bool> any = false;
for (CompartmentsIter c(rt); !c.done(); c.next()) {
@ -3745,7 +3746,7 @@ GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gcki
#endif
/* Recursive GC is no-op. */
if (rt->gcRunning)
if (rt->isHeapBusy())
return;
/* Don't GC if we are reporting an OOM. */
@ -3956,7 +3957,7 @@ void
ShrinkGCBuffers(JSRuntime *rt)
{
AutoLockGC lock(rt);
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
#ifndef JS_THREADSAFE
ExpireChunksAndArenas(rt, true);
#else
@ -3972,8 +3973,8 @@ TraceRuntime(JSTracer *trc)
#ifdef JS_THREADSAFE
{
JSRuntime *rt = trc->runtime;
if (!rt->gcRunning) {
AutoHeapSession session(rt);
if (!rt->isHeapBusy()) {
AutoTraceSession session(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
@ -4029,9 +4030,9 @@ IterateCompartmentsArenasCells(JSRuntime *rt, void *data,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback)
{
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
AutoHeapSession session(rt);
AutoTraceSession session(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
AutoCopyFreeListToArenas copy(rt);
@ -4052,9 +4053,9 @@ void
IterateChunks(JSRuntime *rt, void *data, IterateChunkCallback chunkCallback)
{
/* :XXX: Any way to common this preamble with IterateCompartmentsArenasCells? */
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
AutoHeapSession session(rt);
AutoTraceSession session(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
for (js::GCChunkSet::Range r = rt->gcChunkSet.all(); !r.empty(); r.popFront())
@ -4066,9 +4067,9 @@ IterateCells(JSRuntime *rt, JSCompartment *compartment, AllocKind thingKind,
void *data, IterateCellCallback cellCallback)
{
/* :XXX: Any way to common this preamble with IterateCompartmentsArenasCells? */
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
AutoHeapSession session(rt);
AutoTraceSession session(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
AutoCopyFreeListToArenas copy(rt);
@ -4092,9 +4093,9 @@ IterateGrayObjects(JSCompartment *compartment, GCThingCallback *cellCallback, vo
{
JS_ASSERT(compartment);
JSRuntime *rt = compartment->rt;
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
AutoHeapSession session(rt);
AutoTraceSession session(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
AutoCopyFreeListToArenas copy(rt);
@ -4454,7 +4455,7 @@ StartVerifyBarriers(JSRuntime *rt)
if (rt->gcVerifyData || rt->gcIncrementalState != NO_INCREMENTAL)
return;
AutoHeapSession session(rt);
AutoTraceSession session(rt);
if (!IsIncrementalGCSafe(rt))
return;
@ -4582,7 +4583,7 @@ AssertMarkedOrAllocated(const EdgeValue &edge)
static void
EndVerifyBarriers(JSRuntime *rt)
{
AutoHeapSession session(rt);
AutoTraceSession session(rt);
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
@ -4798,9 +4799,9 @@ JS_PUBLIC_API(void)
JS_IterateCompartments(JSRuntime *rt, void *data,
JSIterateCompartmentCallback compartmentCallback)
{
JS_ASSERT(!rt->gcRunning);
JS_ASSERT(!rt->isHeapBusy());
AutoHeapSession session(rt);
AutoTraceSession session(rt);
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
for (CompartmentsIter c(rt); !c.done(); c.next())

Просмотреть файл

@ -293,12 +293,12 @@ class CellIterUnderGC : public CellIterImpl
{
public:
CellIterUnderGC(JSCompartment *comp, AllocKind kind) {
JS_ASSERT(comp->rt->gcRunning);
JS_ASSERT(comp->rt->isHeapBusy());
init(comp, kind);
}
CellIterUnderGC(ArenaHeader *aheader) {
JS_ASSERT(aheader->compartment->rt->gcRunning);
JS_ASSERT(aheader->compartment->rt->isHeapBusy());
init(aheader);
}
};
@ -330,7 +330,7 @@ class CellIter : public CellIterImpl
if (lists->isSynchronizedFreeList(kind)) {
lists = NULL;
} else {
JS_ASSERT(!comp->rt->gcRunning);
JS_ASSERT(!comp->rt->isHeapBusy());
lists->copyFreeListToArena(kind);
}
#ifdef DEBUG
@ -361,7 +361,7 @@ class GCCompartmentsIter {
public:
GCCompartmentsIter(JSRuntime *rt) {
JS_ASSERT(rt->gcRunning);
JS_ASSERT(rt->isHeapBusy());
it = rt->compartments.begin();
end = rt->compartments.end();
if (!(*it)->isCollecting())
@ -400,7 +400,7 @@ NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
JS_ASSERT(thingSize == js::gc::Arena::thingSize(kind));
JS_ASSERT_IF(cx->compartment == cx->runtime->atomsCompartment,
kind == js::gc::FINALIZE_STRING || kind == js::gc::FINALIZE_SHORT_STRING);
JS_ASSERT(!cx->runtime->gcRunning);
JS_ASSERT(!cx->runtime->isHeapBusy());
JS_ASSERT(!cx->runtime->noGCOrAllocationCheck);
/* For testing out of memory conditions */
@ -431,7 +431,7 @@ TryNewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
JS_ASSERT(thingSize == js::gc::Arena::thingSize(kind));
JS_ASSERT_IF(cx->compartment == cx->runtime->atomsCompartment,
kind == js::gc::FINALIZE_STRING || kind == js::gc::FINALIZE_SHORT_STRING);
JS_ASSERT(!cx->runtime->gcRunning);
JS_ASSERT(!cx->runtime->isHeapBusy());
JS_ASSERT(!cx->runtime->noGCOrAllocationCheck);
#ifdef JS_GC_ZEAL

Просмотреть файл

@ -5417,24 +5417,25 @@ JSScript::makeAnalysis(JSContext *cx)
}
bool
JSScript::typeSetFunction(JSContext *cx, JSFunction *fun, bool singleton)
JSFunction::setTypeForScriptedFunction(JSContext *cx, bool singleton)
{
function_ = fun;
JS_ASSERT(script());
JS_ASSERT(script()->function() == this);
if (!cx->typeInferenceEnabled())
return true;
if (singleton) {
if (!fun->setSingletonType(cx))
if (!setSingletonType(cx))
return false;
} else {
TypeObject *type = cx->compartment->types.newTypeObject(cx, this,
JSProto_Function, fun->getProto());
TypeObject *type = cx->compartment->types.newTypeObject(cx, script(),
JSProto_Function, getProto());
if (!type)
return false;
function_->setType(type);
type->interpretedFunction = function_;
setType(type);
type->interpretedFunction = this;
}
return true;

Просмотреть файл

@ -779,7 +779,7 @@ inline void
TypeCompartment::addPending(JSContext *cx, TypeConstraint *constraint, TypeSet *source, Type type)
{
JS_ASSERT(this == &cx->compartment->types);
JS_ASSERT(!cx->runtime->gcRunning);
JS_ASSERT(!cx->runtime->isHeapBusy());
InferSpew(ISpewOps, "pending: %sC%p%s %s",
InferSpewColor(constraint), constraint, InferSpewColorReset(),

Просмотреть файл

@ -1051,7 +1051,8 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
{
JSAutoResolveFlags rf(cx, RESOLVE_INFER);
gc::MaybeVerifyBarriers(cx, true);
if (interpMode == JSINTERP_NORMAL)
gc::MaybeVerifyBarriers(cx, true);
JS_ASSERT(!cx->compartment->activeAnalysis);

Просмотреть файл

@ -2348,7 +2348,7 @@ NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *paren
JS_ASSERT(clasp != &ArrayClass);
JS_ASSERT_IF(clasp == &FunctionClass,
kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
JS_ASSERT_IF(parent, parent->global() == cx->compartment->global());
JS_ASSERT_IF(parent, &parent->global() == cx->compartment->maybeGlobal());
RootedTypeObject type(cx, type_);

Просмотреть файл

@ -1234,7 +1234,7 @@ JSObject::global() const
JSObject *obj = const_cast<JSObject *>(this);
while (JSObject *parent = obj->getParent())
obj = parent;
JS_ASSERT(obj->asGlobal() == compartment()->global());
JS_ASSERT(&obj->asGlobal() == compartment()->maybeGlobal());
return obj->asGlobal();
}

Просмотреть файл

@ -404,7 +404,7 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
return true;
}
if (cx->runtime->gcRunning || cx->runtime->noGCOrAllocationCheck) {
if (cx->runtime->isHeapBusy() || cx->runtime->noGCOrAllocationCheck) {
char *source = JS_sprintf_append(NULL, "<value>");
if (!source)
return false;

Просмотреть файл

@ -19,7 +19,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, unsigned scopeIndex, JSObject
Shape *shape)
{
JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
JS_ASSERT(!cx->runtime->gcRunning);
JS_ASSERT(!cx->runtime->isHeapBusy());
/*
* Check for overdeep scope and prototype chain. Because resolve, getter,

Просмотреть файл

@ -1340,41 +1340,8 @@ JSScript::fullyInitFromEmitter(JSContext *cx, BytecodeEmitter *bce)
RootedFunction fun(cx, NULL);
if (bce->sc->inFunction()) {
JS_ASSERT(!bce->script->noScriptRval);
script->isGenerator = bce->sc->funIsGenerator();
/*
* We initialize fun->script() to be the script constructed above
* so that the debugger has a valid fun->script().
*/
fun = bce->sc->fun();
JS_ASSERT(fun->isInterpreted());
JS_ASSERT(!fun->script());
if (bce->sc->funIsHeavyweight())
fun->flags |= JSFUN_HEAVYWEIGHT;
/* Mark functions which will only be executed once as singletons. */
bool singleton =
cx->typeInferenceEnabled() &&
bce->parent &&
bce->parent->checkSingletonContext();
if (!script->typeSetFunction(cx, fun, singleton))
return false;
fun->setScript(script);
}
/* Tell the debugger about this compiled script. */
js_CallNewScriptHook(cx, script, fun);
if (!bce->parent) {
GlobalObject *compileAndGoGlobal = NULL;
if (script->compileAndGo) {
compileAndGoGlobal = script->globalObject;
if (!compileAndGoGlobal)
compileAndGoGlobal = &bce->sc->scopeChain()->global();
}
Debugger::onNewScript(cx, script, compileAndGoGlobal);
script->setFunction(bce->sc->fun());
}
/*
@ -2145,6 +2112,7 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, JSScript *script_)
JS_ASSERT(script->analyzedArgsUsage());
JS_ASSERT(script->argumentsHasVarBinding());
JS_ASSERT(!script->isGenerator);
/*
* It is possible that the apply speculation has already failed, everything

Просмотреть файл

@ -627,12 +627,6 @@ struct JSScript : public js::gc::Cell
inline void clearAnalysis();
inline js::analyze::ScriptAnalysis *analysis();
/*
* Associates this script with a specific function, constructing a new type
* object for the function if necessary.
*/
bool typeSetFunction(JSContext *cx, JSFunction *fun, bool singleton = false);
inline bool hasGlobal() const;
inline bool hasClearedGlobal() const;

Просмотреть файл

@ -255,7 +255,7 @@ JSScript::writeBarrierPre(JSScript *script)
JSCompartment *comp = script->compartment();
if (comp->needsBarrier()) {
JS_ASSERT(!comp->rt->gcRunning);
JS_ASSERT(!comp->rt->isHeapBusy());
JSScript *tmp = script;
MarkScriptUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
JS_ASSERT(tmp == script);

Просмотреть файл

@ -1521,7 +1521,7 @@ class TypedArrayTemplate
RootedId id(cx, NameToId(name));
unsigned flags = JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_SHARED | JSPROP_GETTER;
Rooted<GlobalObject*> global(cx, &cx->compartment->global());
Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
JSObject *getter = js_NewFunction(cx, NULL, Getter<ValueGetter>, 0, 0, global, NULL);
if (!getter)
return false;
@ -3008,7 +3008,7 @@ template<class ArrayType>
static inline JSObject *
InitTypedArrayClass(JSContext *cx)
{
Rooted<GlobalObject*> global(cx, &cx->compartment->global());
Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
RootedObject proto(cx, global->createBlankPrototype(cx, ArrayType::protoClass()));
if (!proto)
return NULL;
@ -3085,7 +3085,7 @@ Class TypedArray::protoClasses[TYPE_MAX] = {
static JSObject *
InitArrayBufferClass(JSContext *cx)
{
Rooted<GlobalObject*> global(cx, &cx->compartment->global());
Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
RootedObject arrayBufferProto(cx, global->createBlankPrototype(cx, &ArrayBufferObject::protoClass));
if (!arrayBufferProto)
return NULL;
@ -3198,7 +3198,7 @@ DefineDataViewGetter(JSContext *cx, PropertyName *name, HandleObject proto)
RootedId id(cx, NameToId(name));
unsigned flags = JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_SHARED | JSPROP_GETTER;
Rooted<GlobalObject*> global(cx, &cx->compartment->global());
Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
JSObject *getter = js_NewFunction(cx, NULL, DataViewGetter<ValueGetter>, 0, 0, global, NULL);
if (!getter)
return false;
@ -3211,7 +3211,7 @@ DefineDataViewGetter(JSContext *cx, PropertyName *name, HandleObject proto)
JSObject *
DataViewObject::initClass(JSContext *cx)
{
Rooted<GlobalObject*> global(cx, &cx->compartment->global());
Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
RootedObject proto(cx, global->createBlankPrototype(cx, &DataViewObject::protoClass));
if (!proto)
return NULL;

Просмотреть файл

@ -929,7 +929,7 @@ template<class T>
void
JSXMLArray<T>::finish(FreeOp *fop)
{
if (!fop->runtime()->gcRunning) {
if (!fop->runtime()->isHeapBusy()) {
/* We need to clear these to trigger a write barrier. */
for (uint32_t i = 0; i < length; i++)
vector[i].~HeapPtr<T>();

Просмотреть файл

@ -14,7 +14,6 @@ include $(DEPTH)/config/autoconf.mk
PROGRAM = js$(BIN_SUFFIX)
CPPSRCS = \
js.cpp \
jsworkers.cpp \
jsoptparse.cpp \
jsheaptools.cpp \
$(NULL)

Просмотреть файл

@ -51,7 +51,6 @@
#include "prmjtime.h"
#include "jsoptparse.h"
#include "jsworkers.h"
#include "jsheaptools.h"
#include "jsinferinlines.h"
@ -157,10 +156,6 @@ bool gQuitting = false;
bool gGotError = false;
FILE *gErrFile = NULL;
FILE *gOutFile = NULL;
#ifdef JS_THREADSAFE
JSObject *gWorkers = NULL;
js::workers::ThreadPool *gWorkerThreadPool = NULL;
#endif
static bool reportWarnings = true;
static bool compileOnly = false;
@ -1207,10 +1202,6 @@ Quit(JSContext *cx, unsigned argc, jsval *vp)
JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/ i", &gExitCode);
gQuitting = true;
#ifdef JS_THREADSAFE
if (gWorkerThreadPool)
js::workers::terminateAll(gWorkerThreadPool);
#endif
return false;
}
@ -3035,10 +3026,6 @@ CancelExecution(JSRuntime *rt)
gCanceled = true;
if (gExitCode == 0)
gExitCode = EXITCODE_TIMEOUT;
#ifdef JS_THREADSAFE
if (gWorkerThreadPool)
js::workers::terminateAll(gWorkerThreadPool);
#endif
JS_TriggerOperationCallback(rt);
static const char msg[] = "Script runs for too long, terminating.\n";
@ -4700,29 +4687,8 @@ Shell(JSContext *cx, OptionParser *op, char **envp)
return 1;
JS_SetPrivate(envobj, envp);
#ifdef JS_THREADSAFE
class ShellWorkerHooks : public js::workers::WorkerHooks {
public:
JSObject *newGlobalObject(JSContext *cx) {
return NewGlobalObject(cx);
}
};
ShellWorkerHooks hooks;
if (!JS_AddNamedObjectRoot(cx, &gWorkers, "Workers") ||
(gWorkerThreadPool = js::workers::init(cx, &hooks, glob, &gWorkers)) == NULL) {
return 1;
}
#endif
int result = ProcessArgs(cx, glob, op);
#ifdef JS_THREADSAFE
js::workers::finish(cx, gWorkerThreadPool);
JS_RemoveObjectRoot(cx, &gWorkers);
if (result == 0)
result = gExitCode;
#endif
if (enableDisassemblyDumps)
JS_DumpCompartmentPCCounts(cx);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,60 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jsworkers_h___
#define jsworkers_h___
#ifdef JS_THREADSAFE
#include "jsapi.h"
/*
* Workers for the JS shell.
*
* Note: The real implementation of DOM Workers is in dom/workers.
*/
namespace js {
namespace workers {
class ThreadPool;
class WorkerHooks {
public:
virtual JSObject *newGlobalObject(JSContext *cx) = 0;
virtual ~WorkerHooks() {}
};
/*
* Initialize workers. This defines the Worker constructor on global.
* Requires request. rootp must point to a GC root.
*
* On success, *rootp receives a pointer to an object, and init returns
* a non-null value. The caller must keep the object rooted and must
* pass it to js::workers::finish later.
*/
ThreadPool *init(JSContext *cx, WorkerHooks *hooks, JSObject *global, JSObject **rootp);
/* Asynchronously signal for all workers to terminate.
*
* Call this before calling finish() to shut down without waiting for
* all messages to be proceesed.
*/
void terminateAll(ThreadPool *tp);
/*
* Finish running any workers, shut down the thread pool, and free all
* resources associated with workers. The application must call this
* before shutting down the runtime, and not during GC.
*
* Requires request.
*/
void finish(JSContext *cx, ThreadPool *tp);
}
}
#endif /* JS_THREADSAFE */
#endif /* jsworkers_h___ */

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше