зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to m-c.
This commit is contained in:
Коммит
a1cab9283c
|
@ -165,114 +165,58 @@ ARIAGridAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ARIAGridAccessible::GetColumnDescription(PRInt32 aColumn,
|
||||
nsAString& aDescription)
|
||||
bool
|
||||
ARIAGridAccessible::IsColSelected(PRUint32 aColIdx)
|
||||
{
|
||||
aDescription.Truncate();
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ENSURE_ARG(IsValidColumn(aColumn));
|
||||
|
||||
// XXX: not implemented
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ARIAGridAccessible::GetRowDescription(PRInt32 aRow, nsAString& aDescription)
|
||||
{
|
||||
aDescription.Truncate();
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ENSURE_ARG(IsValidRow(aRow));
|
||||
|
||||
// XXX: not implemented
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ARIAGridAccessible::IsColumnSelected(PRInt32 aColumn, bool* aIsSelected)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ENSURE_ARG(IsValidColumn(aColumn));
|
||||
|
||||
AccIterator rowIter(this, filters::GetRow);
|
||||
Accessible* row = rowIter.Next();
|
||||
if (!row)
|
||||
return NS_OK;
|
||||
return false;
|
||||
|
||||
do {
|
||||
if (!nsAccUtils::IsARIASelected(row)) {
|
||||
Accessible* cell = GetCellInRowAt(row, aColumn);
|
||||
if (!cell) // Do not fail due to wrong markup
|
||||
return NS_OK;
|
||||
|
||||
if (!nsAccUtils::IsARIASelected(cell))
|
||||
return NS_OK;
|
||||
Accessible* cell = GetCellInRowAt(row, aColIdx);
|
||||
if (!cell || !nsAccUtils::IsARIASelected(cell))
|
||||
return false;
|
||||
}
|
||||
} while ((row = rowIter.Next()));
|
||||
|
||||
*aIsSelected = true;
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ARIAGridAccessible::IsRowSelected(PRInt32 aRow, bool* aIsSelected)
|
||||
bool
|
||||
ARIAGridAccessible::IsRowSelected(PRUint32 aRowIdx)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
Accessible* row = GetRowAt(aRow);
|
||||
NS_ENSURE_ARG(row);
|
||||
Accessible* row = GetRowAt(aRowIdx);
|
||||
if(!row)
|
||||
return false;
|
||||
|
||||
if (!nsAccUtils::IsARIASelected(row)) {
|
||||
AccIterator cellIter(row, filters::GetCell);
|
||||
Accessible* cell = nsnull;
|
||||
while ((cell = cellIter.Next())) {
|
||||
if (!nsAccUtils::IsARIASelected(cell))
|
||||
return NS_OK;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*aIsSelected = true;
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ARIAGridAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
|
||||
bool* aIsSelected)
|
||||
bool
|
||||
ARIAGridAccessible::IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
Accessible* row = GetRowAt(aRow);
|
||||
NS_ENSURE_ARG(row);
|
||||
Accessible* row = GetRowAt(aRowIdx);
|
||||
if(!row)
|
||||
return false;
|
||||
|
||||
if (!nsAccUtils::IsARIASelected(row)) {
|
||||
Accessible* cell = GetCellInRowAt(row, aColumn);
|
||||
NS_ENSURE_ARG(cell);
|
||||
|
||||
if (!nsAccUtils::IsARIASelected(cell))
|
||||
return NS_OK;
|
||||
Accessible* cell = GetCellInRowAt(row, aColIdx);
|
||||
if (!cell || !nsAccUtils::IsARIASelected(cell))
|
||||
return false;
|
||||
}
|
||||
|
||||
*aIsSelected = true;
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
|
||||
|
||||
// Accessible
|
||||
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
|
||||
virtual TableAccessible* AsTable() { return this; }
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
|
@ -42,6 +42,9 @@ public:
|
|||
virtual PRUint32 ColCount();
|
||||
virtual PRUint32 RowCount();
|
||||
virtual Accessible* CellAt(PRUint32 aRowIndex, PRUint32 aColumnIndex);
|
||||
virtual bool IsColSelected(PRUint32 aColIdx);
|
||||
virtual bool IsRowSelected(PRUint32 aRowIdx);
|
||||
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx);
|
||||
virtual void SelectCol(PRUint32 aColIdx);
|
||||
virtual void SelectRow(PRUint32 aRowIdx);
|
||||
virtual void UnselectCol(PRUint32 aColIdx);
|
||||
|
|
|
@ -972,108 +972,62 @@ HTMLTableAccessible::RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx)
|
|||
return rowExtent;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLTableAccessible::GetColumnDescription(PRInt32 aColumn, nsAString& _retval)
|
||||
bool
|
||||
HTMLTableAccessible::IsColSelected(PRUint32 aColIdx)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
bool isSelected = false;
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLTableAccessible::GetRowDescription(PRInt32 aRow, nsAString& _retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLTableAccessible::IsColumnSelected(PRInt32 aColumn, bool* aIsSelected)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
PRInt32 colCount = 0;
|
||||
nsresult rv = GetColumnCount(&colCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aColumn < 0 || aColumn >= colCount)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
PRInt32 rowCount = 0;
|
||||
rv = GetRowCount(&rowCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRInt32 rowIdx = 0; rowIdx < rowCount; rowIdx++) {
|
||||
bool isSelected = false;
|
||||
rv = IsCellSelected(rowIdx, aColumn, &isSelected);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aIsSelected = isSelected;
|
||||
if (!isSelected)
|
||||
break;
|
||||
}
|
||||
PRUint32 rowCount = RowCount();
|
||||
for (PRUint32 rowIdx = 0; rowIdx < rowCount; rowIdx++) {
|
||||
isSelected = IsCellSelected(rowIdx, aColIdx);
|
||||
if (!isSelected)
|
||||
return false;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return isSelected;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLTableAccessible::IsRowSelected(PRInt32 aRow, bool* aIsSelected)
|
||||
bool
|
||||
HTMLTableAccessible::IsRowSelected(PRUint32 aRowIdx)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
bool isSelected = false;
|
||||
|
||||
PRInt32 rowCount = 0;
|
||||
nsresult rv = GetRowCount(&rowCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aRow < 0 || aRow >= rowCount)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
PRInt32 colCount = 0;
|
||||
rv = GetColumnCount(&colCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRInt32 colIdx = 0; colIdx < colCount; colIdx++) {
|
||||
bool isSelected = false;
|
||||
rv = IsCellSelected(aRow, colIdx, &isSelected);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aIsSelected = isSelected;
|
||||
if (!isSelected)
|
||||
break;
|
||||
}
|
||||
PRUint32 colCount = ColCount();
|
||||
for (PRUint32 colIdx = 0; colIdx < colCount; colIdx++) {
|
||||
isSelected = IsCellSelected(aRowIdx, colIdx);
|
||||
if (!isSelected)
|
||||
return false;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return isSelected;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLTableAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
|
||||
bool* aIsSelected)
|
||||
bool
|
||||
HTMLTableAccessible::IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
nsITableLayout *tableLayout = GetTableLayout();
|
||||
NS_ENSURE_STATE(tableLayout);
|
||||
if (!tableLayout)
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> domElement;
|
||||
PRInt32 startRowIndex = 0, startColIndex = 0,
|
||||
rowSpan, colSpan, actualRowSpan, actualColSpan;
|
||||
bool isSelected = false;
|
||||
|
||||
nsresult rv = tableLayout->
|
||||
GetCellDataAt(aRow, aColumn, *getter_AddRefs(domElement),
|
||||
startRowIndex, startColIndex, rowSpan, colSpan,
|
||||
actualRowSpan, actualColSpan, *aIsSelected);
|
||||
tableLayout->GetCellDataAt(aRowIdx, aColIdx, *getter_AddRefs(domElement),
|
||||
startRowIndex, startColIndex, rowSpan, colSpan,
|
||||
actualRowSpan, actualColSpan, isSelected);
|
||||
|
||||
if (rv == NS_TABLELAYOUT_CELL_NOT_FOUND)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
return rv;
|
||||
return isSelected;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLTableAccessible::SelectRow(PRUint32 aRowIdx)
|
||||
{
|
||||
nsresult rv = RemoveRowsOrColumnsFromSelection(aRowIdx,
|
||||
nsISelectionPrivate::TABLESELECTION_ROW,
|
||||
true);
|
||||
nsresult rv =
|
||||
RemoveRowsOrColumnsFromSelection(aRowIdx,
|
||||
nsISelectionPrivate::TABLESELECTION_ROW,
|
||||
true);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"RemoveRowsOrColumnsFromSelection() Shouldn't fail!");
|
||||
|
||||
|
@ -1083,9 +1037,10 @@ HTMLTableAccessible::SelectRow(PRUint32 aRowIdx)
|
|||
void
|
||||
HTMLTableAccessible::SelectCol(PRUint32 aColIdx)
|
||||
{
|
||||
nsresult rv = RemoveRowsOrColumnsFromSelection(aColIdx,
|
||||
nsISelectionPrivate::TABLESELECTION_COLUMN,
|
||||
true);
|
||||
nsresult rv =
|
||||
RemoveRowsOrColumnsFromSelection(aColIdx,
|
||||
nsISelectionPrivate::TABLESELECTION_COLUMN,
|
||||
true);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"RemoveRowsOrColumnsFromSelection() Shouldn't fail!");
|
||||
|
||||
|
|
|
@ -106,6 +106,9 @@ public:
|
|||
virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx);
|
||||
virtual PRUint32 ColExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx);
|
||||
virtual PRUint32 RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx);
|
||||
virtual bool IsColSelected(PRUint32 aColIdx);
|
||||
virtual bool IsRowSelected(PRUint32 aRowIdx);
|
||||
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx);
|
||||
virtual void SelectCol(PRUint32 aColIdx);
|
||||
virtual void SelectRow(PRUint32 aRowIdx);
|
||||
virtual void UnselectCol(PRUint32 aColIdx);
|
||||
|
@ -116,7 +119,7 @@ public:
|
|||
virtual void Shutdown();
|
||||
|
||||
// Accessible
|
||||
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
|
||||
virtual TableAccessible* AsTable() { return this; }
|
||||
virtual void Description(nsString& aDescription);
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
virtual a11y::role NativeRole();
|
||||
|
|
|
@ -304,7 +304,9 @@ AndroidPresenter.prototype = {
|
|||
type: 'Accessibility:Event',
|
||||
eventType: this.ANDROID_VIEW_TEXT_CHANGED,
|
||||
text: [aText],
|
||||
fromIndex: aStart
|
||||
fromIndex: aStart,
|
||||
removedCount: 0,
|
||||
addedCount: 0
|
||||
};
|
||||
|
||||
if (aIsInserted) {
|
||||
|
|
|
@ -15,7 +15,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(HyperTextAccessibleWrap,
|
|||
IMPL_IUNKNOWN_INHERITED2(HyperTextAccessibleWrap,
|
||||
AccessibleWrap,
|
||||
ia2AccessibleHypertext,
|
||||
CAccessibleEditableText);
|
||||
ia2AccessibleEditableText);
|
||||
|
||||
nsresult
|
||||
HyperTextAccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
||||
|
|
|
@ -9,13 +9,12 @@
|
|||
#define mozilla_a11y_HyperTextAccessibleWrap_h__
|
||||
|
||||
#include "HyperTextAccessible.h"
|
||||
#include "CAccessibleText.h"
|
||||
#include "CAccessibleEditableText.h"
|
||||
#include "ia2AccessibleEditableText.h"
|
||||
#include "ia2AccessibleHyperText.h"
|
||||
|
||||
class HyperTextAccessibleWrap : public HyperTextAccessible,
|
||||
public ia2AccessibleHypertext,
|
||||
public CAccessibleEditableText
|
||||
public ia2AccessibleEditableText
|
||||
{
|
||||
public:
|
||||
HyperTextAccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
|
|
|
@ -26,8 +26,6 @@ CPPSRCS = \
|
|||
nsAccessNodeWrap.cpp \
|
||||
nsHTMLWin32ObjectAccessible.cpp \
|
||||
nsWinUtils.cpp \
|
||||
CAccessibleText.cpp \
|
||||
CAccessibleEditableText.cpp \
|
||||
CAccessibleHyperlink.cpp \
|
||||
CAccessibleTable.cpp \
|
||||
CAccessibleTableCell.cpp \
|
||||
|
@ -36,9 +34,11 @@ CPPSRCS = \
|
|||
EnumVariant.cpp \
|
||||
ia2AccessibleAction.cpp \
|
||||
ia2AccessibleComponent.cpp \
|
||||
ia2AccessibleEditableText.cpp \
|
||||
ia2AccessibleImage.cpp \
|
||||
ia2AccessibleHypertext.cpp \
|
||||
ia2AccessibleRelation.cpp \
|
||||
ia2AccessibleText.cpp \
|
||||
RootAccessibleWrap.cpp \
|
||||
TextLeafAccessibleWrap.cpp \
|
||||
$(NULL)
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CAccessibleEditableText.h"
|
||||
#include "ia2AccessibleEditableText.h"
|
||||
|
||||
#include "AccessibleEditableText_i.c"
|
||||
#include "HyperTextAccessible.h"
|
||||
#include "HyperTextAccessibleWrap.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
@ -16,7 +16,7 @@
|
|||
// IUnknown
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleEditableText::QueryInterface(REFIID iid, void** ppv)
|
||||
ia2AccessibleEditableText::QueryInterface(REFIID iid, void** ppv)
|
||||
{
|
||||
*ppv = NULL;
|
||||
|
||||
|
@ -35,10 +35,10 @@ CAccessibleEditableText::QueryInterface(REFIID iid, void** ppv)
|
|||
// IAccessibleEditableText
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleEditableText::copyText(long aStartOffset, long aEndOffset)
|
||||
ia2AccessibleEditableText::copyText(long aStartOffset, long aEndOffset)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -50,10 +50,10 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleEditableText::deleteText(long aStartOffset, long aEndOffset)
|
||||
ia2AccessibleEditableText::deleteText(long aStartOffset, long aEndOffset)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -65,10 +65,10 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleEditableText::insertText(long aOffset, BSTR *aText)
|
||||
ia2AccessibleEditableText::insertText(long aOffset, BSTR *aText)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -83,10 +83,10 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleEditableText::cutText(long aStartOffset, long aEndOffset)
|
||||
ia2AccessibleEditableText::cutText(long aStartOffset, long aEndOffset)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -98,10 +98,10 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleEditableText::pasteText(long aOffset)
|
||||
ia2AccessibleEditableText::pasteText(long aOffset)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -113,11 +113,11 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleEditableText::replaceText(long aStartOffset, long aEndOffset,
|
||||
BSTR *aText)
|
||||
ia2AccessibleEditableText::replaceText(long aStartOffset, long aEndOffset,
|
||||
BSTR *aText)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -136,8 +136,8 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleEditableText::setAttributes(long aStartOffset, long aEndOffset,
|
||||
BSTR *aAttributes)
|
||||
ia2AccessibleEditableText::setAttributes(long aStartOffset, long aEndOffset,
|
||||
BSTR *aAttributes)
|
||||
{
|
||||
__try {
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "AccessibleEditableText.h"
|
||||
|
||||
class CAccessibleEditableText: public IAccessibleEditableText
|
||||
class ia2AccessibleEditableText: public IAccessibleEditableText
|
||||
{
|
||||
public:
|
||||
|
|
@ -27,7 +27,7 @@ ia2AccessibleHypertext::QueryInterface(REFIID iid, void** ppv)
|
|||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
return CAccessibleText::QueryInterface(iid, ppv);
|
||||
return ia2AccessibleText::QueryInterface(iid, ppv);
|
||||
}
|
||||
|
||||
// IAccessibleHypertext
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
|
||||
#include "nsISupports.h"
|
||||
|
||||
#include "CAccessibleText.h"
|
||||
#include "ia2AccessibleText.h"
|
||||
#include "AccessibleHypertext.h"
|
||||
|
||||
class ia2AccessibleHypertext : public CAccessibleText,
|
||||
class ia2AccessibleHypertext : public ia2AccessibleText,
|
||||
public IAccessibleHypertext
|
||||
{
|
||||
public:
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
STDMETHODIMP QueryInterface(REFIID, void**);
|
||||
|
||||
// IAccessibleText
|
||||
FORWARD_IACCESSIBLETEXT(CAccessibleText)
|
||||
FORWARD_IACCESSIBLETEXT(ia2AccessibleText)
|
||||
|
||||
// IAccessibleHypertext
|
||||
virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nHyperlinks(
|
||||
|
|
|
@ -5,19 +5,19 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CAccessibleText.h"
|
||||
#include "ia2AccessibleText.h"
|
||||
|
||||
#include "Accessible2.h"
|
||||
#include "AccessibleText_i.c"
|
||||
|
||||
#include "HyperTextAccessible.h"
|
||||
#include "HyperTextAccessibleWrap.h"
|
||||
|
||||
#include "nsIPersistentProperties2.h"
|
||||
|
||||
// IUnknown
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::QueryInterface(REFIID iid, void** ppv)
|
||||
ia2AccessibleText::QueryInterface(REFIID iid, void** ppv)
|
||||
{
|
||||
*ppv = NULL;
|
||||
|
||||
|
@ -37,10 +37,10 @@ CAccessibleText::QueryInterface(REFIID iid, void** ppv)
|
|||
// IAccessibleText
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::addSelection(long aStartOffset, long aEndOffset)
|
||||
ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -52,8 +52,8 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_attributes(long aOffset, long *aStartOffset,
|
||||
long *aEndOffset, BSTR *aTextAttributes)
|
||||
ia2AccessibleText::get_attributes(long aOffset, long *aStartOffset,
|
||||
long *aEndOffset, BSTR *aTextAttributes)
|
||||
{
|
||||
__try {
|
||||
if (!aStartOffset || !aEndOffset || !aTextAttributes)
|
||||
|
@ -63,7 +63,7 @@ __try {
|
|||
*aEndOffset = 0;
|
||||
*aTextAttributes = NULL;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -90,12 +90,12 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_caretOffset(long *aOffset)
|
||||
ia2AccessibleText::get_caretOffset(long *aOffset)
|
||||
{
|
||||
__try {
|
||||
*aOffset = -1;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -112,10 +112,10 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_characterExtents(long aOffset,
|
||||
enum IA2CoordinateType aCoordType,
|
||||
long *aX, long *aY,
|
||||
long *aWidth, long *aHeight)
|
||||
ia2AccessibleText::get_characterExtents(long aOffset,
|
||||
enum IA2CoordinateType aCoordType,
|
||||
long *aX, long *aY,
|
||||
long *aWidth, long *aHeight)
|
||||
{
|
||||
__try {
|
||||
*aX = 0;
|
||||
|
@ -123,7 +123,7 @@ __try {
|
|||
*aWidth = 0;
|
||||
*aHeight = 0;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -148,12 +148,12 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_nSelections(long *aNSelections)
|
||||
ia2AccessibleText::get_nSelections(long *aNSelections)
|
||||
{
|
||||
__try {
|
||||
*aNSelections = 0;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -170,14 +170,14 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_offsetAtPoint(long aX, long aY,
|
||||
enum IA2CoordinateType aCoordType,
|
||||
long *aOffset)
|
||||
ia2AccessibleText::get_offsetAtPoint(long aX, long aY,
|
||||
enum IA2CoordinateType aCoordType,
|
||||
long *aOffset)
|
||||
{
|
||||
__try {
|
||||
*aOffset = 0;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -198,14 +198,14 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_selection(long aSelectionIndex, long *aStartOffset,
|
||||
long *aEndOffset)
|
||||
ia2AccessibleText::get_selection(long aSelectionIndex, long *aStartOffset,
|
||||
long *aEndOffset)
|
||||
{
|
||||
__try {
|
||||
*aStartOffset = 0;
|
||||
*aEndOffset = 0;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -224,12 +224,12 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR *aText)
|
||||
ia2AccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR *aText)
|
||||
{
|
||||
__try {
|
||||
*aText = NULL;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -249,17 +249,17 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_textBeforeOffset(long aOffset,
|
||||
enum IA2TextBoundaryType aBoundaryType,
|
||||
long *aStartOffset, long *aEndOffset,
|
||||
BSTR *aText)
|
||||
ia2AccessibleText::get_textBeforeOffset(long aOffset,
|
||||
enum IA2TextBoundaryType aBoundaryType,
|
||||
long *aStartOffset, long *aEndOffset,
|
||||
BSTR *aText)
|
||||
{
|
||||
__try {
|
||||
*aStartOffset = 0;
|
||||
*aEndOffset = 0;
|
||||
*aText = NULL;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -296,17 +296,17 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_textAfterOffset(long aOffset,
|
||||
enum IA2TextBoundaryType aBoundaryType,
|
||||
long *aStartOffset, long *aEndOffset,
|
||||
BSTR *aText)
|
||||
ia2AccessibleText::get_textAfterOffset(long aOffset,
|
||||
enum IA2TextBoundaryType aBoundaryType,
|
||||
long *aStartOffset, long *aEndOffset,
|
||||
BSTR *aText)
|
||||
{
|
||||
__try {
|
||||
*aStartOffset = 0;
|
||||
*aEndOffset = 0;
|
||||
*aText = NULL;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -343,17 +343,17 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_textAtOffset(long aOffset,
|
||||
enum IA2TextBoundaryType aBoundaryType,
|
||||
long *aStartOffset, long *aEndOffset,
|
||||
BSTR *aText)
|
||||
ia2AccessibleText::get_textAtOffset(long aOffset,
|
||||
enum IA2TextBoundaryType aBoundaryType,
|
||||
long *aStartOffset, long *aEndOffset,
|
||||
BSTR *aText)
|
||||
{
|
||||
__try {
|
||||
*aStartOffset = 0;
|
||||
*aEndOffset = 0;
|
||||
*aText = NULL;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -390,10 +390,10 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::removeSelection(long aSelectionIndex)
|
||||
ia2AccessibleText::removeSelection(long aSelectionIndex)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -405,10 +405,10 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::setCaretOffset(long aOffset)
|
||||
ia2AccessibleText::setCaretOffset(long aOffset)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -420,11 +420,11 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
|
||||
long aEndOffset)
|
||||
ia2AccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
|
||||
long aEndOffset)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -437,12 +437,12 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_nCharacters(long *aNCharacters)
|
||||
ia2AccessibleText::get_nCharacters(long *aNCharacters)
|
||||
{
|
||||
__try {
|
||||
*aNCharacters = 0;
|
||||
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -454,11 +454,11 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
|
||||
enum IA2ScrollType aScrollType)
|
||||
ia2AccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
|
||||
enum IA2ScrollType aScrollType)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -470,12 +470,12 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
|
||||
enum IA2CoordinateType aCoordType,
|
||||
long aX, long aY)
|
||||
ia2AccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
|
||||
enum IA2CoordinateType aCoordType,
|
||||
long aX, long aY)
|
||||
{
|
||||
__try {
|
||||
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
if (textAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -492,7 +492,7 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_newText(IA2TextSegment *aNewText)
|
||||
ia2AccessibleText::get_newText(IA2TextSegment *aNewText)
|
||||
{
|
||||
__try {
|
||||
return GetModifiedText(true, aNewText);
|
||||
|
@ -502,7 +502,7 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleText::get_oldText(IA2TextSegment *aOldText)
|
||||
ia2AccessibleText::get_oldText(IA2TextSegment *aOldText)
|
||||
{
|
||||
__try {
|
||||
return GetModifiedText(false, aOldText);
|
||||
|
@ -511,11 +511,11 @@ __try {
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
// CAccessibleText
|
||||
// ia2AccessibleText
|
||||
|
||||
HRESULT
|
||||
CAccessibleText::GetModifiedText(bool aGetInsertedText,
|
||||
IA2TextSegment *aText)
|
||||
ia2AccessibleText::GetModifiedText(bool aGetInsertedText,
|
||||
IA2TextSegment *aText)
|
||||
{
|
||||
PRUint32 startOffset = 0, endOffset = 0;
|
||||
nsAutoString text;
|
||||
|
@ -536,7 +536,7 @@ CAccessibleText::GetModifiedText(bool aGetInsertedText,
|
|||
}
|
||||
|
||||
AccessibleTextBoundary
|
||||
CAccessibleText::GetGeckoTextBoundary(enum IA2TextBoundaryType aBoundaryType)
|
||||
ia2AccessibleText::GetGeckoTextBoundary(enum IA2TextBoundaryType aBoundaryType)
|
||||
{
|
||||
switch (aBoundaryType) {
|
||||
case IA2_TEXT_BOUNDARY_CHAR:
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "AccessibleText.h"
|
||||
|
||||
class CAccessibleText: public IAccessibleText
|
||||
class ia2AccessibleText: public IAccessibleText
|
||||
{
|
||||
public:
|
||||
|
|
@ -119,6 +119,89 @@ xpcAccessibleTable::GetRowExtentAt(PRInt32 aRowIdx, PRInt32 aColIdx,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpcAccessibleTable::GetColumnDescription(PRInt32 aColIdx,
|
||||
nsAString& aDescription)
|
||||
{
|
||||
if (!mTable)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (aColIdx < 0 || static_cast<PRUint32>(aColIdx) >= mTable->ColCount())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsAutoString description;
|
||||
mTable->ColDescription(aColIdx, description);
|
||||
aDescription.Assign(description);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpcAccessibleTable::GetRowDescription(PRInt32 aRowIdx, nsAString& aDescription)
|
||||
{
|
||||
if (!mTable)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (aRowIdx < 0 || static_cast<PRUint32>(aRowIdx) >= mTable->ColCount())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsAutoString description;
|
||||
mTable->RowDescription(aRowIdx, description);
|
||||
aDescription.Assign(description);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpcAccessibleTable::IsColumnSelected(PRInt32 aColIdx, bool* aIsSelected)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
if (!mTable)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (aColIdx < 0 || static_cast<PRUint32>(aColIdx) >= mTable->ColCount())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
*aIsSelected = mTable->IsColSelected(aColIdx);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpcAccessibleTable::IsRowSelected(PRInt32 aRowIdx, bool* aIsSelected)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
if (!mTable)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (aRowIdx < 0 || static_cast<PRUint32>(aRowIdx) >= mTable->RowCount())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
*aIsSelected = mTable->IsRowSelected(aRowIdx);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpcAccessibleTable::IsCellSelected(PRInt32 aRowIdx, PRInt32 aColIdx,
|
||||
bool* aIsSelected)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
if (!mTable)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (aRowIdx < 0 || static_cast<PRUint32>(aRowIdx) >= mTable->RowCount() ||
|
||||
aColIdx < 0 || static_cast<PRUint32>(aColIdx) >= mTable->ColCount())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
*aIsSelected = mTable->IsCellSelected(aRowIdx, aColIdx);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpcAccessibleTable::GetSummary(nsAString& aSummary)
|
||||
{
|
||||
|
|
|
@ -34,6 +34,11 @@ public:
|
|||
PRInt32* aColumnExtent);
|
||||
nsresult GetRowExtentAt(PRInt32 row, PRInt32 column,
|
||||
PRInt32* aRowExtent);
|
||||
nsresult GetColumnDescription(PRInt32 aColIdx, nsAString& aDescription);
|
||||
nsresult GetRowDescription(PRInt32 aRowIdx, nsAString& aDescription);
|
||||
nsresult IsColumnSelected(PRInt32 aColIdx, bool* _retval);
|
||||
nsresult IsRowSelected(PRInt32 aRowIdx, bool* _retval);
|
||||
nsresult IsCellSelected(PRInt32 aRowIdx, PRInt32 aColIdx, bool* _retval);
|
||||
nsresult SelectColumn(PRInt32 aColIdx);
|
||||
nsresult SelectRow(PRInt32 aRowIdx);
|
||||
nsresult UnselectColumn(PRInt32 aColIdx);
|
||||
|
@ -64,11 +69,16 @@ protected:
|
|||
{ return xpcAccessibleTable::GetColumnExtentAt(row, column, _retval); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32* _retval NS_OUTPARAM) \
|
||||
{ return xpcAccessibleTable::GetRowExtentAt(row, column, _retval); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString & _retval NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString & _retval NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIndex, bool *_retval NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIndex, PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString& _retval NS_OUTPARAM) \
|
||||
{ return xpcAccessibleTable::GetColumnDescription(columnIndex, _retval); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString& _retval NS_OUTPARAM) \
|
||||
{ return xpcAccessibleTable::GetRowDescription(rowIndex, _retval); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 colIdx, bool* _retval NS_OUTPARAM) \
|
||||
{ return xpcAccessibleTable::IsColumnSelected(colIdx, _retval); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIdx, bool* _retval NS_OUTPARAM) \
|
||||
{ return xpcAccessibleTable::IsRowSelected(rowIdx, _retval); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIdx, PRInt32 colIdx, bool* _retval NS_OUTPARAM) \
|
||||
{ return xpcAccessibleTable::IsCellSelected(rowIdx, colIdx, _retval); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedCellCount(PRUint32 *aSelectedCellCount); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32 *aSelectedColumnCount); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32 *aSelectedRowCount); \
|
||||
|
|
|
@ -316,30 +316,9 @@ XULListboxAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULListboxAccessible::GetColumnDescription(PRInt32 aColumn,
|
||||
nsAString& aDescription)
|
||||
bool
|
||||
XULListboxAccessible::IsColSelected(PRUint32 aColIdx)
|
||||
{
|
||||
aDescription.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULListboxAccessible::GetRowDescription(PRInt32 aRow, nsAString& aDescription)
|
||||
{
|
||||
aDescription.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULListboxAccessible::IsColumnSelected(PRInt32 aColumn, bool* aIsSelected)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
|
||||
do_QueryInterface(mContent);
|
||||
NS_ASSERTION(control,
|
||||
|
@ -347,42 +326,32 @@ XULListboxAccessible::IsColumnSelected(PRInt32 aColumn, bool* aIsSelected)
|
|||
|
||||
PRInt32 selectedrowCount = 0;
|
||||
nsresult rv = control->GetSelectedCount(&selectedrowCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
PRInt32 rowCount = 0;
|
||||
rv = GetRowCount(&rowCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aIsSelected = (selectedrowCount == rowCount);
|
||||
return NS_OK;
|
||||
return selectedrowCount == RowCount();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULListboxAccessible::IsRowSelected(PRInt32 aRow, bool* aIsSelected)
|
||||
bool
|
||||
XULListboxAccessible::IsRowSelected(PRUint32 aRowIdx)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMXULSelectControlElement> control =
|
||||
do_QueryInterface(mContent);
|
||||
NS_ASSERTION(control,
|
||||
"Doesn't implement nsIDOMXULSelectControlElement.");
|
||||
|
||||
nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
|
||||
control->GetItemAtIndex(aRow, getter_AddRefs(item));
|
||||
NS_ENSURE_TRUE(item, NS_ERROR_INVALID_ARG);
|
||||
nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
return item->GetSelected(aIsSelected);
|
||||
bool isSelected = false;
|
||||
item->GetSelected(&isSelected);
|
||||
return isSelected;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULListboxAccessible::IsCellSelected(PRInt32 aRowIndex, PRInt32 aColumnIndex,
|
||||
bool* aIsSelected)
|
||||
bool
|
||||
XULListboxAccessible::IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx)
|
||||
{
|
||||
return IsRowSelected(aRowIndex, aIsSelected);
|
||||
return IsRowSelected(aRowIdx);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -76,6 +76,9 @@ public:
|
|||
virtual PRUint32 ColCount();
|
||||
virtual PRUint32 RowCount();
|
||||
virtual Accessible* CellAt(PRUint32 aRowIndex, PRUint32 aColumnIndex);
|
||||
virtual bool IsColSelected(PRUint32 aColIdx);
|
||||
virtual bool IsRowSelected(PRUint32 aRowIdx);
|
||||
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx);
|
||||
virtual void SelectRow(PRUint32 aRowIdx);
|
||||
virtual void UnselectRow(PRUint32 aRowIdx);
|
||||
|
||||
|
|
|
@ -553,6 +553,11 @@ XULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount)
|
|||
if (IsDefunct())
|
||||
return;
|
||||
|
||||
if (!mTreeView) {
|
||||
ClearCache(mAccessibleCache);
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not invalidate the cache if rows have been inserted.
|
||||
if (aCount > 0)
|
||||
return;
|
||||
|
|
|
@ -368,83 +368,53 @@ XULTreeGridAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULTreeGridAccessible::GetColumnDescription(PRInt32 aColumnIndex,
|
||||
nsAString& aDescription)
|
||||
void
|
||||
XULTreeGridAccessible::ColDescription(PRUint32 aColIdx, nsString& aDescription)
|
||||
{
|
||||
aDescription.Truncate();
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> treeColumns;
|
||||
Accessible::GetFirstChild(getter_AddRefs(treeColumns));
|
||||
if (treeColumns) {
|
||||
nsCOMPtr<nsIAccessible> treeColumnItem;
|
||||
treeColumns->GetChildAt(aColumnIndex, getter_AddRefs(treeColumnItem));
|
||||
treeColumns->GetChildAt(aColIdx, getter_AddRefs(treeColumnItem));
|
||||
if (treeColumnItem)
|
||||
return treeColumnItem->GetName(aDescription);
|
||||
treeColumnItem->GetName(aDescription);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULTreeGridAccessible::GetRowDescription(PRInt32 aRowIndex,
|
||||
nsAString& aDescription)
|
||||
bool
|
||||
XULTreeGridAccessible::IsColSelected(PRUint32 aColIdx)
|
||||
{
|
||||
aDescription.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULTreeGridAccessible::IsColumnSelected(PRInt32 aColumnIndex, bool* aIsSelected)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// If all the row has been selected, then all the columns are selected.
|
||||
// Because we can't select a column alone.
|
||||
|
||||
PRInt32 rowCount = 0;
|
||||
nsresult rv = GetRowCount(&rowCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 selectedrowCount = 0;
|
||||
rv = GetSelectionCount(&selectedrowCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv = GetSelectionCount(&selectedrowCount);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
*aIsSelected = rowCount == selectedrowCount;
|
||||
return NS_OK;
|
||||
return selectedrowCount == RowCount();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULTreeGridAccessible::IsRowSelected(PRInt32 aRowIndex, bool* aIsSelected)
|
||||
bool
|
||||
XULTreeGridAccessible::IsRowSelected(PRUint32 aRowIdx)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSelected);
|
||||
*aIsSelected = false;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!mTreeView)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsITreeSelection> selection;
|
||||
nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
return selection->IsSelected(aRowIndex, aIsSelected);
|
||||
bool isSelected = false;
|
||||
selection->IsSelected(aRowIdx, &isSelected);
|
||||
return isSelected;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULTreeGridAccessible::IsCellSelected(PRInt32 aRowIndex, PRInt32 aColumnIndex,
|
||||
bool* aIsSelected)
|
||||
bool
|
||||
XULTreeGridAccessible::IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx)
|
||||
{
|
||||
return IsRowSelected(aRowIndex, aIsSelected);
|
||||
return IsRowSelected(aRowIdx);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -34,6 +34,10 @@ public:
|
|||
virtual PRUint32 ColCount();
|
||||
virtual PRUint32 RowCount();
|
||||
virtual Accessible* CellAt(PRUint32 aRowIndex, PRUint32 aColumnIndex);
|
||||
virtual void ColDescription(PRUint32 aColIdx, nsString& aDescription);
|
||||
virtual bool IsColSelected(PRUint32 aColIdx);
|
||||
virtual bool IsRowSelected(PRUint32 aRowIdx);
|
||||
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx);
|
||||
virtual void SelectRow(PRUint32 aRowIdx);
|
||||
virtual void UnselectRow(PRUint32 aRowIdx);
|
||||
|
||||
|
|
|
@ -50,25 +50,9 @@ function doTest()
|
|||
|
||||
is(accTable.selectedRowCount, 1, "no cells selected");
|
||||
|
||||
var columnDescription;
|
||||
works = true;
|
||||
try{
|
||||
columnDescription = accTable.getColumnDescription(1);
|
||||
}
|
||||
catch (e) {
|
||||
works = false;
|
||||
}
|
||||
todo(works, "columnDescription should not throw");
|
||||
var columnDescription = accTable.getColumnDescription(1);
|
||||
var rowDescription = accTable.getRowDescription(1);
|
||||
|
||||
var rowDescription;
|
||||
works = true;
|
||||
try {
|
||||
rowDescription = accTable.getRowDescription(1);
|
||||
}
|
||||
catch (e) {
|
||||
works = false;
|
||||
}
|
||||
todo(works, "rowDescription should not throw");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
@ -78,6 +62,12 @@ addA11yLoadEvent(doTest);
|
|||
<body >
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=760878"
|
||||
title="decomtaminate Get Row / Column Description() on accessible tables">
|
||||
Mozilla Bug 760878
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
|
|
@ -6,35 +6,6 @@
|
|||
|
||||
pref("toolkit.defaultChromeURI", "chrome://browser/content/shell.xul");
|
||||
pref("browser.chromeURL", "chrome://browser/content/");
|
||||
#ifdef MOZ_OFFICIAL_BRANDING
|
||||
pref("browser.homescreenURL", "http://homescreen.gaiamobile.org/");
|
||||
#else
|
||||
pref("browser.homescreenURL", "http://homescreen.gaiamobile.org/");
|
||||
#endif
|
||||
|
||||
// All the privileged domains
|
||||
// XXX TODO : we should read them from a file somewhere
|
||||
pref("b2g.privileged.domains", "http://browser.gaiamobile.org,
|
||||
http://calculator.gaiamobile.org,
|
||||
http://contacts.gaiamobile.org,
|
||||
http://camera.gaiamobile.org,
|
||||
http://clock.gaiamobile.org,
|
||||
http://crystalskull.gaiamobile.org,
|
||||
http://cubevid.gaiamobile.org,
|
||||
http://dialer.gaiamobile.org,
|
||||
http://gallery.gaiamobile.org,
|
||||
http://homescreen.gaiamobile.org,
|
||||
http://maps.gaiamobile.org,
|
||||
http://market.gaiamobile.org,
|
||||
http://music.gaiamobile.org,
|
||||
http://penguinpop.gaiamobile.org,
|
||||
http://settings.gaiamobile.org,
|
||||
http://sms.gaiamobile.org,
|
||||
http://towerjelly.gaiamobile.org,
|
||||
http://video.gaiamobile.org");
|
||||
|
||||
// URL for the dialer application.
|
||||
pref("dom.telephony.app.phone.url", "http://dialer.gaiamobile.org,http://homescreen.gaiamobile.org");
|
||||
|
||||
// Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
|
||||
pref("browser.viewport.scaleRatio", -1);
|
||||
|
@ -395,7 +366,6 @@ pref("browser.link.open_newwindow.restriction", 0);
|
|||
// Enable browser frames (including OOP, except on Windows, where it doesn't
|
||||
// work), but make in-process browser frames the default.
|
||||
pref("dom.mozBrowserFramesEnabled", true);
|
||||
pref("dom.mozBrowserFramesWhitelist", "http://homescreen.gaiamobile.org,http://browser.gaiamobile.org");
|
||||
|
||||
pref("dom.ipc.tabs.disabled", false);
|
||||
|
||||
|
@ -403,14 +373,9 @@ pref("dom.ipc.browser_frames.oop_by_default", false);
|
|||
|
||||
// Temporary permission hack for WebSMS
|
||||
pref("dom.sms.enabled", true);
|
||||
pref("dom.sms.whitelist", "file://,http://homescreen.gaiamobile.org,http://sms.gaiamobile.org");
|
||||
|
||||
// Temporary permission hack for WebMobileConnection
|
||||
pref("dom.mobileconnection.whitelist", "http://system.gaiamobile.org,http://homescreen.gaiamobile.org,http://dialer.gaiamobile.org");
|
||||
|
||||
// Temporary permission hack for WebContacts
|
||||
pref("dom.mozContacts.enabled", true);
|
||||
pref("dom.mozContacts.whitelist", "http://dialer.gaiamobile.org,http://sms.gaiamobile.org");
|
||||
|
||||
// WebSettings
|
||||
pref("dom.mozSettings.enabled", true);
|
||||
|
@ -439,9 +404,8 @@ pref("b2g.remote-js.port", 9999);
|
|||
pref("b2g.keys.menu.enabled", true);
|
||||
pref("b2g.keys.search.enabled", false);
|
||||
|
||||
// Screen timeout in minutes
|
||||
// Screen timeout in seconds
|
||||
pref("power.screen.timeout", 60);
|
||||
pref("dom.power.whitelist", "http://homescreen.gaiamobile.org,http://settings.gaiamobile.org");
|
||||
|
||||
pref("full-screen-api.enabled", true);
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -24,7 +24,7 @@
|
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="BrowserStartup()" onunload="BrowserShutdown()" onclose="return WindowIsClosing();"
|
||||
onload="gBrowserInit.onLoad()" onunload="gBrowserInit.onUnload()" onclose="return WindowIsClosing();"
|
||||
title="&mainWindow.title;@PRE_RELEASE_SUFFIX@"
|
||||
title_normal="&mainWindow.title;@PRE_RELEASE_SUFFIX@"
|
||||
#ifdef XP_MACOSX
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
return OpenBrowserWindow();
|
||||
}
|
||||
|
||||
addEventListener("load", nonBrowserWindowStartup, false);
|
||||
addEventListener("unload", nonBrowserWindowShutdown, false);
|
||||
addEventListener("load", function() { gBrowserInit.nonBrowserWindowStartup() }, false);
|
||||
addEventListener("unload", function() { gBrowserInit.nonBrowserWindowShutdown() }, false);
|
||||
</script>
|
||||
|
||||
# All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the
|
||||
|
|
|
@ -42,7 +42,8 @@ function test1a() {
|
|||
ok(!popupNotification, "Test 1a, Should not have a click-to-play notification");
|
||||
var plugin = gTestBrowser.contentWindow.addPlugin();
|
||||
|
||||
setTimeout(test1b, 500);
|
||||
var condition = function() PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
waitForCondition(condition, test1b, "Test 1a, Waited too long for plugin notification");
|
||||
}
|
||||
|
||||
function test1b() {
|
||||
|
@ -53,7 +54,7 @@ function test1b() {
|
|||
ok(!objLoadingContent.activated, "Test 1b, Plugin should not be activated");
|
||||
|
||||
popupNotification.mainAction.callback();
|
||||
setTimeout(test1c, 500);
|
||||
test1c();
|
||||
}
|
||||
|
||||
function test1c() {
|
||||
|
@ -61,7 +62,9 @@ function test1c() {
|
|||
ok(!popupNotification, "Test 1c, Should not have a click-to-play notification");
|
||||
var plugin = gTestBrowser.contentWindow.addPlugin();
|
||||
|
||||
setTimeout(test1d, 500);
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
var condition = function() objLoadingContent.activated;
|
||||
waitForCondition(condition, test1d, "Test 1c, Waited too long for plugin activation");
|
||||
}
|
||||
|
||||
function test1d() {
|
||||
|
@ -82,7 +85,9 @@ function test1e() {
|
|||
ok(!popupNotification, "Test 1e, Should not have a click-to-play notification");
|
||||
var plugin = gTestBrowser.contentWindow.addPlugin();
|
||||
|
||||
setTimeout(test1f, 500);
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
var condition = function() objLoadingContent.activated;
|
||||
waitForCondition(condition, test1f, "Test 1e, Waited too long for plugin activation");
|
||||
}
|
||||
|
||||
function test1f() {
|
||||
|
@ -93,8 +98,10 @@ function test1f() {
|
|||
ok(objLoadingContent.activated, "Test 1f, Plugin should be activated");
|
||||
|
||||
gTestBrowser.contentWindow.history.replaceState({}, "", "replacedState");
|
||||
gTestBrowser.contentWindow.addPlugin();
|
||||
setTimeout(test1g, 500);
|
||||
var plugin = gTestBrowser.contentWindow.addPlugin();
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
var condition = function() objLoadingContent.activated;
|
||||
waitForCondition(condition, test1g, "Test 1f, Waited too long for plugin activation");
|
||||
}
|
||||
|
||||
function test1g() {
|
||||
|
|
|
@ -213,21 +213,6 @@ function test8() {
|
|||
prepareTest(test9a, gTestRoot + "plugin_test2.html");
|
||||
}
|
||||
|
||||
function waitForCondition(condition, nextTest, errorMsg) {
|
||||
var tries = 0;
|
||||
var interval = setInterval(function() {
|
||||
if (tries >= 500) {
|
||||
ok(false, errorMsg);
|
||||
moveOn();
|
||||
}
|
||||
if (condition()) {
|
||||
moveOn();
|
||||
}
|
||||
tries++;
|
||||
}, 10);
|
||||
var moveOn = function() { clearInterval(interval); nextTest(); };
|
||||
}
|
||||
|
||||
// Tests that activating one click-to-play plugin will activate only that plugin (part 1/3)
|
||||
function test9a() {
|
||||
var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
|
|
|
@ -72,3 +72,18 @@ function closeToolbarCustomizationUI(aCallback, aBrowserWin) {
|
|||
button.focus();
|
||||
button.doCommand();
|
||||
}
|
||||
|
||||
function waitForCondition(condition, nextTest, errorMsg) {
|
||||
var tries = 0;
|
||||
var interval = setInterval(function() {
|
||||
if (tries >= 30) {
|
||||
ok(false, errorMsg);
|
||||
moveOn();
|
||||
}
|
||||
if (condition()) {
|
||||
moveOn();
|
||||
}
|
||||
tries++;
|
||||
}, 100);
|
||||
var moveOn = function() { clearInterval(interval); nextTest(); };
|
||||
}
|
||||
|
|
|
@ -245,7 +245,7 @@ function openWindow(parent, url, target, features, args, noExternalArgs) {
|
|||
}
|
||||
|
||||
// Pass these as null to ensure that we always trigger the "single URL"
|
||||
// behavior in browser.js's BrowserStartup (which handles the window
|
||||
// behavior in browser.js's gBrowserInit.onLoad (which handles the window
|
||||
// arguments)
|
||||
argArray.AppendElement(null); // charset
|
||||
argArray.AppendElement(null); // referer
|
||||
|
|
|
@ -35,7 +35,8 @@ EXTRA_COMPONENTS = nsSetDefaultBrowser.js nsSetDefaultBrowser.manifest
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES += -DMOZ_APP_NAME=\"$(MOZ_APP_NAME)\"
|
||||
DEFINES += -DMOZ_APP_NAME=\"$(MOZ_APP_NAME)\" \
|
||||
-DMOZ_APP_VERSION=\"$(MOZ_APP_VERSION)\"
|
||||
|
||||
CXXFLAGS += $(TK_CFLAGS)
|
||||
|
||||
|
|
|
@ -201,7 +201,8 @@ static SETTING gDDESettings[] = {
|
|||
#include "updatehelper.h"
|
||||
#include "updatehelper.cpp"
|
||||
|
||||
static const char kPrefetchClearedPref[] = "app.update.service.prefetchCleared";
|
||||
static const char *kPrefetchClearedPref =
|
||||
"app.update.service.lastVersionPrefetchCleared";
|
||||
static nsCOMPtr<nsIThread> sThread;
|
||||
#endif
|
||||
|
||||
|
@ -1016,17 +1017,20 @@ nsWindowsShellService::nsWindowsShellService() :
|
|||
}
|
||||
|
||||
// check to see if we have attempted to do the one time operation of clearing
|
||||
// the prefetch.
|
||||
bool prefetchCleared;
|
||||
// the prefetch. We do it once per version upgrade.
|
||||
nsCString lastClearedVer;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch;
|
||||
nsCOMPtr<nsIPrefService> prefs =
|
||||
do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (!prefs ||
|
||||
NS_FAILED(prefs->GetBranch(nsnull, getter_AddRefs(prefBranch))) ||
|
||||
(NS_SUCCEEDED(prefBranch->GetBoolPref(kPrefetchClearedPref,
|
||||
&prefetchCleared)) &&
|
||||
prefetchCleared)) {
|
||||
return;
|
||||
(NS_SUCCEEDED(prefBranch->GetCharPref(kPrefetchClearedPref,
|
||||
getter_Copies(lastClearedVer))))) {
|
||||
// If the versions are the same, then bail out early. We only want to clear
|
||||
// once per version.
|
||||
if (!strcmp(MOZ_APP_VERSION, lastClearedVer.get())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// In a minute after startup is definitely complete, launch the
|
||||
|
@ -1097,7 +1101,7 @@ nsWindowsShellService::LaunchPrefetchClearCommand(nsITimer *aTimer, void*)
|
|||
do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
if (NS_SUCCEEDED(prefs->GetBranch(nsnull, getter_AddRefs(prefBranch)))) {
|
||||
prefBranch->SetBoolPref(kPrefetchClearedPref, true);
|
||||
prefBranch->SetCharPref(kPrefetchClearedPref, MOZ_APP_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1234,7 +1234,7 @@ InspectorUI.prototype = {
|
|||
|
||||
/**
|
||||
* Destroy the InspectorUI instance. This is called by the InspectorUI API
|
||||
* "user", see BrowserShutdown() in browser.js.
|
||||
* "user", see gBrowserInit.onUnload() in browser.js.
|
||||
*/
|
||||
destroy: function IUI_destroy()
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@ public class FindProcThread extends Thread {
|
|||
boolean bStillRunning = true;
|
||||
|
||||
public FindProcThread(ContextWrapper ctx, String sProcessName) {
|
||||
super("FindProcThread");
|
||||
this.contextWrapper = ctx;
|
||||
this.sProcNameToFind = sProcessName;
|
||||
this.bFoundIt = false;
|
||||
|
|
|
@ -20,6 +20,7 @@ public class RedirOutputThread extends Thread
|
|||
|
||||
public RedirOutputThread(Process pProc, OutputStream out)
|
||||
{
|
||||
super("RedirOutputThread");
|
||||
if (pProc != null)
|
||||
{
|
||||
this.pProc = pProc;
|
||||
|
@ -50,6 +51,13 @@ public class RedirOutputThread extends Thread
|
|||
{
|
||||
try
|
||||
{
|
||||
// If there's no output to collect, sleep for a while
|
||||
// rather than checking again immediately, to avoid
|
||||
// using up cpu capacity in a tight loop.
|
||||
if (sutOut.available() == 0 && sutErr.available() == 0)
|
||||
{
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if ((nBytesOut = sutOut.available()) > 0)
|
||||
{
|
||||
if (nBytesOut > buffer.length)
|
||||
|
@ -109,6 +117,10 @@ public class RedirOutputThread extends Thread
|
|||
// Bug 743766: InputStream.available() unexpectedly throws this sometimes
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
pProc.destroy();
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -4419,12 +4419,6 @@ nsDocument::CreateComment(const nsAString& aData, nsIDOMComment** aReturn)
|
|||
{
|
||||
*aReturn = nsnull;
|
||||
|
||||
// Make sure the substring "--" is not present in aData. Otherwise
|
||||
// we'll create a document that can't be serialized.
|
||||
if (FindInReadable(NS_LITERAL_STRING("--"), aData)) {
|
||||
return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> comment;
|
||||
nsresult rv = NS_NewCommentNode(getter_AddRefs(comment), mNodeInfoManager);
|
||||
|
||||
|
@ -9614,6 +9608,14 @@ nsIDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
|||
&aWindowSizes->mLayoutPresContext);
|
||||
}
|
||||
|
||||
aWindowSizes->mPropertyTables +=
|
||||
mPropertyTable.SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
|
||||
for (PRUint32 i = 0, count = mExtraPropertyTables.Length();
|
||||
i < count; ++i) {
|
||||
aWindowSizes->mPropertyTables +=
|
||||
mExtraPropertyTables[i]->SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
|
||||
}
|
||||
|
||||
// Measurement of the following members may be added later if DMD finds it
|
||||
// is worthwhile:
|
||||
// - many!
|
||||
|
|
|
@ -4098,7 +4098,9 @@ bool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
|
|||
{
|
||||
// Note that for now we only allow nodes inside document fragments if
|
||||
// they're allowed inside elements. If we ever change this to allow
|
||||
// doctype nodes in document fragments, we'll need to update this code
|
||||
// doctype nodes in document fragments, we'll need to update this code.
|
||||
// Also, there's a version of this code in ReplaceOrInsertBefore. If you
|
||||
// change this code, change that too.
|
||||
if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
|
||||
// All good here
|
||||
return true;
|
||||
|
@ -4159,6 +4161,11 @@ nsresult
|
|||
nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
||||
nsINode* aRefChild)
|
||||
{
|
||||
// XXXbz I wish I could assert that nsContentUtils::IsSafeToRunScript() so we
|
||||
// could rely on scriptblockers going out of scope to actually run XBL
|
||||
// teardown, but various crud adds nodes under scriptblockers (e.g. native
|
||||
// anonymous content). The only good news is those insertions can't trigger
|
||||
// the bad XBL cases.
|
||||
if (!aNewChild || (aReplace && !aRefChild)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
@ -4235,6 +4242,8 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
nodeToInsertBefore = nodeToInsertBefore->GetNextSibling();
|
||||
}
|
||||
|
||||
Maybe<nsAutoTArray<nsCOMPtr<nsIContent>, 50> > fragChildren;
|
||||
|
||||
// Remove the new child from the old parent if one exists
|
||||
nsCOMPtr<nsINode> oldParent = newContent->GetNodeParent();
|
||||
if (oldParent) {
|
||||
|
@ -4254,7 +4263,8 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
// Scope for the mutation batch and scriptblocker, so they go away
|
||||
// while kungFuDeathGrip is still alive.
|
||||
{
|
||||
mozAutoDocUpdate batch(GetCurrentDoc(), UPDATE_CONTENT_MODEL, true);
|
||||
mozAutoDocUpdate batch(newContent->GetCurrentDoc(),
|
||||
UPDATE_CONTENT_MODEL, true);
|
||||
nsAutoMutationBatch mb(oldParent, true, true);
|
||||
oldParent->RemoveChildAt(removeIndex, true);
|
||||
if (nsAutoMutationBatch::GetCurrentBatch() == &mb) {
|
||||
|
@ -4299,6 +4309,98 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
|
||||
// Make sure to remove all the fragment's kids. We need to do this before
|
||||
// we start inserting anything, so we will run out XBL destructors and
|
||||
// binding teardown (GOD, I HATE THESE THINGS) before we insert anything
|
||||
// into the DOM.
|
||||
PRUint32 count = newContent->GetChildCount();
|
||||
|
||||
fragChildren.construct();
|
||||
|
||||
// Copy the children into a separate array to avoid having to deal with
|
||||
// mutations to the fragment later on here.
|
||||
fragChildren.ref().SetCapacity(count);
|
||||
for (nsIContent* child = newContent->GetFirstChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
NS_ASSERTION(child->GetCurrentDoc() == nsnull,
|
||||
"How did we get a child with a current doc?");
|
||||
fragChildren.ref().AppendElement(child);
|
||||
}
|
||||
|
||||
// Hold a strong ref to nodeToInsertBefore across the removals
|
||||
nsCOMPtr<nsINode> kungFuDeathGrip = nodeToInsertBefore;
|
||||
|
||||
nsMutationGuard guard;
|
||||
|
||||
// Scope for the mutation batch and scriptblocker, so they go away
|
||||
// while kungFuDeathGrip is still alive.
|
||||
{
|
||||
mozAutoDocUpdate batch(newContent->GetCurrentDoc(),
|
||||
UPDATE_CONTENT_MODEL, true);
|
||||
nsAutoMutationBatch mb(newContent, false, true);
|
||||
|
||||
for (PRUint32 i = count; i > 0;) {
|
||||
newContent->RemoveChildAt(--i, true);
|
||||
}
|
||||
}
|
||||
|
||||
// We expect |count| removals
|
||||
if (guard.Mutated(count)) {
|
||||
// XBL destructors, yuck.
|
||||
|
||||
// Verify that nodeToInsertBefore, if non-null, is still our child. If
|
||||
// it's not, there's no way we can do this insert sanely; just bail out.
|
||||
if (nodeToInsertBefore && nodeToInsertBefore->GetParent() != this) {
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
}
|
||||
|
||||
// Verify that all the things in fragChildren have no parent.
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
if (fragChildren.ref().ElementAt(i)->GetParent()) {
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
// Note that unlike the single-element case above, none of our kids can
|
||||
// be aRefChild, so we can always pass through aReplace in the
|
||||
// IsAllowedAsChild checks below and don't have to worry about whether
|
||||
// recomputing nodeToInsertBefore is OK.
|
||||
|
||||
// Verify that our aRefChild is still sensible
|
||||
if (aRefChild && aRefChild->GetParent() != this) {
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
}
|
||||
|
||||
// Recompute nodeToInsertBefore, just in case.
|
||||
if (aReplace) {
|
||||
nodeToInsertBefore = aRefChild->GetNextSibling();
|
||||
} else {
|
||||
nodeToInsertBefore = aRefChild;
|
||||
}
|
||||
|
||||
// And verify that newContent is still allowed as our child. Sadly, we
|
||||
// need to reimplement the relevant part of IsAllowedAsChild() because
|
||||
// now our nodes are in an array and all. If you change this code,
|
||||
// change the code there.
|
||||
if (IsNodeOfType(nsINode::eDOCUMENT)) {
|
||||
bool sawElement = false;
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
nsIContent* child = fragChildren.ref().ElementAt(i);
|
||||
if (child->IsElement()) {
|
||||
if (sawElement) {
|
||||
// No good
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
}
|
||||
sawElement = true;
|
||||
}
|
||||
if (!IsAllowedAsChild(child, this, aReplace, aRefChild)) {
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mozAutoDocUpdate batch(GetCurrentDoc(), UPDATE_CONTENT_MODEL, true);
|
||||
|
@ -4349,36 +4451,15 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
|
||||
/*
|
||||
* Check if we're inserting a document fragment. If we are, we need
|
||||
* to remove the children of the document fragment and add them
|
||||
* individually (i.e. we don't add the actual document fragment).
|
||||
* to actually add its children individually (i.e. we don't add the
|
||||
* actual document fragment).
|
||||
*/
|
||||
if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
|
||||
PRUint32 count = newContent->GetChildCount();
|
||||
|
||||
PRUint32 count = fragChildren.ref().Length();
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Copy the children into a separate array to avoid having to deal with
|
||||
// mutations to the fragment while we're inserting.
|
||||
nsAutoTArray<nsCOMPtr<nsIContent>, 50> fragChildren;
|
||||
fragChildren.SetCapacity(count);
|
||||
for (nsIContent* child = newContent->GetFirstChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
NS_ASSERTION(child->GetCurrentDoc() == nsnull,
|
||||
"How did we get a child with a current doc?");
|
||||
fragChildren.AppendElement(child);
|
||||
}
|
||||
|
||||
// Remove the children from the fragment.
|
||||
{
|
||||
nsAutoMutationBatch mb(newContent, false, true);
|
||||
for (PRUint32 i = count; i > 0;) {
|
||||
newContent->RemoveChildAt(--i, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!aReplace) {
|
||||
mb.Init(this, true, true);
|
||||
}
|
||||
|
@ -4392,14 +4473,14 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
bool appending =
|
||||
!IsNodeOfType(eDOCUMENT) && PRUint32(insPos) == GetChildCount();
|
||||
PRInt32 firstInsPos = insPos;
|
||||
nsIContent* firstInsertedContent = fragChildren[0];
|
||||
nsIContent* firstInsertedContent = fragChildren.ref().ElementAt(0);
|
||||
|
||||
// Iterate through the fragment's children, and insert them in the new
|
||||
// parent
|
||||
for (PRUint32 i = 0; i < count; ++i, ++insPos) {
|
||||
// XXXbz how come no reparenting here? That seems odd...
|
||||
// Insert the child.
|
||||
res = InsertChildAt(fragChildren[i], insPos, !appending);
|
||||
res = InsertChildAt(fragChildren.ref().ElementAt(i), insPos, !appending);
|
||||
if (NS_FAILED(res)) {
|
||||
// Make sure to notify on any children that we did succeed to insert
|
||||
if (appending && i != 0) {
|
||||
|
@ -4425,7 +4506,7 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
// Optimize for the case when there are no listeners
|
||||
if (nsContentUtils::
|
||||
HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
|
||||
nsGenericElement::FireNodeInserted(doc, this, fragChildren);
|
||||
nsGenericElement::FireNodeInserted(doc, this, fragChildren.ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ public:
|
|||
return mName == aPropertyName;
|
||||
}
|
||||
|
||||
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
|
||||
|
||||
nsCOMPtr<nsIAtom> mName; // property name
|
||||
PLDHashTable mObjectValueMap; // map of object/value pairs
|
||||
NSPropertyDtorFunc mDtorFunc; // property specific value dtor function
|
||||
|
@ -337,6 +339,26 @@ nsPropertyTable::PropertyList::DeletePropertyFor(nsPropertyOwner aObject)
|
|||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
nsPropertyTable::PropertyList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mObjectValueMap, NULL, aMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
nsPropertyTable::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
for (PropertyList *prop = mPropertyList; prop; prop = prop->mNext) {
|
||||
n += prop->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsPropertyTable::SupportsDtorFunc(void *aObject, nsIAtom *aPropertyName,
|
||||
|
|
|
@ -177,6 +177,8 @@ class nsPropertyTable
|
|||
|
||||
class PropertyList;
|
||||
|
||||
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
|
||||
|
||||
private:
|
||||
NS_HIDDEN_(void) DestroyPropertyList();
|
||||
NS_HIDDEN_(PropertyList*) GetPropertyListFor(nsIAtom *aPropertyName) const;
|
||||
|
|
|
@ -1076,14 +1076,14 @@ nsXMLHttpRequest::StaticAssertions()
|
|||
#_uc " should match")
|
||||
|
||||
ASSERT_ENUM_EQUAL(_empty, DEFAULT);
|
||||
ASSERT_ENUM_EQUAL(arraybuffer, ARRAYBUFFER);
|
||||
ASSERT_ENUM_EQUAL(blob, BLOB);
|
||||
ASSERT_ENUM_EQUAL(document, DOCUMENT);
|
||||
ASSERT_ENUM_EQUAL(json, JSON);
|
||||
ASSERT_ENUM_EQUAL(text, TEXT);
|
||||
ASSERT_ENUM_EQUAL(moz_chunked_text, CHUNKED_TEXT);
|
||||
ASSERT_ENUM_EQUAL(moz_chunked_arraybuffer, CHUNKED_ARRAYBUFFER);
|
||||
ASSERT_ENUM_EQUAL(moz_blob, MOZ_BLOB);
|
||||
ASSERT_ENUM_EQUAL(Arraybuffer, ARRAYBUFFER);
|
||||
ASSERT_ENUM_EQUAL(Blob, BLOB);
|
||||
ASSERT_ENUM_EQUAL(Document, DOCUMENT);
|
||||
ASSERT_ENUM_EQUAL(Json, JSON);
|
||||
ASSERT_ENUM_EQUAL(Text, TEXT);
|
||||
ASSERT_ENUM_EQUAL(Moz_chunked_text, CHUNKED_TEXT);
|
||||
ASSERT_ENUM_EQUAL(Moz_chunked_arraybuffer, CHUNKED_ARRAYBUFFER);
|
||||
ASSERT_ENUM_EQUAL(Moz_blob, MOZ_BLOB);
|
||||
#undef ASSERT_ENUM_EQUAL
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -44,7 +44,7 @@ function testCharacterData(aNode, aText)
|
|||
is(aNode.namespaceURI, null, "Check namespaceURI");
|
||||
}
|
||||
|
||||
function testComment(aText, aShouldSucceed)
|
||||
function testComment(aText)
|
||||
{
|
||||
try {
|
||||
var comment = document.createComment(aText);
|
||||
|
@ -58,18 +58,8 @@ function testComment(aText, aShouldSucceed)
|
|||
testCharacterData(comment, aText);
|
||||
is(comment.nodeName, "#comment", "Check nodeName");
|
||||
is(comment.nodeType, Node.COMMENT_NODE, "Check nodeType");
|
||||
|
||||
if (!aShouldSucceed) {
|
||||
ok(0, "Invalid comment creation",
|
||||
"Shouldn't create comment with embedded \"--\"");
|
||||
}
|
||||
} catch (e) {
|
||||
if (aShouldSucceed) {
|
||||
ok(0, "Correct functioning of comment stuff", "something broke: " + e);
|
||||
} else {
|
||||
is(e.name, "InvalidCharacterError", "Check exception");
|
||||
is(e.code, DOMException.INVALID_CHARACTER_ERR, "Check exception code");
|
||||
}
|
||||
ok(0, "Correct functioning of comment stuff", "something broke: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,11 +109,11 @@ function testPI(aTarget, aData, aShouldSucceed, aReason)
|
|||
}
|
||||
}
|
||||
|
||||
testComment("Some text", true);
|
||||
testComment("Some text with a '-' in it", true);
|
||||
testComment("Some text with a '-' and a '-' and another '-'", true);
|
||||
testComment("Some text -- this shouldn't create a node!", false);
|
||||
testComment("<!-- This is an HTML comment -->", false);
|
||||
testComment("Some text");
|
||||
testComment("Some text with a '-' in it");
|
||||
testComment("Some text with a '-' and a '-' and another '-'");
|
||||
testComment("Some text -- this shouldn't create a node!");
|
||||
testComment("<!-- This is an HTML comment -->");
|
||||
|
||||
testCDATASection("Some text", true);
|
||||
testCDATASection("Some text with a '?' in it", true);
|
||||
|
|
|
@ -68,7 +68,7 @@ function testCharacterData(aNode, aText)
|
|||
is(aNode.namespaceURI, null, "Check namespaceURI");
|
||||
}
|
||||
|
||||
function testComment(aText, aShouldSucceed)
|
||||
function testComment(aText)
|
||||
{
|
||||
try {
|
||||
var comment = document.createComment(aText);
|
||||
|
@ -82,18 +82,8 @@ function testComment(aText, aShouldSucceed)
|
|||
testCharacterData(comment, aText);
|
||||
is(comment.nodeName, "#comment", "Check nodeName");
|
||||
is(comment.nodeType, Node.COMMENT_NODE, "Check nodeType");
|
||||
|
||||
if (!aShouldSucceed) {
|
||||
ok(0, "Invalid comment creation",
|
||||
"Shouldn't create comment with embedded \"--\"");
|
||||
}
|
||||
} catch (e) {
|
||||
if (aShouldSucceed) {
|
||||
ok(0, "Correct functioning of comment stuff", "something broke: " + e);
|
||||
} else {
|
||||
is(e.name, "InvalidCharacterError", "Check exception");
|
||||
is(e.code, DOMException.INVALID_CHARACTER_ERR, "Check exception code");
|
||||
}
|
||||
ok(0, "Correct functioning of comment stuff", "something broke: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,11 +153,11 @@ function testPI(aTarget, aData, aShouldSucceed, aReason)
|
|||
}
|
||||
}
|
||||
|
||||
testComment("Some text", true);
|
||||
testComment("Some text with a '-' in it", true);
|
||||
testComment("Some text with a '-' and a '-' and another '-'", true);
|
||||
testComment("Some text -- this shouldn't create a node!", false);
|
||||
testComment("<!-- This is an HTML comment -->", false);
|
||||
testComment("Some text");
|
||||
testComment("Some text with a '-' in it");
|
||||
testComment("Some text with a '-' and a '-' and another '-'");
|
||||
testComment("Some text -- this should create a node!");
|
||||
testComment("<!-- This is an HTML comment -->");
|
||||
|
||||
testCDATASection("Some text", true);
|
||||
testCDATASection("Some text with a '?' in it", true);
|
||||
|
|
|
@ -76,7 +76,7 @@ WebGLContext::WebGLContext()
|
|||
: gl(nsnull)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
mEnabledExtensions.SetLength(WebGLExtensionID_Max);
|
||||
mExtensions.SetLength(WebGLExtensionID_number_of_extensions);
|
||||
|
||||
mGeneration = 0;
|
||||
mInvalidated = false;
|
||||
|
@ -840,37 +840,35 @@ WebGLContext::MozGetUnderlyingParamString(PRUint32 pname, nsAString& retval)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
|
||||
bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext)
|
||||
{
|
||||
bool isSupported;
|
||||
bool isSupported = false;
|
||||
|
||||
switch (ei) {
|
||||
case WebGL_OES_texture_float:
|
||||
switch (ext) {
|
||||
case OES_standard_derivatives:
|
||||
case WEBGL_lose_context:
|
||||
// We always support these extensions.
|
||||
isSupported = true;
|
||||
break;
|
||||
case OES_texture_float:
|
||||
isSupported = gl->IsExtensionSupported(gl->IsGLES2() ? GLContext::OES_texture_float
|
||||
: GLContext::ARB_texture_float);
|
||||
break;
|
||||
case WebGL_OES_standard_derivatives:
|
||||
// We always support this extension.
|
||||
isSupported = true;
|
||||
break;
|
||||
case WebGL_EXT_texture_filter_anisotropic:
|
||||
case EXT_texture_filter_anisotropic:
|
||||
isSupported = gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
|
||||
break;
|
||||
case WebGL_WEBGL_lose_context:
|
||||
// We always support this extension.
|
||||
isSupported = true;
|
||||
break;
|
||||
case WebGL_WEBGL_compressed_texture_s3tc:
|
||||
case WEBGL_compressed_texture_s3tc:
|
||||
if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_s3tc)) {
|
||||
isSupported = true;
|
||||
} else {
|
||||
isSupported = gl->IsExtensionSupported(GLContext::EXT_texture_compression_dxt1) &&
|
||||
gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt3) &&
|
||||
gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt5);
|
||||
} else if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_dxt1) &&
|
||||
gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt3) &&
|
||||
gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt5))
|
||||
{
|
||||
isSupported = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
isSupported = false;
|
||||
MOZ_ASSERT(false, "should not get there.");
|
||||
}
|
||||
|
||||
return isSupported;
|
||||
|
@ -889,62 +887,73 @@ WebGLContext::GetExtension(const nsAString& aName)
|
|||
{
|
||||
if (!IsContextStable())
|
||||
return nsnull;
|
||||
|
||||
|
||||
if (mDisableExtensions) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsString lowerCaseName(aName);
|
||||
ToLowerCase(lowerCaseName);
|
||||
WebGLExtensionID ext = WebGLExtensionID_unknown_extension;
|
||||
|
||||
WebGLExtensionID ei = WebGLExtensionID_Max;
|
||||
if (lowerCaseName.EqualsLiteral("oes_texture_float")) {
|
||||
if (IsExtensionSupported(WebGL_OES_texture_float))
|
||||
ei = WebGL_OES_texture_float;
|
||||
if (aName.Equals(NS_LITERAL_STRING("OES_texture_float"),
|
||||
nsCaseInsensitiveStringComparator()))
|
||||
{
|
||||
if (IsExtensionSupported(OES_texture_float))
|
||||
ext = OES_texture_float;
|
||||
}
|
||||
else if (lowerCaseName.EqualsLiteral("oes_standard_derivatives")) {
|
||||
if (IsExtensionSupported(WebGL_OES_standard_derivatives))
|
||||
ei = WebGL_OES_standard_derivatives;
|
||||
else if (aName.Equals(NS_LITERAL_STRING("OES_standard_derivatives"),
|
||||
nsCaseInsensitiveStringComparator()))
|
||||
{
|
||||
if (IsExtensionSupported(OES_standard_derivatives))
|
||||
ext = OES_standard_derivatives;
|
||||
}
|
||||
else if (lowerCaseName.EqualsLiteral("moz_ext_texture_filter_anisotropic")) {
|
||||
if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
|
||||
ei = WebGL_EXT_texture_filter_anisotropic;
|
||||
else if (aName.Equals(NS_LITERAL_STRING("MOZ_EXT_texture_filter_anisotropic"),
|
||||
nsCaseInsensitiveStringComparator()))
|
||||
{
|
||||
if (IsExtensionSupported(EXT_texture_filter_anisotropic))
|
||||
ext = EXT_texture_filter_anisotropic;
|
||||
}
|
||||
else if (lowerCaseName.EqualsLiteral("moz_webgl_lose_context")) {
|
||||
if (IsExtensionSupported(WebGL_WEBGL_lose_context))
|
||||
ei = WebGL_WEBGL_lose_context;
|
||||
else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"),
|
||||
nsCaseInsensitiveStringComparator()))
|
||||
{
|
||||
if (IsExtensionSupported(WEBGL_lose_context))
|
||||
ext = WEBGL_lose_context;
|
||||
}
|
||||
else if (lowerCaseName.EqualsLiteral("moz_webgl_compressed_texture_s3tc")) {
|
||||
if (IsExtensionSupported(WebGL_WEBGL_compressed_texture_s3tc))
|
||||
ei = WebGL_WEBGL_compressed_texture_s3tc;
|
||||
else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"),
|
||||
nsCaseInsensitiveStringComparator()))
|
||||
{
|
||||
if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
|
||||
ext = WEBGL_compressed_texture_s3tc;
|
||||
}
|
||||
|
||||
if (ei != WebGLExtensionID_Max) {
|
||||
if (!IsExtensionEnabled(ei)) {
|
||||
switch (ei) {
|
||||
case WebGL_OES_standard_derivatives:
|
||||
mEnabledExtensions[ei] = new WebGLExtensionStandardDerivatives(this);
|
||||
break;
|
||||
case WebGL_EXT_texture_filter_anisotropic:
|
||||
mEnabledExtensions[ei] = new WebGLExtensionTextureFilterAnisotropic(this);
|
||||
break;
|
||||
case WebGL_WEBGL_lose_context:
|
||||
mEnabledExtensions[ei] = new WebGLExtensionLoseContext(this);
|
||||
break;
|
||||
case WebGL_WEBGL_compressed_texture_s3tc:
|
||||
mEnabledExtensions[ei] = new WebGLExtensionCompressedTextureS3TC(this);
|
||||
break;
|
||||
// create an extension for any types that don't
|
||||
// have any additional tokens or methods
|
||||
default:
|
||||
mEnabledExtensions[ei] = new WebGLExtension(this);
|
||||
break;
|
||||
}
|
||||
if (ext == WebGLExtensionID_unknown_extension) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!mExtensions[ext]) {
|
||||
switch (ext) {
|
||||
case OES_standard_derivatives:
|
||||
mExtensions[ext] = new WebGLExtensionStandardDerivatives(this);
|
||||
break;
|
||||
case EXT_texture_filter_anisotropic:
|
||||
mExtensions[ext] = new WebGLExtensionTextureFilterAnisotropic(this);
|
||||
break;
|
||||
case WEBGL_lose_context:
|
||||
mExtensions[ext] = new WebGLExtensionLoseContext(this);
|
||||
break;
|
||||
case WEBGL_compressed_texture_s3tc:
|
||||
mExtensions[ext] = new WebGLExtensionCompressedTextureS3TC(this);
|
||||
break;
|
||||
default:
|
||||
// create a generic WebGLExtension object for any extensions that don't
|
||||
// have any additional tokens or methods. We still need these to be separate
|
||||
// objects in case the user might extend the corresponding JS objects with custom
|
||||
// properties.
|
||||
mExtensions[ext] = new WebGLExtension(this);
|
||||
break;
|
||||
}
|
||||
return mEnabledExtensions[ei];
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
return mExtensions[ext];
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1211,13 +1220,13 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLContext)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mEnabledExtensions)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mExtensions)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebGLContext)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCanvasElement, nsINode)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mEnabledExtensions)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mExtensions)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
@ -1312,6 +1321,12 @@ NS_INTERFACE_MAP_BEGIN(WebGLUniformLocation)
|
|||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLUniformLocation)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
JSObject*
|
||||
WebGLUniformLocation::WrapObject(JSContext *cx, JSObject *scope)
|
||||
{
|
||||
return dom::WebGLUniformLocationBinding::Wrap(cx, scope, this);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(WebGLShaderPrecisionFormat)
|
||||
NS_IMPL_RELEASE(WebGLShaderPrecisionFormat)
|
||||
|
||||
|
@ -1491,15 +1506,15 @@ WebGLContext::GetSupportedExtensions(Nullable< nsTArray<nsString> > &retval)
|
|||
|
||||
nsTArray<nsString>& arr = retval.SetValue();
|
||||
|
||||
if (IsExtensionSupported(WebGL_OES_texture_float))
|
||||
if (IsExtensionSupported(OES_texture_float))
|
||||
arr.AppendElement(NS_LITERAL_STRING("OES_texture_float"));
|
||||
if (IsExtensionSupported(WebGL_OES_standard_derivatives))
|
||||
if (IsExtensionSupported(OES_standard_derivatives))
|
||||
arr.AppendElement(NS_LITERAL_STRING("OES_standard_derivatives"));
|
||||
if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
|
||||
if (IsExtensionSupported(EXT_texture_filter_anisotropic))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_EXT_texture_filter_anisotropic"));
|
||||
if (IsExtensionSupported(WebGL_WEBGL_lose_context))
|
||||
if (IsExtensionSupported(WEBGL_lose_context))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
|
||||
if (IsExtensionSupported(WebGL_WEBGL_compressed_texture_s3tc))
|
||||
if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
|
||||
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
|
||||
}
|
||||
|
||||
|
|
|
@ -1156,19 +1156,23 @@ protected:
|
|||
|
||||
// extensions
|
||||
enum WebGLExtensionID {
|
||||
WebGL_OES_texture_float,
|
||||
WebGL_OES_standard_derivatives,
|
||||
WebGL_EXT_texture_filter_anisotropic,
|
||||
WebGL_WEBGL_lose_context,
|
||||
WebGL_WEBGL_compressed_texture_s3tc,
|
||||
WebGLExtensionID_Max
|
||||
OES_texture_float,
|
||||
OES_standard_derivatives,
|
||||
EXT_texture_filter_anisotropic,
|
||||
WEBGL_lose_context,
|
||||
WEBGL_compressed_texture_s3tc,
|
||||
WebGLExtensionID_number_of_extensions,
|
||||
WebGLExtensionID_unknown_extension
|
||||
};
|
||||
nsAutoTArray<nsRefPtr<WebGLExtension>, WebGLExtensionID_Max> mEnabledExtensions;
|
||||
bool IsExtensionEnabled(WebGLExtensionID ext) const {
|
||||
NS_ABORT_IF_FALSE(ext >= 0 && ext < WebGLExtensionID_Max, "bogus index!");
|
||||
return mEnabledExtensions[ext] != nsnull;
|
||||
nsAutoTArray<nsRefPtr<WebGLExtension>, WebGLExtensionID_number_of_extensions> mExtensions;
|
||||
|
||||
// returns true if the extension has been enabled by calling getExtension.
|
||||
bool IsExtensionEnabled(WebGLExtensionID ext) {
|
||||
return mExtensions[ext];
|
||||
}
|
||||
bool IsExtensionSupported(WebGLExtensionID ei);
|
||||
|
||||
// returns true if the extension is supported (as returned by getSupportedExtensions)
|
||||
bool IsExtensionSupported(WebGLExtensionID ext);
|
||||
|
||||
nsTArray<WebGLenum> mCompressedTextureFormats;
|
||||
|
||||
|
@ -2200,7 +2204,11 @@ protected:
|
|||
*/
|
||||
static bool SplitLastSquareBracket(nsACString& string, nsCString& bracketPart)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(bracketPart.Length() == 0, "SplitLastSquareBracket must be called with empty bracketPart string");
|
||||
MOZ_ASSERT(bracketPart.IsEmpty(), "SplitLastSquareBracket must be called with empty bracketPart string");
|
||||
|
||||
if (string.IsEmpty())
|
||||
return false;
|
||||
|
||||
char *string_start = string.BeginWriting();
|
||||
char *s = string_start + string.Length() - 1;
|
||||
|
||||
|
@ -2996,6 +3004,8 @@ public:
|
|||
uint32_t ProgramGeneration() const { return mProgramGeneration; }
|
||||
int ElementSize() const { return mElementSize; }
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBGLUNIFORMLOCATION
|
||||
protected:
|
||||
|
|
|
@ -2423,7 +2423,7 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
|
|||
return JS::Int32Value(i);
|
||||
}
|
||||
case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
|
||||
if (mEnabledExtensions[WebGL_OES_standard_derivatives]) {
|
||||
if (IsExtensionEnabled(OES_standard_derivatives)) {
|
||||
GLint i = 0;
|
||||
gl->fGetIntegerv(pname, &i);
|
||||
return JS::Int32Value(i);
|
||||
|
@ -2470,7 +2470,7 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
|
|||
|
||||
// float
|
||||
case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
|
||||
if (IsExtensionEnabled(EXT_texture_filter_anisotropic)) {
|
||||
GLfloat f = 0.f;
|
||||
gl->fGetFloatv(pname, &f);
|
||||
return JS::DoubleValue(f);
|
||||
|
@ -3114,7 +3114,7 @@ void WebGLContext::TexParameter_base(WebGLenum target, WebGLenum pname,
|
|||
}
|
||||
break;
|
||||
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
|
||||
if (IsExtensionEnabled(EXT_texture_filter_anisotropic)) {
|
||||
if (floatParamPtr && floatParam < 1.f)
|
||||
paramValueInvalid = true;
|
||||
else if (intParamPtr && intParam < 1)
|
||||
|
@ -3198,7 +3198,7 @@ WebGLContext::GetTexParameter(WebGLenum target, WebGLenum pname)
|
|||
return JS::NumberValue(uint32_t(i));
|
||||
}
|
||||
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
|
||||
if (IsExtensionEnabled(EXT_texture_filter_anisotropic)) {
|
||||
GLfloat f = 0.f;
|
||||
gl->fGetTexParameterfv(target, pname, &f);
|
||||
return JS::DoubleValue(f);
|
||||
|
@ -3529,7 +3529,7 @@ WebGLContext::Hint(WebGLenum target, WebGLenum mode)
|
|||
isValid = true;
|
||||
break;
|
||||
case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
|
||||
if (mEnabledExtensions[WebGL_OES_standard_derivatives])
|
||||
if (IsExtensionEnabled(OES_standard_derivatives))
|
||||
isValid = true;
|
||||
break;
|
||||
}
|
||||
|
@ -3849,6 +3849,9 @@ WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width,
|
|||
if (width < 0 || height < 0)
|
||||
return ErrorInvalidValue("readPixels: negative size passed");
|
||||
|
||||
if (!pixels)
|
||||
return ErrorInvalidValue("readPixels: null destination buffer");
|
||||
|
||||
const WebGLRectangleObject *framebufferRect = FramebufferRectangleObject();
|
||||
WebGLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
|
||||
WebGLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
|
||||
|
@ -4915,7 +4918,7 @@ WebGLContext::CompileShader(WebGLShader *shader)
|
|||
resources.MaxTextureImageUnits = mGLMaxTextureImageUnits;
|
||||
resources.MaxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
|
||||
resources.MaxDrawBuffers = 1;
|
||||
if (mEnabledExtensions[WebGL_OES_standard_derivatives])
|
||||
if (IsExtensionEnabled(OES_standard_derivatives))
|
||||
resources.OES_standard_derivatives = 1;
|
||||
|
||||
// We're storing an actual instance of StripComments because, if we don't, the
|
||||
|
|
|
@ -311,6 +311,9 @@ bool WebGLContext::ValidateDrawModeEnum(WebGLenum mode, const char *info)
|
|||
|
||||
bool WebGLContext::ValidateGLSLVariableName(const nsAString& name, const char *info)
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
return false;
|
||||
|
||||
const uint32_t maxSize = 256;
|
||||
if (name.Length() > maxSize) {
|
||||
ErrorInvalidValue("%s: identifier is %d characters long, exceeds the maximum allowed length of %d characters",
|
||||
|
@ -483,7 +486,7 @@ bool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, in
|
|||
uint32_t *texelSize, const char *info)
|
||||
{
|
||||
if (type == LOCAL_GL_UNSIGNED_BYTE ||
|
||||
(IsExtensionEnabled(WebGL_OES_texture_float) && type == LOCAL_GL_FLOAT))
|
||||
(IsExtensionEnabled(OES_texture_float) && type == LOCAL_GL_FLOAT))
|
||||
{
|
||||
if (jsArrayType != -1) {
|
||||
if ((type == LOCAL_GL_UNSIGNED_BYTE && jsArrayType != js::ArrayBufferView::TYPE_UINT8) ||
|
||||
|
|
|
@ -1534,7 +1534,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(WebGLRenderbuffer, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(WebGLUniformLocation, nsDOMGenericSH,
|
||||
NS_DEFINE_CLASSINFO_DATA(WebGLUniformLocation,
|
||||
nsNewDOMBindingNoWrapperCacheSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(WebGLShaderPrecisionFormat, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
@ -9095,9 +9096,10 @@ nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHan
|
|||
void
|
||||
nsHTMLDocumentSH::ReleaseDocument(JSFreeOp *fop, JSObject *obj)
|
||||
{
|
||||
nsIHTMLDocument *doc = (nsIHTMLDocument *)::JS_GetPrivate(obj);
|
||||
|
||||
NS_IF_RELEASE(doc);
|
||||
nsIHTMLDocument *doc = static_cast<nsIHTMLDocument *>(JS_GetPrivate(obj));
|
||||
if (doc) {
|
||||
xpc::DeferredRelease(doc);
|
||||
}
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -10899,6 +10901,16 @@ WebGLExtensionSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
|||
return WrapNativeParent(cx, globalObj, node, node, parentObj);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNewDOMBindingNoWrapperCacheSH::PreCreate(nsISupports *nativeObj,
|
||||
JSContext *cx,
|
||||
JSObject *globalObj,
|
||||
JSObject **parentObj)
|
||||
{
|
||||
// We don't allow this
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebGLViewportHandlerSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj)
|
||||
|
|
|
@ -486,6 +486,28 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// scriptable helper for new-binding objects without wrapper caches
|
||||
|
||||
class nsNewDOMBindingNoWrapperCacheSH : public nsDOMGenericSH
|
||||
{
|
||||
protected:
|
||||
nsNewDOMBindingNoWrapperCacheSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~nsNewDOMBindingNoWrapperCacheSH()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
return new nsNewDOMBindingNoWrapperCacheSH(aData);
|
||||
}
|
||||
};
|
||||
|
||||
// DOM Node helper, this class deals with setting the parent for the
|
||||
// wrappers
|
||||
|
|
|
@ -56,11 +56,7 @@ DOMCI_CASTABLE_INTERFACE(nsGenericHTMLElement, nsGenericHTMLElement, 6, \
|
|||
DOMCI_CASTABLE_INTERFACE(nsHTMLDocument, nsIDocument, 7, _extra) \
|
||||
DOMCI_CASTABLE_INTERFACE(nsStyledElement, nsStyledElement, 8, _extra) \
|
||||
DOMCI_CASTABLE_INTERFACE(nsSVGStylableElement, nsIContent, 9, _extra) \
|
||||
DOMCI_CASTABLE_INTERFACE(nsIWebGLUniformLocation, \
|
||||
nsIWebGLUniformLocation, 11, _extra) \
|
||||
DOMCI_CASTABLE_INTERFACE(nsIDOMImageData, nsIDOMImageData, 12, _extra) \
|
||||
DOMCI_CASTABLE_NAMESPACED_INTERFACE(mozilla, WebGLUniformLocation, \
|
||||
nsIWebGLUniformLocation, 13, _extra)
|
||||
DOMCI_CASTABLE_INTERFACE(nsIDOMImageData, nsIDOMImageData, 12, _extra)
|
||||
|
||||
// Make sure all classes mentioned in DOMCI_CASTABLE_INTERFACES
|
||||
// have been declared.
|
||||
|
|
|
@ -177,6 +177,11 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
|||
"Memory used by the comment nodes in a window's DOM.");
|
||||
aWindowTotalSizes->mDOMCommentNodes += windowSizes.mDOMCommentNodes;
|
||||
|
||||
REPORT("/property-tables",
|
||||
windowSizes.mPropertyTables,
|
||||
"Memory used for the property tables within a window.");
|
||||
aWindowTotalSizes->mPropertyTables += windowSizes.mPropertyTables;
|
||||
|
||||
REPORT("/style-sheets", windowSizes.mStyleSheets,
|
||||
"Memory used by style sheets within a window.");
|
||||
aWindowTotalSizes->mStyleSheets += windowSizes.mStyleSheets;
|
||||
|
@ -328,6 +333,11 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
|||
"Memory used for DOM comment nodes within windows. "
|
||||
"This is the sum of all windows' 'dom/comment-nodes' numbers.");
|
||||
|
||||
REPORT("window-objects/property-tables",
|
||||
windowTotalSizes.mPropertyTables,
|
||||
"Memory used for property tables within windows. "
|
||||
"This is the sum of all windows' 'property-tables' numbers.");
|
||||
|
||||
REPORT("window-objects/style-sheets", windowTotalSizes.mStyleSheets,
|
||||
"Memory used for style sheets within windows. "
|
||||
"This is the sum of all windows' 'style-sheets' numbers.");
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
size_t mLayoutStyleSets;
|
||||
size_t mLayoutTextRuns;
|
||||
size_t mLayoutPresContext;
|
||||
size_t mPropertyTables;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -249,4 +249,19 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
|
||||
|
||||
#define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(_class, _field1,\
|
||||
_field2) \
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_field1) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_field2) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_field1) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_field2) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
|
||||
|
||||
#endif /* nsWrapperCache_h___ */
|
||||
|
|
|
@ -339,6 +339,42 @@ WrapNewBindingObject(JSContext* cx, JSObject* scope, const SmartPtr<T>& value,
|
|||
return WrapNewBindingObject(cx, scope, value.get(), vp);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool
|
||||
WrapNewBindingNonWrapperCachedObject(JSContext* cx, JSObject* scope, T* value,
|
||||
JS::Value* vp)
|
||||
{
|
||||
// We try to wrap in the compartment of the underlying object of "scope"
|
||||
JSObject* obj;
|
||||
{
|
||||
// scope for the JSAutoEnterCompartment so that we restore the
|
||||
// compartment before we call JS_WrapValue.
|
||||
JSAutoEnterCompartment ac;
|
||||
if (js::IsWrapper(scope)) {
|
||||
scope = xpc::Unwrap(cx, scope, false);
|
||||
if (!scope || !ac.enter(cx, scope)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
obj = value->WrapObject(cx, scope);
|
||||
}
|
||||
|
||||
// We can end up here in all sorts of compartments, per above. Make
|
||||
// sure to JS_WrapValue!
|
||||
*vp = JS::ObjectValue(*obj);
|
||||
return JS_WrapValue(cx, vp);
|
||||
}
|
||||
|
||||
// Helper for smart pointers (nsAutoPtr/nsRefPtr/nsCOMPtr).
|
||||
template <template <typename> class SmartPtr, typename T>
|
||||
inline bool
|
||||
WrapNewBindingNonWrapperCachedObject(JSContext* cx, JSObject* scope,
|
||||
const SmartPtr<T>& value, JS::Value* vp)
|
||||
{
|
||||
return WrapNewBindingNonWrapperCachedObject(cx, scope, value.get(), vp);
|
||||
}
|
||||
|
||||
/**
|
||||
* A method to handle new-binding wrap failure, by possibly falling back to
|
||||
* wrapping as a non-new-binding object.
|
||||
|
|
|
@ -34,6 +34,11 @@
|
|||
# dict). The keys are the property names as they appear in the
|
||||
# .webidl file and the values are the names as they should be
|
||||
# in the WebIDL.
|
||||
# * wrapperCache: True if this object is a wrapper cache. Objects that are
|
||||
# not can only be returned from a limited set of methods,
|
||||
# cannot be prefable, and must ensure that they disallow
|
||||
# XPConnect wrapping. Always true for worker descriptors.
|
||||
# Defaults to true.
|
||||
#
|
||||
# The following fields are either a string, an array (defaults to an empty
|
||||
# array) or a dictionary with three possible keys (all, getterOnly and
|
||||
|
@ -221,6 +226,12 @@ DOMInterfaces = {
|
|||
]
|
||||
},
|
||||
|
||||
'WebGLUniformLocation': {
|
||||
'nativeType': 'mozilla::WebGLUniformLocation',
|
||||
'headerFile': 'WebGLContext.h',
|
||||
'wrapperCache': False
|
||||
},
|
||||
|
||||
'XMLHttpRequest': [
|
||||
{
|
||||
'nativeType': 'nsXMLHttpRequest',
|
||||
|
@ -312,12 +323,18 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
'TestExternalInterface' : {
|
||||
'nativeType': 'mozilla::dom::TestExternalInterface',
|
||||
'headerFile': 'TestBindingHeader.h',
|
||||
'register': False,
|
||||
'castable': False
|
||||
},
|
||||
'nativeType': 'mozilla::dom::TestExternalInterface',
|
||||
'headerFile': 'TestBindingHeader.h',
|
||||
'register': False,
|
||||
'castable': False
|
||||
},
|
||||
|
||||
'TestNonWrapperCacheInterface' : {
|
||||
'nativeType': 'mozilla::dom::TestNonWrapperCacheInterface',
|
||||
'headerFile': 'TestBindingHeader.h',
|
||||
'register': False,
|
||||
'wrapperCache': False
|
||||
},
|
||||
}
|
||||
|
||||
# These are temporary, until they've been converted to use new DOM bindings
|
||||
|
@ -366,6 +383,3 @@ addExternalIface('WebGLShaderPrecisionFormat',
|
|||
headerFile='WebGLContext.h')
|
||||
addExternalIface('WebGLTexture', nativeType='mozilla::WebGLTexture',
|
||||
headerFile='WebGLContext.h')
|
||||
addExternalIface('WebGLUniformLocation',
|
||||
nativeType='mozilla::WebGLUniformLocation',
|
||||
headerFile='WebGLContext.h')
|
||||
|
|
|
@ -121,7 +121,7 @@ DOMJSClass Class = {
|
|||
%s
|
||||
};
|
||||
""" % (self.descriptor.interface.identifier.name,
|
||||
ADDPROPERTY_HOOK_NAME if self.descriptor.concrete and not self.descriptor.workers else 'JS_PropertyStub',
|
||||
ADDPROPERTY_HOOK_NAME if self.descriptor.concrete and not self.descriptor.workers and self.descriptor.wrapperCache else 'JS_PropertyStub',
|
||||
FINALIZE_HOOK_NAME, traceHook, prototypeChainString,
|
||||
str(self.descriptor.nativeIsISupports).lower(),
|
||||
nativeHooks)
|
||||
|
@ -518,20 +518,19 @@ class CGClassFinalizeHook(CGAbstractClassHook):
|
|||
return """ if (self) {
|
||||
self->%s(%s);
|
||||
}""" % (self.name, self.args[0].name)
|
||||
clearWrapper = "self->ClearWrapper();\n " if self.descriptor.wrapperCache else ""
|
||||
if self.descriptor.workers:
|
||||
release = "self->Release();"
|
||||
else:
|
||||
assert self.descriptor.nativeIsISupports
|
||||
release = """
|
||||
XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
|
||||
release = """XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
|
||||
if (rt) {
|
||||
rt->DeferredRelease(reinterpret_cast<nsISupports*>(self));
|
||||
} else {
|
||||
NS_RELEASE(self);
|
||||
}"""
|
||||
return """
|
||||
self->ClearWrapper();
|
||||
%s""" % (release)
|
||||
%s%s""" % (clearWrapper, release)
|
||||
|
||||
class CGClassTraceHook(CGAbstractClassHook):
|
||||
"""
|
||||
|
@ -1212,6 +1211,32 @@ class CGWrapMethod(CGAbstractMethod):
|
|||
|
||||
return obj;""" % (CheckPref(self.descriptor, "global", "*aTriedToWrap", "NULL", "aObject"))
|
||||
|
||||
class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
|
||||
def __init__(self, descriptor):
|
||||
# XXX can we wrap if we don't have an interface prototype object?
|
||||
assert descriptor.interface.hasInterfacePrototypeObject()
|
||||
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aScope'),
|
||||
Argument(descriptor.nativeType + '*', 'aObject')]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
|
||||
|
||||
def definition_body(self):
|
||||
return """
|
||||
JSObject* global = JS_GetGlobalForObject(aCx, aScope);
|
||||
JSObject* proto = GetProtoObject(aCx, global, global);
|
||||
if (!proto) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSObject* obj = JS_NewObject(aCx, &Class.mBase, proto, global);
|
||||
if (!obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
js::SetReservedSlot(obj, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aObject));
|
||||
NS_ADDREF(aObject);
|
||||
|
||||
return obj;"""
|
||||
|
||||
builtinNames = {
|
||||
IDLType.Tags.bool: 'bool',
|
||||
IDLType.Tags.int8: 'int8_t',
|
||||
|
@ -1506,6 +1531,11 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
|
||||
templateBody = ""
|
||||
if descriptor.castable:
|
||||
if descriptor.prefable:
|
||||
raise TypeError("We don't support prefable castable object "
|
||||
"arguments (like %s), because we don't know "
|
||||
"how to handle them being preffed off" %
|
||||
descriptor.interface.identifier.name)
|
||||
if failureCode is not None:
|
||||
templateBody += str(CastableObjectUnwrapper(
|
||||
descriptor,
|
||||
|
@ -1923,7 +1953,8 @@ class CGArgumentConverter(CGThing):
|
|||
self.replacementVariables,
|
||||
self.argcAndIndex).define()
|
||||
|
||||
def getWrapTemplateForType(type, descriptorProvider, result, successCode):
|
||||
def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
||||
isCreator):
|
||||
"""
|
||||
Reflect a C++ value stored in "result", of IDL type "type" into JS. The
|
||||
"successCode" is the code to run once we have successfully done the
|
||||
|
@ -1981,7 +2012,8 @@ if (%s.IsNull()) {
|
|||
}
|
||||
%s""" % (result, CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define(),
|
||||
getWrapTemplateForType(type.inner, descriptorProvider,
|
||||
"%s.Value()" % result, successCode))
|
||||
"%s.Value()" % result, successCode,
|
||||
isCreator))
|
||||
|
||||
# Now do non-nullable sequences. We use setting the element
|
||||
# in the array as our succcess code because when we succeed in
|
||||
|
@ -1994,7 +2026,8 @@ if (%s.IsNull()) {
|
|||
" return false;\n"
|
||||
"}"),
|
||||
'jsvalRef': "tmp",
|
||||
'jsvalPtr': "&tmp"
|
||||
'jsvalPtr': "&tmp",
|
||||
'isCreator': isCreator
|
||||
}
|
||||
)
|
||||
innerTemplate = CGIndenter(CGGeneric(innerTemplate)).define()
|
||||
|
@ -2018,7 +2051,13 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
else:
|
||||
wrappingCode = ""
|
||||
if descriptor.castable and not type.unroll().inner.isExternal():
|
||||
wrap = "WrapNewBindingObject(cx, ${obj}, %s, ${jsvalPtr})" % result
|
||||
if descriptor.wrapperCache:
|
||||
wrapMethod = "WrapNewBindingObject"
|
||||
else:
|
||||
if not isCreator:
|
||||
raise MethodNotCreatorError(descriptor.interface.identifier.name)
|
||||
wrapMethod = "WrapNewBindingNonWrapperCachedObject"
|
||||
wrap = "%s(cx, ${obj}, %s, ${jsvalPtr})" % (wrapMethod, result)
|
||||
# We don't support prefable stuff in workers.
|
||||
assert(not descriptor.prefable or not descriptor.workers)
|
||||
if not descriptor.prefable:
|
||||
|
@ -2088,7 +2127,8 @@ if (!%(resultStr)s) {
|
|||
CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
|
||||
"}\n" +
|
||||
getWrapTemplateForType(type.inner, descriptorProvider,
|
||||
"%s.Value()" % result, successCode))
|
||||
"%s.Value()" % result, successCode,
|
||||
isCreator))
|
||||
|
||||
tag = type.tag()
|
||||
|
||||
|
@ -2129,10 +2169,13 @@ def wrapForType(type, descriptorProvider, templateValues):
|
|||
* 'successCode' (optional): the code to run once we have successfully done
|
||||
the conversion, if not supplied 'return true;'
|
||||
will be used as the code
|
||||
* 'isCreator' (optional): If true, we're wrapping for the return value of
|
||||
a [Creator] method. Assumed false if not set.
|
||||
"""
|
||||
wrap = getWrapTemplateForType(type, descriptorProvider,
|
||||
templateValues.get('result', 'result'),
|
||||
templateValues.get('successCode', None))
|
||||
templateValues.get('successCode', None),
|
||||
templateValues.get('isCreator', False))
|
||||
|
||||
defaultValues = {'obj': 'obj'}
|
||||
return string.Template(wrap).substitute(defaultValues, **templateValues)
|
||||
|
@ -2261,6 +2304,10 @@ class CGCallGenerator(CGThing):
|
|||
def define(self):
|
||||
return self.cgRoot.define()
|
||||
|
||||
class MethodNotCreatorError(Exception):
|
||||
def __init__(self, typename):
|
||||
self.typename = typename
|
||||
|
||||
class CGPerSignatureCall(CGThing):
|
||||
"""
|
||||
This class handles the guts of generating code for a particular
|
||||
|
@ -2324,9 +2371,23 @@ class CGPerSignatureCall(CGThing):
|
|||
return not 'infallible' in self.extendedAttributes
|
||||
|
||||
def wrap_return_value(self):
|
||||
resultTemplateValues = {'jsvalRef': '*vp', 'jsvalPtr': 'vp'}
|
||||
return wrapForType(self.returnType, self.descriptor,
|
||||
resultTemplateValues)
|
||||
isCreator = self.idlNode.getExtendedAttribute("Creator") is not None
|
||||
if isCreator:
|
||||
# We better be returning addrefed things!
|
||||
assert isResultAlreadyAddRefed(self.descriptor,
|
||||
self.extendedAttributes)
|
||||
|
||||
resultTemplateValues = { 'jsvalRef': '*vp', 'jsvalPtr': 'vp',
|
||||
'isCreator': isCreator}
|
||||
try:
|
||||
return wrapForType(self.returnType, self.descriptor,
|
||||
resultTemplateValues)
|
||||
except MethodNotCreatorError, err:
|
||||
assert not isCreator
|
||||
raise TypeError("%s being returned from non-creator method or property %s.%s" %
|
||||
(err.typename,
|
||||
self.descriptor.interface.identifier.name,
|
||||
self.idlNode.identifier.name))
|
||||
|
||||
def getErrorReport(self):
|
||||
return 'return ThrowMethodFailedWithDetails<%s>(cx, rv, "%s", "%s");'\
|
||||
|
@ -2842,7 +2903,7 @@ def getEnumValueName(value):
|
|||
if not re.match("^[a-z_]+$", value):
|
||||
raise SyntaxError('Enum value "' + value + '" contains characters '
|
||||
'outside [a-z_]')
|
||||
return value
|
||||
return MakeNativeName(value)
|
||||
|
||||
class CGEnum(CGThing):
|
||||
def __init__(self, enum):
|
||||
|
@ -2925,8 +2986,7 @@ class ClassMethod(ClassItem):
|
|||
if self.bodyInHeader and self.templateArgs else ''
|
||||
args = ', '.join([str(a) for a in self.args])
|
||||
if self.bodyInHeader:
|
||||
body = ' ' + self.getBody();
|
||||
body = body.replace('\n', '\n ').rstrip(' ')
|
||||
body = CGIndenter(CGGeneric(self.getBody())).define()
|
||||
body = '\n{\n' + body + '\n}'
|
||||
else:
|
||||
body = ';'
|
||||
|
@ -2959,8 +3019,7 @@ ${name}(${args})${const}${body}
|
|||
|
||||
args = ', '.join([str(a) for a in self.args])
|
||||
|
||||
body = ' ' + self.getBody()
|
||||
body = body.replace('\n', '\n ').rstrip(' ')
|
||||
body = CGIndenter(CGGeneric(self.getBody())).define()
|
||||
|
||||
return string.Template("""${templateClause}${decorators}${returnType}
|
||||
${className}::${name}(${args})${const}
|
||||
|
@ -3105,13 +3164,10 @@ class CGClass(CGThing):
|
|||
result = result + visibility + ':\n'
|
||||
itemCount = 0
|
||||
for member in list:
|
||||
if itemCount == 0:
|
||||
result = result + ' '
|
||||
else:
|
||||
result = result + separator + ' '
|
||||
if itemCount != 0:
|
||||
result = result + separator
|
||||
declaration = member.declare(cgClass)
|
||||
declaration = declaration.replace('\n', '\n ')
|
||||
declaration = declaration.rstrip(' ')
|
||||
declaration = CGIndenter(CGGeneric(declaration)).define()
|
||||
result = result + declaration
|
||||
itemCount = itemCount + 1
|
||||
lastVisibility = visibility
|
||||
|
@ -3127,9 +3183,8 @@ class CGClass(CGThing):
|
|||
declareMembers(self, memberList, lastVisibility, itemCount,
|
||||
separator)
|
||||
if self.indent:
|
||||
memberString = self.indent + memberString
|
||||
memberString = memberString.replace('\n', '\n' + self.indent)
|
||||
memberString = memberString.rstrip(' ')
|
||||
memberString = CGIndenter(CGGeneric(memberString),
|
||||
len(self.indent)).define()
|
||||
result = result + memberString
|
||||
|
||||
result = result + self.indent + '};\n\n'
|
||||
|
@ -3331,7 +3386,7 @@ class CGDescriptor(CGThing):
|
|||
a.isAttr() and not a.readonly])
|
||||
|
||||
if descriptor.concrete:
|
||||
if not descriptor.workers:
|
||||
if not descriptor.workers and descriptor.wrapperCache:
|
||||
cgThings.append(CGAddPropertyHook(descriptor))
|
||||
|
||||
# Always have a finalize hook, regardless of whether the class wants a
|
||||
|
@ -3375,7 +3430,10 @@ class CGDescriptor(CGThing):
|
|||
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
|
||||
|
||||
if descriptor.concrete:
|
||||
cgThings.append(CGWrapMethod(descriptor))
|
||||
if descriptor.wrapperCache:
|
||||
cgThings.append(CGWrapMethod(descriptor))
|
||||
else:
|
||||
cgThings.append(CGWrapNonWrapperCacheMethod(descriptor))
|
||||
|
||||
cgThings = CGList(cgThings)
|
||||
cgThings = CGWrapper(cgThings, post='\n')
|
||||
|
|
|
@ -113,6 +113,11 @@ class Descriptor:
|
|||
self.nativeIsISupports = not self.workers
|
||||
self.customTrace = desc.get('customTrace', self.workers)
|
||||
self.customFinalize = desc.get('customFinalize', self.workers)
|
||||
self.wrapperCache = self.workers or desc.get('wrapperCache', True)
|
||||
|
||||
if not self.wrapperCache and self.prefable:
|
||||
raise TypeError("Descriptor for %s is prefable but not wrappercached" %
|
||||
self.interface.identifier.name)
|
||||
|
||||
def make_name(name):
|
||||
return name + "_workers" if self.workers else name
|
||||
|
|
|
@ -554,6 +554,9 @@ class IDLInterface(IDLObjectWithScope):
|
|||
allowForbidden=True)
|
||||
|
||||
method = IDLMethod(self.location, identifier, retType, args)
|
||||
# Constructors are always Creators and never have any
|
||||
# other extended attributes.
|
||||
method.addExtendedAttributes(["Creator"])
|
||||
method.resolve(self)
|
||||
|
||||
self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
|
||||
|
|
|
@ -45,6 +45,14 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
};
|
||||
|
||||
class TestNonWrapperCacheInterface : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* cx, JSObject* scope);
|
||||
};
|
||||
|
||||
class TestInterface : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
|
@ -156,6 +164,13 @@ public:
|
|||
void PassOptionalNonNullSelf(const Optional<NonNull<TestInterface> >&, ErrorResult&);
|
||||
void PassOptionalSelfWithDefault(TestInterface*, ErrorResult&);
|
||||
|
||||
already_AddRefed<TestNonWrapperCacheInterface> ReceiveNonWrapperCacheInterface(ErrorResult&);
|
||||
already_AddRefed<TestNonWrapperCacheInterface> ReceiveNullableNonWrapperCacheInterface(ErrorResult&);
|
||||
void ReceiveNonWrapperCacheInterfaceSequence(nsTArray<nsRefPtr<TestNonWrapperCacheInterface> >&, ErrorResult&);
|
||||
void ReceiveNullableNonWrapperCacheInterfaceSequence(nsTArray<nsRefPtr<TestNonWrapperCacheInterface> >&, ErrorResult&);
|
||||
void ReceiveNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&, ErrorResult&);
|
||||
void ReceiveNullableNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&, ErrorResult&);
|
||||
|
||||
already_AddRefed<TestNonCastableInterface> ReceiveOther(ErrorResult&);
|
||||
already_AddRefed<TestNonCastableInterface> ReceiveNullableOther(ErrorResult&);
|
||||
TestNonCastableInterface* ReceiveWeakOther(ErrorResult&);
|
||||
|
|
|
@ -102,6 +102,20 @@ interface TestInterface {
|
|||
void passOptionalNonNullSelf(optional TestInterface arg);
|
||||
void passOptionalSelfWithDefault(optional TestInterface? arg = null);
|
||||
|
||||
// Non-wrapper-cache interface types
|
||||
[Creator]
|
||||
TestNonWrapperCacheInterface receiveNonWrapperCacheInterface();
|
||||
[Creator]
|
||||
TestNonWrapperCacheInterface? receiveNullableNonWrapperCacheInterface();
|
||||
[Creator]
|
||||
sequence<TestNonWrapperCacheInterface> receiveNonWrapperCacheInterfaceSequence();
|
||||
[Creator]
|
||||
sequence<TestNonWrapperCacheInterface?> receiveNullableNonWrapperCacheInterfaceSequence();
|
||||
[Creator]
|
||||
sequence<TestNonWrapperCacheInterface>? receiveNonWrapperCacheInterfaceNullableSequence();
|
||||
[Creator]
|
||||
sequence<TestNonWrapperCacheInterface?>? receiveNullableNonWrapperCacheInterfaceNullableSequence();
|
||||
|
||||
// Non-castable interface types
|
||||
TestNonCastableInterface receiveOther();
|
||||
TestNonCastableInterface? receiveNullableOther();
|
||||
|
@ -236,6 +250,9 @@ interface TestInterface {
|
|||
void passSequenceOfDictionaries(sequence<Dict> x);
|
||||
};
|
||||
|
||||
interface TestNonWrapperCacheInterface {
|
||||
};
|
||||
|
||||
interface ImplementedInterfaceParent {
|
||||
void implementedParentMethod();
|
||||
attribute boolean implementedParentProperty;
|
||||
|
|
|
@ -18,25 +18,24 @@ function debug(msg) {
|
|||
//dump("BrowserElementParent - " + msg + "\n");
|
||||
}
|
||||
|
||||
function sendAsyncMsg(frameElement, msg, data) {
|
||||
let mm = frameElement.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader
|
||||
.messageManager;
|
||||
|
||||
mm.sendAsyncMessage('browser-element-api:' + msg, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The BrowserElementParent implements one half of <iframe mozbrowser>.
|
||||
* (The other half is, unsurprisingly, BrowserElementChild.)
|
||||
* BrowserElementParent implements one half of <iframe mozbrowser>. (The other
|
||||
* half is, unsurprisingly, BrowserElementChild.)
|
||||
*
|
||||
* We detect windows and docshells contained inside <iframe mozbrowser>s and
|
||||
* inject script to listen for certain events in the child. We then listen to
|
||||
* messages from the child script and take appropriate action here.
|
||||
* BrowserElementParentFactory detects when we create a windows or docshell
|
||||
* contained inside a <iframe mozbrowser> and creates a BrowserElementParent
|
||||
* object for that window.
|
||||
*
|
||||
* BrowserElementParent injects script to listen for certain events in the
|
||||
* child. We then listen to messages from the child script and take
|
||||
* appropriate action here in the parent.
|
||||
*/
|
||||
|
||||
function BrowserElementParent() {}
|
||||
BrowserElementParent.prototype = {
|
||||
function BrowserElementParentFactory() {
|
||||
this._initialized = false;
|
||||
}
|
||||
|
||||
BrowserElementParentFactory.prototype = {
|
||||
classID: Components.ID("{ddeafdac-cb39-47c4-9cb8-c9027ee36d26}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
@ -61,8 +60,10 @@ BrowserElementParent.prototype = {
|
|||
debug("_init");
|
||||
this._initialized = true;
|
||||
|
||||
this._screenshotListeners = {};
|
||||
this._screenshotReqCounter = 0;
|
||||
// Maps frame elements to BrowserElementParent objects. We never look up
|
||||
// anything in this map; the purpose is to keep the BrowserElementParent
|
||||
// alive for as long as its frame element lives.
|
||||
this._bepMap = new WeakMap();
|
||||
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.addObserver(this, 'remote-browser-frame-shown', /* ownsWeak = */ true);
|
||||
|
@ -81,175 +82,17 @@ BrowserElementParent.prototype = {
|
|||
|
||||
_observeInProcessBrowserFrameShown: function(frameLoader) {
|
||||
debug("In-process browser frame shown " + frameLoader);
|
||||
this._setUpMessageManagerListeners(frameLoader);
|
||||
this._createBrowserElementParent(frameLoader);
|
||||
},
|
||||
|
||||
_observeRemoteBrowserFrameShown: function(frameLoader) {
|
||||
debug("Remote browser frame shown " + frameLoader);
|
||||
this._setUpMessageManagerListeners(frameLoader);
|
||||
this._createBrowserElementParent(frameLoader);
|
||||
},
|
||||
|
||||
_setUpMessageManagerListeners: function(frameLoader) {
|
||||
_createBrowserElementParent: function(frameLoader) {
|
||||
let frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement;
|
||||
if (!frameElement) {
|
||||
debug("No frame element?");
|
||||
return;
|
||||
}
|
||||
|
||||
let mm = frameLoader.messageManager;
|
||||
|
||||
// Messages we receive are handled by functions with parameters
|
||||
// (frameElement, data), where |data| is the message manager's data object.
|
||||
|
||||
let self = this;
|
||||
function addMessageListener(msg, handler) {
|
||||
mm.addMessageListener('browser-element-api:' + msg, handler.bind(self, frameElement));
|
||||
}
|
||||
|
||||
addMessageListener("hello", this._recvHello);
|
||||
addMessageListener("locationchange", this._fireEventFromMsg);
|
||||
addMessageListener("loadstart", this._fireEventFromMsg);
|
||||
addMessageListener("loadend", this._fireEventFromMsg);
|
||||
addMessageListener("titlechange", this._fireEventFromMsg);
|
||||
addMessageListener("iconchange", this._fireEventFromMsg);
|
||||
addMessageListener("close", this._fireEventFromMsg);
|
||||
addMessageListener("get-mozapp-manifest-url", this._sendMozAppManifestURL);
|
||||
addMessageListener("keyevent", this._fireKeyEvent);
|
||||
addMessageListener("showmodalprompt", this._handleShowModalPrompt);
|
||||
mm.addMessageListener('browser-element-api:got-screenshot',
|
||||
this._recvGotScreenshot.bind(this));
|
||||
|
||||
XPCNativeWrapper.unwrap(frameElement).getScreenshot =
|
||||
this._getScreenshot.bind(this, mm, frameElement);
|
||||
|
||||
XPCNativeWrapper.unwrap(frameElement).setVisible =
|
||||
this._setVisible.bind(this, mm, frameElement);
|
||||
|
||||
mm.loadFrameScript("chrome://global/content/BrowserElementChild.js",
|
||||
/* allowDelayedLoad = */ true);
|
||||
},
|
||||
|
||||
_recvHello: function(frameElement, data) {
|
||||
debug("recvHello " + frameElement);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fire either a vanilla or a custom event, depending on the contents of
|
||||
* |data|.
|
||||
*/
|
||||
_fireEventFromMsg: function(frameElement, data) {
|
||||
let name = data.name.substring('browser-element-api:'.length);
|
||||
let detail = data.json;
|
||||
|
||||
debug('fireEventFromMsg: ' + name + ', ' + detail);
|
||||
let evt = this._createEvent(frameElement, name, detail,
|
||||
/* cancelable = */ false);
|
||||
frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_handleShowModalPrompt: function(frameElement, data) {
|
||||
// Fire a showmodalprmopt event on the iframe. When this method is called,
|
||||
// the child is spinning in a nested event loop waiting for an
|
||||
// unblock-modal-prompt message.
|
||||
//
|
||||
// If the embedder calls preventDefault() on the showmodalprompt event,
|
||||
// we'll block the child until event.detail.unblock() is called.
|
||||
//
|
||||
// Otherwise, if preventDefault() is not called, we'll send the
|
||||
// unblock-modal-prompt message to the child as soon as the event is done
|
||||
// dispatching.
|
||||
|
||||
let detail = data.json;
|
||||
debug('handleShowPrompt ' + JSON.stringify(detail));
|
||||
|
||||
// Strip off the windowID property from the object we send along in the
|
||||
// event.
|
||||
let windowID = detail.windowID;
|
||||
delete detail.windowID;
|
||||
debug("Event will have detail: " + JSON.stringify(detail));
|
||||
let evt = this._createEvent(frameElement, 'showmodalprompt', detail,
|
||||
/* cancelable = */ true);
|
||||
|
||||
let unblockMsgSent = false;
|
||||
function sendUnblockMsg() {
|
||||
if (unblockMsgSent) {
|
||||
return;
|
||||
}
|
||||
unblockMsgSent = true;
|
||||
|
||||
// We don't need to sanitize evt.detail.returnValue (e.g. converting the
|
||||
// return value of confirm() to a boolean); Gecko does that for us.
|
||||
|
||||
let data = { windowID: windowID,
|
||||
returnValue: evt.detail.returnValue };
|
||||
sendAsyncMsg(frameElement, 'unblock-modal-prompt', data);
|
||||
}
|
||||
|
||||
XPCNativeWrapper.unwrap(evt.detail).unblock = function() {
|
||||
sendUnblockMsg();
|
||||
};
|
||||
|
||||
frameElement.dispatchEvent(evt);
|
||||
|
||||
if (!evt.defaultPrevented) {
|
||||
// Unblock the inner frame immediately. Otherwise we'll unblock upon
|
||||
// evt.detail.unblock().
|
||||
sendUnblockMsg();
|
||||
}
|
||||
},
|
||||
|
||||
_createEvent: function(frameElement, evtName, detail, cancelable) {
|
||||
let win = frameElement.ownerDocument.defaultView;
|
||||
let evt;
|
||||
|
||||
// This will have to change if we ever want to send a CustomEvent with null
|
||||
// detail. For now, it's OK.
|
||||
if (detail !== undefined && detail !== null) {
|
||||
evt = new win.CustomEvent('mozbrowser' + evtName,
|
||||
{bubbles: true, cancelable: cancelable,
|
||||
detail: detail});
|
||||
}
|
||||
else {
|
||||
evt = new win.Event('mozbrowser' + evtName,
|
||||
{bubbles: true, cancelable: cancelable});
|
||||
}
|
||||
|
||||
return evt;
|
||||
},
|
||||
|
||||
_sendMozAppManifestURL: function(frameElement, data) {
|
||||
return frameElement.getAttribute('mozapp');
|
||||
},
|
||||
|
||||
_recvGotScreenshot: function(data) {
|
||||
var req = this._screenshotListeners[data.json.id];
|
||||
delete this._screenshotListeners[data.json.id];
|
||||
Services.DOMRequest.fireSuccess(req, data.json.screenshot);
|
||||
},
|
||||
|
||||
_getScreenshot: function(mm, frameElement) {
|
||||
let id = 'req_' + this._screenshotReqCounter++;
|
||||
let req = Services.DOMRequest
|
||||
.createRequest(frameElement.ownerDocument.defaultView);
|
||||
this._screenshotListeners[id] = req;
|
||||
mm.sendAsyncMessage('browser-element-api:get-screenshot', {id: id});
|
||||
return req;
|
||||
},
|
||||
|
||||
_setVisible: function(mm, frameElement, visible) {
|
||||
mm.sendAsyncMessage('browser-element-api:set-visible', {visible: visible});
|
||||
},
|
||||
|
||||
_fireKeyEvent: function(frameElement, data) {
|
||||
let win = frameElement.ownerDocument.defaultView;
|
||||
let evt = frameElement.ownerDocument.createEvent("KeyboardEvent");
|
||||
|
||||
evt.initKeyEvent(data.json.type, true, true, win,
|
||||
false, false, false, false, // modifiers
|
||||
data.json.keyCode,
|
||||
data.json.charCode);
|
||||
|
||||
frameElement.dispatchEvent(evt);
|
||||
this._bepMap.set(frameElement, new BrowserElementParent(frameLoader));
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
|
@ -275,4 +118,180 @@ BrowserElementParent.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementParent]);
|
||||
function BrowserElementParent(frameLoader) {
|
||||
debug("Creating new BrowserElementParent object for " + frameLoader);
|
||||
this._screenshotListeners = {};
|
||||
this._screenshotReqCounter = 0;
|
||||
|
||||
this._frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement;
|
||||
if (!this._frameElement) {
|
||||
debug("No frame element?");
|
||||
return;
|
||||
}
|
||||
|
||||
this._mm = frameLoader.messageManager;
|
||||
|
||||
// Messages we receive are handed to functions which take a (data) argument,
|
||||
// where |data| is the message manager's data object.
|
||||
|
||||
let self = this;
|
||||
function addMessageListener(msg, handler) {
|
||||
self._mm.addMessageListener('browser-element-api:' + msg, handler.bind(self));
|
||||
}
|
||||
|
||||
addMessageListener("hello", this._recvHello);
|
||||
addMessageListener("locationchange", this._fireEventFromMsg);
|
||||
addMessageListener("loadstart", this._fireEventFromMsg);
|
||||
addMessageListener("loadend", this._fireEventFromMsg);
|
||||
addMessageListener("titlechange", this._fireEventFromMsg);
|
||||
addMessageListener("iconchange", this._fireEventFromMsg);
|
||||
addMessageListener("close", this._fireEventFromMsg);
|
||||
addMessageListener("get-mozapp-manifest-url", this._sendMozAppManifestURL);
|
||||
addMessageListener("keyevent", this._fireKeyEvent);
|
||||
addMessageListener("showmodalprompt", this._handleShowModalPrompt);
|
||||
addMessageListener('got-screenshot', this._recvGotScreenshot);
|
||||
|
||||
function defineMethod(name, fn) {
|
||||
XPCNativeWrapper.unwrap(self._frameElement)[name] = fn.bind(self);
|
||||
}
|
||||
|
||||
// Define methods on the frame element.
|
||||
defineMethod('getScreenshot', this._getScreenshot);
|
||||
defineMethod('setVisible', this._setVisible);
|
||||
|
||||
self._mm.loadFrameScript("chrome://global/content/BrowserElementChild.js",
|
||||
/* allowDelayedLoad = */ true);
|
||||
}
|
||||
|
||||
BrowserElementParent.prototype = {
|
||||
get _window() {
|
||||
return this._frameElement.ownerDocument.defaultView;
|
||||
},
|
||||
|
||||
_sendAsyncMsg: function(msg, data) {
|
||||
this._frameElement.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader
|
||||
.messageManager
|
||||
.sendAsyncMessage('browser-element-api:' + msg, data);
|
||||
},
|
||||
|
||||
_recvHello: function(data) {
|
||||
debug("recvHello");
|
||||
},
|
||||
|
||||
/**
|
||||
* Fire either a vanilla or a custom event, depending on the contents of
|
||||
* |data|.
|
||||
*/
|
||||
_fireEventFromMsg: function(data) {
|
||||
let name = data.name.substring('browser-element-api:'.length);
|
||||
let detail = data.json;
|
||||
|
||||
debug('fireEventFromMsg: ' + name + ', ' + detail);
|
||||
let evt = this._createEvent(name, detail,
|
||||
/* cancelable = */ false);
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_handleShowModalPrompt: function(data) {
|
||||
// Fire a showmodalprmopt event on the iframe. When this method is called,
|
||||
// the child is spinning in a nested event loop waiting for an
|
||||
// unblock-modal-prompt message.
|
||||
//
|
||||
// If the embedder calls preventDefault() on the showmodalprompt event,
|
||||
// we'll block the child until event.detail.unblock() is called.
|
||||
//
|
||||
// Otherwise, if preventDefault() is not called, we'll send the
|
||||
// unblock-modal-prompt message to the child as soon as the event is done
|
||||
// dispatching.
|
||||
|
||||
let detail = data.json;
|
||||
debug('handleShowPrompt ' + JSON.stringify(detail));
|
||||
|
||||
// Strip off the windowID property from the object we send along in the
|
||||
// event.
|
||||
let windowID = detail.windowID;
|
||||
delete detail.windowID;
|
||||
debug("Event will have detail: " + JSON.stringify(detail));
|
||||
let evt = this._createEvent('showmodalprompt', detail,
|
||||
/* cancelable = */ true);
|
||||
|
||||
let self = this;
|
||||
let unblockMsgSent = false;
|
||||
function sendUnblockMsg() {
|
||||
if (unblockMsgSent) {
|
||||
return;
|
||||
}
|
||||
unblockMsgSent = true;
|
||||
|
||||
// We don't need to sanitize evt.detail.returnValue (e.g. converting the
|
||||
// return value of confirm() to a boolean); Gecko does that for us.
|
||||
|
||||
let data = { windowID: windowID,
|
||||
returnValue: evt.detail.returnValue };
|
||||
self._sendAsyncMsg('unblock-modal-prompt', data);
|
||||
}
|
||||
|
||||
XPCNativeWrapper.unwrap(evt.detail).unblock = function() {
|
||||
sendUnblockMsg();
|
||||
};
|
||||
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
|
||||
if (!evt.defaultPrevented) {
|
||||
// Unblock the inner frame immediately. Otherwise we'll unblock upon
|
||||
// evt.detail.unblock().
|
||||
sendUnblockMsg();
|
||||
}
|
||||
},
|
||||
|
||||
_createEvent: function(evtName, detail, cancelable) {
|
||||
// This will have to change if we ever want to send a CustomEvent with null
|
||||
// detail. For now, it's OK.
|
||||
if (detail !== undefined && detail !== null) {
|
||||
return new this._window.CustomEvent('mozbrowser' + evtName,
|
||||
{ bubbles: true,
|
||||
cancelable: cancelable,
|
||||
detail: detail });
|
||||
}
|
||||
|
||||
return new this._window.Event('mozbrowser' + evtName,
|
||||
{ bubbles: true,
|
||||
cancelable: cancelable });
|
||||
},
|
||||
|
||||
_sendMozAppManifestURL: function(data) {
|
||||
return this._frameElement.getAttribute('mozapp');
|
||||
},
|
||||
|
||||
|
||||
_getScreenshot: function() {
|
||||
let id = 'req_' + this._screenshotReqCounter++;
|
||||
let req = Services.DOMRequest.createRequest(this._window);
|
||||
this._screenshotListeners[id] = req;
|
||||
this._sendAsyncMsg('get-screenshot', {id: id});
|
||||
return req;
|
||||
},
|
||||
|
||||
_recvGotScreenshot: function(data) {
|
||||
var req = this._screenshotListeners[data.json.id];
|
||||
delete this._screenshotListeners[data.json.id];
|
||||
Services.DOMRequest.fireSuccess(req, data.json.screenshot);
|
||||
},
|
||||
|
||||
_setVisible: function(visible) {
|
||||
this._sendAsyncMsg('set-visible', {visible: visible});
|
||||
},
|
||||
|
||||
_fireKeyEvent: function(data) {
|
||||
let evt = this._window.document.createEvent("KeyboardEvent");
|
||||
evt.initKeyEvent(data.json.type, true, true, this._window,
|
||||
false, false, false, false, // modifiers
|
||||
data.json.keyCode,
|
||||
data.json.charCode);
|
||||
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
};
|
||||
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementParentFactory]);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
component {ddeafdac-cb39-47c4-9cb8-c9027ee36d26} BrowserElementParent.js
|
||||
contract @mozilla.org/browser-element-parent;1 {ddeafdac-cb39-47c4-9cb8-c9027ee36d26}
|
||||
category app-startup BrowserElementParent service,@mozilla.org/browser-element-parent;1
|
||||
contract @mozilla.org/browser-element-parent-factory;1 {ddeafdac-cb39-47c4-9cb8-c9027ee36d26}
|
||||
category app-startup BrowserElementParentFactory service,@mozilla.org/browser-element-parent-factory;1
|
||||
|
|
|
@ -18,7 +18,6 @@ include $(topsrcdir)/config/rules.mk
|
|||
|
||||
_TEST_FILES = \
|
||||
test_contacts_basics.html \
|
||||
test_contacts_events.html \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_TEST_FILES = \
|
||||
|
|
|
@ -48,7 +48,8 @@ interface WebGLShader;
|
|||
|
||||
interface WebGLTexture;
|
||||
|
||||
interface WebGLUniformLocation;
|
||||
interface WebGLUniformLocation {
|
||||
};
|
||||
|
||||
interface WebGLActiveInfo;
|
||||
|
||||
|
@ -589,6 +590,7 @@ interface WebGLRenderingContext {
|
|||
|
||||
any getUniform(WebGLProgram? program, WebGLUniformLocation? location);
|
||||
|
||||
[Creator]
|
||||
WebGLUniformLocation? getUniformLocation(WebGLProgram? program, DOMString name);
|
||||
|
||||
any getVertexAttrib(unsigned long index, unsigned long pname);
|
||||
|
|
|
@ -1431,7 +1431,7 @@ Proxy::HandleEvent(nsIDOMEvent* aEvent)
|
|||
XMLHttpRequest::XMLHttpRequest(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
: XMLHttpRequestEventTarget(aCx), mJSObject(NULL), mUpload(NULL),
|
||||
mWorkerPrivate(aWorkerPrivate),
|
||||
mResponseType(XMLHttpRequestResponseTypeValues::text), mTimeout(0),
|
||||
mResponseType(XMLHttpRequestResponseTypeValues::Text), mTimeout(0),
|
||||
mJSObjectRooted(false), mMultipart(false), mBackgroundRequest(false),
|
||||
mWithCredentials(false), mCanceled(false)
|
||||
{
|
||||
|
@ -2142,7 +2142,7 @@ XMLHttpRequest::SetResponseType(XMLHttpRequestResponseType aResponseType,
|
|||
|
||||
// "document" is fine for the main thread but not for a worker. Short-circuit
|
||||
// that here.
|
||||
if (aResponseType == XMLHttpRequestResponseTypeValues::document) {
|
||||
if (aResponseType == XMLHttpRequestResponseTypeValues::Document) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,7 @@
|
|||
#include "nsIIDNService.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "prprf.h"
|
||||
#include "mozIStorageService.h"
|
||||
#include "mozIStorageStatement.h"
|
||||
#include "mozIStorageConnection.h"
|
||||
#include "mozStorageHelper.h"
|
||||
#include "mozStorageCID.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
static nsPermissionManager *gPermissionManager = nsnull;
|
||||
|
@ -105,6 +101,115 @@ nsHostEntry::nsHostEntry(const nsHostEntry& toCopy)
|
|||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Simple callback used by |AsyncClose| to trigger a treatment once
|
||||
* the database is closed.
|
||||
*
|
||||
* Note: Beware that, if you hold onto a |CloseDatabaseListener| from a
|
||||
* |nsPermissionManager|, this will create a cycle.
|
||||
*
|
||||
* Note: Once the callback has been called this DeleteFromMozHostListener cannot
|
||||
* be reused.
|
||||
*/
|
||||
class CloseDatabaseListener : public mozIStorageCompletionCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_MOZISTORAGECOMPLETIONCALLBACK
|
||||
/**
|
||||
* @param aManager The owning manager.
|
||||
* @param aRebuildOnSuccess If |true|, reinitialize the database once
|
||||
* it has been closed. Otherwise, do nothing such.
|
||||
*/
|
||||
CloseDatabaseListener(nsPermissionManager* aManager,
|
||||
bool aRebuildOnSuccess);
|
||||
|
||||
protected:
|
||||
nsRefPtr<nsPermissionManager> mManager;
|
||||
bool mRebuildOnSuccess;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CloseDatabaseListener, mozIStorageCompletionCallback)
|
||||
|
||||
CloseDatabaseListener::CloseDatabaseListener(nsPermissionManager* aManager,
|
||||
bool aRebuildOnSuccess)
|
||||
: mManager(aManager)
|
||||
, mRebuildOnSuccess(aRebuildOnSuccess)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CloseDatabaseListener::Complete()
|
||||
{
|
||||
// Help breaking cycles
|
||||
nsRefPtr<nsPermissionManager> manager = mManager.forget();
|
||||
if (mRebuildOnSuccess && !manager->mIsShuttingDown) {
|
||||
return manager->InitDB(true);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple callback used by |RemoveAllInternal| to trigger closing
|
||||
* the database and reinitializing it.
|
||||
*
|
||||
* Note: Beware that, if you hold onto a |DeleteFromMozHostListener| from a
|
||||
* |nsPermissionManager|, this will create a cycle.
|
||||
*
|
||||
* Note: Once the callback has been called this DeleteFromMozHostListener cannot
|
||||
* be reused.
|
||||
*/
|
||||
class DeleteFromMozHostListener : public mozIStorageStatementCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
|
||||
|
||||
/**
|
||||
* @param aManager The owning manager.
|
||||
*/
|
||||
DeleteFromMozHostListener(nsPermissionManager* aManager);
|
||||
|
||||
protected:
|
||||
nsRefPtr<nsPermissionManager> mManager;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(DeleteFromMozHostListener, mozIStorageStatementCallback)
|
||||
|
||||
DeleteFromMozHostListener::
|
||||
DeleteFromMozHostListener(nsPermissionManager* aManager)
|
||||
: mManager(aManager)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DeleteFromMozHostListener::HandleResult(mozIStorageResultSet *)
|
||||
{
|
||||
MOZ_NOT_REACHED("Should not get any results");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DeleteFromMozHostListener::HandleError(mozIStorageError *)
|
||||
{
|
||||
// Errors are handled in |HandleCompletion|
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DeleteFromMozHostListener::HandleCompletion(PRUint16 aReason)
|
||||
{
|
||||
// Help breaking cycles
|
||||
nsRefPtr<nsPermissionManager> manager = mManager.forget();
|
||||
|
||||
if (aReason == REASON_ERROR) {
|
||||
manager->CloseDB(true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsPermissionManager Implementation
|
||||
|
||||
|
@ -119,6 +224,7 @@ NS_IMPL_ISUPPORTS3(nsPermissionManager, nsIPermissionManager, nsIObserver, nsISu
|
|||
|
||||
nsPermissionManager::nsPermissionManager()
|
||||
: mLargestID(0)
|
||||
, mIsShuttingDown(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -578,39 +684,53 @@ NS_IMETHODIMP
|
|||
nsPermissionManager::RemoveAll()
|
||||
{
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
|
||||
nsresult rv = RemoveAllInternal();
|
||||
NotifyObservers(nsnull, NS_LITERAL_STRING("cleared").get());
|
||||
return rv;
|
||||
return RemoveAllInternal(true);
|
||||
}
|
||||
|
||||
void
|
||||
nsPermissionManager::CloseDB()
|
||||
nsPermissionManager::CloseDB(bool aRebuildOnSuccess)
|
||||
{
|
||||
// Null the statements, this will finalize them.
|
||||
mStmtInsert = nsnull;
|
||||
mStmtDelete = nsnull;
|
||||
mStmtUpdate = nsnull;
|
||||
if (mDBConn) {
|
||||
mozilla::DebugOnly<nsresult> rv = mDBConn->Close();
|
||||
mozIStorageCompletionCallback* cb = new CloseDatabaseListener(this,
|
||||
aRebuildOnSuccess);
|
||||
mozilla::DebugOnly<nsresult> rv = mDBConn->AsyncClose(cb);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
mDBConn = nsnull;
|
||||
mDBConn = nsnull; // Avoid race conditions
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPermissionManager::RemoveAllInternal()
|
||||
nsPermissionManager::RemoveAllInternal(bool aNotifyObservers)
|
||||
{
|
||||
// Remove from memory and notify immediately. Since the in-memory
|
||||
// database is authoritative, we do not need confirmation from the
|
||||
// on-disk database to notify observers.
|
||||
RemoveAllFromMemory();
|
||||
if (aNotifyObservers) {
|
||||
NotifyObservers(nsnull, NS_LITERAL_STRING("cleared").get());
|
||||
}
|
||||
|
||||
// clear the db
|
||||
if (mDBConn) {
|
||||
nsresult rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_hosts"));
|
||||
if (NS_FAILED(rv)) {
|
||||
CloseDB();
|
||||
rv = InitDB(true);
|
||||
return rv;
|
||||
nsCOMPtr<mozIStorageAsyncStatement> removeStmt;
|
||||
nsresult rv = mDBConn->
|
||||
CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_hosts"
|
||||
), getter_AddRefs(removeStmt));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (!removeStmt) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
nsCOMPtr<mozIStoragePendingStatement> pending;
|
||||
mozIStorageStatementCallback* cb = new DeleteFromMozHostListener(this);
|
||||
rv = removeStmt->ExecuteAsync(cb, getter_AddRefs(pending));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -761,13 +881,14 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
|
|||
if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
|
||||
// The profile is about to change,
|
||||
// or is going away because the application is shutting down.
|
||||
mIsShuttingDown = true;
|
||||
if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
|
||||
// clear the permissions file
|
||||
RemoveAllInternal();
|
||||
// Clear the permissions file and close the db asynchronously
|
||||
RemoveAllInternal(false);
|
||||
} else {
|
||||
RemoveAllFromMemory();
|
||||
CloseDB(false);
|
||||
}
|
||||
CloseDB();
|
||||
}
|
||||
else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
|
||||
// the profile has already changed; init the db from the new location
|
||||
|
|
|
@ -190,9 +190,10 @@ private:
|
|||
void NotifyObservers(nsIPermission *aPermission, const PRUnichar *aData);
|
||||
|
||||
// Finalize all statements, close the DB and null it.
|
||||
void CloseDB();
|
||||
// if aRebuildOnSuccess, reinitialize database
|
||||
void CloseDB(bool aRebuildOnSuccess = false);
|
||||
|
||||
nsresult RemoveAllInternal();
|
||||
nsresult RemoveAllInternal(bool aNotifyObservers);
|
||||
nsresult RemoveAllFromMemory();
|
||||
nsresult NormalizeToACE(nsCString &aHost);
|
||||
nsresult GetHost(nsIURI *aURI, nsACString &aResult);
|
||||
|
@ -219,6 +220,13 @@ private:
|
|||
|
||||
// An array to store the strings identifying the different types.
|
||||
nsTArray<nsCString> mTypeArray;
|
||||
|
||||
// Initially, |false|. Set to |true| once shutdown has started, to avoid
|
||||
// reopening the database.
|
||||
bool mIsShuttingDown;
|
||||
|
||||
friend class DeleteFromMozHostListener;
|
||||
friend class CloseDatabaseListener;
|
||||
};
|
||||
|
||||
// {4F6B5E00-0C36-11d5-A535-0010A401EB10}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
# HG changeset patch
|
||||
# Parent 9ded7a9f94a863dfa1f3227d3013367f51b8b522
|
||||
# User Nicholas Cameron <ncameron@mozilla.com>
|
||||
Bug 765038; fix a Clang compilation bug in Skia; r=jwatt
|
||||
|
||||
diff --git a/gfx/skia/src/sfnt/SkOTTable_head.h b/gfx/skia/src/sfnt/SkOTTable_head.h
|
||||
--- a/gfx/skia/src/sfnt/SkOTTable_head.h
|
||||
+++ b/gfx/skia/src/sfnt/SkOTTable_head.h
|
||||
@@ -109,18 +109,18 @@ struct SkOTTableHead {
|
||||
} raw;
|
||||
} macStyle;
|
||||
SK_OT_USHORT lowestRecPPEM;
|
||||
struct FontDirectionHint {
|
||||
SK_TYPED_ENUM(Value, SK_OT_SHORT,
|
||||
((FullyMixedDirectionalGlyphs, SkTEndian_SwapBE16(0)))
|
||||
((OnlyStronglyLTR, SkTEndian_SwapBE16(1)))
|
||||
((StronglyLTR, SkTEndian_SwapBE16(2)))
|
||||
- ((OnlyStronglyRTL, static_cast<SK_OT_SHORT>(SkTEndian_SwapBE16(-1))))
|
||||
- ((StronglyRTL, static_cast<SK_OT_SHORT>(SkTEndian_SwapBE16(-2))))
|
||||
+ ((OnlyStronglyRTL, static_cast<SK_OT_SHORT>(SkTEndian_SwapBE16(static_cast<SK_OT_USHORT>(-1)))))
|
||||
+ ((StronglyRTL, static_cast<SK_OT_SHORT>(SkTEndian_SwapBE16(static_cast<SK_OT_USHORT>(-2)))))
|
||||
SK_SEQ_END,
|
||||
(value)SK_SEQ_END)
|
||||
} fontDirectionHint;
|
||||
struct IndexToLocFormat {
|
||||
SK_TYPED_ENUM(Value, SK_OT_SHORT,
|
||||
((ShortOffsets, SkTEndian_SwapBE16(0)))
|
||||
((LongOffsets, SkTEndian_SwapBE16(1)))
|
||||
SK_SEQ_END,
|
|
@ -16,3 +16,4 @@ See the relevant bugs in bugzilla for information on these patches:
|
|||
0011-Bug-719575-Fix-clang-build.patch
|
||||
0012-Bug-759683-make-ssse3-conditional.patch
|
||||
0013-Bug-761890-fonts.patch
|
||||
0014-Bug-765038-Fix-clang-build.patch
|
||||
|
|
|
@ -114,8 +114,8 @@ struct SkOTTableHead {
|
|||
((FullyMixedDirectionalGlyphs, SkTEndian_SwapBE16(0)))
|
||||
((OnlyStronglyLTR, SkTEndian_SwapBE16(1)))
|
||||
((StronglyLTR, SkTEndian_SwapBE16(2)))
|
||||
((OnlyStronglyRTL, static_cast<SK_OT_SHORT>(SkTEndian_SwapBE16(-1))))
|
||||
((StronglyRTL, static_cast<SK_OT_SHORT>(SkTEndian_SwapBE16(-2))))
|
||||
((OnlyStronglyRTL, static_cast<SK_OT_SHORT>(SkTEndian_SwapBE16(static_cast<SK_OT_USHORT>(-1)))))
|
||||
((StronglyRTL, static_cast<SK_OT_SHORT>(SkTEndian_SwapBE16(static_cast<SK_OT_USHORT>(-2)))))
|
||||
SK_SEQ_END,
|
||||
(value)SK_SEQ_END)
|
||||
} fontDirectionHint;
|
||||
|
|
|
@ -62,7 +62,7 @@ class HashTableEntry {
|
|||
JS_ASSERT(isLive()); keyHash |= collisionBit;
|
||||
}
|
||||
void unsetCollision() { keyHash &= ~sCollisionBit; }
|
||||
bool hasCollision() const { JS_ASSERT(isLive()); return keyHash & sCollisionBit; }
|
||||
bool hasCollision() const { return keyHash & sCollisionBit; }
|
||||
bool matchHash(HashNumber hn) { return (keyHash & ~sCollisionBit) == hn; }
|
||||
HashNumber getKeyHash() const { JS_ASSERT(!hasCollision()); return keyHash; }
|
||||
};
|
||||
|
@ -185,7 +185,7 @@ class HashTable : private AllocPolicy
|
|||
friend class HashTable;
|
||||
|
||||
HashTable &table;
|
||||
bool added;
|
||||
bool rekeyed;
|
||||
bool removed;
|
||||
|
||||
/* Not copyable. */
|
||||
|
@ -194,7 +194,7 @@ class HashTable : private AllocPolicy
|
|||
|
||||
public:
|
||||
template<class Map> explicit
|
||||
Enum(Map &map) : Range(map.all()), table(map.impl), added(false), removed(false) {}
|
||||
Enum(Map &map) : Range(map.all()), table(map.impl), rekeyed(false), removed(false) {}
|
||||
|
||||
/*
|
||||
* Removes the |front()| element from the table, leaving |front()|
|
||||
|
@ -224,7 +224,7 @@ class HashTable : private AllocPolicy
|
|||
HashPolicy::setKey(t, const_cast<Key &>(k));
|
||||
table.remove(*this->cur);
|
||||
table.putNewInfallible(l, t);
|
||||
added = true;
|
||||
rekeyed = true;
|
||||
this->validEntry = false;
|
||||
}
|
||||
|
||||
|
@ -234,28 +234,11 @@ class HashTable : private AllocPolicy
|
|||
|
||||
/* Potentially rehashes the table. */
|
||||
~Enum() {
|
||||
JS_ASSERT(!added);
|
||||
if (rekeyed)
|
||||
table.checkOverRemoved();
|
||||
if (removed)
|
||||
table.checkUnderloaded();
|
||||
}
|
||||
|
||||
/*
|
||||
* Can be used to end the enumeration before the destructor. Unlike
|
||||
* |~Enum()|, this can report OOM on resize, so must be called if
|
||||
* |rekeyFront()| is used during enumeration.
|
||||
*/
|
||||
bool endEnumeration() {
|
||||
if (added) {
|
||||
added = false;
|
||||
if (table.checkOverloaded() == RehashFailed)
|
||||
return false;
|
||||
}
|
||||
if (removed) {
|
||||
removed = false;
|
||||
table.checkUnderloaded();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -281,6 +264,7 @@ class HashTable : private AllocPolicy
|
|||
uint32_t grows; /* table expansions */
|
||||
uint32_t shrinks; /* table contractions */
|
||||
uint32_t compresses; /* table compressions */
|
||||
uint32_t rehashes; /* tombstone decontaminations */
|
||||
} stats;
|
||||
# define METER(x) x
|
||||
#else
|
||||
|
@ -601,6 +585,16 @@ class HashTable : private AllocPolicy
|
|||
return changeTableSize(deltaLog2);
|
||||
}
|
||||
|
||||
/* Infallibly rehash the table if we are overloaded with removals. */
|
||||
void checkOverRemoved()
|
||||
{
|
||||
if (overloaded()) {
|
||||
METER(stats.rehashes++);
|
||||
rehashTable();
|
||||
JS_ASSERT(!overloaded());
|
||||
}
|
||||
}
|
||||
|
||||
void remove(Entry &e)
|
||||
{
|
||||
JS_ASSERT(table);
|
||||
|
@ -625,6 +619,52 @@ class HashTable : private AllocPolicy
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is identical to changeTableSize(currentSize), but without requiring
|
||||
* a second table. We do this by recycling the collision bits to tell us if
|
||||
* the element is already inserted or still waiting to be inserted. Since
|
||||
* already-inserted elements win any conflicts, we get the same table as we
|
||||
* would have gotten through random insertion order.
|
||||
*/
|
||||
void rehashTable()
|
||||
{
|
||||
removedCount = 0;
|
||||
for (size_t i = 0; i < capacity(); ++i)
|
||||
table[i].unsetCollision();
|
||||
|
||||
for (size_t i = 0; i < capacity();) {
|
||||
Entry *src = &table[i];
|
||||
|
||||
if (!src->isLive() || src->hasCollision()) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
HashNumber keyHash = src->getKeyHash();
|
||||
HashNumber h1 = hash1(keyHash, hashShift);
|
||||
DoubleHash dh = hash2(keyHash, hashShift);
|
||||
Entry *tgt = &table[h1];
|
||||
while (true) {
|
||||
if (!tgt->hasCollision()) {
|
||||
Swap(*src, *tgt);
|
||||
tgt->setCollision();
|
||||
break;
|
||||
}
|
||||
|
||||
h1 = applyDoubleHash(h1, dh);
|
||||
tgt = &table[h1];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: this algorithm leaves collision bits on *all* elements, even if
|
||||
* they are on no collision path. We have the option of setting the
|
||||
* collision bits correctly on a subsequent pass or skipping the rehash
|
||||
* unless we are totally filled with tombstones: benchmark to find out
|
||||
* which approach is best.
|
||||
*/
|
||||
}
|
||||
|
||||
public:
|
||||
void clear()
|
||||
{
|
||||
|
|
|
@ -572,6 +572,8 @@ static JSFunctionSpecWithHelp TestingFunctions[] = {
|
|||
" 3: Collect when the window paints (browser only)\n"
|
||||
" 4: Verify write barriers between instructions\n"
|
||||
" 5: Verify write barriers between paints\n"
|
||||
" 6: Verify stack rooting (ignoring XML and Reflect)\n"
|
||||
" 7: Verify stack rooting (all roots)\n"
|
||||
" Period specifies that collection happens every n allocations.\n"),
|
||||
|
||||
JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,
|
||||
|
|
|
@ -3871,13 +3871,24 @@ dnl ========================================================
|
|||
dnl = Perform moving GC stack rooting analysis
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(root-analysis,
|
||||
[ --enable-root-analysis Enable moving GC stack root analysis],
|
||||
[ --enable-root-analysis Enable moving GC stack root analysis],
|
||||
JSGC_ROOT_ANALYSIS=1,
|
||||
JSGC_ROOT_ANALYSIS= )
|
||||
if test -n "$JSGC_ROOT_ANALYSIS"; then
|
||||
AC_DEFINE(JSGC_ROOT_ANALYSIS)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use exact stack rooting for GC
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(exact-rooting,
|
||||
[ --enable-exact-rooting Enable use of exact stack roots for GC],
|
||||
JSGC_USE_EXACT_ROOTING=1,
|
||||
JSGC_USE_EXACT_ROOTING= )
|
||||
if test -n "$JSGC_USE_EXACT_ROOTING"; then
|
||||
AC_DEFINE(JSGC_USE_EXACT_ROOTING)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use Valgrind
|
||||
dnl ========================================================
|
||||
|
@ -3974,7 +3985,7 @@ MOZ_ARG_ENABLE_BOOL(gczeal,
|
|||
[ --enable-gczeal Enable zealous GCing],
|
||||
JS_GC_ZEAL=1,
|
||||
JS_GC_ZEAL= )
|
||||
if test -n "$JS_GC_ZEAL"; then
|
||||
if test -n "$JS_GC_ZEAL" -o -n "$MOZ_DEBUG"; then
|
||||
AC_DEFINE(JS_GC_ZEAL)
|
||||
fi
|
||||
|
||||
|
@ -4129,7 +4140,7 @@ dnl = E4X support (ECMA-357)
|
|||
dnl ========================================================
|
||||
JS_HAS_XML_SUPPORT=1
|
||||
MOZ_ARG_DISABLE_BOOL(e4x,
|
||||
[ --disable-e4x Disable JS support for XML (ECMA-357)],
|
||||
[ --disable-e4x Disable JS support for XML (ECMA-357)],
|
||||
JS_HAS_XML_SUPPORT=0 )
|
||||
AC_DEFINE_UNQUOTED(JS_HAS_XML_SUPPORT, $JS_HAS_XML_SUPPORT)
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ class Rooted
|
|||
{
|
||||
void init(JSContext *cx_, T initial)
|
||||
{
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
ContextFriendFields *cx = ContextFriendFields::get(cx_);
|
||||
|
||||
ThingRootKind kind = RootMethods<T>::kind();
|
||||
|
@ -174,13 +174,13 @@ class Rooted
|
|||
|
||||
~Rooted()
|
||||
{
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
JS_ASSERT(*stack == this);
|
||||
*stack = prev;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
Rooted<T> *previous() { return prev; }
|
||||
#endif
|
||||
|
||||
|
@ -206,7 +206,7 @@ class Rooted
|
|||
|
||||
private:
|
||||
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
Rooted<T> **stack, *prev;
|
||||
#endif
|
||||
T ptr;
|
||||
|
@ -309,7 +309,7 @@ class SkipRoot
|
|||
* Hook for dynamic root analysis. Checks the native stack and poisons
|
||||
* references to GC things which have not been rooted.
|
||||
*/
|
||||
#if defined(JSGC_ROOT_ANALYSIS) && defined(DEBUG) && !defined(JS_THREADSAFE)
|
||||
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||
void CheckStackRoots(JSContext *cx);
|
||||
inline void MaybeCheckStackRoots(JSContext *cx) { CheckStackRoots(cx); }
|
||||
#else
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
for (i in ['']) {}
|
||||
function f(...patterns) {
|
||||
patterns[i];
|
||||
};
|
||||
f('');
|
|
@ -0,0 +1,20 @@
|
|||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debugger(g);
|
||||
|
||||
var fscript = null;
|
||||
dbg.onNewScript = function(script) {
|
||||
dbg.onNewScript = undefined;
|
||||
fscript = script.getChildScripts()[0];
|
||||
assertEq(fscript.staticLevel, 1);
|
||||
}
|
||||
|
||||
g.eval("function f(x) { arguments[0] = 3; return x }");
|
||||
assertEq(fscript !== null, true);
|
||||
|
||||
fscript.setBreakpoint(0, {hit:function(frame) {
|
||||
assertEq(frame.eval('x').return, 1);
|
||||
assertEq(frame.arguments[0], 1);
|
||||
return {return:42};
|
||||
}});
|
||||
|
||||
assertEq(g.f(1), 42);
|
|
@ -193,13 +193,11 @@ BEGIN_TEST(testHashRekeyManual)
|
|||
CHECK(AddLowKeys(&am, &bm, i));
|
||||
CHECK(MapsAreEqual(am, bm));
|
||||
|
||||
IntMap::Enum e(am);
|
||||
for (; !e.empty(); e.popFront()) {
|
||||
for (IntMap::Enum e(am); !e.empty(); e.popFront()) {
|
||||
uint32_t tmp = LowToHigh::rekey(e.front().key);
|
||||
if (tmp != e.front().key)
|
||||
e.rekeyFront(tmp);
|
||||
}
|
||||
CHECK(e.endEnumeration());
|
||||
CHECK(SlowRekey<LowToHigh>(&bm));
|
||||
|
||||
CHECK(MapsAreEqual(am, bm));
|
||||
|
@ -217,13 +215,11 @@ BEGIN_TEST(testHashRekeyManual)
|
|||
CHECK(AddLowKeys(&as, &bs, i));
|
||||
CHECK(SetsAreEqual(as, bs));
|
||||
|
||||
IntSet::Enum e(as);
|
||||
for (; !e.empty(); e.popFront()) {
|
||||
for (IntSet::Enum e(as); !e.empty(); e.popFront()) {
|
||||
uint32_t tmp = LowToHigh::rekey(e.front());
|
||||
if (tmp != e.front())
|
||||
e.rekeyFront(tmp);
|
||||
}
|
||||
CHECK(e.endEnumeration());
|
||||
CHECK(SlowRekey<LowToHigh>(&bs));
|
||||
|
||||
CHECK(SetsAreEqual(as, bs));
|
||||
|
@ -247,8 +243,7 @@ BEGIN_TEST(testHashRekeyManualRemoval)
|
|||
CHECK(AddLowKeys(&am, &bm, i));
|
||||
CHECK(MapsAreEqual(am, bm));
|
||||
|
||||
IntMap::Enum e(am);
|
||||
for (; !e.empty(); e.popFront()) {
|
||||
for (IntMap::Enum e(am); !e.empty(); e.popFront()) {
|
||||
if (LowToHighWithRemoval::shouldBeRemoved(e.front().key)) {
|
||||
e.removeFront();
|
||||
} else {
|
||||
|
@ -257,7 +252,6 @@ BEGIN_TEST(testHashRekeyManualRemoval)
|
|||
e.rekeyFront(tmp);
|
||||
}
|
||||
}
|
||||
CHECK(e.endEnumeration());
|
||||
CHECK(SlowRekey<LowToHighWithRemoval>(&bm));
|
||||
|
||||
CHECK(MapsAreEqual(am, bm));
|
||||
|
@ -275,8 +269,7 @@ BEGIN_TEST(testHashRekeyManualRemoval)
|
|||
CHECK(AddLowKeys(&as, &bs, i));
|
||||
CHECK(SetsAreEqual(as, bs));
|
||||
|
||||
IntSet::Enum e(as);
|
||||
for (; !e.empty(); e.popFront()) {
|
||||
for (IntSet::Enum e(as); !e.empty(); e.popFront()) {
|
||||
if (LowToHighWithRemoval::shouldBeRemoved(e.front())) {
|
||||
e.removeFront();
|
||||
} else {
|
||||
|
@ -285,7 +278,6 @@ BEGIN_TEST(testHashRekeyManualRemoval)
|
|||
e.rekeyFront(tmp);
|
||||
}
|
||||
}
|
||||
CHECK(e.endEnumeration());
|
||||
CHECK(SlowRekey<LowToHighWithRemoval>(&bs));
|
||||
|
||||
CHECK(SetsAreEqual(as, bs));
|
||||
|
@ -296,4 +288,3 @@ BEGIN_TEST(testHashRekeyManualRemoval)
|
|||
return true;
|
||||
}
|
||||
END_TEST(testHashRekeyManualRemoval)
|
||||
|
||||
|
|
|
@ -6643,7 +6643,9 @@ JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency)
|
|||
" 2: GC every F allocations (default: 100)\n"
|
||||
" 3: GC when the window paints (browser only)\n"
|
||||
" 4: Verify write barriers between instructions\n"
|
||||
" 5: Verify write barriers between paints\n");
|
||||
" 5: Verify write barriers between paints\n"
|
||||
" 6: Verify stack rooting (ignoring XML and Reflect)\n"
|
||||
" 7: Verify stack rooting (all roots)\n");
|
||||
}
|
||||
const char *p = strchr(env, ',');
|
||||
zeal = atoi(env);
|
||||
|
|
|
@ -5697,10 +5697,6 @@ JS_NewObjectForConstructor(JSContext *cx, JSClass *clasp, const jsval *vp);
|
|||
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef DEBUG
|
||||
#define JS_GC_ZEAL 1
|
||||
#endif
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
#define JS_DEFAULT_ZEAL_FREQ 100
|
||||
|
||||
|
|
|
@ -879,6 +879,45 @@ InFreeList(ArenaHeader *aheader, uintptr_t addr)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef JSGC_USE_EXACT_ROOTING
|
||||
static void
|
||||
MarkExactStackRoots(JSTracer *trc)
|
||||
{
|
||||
for (ContextIter cx(trc->runtime); !cx.done(); cx.next()) {
|
||||
for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) {
|
||||
Rooted<void*> *rooter = cx->thingGCRooters[i];
|
||||
while (rooter) {
|
||||
void **addr = (void **)rooter->address();
|
||||
if (*addr) {
|
||||
if (i == THING_ROOT_OBJECT) {
|
||||
MarkObjectRoot(trc, (JSObject **)addr, "exact stackroot object");
|
||||
} else if (i == THING_ROOT_STRING) {
|
||||
MarkStringRoot(trc, (JSString **)addr, "exact stackroot string");
|
||||
} else if (i == THING_ROOT_ID) {
|
||||
MarkIdRoot(trc, (jsid *)addr, "exact stackroot id");
|
||||
} else if (i == THING_ROOT_VALUE) {
|
||||
MarkValueRoot(trc, (Value *)addr, "exact stackroot value");
|
||||
} else if (i == THING_ROOT_SHAPE) {
|
||||
MarkShapeRoot(trc, (Shape **)addr, "exact stackroot shape");
|
||||
} else if (i == THING_ROOT_BASE_SHAPE) {
|
||||
MarkBaseShapeRoot(trc, (BaseShape **)addr, "exact stackroot baseshape");
|
||||
} else if (i == THING_ROOT_TYPE_OBJECT) {
|
||||
MarkTypeObjectRoot(trc, (types::TypeObject **)addr, "exact stackroot typeobject");
|
||||
} else if (i == THING_ROOT_SCRIPT) {
|
||||
MarkScriptRoot(trc, (JSScript **)addr, "exact stackroot script");
|
||||
} else if (i == THING_ROOT_XML) {
|
||||
MarkXMLRoot(trc, (JSXML **)addr, "exact stackroot xml");
|
||||
} else {
|
||||
JS_NOT_REACHED("Invalid thing root kind.");
|
||||
}
|
||||
}
|
||||
rooter = rooter->previous();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* JSGC_USE_EXACT_ROOTING */
|
||||
|
||||
enum ConservativeGCTest
|
||||
{
|
||||
CGCT_VALID,
|
||||
|
@ -1038,6 +1077,8 @@ MarkRangeConservatively(JSTracer *trc, const uintptr_t *begin, const uintptr_t *
|
|||
MarkWordConservatively(trc, *i);
|
||||
}
|
||||
|
||||
#ifndef JSGC_USE_EXACT_ROOTING
|
||||
|
||||
static JS_NEVER_INLINE void
|
||||
MarkConservativeStackRoots(JSTracer *trc, bool useSavedRoots)
|
||||
{
|
||||
|
@ -1083,6 +1124,8 @@ MarkConservativeStackRoots(JSTracer *trc, bool useSavedRoots)
|
|||
ArrayEnd(cgcd->registerSnapshot.words));
|
||||
}
|
||||
|
||||
#endif /* JSGC_USE_EXACT_ROOTING */
|
||||
|
||||
void
|
||||
MarkStackRangeConservatively(JSTracer *trc, Value *beginv, Value *endv)
|
||||
{
|
||||
|
@ -1101,8 +1144,6 @@ MarkStackRangeConservatively(JSTracer *trc, Value *beginv, Value *endv)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
JS_NEVER_INLINE void
|
||||
ConservativeGCData::recordStackTop()
|
||||
{
|
||||
|
@ -2299,8 +2340,13 @@ MarkRuntime(JSTracer *trc, bool useSavedRoots = false)
|
|||
|
||||
AutoGCRooter::traceAll(trc);
|
||||
|
||||
if (rt->hasContexts())
|
||||
if (rt->hasContexts()) {
|
||||
#ifdef JSGC_USE_EXACT_ROOTING
|
||||
MarkExactStackRoots(trc);
|
||||
#else
|
||||
MarkConservativeStackRoots(trc, useSavedRoots);
|
||||
#endif
|
||||
}
|
||||
|
||||
for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront())
|
||||
gc_root_traversal(trc, r.front());
|
||||
|
@ -4086,7 +4132,7 @@ SetDeterministicGC(JSContext *cx, bool enabled)
|
|||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
#if defined(DEBUG) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||
|
||||
static void
|
||||
CheckStackRoot(JSTracer *trc, uintptr_t *w)
|
||||
|
@ -4146,7 +4192,9 @@ JS::CheckStackRoots(JSContext *cx)
|
|||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
|
||||
if (!rt->gcExactScanningEnabled)
|
||||
if (rt->gcZeal_ != ZealStackRootingSafeValue && rt->gcZeal_ != ZealStackRootingValue)
|
||||
return;
|
||||
if (rt->gcZeal_ == ZealStackRootingSafeValue && !rt->gcExactScanningEnabled)
|
||||
return;
|
||||
|
||||
AutoCopyFreeListToArenas copy(rt);
|
||||
|
@ -4206,7 +4254,7 @@ JS::CheckStackRoots(JSContext *cx)
|
|||
ArrayEnd(cgcd->registerSnapshot.words));
|
||||
}
|
||||
|
||||
#endif /* DEBUG && JSGC_ROOT_ANALYSIS && !JS_THREADSAFE */
|
||||
#endif /* DEBUG && JS_GC_ZEAL && JSGC_ROOT_ANALYSIS && !JS_THREADSAFE */
|
||||
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
|
|
@ -1067,6 +1067,8 @@ const int ZealAllocValue = 2;
|
|||
const int ZealFrameGCValue = 3;
|
||||
const int ZealVerifierValue = 4;
|
||||
const int ZealFrameVerifierValue = 5;
|
||||
const int ZealStackRootingSafeValue = 6;
|
||||
const int ZealStackRootingValue = 7;
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
|
||||
|
|
|
@ -3651,15 +3651,21 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
|||
|
||||
case JSOP_REST: {
|
||||
TypeSet *types = script->analysis()->bytecodeTypes(pc);
|
||||
types->addSubset(cx, &pushed[0]);
|
||||
if (script->hasGlobal()) {
|
||||
TypeObject *rest = TypeScript::InitObject(cx, script, pc, JSProto_Array);
|
||||
if (!rest)
|
||||
return false;
|
||||
types->addType(cx, Type::ObjectType(rest));
|
||||
|
||||
// Simulate setting a element.
|
||||
TypeSet *propTypes = rest->getProperty(cx, JSID_VOID, true);
|
||||
if (!propTypes)
|
||||
return false;
|
||||
propTypes->addType(cx, Type::UnknownType());
|
||||
} else {
|
||||
types->addType(cx, Type::UnknownType());
|
||||
}
|
||||
types->addSubset(cx, &pushed[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -248,15 +248,15 @@ struct ContextFriendFields {
|
|||
return reinterpret_cast<ContextFriendFields *>(cx);
|
||||
}
|
||||
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
/*
|
||||
* Stack allocated GC roots for stack GC heap pointers, which may be
|
||||
* overwritten if moved during a GC.
|
||||
*/
|
||||
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||
/*
|
||||
* Stack allocated list of stack locations which hold non-relocatable
|
||||
* GC heap pointers (where the target is rooted somewhere else) or integer
|
||||
|
@ -267,8 +267,6 @@ struct ContextFriendFields {
|
|||
*/
|
||||
SkipRoot *skipGCRooters;
|
||||
#endif
|
||||
|
||||
#endif /* JSGC_ROOT_ANALYSIS */
|
||||
};
|
||||
|
||||
} /* namespace JS */
|
||||
|
|
|
@ -3169,10 +3169,10 @@ DebuggerArguments_getArg(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (unsigned(i) < fp->numActualArgs()) {
|
||||
if (unsigned(i) < fp->numFormalArgs() && fp->script()->formalLivesInCallObject(i))
|
||||
arg = fp->callObj().arg(i);
|
||||
else if (fp->script()->argsObjAliasesFormals())
|
||||
else if (fp->script()->argsObjAliasesFormals() && fp->hasArgsObj())
|
||||
arg = fp->argsObj().arg(i);
|
||||
else
|
||||
arg = fp->unaliasedActual(i);
|
||||
arg = fp->unaliasedActual(i, DONT_CHECK_ALIASING);
|
||||
} else {
|
||||
arg.setUndefined();
|
||||
}
|
||||
|
|
|
@ -191,10 +191,10 @@ CallObject::copyUnaliasedValues(StackFrame *fp)
|
|||
/* Copy the unaliased formals. */
|
||||
for (unsigned i = 0; i < script->bindings.numArgs(); ++i) {
|
||||
if (!script->formalLivesInCallObject(i)) {
|
||||
if (script->argsObjAliasesFormals())
|
||||
if (script->argsObjAliasesFormals() && fp->hasArgsObj())
|
||||
setArg(i, fp->argsObj().arg(i), DONT_CHECK_ALIASING);
|
||||
else
|
||||
setArg(i, fp->unaliasedFormal(i), DONT_CHECK_ALIASING);
|
||||
setArg(i, fp->unaliasedFormal(i, DONT_CHECK_ALIASING), DONT_CHECK_ALIASING);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1113,7 +1113,7 @@ class DebugScopeProxy : public BaseProxyHandler
|
|||
* This function handles access to unaliased locals/formals. If such
|
||||
* accesses were passed on directly to the DebugScopeObject::scope, they
|
||||
* would not be reading/writing the canonical location for the variable,
|
||||
* which is on the stack. Thus, handleUn must translate would-be
|
||||
* which is on the stack. Thus, handleUnaliasedAccess must translate
|
||||
* accesses to scope objects into analogous accesses of the stack frame.
|
||||
*
|
||||
* handleUnaliasedAccess returns 'true' if the access was unaliased and
|
||||
|
@ -1162,16 +1162,16 @@ class DebugScopeProxy : public BaseProxyHandler
|
|||
return false;
|
||||
|
||||
if (maybefp) {
|
||||
if (script->argsObjAliasesFormals()) {
|
||||
if (script->argsObjAliasesFormals() && maybefp->hasArgsObj()) {
|
||||
if (action == GET)
|
||||
*vp = maybefp->argsObj().arg(i);
|
||||
else
|
||||
maybefp->argsObj().setArg(i, *vp);
|
||||
} else {
|
||||
if (action == GET)
|
||||
*vp = maybefp->unaliasedFormal(i);
|
||||
*vp = maybefp->unaliasedFormal(i, DONT_CHECK_ALIASING);
|
||||
else
|
||||
maybefp->unaliasedFormal(i) = *vp;
|
||||
maybefp->unaliasedFormal(i, DONT_CHECK_ALIASING) = *vp;
|
||||
}
|
||||
} else {
|
||||
if (action == GET)
|
||||
|
|
|
@ -252,10 +252,10 @@ StackFrame::unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing)
|
|||
}
|
||||
|
||||
inline Value &
|
||||
StackFrame::unaliasedActual(unsigned i)
|
||||
StackFrame::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing)
|
||||
{
|
||||
JS_ASSERT(i < numActualArgs());
|
||||
JS_ASSERT(!script()->formalIsAliased(i));
|
||||
JS_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
|
||||
return i < numFormalArgs() ? formals()[i] : actuals()[i];
|
||||
}
|
||||
|
||||
|
|
|
@ -591,7 +591,7 @@ class StackFrame
|
|||
|
||||
bool hasArgs() const { return isNonEvalFunctionFrame(); }
|
||||
inline Value &unaliasedFormal(unsigned i, MaybeCheckAliasing = CHECK_ALIASING);
|
||||
inline Value &unaliasedActual(unsigned i);
|
||||
inline Value &unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING);
|
||||
template <class Op> inline void forEachUnaliasedActual(Op op);
|
||||
|
||||
inline unsigned numFormalArgs() const;
|
||||
|
@ -1011,11 +1011,24 @@ class StackFrame
|
|||
return !!(flags_ & CONSTRUCTING);
|
||||
}
|
||||
|
||||
/*
|
||||
* These two queries should not be used in general: the presence/absence of
|
||||
* the call/args object is determined by the static(ish) properties of the
|
||||
* JSFunction/JSScript. These queries should only be performed when probing
|
||||
* a stack frame that may be in the middle of the prologue (during which
|
||||
* time the call/args object are created).
|
||||
*/
|
||||
|
||||
bool hasCallObj() const {
|
||||
JS_ASSERT(isStrictEvalFrame() || fun()->isHeavyweight());
|
||||
return flags_ & HAS_CALL_OBJ;
|
||||
}
|
||||
|
||||
bool hasArgsObj() const {
|
||||
JS_ASSERT(script()->needsArgsObj());
|
||||
return flags_ & HAS_ARGS_OBJ;
|
||||
}
|
||||
|
||||
/*
|
||||
* The method JIT call/apply optimization can erase Function.{call,apply}
|
||||
* invocations from the stack and push the callee frame directly. The base
|
||||
|
|
|
@ -2128,7 +2128,7 @@ XPCJSRuntime::OnJSContextNew(JSContext *cx)
|
|||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
bool
|
||||
XPCJSRuntime::DeferredRelease(nsISupports* obj)
|
||||
{
|
||||
NS_ASSERTION(obj, "bad param");
|
||||
|
|
|
@ -13,12 +13,7 @@
|
|||
#include "nsHTMLVideoElement.h"
|
||||
#include "nsHTMLDocument.h"
|
||||
#include "nsICSSDeclaration.h"
|
||||
#include "nsIDOMWebGLRenderingContext.h"
|
||||
#include "nsSVGStylableElement.h"
|
||||
#include "WebGLContext.h"
|
||||
// WebGLContext pulls in windows.h, which defines random crap, so nuke
|
||||
// those defines.
|
||||
#include "qsWinUndefs.h"
|
||||
|
||||
#define DEFINE_UNWRAP_CAST(_interface, _base, _bit) \
|
||||
template <> \
|
||||
|
|
|
@ -2558,6 +2558,12 @@ nsXPConnect::GetCaller(JSContext **aJSContext, JSObject **aObj)
|
|||
|
||||
namespace xpc {
|
||||
|
||||
bool
|
||||
DeferredRelease(nsISupports *obj)
|
||||
{
|
||||
return nsXPConnect::GetRuntimeInstance()->DeferredRelease(obj);
|
||||
}
|
||||
|
||||
bool
|
||||
Base64Encode(JSContext *cx, JS::Value val, JS::Value *out)
|
||||
{
|
||||
|
|
|
@ -698,7 +698,7 @@ public:
|
|||
|
||||
JSBool OnJSContextNew(JSContext* cx);
|
||||
|
||||
JSBool DeferredRelease(nsISupports* obj);
|
||||
bool DeferredRelease(nsISupports* obj);
|
||||
|
||||
JSBool GetDoingFinalization() const {return mDoingFinalization;}
|
||||
|
||||
|
|
|
@ -219,6 +219,8 @@ class nsIMemoryMultiReporterCallback;
|
|||
|
||||
namespace xpc {
|
||||
|
||||
bool DeferredRelease(nsISupports *obj);
|
||||
|
||||
// If these functions return false, then an exception will be set on cx.
|
||||
bool Base64Encode(JSContext *cx, JS::Value val, JS::Value *out);
|
||||
bool Base64Decode(JSContext *cx, JS::Value val, JS::Value *out);
|
||||
|
|
|
@ -2545,7 +2545,8 @@ nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement)
|
|||
/*
|
||||
how the root frame hierarchy should look
|
||||
|
||||
Galley presentation, non-XUL, with scrolling (i.e. not a frameset):
|
||||
Galley presentation, non-XUL, with scrolling (i.e. not a frameset,
|
||||
or framesets with async pan/zoom like on Fennec):
|
||||
|
||||
ViewportFrame [fixed-cb]
|
||||
nsHTMLScrollFrame
|
||||
|
@ -2553,7 +2554,8 @@ nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement)
|
|||
root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
|
||||
nsTableOuterFrame, nsPlaceholderFrame)
|
||||
|
||||
Galley presentation, non-XUL, without scrolling (i.e. a frameset):
|
||||
Galley presentation, non-XUL, without scrolling (i.e. a frameset,
|
||||
except when async pan/zoom is enabled):
|
||||
|
||||
ViewportFrame [fixed-cb]
|
||||
nsCanvasFrame [abs-cb]
|
||||
|
@ -2670,12 +2672,15 @@ nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement)
|
|||
// Never create scrollbars for XUL documents
|
||||
bool isScrollable = !isXUL;
|
||||
|
||||
// Never create scrollbars for frameset documents.
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
// Never create scrollbars for frameset documents, except on android
|
||||
// where we have async pan/zoom and need a scrollable root frame.
|
||||
if (isHTML) {
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
|
||||
if (htmlDoc && htmlDoc->GetIsFrameset())
|
||||
isScrollable = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (isPaginated) {
|
||||
isScrollable = presContext->HasPaginatedScrolling();
|
||||
|
|
|
@ -71,7 +71,6 @@ enum Type {
|
|||
TYPE_WRAP_LIST,
|
||||
TYPE_ZOOM,
|
||||
TYPE_EXCLUDE_GLASS_FRAME,
|
||||
TYPE_SIMPLE_SCROLL_LAYER,
|
||||
|
||||
#if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
|
||||
TYPE_REFLOW_COUNT,
|
||||
|
|
|
@ -2072,12 +2072,15 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
nsIContent* content = mScrolledFrame->GetContent();
|
||||
ViewID scrollId = nsLayoutUtils::FindIDFor(content);
|
||||
|
||||
nsRect viewport =
|
||||
nsRect(aBuilder->ToReferenceFrame(mScrollFrame), mScrollFrame->GetSize());
|
||||
nsRect viewport = mScrollFrame->GetRect() -
|
||||
mScrollFrame->GetPosition() +
|
||||
aBuilder->ToReferenceFrame(mScrollFrame);
|
||||
|
||||
bool usingDisplayport = false;
|
||||
nsRect displayport;
|
||||
usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
|
||||
if (content) {
|
||||
usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
|
||||
}
|
||||
RecordFrameMetrics(mScrolledFrame, mScrollFrame, layer, mVisibleRect, viewport,
|
||||
(usingDisplayport ? &displayport : nsnull), scrollId,
|
||||
aContainerParameters);
|
||||
|
@ -2230,71 +2233,6 @@ nsDisplayScrollInfoLayer::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
|
|||
return RemoveScrollLayerCount() == 1;
|
||||
}
|
||||
|
||||
nsDisplaySimpleScrollLayer::nsDisplaySimpleScrollLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList)
|
||||
: nsDisplayWrapList(aBuilder, aFrame, aList) {
|
||||
MOZ_COUNT_CTOR(nsDisplaySimpleScrollLayer);
|
||||
}
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsDisplaySimpleScrollLayer::~nsDisplaySimpleScrollLayer() {
|
||||
MOZ_COUNT_DTOR(nsDisplaySimpleScrollLayer);
|
||||
}
|
||||
#endif
|
||||
|
||||
already_AddRefed<Layer>
|
||||
nsDisplaySimpleScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters) {
|
||||
nsRefPtr<ContainerLayer> layer = aBuilder->LayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
aContainerParameters, nsnull);
|
||||
|
||||
// Get the already set unique ID for scrolling this content remotely.
|
||||
// Or, if not set, generate a new ID.
|
||||
nsIContent* content = mFrame->PresContext()->Document()->GetRootElement();
|
||||
ViewID scrollId = nsLayoutUtils::FindIDFor(content);
|
||||
|
||||
nsRect viewport = nsRect(ToReferenceFrame(), mFrame->GetSize());
|
||||
|
||||
bool usingDisplayport = false;
|
||||
nsRect displayport;
|
||||
usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
|
||||
RecordFrameMetrics(mFrame, nsnull, layer, mVisibleRect, viewport,
|
||||
(usingDisplayport ? &displayport : nsnull), scrollId,
|
||||
aContainerParameters);
|
||||
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplaySimpleScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion)
|
||||
{
|
||||
nsRect displayport;
|
||||
if (nsLayoutUtils::GetDisplayPort(mFrame->PresContext()->Document()->GetRootElement(), &displayport)) {
|
||||
// The visible region for the children may be much bigger than the hole we
|
||||
// are viewing the children from, so that the compositor process has enough
|
||||
// content to asynchronously pan while content is being refreshed.
|
||||
|
||||
nsRegion childVisibleRegion = displayport + ToReferenceFrame();
|
||||
|
||||
nsRect boundedRect =
|
||||
childVisibleRegion.GetBounds().Intersect(mList.GetBounds(aBuilder));
|
||||
nsRect allowExpansion = boundedRect.Intersect(aAllowVisibleRegionExpansion);
|
||||
bool visible = mList.ComputeVisibilityForSublist(
|
||||
aBuilder, &childVisibleRegion, boundedRect, allowExpansion);
|
||||
mVisibleRect = boundedRect;
|
||||
|
||||
return visible;
|
||||
|
||||
} else {
|
||||
return nsDisplayWrapList::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion);
|
||||
}
|
||||
}
|
||||
|
||||
nsDisplayClip::nsDisplayClip(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayItem* aItem,
|
||||
const nsRect& aRect)
|
||||
|
|
|
@ -2015,39 +2015,6 @@ public:
|
|||
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder);
|
||||
};
|
||||
|
||||
/**
|
||||
* A display item that has no purpose but to ensure its contents get
|
||||
* their own layer and that FrameMetrics are recorded, if the frame's
|
||||
* document's root element has a displayport.
|
||||
*/
|
||||
class nsDisplaySimpleScrollLayer : public nsDisplayWrapList {
|
||||
public:
|
||||
nsDisplaySimpleScrollLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplaySimpleScrollLayer();
|
||||
#endif
|
||||
|
||||
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion);
|
||||
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters);
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters)
|
||||
{
|
||||
return mozilla::LAYER_ACTIVE;
|
||||
}
|
||||
virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
NS_DISPLAY_DECL_NAME("SimpleScrollLayer", TYPE_SIMPLE_SCROLL_LAYER)
|
||||
};
|
||||
|
||||
/**
|
||||
* nsDisplayClip can clip a list of items, but we take a single item
|
||||
* initially and then later merge other items into it when we merge
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
#include "nsObjectFrame.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPopupManager.h"
|
||||
|
@ -345,27 +344,6 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
}
|
||||
|
||||
if (subdocRootFrame && !aBuilder->IsForEventDelivery()) {
|
||||
bool framesetUsingDisplayPort = false;
|
||||
nsIDocument* doc = presContext->Document();
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc);
|
||||
if (htmlDoc && htmlDoc->GetIsFrameset()) {
|
||||
nsIContent* root = doc->GetRootElement();
|
||||
if (root) {
|
||||
framesetUsingDisplayPort = nsLayoutUtils::GetDisplayPort(root, nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Frameset document's don't have a scroll frame but we still need to
|
||||
// communicate the basic metrics of the document.
|
||||
if (framesetUsingDisplayPort) {
|
||||
nsDisplaySimpleScrollLayer* item =
|
||||
new (aBuilder) nsDisplaySimpleScrollLayer(aBuilder, subdocRootFrame, &childItems);
|
||||
childItems.AppendToTop(item);
|
||||
}
|
||||
}
|
||||
|
||||
bool addedLayer = false;
|
||||
|
||||
if (subdocRootFrame && parentAPD != subdocAPD) {
|
||||
|
|
|
@ -47,14 +47,35 @@ nsSVGClipPathFrame::ClipPaint(nsRenderingContext* aContext,
|
|||
mClipParentMatrix = new gfxMatrix(aMatrix);
|
||||
}
|
||||
|
||||
bool isTrivial = IsTrivial();
|
||||
|
||||
SVGAutoRenderState mode(aContext,
|
||||
isTrivial ? SVGAutoRenderState::CLIP
|
||||
: SVGAutoRenderState::CLIP_MASK);
|
||||
|
||||
gfxContext *gfx = aContext->ThebesContext();
|
||||
|
||||
nsISVGChildFrame *singleClipPathChild = nsnull;
|
||||
|
||||
if (IsTrivial(&singleClipPathChild)) {
|
||||
// Notify our child that it's painting as part of a clipPath, and that
|
||||
// we only require it to draw its path (it should skip filling, etc.):
|
||||
SVGAutoRenderState mode(aContext, SVGAutoRenderState::CLIP);
|
||||
|
||||
if (!singleClipPathChild) {
|
||||
// We have no children - the spec says clip away everything:
|
||||
gfx->Rectangle(gfxRect());
|
||||
} else {
|
||||
singleClipPathChild->NotifySVGChanged(
|
||||
nsISVGChildFrame::DO_NOT_NOTIFY_RENDERING_OBSERVERS |
|
||||
nsISVGChildFrame::TRANSFORM_CHANGED);
|
||||
singleClipPathChild->PaintSVG(aContext, nsnull);
|
||||
}
|
||||
gfx->Clip();
|
||||
gfx->NewPath();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Seems like this is a non-trivial clipPath, so we need to use a clip mask.
|
||||
|
||||
// Notify our children that they're painting into a clip mask:
|
||||
SVGAutoRenderState mode(aContext, SVGAutoRenderState::CLIP_MASK);
|
||||
|
||||
// Check if this clipPath is itself clipped by another clipPath:
|
||||
nsSVGClipPathFrame *clipPathFrame =
|
||||
nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(nsnull);
|
||||
bool referencedClipIsTrivial;
|
||||
|
@ -134,11 +155,6 @@ nsSVGClipPathFrame::ClipPaint(nsRenderingContext* aContext,
|
|||
gfx->Restore();
|
||||
}
|
||||
|
||||
if (isTrivial) {
|
||||
gfx->Clip();
|
||||
gfx->NewPath();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -185,13 +201,17 @@ nsSVGClipPathFrame::ClipHitTest(nsIFrame* aParent,
|
|||
}
|
||||
|
||||
bool
|
||||
nsSVGClipPathFrame::IsTrivial()
|
||||
nsSVGClipPathFrame::IsTrivial(nsISVGChildFrame **aSingleChild)
|
||||
{
|
||||
// If the clip path is clipped then it's non-trivial
|
||||
if (nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(nsnull))
|
||||
return false;
|
||||
|
||||
bool foundChild = false;
|
||||
if (aSingleChild) {
|
||||
*aSingleChild = nsnull;
|
||||
}
|
||||
|
||||
nsISVGChildFrame *foundChild = nsnull;
|
||||
|
||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
|
@ -206,9 +226,12 @@ nsSVGClipPathFrame::IsTrivial()
|
|||
if (nsSVGEffects::GetEffectProperties(kid).GetClipPathFrame(nsnull))
|
||||
return false;
|
||||
|
||||
foundChild = true;
|
||||
foundChild = svgChild;
|
||||
}
|
||||
}
|
||||
if (aSingleChild) {
|
||||
*aSingleChild = foundChild;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsSVGUtils.h"
|
||||
|
||||
class nsRenderingContext;
|
||||
class nsISVGChildFrame;
|
||||
|
||||
typedef nsSVGContainerFrame nsSVGClipPathFrameBase;
|
||||
|
||||
|
@ -41,7 +42,7 @@ public:
|
|||
// Check if this clipPath is made up of more than one geometry object.
|
||||
// If so, the clipping API in cairo isn't enough and we need to use
|
||||
// mask based clipping.
|
||||
bool IsTrivial();
|
||||
bool IsTrivial(nsISVGChildFrame **aSingleChild = nsnull);
|
||||
|
||||
bool IsValid();
|
||||
|
||||
|
|
|
@ -317,6 +317,9 @@ nsSVGGlyphFrame::PaintSVG(nsRenderingContext *aContext,
|
|||
}
|
||||
|
||||
if (renderMode != SVGAutoRenderState::NORMAL) {
|
||||
NS_ABORT_IF_FALSE(renderMode == SVGAutoRenderState::CLIP ||
|
||||
renderMode == SVGAutoRenderState::CLIP_MASK,
|
||||
"Unknown render mode");
|
||||
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(gfx);
|
||||
SetupGlobalTransform(gfx);
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче