зеркало из https://github.com/mozilla/gecko-dev.git
Merge the last green PGO changeset from mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
1aabf0598f
|
@ -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;
|
||||
}
|
||||
|
|
420
js/src/jsapi.cpp
420
js/src/jsapi.cpp
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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___ */
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче