--- a/accessible/src/base/TextAttrs.cpp
+++ b/accessible/src/base/TextAttrs.cpp
@@ -47,42 +47,16 @@
#include "gfxUserFontSet.h"
#include "nsFontMetrics.h"
#include "nsLayoutUtils.h"
using namespace mozilla;
using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
-// Constants and structures
-
-/**
- * Item of the gCSSTextAttrsMap map.
- */
-struct nsCSSTextAttrMapItem
-{
- const char* mCSSName;
- const char* mCSSValue;
- nsIAtom** mAttrName;
- const char* mAttrValue;
-};
-
-/**
- * The map of CSS properties to text attributes.
- */
-const char* const kAnyValue = nsnull;
-const char* const kCopyValue = nsnull;
-
-static nsCSSTextAttrMapItem gCSSTextAttrsMap[] =
-{
- // CSS name CSS value Attribute name Attribute value
- { "vertical-align", kAnyValue, &nsGkAtoms::textPosition, kCopyValue }
-};
-
-////////////////////////////////////////////////////////////////////////////////
// TextAttrsMgr
////////////////////////////////////////////////////////////////////////////////
void
TextAttrsMgr::GetAttributes(nsIPersistentProperties* aAttributes,
PRInt32* aStartHTOffset,
PRInt32* aEndHTOffset)
{
@@ -134,88 +108,87 @@ TextAttrsMgr::GetAttributes(nsIPersisten
nsIContent *offsetNode = nsnull, *offsetElm = nsnull;
nsIFrame *frame = nsnull;
if (mOffsetAcc) {
offsetNode = mOffsetAcc->GetContent();
offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
frame = offsetElm->GetPrimaryFrame();
}
- nsTArray<TextAttr*> textAttrArray(9);
-
// "language" text attribute
LangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
- textAttrArray.AppendElement(&langTextAttr);
-
- // "text-position" text attribute
- CSSTextAttr posTextAttr(0, hyperTextElm, offsetElm);
- textAttrArray.AppendElement(&posTextAttr);
// "background-color" text attribute
BGColorTextAttr bgColorTextAttr(rootFrame, frame);
- textAttrArray.AppendElement(&bgColorTextAttr);
// "color" text attribute
ColorTextAttr colorTextAttr(rootFrame, frame);
- textAttrArray.AppendElement(&colorTextAttr);
// "font-family" text attribute
FontFamilyTextAttr fontFamilyTextAttr(rootFrame, frame);
- textAttrArray.AppendElement(&fontFamilyTextAttr);
// "font-size" text attribute
FontSizeTextAttr fontSizeTextAttr(rootFrame, frame);
- textAttrArray.AppendElement(&fontSizeTextAttr);
// "font-style" text attribute
FontStyleTextAttr fontStyleTextAttr(rootFrame, frame);
- textAttrArray.AppendElement(&fontStyleTextAttr);
// "font-weight" text attribute
FontWeightTextAttr fontWeightTextAttr(rootFrame, frame);
- textAttrArray.AppendElement(&fontWeightTextAttr);
// "text-underline(line-through)-style(color)" text attributes
TextDecorTextAttr textDecorTextAttr(rootFrame, frame);
- textAttrArray.AppendElement(&textDecorTextAttr);
+
+ // "text-position" text attribute
+ TextPosTextAttr textPosTextAttr(rootFrame, frame);
+
+ TextAttr* attrArray[] =
+ {
+ &langTextAttr,
+ &bgColorTextAttr,
+ &colorTextAttr,
+ &fontFamilyTextAttr,
+ &fontSizeTextAttr,
+ &fontStyleTextAttr,
+ &fontWeightTextAttr,
+ &textDecorTextAttr,
+ &textPosTextAttr
+ };
// Expose text attributes if applicable.
if (aAttributes) {
- PRUint32 len = textAttrArray.Length();
- for (PRUint32 idx = 0; idx < len; idx++)
- textAttrArray[idx]->Expose(aAttributes, mIncludeDefAttrs);
+ for (PRUint32 idx = 0; idx < ArrayLength(attrArray); idx++)
+ attrArray[idx]->Expose(aAttributes, mIncludeDefAttrs);
}
// Expose text attributes range where they are applied if applicable.
if (mOffsetAcc)
- GetRange(textAttrArray, aStartHTOffset, aEndHTOffset);
+ GetRange(attrArray, ArrayLength(attrArray), aStartHTOffset, aEndHTOffset);
}
void
-TextAttrsMgr::GetRange(const nsTArray<TextAttr*>& aTextAttrArray,
+TextAttrsMgr::GetRange(TextAttr* aAttrArray[], PRUint32 aAttrArrayLen,
PRInt32* aStartHTOffset, PRInt32* aEndHTOffset)
{
- PRUint32 attrLen = aTextAttrArray.Length();
-
// Navigate backward from anchor accessible to find start offset.
for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
// Stop on embedded accessible since embedded accessibles are combined into
// own range.
if (nsAccUtils::IsEmbeddedObject(currAcc))
break;
nsIContent* currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent());
if (!currElm)
return;
bool offsetFound = false;
- for (PRUint32 attrIdx = 0; attrIdx < attrLen; attrIdx++) {
- TextAttr* textAttr = aTextAttrArray[attrIdx];
+ for (PRUint32 attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
+ TextAttr* textAttr = aAttrArray[attrIdx];
if (!textAttr->Equal(currElm)) {
offsetFound = true;
break;
}
}
if (offsetFound)
break;
@@ -230,18 +203,18 @@ TextAttrsMgr::GetRange(const nsTArray<Te
if (nsAccUtils::IsEmbeddedObject(currAcc))
break;
nsIContent* currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent());
if (!currElm)
return;
bool offsetFound = false;
- for (PRUint32 attrIdx = 0; attrIdx < attrLen; attrIdx++) {
- TextAttr* textAttr = aTextAttrArray[attrIdx];
+ for (PRUint32 attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
+ TextAttr* textAttr = aAttrArray[attrIdx];
// Alter the end offset when text attribute changes its value and stop
// the search.
if (!textAttr->Equal(currElm)) {
offsetFound = true;
break;
}
}
@@ -289,70 +262,16 @@ TextAttrsMgr::LangTextAttr::
GetLang(nsIContent* aElm, nsAString& aLang)
{
nsCoreUtils::GetLanguageFor(aElm, mRootContent, aLang);
return !aLang.IsEmpty();
}
////////////////////////////////////////////////////////////////////////////////
-// CSSTextAttr
-////////////////////////////////////////////////////////////////////////////////
-
-TextAttrsMgr::CSSTextAttr::
- CSSTextAttr(PRUint32 aIndex, nsIContent* aRootElm, nsIContent* aElm) :
- TTextAttr<nsString>(!aElm), mIndex(aIndex)
-{
- mIsRootDefined = GetValueFor(aRootElm, &mRootNativeValue);
-
- if (aElm)
- mIsDefined = GetValueFor(aElm, &mNativeValue);
-}
-
-bool
-TextAttrsMgr::CSSTextAttr::
- GetValueFor(nsIContent* aElm, nsString* aValue)
-{
- nsCOMPtr<nsIDOMCSSStyleDeclaration> currStyleDecl =
- nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aElm);
- if (!currStyleDecl)
- return false;
-
- NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName);
-
- nsresult rv = currStyleDecl->GetPropertyValue(cssName, *aValue);
- if (NS_FAILED(rv))
- return true;
-
- const char *cssValue = gCSSTextAttrsMap[mIndex].mCSSValue;
- if (cssValue != kAnyValue && !aValue->EqualsASCII(cssValue))
- return false;
-
- return true;
-}
-
-void
-TextAttrsMgr::CSSTextAttr::
- ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue)
-{
- const char* attrValue = gCSSTextAttrsMap[mIndex].mAttrValue;
- if (attrValue != kCopyValue) {
- nsAutoString formattedValue;
- AppendASCIItoUTF16(attrValue, formattedValue);
- nsAccUtils::SetAccAttr(aAttributes, *gCSSTextAttrsMap[mIndex].mAttrName,
- formattedValue);
- return;
- }
-
- nsAccUtils::SetAccAttr(aAttributes, *gCSSTextAttrsMap[mIndex].mAttrName,
- aValue);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
// BGColorTextAttr
////////////////////////////////////////////////////////////////////////////////
TextAttrsMgr::BGColorTextAttr::
BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
TTextAttr<nscolor>(!aFrame), mRootFrame(aRootFrame)
{
mIsRootDefined = GetColor(mRootFrame, &mRootNativeValue);
@@ -737,8 +656,109 @@ TextAttrsMgr::TextDecorTextAttr::
formattedStyle);
nsAutoString formattedColor;
StyleInfo::FormatColor(aValue.Color(), formattedColor);
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textLineThroughColor,
formattedColor);
}
}
+
+////////////////////////////////////////////////////////////////////////////////
+// TextPosTextAttr
+////////////////////////////////////////////////////////////////////////////////
+
+TextAttrsMgr::TextPosTextAttr::
+ TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
+ TTextAttr<TextPosValue>(!aFrame)
+{
+ mRootNativeValue = GetTextPosValue(aRootFrame);
+ mIsRootDefined = mRootNativeValue != eTextPosNone;
+
+ if (aFrame) {
+ mNativeValue = GetTextPosValue(aFrame);
+ mIsDefined = mNativeValue != eTextPosNone;
+ }
+}
+
+bool
+TextAttrsMgr::TextPosTextAttr::
+ GetValueFor(nsIContent* aContent, TextPosValue* aValue)
+{
+ nsIFrame* frame = aContent->GetPrimaryFrame();
+ if (frame) {
+ *aValue = GetTextPosValue(frame);
+ return *aValue != eTextPosNone;
+ }
+
+ return false;
+}
+
+void
+TextAttrsMgr::TextPosTextAttr::
+ ExposeValue(nsIPersistentProperties* aAttributes, const TextPosValue& aValue)
+{
+ switch (aValue) {
+ case eTextPosBaseline:
+ nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
+ NS_LITERAL_STRING("baseline"));
+ break;
+
+ case eTextPosSub:
+ nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
+ NS_LITERAL_STRING("sub"));
+ break;
+
+ case eTextPosSuper:
+ nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
+ NS_LITERAL_STRING("super"));
+ break;
+ }
+}
+
+TextAttrsMgr::TextPosValue
+TextAttrsMgr::TextPosTextAttr::
+ GetTextPosValue(nsIFrame* aFrame) const
+{
+ const nsStyleCoord& styleCoord = aFrame->GetStyleTextReset()->mVerticalAlign;
+ switch (styleCoord.GetUnit()) {
+ case eStyleUnit_Enumerated:
+ switch (styleCoord.GetIntValue()) {
+ case NS_STYLE_VERTICAL_ALIGN_BASELINE:
+ return eTextPosBaseline;
+ case NS_STYLE_VERTICAL_ALIGN_SUB:
+ return eTextPosSub;
+ case NS_STYLE_VERTICAL_ALIGN_SUPER:
+ return eTextPosSuper;
+
+ // No good guess for these:
+ // NS_STYLE_VERTICAL_ALIGN_TOP
+ // NS_STYLE_VERTICAL_ALIGN_TEXT_TOP
+ // NS_STYLE_VERTICAL_ALIGN_MIDDLE
+ // NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM
+ // NS_STYLE_VERTICAL_ALIGN_BOTTOM
+ // NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE
+ // Do not expose value of text-position attribute.
+
+ default:
+ break;
+ }
+ return eTextPosNone;
+
+ case eStyleUnit_Percent:
+ {
+ float percentValue = styleCoord.GetPercentValue();
+ return percentValue > 0 ?
+ eTextPosSuper :
+ (percentValue < 0 ? eTextPosSub : eTextPosBaseline);
+ }
+
+ case eStyleUnit_Coord:
+ {
+ nscoord coordValue = styleCoord.GetCoordValue();
+ return coordValue > 0 ?
+ eTextPosSuper :
+ (coordValue < 0 ? eTextPosSub : eTextPosBaseline);
+ }
+ }
+
+ return eTextPosNone;
+}
--- a/accessible/src/base/TextAttrs.h
+++ b/accessible/src/base/TextAttrs.h
@@ -102,21 +102,22 @@ public:
protected:
/**
* Calculates range (start and end offsets) of text where the text attributes
* are stretched. New offsets may be smaller if one of text attributes changes
* its value before or after the given offsets.
*
* @param aTextAttrArray [in] text attributes array
+ * @param aAttrArrayLen [in] text attributes array length
* @param aStartHTOffset [in, out] the start offset
* @param aEndHTOffset [in, out] the end offset
*/
class TextAttr;
- void GetRange(const nsTArray<TextAttr*>& aTextAttrArray,
+ void GetRange(TextAttr* aAttrArray[], PRUint32 aAttrArrayLen,
PRInt32* aStartHTOffset, PRInt32* aEndHTOffset);
private:
nsHyperTextAccessible* mHyperTextAcc;
bool mIncludeDefAttrs;
nsAccessible* mOffsetAcc;
@@ -152,17 +153,17 @@ protected:
* Base class to work with text attributes. See derived classes below.
*/
template<class T>
class TTextAttr : public TextAttr
{
public:
TTextAttr(bool aGetRootValue) : mGetRootValue(aGetRootValue) {}
- // ITextAttr
+ // TextAttr
virtual void Expose(nsIPersistentProperties* aAttributes,
bool aIncludeDefAttrValue)
{
if (mGetRootValue) {
if (mIsRootDefined)
ExposeValue(aAttributes, mRootNativeValue);
return;
}
@@ -238,37 +239,16 @@ protected:
private:
bool GetLang(nsIContent* aElm, nsAString& aLang);
nsCOMPtr<nsIContent> mRootContent;
};
/**
- * Class is used for the work with CSS based text attributes.
- */
- class CSSTextAttr : public TTextAttr<nsString>
- {
- public:
- CSSTextAttr(PRUint32 aIndex, nsIContent* aRootElm, nsIContent* aElm);
- virtual ~CSSTextAttr() { }
-
- protected:
-
- // TextAttr
- virtual bool GetValueFor(nsIContent* aElm, nsString* aValue);
- virtual void ExposeValue(nsIPersistentProperties* aAttributes,
- const nsString& aValue);
-
- private:
- PRInt32 mIndex;
- };
-
-
- /**
* Class is used for the work with 'background-color' text attribute.
*/
class BGColorTextAttr : public TTextAttr<nscolor>
{
public:
BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
virtual ~BGColorTextAttr() { }
@@ -430,14 +410,42 @@ protected:
protected:
// TextAttr
virtual bool GetValueFor(nsIContent* aElm, TextDecorValue* aValue);
virtual void ExposeValue(nsIPersistentProperties* aAttributes,
const TextDecorValue& aValue);
};
+ /**
+ * Class is used for the work with "text-position" text attribute.
+ */
+
+ enum TextPosValue {
+ eTextPosNone = 0,
+ eTextPosBaseline,
+ eTextPosSub,
+ eTextPosSuper
+ };
+
+ class TextPosTextAttr : public TTextAttr<TextPosValue>
+ {
+ public:
+ TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
+ virtual ~TextPosTextAttr() { }
+
+ protected:
+
+ // TextAttr
+ virtual bool GetValueFor(nsIContent* aElm, TextPosValue* aValue);
+ virtual void ExposeValue(nsIPersistentProperties* aAttributes,
+ const TextPosValue& aValue);
+
+ private:
+ TextPosValue GetTextPosValue(nsIFrame* aFrame) const;
+ };
+
}; // TextAttrMgr
} // namespace a11y
} // namespace mozilla
#endif
--- a/accessible/tests/mochitest/attributes/test_text.html
+++ b/accessible/tests/mochitest/attributes/test_text.html
@@ -176,16 +176,40 @@
attrs = {};
testTextAttrs(ID, 50, attrs, defAttrs, 50, 55);
tempElem = tempElem.nextSibling.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"text-position": gComputedStyle.verticalAlign};
testTextAttrs(ID, 55, attrs, defAttrs, 55, 64);
+ attrs = {};
+ testTextAttrs(ID, 64, attrs, defAttrs, 64, 69);
+
+ attrs = { "text-position": "super" };
+ testTextAttrs(ID, 69, attrs, defAttrs, 69, 84);
+
+ attrs = {};
+ testTextAttrs(ID, 84, attrs, defAttrs, 84, 89);
+
+ attrs = { "text-position": "sub" };
+ testTextAttrs(ID, 89, attrs, defAttrs, 89, 102);
+
+ attrs = {};
+ testTextAttrs(ID, 102, attrs, defAttrs, 102, 107);
+
+ attrs = { "text-position": "super" };
+ testTextAttrs(ID, 107, attrs, defAttrs, 107, 123);
+
+ attrs = {};
+ testTextAttrs(ID, 123, attrs, defAttrs, 123, 128);
+
+ attrs = { "text-position": "sub" };
+ testTextAttrs(ID, 128, attrs, defAttrs, 128, 142);
+
//////////////////////////////////////////////////////////////////////////
// area7
ID = "area7";
defAttrs = buildDefaultTextAttrs(ID, "12pt");
defAttrs["language"] = "en";
testDefaultTextAttrs(ID, defAttrs);
attrs = {"language": "ru"};
@@ -501,16 +525,21 @@
<body style="font-size: 12pt">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=345759"
title="Implement text attributes">
Mozilla Bug 345759
</a>
<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=473569"
+ title="Restrict text-position to allowed values">
+ Mozilla Bug 473569
+ </a>
+ <a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=473576"
title="font-family text attribute should expose actual font used">
Mozilla Bug 473576
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=523304"
title="expose text-underline-color and text-line-through-color text attributes">
Mozilla Bug 523304
@@ -544,17 +573,21 @@
<span style="color: green">Green</span>
<img src="../moz.png" alt="image"/>
<span style="color: red">Red</span>Normal
</p>
<p id="area6">
This <sup>sentence</sup> has the word
<span style="vertical-align:super;">sentence</span> in
<sub>superscript</sub> and
- <span style="vertical-align:sub;">subscript</span>
+ <span style="vertical-align:sub;">subscript</span> and
+ <span style="vertical-align:20%;">superscript 20%</span> and
+ <span style="vertical-align:-20%;">subscript 20%</span> and
+ <span style="vertical-align:20px;">superscript 20px</span> and
+ <span style="vertical-align:-20px;">subscript 20px</span>
</p>
<p lang="en" id="area7">
<span lang="ru">Привет</span>
<span style="background-color: blue">Blue BG color</span>
<span lang="de">Ich bin/Du bist</span>
<span lang="en">
Normal
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -371,41 +371,36 @@ PlacesViewBase.prototype = {
* @param aPopup
* The livemark container popup
* @param aStatus
* The livemark status
*/
_setLivemarkStatusMenuItem:
function PVB_setLivemarkStatusMenuItem(aPopup, aStatus) {
let statusMenuitem = aPopup._statusMenuitem;
- let stringId = "";
- if (aStatus == Ci.mozILivemark.STATUS_LOADING)
- stringId = "bookmarksLivemarkLoading";
- else if (aStatus == Ci.mozILivemark.STATUS_FAILED)
- stringId = "bookmarksLivemarkFailed";
-
- if (stringId && !statusMenuitem) {
+ if (!statusMenuitem) {
// Create the status menuitem and cache it in the popup object.
statusMenuitem = document.createElement("menuitem");
- statusMenuitem.setAttribute("livemarkStatus", stringId);
statusMenuitem.className = "livemarkstatus-menuitem";
- statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
statusMenuitem.setAttribute("disabled", true);
- aPopup.insertBefore(statusMenuitem, aPopup._startMarker.nextSibling);
aPopup._statusMenuitem = statusMenuitem;
}
- else if (stringId &&
- statusMenuitem.getAttribute("livemarkStatus") != stringId) {
+
+ if (aStatus == Ci.mozILivemark.STATUS_LOADING ||
+ aStatus == Ci.mozILivemark.STATUS_FAILED) {
// Status has changed, update the cached status menuitem.
+ let stringId = aStatus == Ci.mozILivemark.STATUS_LOADING ?
+ "bookmarksLivemarkLoading" : "bookmarksLivemarkFailed";
statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
+ if (aPopup._startMarker.nextSibling != statusMenuitem)
+ aPopup.insertBefore(statusMenuitem, aPopup._startMarker.nextSibling);
}
- else if (!stringId && statusMenuitem) {
+ else {
// The livemark has finished loading.
aPopup.removeChild(aPopup._statusMenuitem);
- aPopup._statusMenuitem = null;
}
},
toggleCutNode: function PVB_toggleCutNode(aNode, aValue) {
let elt = aNode._DOMElement;
if (elt) {
// We may get the popup for menus, but we need the menu itself.
if (elt.localName == "menupopup")
@@ -1012,19 +1007,20 @@ PlacesToolbar.prototype = {
if (aBefore)
this._rootElt.insertBefore(button, aBefore);
else
this._rootElt.appendChild(button);
},
_updateChevronPopupNodesVisibility:
function PT__updateChevronPopupNodesVisibility() {
- for (let i = 0; i < this._chevronPopup.childNodes.length; i++) {
- this._chevronPopup.childNodes[i].hidden =
- this._rootElt.childNodes[i].style.visibility != "hidden";
+ for (let i = 0, node = this._chevronPopup._startMarker.nextSibling;
+ node != this._chevronPopup._endMarker;
+ i++, node = node.nextSibling) {
+ node.hidden = this._rootElt.childNodes[i].style.visibility != "hidden";
}
},
_onChevronPopupShowing:
function PT__onChevronPopupShowing(aEvent) {
// Handle popupshowing only for the chevron popup, not for nested ones.
if (aEvent.target != this._chevronPopup)
return;
--- a/browser/config/mozconfigs/linux32/debug
+++ b/browser/config/mozconfigs/linux32/debug
@@ -13,8 +13,11 @@ export MOZILLA_OFFICIAL=1
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux32/nightly
+++ b/browser/config/mozconfigs/linux32/nightly
@@ -22,8 +22,11 @@ mk_add_options PROFILE_GEN_SCRIPT='$(PYT
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux32/release
+++ b/browser/config/mozconfigs/linux32/release
@@ -16,8 +16,11 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux64/debug
+++ b/browser/config/mozconfigs/linux64/debug
@@ -10,8 +10,11 @@ ac_add_options --enable-stdcxx-compat
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux64/nightly
+++ b/browser/config/mozconfigs/linux64/nightly
@@ -22,8 +22,11 @@ mk_add_options PROFILE_GEN_SCRIPT='$(PYT
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux64/release
+++ b/browser/config/mozconfigs/linux64/release
@@ -16,8 +16,11 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/macosx-universal/nightly
+++ b/browser/config/mozconfigs/macosx-universal/nightly
@@ -17,8 +17,11 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
mk_add_options MOZ_MAKE_FLAGS="-j4"
ac_add_options --with-macbundlename-prefix=Firefox
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/macosx-universal/release
+++ b/browser/config/mozconfigs/macosx-universal/release
@@ -12,8 +12,11 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/macosx32/debug
+++ b/browser/config/mozconfigs/macosx32/debug
@@ -5,8 +5,11 @@ ac_add_options --enable-signmar
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
ac_add_options --with-macbundlename-prefix=Firefox
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/macosx64/debug
+++ b/browser/config/mozconfigs/macosx64/debug
@@ -10,8 +10,11 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
ac_add_options --with-macbundlename-prefix=Firefox
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win32/debug
+++ b/browser/config/mozconfigs/win32/debug
@@ -3,8 +3,11 @@ ac_add_options --enable-trace-malloc
ac_add_options --enable-signmar
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
mk_add_options MOZ_MAKE_FLAGS=-j1
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win32/nightly
+++ b/browser/config/mozconfigs/win32/nightly
@@ -12,8 +12,11 @@ ac_add_options --enable-js-diagnostics
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
mk_add_options MOZ_MAKE_FLAGS=-j1
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win32/release
+++ b/browser/config/mozconfigs/win32/release
@@ -8,8 +8,11 @@ ac_add_options --enable-jemalloc
ac_add_options --enable-official-branding
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win64/debug
+++ b/browser/config/mozconfigs/win64/debug
@@ -4,8 +4,13 @@ ac_add_options --host=x86_64-pc-mingw32
ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
ac_add_options --enable-signmar
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
mk_add_options MOZ_MAKE_FLAGS=-j1
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
+
+. $topsrcdir/browser/config/mozconfigs/win64/vs2010-mozconfig
--- a/browser/config/mozconfigs/win64/nightly
+++ b/browser/config/mozconfigs/win64/nightly
@@ -13,8 +13,13 @@ ac_add_options --enable-signmar
ac_add_options --enable-js-diagnostics
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
mk_add_options MOZ_MAKE_FLAGS=-j1
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
+
+. $topsrcdir/browser/config/mozconfigs/win64/vs2010-mozconfig
new file mode 100644
--- /dev/null
+++ b/browser/config/mozconfigs/win64/vs2010-mozconfig
@@ -0,0 +1,16 @@
+export INCLUDE=/c/tools/msvs10/vc/include:/c/tools/msvs10/vc/atlmfc/include:/c/tools/sdks/v7.0/include:/c/tools/sdks/v7.0/include/atl:/c/tools/sdks/dx10/include
+export LIBPATH=/c/tools/msvs10/vc/lib/amd64:/c/tools/msvs10/vc/atlmfc/lib/amd64
+export LIB=/c/tools/msvs10/vc/lib/amd64:/c/tools/msvs10/vc/atlmfc/lib/amd64:/c/tools/sdks/v7.0/lib/x64:/c/tools/sdks/dx10/lib/x64
+export PATH="/c/tools/msvs10/Common7/IDE:/c/tools/msvs10/VC/BIN/amd64:/c/tools/msvs10/VC/BIN/x86_amd64:/c/tools/msvs10/VC/BIN:/c/tools/msvs10/Common7/Tools:/c/tools/msvs10/VC/VCPackages:${PATH}"
+export WIN32_REDIST_DIR=/c/tools/msvs10/VC/redist/x64/Microsoft.VC100.CRT
+
+# Use 32bit linker for PGO crash bug.
+# https://connect.microsoft.com/VisualStudio/feedback/details/686117/
+export LD=/c/tools/msvs10/VC/BIN/x86_amd64/link.exe
+
+
+mk_add_options "export LIB=$LIB"
+mk_add_options "export LIBPATH=$LIBPATH"
+mk_add_options "export PATH=$PATH"
+mk_add_options "export INCLUDE=$INCLUDE"
+mk_add_options "export WIN32_REDIST_DIR=$WIN32_REDIST_DIR"
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -445,51 +445,43 @@ PBBUILD_BIN = @PBBUILD@
SDP = @SDP@
NSINSTALL_BIN = @NSINSTALL_BIN@
WGET = @WGET@
RPMBUILD = @RPMBUILD@
ifdef MOZ_NATIVE_JPEG
JPEG_CFLAGS = @JPEG_CFLAGS@
JPEG_LIBS = @JPEG_LIBS@
-JPEG_REQUIRES =
else
JPEG_CFLAGS = @MOZ_JPEG_CFLAGS@
JPEG_LIBS = @MOZ_JPEG_LIBS@
-JPEG_REQUIRES = jpeg
endif
ifdef MOZ_NATIVE_ZLIB
ZLIB_CFLAGS = @ZLIB_CFLAGS@
ZLIB_LIBS = @ZLIB_LIBS@
-ZLIB_REQUIRES =
else
ZLIB_CFLAGS = @MOZ_ZLIB_CFLAGS@
MOZ_ZLIB_LIBS = @MOZ_ZLIB_LIBS@
-ZLIB_REQUIRES = zlib
endif
ifdef MOZ_NATIVE_BZ2
BZ2_CFLAGS = @BZ2_CFLAGS@
BZ2_LIBS = @BZ2_LIBS@
-BZ2_REQUIRES =
else
BZ2_CFLAGS = @MOZ_BZ2_CFLAGS@
BZ2_LIBS = @MOZ_BZ2_LIBS@
-BZ2_REQUIRES = libbz2
endif
ifdef MOZ_NATIVE_PNG
PNG_CFLAGS = @PNG_CFLAGS@
PNG_LIBS = @PNG_LIBS@
-PNG_REQUIRES =
else
PNG_CFLAGS = @MOZ_PNG_CFLAGS@
PNG_LIBS = @MOZ_PNG_LIBS@
-PNG_REQUIRES = png
endif
QCMS_LIBS = @QCMS_LIBS@
MOZ_HARFBUZZ_LIBS = @MOZ_HARFBUZZ_LIBS@
MOZ_GRAPHITE_LIBS = @MOZ_GRAPHITE_LIBS@
MOZ_GRAPHITE = @MOZ_GRAPHITE@
MOZ_OTS_LIBS = @MOZ_OTS_LIBS@
@@ -702,16 +694,18 @@ ANDROID_VERSION = @ANDROID_VERSION@
ANDROID_PACKAGE_NAME = @ANDROID_PACKAGE_NAME@
JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@
MOZ_INSTRUMENT_EVENT_LOOP = @MOZ_INSTRUMENT_EVENT_LOOP@
MOZ_SYSTEM_PLY = @MOZ_SYSTEM_PLY@
+MOZ_PACKAGE_JSSHELL = @MOZ_PACKAGE_JSSHELL@
+
# We only want to do the pymake sanity on Windows, other os's can cope
ifeq ($(HOST_OS_ARCH),WINNT)
# Ensure invariants between GNU Make and pymake
# Checked here since we want the sane error in a file that
# actually can be found regardless of path-style.
ifeq (_:,$(.PYMAKE)_$(findstring :,$(srcdir)))
$(error Windows-style srcdir being used with GNU make. Did you mean to run $(topsrcdir)/build/pymake/make.py instead? [see-also: https://developer.mozilla.org/en/Gmake_vs._Pymake])
endif
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1906,19 +1906,16 @@ echo-tier-dirs:
@$(foreach tier,$(TIERS),echo '$(tier):'; echo ' dirs: $(tier_$(tier)_dirs)'; echo ' staticdirs: $(tier_$(tier)_staticdirs)'; )
echo-dirs:
@echo $(DIRS)
echo-module:
@echo $(MODULE)
-echo-requires:
- @echo $(REQUIRES)
-
echo-depth-path:
@$(topsrcdir)/build/unix/print-depth-path.sh
echo-module-name:
@$(topsrcdir)/build/package/rpm/print-module-name.sh
echo-module-filelist:
@$(topsrcdir)/build/package/rpm/print-module-filelist.sh
@@ -2015,17 +2012,16 @@ endif
FREEZE_VARIABLES = \
CSRCS \
CPPSRCS \
EXPORTS \
XPIDLSRCS \
DIRS \
LIBRARY \
MODULE \
- REQUIRES \
SHORT_LIBNAME \
TIERS \
EXTRA_COMPONENTS \
EXTRA_PP_COMPONENTS \
$(NULL)
$(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
--- a/configure.in
+++ b/configure.in
@@ -8826,16 +8826,18 @@ AC_SUBST(VPX_ARM_ASM)
AC_SUBST(VPX_NEED_OBJ_INT_EXTRACT)
AC_SUBST(MOZ_INSTRUMENT_EVENT_LOOP)
AC_SUBST(LIBJPEG_TURBO_AS)
AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
AC_SUBST(LIBJPEG_TURBO_X86_ASM)
AC_SUBST(LIBJPEG_TURBO_X64_ASM)
AC_SUBST(LIBJPEG_TURBO_ARM_ASM)
+AC_SUBST(MOZ_PACKAGE_JSSHELL)
+
AC_MSG_CHECKING([for posix_fallocate])
AC_TRY_LINK([#define _XOPEN_SOURCE 600
#include <fcntl.h>],
[posix_fallocate(0, 0, 0);],
[ac_cv___posix_fallocate=true],
[ac_cv___posix_fallocate=false])
if test "$ac_cv___posix_fallocate" = true ; then
--- a/content/base/public/nsDOMFile.h
+++ b/content/base/public/nsDOMFile.h
@@ -54,16 +54,18 @@
#include "nsAutoPtr.h"
#include "mozilla/GuardObjects.h"
#include "mozilla/StandardInteger.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/indexedDB/FileInfo.h"
#include "mozilla/dom/indexedDB/FileManager.h"
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
+#include "nsWrapperCache.h"
+#include "nsCycleCollectionParticipant.h"
class nsIFile;
class nsIInputStream;
class nsIClassInfo;
class nsIBlobBuilder;
nsresult NS_NewBlobBuilder(nsISupports* *aSupports);
@@ -321,32 +323,48 @@ protected:
}
void* mData;
};
// Used when backed by a memory store
nsRefPtr<DataOwner> mDataOwner;
};
-class nsDOMFileList : public nsIDOMFileList
+class nsDOMFileList MOZ_FINAL : public nsIDOMFileList,
+ public nsWrapperCache
{
public:
- NS_DECL_ISUPPORTS
+ nsDOMFileList(nsISupports *aParent) : mParent(aParent)
+ {
+ SetIsProxy();
+ }
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMFileList)
+
NS_DECL_NSIDOMFILELIST
+ virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap);
+
+ nsISupports* GetParentObject()
+ {
+ return mParent;
+ }
+
+ void Disconnect()
+ {
+ mParent = nsnull;
+ }
+
bool Append(nsIDOMFile *aFile) { return mFiles.AppendObject(aFile); }
bool Remove(PRUint32 aIndex) { return mFiles.RemoveObjectAt(aIndex); }
void Clear() { return mFiles.Clear(); }
- nsIDOMFile* GetItemAt(PRUint32 aIndex)
- {
- return mFiles.SafeObjectAt(aIndex);
- }
-
static nsDOMFileList* FromSupports(nsISupports* aSupports)
{
#ifdef DEBUG
{
nsCOMPtr<nsIDOMFileList> list_qi = do_QueryInterface(aSupports);
// If this assertion fires the QI implementation for the object in
// question doesn't use the nsIDOMFileList pointer as the nsISupports
@@ -356,16 +374,17 @@ public:
}
#endif
return static_cast<nsDOMFileList*>(aSupports);
}
private:
nsCOMArray<nsIDOMFile> mFiles;
+ nsISupports *mParent;
};
class NS_STACK_CLASS nsDOMFileInternalUrlHolder {
public:
nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile, nsIPrincipal* aPrincipal
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
~nsDOMFileInternalUrlHolder();
nsAutoString mUrl;
--- a/content/base/public/nsIDOMFileList.idl
+++ b/content/base/public/nsIDOMFileList.idl
@@ -38,10 +38,11 @@
#include "domstubs.idl"
interface nsIDOMFile;
[scriptable, uuid(3bfef9fa-8ad3-4e49-bd62-d6cd75b29298)]
interface nsIDOMFileList : nsISupports
{
readonly attribute unsigned long length;
- nsIDOMFile item(in unsigned long index);
+ [getter,forward(getItemAt)] nsIDOMFile item(in unsigned long index);
+ [noscript,notxpcom,nostdcall] nsIDOMFile getItemAt(in unsigned long index);
};
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -62,16 +62,17 @@
#include "nsBlobProtocolHandler.h"
#include "nsStringStream.h"
#include "CheckedInt.h"
#include "nsJSUtils.h"
#include "mozilla/Preferences.h"
#include "plbase64.h"
#include "prmem.h"
+#include "dombindings.h"
using namespace mozilla;
using namespace mozilla::dom;
// XXXkhuey the input stream that we pass out of a DOMFile
// can outlive the actual DOMFile object. Thus, we must
// ensure that the buffer underlying the stream we get
// from NS_NewByteInputStream is held alive as long as the
@@ -602,37 +603,62 @@ nsDOMMemoryFile::GetInternalStream(nsIIn
return DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
}
////////////////////////////////////////////////////////////////////////////
// nsDOMFileList implementation
DOMCI_DATA(FileList, nsDOMFileList)
-NS_INTERFACE_MAP_BEGIN(nsDOMFileList)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMFileList)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMFileList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMFileList)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMFileList)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFileList)
NS_INTERFACE_MAP_ENTRY(nsIDOMFileList)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(FileList)
NS_INTERFACE_MAP_END
-NS_IMPL_ADDREF(nsDOMFileList)
-NS_IMPL_RELEASE(nsDOMFileList)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMFileList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMFileList)
+
+JSObject*
+nsDOMFileList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap)
+{
+ return mozilla::dom::binding::FileList::create(cx, scope, this, triedToWrap);
+}
+
+nsIDOMFile*
+nsDOMFileList::GetItemAt(PRUint32 aIndex)
+{
+ return mFiles.SafeObjectAt(aIndex);
+}
NS_IMETHODIMP
nsDOMFileList::GetLength(PRUint32* aLength)
{
*aLength = mFiles.Count();
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileList::Item(PRUint32 aIndex, nsIDOMFile **aFile)
{
- NS_IF_ADDREF(*aFile = GetItemAt(aIndex));
+ NS_IF_ADDREF(*aFile = nsDOMFileList::GetItemAt(aIndex));
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////
// nsDOMFileInternalUrlHolder implementation
nsDOMFileInternalUrlHolder::nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile,
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8460,17 +8460,18 @@ nsDocument::CreateTouch(nsIDOMWindow* aV
aForce));
return NS_OK;
}
NS_IMETHODIMP
nsDocument::CreateTouchList(nsIVariant* aPoints,
nsIDOMTouchList** aRetVal)
{
- nsRefPtr<nsDOMTouchList> retval = new nsDOMTouchList();
+ nsRefPtr<nsDOMTouchList> retval =
+ new nsDOMTouchList(static_cast<nsIDocument*>(this));
if (aPoints) {
PRUint16 type;
aPoints->GetDataType(&type);
if (type == nsIDataType::VTYPE_INTERFACE ||
type == nsIDataType::VTYPE_INTERFACE_IS) {
nsCOMPtr<nsISupports> data;
aPoints->GetAsISupports(getter_AddRefs(data));
nsCOMPtr<nsIDOMTouch> point = do_QueryInterface(data);
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2309,17 +2309,17 @@ nsGenericElement::GetElementsByClassName
return nsContentUtils::GetElementsByClassName(this, aClasses, aReturn);
}
NS_IMETHODIMP
nsGenericElement::GetClientRects(nsIDOMClientRectList** aResult)
{
*aResult = nsnull;
- nsRefPtr<nsClientRectList> rectList = new nsClientRectList();
+ nsRefPtr<nsClientRectList> rectList = new nsClientRectList(this);
nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
if (!frame) {
// display:none, perhaps? Return an empty list
*aResult = rectList.forget().get();
return NS_OK;
}
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -2494,17 +2494,18 @@ nsRange::GetBoundingClientRect(nsIDOMCli
NS_IMETHODIMP
nsRange::GetClientRects(nsIDOMClientRectList** aResult)
{
*aResult = nsnull;
if (!mStartParent)
return NS_OK;
- nsRefPtr<nsClientRectList> rectList = new nsClientRectList();
+ nsRefPtr<nsClientRectList> rectList =
+ new nsClientRectList(static_cast<nsIDOMRange*>(this));
if (!rectList)
return NS_ERROR_OUT_OF_MEMORY;
nsLayoutUtils::RectListBuilder builder(rectList);
CollectClientRects(&builder, this, mStartParent, mStartOffset,
mEndParent, mEndOffset);
--- a/content/events/src/nsDOMDataTransfer.cpp
+++ b/content/events/src/nsDOMDataTransfer.cpp
@@ -53,17 +53,30 @@
#include "nsIScriptableRegion.h"
#include "nsContentUtils.h"
#include "nsIContent.h"
#include "nsCRT.h"
#include "nsIScriptObjectPrincipal.h"
using namespace mozilla;
-NS_IMPL_CYCLE_COLLECTION_2(nsDOMDataTransfer, mDragTarget, mDragImage)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataTransfer)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMDataTransfer)
+ if (tmp->mFiles) {
+ tmp->mFiles->Disconnect();
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFiles)
+ }
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDragTarget)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDragImage)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMDataTransfer)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFiles)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDragTarget)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDragImage)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMDataTransfer)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMDataTransfer)
DOMCI_DATA(DataTransfer, nsDOMDataTransfer)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMDataTransfer)
NS_INTERFACE_MAP_ENTRY(nsIDOMDataTransfer)
@@ -230,17 +243,17 @@ NS_IMETHODIMP
nsDOMDataTransfer::GetFiles(nsIDOMFileList** aFileList)
{
*aFileList = nsnull;
if (mEventType != NS_DRAGDROP_DROP && mEventType != NS_DRAGDROP_DRAGDROP)
return NS_OK;
if (!mFiles) {
- mFiles = new nsDOMFileList();
+ mFiles = new nsDOMFileList(static_cast<nsIDOMDataTransfer*>(this));
NS_ENSURE_TRUE(mFiles, NS_ERROR_OUT_OF_MEMORY);
PRUint32 count = mItems.Length();
for (PRUint32 i = 0; i < count; i++) {
nsCOMPtr<nsIVariant> variant;
nsresult rv = MozGetDataAt(NS_ConvertUTF8toUTF16(kFileMime), i, getter_AddRefs(variant));
NS_ENSURE_SUCCESS(rv, rv);
--- a/content/events/src/nsDOMDataTransfer.h
+++ b/content/events/src/nsDOMDataTransfer.h
@@ -100,16 +100,23 @@ protected:
bool aCursorState,
bool aIsExternal,
bool aUserCancelled,
nsTArray<nsTArray<TransferItem> >& aItems,
nsIDOMElement* aDragImage,
PRUint32 aDragImageX,
PRUint32 aDragImageY);
+ ~nsDOMDataTransfer()
+ {
+ if (mFiles) {
+ mFiles->Disconnect();
+ }
+ }
+
static const char sEffects[8][9];
public:
void GetDragTarget(nsIDOMElement** aDragTarget)
{
*aDragTarget = mDragTarget;
NS_IF_ADDREF(*aDragTarget);
--- a/content/events/src/nsDOMNotifyPaintEvent.cpp
+++ b/content/events/src/nsDOMNotifyPaintEvent.cpp
@@ -98,17 +98,18 @@ nsDOMNotifyPaintEvent::GetBoundingClient
rect->SetLayoutRect(GetRegion().GetBounds());
return NS_OK;
}
NS_IMETHODIMP
nsDOMNotifyPaintEvent::GetClientRects(nsIDOMClientRectList** aResult)
{
- nsRefPtr<nsClientRectList> rectList = new nsClientRectList();
+ nsRefPtr<nsClientRectList> rectList =
+ new nsClientRectList(static_cast<nsIDOMEvent*>(static_cast<nsDOMEvent*>(this)));
if (!rectList)
return NS_ERROR_OUT_OF_MEMORY;
nsRegion r = GetRegion();
nsRegionRectIterator iter(r);
for (const nsRect* rgnRect = iter.Next(); rgnRect; rgnRect = iter.Next()) {
nsRefPtr<nsClientRect> rect = new nsClientRect();
if (!rect)
@@ -120,17 +121,18 @@ nsDOMNotifyPaintEvent::GetClientRects(ns
rectList.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsDOMNotifyPaintEvent::GetPaintRequests(nsIDOMPaintRequestList** aResult)
{
- nsRefPtr<nsPaintRequestList> requests = new nsPaintRequestList();
+ nsRefPtr<nsPaintRequestList> requests =
+ new nsPaintRequestList(static_cast<nsDOMEvent*>(this));
if (!requests)
return NS_ERROR_OUT_OF_MEMORY;
bool isTrusted = nsContentUtils::IsCallerTrustedForRead();
for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
if (!isTrusted &&
(mInvalidateRequests[i].mFlags & nsIFrame::INVALIDATE_CROSS_DOC))
continue;
--- a/content/events/src/nsDOMTouchEvent.cpp
+++ b/content/events/src/nsDOMTouchEvent.cpp
@@ -155,53 +155,56 @@ nsDOMTouch::Equals(nsIDOMTouch* aTouch)
aTouch->GetRadiusY(&radiusY);
return mRefPoint != aTouch->mRefPoint ||
(mForce != force) ||
(mRotationAngle != orientation) ||
(mRadius.x != radiusX) || (mRadius.y != radiusY);
}
// TouchList
-nsDOMTouchList::nsDOMTouchList(nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches)
-{
- mPoints.AppendElements(aTouches);
-}
DOMCI_DATA(TouchList, nsDOMTouchList)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTouchList)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMTouchList)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIDOMTouchList)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TouchList)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMTouchList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mPoints)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMTouchList)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMTouchList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mPoints)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMTouchList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMTouchList)
NS_IMETHODIMP
nsDOMTouchList::GetLength(PRUint32* aLength)
{
*aLength = mPoints.Length();
return NS_OK;
}
NS_IMETHODIMP
nsDOMTouchList::Item(PRUint32 aIndex, nsIDOMTouch** aRetVal)
{
- NS_IF_ADDREF(*aRetVal = mPoints.SafeElementAt(aIndex, nsnull));
+ NS_IF_ADDREF(*aRetVal = nsDOMTouchList::GetItemAt(aIndex));
return NS_OK;
}
NS_IMETHODIMP
nsDOMTouchList::IdentifiedTouch(PRInt32 aIdentifier, nsIDOMTouch** aRetVal)
{
*aRetVal = nsnull;
for (PRUint32 i = 0; i < mPoints.Length(); ++i) {
@@ -211,16 +214,22 @@ nsDOMTouchList::IdentifiedTouch(PRInt32
aIdentifier == identifier) {
point.swap(*aRetVal);
break;
}
}
return NS_OK;
}
+nsIDOMTouch*
+nsDOMTouchList::GetItemAt(PRUint32 aIndex)
+{
+ return mPoints.SafeElementAt(aIndex, nsnull);
+}
+
// TouchEvent
nsDOMTouchEvent::nsDOMTouchEvent(nsPresContext* aPresContext,
nsTouchEvent* aEvent)
: nsDOMUIEvent(aPresContext, aEvent ? aEvent :
new nsTouchEvent(false, 0, nsnull))
{
if (aEvent) {
@@ -317,19 +326,21 @@ nsDOMTouchEvent::GetTouches(nsIDOMTouchL
// for touchend events, remove any changed touches from the touches array
nsTArray<nsCOMPtr<nsIDOMTouch> > unchangedTouches;
nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
for (PRUint32 i = 0; i < touches.Length(); ++i) {
if (!touches[i]->mChanged) {
unchangedTouches.AppendElement(touches[i]);
}
}
- t = new nsDOMTouchList(unchangedTouches);
+ t = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
+ unchangedTouches);
} else {
- t = new nsDOMTouchList(touchEvent->touches);
+ t = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
+ touchEvent->touches);
}
mTouches = t;
return CallQueryInterface(mTouches, aTouches);
}
NS_IMETHODIMP
nsDOMTouchEvent::GetTargetTouches(nsIDOMTouchList** aTargetTouches)
{
@@ -349,17 +360,18 @@ nsDOMTouchEvent::GetTargetTouches(nsIDOM
if ((mEvent->message != NS_TOUCH_END &&
mEvent->message != NS_TOUCH_CANCEL) || !touches[i]->mChanged) {
nsIDOMEventTarget* targetPtr = touches[i]->GetTarget();
if (targetPtr == mEvent->target) {
targetTouches.AppendElement(touches[i]);
}
}
}
- mTargetTouches = new nsDOMTouchList(targetTouches);
+ mTargetTouches = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
+ targetTouches);
return CallQueryInterface(mTargetTouches, aTargetTouches);
}
NS_IMETHODIMP
nsDOMTouchEvent::GetChangedTouches(nsIDOMTouchList** aChangedTouches)
{
NS_ENSURE_ARG_POINTER(aChangedTouches);
NS_ENSURE_STATE(mEvent);
@@ -371,17 +383,18 @@ nsDOMTouchEvent::GetChangedTouches(nsIDO
nsTArray<nsCOMPtr<nsIDOMTouch> > changedTouches;
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
for (PRUint32 i = 0; i < touches.Length(); ++i) {
if (touches[i]->mChanged) {
changedTouches.AppendElement(touches[i]);
}
}
- mChangedTouches = new nsDOMTouchList(changedTouches);
+ mChangedTouches = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
+ changedTouches);
return CallQueryInterface(mChangedTouches, aChangedTouches);
}
NS_IMETHODIMP
nsDOMTouchEvent::GetAltKey(bool* aAltKey)
{
*aAltKey = static_cast<nsInputEvent*>(mEvent)->isAlt;
return NS_OK;
--- a/content/events/src/nsDOMTouchEvent.h
+++ b/content/events/src/nsDOMTouchEvent.h
@@ -36,16 +36,18 @@
* ***** END LICENSE BLOCK ***** */
#ifndef nsDOMTouchEvent_h_
#define nsDOMTouchEvent_h_
#include "nsDOMUIEvent.h"
#include "nsIDOMTouchEvent.h"
#include "nsString.h"
#include "nsTArray.h"
+#include "nsIDocument.h"
+#include "dombindings.h"
class nsDOMTouch : public nsIDOMTouch
{
public:
nsDOMTouch(nsIDOMEventTarget* aTarget,
PRInt32 aIdentifier,
PRInt32 aPageX,
PRInt32 aPageY,
@@ -122,37 +124,56 @@ protected:
nsIntPoint mPagePoint;
nsIntPoint mClientPoint;
nsIntPoint mScreenPoint;
nsIntPoint mRadius;
float mRotationAngle;
float mForce;
};
-class nsDOMTouchList : public nsIDOMTouchList
+class nsDOMTouchList MOZ_FINAL : public nsIDOMTouchList,
+ public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMTouchList)
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMTouchList)
NS_DECL_NSIDOMTOUCHLIST
- nsDOMTouchList() { }
- nsDOMTouchList(nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches);
-
+ nsDOMTouchList(nsISupports *aParent) : mParent(aParent)
+ {
+ SetIsProxy();
+ }
+ nsDOMTouchList(nsISupports *aParent,
+ nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches)
+ : mPoints(aTouches),
+ mParent(aParent)
+ {
+ SetIsProxy();
+ }
+
+ virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap)
+ {
+ return mozilla::dom::binding::TouchList::create(cx, scope, this,
+ triedToWrap);
+ }
+
+ nsISupports *GetParentObject()
+ {
+ return mParent;
+ }
+
void Append(nsIDOMTouch* aPoint)
{
mPoints.AppendElement(aPoint);
}
- nsIDOMTouch* GetItemAt(PRUint32 aIndex)
- {
- return mPoints.SafeElementAt(aIndex, nsnull);
- }
protected:
nsTArray<nsCOMPtr<nsIDOMTouch> > mPoints;
+ nsCOMPtr<nsISupports> mParent;
};
class nsDOMTouchEvent : public nsDOMUIEvent,
public nsIDOMTouchEvent
{
public:
nsDOMTouchEvent(nsPresContext* aPresContext, nsTouchEvent* aEvent);
virtual ~nsDOMTouchEvent();
--- a/content/events/src/nsPaintRequest.cpp
+++ b/content/events/src/nsPaintRequest.cpp
@@ -36,16 +36,17 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsPaintRequest.h"
#include "nsDOMClassInfoID.h"
#include "nsClientRect.h"
#include "nsIFrame.h"
+#include "nsContentUtils.h"
DOMCI_DATA(PaintRequest, nsPaintRequest)
NS_INTERFACE_TABLE_HEAD(nsPaintRequest)
NS_INTERFACE_TABLE1(nsPaintRequest, nsIDOMPaintRequest)
NS_INTERFACE_TABLE_TO_MAP_SEGUE
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PaintRequest)
NS_INTERFACE_MAP_END
@@ -78,31 +79,50 @@ nsPaintRequest::GetReason(nsAString& aRe
aResult.Truncate();
break;
}
return NS_OK;
}
DOMCI_DATA(PaintRequestList, nsPaintRequestList)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsPaintRequestList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPaintRequestList)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPaintRequestList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsPaintRequestList)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
NS_INTERFACE_TABLE_HEAD(nsPaintRequestList)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_TABLE1(nsPaintRequestList, nsIDOMPaintRequestList)
- NS_INTERFACE_TABLE_TO_MAP_SEGUE
+ NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsPaintRequestList)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PaintRequestList)
NS_INTERFACE_MAP_END
-NS_IMPL_ADDREF(nsPaintRequestList)
-NS_IMPL_RELEASE(nsPaintRequestList)
-
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPaintRequestList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPaintRequestList)
NS_IMETHODIMP
nsPaintRequestList::GetLength(PRUint32* aLength)
{
*aLength = mArray.Count();
return NS_OK;
}
NS_IMETHODIMP
nsPaintRequestList::Item(PRUint32 aIndex, nsIDOMPaintRequest** aReturn)
{
- NS_IF_ADDREF(*aReturn = GetItemAt(aIndex));
+ NS_IF_ADDREF(*aReturn = nsPaintRequestList::GetItemAt(aIndex));
return NS_OK;
}
+
+nsIDOMPaintRequest*
+nsPaintRequestList::GetItemAt(PRUint32 aIndex)
+{
+ return mArray.SafeObjectAt(aIndex);
+}
--- a/content/events/src/nsPaintRequest.h
+++ b/content/events/src/nsPaintRequest.h
@@ -37,17 +37,18 @@
* ***** END LICENSE BLOCK ***** */
#ifndef NSPAINTREQUEST_H_
#define NSPAINTREQUEST_H_
#include "nsIDOMPaintRequest.h"
#include "nsIDOMPaintRequestList.h"
#include "nsPresContext.h"
-#include "nsClientRect.h"
+#include "nsIDOMEvent.h"
+#include "dombindings.h"
class nsPaintRequest : public nsIDOMPaintRequest
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMPAINTREQUEST
nsPaintRequest() { mRequest.mFlags = 0; }
@@ -56,31 +57,43 @@ public:
{ mRequest = aRequest; }
private:
~nsPaintRequest() {}
nsInvalidateRequestList::Request mRequest;
};
-class nsPaintRequestList : public nsIDOMPaintRequestList
+class nsPaintRequestList MOZ_FINAL : public nsIDOMPaintRequestList,
+ public nsWrapperCache
{
public:
- nsPaintRequestList() {}
+ nsPaintRequestList(nsIDOMEvent *aParent) : mParent(aParent)
+ {
+ SetIsProxy();
+ }
- NS_DECL_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPaintRequestList)
NS_DECL_NSIDOMPAINTREQUESTLIST
- void Append(nsIDOMPaintRequest* aElement) { mArray.AppendObject(aElement); }
+ virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap)
+ {
+ return mozilla::dom::binding::PaintRequestList::create(cx, scope, this,
+ triedToWrap);
+ }
- nsIDOMPaintRequest* GetItemAt(PRUint32 aIndex)
+ nsISupports* GetParentObject()
{
- return mArray.SafeObjectAt(aIndex);
+ return mParent;
}
+ void Append(nsIDOMPaintRequest* aElement) { mArray.AppendObject(aElement); }
+
static nsPaintRequestList* FromSupports(nsISupports* aSupports)
{
#ifdef DEBUG
{
nsCOMPtr<nsIDOMPaintRequestList> list_qi = do_QueryInterface(aSupports);
// If this assertion fires the QI implementation for the object in
// question doesn't use the nsIDOMClientRectList pointer as the nsISupports
@@ -92,11 +105,12 @@ public:
return static_cast<nsPaintRequestList*>(aSupports);
}
private:
~nsPaintRequestList() {}
nsCOMArray<nsIDOMPaintRequest> mArray;
+ nsCOMPtr<nsIDOMEvent> mParent;
};
#endif /*NSPAINTREQUEST_H_*/
--- a/content/html/content/src/nsClientRect.cpp
+++ b/content/html/content/src/nsClientRect.cpp
@@ -36,16 +36,17 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsClientRect.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfoID.h"
#include "nsPresContext.h"
+#include "dombindings.h"
DOMCI_DATA(ClientRect, nsClientRect)
NS_INTERFACE_TABLE_HEAD(nsClientRect)
NS_INTERFACE_TABLE1(nsClientRect, nsIDOMClientRect)
NS_INTERFACE_TABLE_TO_MAP_SEGUE
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ClientRect)
NS_INTERFACE_MAP_END
@@ -97,40 +98,68 @@ NS_IMETHODIMP
nsClientRect::GetHeight(float* aResult)
{
*aResult = mHeight;
return NS_OK;
}
DOMCI_DATA(ClientRectList, nsClientRectList)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsClientRectList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsClientRectList)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsClientRectList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsClientRectList)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
NS_INTERFACE_TABLE_HEAD(nsClientRectList)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_TABLE1(nsClientRectList, nsIDOMClientRectList)
- NS_INTERFACE_TABLE_TO_MAP_SEGUE
+ NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsClientRectList)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ClientRectList)
NS_INTERFACE_MAP_END
-NS_IMPL_ADDREF(nsClientRectList)
-NS_IMPL_RELEASE(nsClientRectList)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsClientRectList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsClientRectList)
NS_IMETHODIMP
nsClientRectList::GetLength(PRUint32* aLength)
{
*aLength = mArray.Count();
return NS_OK;
}
NS_IMETHODIMP
nsClientRectList::Item(PRUint32 aIndex, nsIDOMClientRect** aReturn)
{
- NS_IF_ADDREF(*aReturn = GetItemAt(aIndex));
+ NS_IF_ADDREF(*aReturn = nsClientRectList::GetItemAt(aIndex));
return NS_OK;
}
+nsIDOMClientRect*
+nsClientRectList::GetItemAt(PRUint32 aIndex)
+{
+ return mArray.SafeObjectAt(aIndex);
+}
+
+JSObject*
+nsClientRectList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap)
+{
+ return mozilla::dom::binding::ClientRectList::create(cx, scope, this,
+ triedToWrap);
+}
+
static double
RoundFloat(double aValue)
{
return floor(aValue + 0.5);
}
void
nsClientRect::SetLayoutRect(const nsRect& aLayoutRect)
--- a/content/html/content/src/nsClientRect.h
+++ b/content/html/content/src/nsClientRect.h
@@ -39,16 +39,18 @@
#ifndef NSCLIENTRECT_H_
#define NSCLIENTRECT_H_
#include "nsIDOMClientRect.h"
#include "nsIDOMClientRectList.h"
#include "nsCOMArray.h"
#include "nsRect.h"
#include "nsCOMPtr.h"
+#include "nsWrapperCache.h"
+#include "nsCycleCollectionParticipant.h"
class nsClientRect : public nsIDOMClientRect
{
public:
NS_DECL_ISUPPORTS
nsClientRect();
void SetRect(float aX, float aY, float aWidth, float aHeight) {
@@ -59,32 +61,40 @@ public:
NS_DECL_NSIDOMCLIENTRECT
void SetLayoutRect(const nsRect& aLayoutRect);
protected:
float mX, mY, mWidth, mHeight;
};
-class nsClientRectList : public nsIDOMClientRectList
+class nsClientRectList MOZ_FINAL : public nsIDOMClientRectList,
+ public nsWrapperCache
{
public:
- nsClientRectList() {}
+ nsClientRectList(nsISupports *aParent) : mParent(aParent)
+ {
+ SetIsProxy();
+ }
- NS_DECL_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsClientRectList)
NS_DECL_NSIDOMCLIENTRECTLIST
- void Append(nsIDOMClientRect* aElement) { mArray.AppendObject(aElement); }
+ virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap);
- nsIDOMClientRect* GetItemAt(PRUint32 aIndex)
+ nsISupports* GetParentObject()
{
- return mArray.SafeObjectAt(aIndex);
+ return mParent;
}
+ void Append(nsIDOMClientRect* aElement) { mArray.AppendObject(aElement); }
+
static nsClientRectList* FromSupports(nsISupports* aSupports)
{
#ifdef DEBUG
{
nsCOMPtr<nsIDOMClientRectList> list_qi = do_QueryInterface(aSupports);
// If this assertion fires the QI implementation for the object in
// question doesn't use the nsIDOMClientRectList pointer as the nsISupports
@@ -96,11 +106,12 @@ public:
return static_cast<nsClientRectList*>(aSupports);
}
protected:
virtual ~nsClientRectList() {}
nsCOMArray<nsIDOMClientRect> mArray;
+ nsCOMPtr<nsISupports> mParent;
};
#endif /*NSCLIENTRECT_H_*/
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -582,16 +582,19 @@ nsHTMLInputElement::nsHTMLInputElement(a
// by default we don't have to show validity UI and so forth.
AddStatesSilently(NS_EVENT_STATE_ENABLED |
NS_EVENT_STATE_OPTIONAL |
NS_EVENT_STATE_VALID);
}
nsHTMLInputElement::~nsHTMLInputElement()
{
+ if (mFileList) {
+ mFileList->Disconnect();
+ }
DestroyImageLoadingContent();
FreeData();
}
void
nsHTMLInputElement::FreeData()
{
if (!IsSingleLineTextControl(false)) {
@@ -629,17 +632,20 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mFiles)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFileList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLInputElement,
nsGenericHTMLFormElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mControllers)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mFiles)
- NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFileList);
+ if (tmp->mFileList) {
+ tmp->mFileList->Disconnect();
+ tmp->mFileList = nsnull;
+ }
//XXX should unlink more?
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ADDREF_INHERITED(nsHTMLInputElement, nsGenericElement)
NS_IMPL_RELEASE_INHERITED(nsHTMLInputElement, nsGenericElement)
DOMCI_NODE_DATA(HTMLInputElement, nsHTMLInputElement)
@@ -2768,17 +2774,17 @@ nsHTMLInputElement::GetFiles(nsIDOMFileL
{
*aFileList = nsnull;
if (mType != NS_FORM_INPUT_FILE) {
return NS_OK;
}
if (!mFileList) {
- mFileList = new nsDOMFileList();
+ mFileList = new nsDOMFileList(static_cast<nsIContent*>(this));
if (!mFileList) return NS_ERROR_OUT_OF_MEMORY;
UpdateFileList();
}
NS_ADDREF(*aFileList = mFileList);
return NS_OK;
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -32,19 +32,16 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-#include "nsISeekableStream.h"
-#include "nsClassHashtable.h"
-#include "nsTArray.h"
#include "nsBuiltinDecoder.h"
#include "nsBuiltinDecoderReader.h"
#include "nsBuiltinDecoderStateMachine.h"
#include "VideoUtils.h"
#include "mozilla/mozalloc.h"
#include "mozilla/StandardInteger.h"
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -35,26 +35,20 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#if !defined(nsBuiltinDecoderReader_h_)
#define nsBuiltinDecoderReader_h_
#include <nsDeque.h>
-#include "Layers.h"
#include "ImageLayers.h"
-#include "nsClassHashtable.h"
-#include "mozilla/TimeStamp.h"
#include "nsSize.h"
-#include "nsRect.h"
#include "mozilla/ReentrantMonitor.h"
-class nsBuiltinDecoderStateMachine;
-
// Stores info relevant to presenting media frames.
class nsVideoInfo {
public:
nsVideoInfo()
: mAudioRate(0),
mAudioChannels(0),
mDisplay(0,0),
mStereoMode(mozilla::layers::STEREO_MODE_MONO),
--- a/content/media/nsMediaDecoder.cpp
+++ b/content/media/nsMediaDecoder.cpp
@@ -34,30 +34,18 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsMediaDecoder.h"
#include "MediaResource.h"
-#include "prlog.h"
-#include "prmem.h"
-#include "nsIFrame.h"
-#include "nsIDocument.h"
-#include "nsThreadUtils.h"
-#include "nsIDOMHTMLMediaElement.h"
-#include "nsNetUtil.h"
#include "nsHTMLMediaElement.h"
-#include "gfxContext.h"
-#include "nsPresContext.h"
#include "nsDOMError.h"
-#include "nsDisplayList.h"
-#include "nsSVGEffects.h"
-#include "VideoUtils.h"
using namespace mozilla;
// Number of milliseconds between progress events as defined by spec
static const PRUint32 PROGRESS_MS = 350;
// Number of milliseconds of no data before a stall event is fired as defined by spec
static const PRUint32 STALL_MS = 3000;
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -33,32 +33,26 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#if !defined(nsMediaDecoder_h_)
#define nsMediaDecoder_h_
-#include "mozilla/XPCOM.h"
-
-#include "nsIPrincipal.h"
-#include "nsSize.h"
-#include "prlog.h"
-#include "gfxContext.h"
-#include "gfxRect.h"
-#include "nsITimer.h"
#include "ImageLayers.h"
#include "mozilla/ReentrantMonitor.h"
-#include "nsIMemoryReporter.h"
#include "VideoFrameContainer.h"
class nsHTMLMediaElement;
class nsIStreamListener;
class nsTimeRanges;
+class nsIMemoryReporter;
+class nsIPrincipal;
+class nsITimer;
namespace mozilla {
class MediaResource;
}
// The size to use for audio data frames in MozAudioAvailable events.
// This value is per channel, and is chosen to give ~43 fps of events,
// for example, 44100 with 2 channels, 2*1024 = 2048.
--- a/content/media/wave/nsWaveReader.cpp
+++ b/content/media/wave/nsWaveReader.cpp
@@ -31,17 +31,16 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsError.h"
-#include "nsBuiltinDecoderStateMachine.h"
#include "nsBuiltinDecoder.h"
#include "MediaResource.h"
#include "nsWaveReader.h"
#include "nsTimeRanges.h"
#include "VideoUtils.h"
#include "mozilla/StandardInteger.h"
--- a/content/media/wave/nsWaveReader.h
+++ b/content/media/wave/nsWaveReader.h
@@ -35,17 +35,18 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#if !defined(nsWaveReader_h_)
#define nsWaveReader_h_
#include "nsBuiltinDecoderReader.h"
-class nsMediaDecoder;
+class nsBuiltinDecoder;
+class nsTimeRanges;
class nsWaveReader : public nsBuiltinDecoderReader
{
public:
nsWaveReader(nsBuiltinDecoder* aDecoder);
~nsWaveReader();
virtual nsresult Init(nsBuiltinDecoderReader* aCloneDonor);
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -36,20 +36,25 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsError.h"
#include "nsBuiltinDecoderStateMachine.h"
#include "nsBuiltinDecoder.h"
#include "MediaResource.h"
#include "nsWebMReader.h"
+#include "nsWebMBufferedParser.h"
#include "VideoUtils.h"
#include "nsTimeRanges.h"
#include "mozilla/Preferences.h"
+#define VPX_DONT_DEFINE_STDINT_TYPES
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_decoder.h"
+
using namespace mozilla;
using namespace mozilla::layers;
// Un-comment to enable logging of seek bisections.
//#define SEEK_LOGGING
#ifdef PR_LOGGING
extern PRLogModuleInfo* gBuiltinDecoderLog;
--- a/content/media/webm/nsWebMReader.h
+++ b/content/media/webm/nsWebMReader.h
@@ -38,31 +38,29 @@
* ***** END LICENSE BLOCK ***** */
#if !defined(nsWebMReader_h_)
#define nsWebMReader_h_
#include "mozilla/StandardInteger.h"
#include "nsDeque.h"
#include "nsBuiltinDecoderReader.h"
-#include "nsWebMBufferedParser.h"
#include "nsAutoRef.h"
#include "nestegg/nestegg.h"
#define VPX_DONT_DEFINE_STDINT_TYPES
-#include "vpx/vpx_decoder.h"
-#include "vpx/vp8dx.h"
+#include "vpx/vpx_codec.h"
#ifdef MOZ_TREMOR
#include "tremor/ivorbiscodec.h"
#else
#include "vorbis/codec.h"
#endif
-class nsMediaDecoder;
+class nsWebMBufferedState;
// Holds a nestegg_packet, and its file offset. This is needed so we
// know the offset in the file we've played up to, in order to calculate
// whether it's likely we can play through to the end without needing
// to stop to buffer, given the current download rate.
class NesteggPacketHolder {
public:
NesteggPacketHolder(nestegg_packet* aPacket, PRInt64 aOffset)
--- a/content/svg/content/src/DOMSVGLengthList.cpp
+++ b/content/svg/content/src/DOMSVGLengthList.cpp
@@ -35,16 +35,18 @@
* ***** END LICENSE BLOCK ***** */
#include "nsSVGElement.h"
#include "DOMSVGLengthList.h"
#include "DOMSVGLength.h"
#include "nsDOMError.h"
#include "SVGAnimatedLengthList.h"
#include "nsCOMPtr.h"
+#include "nsContentUtils.h"
+#include "dombindings.h"
// See the comment in this file's header.
// local helper functions
namespace {
using mozilla::DOMSVGLength;
@@ -67,38 +69,51 @@ namespace mozilla {
// We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
// clear our DOMSVGAnimatedLengthList's weak ref to us to be safe. (The other
// option would be to not unlink and rely on the breaking of the other edges in
// the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGLengthList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGLengthList)
// No need to null check tmp - script/SMIL can't detach us from mAList
( tmp->IsAnimValList() ? tmp->mAList->mAnimVal : tmp->mAList->mBaseVal ) = nsnull;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGLengthList)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGLengthList)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGLengthList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGLengthList)
} // namespace mozilla
DOMCI_DATA(SVGLengthList, mozilla::DOMSVGLengthList)
namespace mozilla {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGLengthList)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLengthList)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGLengthList)
NS_INTERFACE_MAP_END
+JSObject*
+DOMSVGLengthList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap)
+{
+ return mozilla::dom::binding::SVGLengthList::create(cx, scope, this,
+ triedToWrap);
+}
nsIDOMSVGLength*
-DOMSVGLengthList::GetItemWithoutAddRef(PRUint32 aIndex)
+DOMSVGLengthList::GetItemAt(PRUint32 aIndex)
{
if (IsAnimValList()) {
Element()->FlushAnimations();
}
if (aIndex < Length()) {
EnsureItemAt(aIndex);
return mItems[aIndex];
}
@@ -215,17 +230,17 @@ DOMSVGLengthList::Initialize(nsIDOMSVGLe
Clear();
return InsertItemBefore(newItem, 0, _retval);
}
NS_IMETHODIMP
DOMSVGLengthList::GetItem(PRUint32 index,
nsIDOMSVGLength **_retval)
{
- *_retval = GetItemWithoutAddRef(index);
+ *_retval = GetItemAt(index);
if (!*_retval) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
NS_ADDREF(*_retval);
return NS_OK;
}
NS_IMETHODIMP
--- a/content/svg/content/src/DOMSVGLengthList.h
+++ b/content/svg/content/src/DOMSVGLengthList.h
@@ -64,29 +64,32 @@ class DOMSVGLength;
* DOMSVGLength. We are a friend of DOMSVGAnimatedLengthList, and are
* responsible for nulling out our DOMSVGAnimatedLengthList's pointer to us
* when we die, essentially making its pointer to us a weak pointer. Similarly,
* our DOMSVGLength items are friends of us and responsible for nulling out our
* pointers to them.
*
* Our DOM items are created lazily on demand as and when script requests them.
*/
-class DOMSVGLengthList : public nsIDOMSVGLengthList
+class DOMSVGLengthList : public nsIDOMSVGLengthList,
+ public nsWrapperCache
{
friend class DOMSVGLength;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGLengthList)
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGLengthList)
NS_DECL_NSIDOMSVGLENGTHLIST
DOMSVGLengthList(DOMSVGAnimatedLengthList *aAList,
const SVGLengthList &aInternalList)
: mAList(aAList)
{
+ SetIsProxy();
+
// aInternalList must be passed in explicitly because we can't use
// InternalList() here. (Because it depends on IsAnimValList, which depends
// on this object having been assigned to aAList's mBaseVal or mAnimVal,
// which hasn't happend yet.)
InternalListLengthWillChange(aInternalList.Length()); // Sync mItems
}
@@ -94,29 +97,35 @@ public:
// Our mAList's weak ref to us must be nulled out when we die. If GC has
// unlinked us using the cycle collector code, then that has already
// happened, and mAList is null.
if (mAList) {
( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nsnull;
}
};
+ virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap);
+
+ nsISupports* GetParentObject()
+ {
+ return static_cast<nsIContent*>(Element());
+ }
+
/**
* This will normally be the same as InternalList().Length(), except if we've
* hit OOM in which case our length will be zero.
*/
PRUint32 Length() const {
NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
mItems.Length() == InternalList().Length(),
"DOM wrapper's list length is out of sync");
return mItems.Length();
}
- nsIDOMSVGLength* GetItemWithoutAddRef(PRUint32 aIndex);
-
/// Called to notify us to syncronize our length and detach excess items.
void InternalListLengthWillChange(PRUint32 aNewLength);
private:
nsSVGElement* Element() const {
return mAList->mElement;
}
--- a/content/svg/content/src/DOMSVGNumberList.cpp
+++ b/content/svg/content/src/DOMSVGNumberList.cpp
@@ -35,16 +35,18 @@
* ***** END LICENSE BLOCK ***** */
#include "nsSVGElement.h"
#include "DOMSVGNumberList.h"
#include "DOMSVGNumber.h"
#include "nsDOMError.h"
#include "SVGAnimatedNumberList.h"
#include "nsCOMPtr.h"
+#include "nsContentUtils.h"
+#include "dombindings.h"
// See the comment in this file's header.
namespace mozilla {
// local helper functions
namespace {
@@ -67,38 +69,52 @@ void UpdateListIndicesFromIndex(nsTArray
// We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
// clear our DOMSVGAnimatedNumberList's weak ref to us to be safe. (The other
// option would be to not unlink and rely on the breaking of the other edges in
// the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumberList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumberList)
// No need to null check tmp - script/SMIL can't detach us from mAList
( tmp->IsAnimValList() ? tmp->mAList->mAnimVal : tmp->mAList->mBaseVal ) = nsnull;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumberList)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGNumberList)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGNumberList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGNumberList)
} // namespace mozilla
DOMCI_DATA(SVGNumberList, mozilla::DOMSVGNumberList)
namespace mozilla {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGNumberList)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGNumberList)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGNumberList)
NS_INTERFACE_MAP_END
+JSObject*
+DOMSVGNumberList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap)
+{
+ return mozilla::dom::binding::SVGNumberList::create(cx, scope, this,
+ triedToWrap);
+}
+
nsIDOMSVGNumber*
-DOMSVGNumberList::GetItemWithoutAddRef(PRUint32 aIndex)
+DOMSVGNumberList::GetItemAt(PRUint32 aIndex)
{
if (IsAnimValList()) {
Element()->FlushAnimations();
}
if (aIndex < Length()) {
EnsureItemAt(aIndex);
return mItems[aIndex];
}
@@ -215,17 +231,17 @@ DOMSVGNumberList::Initialize(nsIDOMSVGNu
Clear();
return InsertItemBefore(newItem, 0, _retval);
}
NS_IMETHODIMP
DOMSVGNumberList::GetItem(PRUint32 index,
nsIDOMSVGNumber **_retval)
{
- *_retval = GetItemWithoutAddRef(index);
+ *_retval = GetItemAt(index);
if (!*_retval) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
NS_ADDREF(*_retval);
return NS_OK;
}
NS_IMETHODIMP
--- a/content/svg/content/src/DOMSVGNumberList.h
+++ b/content/svg/content/src/DOMSVGNumberList.h
@@ -63,29 +63,32 @@ class DOMSVGNumber;
* DOMSVGNumber. We are a friend of DOMSVGAnimatedNumberList, and are
* responsible for nulling out our DOMSVGAnimatedNumberList's pointer to us
* when we die, essentially making its pointer to us a weak pointer. Similarly,
* our DOMSVGNumber items are friends of us and responsible for nulling out our
* pointers to them.
*
* Our DOM items are created lazily on demand as and when script requests them.
*/
-class DOMSVGNumberList : public nsIDOMSVGNumberList
+class DOMSVGNumberList : public nsIDOMSVGNumberList,
+ public nsWrapperCache
{
friend class DOMSVGNumber;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGNumberList)
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGNumberList)
NS_DECL_NSIDOMSVGNUMBERLIST
DOMSVGNumberList(DOMSVGAnimatedNumberList *aAList,
const SVGNumberList &aInternalList)
: mAList(aAList)
{
+ SetIsProxy();
+
// aInternalList must be passed in explicitly because we can't use
// InternalList() here. (Because it depends on IsAnimValList, which depends
// on this object having been assigned to aAList's mBaseVal or mAnimVal,
// which hasn't happend yet.)
InternalListLengthWillChange(aInternalList.Length()); // Sync mItems
}
@@ -93,29 +96,35 @@ public:
// Our mAList's weak ref to us must be nulled out when we die. If GC has
// unlinked us using the cycle collector code, then that has already
// happened, and mAList is null.
if (mAList) {
( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nsnull;
}
}
+ virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap);
+
+ nsISupports* GetParentObject()
+ {
+ return static_cast<nsIContent*>(Element());
+ }
+
/**
* This will normally be the same as InternalList().Length(), except if we've
* hit OOM in which case our length will be zero.
*/
PRUint32 Length() const {
NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
mItems.Length() == InternalList().Length(),
"DOM wrapper's list length is out of sync");
return mItems.Length();
}
- nsIDOMSVGNumber* GetItemWithoutAddRef(PRUint32 aIndex);
-
/// Called to notify us to syncronize our length and detach excess items.
void InternalListLengthWillChange(PRUint32 aNewLength);
private:
nsSVGElement* Element() const {
return mAList->mElement;
}
--- a/content/svg/content/src/DOMSVGPathSegList.cpp
+++ b/content/svg/content/src/DOMSVGPathSegList.cpp
@@ -37,34 +37,49 @@
#include "nsSVGElement.h"
#include "DOMSVGPathSegList.h"
#include "DOMSVGPathSeg.h"
#include "nsDOMError.h"
#include "SVGAnimatedPathSegList.h"
#include "nsCOMPtr.h"
#include "nsSVGAttrTearoffTable.h"
#include "SVGPathSegUtils.h"
+#include "dombindings.h"
+#include "nsContentUtils.h"
// See the comment in this file's header.
namespace mozilla {
static nsSVGAttrTearoffTable<void, DOMSVGPathSegList>
sSVGPathSegListTearoffTable;
-NS_SVG_VAL_IMPL_CYCLE_COLLECTION(DOMSVGPathSegList, mElement)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPathSegList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSegList)
+ // No unlinking of mElement, we'd need to null out the value pointer (the
+ // object it points to is held by the element) and null-check it everywhere.
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSegList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mElement, nsIContent)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPathSegList)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGPathSegList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGPathSegList)
} // namespace mozilla
DOMCI_DATA(SVGPathSegList, mozilla::DOMSVGPathSegList)
namespace mozilla {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGPathSegList)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGPathSegList)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPathSegList)
NS_INTERFACE_MAP_END
/* static */ already_AddRefed<DOMSVGPathSegList>
DOMSVGPathSegList::GetDOMWrapper(void *aList,
@@ -92,18 +107,26 @@ DOMSVGPathSegList::~DOMSVGPathSegList()
// There are now no longer any references to us held by script or list items.
// Note we must use GetAnimValKey/GetBaseValKey here, NOT InternalList()!
void *key = mIsAnimValList ?
InternalAList().GetAnimValKey() :
InternalAList().GetBaseValKey();
sSVGPathSegListTearoffTable.RemoveTearoff(key);
}
+JSObject*
+DOMSVGPathSegList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap)
+{
+ return mozilla::dom::binding::SVGPathSegList::create(cx, scope, this,
+ triedToWrap);
+}
+
nsIDOMSVGPathSeg*
-DOMSVGPathSegList::GetItemWithoutAddRef(PRUint32 aIndex)
+DOMSVGPathSegList::GetItemAt(PRUint32 aIndex)
{
if (IsAnimValList()) {
Element()->FlushAnimations();
}
if (aIndex < Length()) {
EnsureItemAt(aIndex);
return ItemAt(aIndex);
}
@@ -322,17 +345,17 @@ DOMSVGPathSegList::Initialize(nsIDOMSVGP
Clear();
return InsertItemBefore(aNewItem, 0, _retval);
}
NS_IMETHODIMP
DOMSVGPathSegList::GetItem(PRUint32 aIndex,
nsIDOMSVGPathSeg **_retval)
{
- *_retval = GetItemWithoutAddRef(aIndex);
+ *_retval = GetItemAt(aIndex);
if (!*_retval) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
NS_ADDREF(*_retval);
return NS_OK;
}
NS_IMETHODIMP
--- a/content/svg/content/src/DOMSVGPathSegList.h
+++ b/content/svg/content/src/DOMSVGPathSegList.h
@@ -73,25 +73,34 @@ class SVGAnimatedPathSegList;
* DOMSVGAnimatedLengthList) is contained in this class.
*
* This class is strongly intertwined with DOMSVGPathSeg. Our DOMSVGPathSeg
* items are friends of us and responsible for nulling out our pointers to
* them when they die.
*
* Our DOM items are created lazily on demand as and when script requests them.
*/
-class DOMSVGPathSegList : public nsIDOMSVGPathSegList
+class DOMSVGPathSegList : public nsIDOMSVGPathSegList,
+ public nsWrapperCache
{
friend class DOMSVGPathSeg;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGPathSegList)
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPathSegList)
NS_DECL_NSIDOMSVGPATHSEGLIST
+ virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap);
+
+ nsISupports* GetParentObject()
+ {
+ return static_cast<nsIContent*>(mElement);
+ }
+
/**
* Factory method to create and return a DOMSVGPathSegList wrapper
* for a given internal SVGPathData object. The factory takes care
* of caching the object that it returns so that the same object can be
* returned for the given SVGPathData each time it is requested.
* The cached object is only removed from the cache when it is destroyed due
* to there being no more references to it or to any of its descendant
* objects. If that happens, any subsequent call requesting the DOM wrapper
@@ -123,18 +132,16 @@ public:
*/
PRUint32 Length() const {
NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
mItems.Length() == InternalList().CountItems(),
"DOM wrapper's list length is out of sync");
return mItems.Length();
}
- nsIDOMSVGPathSeg* GetItemWithoutAddRef(PRUint32 aIndex);
-
/**
* WATCH OUT! If you add code to call this on a baseVal wrapper, then you
* must also call it on the animVal wrapper too if necessary!! See other
* callers!
*
* Called by internal code to notify us when we need to sync the length of
* this DOM list with its internal list. This is called immediately prior to
* the length of the internal list being changed so that any DOM list items
@@ -159,16 +166,18 @@ private:
/**
* Only our static GetDOMWrapper() factory method may create objects of our
* type.
*/
DOMSVGPathSegList(nsSVGElement *aElement, bool aIsAnimValList)
: mElement(aElement)
, mIsAnimValList(aIsAnimValList)
{
+ SetIsProxy();
+
InternalListWillChangeTo(InternalList()); // Sync mItems
}
~DOMSVGPathSegList();
nsSVGElement* Element() {
return mElement.get();
}
--- a/content/svg/content/src/DOMSVGPointList.cpp
+++ b/content/svg/content/src/DOMSVGPointList.cpp
@@ -36,16 +36,18 @@
#include "nsSVGElement.h"
#include "DOMSVGPointList.h"
#include "DOMSVGPoint.h"
#include "nsDOMError.h"
#include "SVGAnimatedPointList.h"
#include "nsCOMPtr.h"
#include "nsSVGAttrTearoffTable.h"
+#include "nsContentUtils.h"
+#include "dombindings.h"
// See the comment in this file's header.
// local helper functions
namespace {
using mozilla::DOMSVGPoint;
@@ -64,26 +66,39 @@ UpdateListIndicesFromIndex(nsTArray<DOMS
} // namespace
namespace mozilla {
static nsSVGAttrTearoffTable<void, DOMSVGPointList>
sSVGPointListTearoffTable;
-NS_SVG_VAL_IMPL_CYCLE_COLLECTION(DOMSVGPointList, mElement)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPointList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPointList)
+ // No unlinking of mElement, we'd need to null out the value pointer (the
+ // object it points to is held by the element) and null-check it everywhere.
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPointList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mElement, nsIContent)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPointList)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGPointList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGPointList)
} // namespace mozilla
DOMCI_DATA(SVGPointList, mozilla::DOMSVGPointList)
namespace mozilla {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGPointList)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGPointList)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPointList)
NS_INTERFACE_MAP_END
/* static */ already_AddRefed<DOMSVGPointList>
DOMSVGPointList::GetDOMWrapper(void *aList,
@@ -111,18 +126,26 @@ DOMSVGPointList::~DOMSVGPointList()
// There are now no longer any references to us held by script or list items.
// Note we must use GetAnimValKey/GetBaseValKey here, NOT InternalList()!
void *key = mIsAnimValList ?
InternalAList().GetAnimValKey() :
InternalAList().GetBaseValKey();
sSVGPointListTearoffTable.RemoveTearoff(key);
}
+JSObject*
+DOMSVGPointList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap)
+{
+ return mozilla::dom::binding::SVGPointList::create(cx, scope, this,
+ triedToWrap);
+}
+
nsIDOMSVGPoint*
-DOMSVGPointList::GetItemWithoutAddRef(PRUint32 aIndex)
+DOMSVGPointList::GetItemAt(PRUint32 aIndex)
{
if (IsAnimValList()) {
Element()->FlushAnimations();
}
if (aIndex < Length()) {
EnsureItemAt(aIndex);
return mItems[aIndex];
}
@@ -266,17 +289,17 @@ DOMSVGPointList::Initialize(nsIDOMSVGPoi
Clear();
return InsertItemBefore(aNewItem, 0, _retval);
}
NS_IMETHODIMP
DOMSVGPointList::GetItem(PRUint32 aIndex,
nsIDOMSVGPoint **_retval)
{
- *_retval = GetItemWithoutAddRef(aIndex);
+ *_retval = GetItemAt(aIndex);
if (!*_retval) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
NS_ADDREF(*_retval);
return NS_OK;
}
NS_IMETHODIMP
--- a/content/svg/content/src/DOMSVGPointList.h
+++ b/content/svg/content/src/DOMSVGPointList.h
@@ -73,25 +73,34 @@ class SVGAnimatedPointList;
* DOMSVGAnimatedLengthList) is contained in this class.
*
* This class is strongly intertwined with DOMSVGPoint. Our DOMSVGPoint
* items are friends of us and responsible for nulling out our pointers to
* them when they die.
*
* Our DOM items are created lazily on demand as and when script requests them.
*/
-class DOMSVGPointList : public nsIDOMSVGPointList
+class DOMSVGPointList : public nsIDOMSVGPointList,
+ public nsWrapperCache
{
friend class DOMSVGPoint;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGPointList)
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPointList)
NS_DECL_NSIDOMSVGPOINTLIST
+ virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap);
+
+ nsISupports* GetParentObject()
+ {
+ return static_cast<nsIContent*>(mElement);
+ }
+
/**
* Factory method to create and return a DOMSVGPointList wrapper
* for a given internal SVGPointList object. The factory takes care
* of caching the object that it returns so that the same object can be
* returned for the given SVGPointList each time it is requested.
* The cached object is only removed from the cache when it is destroyed due
* to there being no more references to it or to any of its descendant
* objects. If that happens, any subsequent call requesting the DOM wrapper
@@ -123,18 +132,16 @@ public:
*/
PRUint32 Length() const {
NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
mItems.Length() == InternalList().Length(),
"DOM wrapper's list length is out of sync");
return mItems.Length();
}
- nsIDOMSVGPoint* GetItemWithoutAddRef(PRUint32 aIndex);
-
/**
* WATCH OUT! If you add code to call this on a baseVal wrapper, then you
* must also call it on the animVal wrapper too if necessary!! See other
* callers!
*
* Called by internal code to notify us when we need to sync the length of
* this DOM list with its internal list. This is called immediately prior to
* the length of the internal list being changed so that any DOM list items
@@ -159,16 +166,18 @@ private:
/**
* Only our static GetDOMWrapper() factory method may create objects of our
* type.
*/
DOMSVGPointList(nsSVGElement *aElement, bool aIsAnimValList)
: mElement(aElement)
, mIsAnimValList(aIsAnimValList)
{
+ SetIsProxy();
+
InternalListWillChangeTo(InternalList()); // Sync mItems
}
~DOMSVGPointList();
nsSVGElement* Element() {
return mElement.get();
}
--- a/content/svg/content/src/DOMSVGTransformList.cpp
+++ b/content/svg/content/src/DOMSVGTransformList.cpp
@@ -37,16 +37,18 @@
*
* ***** END LICENSE BLOCK ***** */
#include "DOMSVGTransformList.h"
#include "DOMSVGTransform.h"
#include "DOMSVGMatrix.h"
#include "SVGAnimatedTransformList.h"
#include "nsSVGElement.h"
+#include "nsContentUtils.h"
+#include "dombindings.h"
// local helper functions
namespace {
void UpdateListIndicesFromIndex(
nsTArray<mozilla::DOMSVGTransform*>& aItemsArray,
PRUint32 aStartingIndex)
{
@@ -67,40 +69,54 @@ namespace mozilla {
// clear our DOMSVGAnimatedTransformList's weak ref to us to be safe. (The other
// option would be to not unlink and rely on the breaking of the other edges in
// the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGTransformList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGTransformList)
// No need to null check tmp - script/SMIL can't detach us from mAList
( tmp->IsAnimValList() ? tmp->mAList->mAnimVal : tmp->mAList->mBaseVal ) =
nsnull;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGTransformList)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGTransformList)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGTransformList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGTransformList)
} // namespace mozilla
DOMCI_DATA(SVGTransformList, mozilla::DOMSVGTransformList)
namespace mozilla {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGTransformList)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTransformList)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGTransformList)
NS_INTERFACE_MAP_END
//----------------------------------------------------------------------
// DOMSVGTransformList methods:
+JSObject*
+DOMSVGTransformList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap)
+{
+ return mozilla::dom::binding::SVGTransformList::create(cx, scope, this,
+ triedToWrap);
+}
+
nsIDOMSVGTransform*
-DOMSVGTransformList::GetItemWithoutAddRef(PRUint32 aIndex)
+DOMSVGTransformList::GetItemAt(PRUint32 aIndex)
{
if (IsAnimValList()) {
Element()->FlushAnimations();
}
if (aIndex < Length()) {
EnsureItemAt(aIndex);
return mItems[aIndex];
}
@@ -229,17 +245,17 @@ DOMSVGTransformList::Initialize(nsIDOMSV
Clear();
return InsertItemBefore(newItem, 0, _retval);
}
/* nsIDOMSVGTransform getItem (in unsigned long index); */
NS_IMETHODIMP
DOMSVGTransformList::GetItem(PRUint32 index, nsIDOMSVGTransform **_retval)
{
- *_retval = GetItemWithoutAddRef(index);
+ *_retval = GetItemAt(index);
if (!*_retval) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
NS_ADDREF(*_retval);
return NS_OK;
}
/* nsIDOMSVGTransform insertItemBefore (in nsIDOMSVGTransform newItem,
--- a/content/svg/content/src/DOMSVGTransformList.h
+++ b/content/svg/content/src/DOMSVGTransformList.h
@@ -59,29 +59,32 @@ class DOMSVGTransform;
/**
* Class DOMSVGTransformList
*
* This class is used to create the DOM tearoff objects that wrap internal
* SVGTransformList objects.
*
* See the architecture comment in DOMSVGAnimatedTransformList.h.
*/
-class DOMSVGTransformList : public nsIDOMSVGTransformList
+class DOMSVGTransformList : public nsIDOMSVGTransformList,
+ public nsWrapperCache
{
friend class DOMSVGTransform;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGTransformList)
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGTransformList)
NS_DECL_NSIDOMSVGTRANSFORMLIST
DOMSVGTransformList(DOMSVGAnimatedTransformList *aAList,
const SVGTransformList &aInternalList)
: mAList(aAList)
{
+ SetIsProxy();
+
// aInternalList must be passed in explicitly because we can't use
// InternalList() here. (Because it depends on IsAnimValList, which depends
// on this object having been assigned to aAList's mBaseVal or mAnimVal,
// which hasn't happend yet.)
InternalListLengthWillChange(aInternalList.Length()); // Sync mItems
}
@@ -89,29 +92,35 @@ public:
// Our mAList's weak ref to us must be nulled out when we die. If GC has
// unlinked us using the cycle collector code, then that has already
// happened, and mAList is null.
if (mAList) {
( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nsnull;
}
}
+ virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+ bool *triedToWrap);
+
+ nsISupports* GetParentObject()
+ {
+ return static_cast<nsIContent*>(Element());
+ }
+
/**
* This will normally be the same as InternalList().Length(), except if we've
* hit OOM in which case our length will be zero.
*/
PRUint32 Length() const {
NS_ABORT_IF_FALSE(mItems.IsEmpty() ||
mItems.Length() == InternalList().Length(),
"DOM wrapper's list length is out of sync");
return mItems.Length();
}
- nsIDOMSVGTransform* GetItemWithoutAddRef(PRUint32 aIndex);
-
/// Called to notify us to synchronize our length and detach excess items.
void InternalListLengthWillChange(PRUint32 aNewLength);
private:
nsSVGElement* Element() const {
return mAList->mElement;
}
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -10635,17 +10635,17 @@ nsSVGListSH<ListInterfaceType, ListType>
// If this assertion fires the QI implementation for the object in
// question doesn't use the nsIDOMSVGXXXList pointer as the nsISupports
// pointer. That must be fixed, or we'll crash...
NS_ABORT_IF_FALSE(list_qi == list, "Uh, fix QI!");
}
#endif
- return list->GetItemWithoutAddRef(aIndex);
+ return list->GetItemAt(aIndex);
}
// SVGStringList helper
nsresult
nsSVGStringListSH::GetStringAt(nsISupports *aNative, PRInt32 aIndex,
nsAString& aResult)
--- a/dom/interfaces/base/nsIDOMClientRectList.idl
+++ b/dom/interfaces/base/nsIDOMClientRectList.idl
@@ -37,10 +37,11 @@
* ***** END LICENSE BLOCK ***** */
#include "domstubs.idl"
[scriptable, uuid(917da19d-62f5-441d-b47e-9e35f05639c9)]
interface nsIDOMClientRectList : nsISupports
{
readonly attribute unsigned long length;
- nsIDOMClientRect item(in unsigned long index);
+ [getter,forward(getItemAt)] nsIDOMClientRect item(in unsigned long index);
+ [noscript,notxpcom,nostdcall] nsIDOMClientRect getItemAt(in unsigned long index);
};
--- a/dom/interfaces/events/nsIDOMPaintRequestList.idl
+++ b/dom/interfaces/events/nsIDOMPaintRequestList.idl
@@ -39,10 +39,11 @@
#include "domstubs.idl"
interface nsIDOMPaintRequest;
[scriptable, uuid(01627136-fdd8-44b4-aac0-7d613608a3d4)]
interface nsIDOMPaintRequestList : nsISupports
{
readonly attribute unsigned long length;
- nsIDOMPaintRequest item(in unsigned long index);
+ [getter,forward(getItemAt)] nsIDOMPaintRequest item(in unsigned long index);
+ [noscript,notxpcom,nostdcall] nsIDOMPaintRequest getItemAt(in unsigned long index);
};
--- a/dom/interfaces/events/nsIDOMTouchEvent.idl
+++ b/dom/interfaces/events/nsIDOMTouchEvent.idl
@@ -68,17 +68,18 @@ interface nsIDOMTouch : nsISupports {
bool mChanged;
PRUint32 mMessage;
%}
};
[scriptable, uuid(60706eb7-d50d-4379-b01c-e78e6af84213)]
interface nsIDOMTouchList : nsISupports {
readonly attribute unsigned long length;
- nsIDOMTouch item(in unsigned long index);
+ [getter,forward(getItemAt)] nsIDOMTouch item(in unsigned long index);
+ [noscript,notxpcom,nostdcall] nsIDOMTouch getItemAt(in unsigned long index);
nsIDOMTouch identifiedTouch(in long identifier);
};
[scriptable, uuid(0cc687df-0ed5-4b7f-b89d-cbb99b21d23a)]
interface nsIDOMTouchEvent : nsIDOMUIEvent {
readonly attribute nsIDOMTouchList touches;
readonly attribute nsIDOMTouchList targetTouches;
readonly attribute nsIDOMTouchList changedTouches;
--- a/dom/interfaces/svg/nsIDOMSVGLengthList.idl
+++ b/dom/interfaces/svg/nsIDOMSVGLengthList.idl
@@ -47,16 +47,17 @@ interface nsIDOMSVGLengthList : nsISuppo
readonly attribute unsigned long length; // synonym for numberOfItems
void clear();
// raises(nsIDOMDOMException);
nsIDOMSVGLength initialize(in nsIDOMSVGLength newItem );
// raises(nsIDOMDOMException, nsIDOMSVGException);
nsIDOMSVGLength getItem(in unsigned long index);
// raises(nsIDOMDOMException);
+ [getter,noscript,notxpcom,nostdcall] nsIDOMSVGLength getItemAt(in unsigned long index);
nsIDOMSVGLength insertItemBefore(in nsIDOMSVGLength newItem, in unsigned long index);
// raises(nsIDOMDOMException, nsIDOMSVGException);
nsIDOMSVGLength replaceItem(in nsIDOMSVGLength newItem, in unsigned long index);
// raises(nsIDOMDOMException, nsIDOMSVGException);
nsIDOMSVGLength removeItem(in unsigned long index);
// raises(nsIDOMDOMException);
nsIDOMSVGLength appendItem(in nsIDOMSVGLength newItem);
// raises(nsIDOMDOMException, nsIDOMSVGException);
--- a/dom/interfaces/svg/nsIDOMSVGNumberList.idl
+++ b/dom/interfaces/svg/nsIDOMSVGNumberList.idl
@@ -47,16 +47,17 @@ interface nsIDOMSVGNumberList : nsISuppo
readonly attribute unsigned long length; // synonym for numberOfItems
void clear();
// raises(nsIDOMDOMException);
nsIDOMSVGNumber initialize(in nsIDOMSVGNumber newItem );
// raises(nsIDOMDOMException, nsIDOMSVGException);
nsIDOMSVGNumber getItem(in unsigned long index);
// raises(nsIDOMDOMException);
+ [getter,noscript,notxpcom,nostdcall] nsIDOMSVGNumber getItemAt(in unsigned long index);
nsIDOMSVGNumber insertItemBefore(in nsIDOMSVGNumber newItem, in unsigned long index);
// raises(nsIDOMDOMException, nsIDOMSVGException);
nsIDOMSVGNumber replaceItem(in nsIDOMSVGNumber newItem, in unsigned long index);
// raises(nsIDOMDOMException, nsIDOMSVGException);
nsIDOMSVGNumber removeItem(in unsigned long index);
// raises(nsIDOMDOMException);
nsIDOMSVGNumber appendItem(in nsIDOMSVGNumber newItem);
// raises(nsIDOMDOMException, nsIDOMSVGException);
--- a/dom/interfaces/svg/nsIDOMSVGPathSegList.idl
+++ b/dom/interfaces/svg/nsIDOMSVGPathSegList.idl
@@ -47,16 +47,17 @@ interface nsIDOMSVGPathSegList : nsISupp
readonly attribute unsigned long length; // synonym for numberOfItems
void clear();
// raises(nsIDOMDOMException);
nsIDOMSVGPathSeg initialize(in nsIDOMSVGPathSeg newItem );
// raises(nsIDOMDOMException, nsIDOMSVGException);
nsIDOMSVGPathSeg getItem(in unsigned long index);
// raises(nsIDOMDOMException);
+ [getter,noscript,notxpcom,nostdcall] nsIDOMSVGPathSeg getItemAt(in unsigned long index);
nsIDOMSVGPathSeg insertItemBefore(in nsIDOMSVGPathSeg newItem, in unsigned long index);
// raises(nsIDOMDOMException, nsIDOMSVGException);
nsIDOMSVGPathSeg replaceItem(in nsIDOMSVGPathSeg newItem, in unsigned long index);
// raises(nsIDOMDOMException, nsIDOMSVGException);
nsIDOMSVGPathSeg removeItem(in unsigned long index);
// raises(nsIDOMDOMException);
nsIDOMSVGPathSeg appendItem(in nsIDOMSVGPathSeg newItem);
// raises(nsIDOMDOMException, nsIDOMSVGException);
--- a/dom/interfaces/svg/nsIDOMSVGPointList.idl
+++ b/dom/interfaces/svg/nsIDOMSVGPointList.idl
@@ -47,16 +47,17 @@ interface nsIDOMSVGPointList : nsISuppor
readonly attribute unsigned long length; // synonym for numberOfItems
void clear();
// raises( DOMException );
nsIDOMSVGPoint initialize(in nsIDOMSVGPoint newItem);
// raises( DOMException, SVGException );
nsIDOMSVGPoint getItem (in unsigned long index);
// raises( DOMException );
+ [getter,noscript,notxpcom,nostdcall] nsIDOMSVGPoint getItemAt(in unsigned long index);
nsIDOMSVGPoint insertItemBefore(in nsIDOMSVGPoint newItem, in unsigned long index);
// raises( DOMException, SVGException );
nsIDOMSVGPoint replaceItem(in nsIDOMSVGPoint newItem, in unsigned long index);
// raises( DOMException, SVGException );
nsIDOMSVGPoint removeItem(in unsigned long index);
// raises( DOMException );
nsIDOMSVGPoint appendItem(in nsIDOMSVGPoint newItem);
// raises( DOMException, SVGException );
--- a/dom/interfaces/svg/nsIDOMSVGTransformList.idl
+++ b/dom/interfaces/svg/nsIDOMSVGTransformList.idl
@@ -48,16 +48,17 @@ interface nsIDOMSVGTransformList : nsISu
readonly attribute unsigned long length; // synonym for numberOfItems
void clear();
// raises( DOMException );
nsIDOMSVGTransform initialize(in nsIDOMSVGTransform newItem);
// raises( DOMException, SVGException );
nsIDOMSVGTransform getItem(in unsigned long index);
// raises( DOMException );
+ [getter,noscript,notxpcom,nostdcall] nsIDOMSVGTransform getItemAt(in unsigned long index);
nsIDOMSVGTransform insertItemBefore(in nsIDOMSVGTransform newItem,
in unsigned long index);
// raises( DOMException, SVGException );
nsIDOMSVGTransform replaceItem(in nsIDOMSVGTransform newItem,
in unsigned long index);
// raises( DOMException, SVGException );
nsIDOMSVGTransform removeItem(in unsigned long index);
// raises( DOMException );
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -1483,26 +1483,26 @@ nsNPAPIPluginInstance::URLRedirectRespon
NPError
nsNPAPIPluginInstance::InitAsyncSurface(NPSize *size, NPImageFormat format,
void *initData, NPAsyncSurface *surface)
{
if (mOwner)
return mOwner->InitAsyncSurface(size, format, initData, surface);
- return NS_ERROR_FAILURE;
+ return NPERR_GENERIC_ERROR;
}
NPError
nsNPAPIPluginInstance::FinalizeAsyncSurface(NPAsyncSurface *surface)
{
if (mOwner)
return mOwner->FinalizeAsyncSurface(surface);
- return NS_ERROR_FAILURE;
+ return NPERR_GENERIC_ERROR;
}
void
nsNPAPIPluginInstance::SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed)
{
if (mOwner)
mOwner->SetCurrentAsyncSurface(surface, changed);
}
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -799,22 +799,22 @@ NPBool nsPluginInstanceOwner::ConvertPoi
// we should implement this for all platforms
return false;
#endif
}
NPError nsPluginInstanceOwner::InitAsyncSurface(NPSize *size, NPImageFormat format,
void *initData, NPAsyncSurface *surface)
{
- return NPERR_GENERIC_ERROR;
+ return NPERR_INCOMPATIBLE_VERSION_ERROR;
}
NPError nsPluginInstanceOwner::FinalizeAsyncSurface(NPAsyncSurface *)
{
- return NPERR_GENERIC_ERROR;
+ return NPERR_INCOMPATIBLE_VERSION_ERROR;
}
void nsPluginInstanceOwner::SetCurrentAsyncSurface(NPAsyncSurface *, NPRect*)
{
}
NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result)
{
--- a/gfx/thebes/gfxQtPlatform.cpp
+++ b/gfx/thebes/gfxQtPlatform.cpp
@@ -88,16 +88,18 @@ static QPaintEngine::Type sDefaultQtPain
gfxFontconfigUtils *gfxQtPlatform::sFontconfigUtils = nsnull;
static cairo_user_data_key_t cairo_qt_pixmap_key;
static void do_qt_pixmap_unref (void *data)
{
QPixmap *pmap = (QPixmap*)data;
delete pmap;
}
+static gfxImageFormat sOffscreenFormat = gfxASurface::ImageFormatRGB24;
+
#ifndef MOZ_PANGO
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
typedef nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<FontEntry> > > PrefFontTable;
static FontTable *gPlatformFonts = NULL;
static FontTable *gPlatformFontAliases = NULL;
static PrefFontTable *gPrefFonts = NULL;
static gfxSparseBitSet *gCodepointsWithNoFonts = NULL;
static FT_Library gPlatformFTLibrary = NULL;
@@ -146,16 +148,19 @@ gfxQtPlatform::gfxQtPlatform()
break;
default:
mRenderMode = RENDER_QPAINTER;
}
// Qt doesn't provide a public API to detect the graphicssystem type. We hack
// around this by checking what type of graphicssystem a test QPixmap uses.
QPixmap pixmap(1, 1);
+ if (pixmap.depth() == 16) {
+ sOffscreenFormat = gfxASurface::ImageFormatRGB16_565;
+ }
#if (QT_VERSION < QT_VERSION_CHECK(4,8,0))
if (pixmap.paintEngine())
sDefaultQtPaintEngineType = pixmap.paintEngine()->type();
#endif
}
gfxQtPlatform::~gfxQtPlatform()
{
@@ -584,14 +589,10 @@ gfxQtPlatform::GetDPI()
QDesktopWidget* rootWindow = qApp->desktop();
PRInt32 dpi = rootWindow->logicalDpiY(); // y-axis DPI for fonts
return dpi <= 0 ? 96 : dpi;
}
gfxImageFormat
gfxQtPlatform::GetOffscreenFormat()
{
- if (qApp->desktop()->depth() == 16) {
- return gfxASurface::ImageFormatRGB16_565;
- }
-
- return gfxASurface::ImageFormatRGB24;
+ return sOffscreenFormat;
}
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -1906,19 +1906,16 @@ echo-tier-dirs:
@$(foreach tier,$(TIERS),echo '$(tier):'; echo ' dirs: $(tier_$(tier)_dirs)'; echo ' staticdirs: $(tier_$(tier)_staticdirs)'; )
echo-dirs:
@echo $(DIRS)
echo-module:
@echo $(MODULE)
-echo-requires:
- @echo $(REQUIRES)
-
echo-depth-path:
@$(topsrcdir)/build/unix/print-depth-path.sh
echo-module-name:
@$(topsrcdir)/build/package/rpm/print-module-name.sh
echo-module-filelist:
@$(topsrcdir)/build/package/rpm/print-module-filelist.sh
@@ -2015,17 +2012,16 @@ endif
FREEZE_VARIABLES = \
CSRCS \
CPPSRCS \
EXPORTS \
XPIDLSRCS \
DIRS \
LIBRARY \
MODULE \
- REQUIRES \
SHORT_LIBNAME \
TIERS \
EXTRA_COMPONENTS \
EXTRA_PP_COMPONENTS \
$(NULL)
$(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
--- a/js/xpconnect/src/Makefile.in
+++ b/js/xpconnect/src/Makefile.in
@@ -92,16 +92,17 @@ CPPSRCS = \
include $(topsrcdir)/config/config.mk
LOCAL_INCLUDES = \
-I$(srcdir)/../wrappers \
-I$(srcdir)/../loader \
-I$(topsrcdir)/caps/include \
-I$(topsrcdir)/content/base/src \
+ -I$(topsrcdir)/content/events/src \
-I$(topsrcdir)/content/html/content/src \
-I$(topsrcdir)/content/html/document/src \
-I$(topsrcdir)/content/svg/content/src \
-I$(topsrcdir)/layout/style \
-I$(topsrcdir)/layout/base \
-I$(topsrcdir)/dom/base \
-I$(topsrcdir)/xpcom/ds \
$(NULL)
--- a/js/xpconnect/src/codegen.py
+++ b/js/xpconnect/src/codegen.py
@@ -264,17 +264,17 @@ def writeArgumentUnboxing(f, i, name, ty
% (type.name, argVal, name, name, argPtr))
f.write(" if (NS_FAILED(rv)) {\n")
if isSetter:
f.write(" xpc_qsThrowBadSetterValue("
"cx, rv, JSVAL_TO_OBJECT(*tvr.jsval_addr()), id);\n")
elif haveCcx:
f.write(" xpc_qsThrowBadArgWithCcx(ccx, rv, %d);\n" % i)
else:
- f.write(" xpc_qsThrowBadArg(cx, rv, vp, %d);\n" % i)
+ f.write(" xpc_qsThrowBadArgWithDetails(cx, rv, %d, %s, %s);\n" % (i, "\"\"", "\"\""))
f.write(" return JS_FALSE;\n"
" }\n")
return True
warn("Unable to unbox argument of type %s (native type %s)" % (type.name, typeName))
if i is None:
src = '*vp'
else:
--- a/js/xpconnect/src/dombindings.conf
+++ b/js/xpconnect/src/dombindings.conf
@@ -1,17 +1,32 @@
classes = {
'NodeList': 'nsINodeList',
'HTMLCollection': 'nsIHTMLCollection',
'HTMLOptionsCollection': 'nsHTMLOptionCollection',
}
prefableClasses = {
'DOMTokenList': 'nsDOMTokenList',
'DOMSettableTokenList': 'nsDOMSettableTokenList',
+ 'ClientRectList': 'nsClientRectList',
+ 'PaintRequestList': 'nsPaintRequestList',
+ 'TouchList': 'nsDOMTouchList',
+ 'FileList': 'nsDOMFileList',
+ 'SVGLengthList': 'mozilla::DOMSVGLengthList',
+ 'SVGNumberList': 'mozilla::DOMSVGNumberList',
+ 'SVGPathSegList': 'mozilla::DOMSVGPathSegList',
+ 'SVGPointList': 'mozilla::DOMSVGPointList',
+ 'SVGTransformList': 'mozilla::DOMSVGTransformList',
}
irregularFilenames = {
'nsHTMLOptionCollection': 'nsHTMLSelectElement',
+ 'nsClientRectList': 'nsClientRect',
+ 'nsPaintRequestList': 'nsPaintRequest',
+ 'nsIDOMTouch': 'nsIDOMTouchEvent',
+ 'nsIDOMTouchList': 'nsIDOMTouchEvent',
+ 'nsDOMTouchList': 'nsDOMTouchEvent',
+ 'nsDOMFileList': 'nsDOMFile',
}
customInheritance = {
'nsIDOMHTMLOptionsCollection': 'nsIDOMHTMLCollection',
}
--- a/js/xpconnect/src/dombindingsgen.py
+++ b/js/xpconnect/src/dombindingsgen.py
@@ -321,33 +321,38 @@ def completeConfiguration(conf, includeP
for iface in stubbedInterfaces:
for member in iface.stubMembers:
checkStubMember(member)
return interfaces
# === Generating the header file
-def needsForwardDeclaration(type):
- return isInterfaceType(type) or (type.kind == 'native' and type.specialtype is None)
-
-def getTypes(classes, map={}):
+def addType(types, type, map):
def getTranslatedType(type):
return map.get(type, type)
+ type = xpidl.unaliasType(type)
+ if isInterfaceType(type) or (type.kind == 'native' and type.specialtype is None):
+ types.add(getTranslatedType(type.name))
+
+
+def getTypes(classes, map):
types = set()
for clazz in classes.itervalues():
- types.add(getTranslatedType(clazz.nativeClass))
- if clazz.indexGetter and needsForwardDeclaration(clazz.realIndexGetter.realtype):
- types.add(getTranslatedType(clazz.realIndexGetter.realtype.name))
- if clazz.indexSetter and needsForwardDeclaration(clazz.realIndexSetter.realtype):
- types.add(getTranslatedType(clazz.realIndexSetter.realtype.name))
- if clazz.nameGetter and needsForwardDeclaration(clazz.realNameGetter.realtype):
- types.add(getTranslatedType(clazz.realNameGetter.realtype.name))
- return sorted(types)
+ types.add(map.get(clazz.nativeClass, clazz.nativeClass))
+ if clazz.indexGetter:
+ addType(types, clazz.realIndexGetter.realtype, map)
+ if clazz.indexSetter:
+ addType(types, clazz.realIndexSetter.realtype, map)
+ if clazz.nameGetter:
+ addType(types, clazz.realNameGetter.realtype, map)
+ if clazz.nameSetter:
+ addType(types, clazz.realNameSetter.realtype, map)
+ return types
listDefinitionTemplate = (
"class ${name} {\n"
"public:\n"
" template<typename I>\n"
" static JSObject *create(JSContext *cx, XPCWrappedNativeScope *scope, I *list, bool *triedToWrap)\n"
" {\n"
" return create(cx, scope, list, GetWrapperCache(list), triedToWrap);\n"
@@ -368,17 +373,17 @@ def writeHeaderFile(filename, config):
headerMacro = '__gen_%s__' % filename.replace('.', '_')
f = open(filename, 'w')
try:
f.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
"#ifndef " + headerMacro + "\n"
"#define " + headerMacro + "\n\n")
namespaces = []
- for type in getTypes(config.classes, {}):
+ for type in sorted(getTypes(config.classes, {})):
newNamespaces = type.split('::')
type = newNamespaces.pop()
j = 0
for i in range(min(len(namespaces), len(newNamespaces))):
if namespaces[i] != newNamespaces[i]:
break
j += 1
for i in range(j, len(namespaces)):
@@ -628,40 +633,30 @@ def writeMethodStub(f, classname, method
def writeStubFile(filename, config, interfaces):
print "Creating stub file", filename
make_targets.append(filename)
f = open(filename, 'w')
filesIncluded = set()
- def includeType(type):
- type = unaliasType(type)
- if type.kind in ('builtin', 'native'):
- return None
- file = conf.irregularFilenames.get(type.name, type.name) + '.h'
- if file not in filesIncluded:
- f.write('#include "%s"\n' % file)
- filesIncluded.add(file)
- return type
-
- def writeIncludesForMember(member):
- assert member.kind in ('attribute', 'method')
- resulttype = includeType(member.realtype)
- if member.kind == 'method':
- for p in member.params:
- includeType(p.realtype)
- return resulttype
-
headerFilename = re.sub(r'(\.cpp)?$', '.h', filename)
try:
f.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n")
- f.write("".join([("#include \"%s.h\"\n" % re.sub(r'(([^:]+::)*)', '', type)) for type in getTypes(config.classes, config.irregularFilenames)]))
+ types = getTypes(config.classes, config.irregularFilenames)
+ for clazz in config.classes.itervalues():
+ for member in clazz.members:
+ addType(types, member.realtype, config.irregularFilenames)
+ if member.kind == 'method':
+ for p in member.params:
+ addType(types, p.realtype, config.irregularFilenames)
+
+ f.write("".join([("#include \"%s.h\"\n" % re.sub(r'(([^:]+::)*)', '', type)) for type in sorted(types)]))
f.write("\n")
f.write("namespace mozilla {\n"
"namespace dom {\n"
"namespace binding {\n\n")
f.write("// Property name ids\n\n")
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2446,36 +2446,34 @@ gfxPoint3D GetDeltaToMozTransformOrigin(
}
/* Returns the delta specified by the -moz-perspective-origin property.
* This is a positive delta, meaning that it indicates the direction to move
* to get from (0, 0) of the frame to the perspective origin.
*/
static
gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
- float aAppUnitsPerPixel,
- const nsRect* aBoundsOverride)
+ float aAppUnitsPerPixel)
{
NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
NS_PRECONDITION(aFrame->GetStyleDisplay()->HasTransform(),
"Can't get a delta for an untransformed frame!");
NS_PRECONDITION(aFrame->GetParentStyleContextFrame(),
"Can't get delta without a style parent!");
/* For both of the coordinates, if the value of -moz-perspective-origin is a
* percentage, it's relative to the size of the frame. Otherwise, if it's
* a distance, it's already computed for us!
*/
//TODO: Should this be using our bounds or the parent's bounds?
// How do we handle aBoundsOverride in the latter case?
nsIFrame* parent = aFrame->GetParentStyleContextFrame();
const nsStyleDisplay* display = aFrame->GetParent()->GetStyleDisplay();
- nsRect boundingRect = (aBoundsOverride ? *aBoundsOverride :
- nsDisplayTransform::GetFrameBoundsForTransform(parent));
+ nsRect boundingRect = nsDisplayTransform::GetFrameBoundsForTransform(parent);
/* Allows us to access named variables by index. */
gfxPoint3D result;
result.z = 0.0f;
gfxFloat* coords[2] = {&result.x, &result.y};
const nscoord* dimensions[2] =
{&boundingRect.width, &boundingRect.height};
@@ -2549,18 +2547,19 @@ nsDisplayTransform::GetResultingTransfor
gfx3DMatrix result;
/* Transformed frames always have a transform, or are preserving 3d (and might still have perspective!) */
if (disp->mSpecifiedTransform) {
result = nsStyleTransformMatrix::ReadTransforms(disp->mSpecifiedTransform,
aFrame->GetStyleContext(),
aFrame->PresContext(),
dummy, bounds, aAppUnitsPerPixel);
} else {
- NS_ASSERTION(aFrame->GetStyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D,
- "If we don't have a transform, then we must be at least attempting to preserve the transforms of our children");
+ NS_ASSERTION(aFrame->GetStyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
+ aFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN,
+ "If we don't have a transform, then we must have another reason to have an nsDisplayTransform created");
}
const nsStyleDisplay* parentDisp = nsnull;
nsStyleContext* parentStyleContext = aFrame->GetStyleContext()->GetParent();
if (parentStyleContext) {
parentDisp = parentStyleContext->GetStyleDisplay();
}
if (nsLayoutUtils::Are3DTransformsEnabled() &&
@@ -2568,17 +2567,17 @@ nsDisplayTransform::GetResultingTransfor
parentDisp->mChildPerspective.GetCoordValue() > 0.0) {
gfx3DMatrix perspective;
perspective._34 =
-1.0 / NSAppUnitsToFloatPixels(parentDisp->mChildPerspective.GetCoordValue(),
aAppUnitsPerPixel);
/* At the point when perspective is applied, we have been translated to the transform origin.
* The translation to the perspective origin is the difference between these values.
*/
- gfxPoint3D toPerspectiveOrigin = GetDeltaToMozPerspectiveOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride);
+ gfxPoint3D toPerspectiveOrigin = GetDeltaToMozPerspectiveOrigin(aFrame, aAppUnitsPerPixel);
result = result * nsLayoutUtils::ChangeMatrixBasis(toPerspectiveOrigin - toMozOrigin, perspective);
}
if (aFrame->Preserves3D() && nsLayoutUtils::Are3DTransformsEnabled()) {
// Include the transform set on our parent
NS_ASSERTION(aFrame->GetParent() &&
aFrame->GetParent()->IsTransformed() &&
aFrame->GetParent()->Preserves3DChildren(),
--- a/layout/base/tests/Makefile.in
+++ b/layout/base/tests/Makefile.in
@@ -180,16 +180,17 @@ DEFINES += -D_IMPL_NS_LAYOUT
bug583889_inner2.html \
test_bug582771.html \
test_bug603550.html \
test_bug629838.html \
test_bug646757.html \
test_bug718809.html \
test_font_inflation_reftests.html \
test_bug725426.html \
+ test_bug731777.html \
$(NULL)
# Tests for bugs 441782, 467672 and 570378 don't pass reliably on Windows, because of bug 469208
ifeq (,$(filter windows,$(MOZ_WIDGET_TOOLKIT)))
# THESE TESTS (BELOW) DO NOT RUN ON WINDOWS
_TEST_FILES += \
bidi_numeral_test.js \
$(NULL)
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/test_bug731777.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 731777</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ #container {
+ position: relative;
+ height: 300px;
+ width: 300px;
+ margin: 50px 100px;
+ border: 2px solid blue;
+ background-color: #044B0A;
+
+ -moz-perspective: 500px;
+ overflow:hidden;
+ }
+
+ #inner {
+ margin: 0px;
+ width: 480px;
+ border: 2px solid blue;
+ height: 220px;
+ background-color: #844BCA;
+
+ -moz-transform: rotateY(91deg) translateX(0px) translateZ(0px);
+ -moz-transition: 5s;
+ }
+
+ </style>
+</head>
+<body>
+<div id="container">
+ <div id="inner"></div>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 731777 **/
+
+is(document.elementFromPoint(325,170), document.getElementById("inner"), "Able to hit transformed object");
+is(document.elementFromPoint(405,170), document.getElementById("inner"), "Able to hit transformed object");
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -154,67 +154,16 @@ nsFileControlFrame::DestroyFrom(nsIFrame
}
nsContentUtils::DestroyAnonymousContent(&mTextContent);
mCaptureMouseListener->ForgetFrame();
mMouseListener->ForgetFrame();
nsBlockFrame::DestroyFrom(aDestructRoot);
}
-struct CaptureCallbackData {
- nsICapturePicker* picker;
- PRUint32* mode;
-};
-
-typedef struct CaptureCallbackData CaptureCallbackData;
-
-bool CapturePickerAcceptCallback(const nsAString& aAccept, void* aClosure)
-{
- nsresult rv;
- bool captureEnabled;
- CaptureCallbackData* closure = (CaptureCallbackData*)aClosure;
-
- if (StringBeginsWith(aAccept,
- NS_LITERAL_STRING("image/"))) {
- rv = closure->picker->ModeMayBeAvailable(nsICapturePicker::MODE_STILL,
- &captureEnabled);
- NS_ENSURE_SUCCESS(rv, true);
- if (captureEnabled) {
- *closure->mode = nsICapturePicker::MODE_STILL;
- return false;
- }
- } else if (StringBeginsWith(aAccept,
- NS_LITERAL_STRING("audio/"))) {
- rv = closure->picker->ModeMayBeAvailable(nsICapturePicker::MODE_AUDIO_CLIP,
- &captureEnabled);
- NS_ENSURE_SUCCESS(rv, true);
- if (captureEnabled) {
- *closure->mode = nsICapturePicker::MODE_AUDIO_CLIP;
- return false;
- }
- } else if (StringBeginsWith(aAccept,
- NS_LITERAL_STRING("video/"))) {
- rv = closure->picker->ModeMayBeAvailable(nsICapturePicker::MODE_VIDEO_CLIP,
- &captureEnabled);
- NS_ENSURE_SUCCESS(rv, true);
- if (captureEnabled) {
- *closure->mode = nsICapturePicker::MODE_VIDEO_CLIP;
- return false;
- }
- rv = closure->picker->ModeMayBeAvailable(nsICapturePicker::MODE_VIDEO_NO_SOUND_CLIP,
- &captureEnabled);
- NS_ENSURE_SUCCESS(rv, true);
- if (captureEnabled) {
- *closure->mode = nsICapturePicker::MODE_VIDEO_NO_SOUND_CLIP;
- return false;
- }
- }
- return true;
-}
-
nsresult
nsFileControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
{
// Get the NodeInfoManager and tag necessary to create input elements
nsCOMPtr<nsIDocument> doc = mContent->GetDocument();
nsCOMPtr<nsINodeInfo> nodeInfo;
nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::input, nsnull,
@@ -277,25 +226,22 @@ nsFileControlFrame::CreateAnonymousConte
mBrowse->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
NS_LITERAL_STRING("button"), false);
// Create the capture button
nsCOMPtr<nsICapturePicker> capturePicker;
capturePicker = do_GetService("@mozilla.org/capturepicker;1");
if (capturePicker) {
- PRUint32 mode = 0;
-
CaptureCallbackData data;
data.picker = capturePicker;
- data.mode = &mode;
- ParseAcceptAttribute(&CapturePickerAcceptCallback, (void*)&data);
+ data.mode = GetCaptureMode(data);
- if (mode != 0) {
- mCaptureMouseListener->mMode = mode;
+ if (data.mode != 0) {
+ mCaptureMouseListener->mMode = data.mode;
nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::input, nsnull,
kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE);
NS_NewHTMLElement(getter_AddRefs(mCapture), nodeInfo.forget(),
dom::NOT_FROM_PARSER);
if (!mCapture)
return NS_ERROR_OUT_OF_MEMORY;
@@ -742,26 +688,58 @@ nsFileControlFrame::CreateAccessible()
if (!accService)
return nsnull;
return accService->CreateHTMLFileInputAccessible(mContent,
PresContext()->PresShell());
}
#endif
-void
-nsFileControlFrame::ParseAcceptAttribute(AcceptAttrCallback aCallback,
- void* aClosure) const
+PRUint32
+nsFileControlFrame::GetCaptureMode(const CaptureCallbackData& aData)
{
- nsAutoString accept;
- mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accept, accept);
+ PRInt32 filters = nsHTMLInputElement::FromContent(mContent)->GetFilterFromAccept();
+ nsresult rv;
+ bool captureEnabled;
+
+ if (filters == nsIFilePicker::filterImages) {
+ rv = aData.picker->ModeMayBeAvailable(nsICapturePicker::MODE_STILL,
+ &captureEnabled);
+ NS_ENSURE_SUCCESS(rv, 0);
+ if (captureEnabled) {
+ return nsICapturePicker::MODE_STILL;
+ }
+ return 0;
+ }
- HTMLSplitOnSpacesTokenizer tokenizer(accept, ',');
- // Empty loop body because aCallback is doing the work
- while (tokenizer.hasMoreTokens() &&
- (*aCallback)(tokenizer.nextToken(), aClosure));
+ if (filters == nsIFilePicker::filterAudio) {
+ rv = aData.picker->ModeMayBeAvailable(nsICapturePicker::MODE_AUDIO_CLIP,
+ &captureEnabled);
+ NS_ENSURE_SUCCESS(rv, 0);
+ if (captureEnabled) {
+ return nsICapturePicker::MODE_AUDIO_CLIP;
+ }
+ return 0;
+ }
+
+ if (filters == nsIFilePicker::filterVideo) {
+ rv = aData.picker->ModeMayBeAvailable(nsICapturePicker::MODE_VIDEO_CLIP,
+ &captureEnabled);
+ NS_ENSURE_SUCCESS(rv, 0);
+ if (captureEnabled) {
+ return nsICapturePicker::MODE_VIDEO_CLIP;
+ }
+ rv = aData.picker->ModeMayBeAvailable(nsICapturePicker::MODE_VIDEO_NO_SOUND_CLIP,
+ &captureEnabled);
+ NS_ENSURE_SUCCESS(rv, 0);
+ if (captureEnabled) {
+ return nsICapturePicker::MODE_VIDEO_NO_SOUND_CLIP;
+ }
+ return 0;
+ }
+
+ return 0;
}
-
////////////////////////////////////////////////////////////
// Mouse listener implementation
NS_IMPL_ISUPPORTS1(nsFileControlFrame::MouseListener,
nsIDOMEventListener)
--- a/layout/forms/nsFileControlFrame.h
+++ b/layout/forms/nsFileControlFrame.h
@@ -89,23 +89,29 @@ public:
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements);
virtual void AppendAnonymousContentTo(nsBaseContentList& aElements,
PRUint32 aFilter);
#ifdef ACCESSIBILITY
virtual already_AddRefed<nsAccessible> CreateAccessible();
-#endif
+#endif
typedef bool (*AcceptAttrCallback)(const nsAString&, void*);
- void ParseAcceptAttribute(AcceptAttrCallback aCallback, void* aClosure) const;
protected:
-
+
+ struct CaptureCallbackData {
+ nsICapturePicker* picker;
+ PRUint32 mode;
+ };
+
+ PRUint32 GetCaptureMode(const CaptureCallbackData& aData);
+
class MouseListener;
friend class MouseListener;
class MouseListener : public nsIDOMEventListener {
public:
NS_DECL_ISUPPORTS
MouseListener(nsFileControlFrame* aFrame) :
mFrame(aFrame)
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -990,16 +990,28 @@ nsIFrame::HasPerspective() const
if (parentDisp &&
parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
parentDisp->mChildPerspective.GetCoordValue() > 0.0) {
return true;
}
return false;
}
+bool
+nsIFrame::ChildrenHavePerspective() const
+{
+ const nsStyleDisplay *disp = GetStyleContext()->GetStyleDisplay();
+ if (disp &&
+ disp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
+ disp->mChildPerspective.GetCoordValue() > 0.0) {
+ return true;
+ }
+ return false;
+}
+
nsRect
nsIFrame::GetContentRectRelativeToSelf() const
{
nsMargin bp(GetUsedBorderAndPadding());
ApplySkipSides(bp);
nsRect r(0, 0, mRect.width, mRect.height);
r.Deflate(bp);
return r;
@@ -6766,22 +6778,27 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
nsRect newBounds(nsPoint(0, 0), aNewSize);
// Transform affects both overflow areas.
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
nsRect& o = aOverflowAreas.Overflow(otype);
o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds);
}
if (Preserves3DChildren()) {
ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
- } else if (HasPerspective()) {
- RecomputePerspectiveChildrenOverflow(this, &newBounds);
+ } else if (ChildrenHavePerspective()) {
+ RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
}
} else {
Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
- }
+ if (ChildrenHavePerspective()) {
+ nsRect newBounds(nsPoint(0, 0), aNewSize);
+ RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
+ }
+ }
+
bool anyOverflowChanged;
if (aOverflowAreas != nsOverflowAreas(bounds, bounds)) {
anyOverflowChanged = SetOverflowAreas(aOverflowAreas);
} else {
anyOverflowChanged = ClearOverflowRects();
}
@@ -6828,17 +6845,17 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
InvalidateLayer(aOverflowAreas.VisualOverflow(),
nsDisplayItem::TYPE_TRANSFORM);
}
return anyOverflowChanged;
}
void
-nsIFrame::RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame, const nsRect* aBounds)
+nsIFrame::RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds)
{
// Children may check our size when getting our transform, make sure it's valid.
nsSize oldSize = GetSize();
if (aBounds) {
SetSize(aBounds->Size());
}
nsIFrame::ChildListIterator lists(this);
for (; !lists.IsDone(); lists.Next()) {
@@ -6851,18 +6868,21 @@ nsIFrame::RecomputePerspectiveChildrenOv
nsRect bounds(nsPoint(0, 0), child->GetSize());
if (overflow) {
child->FinishAndStoreOverflow(*overflow, bounds.Size());
} else {
nsOverflowAreas boundsOverflow;
boundsOverflow.SetAllTo(bounds);
child->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
}
- } else if (child->GetParentStyleContextFrame() != aStartFrame) {
- child->RecomputePerspectiveChildrenOverflow(aStartFrame, nsnull);
+ } else if (child->GetStyleContext()->GetParent() == aStartStyle ||
+ child->GetStyleContext() == aStartStyle) {
+ // Recurse into frames with the same style context, or a direct
+ // child style context.
+ child->RecomputePerspectiveChildrenOverflow(aStartStyle, nsnull);
}
}
}
// Restore our old size just in case something depends on this elesewhere.
SetSize(oldSize);
}
/* The overflow rects for leaf nodes in a preserve-3d hierarchy depends on
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1240,20 +1240,22 @@ public:
/**
* Returns whether this frame has a parent that Preserves3DChildren() and
* can respect this. Returns false if the frame is clipped.
*/
bool Preserves3D() const;
bool HasPerspective() const;
+ bool ChildrenHavePerspective() const;
+
// Calculate the overflow size of all child frames, taking preserve-3d into account
void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
- void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame, const nsRect* aBounds);
+ void RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds);
/**
* Event handling of GUI events.
*
* @param aEvent event structure describing the type of event and rge widget
* where the event originated
* The |point| member of this is in the coordinate system of the
* view returned by GetOffsetFromView.
new file mode 100644
--- /dev/null
+++ b/layout/reftests/transform-3d/backface-visibility-2-ref.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<body>
+ <style>
+ #container {
+ position: relative;
+ margin: 10px auto;
+ width: 450px;
+ height: 281px;
+ z-index: 1;
+ -moz-perspective: 1000px;
+ }
+ #card {
+ width: 100%;
+ height: 100%;
+ -moz-transform-style: preserve-3d;
+ -moz-transform: rotateY(165deg);
+ }
+ .face {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ -moz-backface-visibility: hidden;
+ background: red;
+ }
+ .face.back {
+ display: block;
+ -moz-transform: rotateY(180deg);
+ -moz-box-sizing: border-box;
+ padding: 10px;
+ color: white;
+ text-align: center;
+ background: green;
+ }
+ </style>
+
+ <div id="container" class="hover">
+ <div id="card">
+ <div class="back face">
+ </div>
+ </div>
+ </div>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/transform-3d/backface-visibility-2.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<body>
+ <style>
+ #container {
+ position: relative;
+ margin: 10px auto;
+ width: 450px;
+ height: 281px;
+ z-index: 1;
+ -moz-perspective: 1000px;
+ }
+ #card {
+ width: 100%;
+ height: 100%;
+ -moz-transform-style: preserve-3d;
+ -moz-transform: rotateY(165deg);
+ }
+ .face {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ -moz-backface-visibility: hidden;
+ background: red;
+ }
+ .face.back {
+ display: block;
+ -moz-transform: rotateY(180deg);
+ -moz-box-sizing: border-box;
+ padding: 10px;
+ color: white;
+ text-align: center;
+ background: green;
+ }
+ </style>
+
+ <div id="container" class="hover">
+ <div id="card">
+ <div class="front face">
+ </div>
+ <div class="back face">
+ </div>
+ </div>
+ </div>
+</body></html>
--- a/layout/reftests/transform-3d/reftest.list
+++ b/layout/reftests/transform-3d/reftest.list
@@ -29,16 +29,17 @@ fails-if(Android) == scale3d-all-separat
== translate3d-1a.html translate3d-1-ref.html
== matrix3d-1a.html matrix3d-1-ref.html
== matrix3d-2a.html matrix3d-2-ref.html
== rotate3d-1a.html rotatex-1-ref.html
== rotate3d-2a.html rotatey-1-ref.html
!= backface-visibility-1a.html about:blank
== backface-visibility-1b.html about:blank
== backface-visibility-1c.html about:blank
+== backface-visibility-2.html backface-visibility-2-ref.html
!= perspective-origin-1a.html rotatex-perspective-1a.html
== perspective-origin-1b.html perspective-origin-1a.html
== perspective-origin-2a.html perspective-origin-2-ref.html
!= sorting-1a.html sorting-1-ref.html
# Parallel planes, different z depth
== sorting-2a.html sorting-2-ref.html
# Parallel planes, same z depth (shouldn't be sorted!)
== sorting-2b.html sorting-2-ref.html
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1661,17 +1661,19 @@ struct nsStyleDisplay {
// mOverflowX and mOverflowY always match when one of them is
// NS_STYLE_OVERFLOW_VISIBLE or NS_STYLE_OVERFLOW_CLIP.
return mOverflowX != NS_STYLE_OVERFLOW_VISIBLE &&
mOverflowX != NS_STYLE_OVERFLOW_CLIP;
}
/* Returns whether the element has the -moz-transform property. */
bool HasTransform() const {
- return mSpecifiedTransform != nsnull || mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D;
+ return mSpecifiedTransform != nsnull ||
+ mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
+ mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN;
}
};
struct nsStyleTable {
nsStyleTable(void);
nsStyleTable(const nsStyleTable& aOther);
~nsStyleTable(void);
--- a/mobile/android/base/AwesomeBar.java
+++ b/mobile/android/base/AwesomeBar.java
@@ -47,16 +47,17 @@ import android.content.Context;
import android.content.res.Resources;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
+import android.text.Spanned;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -190,30 +191,42 @@ public class AwesomeBar extends Activity
}
return false;
}
});
mText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
- // do nothing
+ String text = s.toString();
+ mAwesomeTabs.filter(text);
+
+ // If awesome bar has compositing string, don't call updateGoButton().
+ // Since that method resets IME, composing state will be borken.
+ Object[] spans = s.getSpans(0, s.length(), Object.class);
+ if (spans != null) {
+ for (Object span : spans) {
+ if ((s.getSpanFlags(span) & Spanned.SPAN_COMPOSING) != 0) {
+ // Found composition string.
+ return;
+ }
+ }
+ }
+ // no composition string. It is safe to update IME flags.
+ updateGoButton(text);
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// do nothing
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
- String text = s.toString();
-
- mAwesomeTabs.filter(text);
- updateGoButton(text);
+ // do nothing
}
});
mText.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
if (event.getAction() != KeyEvent.ACTION_DOWN)
return true;
--- a/mobile/android/components/build/Makefile.in
+++ b/mobile/android/components/build/Makefile.in
@@ -48,22 +48,16 @@ MODULE = browsercomps
LIBRARY_NAME = browsercomps
LIBXUL_LIBRARY = 1
IS_COMPONENT = 1
EXPORT_LIBRARY = 1
EXPORTS = nsBrowserComponents.h
-REQUIRES = \
- xpcom \
- string \
- pref \
- $(NULL)
-
XPIDL_MODULE = browsercomps
XPIDLSRCS = nsIShellService.idl
CPPSRCS = \
nsBrowserModule.cpp \
nsShellService.cpp \
$(NULL)
--- a/mobile/xul/components/build/Makefile.in
+++ b/mobile/xul/components/build/Makefile.in
@@ -48,22 +48,16 @@ MODULE = browsercomps
LIBRARY_NAME = browsercomps
LIBXUL_LIBRARY = 1
IS_COMPONENT = 1
EXPORT_LIBRARY = 1
EXPORTS = nsBrowserComponents.h
-REQUIRES = \
- xpcom \
- string \
- pref \
- $(NULL)
-
XPIDL_MODULE = browsercomps
XPIDLSRCS = nsIShellService.idl
CPPSRCS = \
nsBrowserModule.cpp \
nsShellService.cpp \
$(NULL)
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -128,22 +128,30 @@ public:
~TelemetryImpl();
static bool CanRecord();
static already_AddRefed<nsITelemetry> CreateTelemetryInstance();
static void ShutdownTelemetry();
static void RecordSlowStatement(const nsACString &statement,
const nsACString &dbName,
PRUint32 delay);
+ static void RecordChromeHang(PRUint32 duration,
+ const Telemetry::HangStack &callStack,
+ SharedLibraryInfo &moduleMap);
static nsresult GetHistogramEnumId(const char *name, Telemetry::ID *id);
struct StmtStats {
PRUint32 hitCount;
PRUint32 totalTime;
};
typedef nsBaseHashtableET<nsCStringHashKey, StmtStats> SlowSQLEntryType;
+ struct HangReport {
+ PRUint32 duration;
+ Telemetry::HangStack callStack;
+ SharedLibraryInfo moduleMap;
+ };
private:
static bool StatementReflector(SlowSQLEntryType *entry, JSContext *cx,
JSObject *obj);
bool AddSQLInfo(JSContext *cx, JSObject *rootObj, bool mainThread);
// Like GetHistogramById, but returns the underlying C++ object, not the JS one.
nsresult GetHistogramByName(const nsACString &name, Histogram **ret);
@@ -176,16 +184,18 @@ private:
bool mCanRecord;
static TelemetryImpl *sTelemetry;
AutoHashtable<SlowSQLEntryType> mSlowSQLOnMainThread;
AutoHashtable<SlowSQLEntryType> mSlowSQLOnOtherThread;
// This gets marked immutable in debug builds, so we can't use
// AutoHashtable here.
nsTHashtable<nsCStringHashKey> mTrackedDBs;
Mutex mHashMutex;
+ nsTArray<HangReport> mHangReports;
+ Mutex mHangReportsMutex;
};
TelemetryImpl* TelemetryImpl::sTelemetry = NULL;
// A initializer to initialize histogram collection
StatisticsRecorder gStatisticsRecorder;
// Hardcoded probes
@@ -455,17 +465,18 @@ WrapAndReturnHistogram(Histogram *h, JSC
*ret = OBJECT_TO_JSVAL(obj);
JS_SetPrivate(obj, h);
return NS_OK;
}
TelemetryImpl::TelemetryImpl():
mHistogramMap(Telemetry::HistogramCount),
mCanRecord(XRE_GetProcessType() == GeckoProcessType_Default),
-mHashMutex("Telemetry::mHashMutex")
+mHashMutex("Telemetry::mHashMutex"),
+mHangReportsMutex("Telemetry::mHangReportsMutex")
{
// A whitelist to prevent Telemetry reporting on Addon & Thunderbird DBs
const char *trackedDBs[] = {
"addons.sqlite", "chromeappsstore.sqlite", "content-prefs.sqlite",
"cookies.sqlite", "downloads.sqlite", "extensions.sqlite",
"formhistory.sqlite", "index.sqlite", "permissions.sqlite", "places.sqlite",
"search.sqlite", "signons.sqlite", "urlclassifier3.sqlite",
"webappsstore.sqlite"
@@ -938,16 +949,154 @@ TelemetryImpl::GetSlowSQL(JSContext *cx,
// Add info about slow SQL queries on other threads
if (!AddSQLInfo(cx, root_obj, false))
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
+TelemetryImpl::GetChromeHangs(JSContext *cx, jsval *ret)
+{
+ MutexAutoLock hangReportMutex(mHangReportsMutex);
+ JSObject *reportArray = JS_NewArrayObject(cx, 0, nsnull);
+ if (!reportArray) {
+ return NS_ERROR_FAILURE;
+ }
+ *ret = OBJECT_TO_JSVAL(reportArray);
+
+ // Each hang report is an object in the 'chromeHangs' array
+ for (size_t i = 0; i < mHangReports.Length(); ++i) {
+ JSObject *reportObj = JS_NewObject(cx, NULL, NULL, NULL);
+ if (!reportObj) {
+ return NS_ERROR_FAILURE;
+ }
+ jsval reportObjVal = OBJECT_TO_JSVAL(reportObj);
+ if (!JS_SetElement(cx, reportArray, i, &reportObjVal)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Record the hang duration (expressed in seconds)
+ JSBool ok = JS_DefineProperty(cx, reportObj, "duration",
+ INT_TO_JSVAL(mHangReports[i].duration),
+ NULL, NULL, JSPROP_ENUMERATE);
+ if (!ok) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Represent call stack PCs as strings
+ // (JS can't represent all 64-bit integer values)
+ JSObject *pcArray = JS_NewArrayObject(cx, 0, nsnull);
+ if (!pcArray) {
+ return NS_ERROR_FAILURE;
+ }
+ ok = JS_DefineProperty(cx, reportObj, "stack", OBJECT_TO_JSVAL(pcArray),
+ NULL, NULL, JSPROP_ENUMERATE);
+ if (!ok) {
+ return NS_ERROR_FAILURE;
+ }
+
+ const PRUint32 pcCount = mHangReports[i].callStack.Length();
+ for (size_t pcIndex = 0; pcIndex < pcCount; ++pcIndex) {
+ nsCAutoString pcString;
+ pcString.AppendPrintf("0x%p", mHangReports[i].callStack[pcIndex]);
+ JSString *str = JS_NewStringCopyZ(cx, pcString.get());
+ if (!str) {
+ return NS_ERROR_FAILURE;
+ }
+ jsval v = STRING_TO_JSVAL(str);
+ if (!JS_SetElement(cx, pcArray, pcIndex, &v)) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ // Record memory map info
+ JSObject *moduleArray = JS_NewArrayObject(cx, 0, nsnull);
+ if (!moduleArray) {
+ return NS_ERROR_FAILURE;
+ }
+ ok = JS_DefineProperty(cx, reportObj, "memoryMap",
+ OBJECT_TO_JSVAL(moduleArray),
+ NULL, NULL, JSPROP_ENUMERATE);
+ if (!ok) {
+ return NS_ERROR_FAILURE;
+ }
+
+ const PRUint32 moduleCount = mHangReports[i].moduleMap.GetSize();
+ for (size_t moduleIndex = 0; moduleIndex < moduleCount; ++moduleIndex) {
+ // Current module
+ const SharedLibrary &module =
+ mHangReports[i].moduleMap.GetEntry(moduleIndex);
+
+ JSObject *moduleInfoArray = JS_NewArrayObject(cx, 0, nsnull);
+ if (!moduleInfoArray) {
+ return NS_ERROR_FAILURE;
+ }
+ jsval val = OBJECT_TO_JSVAL(moduleInfoArray);
+ if (!JS_SetElement(cx, moduleArray, moduleIndex, &val)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Start address
+ nsCAutoString addressString;
+ addressString.AppendPrintf("0x%p", module.GetStart());
+ JSString *str = JS_NewStringCopyZ(cx, addressString.get());
+ if (!str) {
+ return NS_ERROR_FAILURE;
+ }
+ val = STRING_TO_JSVAL(str);
+ if (!JS_SetElement(cx, moduleInfoArray, 0, &val)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Module name
+ str = JS_NewStringCopyZ(cx, module.GetName());
+ if (!str) {
+ return NS_ERROR_FAILURE;
+ }
+ val = STRING_TO_JSVAL(str);
+ if (!JS_SetElement(cx, moduleInfoArray, 1, &val)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Module size in memory
+ val = INT_TO_JSVAL(int32_t(module.GetEnd() - module.GetStart()));
+ if (!JS_SetElement(cx, moduleInfoArray, 2, &val)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // "PDB Age" identifier
+ val = INT_TO_JSVAL(0);
+#if defined(MOZ_PROFILING) && defined(XP_WIN)
+ val = INT_TO_JSVAL(module.GetPdbAge());
+#endif
+ if (!JS_SetElement(cx, moduleInfoArray, 3, &val)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // "PDB Signature" GUID
+ char guidString[NSID_LENGTH] = { 0 };
+#if defined(MOZ_PROFILING) && defined(XP_WIN)
+ module.GetPdbSignature().ToProvidedString(guidString);
+#endif
+ str = JS_NewStringCopyZ(cx, guidString);
+ if (!str) {
+ return NS_ERROR_FAILURE;
+ }
+ val = STRING_TO_JSVAL(str);
+ if (!JS_SetElement(cx, moduleInfoArray, 4, &val)) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
TelemetryImpl::GetRegisteredHistograms(JSContext *cx, jsval *ret)
{
size_t count = ArrayLength(gHistograms);
JSObject *info = JS_NewObject(cx, NULL, NULL, NULL);
if (!info)
return NS_ERROR_FAILURE;
JS::AutoObjectRooter root(cx, info);
@@ -1373,16 +1522,44 @@ TelemetryImpl::RecordSlowStatement(const
return;
entry->mData.hitCount = 0;
entry->mData.totalTime = 0;
}
entry->mData.hitCount++;
entry->mData.totalTime += delay;
}
+void
+TelemetryImpl::RecordChromeHang(PRUint32 duration,
+ const Telemetry::HangStack &callStack,
+ SharedLibraryInfo &moduleMap)
+{
+ MOZ_ASSERT(sTelemetry);
+ if (!sTelemetry->mCanRecord) {
+ return;
+ }
+
+ MutexAutoLock hangReportMutex(sTelemetry->mHangReportsMutex);
+
+ // Only report the modules which changed since the first hang report
+ if (sTelemetry->mHangReports.Length()) {
+ SharedLibraryInfo &firstModuleMap =
+ sTelemetry->mHangReports[0].moduleMap;
+ for (size_t i = 0; i < moduleMap.GetSize(); ++i) {
+ if (firstModuleMap.Contains(moduleMap.GetEntry(i))) {
+ moduleMap.RemoveEntries(i, i + 1);
+ --i;
+ }
+ }
+ }
+
+ HangReport newReport = { duration, callStack, moduleMap };
+ sTelemetry->mHangReports.AppendElement(newReport);
+}
+
NS_IMPL_THREADSAFE_ISUPPORTS1(TelemetryImpl, nsITelemetry)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelemetry, TelemetryImpl::CreateTelemetryInstance)
#define NS_TELEMETRY_CID \
{0xaea477f2, 0xb3a2, 0x469c, {0xaa, 0x29, 0x0a, 0x82, 0xd1, 0x32, 0xb8, 0x29}}
NS_DEFINE_NAMED_CID(NS_TELEMETRY_CID);
const Module::CIDEntry kTelemetryCIDs[] = {
@@ -1454,16 +1631,23 @@ RecordSlowSQLStatement(const nsACString
void Init()
{
// Make the service manager hold a long-lived reference to the service
nsCOMPtr<nsITelemetry> telemetryService =
do_GetService("@mozilla.org/base/telemetry;1");
MOZ_ASSERT(telemetryService);
}
+void RecordChromeHang(PRUint32 duration,
+ const Telemetry::HangStack &callStack,
+ SharedLibraryInfo &moduleMap)
+{
+ TelemetryImpl::RecordChromeHang(duration, callStack, moduleMap);
+}
+
} // namespace Telemetry
} // namespace mozilla
NSMODULE_DEFN(nsTelemetryModule) = &kTelemetryModule;
/**
* The XRE_TelemetryAdd function is to be used by embedding applications
* that can't use mozilla::Telemetry::Accumulate() directly.
--- a/toolkit/components/telemetry/Telemetry.h
+++ b/toolkit/components/telemetry/Telemetry.h
@@ -37,16 +37,19 @@
* ***** END LICENSE BLOCK ***** */
#ifndef Telemetry_h__
#define Telemetry_h__
#include "mozilla/GuardObjects.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/StartupTimeline.h"
+#include "nsTArray.h"
+#include "nsStringGlue.h"
+#include "shared-libraries.h"
namespace base {
class Histogram;
}
namespace mozilla {
namespace Telemetry {
@@ -151,11 +154,27 @@ void RecordSlowSQLStatement(const nsACSt
const nsACString &dbName,
PRUint32 delay);
/**
* Threshold for a statement to be considered slow, in milliseconds
*/
const PRUint32 kSlowStatementThreshold = 100;
+/**
+ * nsTArray of pointers representing PCs on a call stack
+ */
+typedef nsTArray<uintptr_t> HangStack;
+
+/**
+ * Record the main thread's call stack after it hangs.
+ *
+ * @param duration - Approximate duration of main thread hang in seconds
+ * @param callStack - Array of PCs from the hung call stack
+ * @param moduleMap - Array of info about modules in memory (for symbolication)
+ */
+void RecordChromeHang(PRUint32 duration,
+ const HangStack &callStack,
+ SharedLibraryInfo &moduleMap);
+
} // namespace Telemetry
} // namespace mozilla
#endif // Telemetry_h__
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -448,16 +448,17 @@ TelemetryPing.prototype = {
if (havePreviousSession) {
payloadObj.histograms = this.getHistograms(this._prevSession.snapshots);
}
else {
payloadObj.simpleMeasurements = getSimpleMeasurements();
payloadObj.histograms = this.getHistograms(Telemetry.histogramSnapshots);
payloadObj.slowSQL = Telemetry.slowSQL;
+ payloadObj.chromeHangs = Telemetry.chromeHangs;
payloadObj.addonHistograms = this.getAddonHistograms();
}
if (Object.keys(this._slowSQLStartup.mainThread).length
|| Object.keys(this._slowSQLStartup.otherThreads).length) {
payloadObj.slowSQLStartup = this._slowSQLStartup;
}
return { previous: !!havePreviousSession,
--- a/toolkit/components/telemetry/nsITelemetry.idl
+++ b/toolkit/components/telemetry/nsITelemetry.idl
@@ -65,17 +65,17 @@ interface nsITelemetryLoadSessionDataCal
};
[scriptable, function, uuid(40065f26-afd2-4417-93de-c1de9adb1548)]
interface nsITelemetrySaveSessionDataCallback : nsISupports
{
void handle(in bool success);
};
-[scriptable, uuid(db854295-478d-4de9-8211-d73ed7d81cd0)]
+[scriptable, uuid(f23a2c8d-9286-42e9-ab1b-ed287eeade6d)]
interface nsITelemetry : nsISupports
{
/**
* Histogram types:
* HISTOGRAM_EXPONENTIAL - buckets increase exponentially
* HISTOGRAM_LINEAR - buckets increase linearly
* HISTOGRAM_BOOLEAN - For storing 0/1 values
* HISTOGRAM_FLAG - For storing a single value; its count is always == 1.
@@ -113,16 +113,24 @@ interface nsITelemetry : nsISupports
* otherThreads: Slow statements that executed on a non-main thread
* sqlString - String of the offending prepared statement
* hit count - The number of times this statement required longer than the threshold time to execute
* total time - The sum of all execution times above the threshold time for this statement
*/
[implicit_jscontext]
readonly attribute jsval slowSQL;
+ /*
+ * An array of chrome hang reports. Each element is a hang report represented
+ * as an object containing the hang duration, call stack PCs and information
+ * about modules in memory.
+ */
+ [implicit_jscontext]
+ readonly attribute jsval chromeHangs;
+
/**
* An object whose properties are the names of histograms defined in
* TelemetryHistograms.h and whose corresponding values are the textual
* comments associated with said histograms.
*/
[implicit_jscontext]
readonly attribute jsval registeredHistograms;
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -51,17 +51,16 @@ SHARED_LIBRARY_LIBS += \
$(foreach lib,$(STATIC_LIBS),$(DEPTH)/staticlib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX)) \
$(NULL)
CPPSRCS += \
nsStaticXULComponents.cpp \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
-REQUIRES += widget gfx
CPPSRCS += \
nsDllMain.cpp \
$(NULL)
endif
ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
CPPSRCS += \
nsGFXDeps.cpp \
@@ -77,17 +76,16 @@ LOCAL_INCLUDES += -I$(topsrcdir)/widget/
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
endif
ifneq (,$(filter WINNT OS2,$(OS_ARCH)))
DEFINES += -DZLIB_DLL=1
endif
ifeq ($(OS_ARCH),OS2)
-REQUIRES += widget gfx
CPPSRCS += \
nsGFXDeps.cpp \
$(NULL)
ifndef MOZ_NATIVE_ZLIB
CPPSRCS += dlldeps-zlib.cpp
endif
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -822,20 +822,22 @@ ifdef NO_PKG_FILES
endif
ifdef MOZ_PKG_REMOVALS
$(SYSINSTALL) $(IFLAGS1) $(MOZ_PKG_REMOVALS_GEN) $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)
endif # MOZ_PKG_REMOVALS
ifdef MOZ_POST_STAGING_CMD
cd $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH) && $(MOZ_POST_STAGING_CMD)
endif # MOZ_POST_STAGING_CMD
ifndef LIBXUL_SDK
+ifdef MOZ_PACKAGE_JSSHELL
# Package JavaScript Shell
@echo "Packaging JavaScript Shell..."
$(RM) $(PKG_JSSHELL)
$(MAKE_JSSHELL)
+endif # MOZ_PACKAGE_JSSHELL
endif # LIBXUL_SDK
make-package: stage-package $(PACKAGE_XULRUNNER) make-sourcestamp-file
@echo "Compressing..."
cd $(DIST) && $(MAKE_PACKAGE)
make-sourcestamp-file::
$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
--- a/tools/profiler/Makefile.in
+++ b/tools/profiler/Makefile.in
@@ -43,16 +43,17 @@ srcdir = @srcdir@
VPATH = $(srcdir)
include $(DEPTH)/config/autoconf.mk
EXPORTS = \
sampler.h \
sps_sampler.h \
thread_helper.h \
+ shared-libraries.h \
$(NULL)
LOCAL_INCLUDES += \
-I$(topsrcdir)/ipc/chromium/src \
$(NULL)
MODULE = profiler
MODULE_NAME = nsProfilerModule
--- a/tools/profiler/nsIProfiler.idl
+++ b/tools/profiler/nsIProfiler.idl
@@ -49,12 +49,16 @@ interface nsIProfiler : nsISupports
void GetResponsivenessTimes(out PRUint32 aCount, [retval, array, size_is(aCount)] out double aResult);
void GetFeatures(out PRUint32 aCount, [retval, array, size_is(aCount)] out string aFeatures);
/**
* Returns a JSON string of an array of shared library objects.
* Every object has three properties: start, end, and name.
* start and end are integers describing the address range that the library
* occupies in memory. name is the path of the library as a string.
+ *
+ * On Windows profiling builds, the shared library objects will have
+ * additional pdbSignature and pdbAge properties for uniquely identifying
+ * shared library versions for stack symbolication.
*/
AString getSharedLibraryInformation();
};
--- a/tools/profiler/nsProfiler.cpp
+++ b/tools/profiler/nsProfiler.cpp
@@ -91,16 +91,20 @@ nsProfiler::GetProfile(char **aProfile)
static void
AddSharedLibraryInfoToStream(std::ostream& aStream, SharedLibrary& aLib)
{
aStream << "{";
aStream << "\"start\":" << aLib.GetStart();
aStream << ",\"end\":" << aLib.GetEnd();
aStream << ",\"name\":\"" << aLib.GetName() << "\"";
+#ifdef XP_WIN
+ aStream << ",\"pdbSignature\":\"" << aLib.GetPdbSignature().ToString() << "\"";
+ aStream << ",\"pdbAge\":" << aLib.GetPdbAge();
+#endif
aStream << "}";
}
static std::string
GetSharedLibraryInfoString()
{
SharedLibraryInfo info = SharedLibraryInfo::GetInfoForSelf();
if (info.GetSize() == 0)
--- a/tools/profiler/shared-libraries-win32.cc
+++ b/tools/profiler/shared-libraries-win32.cc
@@ -16,16 +16,17 @@
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jeff Muizelaar <jmuizelaar@mozilla.com>
+ * Vladan Djeric <vdjeric@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
@@ -33,33 +34,94 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <windows.h>
#include <tlhelp32.h>
+#include <Dbghelp.h>
#include "shared-libraries.h"
#include "nsWindowsHelpers.h"
+#define CV_SIGNATURE 0x53445352 // 'SDSR'
+
+struct CodeViewRecord70
+{
+ uint32_t signature;
+ GUID pdbSignature;
+ uint32_t pdbAge;
+ uint8_t pdbFileName[1];
+};
+
+static bool GetPdbInfo(uintptr_t aStart, nsID& aSignature, uint32_t& aAge)
+{
+ if (!aStart) {
+ return false;
+ }
+
+ PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(aStart);
+ if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
+ return false;
+ }
+
+ PIMAGE_NT_HEADERS ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
+ aStart + dosHeader->e_lfanew);
+ if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
+ return false;
+ }
+
+ uint32_t relativeVirtualAddress =
+ ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ if (!relativeVirtualAddress) {
+ return false;
+ }
+
+ PIMAGE_DEBUG_DIRECTORY debugDirectory =
+ reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>(aStart + relativeVirtualAddress);
+ if (!debugDirectory || debugDirectory->Type != IMAGE_DEBUG_TYPE_CODEVIEW) {
+ return false;
+ }
+
+ CodeViewRecord70 *debugInfo = reinterpret_cast<CodeViewRecord70 *>(
+ aStart + debugDirectory->AddressOfRawData);
+ if (!debugInfo || debugInfo->signature != CV_SIGNATURE) {
+ return false;
+ }
+
+ aAge = debugInfo->pdbAge;
+ GUID& pdbSignature = debugInfo->pdbSignature;
+ aSignature.m0 = pdbSignature.Data1;
+ aSignature.m1 = pdbSignature.Data2;
+ aSignature.m2 = pdbSignature.Data3;
+ memcpy(aSignature.m3, pdbSignature.Data4, sizeof(pdbSignature.Data4));
+ return true;
+}
+
SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf()
{
SharedLibraryInfo sharedLibraryInfo;
nsAutoHandle snap(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()));
MODULEENTRY32 module = {0};
module.dwSize = sizeof(MODULEENTRY32);
if (Module32First(snap, &module)) {
do {
- SharedLibrary shlib((uintptr_t)module.modBaseAddr,
- (uintptr_t)module.modBaseAddr+module.modBaseSize,
- 0, // DLLs are always mapped at offset 0 on Windows
- module.szModule);
- sharedLibraryInfo.AddSharedLibrary(shlib);
+ nsID pdbSig;
+ uint32_t pdbAge;
+ if (GetPdbInfo((uintptr_t)module.modBaseAddr, pdbSig, pdbAge)) {
+ SharedLibrary shlib((uintptr_t)module.modBaseAddr,
+ (uintptr_t)module.modBaseAddr+module.modBaseSize,
+ 0, // DLLs are always mapped at offset 0 on Windows
+ pdbSig,
+ pdbAge,
+ module.szModule);
+ sharedLibraryInfo.AddSharedLibrary(shlib);
+ }
} while (Module32Next(snap, &module));
}
return sharedLibraryInfo;
}
--- a/tools/profiler/shared-libraries.h
+++ b/tools/profiler/shared-libraries.h
@@ -31,83 +31,159 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
+#include <algorithm>
#include <vector>
#include <string.h>
#include <stdlib.h>
#include <mozilla/StandardInteger.h>
+#include <nsID.h>
class SharedLibrary {
public:
- SharedLibrary(unsigned long aStart, unsigned long aEnd, unsigned long aOffset, char *aName)
+
+ SharedLibrary(unsigned long aStart,
+ unsigned long aEnd,
+ unsigned long aOffset,
+#ifdef XP_WIN
+ nsID aPdbSignature,
+ unsigned long aPdbAge,
+#endif
+ char *aName)
: mStart(aStart)
, mEnd(aEnd)
, mOffset(aOffset)
+#ifdef XP_WIN
+ , mPdbSignature(aPdbSignature)
+ , mPdbAge(aPdbAge)
+#endif
, mName(strdup(aName))
{}
SharedLibrary(const SharedLibrary& aEntry)
: mStart(aEntry.mStart)
, mEnd(aEntry.mEnd)
, mOffset(aEntry.mOffset)
+#ifdef XP_WIN
+ , mPdbSignature(aEntry.mPdbSignature)
+ , mPdbAge(aEntry.mPdbAge)
+#endif
, mName(strdup(aEntry.mName))
{}
SharedLibrary& operator=(const SharedLibrary& aEntry)
{
// Gracefully handle self assignment
if (this == &aEntry) return *this;
mStart = aEntry.mStart;
mEnd = aEntry.mEnd;
mOffset = aEntry.mOffset;
+#ifdef XP_WIN
+ mPdbSignature = aEntry.mPdbSignature;
+ mPdbAge = aEntry.mPdbAge;
+#endif
if (mName)
free(mName);
mName = strdup(aEntry.mName);
return *this;
}
+ bool operator==(const SharedLibrary& other) const
+ {
+ bool equal = ((mStart == other.mStart) &&
+ (mEnd == other.mEnd) &&
+ (mOffset == other.mOffset) &&
+ (mName && other.mName && (strcmp(mName, other.mName) == 0)));
+#ifdef XP_WIN
+ equal = equal &&
+ (mPdbSignature.Equals(other.mPdbSignature)) &&
+ (mPdbAge == other.mPdbAge);
+#endif
+ return equal;
+ }
+
~SharedLibrary()
{
free(mName);
+ mName = NULL;
}
- uintptr_t GetStart() { return mStart; }
- uintptr_t GetEnd() { return mEnd; }
- char* GetName() { return mName; }
+ uintptr_t GetStart() const { return mStart; }
+ uintptr_t GetEnd() const { return mEnd; }
+#ifdef XP_WIN
+ nsID GetPdbSignature() const { return mPdbSignature; }
+ uint32_t GetPdbAge() const { return mPdbAge; }
+#endif
+ char* GetName() const { return mName; }
private:
explicit SharedLibrary() {}
uintptr_t mStart;
uintptr_t mEnd;
uintptr_t mOffset;
+#ifdef XP_WIN
+ // Windows-specific PDB file identifiers
+ nsID mPdbSignature;
+ uint32_t mPdbAge;
+#endif
char *mName;
};
+static bool
+CompareAddresses(const SharedLibrary& first, const SharedLibrary& second)
+{
+ return first.GetStart() < second.GetStart();
+}
+
class SharedLibraryInfo {
public:
static SharedLibraryInfo GetInfoForSelf();
SharedLibraryInfo() {}
void AddSharedLibrary(SharedLibrary entry)
{
mEntries.push_back(entry);
}
SharedLibrary& GetEntry(size_t i)
{
return mEntries[i];
}
- size_t GetSize()
+ // Removes items in the range [first, last)
+ // i.e. element at the "last" index is not removed
+ void RemoveEntries(size_t first, size_t last)
+ {
+ mEntries.erase(mEntries.begin() + first, mEntries.begin() + last);
+ }
+
+ bool Contains(const SharedLibrary& searchItem) const
+ {
+ return (mEntries.end() !=
+ std::find(mEntries.begin(), mEntries.end(), searchItem));
+ }
+
+ size_t GetSize() const
{
return mEntries.size();
}
+
+ void SortByAddress()
+ {
+ std::sort(mEntries.begin(), mEntries.end(), CompareAddresses);
+ }
+
+ void Clear()
+ {
+ mEntries.clear();
+ }
+
private:
std::vector<SharedLibrary> mEntries;
};
--- a/xpcom/threads/HangMonitor.cpp
+++ b/xpcom/threads/HangMonitor.cpp
@@ -33,37 +33,45 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/HangMonitor.h"
#include "mozilla/Monitor.h"
#include "mozilla/Preferences.h"
+#include "mozilla/Telemetry.h"
#include "nsXULAppAPI.h"
#include "nsThreadUtils.h"
+#include "nsStackWalk.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
#ifdef XP_WIN
#include <windows.h>
#endif
+#if defined(MOZ_PROFILING) && defined(XP_WIN)
+ #define REPORT_CHROME_HANGS
+#endif
+
namespace mozilla { namespace HangMonitor {
/**
* A flag which may be set from within a debugger to disable the hang
* monitor.
*/
volatile bool gDebugDisableHangMonitor = false;
const char kHangMonitorPrefName[] = "hangmonitor.timeout";
+const char kTelemetryPrefName[] = "toolkit.telemetry.enabled";
+
// Monitor protects gShutdown and gTimeout, but not gTimestamp which rely on
// being atomically set by the processor; synchronization doesn't really matter
// in this use case.
Monitor* gMonitor;
// The timeout preference, in seconds.
PRInt32 gTimeout;
@@ -71,21 +79,38 @@ PRThread* gThread;
// Set when shutdown begins to signal the thread to exit immediately.
bool gShutdown;
// The timestamp of the last event notification, or PR_INTERVAL_NO_WAIT if
// we're currently not processing events.
volatile PRIntervalTime gTimestamp;
+#ifdef REPORT_CHROME_HANGS
+// Main thread ID used in reporting chrome hangs under Windows
+static HANDLE winMainThreadHandle = NULL;
+
+// Default timeout for reporting chrome hangs to Telemetry (10 seconds)
+static const PRInt32 DEFAULT_CHROME_HANG_INTERVAL = 10;
+#endif
+
// PrefChangedFunc
int
PrefChanged(const char*, void*)
{
PRInt32 newval = Preferences::GetInt(kHangMonitorPrefName);
+#ifdef REPORT_CHROME_HANGS
+ // Monitor chrome hangs on the profiling branch if Telemetry enabled
+ if (newval == 0) {
+ PRBool telemetryEnabled = Preferences::GetBool(kTelemetryPrefName);
+ if (telemetryEnabled) {
+ newval = DEFAULT_CHROME_HANG_INTERVAL;
+ }
+ }
+#endif
MonitorAutoLock lock(*gMonitor);
if (newval != gTimeout) {
gTimeout = newval;
lock.Notify();
}
return 0;
}
@@ -106,27 +131,100 @@ Crash()
#ifdef MOZ_CRASHREPORTER
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Hang"),
NS_LITERAL_CSTRING("1"));
#endif
NS_RUNTIMEABORT("HangMonitor triggered");
}
+#ifdef REPORT_CHROME_HANGS
+static void
+ChromeStackWalker(void *aPC, void *aClosure)
+{
+ MOZ_ASSERT(aClosure);
+ Telemetry::HangStack *callStack =
+ reinterpret_cast< Telemetry::HangStack* >(aClosure);
+ callStack->AppendElement(reinterpret_cast<uintptr_t>(aPC));
+}
+
+static void
+GetChromeHangReport(Telemetry::HangStack &callStack, SharedLibraryInfo &moduleMap)
+{
+ MOZ_ASSERT(winMainThreadHandle);
+ moduleMap = SharedLibraryInfo::GetInfoForSelf();
+ moduleMap.SortByAddress();
+
+ DWORD ret = ::SuspendThread(winMainThreadHandle);
+ if (ret == -1) {
+ callStack.Clear();
+ moduleMap.Clear();
+ return;
+ }
+ NS_StackWalk(ChromeStackWalker, 0, &callStack,
+ reinterpret_cast<uintptr_t>(winMainThreadHandle));
+ ret = ::ResumeThread(winMainThreadHandle);
+ if (ret == -1) {
+ callStack.Clear();
+ moduleMap.Clear();
+ return;
+ }
+
+ // Remove all modules not referenced by a PC on the stack
+ Telemetry::HangStack sortedStack = callStack;
+ sortedStack.Sort();
+
+ size_t moduleIndex = 0;
+ size_t stackIndex = 0;
+ bool unreferencedModule = true;
+ while (stackIndex < sortedStack.Length() && moduleIndex < moduleMap.GetSize()) {
+ uintptr_t pc = sortedStack[stackIndex];
+ SharedLibrary& module = moduleMap.GetEntry(moduleIndex);
+ uintptr_t moduleStart = module.GetStart();
+ uintptr_t moduleEnd = module.GetEnd() - 1;
+ if (moduleStart <= pc && pc <= moduleEnd) {
+ // If the current PC is within the current module, mark module as used
+ unreferencedModule = false;
+ ++stackIndex;
+ } else if (pc > moduleEnd) {
+ if (unreferencedModule) {
+ // Remove module if no PCs within its address range
+ moduleMap.RemoveEntries(moduleIndex, moduleIndex + 1);
+ } else {
+ // Module was referenced on stack, but current PC belongs to later module
+ unreferencedModule = true;
+ ++moduleIndex;
+ }
+ } else {
+ // PC does not belong to any module
+ ++stackIndex;
+ }
+ }
+
+ // Clean up remaining unreferenced modules, i.e. module addresses > max(pc)
+ if (moduleIndex + 1 < moduleMap.GetSize()) {
+ moduleMap.RemoveEntries(moduleIndex + 1, moduleMap.GetSize());
+ }
+}
+#endif
+
void
ThreadMain(void*)
{
MonitorAutoLock lock(*gMonitor);
// In order to avoid issues with the hang monitor incorrectly triggering
// during a general system stop such as sleeping, the monitor thread must
// run twice to trigger hang protection.
PRIntervalTime lastTimestamp = 0;
int waitCount = 0;
+ Telemetry::HangStack hangStack;
+ SharedLibraryInfo hangModuleMap;
+
while (true) {
if (gShutdown) {
return; // Exit the thread
}
// avoid rereading the volatile value in this loop
PRIntervalTime timestamp = gTimestamp;
@@ -138,25 +236,37 @@ ThreadMain(void*)
timestamp = 1; // lowest legal PRInterval value
}
if (timestamp != PR_INTERVAL_NO_WAIT &&
timestamp == lastTimestamp &&
gTimeout > 0) {
++waitCount;
if (waitCount == 2) {
+#ifdef REPORT_CHROME_HANGS
+ GetChromeHangReport(hangStack, hangModuleMap);
+#else
PRInt32 delay =
PRInt32(PR_IntervalToSeconds(now - timestamp));
if (delay > gTimeout) {
MonitorAutoUnlock unlock(*gMonitor);
Crash();
}
+#endif
}
}
else {
+#ifdef REPORT_CHROME_HANGS
+ if (waitCount >= 2) {
+ PRUint32 hangDuration = PR_IntervalToSeconds(now - lastTimestamp);
+ Telemetry::RecordChromeHang(hangDuration, hangStack, hangModuleMap);
+ hangStack.Clear();
+ hangModuleMap.Clear();
+ }
+#endif
lastTimestamp = timestamp;
waitCount = 0;
}
PRIntervalTime timeout;
if (gTimeout <= 0) {
timeout = PR_INTERVAL_NO_TIMEOUT;
}
@@ -177,16 +287,24 @@ Startup()
return;
NS_ASSERTION(!gMonitor, "Hang monitor already initialized");
gMonitor = new Monitor("HangMonitor");
Preferences::RegisterCallback(PrefChanged, kHangMonitorPrefName, NULL);
PrefChanged(NULL, NULL);
+#ifdef REPORT_CHROME_HANGS
+ Preferences::RegisterCallback(PrefChanged, kTelemetryPrefName, NULL);
+ winMainThreadHandle =
+ OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId());
+ if (!winMainThreadHandle)
+ return;
+#endif
+
// Don't actually start measuring hangs until we hit the main event loop.
// This potentially misses a small class of really early startup hangs,
// but avoids dealing with some xpcshell tests and other situations which
// start XPCOM but don't ever start the event loop.
Suspend();
gThread = PR_CreateThread(PR_USER_THREAD,
ThreadMain,